diff --git a/nemu/src/cpu/cpu-exec.c b/nemu/src/cpu/cpu-exec.c index d2b1f98..097c02f 100644 --- a/nemu/src/cpu/cpu-exec.c +++ b/nemu/src/cpu/cpu-exec.c @@ -83,7 +83,7 @@ static void execute(uint64_t n) { g_nr_guest_inst ++; trace_and_difftest(&s, cpu.pc); if (wp_eval_all()) { - puts(logbuf[logbuf_rear]); + IFDEF(CONFIG_ITRACE, puts(logbuf[logbuf_rear])); break; } if (nemu_state.state != NEMU_RUNNING) break; @@ -132,7 +132,7 @@ void cpu_exec(uint64_t n) { ANSI_FMT("HIT BAD TRAP", ANSI_FG_RED))), nemu_state.halt_pc); if(nemu_state.halt_ret != 0) { - log_itrace_print(); + IFDEF(CONFIG_ITRACE, log_itrace_print()); } } // fall through case NEMU_QUIT: statistic(); diff --git a/npc/CMakeLists.txt b/npc/CMakeLists.txt index bd56708..b40fa44 100644 --- a/npc/CMakeLists.txt +++ b/npc/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.26) project(flow) -set (CMAKE_CXX_STANDARD 14) +set (CMAKE_CXX_STANDARD 17) cmake_policy(SET CMP0144 NEW) include(CMakeDependentOption) diff --git a/npc/csrc/Flow/main.cpp b/npc/csrc/Flow/main.cpp index 465e1f0..3fd0129 100644 --- a/npc/csrc/Flow/main.cpp +++ b/npc/csrc/Flow/main.cpp @@ -1,3 +1,8 @@ +#include "VFlow___024root.h" +#include "tracer.h" +#include +#include +#include #include #include #include @@ -13,40 +18,90 @@ std::vector regsHandle; int regs[32]; -static void init_vpi_regs() { - std::string regfile = "TOP.Flow.reg_0.regFile_"; - for(int i = 0; i < 32; i++) { - std::string regname = regfile + std::to_string(i); - vpiHandle vh = vpi_handle_by_name((PLI_BYTE8 *)regname.c_str(), NULL); - regsHandle.push_back(vh); +template +class Tracer { +#ifdef VERILATOR_TRACE + std::shared_ptr top; + std::unique_ptr m_trace; + uint64_t time = 0; +#endif + public: + Tracer(std::shared_ptr top, std::filesystem::path wavefile) { +#ifdef VERILATOR_TRACE + top = top; + Verilated::traceEverOn(true); + m_trace = std::make_unique(); + top->trace(m_trace.get(), 5); + m_trace->open(wavefile.c_str()); +#endif + } + ~Tracer() { +#ifdef VERILATOR_TRACE + m_trace->close(); +#endif + } + + /** + * Dump signals to waveform file. Must be called once after every top->eval() call. + */ + void update() { +#ifdef VERILATOR_TRACE + m_trace->dump(time++); +#endif + } +}; +template +class _RegistersBase { + std::array regs; + virtual T fetch_reg(size_t id); + public: + void update() { + for(int i = 0; i < regs.size(); i++) { + regs[i] = fetch_reg(i); + } + } + void print_regs() { + for(int i = 0; i < regs.size(); i++) { + printf("%d: %d\t", i, regs[i]); + if(i % 8 == 7) putchar('\n'); + } + putchar('\n'); + } +}; + +template +class _RegistersVPI : public _RegistersBase { + std::array reg_handles; + T fetch_reg(size_t id) { + s_vpi_value v; + v.format = vpiIntVal; + vpi_get_value(reg_handles[id], &v); + return v.value.integer; } -} + public: + _RegistersVPI(const std::string regs_prefix) { + for(int i = 0; i < nr; i++) { + std::string regname = regs_prefix + std::to_string(i); + vpiHandle vh = vpi_handle_by_name((PLI_BYTE8 *)regname.c_str(), NULL); + reg_handles[i] = vh; + } + } +}; -static void init_vpi() { - init_vpi_regs(); -} - -static int vpi_get_int(vpiHandle vh) { - s_vpi_value v; - v.format = vpiIntVal; - vpi_get_value(vh, &v); - return v.value.integer; -} - -static void update_regs() { - for(int i = 0; i < 32; i++) { - regs[i] = vpi_get_int(regsHandle[i]); +template +class Memory { + std::array mem; + size_t addr_to_index(size_t addr) { + // Linear mapping + return addr - 0x80000000; } -} - -static void print_regs() { - for(int i = 0; i < 32; i++) { - printf("%d: %d\t", i, regs[i]); - if(i % 8 == 7) putchar('\n'); - } - putchar('\n'); -} + public: + const T& operator[](size_t addr) { + return mem[addr_to_index(index)]; + } +}; +typedef _RegistersVPI Registers; static int sim_time = 0; int main(int argc, char **argv, char **env) { @@ -54,33 +109,22 @@ int main(int argc, char **argv, char **env) { int posedge_cnt = 0; Verilated::commandArgs(argc, argv); - std::unique_ptr top{new VFlow}; - Verilated::traceEverOn(true); - VerilatedVcdC *m_trace = new VerilatedVcdC; -#ifdef VERILATOR_TRACE - top->trace(m_trace, 5); - m_trace->open("waveform.vcd"); -#endif + auto top = std::make_shared(); + auto top_tracer = std::make_unique>(top, "waveform.vcd"); - init_vpi(); + Registers regs("TOP.Flow.reg_0.regFile_"); top->reset = 0; + top->eval(); for (sim_time = 10; sim_time < MAX_SIM_TIME; sim_time++) { - top->eval(); top->clock = !top->clock; if(top->clock == 1) { // Posedge ++posedge_cnt; - update_regs(); - print_regs(); + regs.update(); + regs.print_regs(); } - -#ifdef VERILATOR_TRACE - m_trace->dump(sim_time); -#endif + top->eval(); } -#ifdef VERILATOR_TRACE - m_trace->close(); -#endif exit(EXIT_SUCCESS); }