自作CPUの実装、ロードストア命令の物理アドレスが決まらないうえでのハザードのボトルネックを解決した。 そうこうしているうちにいつの間にかRET命令のRAS予測が怪しくなってきているので修正しておきたい。
フロントエンドのパイプラインステージをs0, s1, ...
と表記すると、これまではBTBとBIMの参照をs0
で行い、その結果s1
でBTBの結果からそのまま分岐予測を実行していた。この方式は遅延なく分岐予測を実行できるのがメリットだが、RET
命令の検出は命令キャッシュから命令を取得するまで分からないので、RASがあまり活用されていない。
命令キャッシュからデータを取得するのはs2
ステージのため、s2
ステージからも分岐予測を実行してフェッチアドレスを更新できるように変更してみる。こうすることで、RET
命令は1サイクル遅れて分岐予測を行うので、性能的には他の分岐命令に比べて1サイクル遅れることになるが、完全にパイプラインフラッシュするよりかはマシなはずだ。
分岐命令のフロントエンドを以下のように変更して、s1
ステージ、s2
ステージのどちらからも分岐予測を適用可能にしてみる。
s2
ステージにおいてRET
命令のRASによる予測を行うと、自動的にその一つ先のs1
ステージはフラッシュする。
diff --git a/src/msrh_frontend.sv b/src/msrh_frontend.sv index 1b1e859..5583f37 100644 --- a/src/msrh_frontend.sv +++ b/src/msrh_frontend.sv @@ -86,6 +86,11 @@ logic r_s1_tlb_miss; logic r_s1_tlb_except_valid; msrh_pkg::except_t r_s1_tlb_except_cause; +logic [riscv_pkg::VADDR_W-1: 0] w_s1_btb_target_vaddr; + +logic w_s1_predict_valid; +logic [riscv_pkg::VADDR_W-1: 0] w_s1_predict_target_vaddr; + // ============== // s2 stage // ============== @@ -101,10 +106,8 @@ logic r_s2_tlb_miss; logic r_s2_tlb_except_valid; msrh_pkg::except_t r_s2_tlb_except_cause; -logic [riscv_pkg::VADDR_W-1: 0] w_s1_btb_target_vaddr; - -logic w_s1_predict_valid; -logic [riscv_pkg::VADDR_W-1: 0] w_s1_predict_target_vaddr; +logic w_s2_predict_valid; +logic [riscv_pkg::VADDR_W-1: 0] w_s2_predict_target_vaddr; // ======================= // Predictors @@ -310,6 +313,9 @@ always_comb begin w_s0_vaddr_next = {w_s2_ic_resp.vaddr, 1'b0}; w_if_state_next = WAIT_IBUF_FREE; end + end else if (w_s2_predict_valid) begin + w_s0_vaddr_next = (w_s2_predict_target_vaddr & ~((1 << $clog2(msrh_lsu_pkg::ICACHE_DATA_B_W))-1)) + + (1 << $clog2(msrh_lsu_pkg::ICACHE_DATA_B_W)); end else if (w_s1_predict_valid) begin w_s0_vaddr_next = (w_s1_predict_target_vaddr & ~((1 << $clog2(msrh_lsu_pkg::ICACHE_DATA_B_W))-1)) + (1 << $clog2(msrh_lsu_pkg::ICACHE_DATA_B_W)); @@ -596,6 +602,9 @@ assign w_s1_predict_valid = w_s1_inst_valid & assign w_s1_predict_target_vaddr = |w_ras_search_if.s1_is_ret ? {w_ras_search_if.s1_ras_vaddr, 1'b0} : w_s1_btb_target_vaddr; +assign w_s2_predict_valid = w_s2_inst_valid & (|w_ras_search_if.s2_is_ret); // from RAS +assign w_s2_predict_target_vaddr = {w_ras_search_if.s2_ras_vaddr, 1'b0}; + msrh_predictor u_predictor (