自作RISC-V CPUの検証をするため、SpikeのMMUを使うことを考える。どうしてもTLB周りとか、VA→PAの検証はデバッグが難しい。 ハードウェアが勝手にPage Table Walkして、万が一L1Dキャッシュにデータを書き損じていた場合、波形を一生懸命眺めないと検証できない。
まずは、基本的にTLBの出力結果がISSとあっていなければどうしようもない。この部分のインタフェースを検証するためのDPIを追加することにした。
SpikeのMMUの実装は以下になっている。
本当はこのtranslate()
を使用すればいいのだが、private
なので簡単には使えない。とりあえずpublic
に移動して使ってみることにする。
reg_t translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_flags);
ハードウェア側の実装で、VA→PA変換を行ったときにDPI-Cを呼び出してSpike側のインタフェースを起動するようにしてみる。
reg_t iss_paddr = mmu->translate(rtl_va, rtl_len, static_cast<access_type>(rtl_acc_type), 0);
で変換ルーチンを呼び出す。
ちなみに、try - catch
を実装しておかないと、Spikeの実装は変換に失敗すると例外を飛ばしてしまうのでしっかりキャッチしておかなければならない。
`ifdef SIMULATION import "DPI-C" function void check_mmu_trans ( input longint rtl_time, input longint rtl_va, input int rtl_len, input int rtl_acc_type, input longint rtl_pa ); always_ff @ (negedge i_clk, negedge i_reset_n) begin if (i_reset_n) begin if (i_tlb_req.valid & !w_tlb_miss) begin check_mmu_trans ($time, i_tlb_req.vaddr, i_tlb_req.size, i_tlb_req.cmd, o_tlb_resp.paddr); end end end `endif // SIMULATION
C++側の実装は以下のようになった。
void check_mmu_trans (long long time, long long rtl_va, int rtl_len, int rtl_acc_type, long long rtl_pa) { processor_t *p = spike_core->get_core(0); spike_core->set_procs_debug(true); mmu_t *mmu = p->get_mmu(); access_type acc_type; switch (rtl_acc_type) { case 0 : acc_type = LOAD; break; case 1 : acc_type = STORE; break; default : fprintf (stderr, "rtl_acc_type = %d is not supported\n", rtl_acc_type); stop_sim(1); } try { reg_t iss_paddr = mmu->translate(rtl_va, rtl_len, static_cast<access_type>(rtl_acc_type), 0); if (iss_paddr != rtl_pa) { char spike_out_str[256]; sprintf (spike_out_str, "Error : PA->VA different.\nRTL = %08x, ISS=%08x", rtl_pa, iss_paddr); fprintf (compare_log_fp, spike_out_str); fprintf (stderr, spike_out_str); stop_sim(101); } else { // fprintf (compare_log_fp, "MMU check passed : VA = %08x, PA = %08x\n", rtl_va, rtl_pa); } } catch (trap_t &t) { // fprintf (compare_log_fp, "Catch exception at check_mmu_trans : VA = %08x, PA = %08x\n", rtl_va, rtl_pa); } spike_core->set_procs_debug(false); }
とりあえずここまでで変換ルーチンで、検証できるようになったことは確認した。
ただし、このアサーションをつけてもまだテストパタンのFailを検出することができない。もう少しチェックが必要だ。