diff --git a/Makefile b/Makefile index 855c5ada75c9cda2194a3c2ba73b613a4b6d3b9c..7418a10d2292798eecd6b0c6b547500b0759cf81 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,6 @@ EMU_CXXFLAGS = -std=c++11 -static -Wall -I$(EMU_CSRC_DIR) EMU_CXXFLAGS += -DVERILATOR -Wno-maybe-uninitialized EMU_LDFLAGS = -lpthread -lSDL2 -ldl -# dump vcd: --debug --trace VERILATOR_FLAGS = --top-module $(SIM_TOP) \ +define+VERILATOR=1 \ +define+PRINTF_COND=1 \ @@ -72,6 +71,7 @@ VERILATOR_FLAGS = --top-module $(SIM_TOP) \ --assert \ --savable \ --stats-vars \ + --trace \ --output-split 5000 \ --output-split-cfuncs 5000 \ -I$(abspath $(BUILD_DIR)) \ @@ -115,7 +115,7 @@ else SNAPSHOT_OPTION = --load-snapshot=$(REMOTE_PREFIX)/$(SNAPSHOT) endif -EMU_FLAGS = -s $(SEED) -b $(B) -e $(E) $(SNAPSHOT_OPTION) +EMU_FLAGS = -s $(SEED) -b $(B) -e $(E) $(SNAPSHOT_OPTION) --dump-wave emu: $(EMU) ifeq ($(REMOTE),localhost) diff --git a/src/test/csrc/emu.cpp b/src/test/csrc/emu.cpp index 98295f4d00945ef1f3563de4214e152b67893fd6..7e29b9a864387acd24a09f550cf9f2d9e59e1056 100644 --- a/src/test/csrc/emu.cpp +++ b/src/test/csrc/emu.cpp @@ -25,10 +25,20 @@ Emulator::Emulator(EmuArgs &args): init_difftest(); + enable_waveform = args.enable_waveform; + if (enable_waveform) { + Verilated::traceEverOn(true); // Verilator must compute traced signals + tfp = new VerilatedVcdC; + dut_ptr->trace(tfp, 99); // Trace 99 levels of hierarchy + time_t now = time(NULL); + tfp->open(waveform_filename(now)); // Open the dump file + } + // init core reset_ncycles(10); if (args.snapshot_path != NULL) { + printf("loading from snapshot `%s`...\n", args.snapshot_path); snapshot_load(args.snapshot_path); hascommit = 1; } @@ -93,9 +103,13 @@ inline void Emulator::single_cycle() { dut_ptr->clock = 1; dut_ptr->eval(); -#if VM_TRACE - tfp->dump(cycles); -#endif + if (enable_waveform) { + uint64_t cycle = dut_ptr->io_trap_cycleCnt; + uint64_t begin = dut_ptr->io_logCtrl_log_begin; + uint64_t end = dut_ptr->io_logCtrl_log_end; + bool in_range = (begin <= cycle) && (cycle <= end); + if (in_range) { tfp->dump(cycle); } + } if (dut_ptr->io_uart_out_valid) { printf("%c", dut_ptr->io_uart_out_ch); @@ -127,14 +141,6 @@ uint64_t Emulator::execute(uint64_t n) { diff.wdata = wdata; diff.wdst = wdst; -#if VM_TRACE - Verilated::traceEverOn(true); // Verilator must compute traced signals - VL_PRINTF("Enabling waves...\n"); - tfp = new VerilatedVcdC; - dut_ptr->trace(tfp, 99); // Trace 99 levels of hierarchy - tfp->open("vlt_dump.vcd"); // Open the dump file -#endif - while (trapCode == STATE_RUNNING && n > 0) { single_cycle(); n --; @@ -146,9 +152,6 @@ uint64_t Emulator::execute(uint64_t n) { eprintf("No instruction commits for %d cycles, maybe get stuck\n" "(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)\n", stuck_limit, stuck_limit); -#if VM_TRACE - tfp->close(); -#endif difftest_display(dut_ptr->io_difftest_priviledgeMode); trapCode = STATE_ABORT; } @@ -176,9 +179,6 @@ uint64_t Emulator::execute(uint64_t n) { diff.priviledgeMode = dut_ptr->io_difftest_priviledgeMode; if (difftest_step(&diff)) { -#if VM_TRACE - tfp->close(); -#endif trapCode = STATE_ABORT; } lastcommit = n; @@ -197,17 +197,31 @@ uint64_t Emulator::execute(uint64_t n) { } } + if (enable_waveform) tfp->close(); display_trapinfo(); return cycles; } -inline char* Emulator::snapshot_filename(time_t t) { - static char buf[1024]; +inline char* Emulator::timestamp_filename(time_t t, char *buf) { char buf_time[64]; strftime(buf_time, sizeof(buf_time), "%F@%T", localtime(&t)); char *noop_home = getenv("NOOP_HOME"); assert(noop_home != NULL); - snprintf(buf, 1024, "%s/build/%s.snapshot", noop_home, buf_time); + int len = snprintf(buf, 1024, "%s/build/%s", noop_home, buf_time); + return buf + len; +} + +inline char* Emulator::snapshot_filename(time_t t) { + static char buf[1024]; + char *p = timestamp_filename(t, buf); + strcpy(p, ".snapshot"); + return buf; +} + +inline char* Emulator::waveform_filename(time_t t) { + static char buf[1024]; + char *p = timestamp_filename(t, buf); + strcpy(p, ".vcd"); return buf; } diff --git a/src/test/csrc/emu.h b/src/test/csrc/emu.h index 1a2bfbe2f10eec681913325343fee2b99f44a648..90e2aba44d8cbdbb38e6cb00eac6c1c9cbcd4758 100644 --- a/src/test/csrc/emu.h +++ b/src/test/csrc/emu.h @@ -1,10 +1,7 @@ #include "common.h" #include "snapshot.h" #include "VXSSimTop.h" - -#if VM_TRACE #include // Trace file format header -#endif #define DIFFTEST_WIDTH 6 #define SNAPSHOT_INTERVAL 10 // unit: second @@ -15,6 +12,7 @@ struct EmuArgs { uint64_t log_begin, log_end; const char *image; const char *snapshot_path; + bool enable_waveform; EmuArgs() { seed = 0; @@ -23,14 +21,14 @@ struct EmuArgs { log_end = -1; snapshot_path = NULL; image = NULL; + enable_waveform = false; } }; class Emulator { VXSSimTop *dut_ptr; -#if VM_TRACE VerilatedVcdC* tfp; -#endif + bool enable_waveform; VerilatedSaveMem snapshot_slot[2]; enum { @@ -50,9 +48,11 @@ class Emulator { inline void reset_ncycles(size_t cycles); inline void single_cycle(); void display_trapinfo(); + inline char* timestamp_filename(time_t t, char *buf); inline char* snapshot_filename(time_t t); void snapshot_save(const char *filename); void snapshot_load(const char *filename); + inline char* waveform_filename(time_t t); public: Emulator(EmuArgs &args); diff --git a/src/test/csrc/main.cpp b/src/test/csrc/main.cpp index a7c5f99feafce22259b9bd6708fb8efd47ba67ee..1cec6474384ce91ac6190f3a2b92e0aa4d2ad224 100644 --- a/src/test/csrc/main.cpp +++ b/src/test/csrc/main.cpp @@ -16,6 +16,8 @@ static inline void print_help(const char *file) { printf(" -i, --image=FILE run with this image file\n"); printf(" -b, --log-begin=NUM display log from NUM th cycle\n"); printf(" -e, --log-end=NUM stop display log at NUM th cycle\n"); + printf(" --load-snapshot=PATH load snapshot from PATH\n"); + printf(" --dump-wave dump waveform when log is enabled\n"); printf(" -h, --help print program help info\n"); printf("\n"); } @@ -25,6 +27,7 @@ static inline EmuArgs parse_args(int argc, const char *argv[]) { int long_index = 0; const struct option long_options[] = { { "load-snapshot", 1, NULL, 0 }, + { "dump-wave", 0, NULL, 0 }, { "seed", 1, NULL, 's' }, { "max-cycles", 1, NULL, 'C' }, { "image", 1, NULL, 'i' }, @@ -39,9 +42,9 @@ static inline EmuArgs parse_args(int argc, const char *argv[]) { "-s:C:hi:m:b:e:", long_options, &long_index)) != -1) { switch (o) { case 0: - if (long_index == 0) { - args.snapshot_path = optarg; - break; + switch (long_index) { + case 0: args.snapshot_path = optarg; continue; + case 1: args.enable_waveform = true; continue; } // fall through default: