SonicBOOMに関する調査 (5. BranchTagの構成 2) - FPGA開発日記

FPGA開発日記

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

SonicBOOMに関する調査 (5. BranchTagの構成 2)

BOOMのBranchTagについての解析の続き。分岐命令の予測が外れて、分岐がジャンプする方向に分岐が飛んだものとする。これがこの波形。

f:id:msyksphinz:20210609003611p:plain
f:id:msyksphinz:20210609003651p:plain

この部分のようだ。ずっとBEQでループを繰り返していたが、ループの終了で予測が外れている。

              121368 3 0x00000000800015ee sb      a0, 0(a5)
              121369 3 0x00000000800015f2 addi    a4, sp, 63 x14 0x0000000080024ccf
              121369 3 0x00000000800015f6 c.li    a5, 10 x15 0x000000000000000a
              121370 3 0x00000000800015f8 andi    a4, a4, -64 x14 0x0000000080024cc0
              // この命令の分岐予測が外れる
              121370 3 0x00000000800015fc beq     a0, a5, pc + 18
              // 160eへジャンプ
              121380 3 0x000000008000160e li      a5, 64 x15 0x0000000000000040
              121380 3 0x0000000080001612 c.sd    a5, 0(a4)
              121381 3 0x0000000080001614 c.li    a5, 1 x15 0x0000000000000001
              121381 3 0x0000000080001616 c.sd    a5, 8(a4)
              121382 3 0x0000000080001618 mv      a2, tp x12 0x0000000080005100
              121382 3 0x000000008000161c c.sd    a2, 16(a4)
              121383 3 0x000000008000161e c.sd    a3, 24(a4)
              121423 3 0x0000000080001620 fence
              121437 3 0x0000000080001624 auipc   a5, 0x0 x15 0x0000000080001624
              121442 3 0x0000000080001628 sd      a4, -1572(a5)
              121443 3 0x000000008000162c auipc   a3, 0x0 x13 0x000000008000162c
              121445 3 0x0000000080001630 addi    a3, a3, -1516 x13 0x0000000080001040

もう少し波形を追いかけてみると、命令キャッシュの格納されているフロントエンド側にリダイレクト用の信号が飛んでおり、これに基づいて命令キャッシュアドレスが変更されている。

f:id:msyksphinz:20210609003631p:plain

これを作り出しているのが以下のChiselの実装部分。mispredictで動くようになっている。

  • src/main/scala/exu/core.scala
  } .elsewhen (brupdate.b2.mispredict && !RegNext(rob.io.flush.valid)) {
    val block_pc = AlignPCToBoundary(io.ifu.get_pc(1).pc, icBlockBytes)
    val uop_maybe_pc = block_pc | brupdate.b2.uop.pc_lob
    val npc = uop_maybe_pc + Mux(brupdate.b2.uop.is_rvc || brupdate.b2.uop.edge_inst, 2.U, 4.U)
    val jal_br_target = Wire(UInt(vaddrBitsExtended.W))
    jal_br_target := (uop_maybe_pc.asSInt + brupdate.b2.target_offset +
      (Fill(vaddrBitsExtended-1, brupdate.b2.uop.edge_inst) << 1).asSInt).asUInt
    val bj_addr = Mux(brupdate.b2.cfi_type === CFI_JALR, brupdate.b2.jalr_target, jal_br_target)
    val mispredict_target = Mux(brupdate.b2.pc_sel === PC_PLUS4, npc, bj_addr)
    io.ifu.redirect_val     := true.B
    io.ifu.redirect_pc      := mispredict_target
    io.ifu.redirect_flush   := true.B
    io.ifu.redirect_ftq_idx := brupdate.b2.uop.ftq_idx
    val use_same_ghist = (brupdate.b2.cfi_type === CFI_BR &&