-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregfile_sc.cpp
179 lines (155 loc) · 4.21 KB
/
regfile_sc.cpp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <systemc.h>
#include "Vregfile.h"
class regfile_tb_t : public sc_module
{
public:
Vregfile* dut;
sc_in<bool> clk_tb;
sc_signal<bool> resetb_tb;
sc_signal<uint32_t> a_rs1_tb;
sc_signal<uint32_t> a_rs2_tb;
sc_signal<uint32_t> a_rd_tb;
sc_signal<uint32_t> d_rs1_tb;
sc_signal<uint32_t> d_rs2_tb;
sc_signal<uint32_t> d_rd_tb;
sc_signal<bool> we_rd_tb;
SC_CTOR(regfile_tb_t)
: clk_tb("clk_tb")
, resetb_tb("resetb_tb")
, a_rs1_tb("a_rs1_tb")
, a_rs2_tb("a_rs2_tb")
, a_rd_tb("a_rd_tb")
, d_rs1_tb("d_rs1_tb")
, d_rs2_tb("d_rs2_tb")
, d_rd_tb("d_rd_tb")
, we_rd_tb("we_rd_tb")
{
SC_THREAD(test_thread);
sensitive << clk_tb.pos();
dut = new Vregfile("dut");
dut->clk(clk_tb);
dut->resetb(resetb_tb);
dut->a_rs1(a_rs1_tb);
dut->a_rs2(a_rs2_tb);
dut->a_rd(a_rd_tb);
dut->d_rs1(d_rs1_tb);
dut->d_rs2(d_rs2_tb);
dut->d_rd(d_rd_tb);
dut->we_rd(we_rd_tb);
}
~regfile_tb_t()
{
delete dut;
}
void test_thread(void);
private:
void reset(void);
void test1(void);
void test2(void);
};
void regfile_tb_t::reset()
{
resetb_tb.write(false);
wait();
resetb_tb.write(true);
wait(SC_ZERO_TIME);
}
void regfile_tb_t::test_thread()
{
reset();
test1();
test2();
sc_stop();
}
void regfile_tb_t::test1()
{
std::cout
<< "(TT) --------------------------------------------------" << std::endl
<< "(TT) Test 1: Basic R/W " << std::endl
<< "(TT) 1. Writes 32, 31, ... to x0, x1, ... consecutively" << std::endl
<< "(TT) 2. RS1 reads x31, x0, x1, ..." << std::endl
<< "(TT) 3. RS2 reads x30, x31, x0, x1, ..." << std::endl
<< "(TT) 4. RS1 should read X, 0, 31, 30, ..." << std::endl
<< "(TT) 5. RS2 should read X, X, 0, 31, 30, ..." << std::endl
<< "(TT) 6. No stray value should remain" << std::endl
<< "(TT) --------------------------------------------------" << std::endl;
// Reset DUT
// Do not write
we_rd_tb.write(false);
reset();
for (uint32_t i=0; i<40; ++i) {
// Writeback addr
a_rd_tb.write(i % 32);
// Writeback data
d_rd_tb.write(32 - i % 32);
// Write enbale
we_rd_tb.write(true);
// RS1 addr
a_rs1_tb.write((i - 1) % 32);
// RS2 addr
a_rs2_tb.write((i - 2) % 32);
// Wait for combinational logic
wait();
std::cout << "(TT) a_rd = x" << a_rd_tb
<< ", d_rd = " << d_rd_tb
<< ", we_rd = " << we_rd_tb
<< std::endl;
std::cout << "(TT) a_rs1 = x" << a_rs1_tb
<< ", d_rs1 = " << d_rs1_tb
<< std::endl;
std::cout << "(TT) a_rs2 = x" << a_rs2_tb
<< ", d_rs2 = " << d_rs2_tb
<< std::endl;
std::cout << std::endl;
}
}
void regfile_tb_t::test2()
{
std::cout
<< "(TT) --------------------------------------------------" << std::endl
<< "(TT) Test 2: Forwarding R/W " << std::endl
<< "(TT) 1. Writes 32, 31, ... to x0, x1, ... consecutively" << std::endl
<< "(TT) 2. RS1 reads x0, x1, ..." << std::endl
<< "(TT) 3. RS2 reads x31, x0, x1, ..." << std::endl
<< "(TT) 4. RS1 should read 0, 31, 30, ..." << std::endl
<< "(TT) 5. RS2 should read X, 0, 31, 30, ..." << std::endl
<< "(TT) 6. No stray value should remain" << std::endl
<< "(TT) --------------------------------------------------" << std::endl;
// Reset
we_rd_tb.write(false);
reset();
for (uint32_t i=0; i<40; ++i) {
// Writeback addr
a_rd_tb.write(i % 32);
// Writeback data
d_rd_tb.write(32 - i % 32);
we_rd_tb.write(true);
// RS1 addr
a_rs1_tb.write(i % 32);
// RS2 addr
a_rs2_tb.write((i-1) % 32);
wait();
std::cout << "(TT) a_rd = x" << a_rd_tb
<< ", d_rd = " << d_rd_tb
<< ", we_rd = " << we_rd_tb
<< std::endl;
std::cout << "(TT) a_rs1 = x" << a_rs1_tb
<< ", d_rs1 = " << d_rs1_tb
<< std::endl;
std::cout << "(TT) a_rs2 = x" << a_rs2_tb
<< ", d_rs2 = " << d_rs2_tb
<< std::endl;
std::cout << std::endl;
}
}
int sc_main(int argc, char** argv)
{
Verilated::commandArgs(argc, argv);
auto tb = new regfile_tb_t("tb");
sc_clock sysclk("sysclk", 10, SC_NS);
tb->clk_tb(sysclk);
// while(!Verilated::gotFinish()) {sc_start(1, SC_NS);}
sc_start();
delete tb;
exit(0);
}