aboutsummaryrefslogtreecommitdiff
path: root/rv64cpu/tb/unit/tb_regfile.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-03-16 14:57:03 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-03-16 15:02:06 +0800
commitac1bfb6ae8253d71904a273b20a1d0e5d4803fd4 (patch)
tree61bd790dcf30dfd3435c7738c1f9e63f3ac121dd /rv64cpu/tb/unit/tb_regfile.cc
parent1554746fd79d51c6bd2281820520a4e2d2c16301 (diff)
downloadrcc-project-ac1bfb6ae8253d71904a273b20a1d0e5d4803fd4.tar.gz
rcc-project-ac1bfb6ae8253d71904a273b20a1d0e5d4803fd4.tar.xz
expand tests and format output
Diffstat (limited to 'rv64cpu/tb/unit/tb_regfile.cc')
-rw-r--r--rv64cpu/tb/unit/tb_regfile.cc98
1 files changed, 93 insertions, 5 deletions
diff --git a/rv64cpu/tb/unit/tb_regfile.cc b/rv64cpu/tb/unit/tb_regfile.cc
index eef92a2..2491eb6 100644
--- a/rv64cpu/tb/unit/tb_regfile.cc
+++ b/rv64cpu/tb/unit/tb_regfile.cc
@@ -48,7 +48,7 @@ int main(int argc, char** argv) {
dut->rst = 1;
tick(dut);
dut->rst = 0;
- std::cout << "[PASS] Reset complete" << std::endl;
+ std::cout << "\033[32m[PASS] Reset complete\033[0m" << std::endl;
// Test 2: Write and read
dut->reg_write_en = 1;
@@ -60,7 +60,7 @@ int main(int argc, char** argv) {
dut->rs1_addr = 5;
dut->eval();
assert(dut->rs1_rdata == 0xDEADBEEF);
- std::cout << "[PASS] Write and read (x5) complete" << std::endl;
+ std::cout << "\033[32m[PASS] Write and read (x5) complete\033[0m" << std::endl;
// Test 3: x0
dut->reg_write_en = 1;
@@ -72,7 +72,7 @@ int main(int argc, char** argv) {
dut->rs2_addr = 0;
dut->eval();
assert(dut->rs2_rdata == 0);
- std::cout << "[PASS] Write and read (x0) complete" << std::endl;
+ std::cout << "\033[32m[PASS] Write and read (x0) complete\033[0m" << std::endl;
// Test 4: Dual-port simultaneous read
dut->reg_write_en = 1;
@@ -90,9 +90,97 @@ int main(int argc, char** argv) {
dut->eval();
assert(dut->rs1_rdata == 0x87654321 && dut->rs2_rdata == 0x11223344);
- std::cout << "[PASS] Dual-port simultaneous read complete" << std::endl;
+ std::cout << "\033[32m[PASS] Dual-port simultaneous read complete\033[0m" << std::endl;
- std::cout << "Register file unit test complete" << std::endl;
+
+ // Test 5: Write enable = 0 (Data should not change)
+ dut->reg_write_en = 1;
+ dut->rd_addr = 10;
+ dut->rd_wdata = 0xCAFEBABE;
+ tick(dut);
+
+ dut->reg_write_en = 0; // Disable write
+ dut->rd_addr = 10;
+ dut->rd_wdata = 0x11111111; // Attempt to overwrite
+ tick(dut);
+
+ dut->rs1_addr = 10;
+ dut->eval();
+ assert(dut->rs1_rdata == 0xCAFEBABE);
+ std::cout << "\033[32m[PASS] Write enable = 0 correctly ignores write\033[0m" << std::endl;
+
+ // Test 6: Verify full reset behavior
+ // First, dirty up some registers
+ for (int i = 1; i < 32; i += 5) {
+ dut->reg_write_en = 1;
+ dut->rd_addr = i;
+ dut->rd_wdata = 0x1000 + i;
+ tick(dut);
+ }
+
+ // Apply reset
+ dut->rst = 1;
+ tick(dut);
+ dut->rst = 0;
+
+ // Check all are zero
+ bool reset_ok = true;
+ for (int i = 1; i < 32; i++) {
+ dut->rs1_addr = i;
+ dut->eval();
+ if (dut->rs1_rdata != 0) {
+ reset_ok = false;
+ std::cerr << "\033[31m[FAIL] Reset failed on register x" << i << std::endl;
+ }
+ }
+ assert(reset_ok);
+ std::cout << "\033[32m[PASS] Full memory reset verified\033[0m" << std::endl;
+
+ // Test 7: Read-After-Write (Same cycle collision check)
+ // Combinational read should return the OLD value on the cycle WE is asserted
+ // NOTE: Verilator handles combinational loops. Before the clock edge, it evaluates.
+ dut->reg_write_en = 1;
+ dut->rd_addr = 15;
+ dut->rd_wdata = 0x55555555; // Pseudo
+
+ // Setup for RAW
+ dut->reg_write_en = 1;
+ dut->rd_addr = 15;
+ dut->rd_wdata = 0x99999999;
+
+ // Before tick, read should be 0 (from previous reset)
+ dut->rs1_addr = 15;
+ dut->eval();
+ assert(dut->rs1_rdata == 0);
+
+ tick(dut); // Clock edge happens
+
+ dut->reg_write_en = 0; // Turn off write
+ dut->eval(); // Combinational read update
+ assert(dut->rs1_rdata == 0x99999999);
+ std::cout << "\033[32m[PASS] Read-After-Write (RAW) behavior verified\033[0m" << std::endl;
+
+ // Test 8: Sweep all registers (Write and Read distinct values)
+ for (int i = 1; i < 32; i++) {
+ dut->reg_write_en = 1;
+ dut->rd_addr = i;
+ dut->rd_wdata = 0xABCDE000 + i;
+ tick(dut);
+ }
+
+ dut->reg_write_en = 0;
+ bool sweep_ok = true;
+ for (int i = 1; i < 32; i++) {
+ dut->rs1_addr = i;
+ dut->eval();
+ if (dut->rs1_rdata != (0xABCDE000 + i)) {
+ sweep_ok = false;
+ }
+ }
+ assert(sweep_ok);
+ std::cout << "\033[32m[PASS] All 31 mutable registers write/read successfully without collision\033[0m" << std::endl;
+
+ std::cout << "Register file unit test complete\033[0m" << std::endl;
delete dut;
exit(0);