FPGA開発日記

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

SonicBOOMのデザインを読み解く (ロードストアのトレースログ)

ロードストアのトレースログについては、以下のオプションを変更してリコンパイルすることで出力されるようになるらしい。リコンパイルには例によってかなり時間がかかってしまうのだけれども。

  • src/main/scala/common/parameters.scala
diff --git a/src/main/scala/common/parameters.scala b/src/main/scala/common/parameters.scala
index 1a0c25fd..ca1d7edf 100644
--- a/src/main/scala/common/parameters.scala
+++ b/src/main/scala/common/parameters.scala
@@ -92,9 +92,9 @@ case class BoomCoreParams(
   clockGate: Boolean = false,

   /* debug stuff */
-  enableCommitLogPrintf: Boolean = false,
+  enableCommitLogPrintf: Boolean = true,
   enableBranchPrintf: Boolean = false,
-  enableMemtracePrintf: Boolean = false
+  enableMemtracePrintf: Boolean = true

 // DOC include end: BOOM Parameters
 ) extends freechips.rocketchip.tile.CoreParams

これで同じようにシミュレーションを行うと、以下のようにトレース情報に加えてメモリアクセスの情報が出力される。

                3425 3 0x00000000800031fa 0x034000ef jal     pc + 0x34 x 1 0x00000000800031fe
                3432 3 0x000000008000322e 0x00000517 auipc   a0, 0x0 x10 0x000000008000322e
                3436 3 0x0000000080003232 0x1d250513 addi    a0, a0, 466 x10 0x0000000080003400
                3438 3 0x0000000080003236 0x6108 c.ld    a0, 0(a0) x10 0xdeadbeef00000000
MT 0000000000003df6 01 00 3 0080003400 0000000000000000 deadbeef00000000
                3439 3 0x0000000080003238 0x8082 ret
                3441 3 0x00000000800031fe 0x87aa c.mv    a5, a0 x15 0xdeadbeef00000000
                3442 3 0x0000000080003200 0x85be c.mv    a1, a5 x11 0xdeadbeef00000000
                3442 3 0x0000000080003202 0x00000517 auipc   a0, 0x0 x10 0x0000000080003202
                3442 3 0x0000000080003206 0x1ee50513 addi    a0, a0, 494 x10 0x00000000800033f0
                3442 3 0x000000008000320a 0xaefff0ef jal     pc - 0x512 x 1 0x000000008000320e
                3443 3 0x0000000080002cf8 0x7159 c.addi16sp sp, -112 x 2 0x0000000080023300
                3443 3 0x0000000080002cfa 0xf406 c.sdsp  ra, 40(sp)
                3443 3 0x0000000080002cfc 0xf022 c.sdsp  s0, 32(sp)
                3443 3 0x0000000080002cfe 0x1800 c.addi4spn s0, sp, 48 x 8 0x0000000080023330
MT 0000000000003dfb 02 01 3 0080023328 000000008000320e 2a3549fad288d2d0
MT 0000000000003dfb 02 01 3 0080023320 0000000080023380 9b41f14b36cbd0ae
                3444 3 0x0000000080002d00 0xfca43c23 sd      a0, -40(s0)
MT 0000000000003dfc 02 01 3 0080023308 00000000800033f0 b0d68963f68c7912
                3445 3 0x0000000080002d04 0xe40c c.sd    a1, 8(s0)
                3445 3 0x0000000080002d06 0xe810 c.sd    a2, 16(s0)
                3445 3 0x0000000080002d08 0xec14 c.sd    a3, 24(s0)
                3445 3 0x0000000080002d0a 0xf018 c.sd    a4, 32(s0)
MT 0000000000003dfd 02 01 3 0080023338 deadbeef00000000 605e758e69ca86a0
MT 0000000000003dfd 02 01 3 0080023340 0000000080003480 24726ea7be9d2eb6
MT 0000000000003dfd 02 01 3 0080023348 0000000080023200 a85fb40e04d7f7e8
MT 0000000000003dfd 02 01 3 0080023350 0000000000000000 c29b4f52e59f9f04
                3446 3 0x0000000080002d0c 0xf41c c.sd    a5, 40(s0)
MT 0000000000003dfe 02 01 3 0080023358 deadbeef00000000 bfde1696b4cac50a
                3447 3 0x0000000080002d0e 0x03043823 sd      a6, 48(s0)
                3447 3 0x0000000080002d12 0x03143c23 sd      a7, 56(s0)

なるほど、最初のMTはMemTraceのことか、マニュアル運転のことかと思った。

  • src/main/scala/lsu/lsu.scala
    if (MEMTRACE_PRINTF) {
      when (commit_store || commit_load) {
        val uop    = Mux(commit_store, stq(idx).bits.uop, ldq(idx).bits.uop)
        val addr   = Mux(commit_store, stq(idx).bits.addr.bits, ldq(idx).bits.addr.bits)
        val stdata = Mux(commit_store, stq(idx).bits.data.bits, 0.U)
        val wbdata = Mux(commit_store, stq(idx).bits.debug_wb_data, ldq(idx).bits.debug_wb_data)
        printf("MT %x %x %x %x %x %x %x\n",
          io.core.tsc_reg, uop.uopc, uop.mem_cmd, uop.mem_size, addr, stdata, wbdata)
      }
    }

うーん、例えば以下のログについて考えてみると、

MT 0000000000003df6 01 00 3 0080003400 0000000000000000 deadbeef00000000
  • TSCカウンタ(これはtimeレジスタとは違い、ずっと動いているタイプのものらしい)
  • マイクロオペレーション
  • マイクロオペレーション内のメモリコマンド
  • メモリアクセスサイズ
  • アドレス
  • 書き込みデータ(読み込みと書き込みが両方表示されているようだが、たぶんアトミック操作のためかしら?)

が情報として並んでいるようだ。uopsは本当にコミットの情報をそのまま出しているのかな?uop内にはどのような情報が入っているのかというと、

  • src/main/scala/common/micro-op.scala
class MicroOp(implicit p: Parameters) extends BoomBundle
  with freechips.rocketchip.rocket.constants.MemoryOpConstants
  with freechips.rocketchip.rocket.constants.ScalarOpConstants
{
  val uopc             = UInt(UOPC_SZ.W)       // micro-op code
  val inst             = UInt(32.W)
  val debug_inst       = UInt(32.W)
  val is_rvc           = Bool()
  val debug_pc         = UInt(coreMaxAddrBits.W)
  val iq_type          = UInt(IQT_SZ.W)        // which issue unit do we use?
  val fu_code          = UInt(FUConstants.FUC_SZ.W) // which functional unit do we use?
  val ctrl             = new CtrlSignals

...

結構たくさん情報が入っている。これはちょっと簡単には追いかけられそうにないな。