#ifndef _NPC_TRACER_H_ #define _NPC_TRACER_H_ #include "components.hpp" #include #include template class Tracer { std::shared_ptr top; std::unique_ptr m_trace; uint64_t cycle = 0; public: Tracer(T *top, std::filesystem::path wavefile) { top = top; Verilated::traceEverOn(true); m_trace = std::make_unique(); top->trace(m_trace.get(), 5); m_trace->open(wavefile.c_str()); } ~Tracer() { m_trace->close(); } /** * Dump signals to waveform file. Must be called once after every top->eval() * call. */ void update() { m_trace->dump(cycle++); } }; template class VlModuleInterfaceCommon : public T { uint64_t sim_time = 0; uint64_t posedge_cnt = 0; std::unique_ptr> tracer; public: VlModuleInterfaceCommon(std::filesystem::path wavefile) { if (!wavefile.empty()) tracer = std::make_unique>(this, wavefile); } void eval() { if (this->is_posedge()) { posedge_cnt++; } T::clock = !T::clock; sim_time++; T::eval(); if (tracer) tracer->update(); } void eval(int n) { for (int i = 0; i < n; i++) { this->eval(); } } void reset_eval(int n) { extern bool g_skip_memcheck; g_skip_memcheck = true; this->reset = 1; this->eval(n); this->reset = 0; g_skip_memcheck = false; } bool is_posedge() { // Will be posedge when eval is called return T::clock == 0; } }; #endif