ysyx-workbench/npc/include/vl_wrapper.hpp

119 lines
2.6 KiB
C++
Raw Permalink Normal View History

2024-04-09 09:03:21 +00:00
#ifndef _NPC_TRACER_H_
#define _NPC_TRACER_H_
2024-04-12 01:35:41 +00:00
#include "components.hpp"
2024-07-10 12:27:09 +00:00
#include "types.h"
#include "verilated.h"
2024-04-09 09:03:21 +00:00
#include <filesystem>
2024-07-10 12:27:09 +00:00
#include <gdbstub.h>
#include <sys/types.h>
2024-04-09 09:03:21 +00:00
#include <verilated_vcd_c.h>
template <class T> class Tracer {
std::shared_ptr<T> top;
std::unique_ptr<VerilatedVcdC> m_trace;
uint64_t cycle = 0;
public:
Tracer(T *top, std::filesystem::path wavefile) {
top = top;
Verilated::traceEverOn(true);
m_trace = std::make_unique<VerilatedVcdC>();
top->trace(m_trace.get(), 5);
m_trace->open(wavefile.c_str());
}
~Tracer() { m_trace->close(); }
/**
2024-04-12 01:35:41 +00:00
* Dump signals to waveform file. Must be called once after every top->eval()
* call.
2024-04-09 09:03:21 +00:00
*/
void update() { m_trace->dump(cycle++); }
};
2024-07-10 12:27:09 +00:00
template <typename T, typename R> class VlModuleInterfaceCommon : public T {
2024-04-09 09:03:21 +00:00
uint64_t sim_time = 0;
uint64_t posedge_cnt = 0;
std::unique_ptr<Tracer<T>> tracer;
2024-09-06 06:56:10 +00:00
std::filesystem::path wavefile;
2024-04-09 09:03:21 +00:00
public:
2024-07-10 12:27:09 +00:00
const R *registers;
VlModuleInterfaceCommon<T, R>() {
tracer = nullptr;
registers = nullptr;
}
void setup(std::filesystem::path wavefile, const R *r) {
2024-09-06 06:56:10 +00:00
wavefile = "wave.vcd";
2024-07-10 12:27:09 +00:00
registers = r;
2024-04-09 09:03:21 +00:00
}
2024-07-10 12:27:09 +00:00
void eval(void) {
2024-04-09 09:03:21 +00:00
if (this->is_posedge()) {
posedge_cnt++;
}
T::clock = !T::clock;
sim_time++;
T::eval();
if (tracer)
tracer->update();
}
const Breakpoint *stepi(const std::vector<Breakpoint> &breakpoints) {
this->eval();
this->eval();
size_t pc = registers->get_pc();
for (const auto &bp : breakpoints) {
if (pc == bp.addr) {
return &bp;
}
2024-04-09 09:03:21 +00:00
}
return nullptr;
2024-04-09 09:03:21 +00:00
}
2024-07-10 12:27:09 +00:00
const Breakpoint *cont(const std::vector<Breakpoint> &breakpoints) {
const Breakpoint *res = nullptr;
2024-07-10 12:27:09 +00:00
do {
res = stepi(breakpoints);
} while (res == nullptr);
return res;
2024-07-10 12:27:09 +00:00
}
2024-04-09 09:03:21 +00:00
void reset_eval(int n) {
2024-04-12 01:35:41 +00:00
extern bool g_skip_memcheck;
g_skip_memcheck = true;
2024-04-09 09:03:21 +00:00
this->reset = 1;
do {
this->eval();
} while (--n);
2024-04-09 09:03:21 +00:00
this->reset = 0;
2024-04-12 01:35:41 +00:00
g_skip_memcheck = false;
2024-04-09 09:03:21 +00:00
}
2024-09-06 06:56:10 +00:00
2024-04-09 09:03:21 +00:00
bool is_posedge() {
// Will be posedge when eval is called
return T::clock == 0;
}
2024-09-06 06:56:10 +00:00
bool start_trace() { return init_tracer(wavefile); }
bool end_trace() {
tracer.reset();
return true;
}
private:
bool init_tracer(std::filesystem::path wavefile) {
fmt::print("wavefile: {}", wavefile.string());
std::filesystem::path wav = "wave.vcd";
if (!wav.empty()) {
// Creating of tracer must happen after this class fully initialized
tracer = std::make_unique<Tracer<T>>(this, wav);
return true;
}
return false;
}
2024-04-09 09:03:21 +00:00
};
#endif