FPGA開発日記

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

自作CPUコアとBOOMv3のPPA(Performance, Power, Area)を比較する (3. BOOM側のトレースファイルの出力)

BOOMv3側の性能をKonataでチェックするために、BOOMのログからKanataのフォーマットを生成してみた。

まず、BOOMのログ生成部に以下のような変更を加えて、各命令におけるコミットのタイミングを出力する。 主にやっていることは、ログの生成と、ログの先頭にサイクル時間をつけ足していることだ。

diff --git a/src/main/scala/common/parameters.scala b/src/main/scala/common/parameters.scala
index 24e2beb4..3328f55e 100644
--- a/src/main/scala/common/parameters.scala
+++ b/src/main/scala/common/parameters.scala
@@ -98,9 +98,9 @@ case class BoomCoreParams(
   scontextWidth: Int = 0,
 
   /* debug stuff */
-  enableCommitLogPrintf: Boolean = false,
-  enableBranchPrintf: Boolean = false,
-  enableMemtracePrintf: Boolean = false
+  enableCommitLogPrintf: Boolean = true,
+  enableBranchPrintf: Boolean = true,
+  enableMemtracePrintf: Boolean = true
 
 // DOC include end: BOOM Parameters
 ) extends freechips.rocketchip.tile.CoreParams
diff --git a/src/main/scala/exu/core.scala b/src/main/scala/exu/core.scala
index b267c020..f777ec39 100644
--- a/src/main/scala/exu/core.scala
+++ b/src/main/scala/exu/core.scala
@@ -1332,20 +1332,23 @@ class BoomCore(usingTrace: Boolean)(implicit p: Parameters) extends BoomModule
   if (COMMIT_LOG_PRINTF) {
     var new_commit_cnt = 0.U
 
+    val time = csr.io.time
+
     for (w <- 0 until coreWidth) {
       val priv = RegNext(csr.io.status.prv) // erets change the privilege. Get the old one
 
       // To allow for diffs against spike :/
       def printf_inst(uop: MicroOp) = {
         when (uop.is_rvc) {
-          printf("(0x%x)", uop.debug_inst(15,0))
+          printf("DASM(0x%x)", uop.debug_inst(15,0))
         } .otherwise {
-          printf("(0x%x)", uop.debug_inst)
+          printf("DASM(0x%x)", uop.debug_inst)
         }
       }
 
       when (rob.io.commit.arch_valids(w)) {
-        printf("%d 0x%x ",
+        printf("%d %d 0x%x ",
+          time,
           priv,
           Sext(rob.io.commit.uops(w).debug_pc(vaddrBits-1,0), xLen))
         printf_inst(rob.io.commit.uops(w))

これで、以下のようなログが生成される。

                 860 3 0x0000000080003282 addi    a3, a4, 3 x13 0x0000000080006d6b
                 861 3 0x0000000080003286 sb      a5, 2(a4)
MT 000000000001955a 02 01 0 0080006d6a 0000000000000000 0000000000000000
                 862 3 0x000000008000328a bgeu    a3, a6, pc + 128
                 874 3 0x000000008000328e addi    a3, a4, 4 x13 0x0000000080006d6c
                 874 3 0x0000000080003292 sb      a5, 3(a4)
MT 0000000000019567 02 01 0 0080006d6b 0000000000000000 0000000000000000
                 875 3 0x0000000080003296 bgeu    a3, a6, pc + 116
                 878 3 0x000000008000330a ret
                 881 3 0x0000000080003394 c.mv    a0, s1 x10 0x0000000000000000
                 881 3 0x0000000080003396 c.mv    a1, s2 x11 0x0000000000000001
                 882 3 0x0000000080003398 jal     pc - 0x5ae x 1 0x000000008000339c
                 901 3 0x0000000080002dea c.beqz  a0, pc + 4
                 904 3 0x0000000080002dee ret
                 907 3 0x000000008000339c c.li    a1, 0 x11 0x0000000000000000
                 908 3 0x000000008000339e c.li    a0, 0 x10 0x0000000000000000
                 909 3 0x00000000800033a0 jal     pc + 0x132 x 1 0x00000000800033a4
                 927 3 0x00000000800034d2 c.addi16sp sp, -208 x 2 0x0000000080026b80
                 927 3 0x00000000800034d4 c.li    a1, 1 x11 0x0000000000000001
                 928 3 0x00000000800034d6 auipc   a5, 0x0 x15 0x00000000800034d6
                 934 3 0x00000000800034da addi    a5, a5, 1698 x15 0x0000000080003b78

これをさらに加工してKanataフォーマットに変換するコードは以下だ:

#!/bin/ruby

kanata_fp = File.open("kanata.boom.log", "w")

kanata_fp.write("Kanata\t0004\n")
kanata_fp.write("C\t0\n")

inst_idx = 0
cycle = 0

while str = STDIN.gets
  if str =~ /^ +(\d+) \d (0x\h+) ([\w\-\+., \(\)]+)$/ then
    now_cycle = $1.to_i
    pc = $2
    mnemonic = $3
  else
    puts (str)
    next
  end

  if inst_idx != 0 then
    kanata_fp.write("E\t" + (inst_idx-1).to_s + "\t0\tCMT\n")
    kanata_fp.write("R\t" + (inst_idx-1).to_s + "\t" + (inst_idx-1).to_s + "\t0\n")
  end

  kanata_fp.write("I\t" + inst_idx.to_s + "\t" + inst_idx.to_s + "\t0\n")
  kanata_fp.write("L\t" + inst_idx.to_s + "\t0\t" + pc +":"+ mnemonic + "\n")
  kanata_fp.write("S\t" + inst_idx.to_s + "\t0\tCMT\n")

  kanata_fp.write("C\t" + (now_cycle - cycle).to_s + "\n")

  inst_idx = inst_idx + 1
  cycle = now_cycle
end

このコードはイマイチで、同時に複数コミットが発生した命令を正確に表示することができないが、まあ傾向はつかめるだろうからそれで良しとする。

これにより、以下のようなビューワでの表示が可能となる。

ちなみに、自作CPU側はもう少し詳細なログを出すことができる。