-
Notifications
You must be signed in to change notification settings - Fork 9
/
verilator.hpp
141 lines (114 loc) · 2.44 KB
/
verilator.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*! Preamble shared by all Kôika programs compiled to C++ using Verilator !*/
#include <cstdint>
#include "verilated.h"
#ifdef TRACE
#include "verilated_vcd_c.h"
#endif
#define TIMESTEP 5
template<typename Dut>
class Toplevel {
protected:
Dut dut;
std::uint64_t time;
#ifdef TRACE
VerilatedVcdC* tfp{};
#endif
virtual void clock(bool /*up*/) = 0;
virtual void reset(bool /*up*/) = 0;
void dump() {
#ifdef TRACE
tfp->dump(time);
#endif
}
void tick(bool up) {
time += TIMESTEP;
clock(up);
dut.eval();
dump();
}
void cycle() {
tick(1);
tick(0);
}
void reset() {
reset(0);
clock(0);
dut.eval();
time = 0;
cycle();
reset(1);
}
public:
void run(std::uint_fast64_t ncycles) {
reset();
for (std::uint_fast64_t cid = 0; !Verilated::gotFinish() && cid < ncycles; cid++) {
cycle();
}
}
#ifdef TRACE
void trace(std::uint_fast64_t ncycles, char* vcdpath) {
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC{};
dut.trace(tfp, 99);
tfp->open(vcdpath);
run(ncycles);
dump();
tfp->close();
delete tfp;
}
#endif
Toplevel() : dut{}, time{0} {}
};
template<typename Dut>
class KoikaToplevel : public Toplevel<Dut> {
protected:
using Toplevel<Dut>::dut;
using Toplevel<Dut>::cycle;
// Change CLK to the name of your clock signal
void clock(bool up) {
dut.CLK = up;
}
// Change RST_N to the name of your clock signal
void reset(bool up) {
dut.RST_N = up;
}
public:
KoikaToplevel() : Toplevel<Dut>{} {}
};
struct cli_arguments {
char* vcd_fpath;
std::uint64_t ncycles;
cli_arguments(int argc, char** argv) : vcd_fpath(nullptr), ncycles(UINT64_MAX) {
int offset = 1;
while (offset < argc && argv[offset][0] == '+') {
offset++;
}
if (offset + 1 < argc) {
vcd_fpath = argv[offset + 1];
}
if (offset < argc) {
ncycles = static_cast<std::uint64_t>(std::strtoull(argv[offset], nullptr, 10));
}
}
};
template<typename Top>
int _main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
cli_arguments args(argc, argv);
#ifdef TRACE
if (!args.vcd_fpath) {
printf("Usage: %s ncycles vcd_fname\n", argv[0]);
return 1;
}
#endif
Top toplevel{};
#ifdef TRACE
toplevel.trace(args.ncycles, args.vcd_fpath);
#else
toplevel.run(args.ncycles);
#endif
return 0;
}
// Local Variables:
// flycheck-clang-include-path: ("/usr/share/verilator/include")
// End: