自作CPUのデバッグをチマチマ進めている。 現在、1つのVerilogファイルから10個程度のコンフィグレーションを生成するようにしてリグレッションを走らせている。 TLBの挙動がおかしくなってしまったので、いろいろ見ているのだが、どうもVerilatorの問題を踏んでしまっているような気がしている。
struct
で定義した入出力ポートに対してTLBの探索結果を返しているのだが、以下の.miss
がどう頑張っても所望の動作をしてくれない。
念のため無料版のModelSimで走らせても挙動が違うため、どうもVerilatorのバグを踏んでいるような気がする?
// ------------------ // Response of TLB // ------------------ assign o_tlb_resp.pf.ld = (w_bad_va && w_cmd_read) || (|(w_pf_ld_array & w_is_hit)); assign o_tlb_resp.pf.st = (w_bad_va && w_cmd_write_perms) || (|(w_pf_st_array & w_is_hit)); assign o_tlb_resp.pf.inst = w_bad_va || (|(w_pf_inst_array & w_is_hit)); assign o_tlb_resp.ae.ld = |(w_ae_ld_array & w_is_hit); assign o_tlb_resp.ae.st = |(w_ae_st_array & w_is_hit); assign o_tlb_resp.ae.inst = |(~w_px_array & w_is_hit); assign o_tlb_resp.ma.ld = |(w_ma_ld_array & w_is_hit); assign o_tlb_resp.ma.st = |(w_ma_st_array & w_is_hit); assign o_tlb_resp.ma.inst = 1'b0; // this is up to the pipeline to figure out assign o_tlb_resp.cacheable = |(w_c_array & w_is_hit); assign o_tlb_resp.must_alloc = |(w_must_alloc_array & w_is_hit); // && edge.manager.managers.forall(m => !m.supportsAcquireB || m.supportsHint).B; assign o_tlb_resp.prefetchable = |(w_prefetchable_array & w_is_hit); logic w_tlb_resp_miss; assign w_tlb_resp_miss = w_do_refill | w_tlb_miss; assign o_tlb_resp.miss = w_tlb_resp_miss; /* || multiplehits */; assign o_tlb_resp.paddr = {w_ppn, i_tlb_req.vaddr[11: 0]};
ちなみにこういうstruct
の記述はVerilatorによって以下のようなC++に変換されているようだ。
正気ですか?みたいなコードが出てきた。これ、どうやってデバッグしろって言うんだ...
もう少し問題を簡潔にして絞り込んでいくしかないような気がしている。
vlSelf->o_tlb_resp = (((QData)((IData)((((((((IData)( (0U != (((IData)(vlSelf->__PVT__w_cmd_read) ? (~ ((IData)(vlSelf->__PVT__w_r_array) | (IData)(vlSelf->__PVT__w_ptw_ae_array))) : 0U) & (IData)(vlSelf->__PVT__w_is_hit)))) << 1U) | (0U != (((IData)(vlSelf->__PVT__w_cmd_write_perms) ? (~ ((IData)(vlSelf->__PVT__w_w_array) | (IData)(vlSelf->__PVT__w_ptw_ae_array))) : 0U) & (IData)(vlSelf->__PVT__w_is_hit)))) << 0xaU) | ((((IData)( (0U != ((~ ((IData)(vlSelf->__PVT__w_x_array) | (IData)(vlSelf->__PVT__w_ptw_ae_array))) & (IData)(vlSelf->__PVT__w_is_hit)))) << 3U) | (((IData)( (0U != (((IData)(vlSelf->__PVT__w_cmd_read) ? ((IData)(__PVT__w_ae_array) | (~ (IData)(vlSelf->__PVT__w_pr_array))) : 0U) & (IData)(vlSelf->__PVT__w_is_hit)))) << 2U) | (((IData)( (0U != (((((IData)(vlSelf->__PVT__w_cmd_write_perms)