diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-11-07 03:30:17 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-11-07 03:31:03 +0800 |
| commit | 2a4c290c55b683352a16747432a7fc4635597cc6 (patch) | |
| tree | a150caea2ade12af4c5dcd70f09bacd3318f4d43 /rv64cpu/tb/unit/tb_mmu_top.cc | |
| parent | e0948e3fc10029ba4bb4d48d7b5daae94fe575b9 (diff) | |
| download | rcc-project-2a4c290c55b683352a16747432a7fc4635597cc6.tar.gz rcc-project-2a4c290c55b683352a16747432a7fc4635597cc6.tar.xz | |
refactor: reset software and test directories
Diffstat (limited to 'rv64cpu/tb/unit/tb_mmu_top.cc')
| -rw-r--r-- | rv64cpu/tb/unit/tb_mmu_top.cc | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/rv64cpu/tb/unit/tb_mmu_top.cc b/rv64cpu/tb/unit/tb_mmu_top.cc deleted file mode 100644 index 5df90ef..0000000 --- a/rv64cpu/tb/unit/tb_mmu_top.cc +++ /dev/null @@ -1,236 +0,0 @@ -#include <cassert> -#include <cstdint> -#include <iostream> -#include <unordered_map> - -#include <verilated.h> - -#include "Vmmu_top.h" - -namespace { - -constexpr uint8_t MODE_BARE = 0; -constexpr uint8_t MODE_SV39 = 8; -constexpr uint8_t MODE_SV48 = 9; - -constexpr uint64_t FLAG_V = 1ULL << 0; -constexpr uint64_t FLAG_R = 1ULL << 1; -constexpr uint64_t FLAG_W = 1ULL << 2; -constexpr uint64_t FLAG_X = 1ULL << 3; -constexpr uint64_t FLAG_A = 1ULL << 6; -constexpr uint64_t FLAG_D = 1ULL << 7; - -int g_pass_count = 0; - -void check(bool cond, const char* name) { - if (cond) { - std::cout << "\033[32m[PASS] " << name << "\033[0m\n"; - ++g_pass_count; - } else { - std::cout << "\033[31m[FAIL] " << name << "\033[0m\n"; - assert(false); - } -} - -uint64_t make_satp(uint8_t mode, uint16_t asid, uint64_t ppn) { - return (uint64_t(mode) << 60) | (uint64_t(asid) << 44) | (ppn & ((1ULL << 44) - 1ULL)); -} - -uint64_t make_pte(uint64_t ppn, uint64_t flags) { - return ((ppn & ((1ULL << 44) - 1ULL)) << 10) | (flags & 0x3ffULL); -} - -void tick(Vmmu_top* dut) { - dut->clk = 0; - dut->eval(); - dut->clk = 1; - dut->eval(); -} - -void reset(Vmmu_top* dut) { - dut->rst = 1; - dut->i_req_valid = 0; - dut->d_req_valid = 0; - dut->d_req_is_store = 0; - dut->flush_all = 0; - dut->flush_asid_valid = 0; - dut->flush_asid = 0; - dut->flush_vpn_valid = 0; - dut->flush_vpn = 0; - dut->ptw_mem_req_ready = 1; - dut->ptw_mem_resp_valid = 0; - dut->ptw_mem_resp_data = 0; - tick(dut); - tick(dut); - dut->rst = 0; - tick(dut); -} - -struct StepResult { - bool issued; - uint64_t req_addr; - bool i_resp_valid; - bool i_resp_hit; - bool i_resp_page_fault; - uint64_t i_resp_paddr; - bool d_resp_valid; - bool d_resp_hit; - bool d_resp_page_fault; - uint64_t d_resp_paddr; -}; - -StepResult step(Vmmu_top* dut, bool inject_resp, uint64_t resp_data) { - dut->ptw_mem_req_ready = 1; - dut->ptw_mem_resp_valid = inject_resp ? 1 : 0; - dut->ptw_mem_resp_data = resp_data; - - dut->clk = 0; - dut->eval(); - const bool issued = dut->ptw_mem_req_valid && dut->ptw_mem_req_ready; - const uint64_t req_addr = dut->ptw_mem_req_addr; - StepResult result{ - issued, - req_addr, - bool(dut->i_resp_valid), - bool(dut->i_resp_hit), - bool(dut->i_resp_page_fault), - dut->i_resp_paddr, - bool(dut->d_resp_valid), - bool(dut->d_resp_hit), - bool(dut->d_resp_page_fault), - dut->d_resp_paddr, - }; - - dut->clk = 1; - dut->eval(); - - return result; -} - -void add_sv39_mapping( - std::unordered_map<uint64_t, uint64_t>& memory, - uint64_t root_ppn, - uint64_t vaddr, - uint64_t l1_ppn, - uint64_t l0_ppn, - uint64_t leaf_ppn, - uint64_t leaf_flags -) { - const uint64_t vpn2 = (vaddr >> 30) & 0x1ffULL; - const uint64_t vpn1 = (vaddr >> 21) & 0x1ffULL; - const uint64_t vpn0 = (vaddr >> 12) & 0x1ffULL; - memory[(root_ppn << 12) + (vpn2 << 3)] = make_pte(l1_ppn, FLAG_V); - memory[(l1_ppn << 12) + (vpn1 << 3)] = make_pte(l0_ppn, FLAG_V); - memory[(l0_ppn << 12) + (vpn0 << 3)] = make_pte(leaf_ppn, leaf_flags); -} - -StepResult run_until_response( - Vmmu_top* dut, - const std::unordered_map<uint64_t, uint64_t>& memory, - bool want_d -) { - bool inject_resp = false; - uint64_t next_resp = 0; - StepResult last{}; - - for (int cycle = 0; cycle < 100; ++cycle) { - last = step(dut, inject_resp, next_resp); - if ((!want_d && last.i_resp_valid) || (want_d && last.d_resp_valid)) { - return last; - } - - inject_resp = false; - next_resp = 0; - if (last.issued) { - const auto it = memory.find(last.req_addr); - next_resp = (it == memory.end()) ? 0 : it->second; - inject_resp = true; - } - } - - check(false, "MMU_ResponseTimeout"); - return last; -} - -} // namespace - -int main(int argc, char** argv) { - Verilated::commandArgs(argc, argv); - auto* dut = new Vmmu_top; - - std::cout << "----------------------------------\n"; - std::cout << " MMU Top Unit Test\n"; - std::cout << "----------------------------------\n"; - - dut->satp_value = make_satp(MODE_BARE, 0, 0); - dut->priv_mode = 1; - dut->sum = 0; - dut->mxr = 0; - reset(dut); - - dut->i_req_valid = 1; - dut->i_req_vaddr = 0x80001234ULL; - dut->d_req_valid = 1; - dut->d_req_vaddr = 0x90005678ULL; - dut->d_req_is_store = 0; - dut->eval(); - check(dut->i_resp_valid && dut->i_resp_hit && dut->i_resp_paddr == 0x80001234ULL, "Bare_I_Bypass"); - check(dut->d_resp_valid && dut->d_resp_hit && dut->d_resp_paddr == 0x90005678ULL, "Bare_D_Bypass"); - dut->i_req_valid = 0; - dut->d_req_valid = 0; - tick(dut); - - dut->satp_value = make_satp(MODE_SV48, 1, 0x100); - dut->i_req_valid = 1; - dut->i_req_vaddr = 0x0000000040401000ULL; - dut->eval(); - check(dut->i_resp_valid && dut->i_resp_page_fault, "Sv48_Stub_IFault"); - dut->i_req_valid = 0; - tick(dut); - - const uint64_t root_ppn = 0x100; - const uint64_t i_va = 0x0000000040401234ULL; - const uint64_t d_va = 0x0000000080505678ULL; - const uint64_t i_leaf_ppn = 0x45670; - const uint64_t d_leaf_ppn = 0x56780; - std::unordered_map<uint64_t, uint64_t> memory; - add_sv39_mapping(memory, root_ppn, i_va, 0x210, 0x220, i_leaf_ppn, - FLAG_V | FLAG_R | FLAG_X | FLAG_A); - add_sv39_mapping(memory, root_ppn, d_va, 0x230, 0x240, d_leaf_ppn, - FLAG_V | FLAG_R | FLAG_W | FLAG_A | FLAG_D); - - dut->satp_value = make_satp(MODE_SV39, 1, root_ppn); - dut->i_req_valid = 1; - dut->i_req_vaddr = i_va; - StepResult i_resp = run_until_response(dut, memory, false); - check(i_resp.i_resp_hit && !i_resp.i_resp_page_fault, "Sv39_I_Walk_Hit"); - check(i_resp.i_resp_paddr == ((i_leaf_ppn << 12) | (i_va & 0xfffULL)), "Sv39_I_Walk_Paddr"); - dut->i_req_valid = 0; - tick(dut); - - dut->d_req_valid = 1; - dut->d_req_vaddr = d_va; - dut->d_req_is_store = 1; - StepResult d_resp = run_until_response(dut, memory, true); - check(d_resp.d_resp_hit && !d_resp.d_resp_page_fault, "Sv39_D_Walk_Hit"); - check(d_resp.d_resp_paddr == ((d_leaf_ppn << 12) | (d_va & 0xfffULL)), "Sv39_D_Walk_Paddr"); - - dut->d_req_valid = 0; - tick(dut); - dut->i_req_valid = 1; - dut->i_req_vaddr = i_va; - dut->d_req_valid = 1; - dut->d_req_vaddr = d_va; - dut->d_req_is_store = 1; - dut->eval(); - check(dut->i_resp_valid && dut->i_resp_hit, "Sv39_I_TLB_Hit"); - check(dut->d_resp_valid && dut->d_resp_hit, "Sv39_D_TLB_Hit"); - check(dut->ptw_mem_req_valid == 0, "Sv39_TLB_Hit_NoPTW"); - - std::cout << "----------------------------------\n"; - std::cout << "All " << g_pass_count << " MMU top tests passed!\n"; - std::cout << "----------------------------------\n"; - - delete dut; - return 0; -} |
