FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-VのBOOMv3の分岐予測についてドキュメントとソースコードを読む2

BOOMv3のフロントエンド、特に分岐予測の部分についてちょっと実装を確認したくなった。 以下ドキュメントとソースコードを読んだ時のメモ。続き。

docs.boom-core.org


RASのアップデートのタイミング

読み込みのタイミング。f3のタイミングでRASを読んでいる。それと同時にras_read_idxレジスタのアップデートを行っている。

ポイントとなるのは、Global History TableからRASのインデックスを引いてきている、ということか?

   // RAS takes a cycle to read
   val ras_read_idx = RegInit(0.U(log2Ceil(nRasEntries).W))
   ras.io.read_idx := ras_read_idx
   when (f3.io.enq.fire()) {
     ras_read_idx := f3.io.enq.bits.ghist.ras_idx
     ras.io.read_idx := f3.io.enq.bits.ghist.ras_idx
   }

おや、同じサイクルでRASを読み込んでいるようだ。ret命令の場合はRASの値ras.io.read_addrを使用している。

   f3_fetch_bundle.ras_top := ras.io.read_addr
   // Redirect earlier stages only if the later stage
   // can consume this packet

   val f3_predicted_target = Mux(f3_redirects.reduce(_||_),
     Mux(f3_fetch_bundle.cfi_is_ret && useBPD.B && useRAS.B,
       ras.io.read_addr,
       f3_targs(PriorityEncoder(f3_redirects))
     ),
     nextFetch(f3_fetch_bundle.pc)
   )

次に書き込みのタイミングだが、f3のBTB Response Queueを抜けた時点ですぐに書き込むようだ。

   ras.io.write_valid := false.B
   ras.io.write_addr  := f3_aligned_pc + (f3_fetch_bundle.cfi_idx.bits << 1) + Mux(
     f3_fetch_bundle.cfi_npc_plus4, 4.U, 2.U)
   ras.io.write_idx   := WrapInc(f3_fetch_bundle.ghist.ras_idx, nRasEntries)
   /* 途中省略 */
   when (f3.io.deq.valid && f4_ready) {
     when (f3_fetch_bundle.cfi_is_call && f3_fetch_bundle.cfi_idx.valid) {
       ras.io.write_valid := true.B
     }

一方で、FTQを通じてバックエンドからも更新通知がやってくる。

when (ftq.io.ras_update && enableRasTopRepair.B) {
     ras.io.write_valid := true.B
     ras.io.write_idx   := ftq.io.ras_update_idx
     ras.io.write_addr  := ftq.io.ras_update_pc
   }