1
0
rocket-chip/csrc/emulator.cc
Andrew Waterman ed827678ac Write test harness in Chisel
This is an unavoidably invasive commit, because it affects the unit tests
(which formerly exited using stop()), the test harness Verilog generator
(since it is no longer necessary), and the DRAM model (since it is no
longer connected).  However, this should substantially reduce the effort
of building test harnesses in the future, since manual or semi-automatic
Verilog writing should no longer be necessary.  Furthermore, there is now
very little duplication of effort between the Verilator and VCS test
harnesses.

This commit removes support for DRAMsim, which is a bit of an unfortunate
consequence.  The main blocker is the lack of Verilog parameterization for
BlackBox.  It would be straightforward to revive DRAMsim once support for
that feature is added to Chisel and FIRRTL.  But that might not even be
necessary, as we move towards synthesizable DRAM models and FAME-1
transformations.
2016-08-15 23:27:27 -07:00

138 lines
2.9 KiB
C++

// See LICENSE for license details.
#include "verilated.h"
#if VM_TRACE
#include "verilated_vcd_c.h"
#endif
#include <fesvr/dtm.h>
#include <iostream>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern dtm_t* dtm;
static uint64_t trace_count = 0;
bool verbose;
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;
#if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
std::unique_ptr<VerilatedVcdC> 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<std::string>(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;
}
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(trace_count * 2);
#endif
tile.clk = 1;
tile.eval();
#if VM_TRACE
if (dump)
tfp->dump(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;
return ret;
}