#include <iostream>
#include <iomanip>
#include "Vget_noise_matrix.h"
#include <verilated.h>
#include <verilated_vcd_c.h>

int main(int argc, const char ** argv, const char ** env) {
  Verilated::commandArgs(argc, argv);

  // Treat the argument on the command-line as the place to start
  int width, length;
  if (argc > 1 && argv[1][0] != '+') {
    width = atoi(argv[1]);
    length = atoi(argv[2]);
  } else {
    width = 8; // Default
    length = 8; // Default
  }

  Vget_noise_matrix * dut = new Vget_noise_matrix;  // Instantiate a new module

  // Enable dumping a VCD file

  Verilated::traceEverOn(true);
  VerilatedVcdC * tfp = new VerilatedVcdC;
  dut->trace(tfp, 99);
  tfp->open("get_noise_matrix.vcd");

  dut->clk = 0;
  dut->width = width;
  dut->length = length;
  dut->start = 0;
  
  int time;
  std::cout << "width: " << width;
  std::cout << std::endl;
  std::cout << "length: " << length;
  std::cout << std::endl;
  int start_stamp = 100;
  // let run (width * length) cycles for computations
  int read_stamp = start_stamp + (length * width) * 20;
  for (time = 0 ; time < 10000 ; time += 10) {
    dut->clk = ((time % 20) >= 10) ? 1 : 0; // Simulate a 50 MHz clock
    if (time == 20) dut->reset = 1; // Handle "reset" on for four cycles
    if (time == 100) {
      dut->reset = 0;
      dut->start = 1;   // Put "start" on
    }

    if (time == read_stamp) dut->start = 0;

    dut->eval();     // Run the simulation for a cycle
    tfp->dump(time); // Write the VCD file for this cycle

    // get outputs for (length) rows
    // for each row, get outputs for (width * ell) cycles
    if (time >= read_stamp && time <= read_stamp + (length * width) * 20 && dut->clk == 1) {
        std::cout << "random output: " << std::setfill('0') << (int) dut->data_out;
        std::cout << std::endl;
    }

    if (dut->done) break;
  }

  tfp->close(); // Stop dumping the VCD file
  delete tfp;

  dut->final(); // Stop the simulation
  delete dut;

  return 0;
}