// See LICENSE for license details. #include "verilated.h" #if VM_TRACE #include "verilated_vcd_c.h" #endif #include #include #include #include #include #include #include extern dtm_t* dtm; static uint64_t trace_count = 0; bool verbose; bool done_reset; void handle_sigterm(int sig) { dtm->stop(); } double sc_time_stamp() { return trace_count; } extern "C" int vpi_get_vlog_info(void* arg) { return 0; } int main(int argc, char** argv) { unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid(); uint64_t max_cycles = -1; uint64_t start = 0; int ret = 0; FILE *vcdfile = NULL; bool print_cycles = false; for (int i = 1; i < argc; i++) { std::string arg = argv[i]; if (arg.substr(0, 2) == "-v") { const char* filename = argv[i]+2; vcdfile = strcmp(filename, "-") == 0 ? stdout : fopen(filename, "w"); if (!vcdfile) abort(); } else if (arg.substr(0, 2) == "-s") random_seed = atoi(argv[i]+2); else if (arg == "+verbose") verbose = true; else if (arg.substr(0, 12) == "+max-cycles=") max_cycles = atoll(argv[i]+12); else if (arg.substr(0, 7) == "+start=") start = atoll(argv[i]+7); else if (arg.substr(0, 12) == "+cycle-count") print_cycles = true; } srand(random_seed); srand48(random_seed); Verilated::randReset(2); VTestHarness *tile = new VTestHarness; #if VM_TRACE Verilated::traceEverOn(true); // Verilator must compute traced signals std::unique_ptr vcdfd(new VerilatedVcdFILE(vcdfile)); std::unique_ptr tfp(new VerilatedVcdC(vcdfd.get())); if (vcdfile) { tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy tfp->open(""); } #endif dtm = new dtm_t(std::vector(argv + 1, argv + argc)); signal(SIGTERM, handle_sigterm); // reset for several cycles to handle pipelined reset for (int i = 0; i < 10; i++) { tile->reset = 1; tile->clk = 0; tile->eval(); tile->clk = 1; tile->eval(); tile->reset = 0; } done_reset = true; while (!dtm->done() && !tile->io_success && trace_count < max_cycles) { tile->clk = 0; tile->eval(); #if VM_TRACE bool dump = tfp && trace_count >= start; if (dump) tfp->dump(static_cast(trace_count * 2)); #endif tile->clk = 1; tile->eval(); #if VM_TRACE if (dump) tfp->dump(static_cast(trace_count * 2 + 1)); #endif trace_count++; } #if VM_TRACE if (tfp) tfp->close(); #endif if (vcdfile) fclose(vcdfile); if (dtm->exit_code()) { fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count); ret = dtm->exit_code(); } else if (trace_count == max_cycles) { fprintf(stderr, "*** FAILED *** (timeout, seed %d) after %ld cycles\n", random_seed, trace_count); ret = 2; } else if (verbose || print_cycles) { fprintf(stderr, "Completed after %ld cycles\n", trace_count); } delete dtm; delete tile; return ret; }