diff options
Diffstat (limited to 'rv64cpu/tb/unit/tb_regfile.cc')
| -rw-r--r-- | rv64cpu/tb/unit/tb_regfile.cc | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/rv64cpu/tb/unit/tb_regfile.cc b/rv64cpu/tb/unit/tb_regfile.cc deleted file mode 100644 index 8e210ec..0000000 --- a/rv64cpu/tb/unit/tb_regfile.cc +++ /dev/null @@ -1,192 +0,0 @@ -// Richard CPU -// Copyright (C) 2026 Richard Qin -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -// File path: tb/unit/tb_regfile.cc -// Description: Register file unit test - -#include <iostream> -#include <cassert> -#include <verilated.h> -#include "Vregfile.h" - -void tick(Vregfile* dut) { - dut->clk = 0; - dut->eval(); - dut->clk = 1; - dut->eval(); - dut->clk = 0; - dut->eval(); -} - -int main(int argc, char** argv) { - Verilated::commandArgs(argc, argv); - Vregfile* dut = new Vregfile; - - dut->clk = 0; - dut->rst = 0; - dut->reg_write_en = 0; - dut->rd_addr = 0; - dut->rd_wdata = 0; - dut->rs1_addr = 0; - dut->rs2_addr = 0; - - std::cout << "----------------------------------" << std::endl; - std::cout << " Register File Unit Test" << std::endl; - std::cout << "----------------------------------" << std::endl; - - // Test 1: Reset - dut->rst = 1; - tick(dut); - dut->rst = 0; - std::cout << "\033[32m[PASS] Reset complete\033[0m" << std::endl; - - // Test 2: Write and read - dut->reg_write_en = 1; - dut->rd_addr = 5; - dut->rd_wdata = 0xDEADBEEF; - tick(dut); - - dut->reg_write_en = 0; - dut->rs1_addr = 5; - dut->eval(); - assert(dut->rs1_rdata == 0xDEADBEEF); - std::cout << "\033[32m[PASS] Write and read (x5) complete\033[0m" << std::endl; - - // Test 3: x0 - dut->reg_write_en = 1; - dut->rd_addr = 0; - dut->rd_wdata = 0x12345678; - tick(dut); - - dut->reg_write_en = 0; - dut->rs2_addr = 0; - dut->eval(); - assert(dut->rs2_rdata == 0); - 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; - dut->rd_addr = 6; - dut->rd_wdata = 0x87654321; - tick(dut); - - dut->reg_write_en = 1; - dut->rd_addr = 7; - dut->rd_wdata = 0x11223344; - tick(dut); - - dut->rs1_addr = 6; - dut->rs2_addr = 7; - dut->eval(); - - assert(dut->rs1_rdata == 0x87654321 && dut->rs2_rdata == 0x11223344); - std::cout << "\033[32m[PASS] Dual-port simultaneous read complete\033[0m" << 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; - dut->reg_write_en = 0; // Clear write enable from previous test - 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) - // With internal bypass added, combinational read should return the NEW bypassed value immediately. - dut->reg_write_en = 0; - dut->rd_addr = 15; - dut->rd_wdata = 0x55555555; - tick(dut); // Write 0x55555555 to x15 to set old value - - // Setup for RAW - dut->reg_write_en = 1; - dut->rd_addr = 15; - dut->rd_wdata = 0x99999999; - - // Before tick, read should be the new bypassed value (0x99999999) - dut->rs1_addr = 15; - dut->eval(); - assert(dut->rs1_rdata == 0x99999999); - - 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 << "----------------------------------" << std::endl; - std::cout << "\033[32mAll 8 tests passed!\033[0m" << std::endl; - std::cout << "----------------------------------" << std::endl; - - delete dut; - exit(0); -}
\ No newline at end of file |
