SonicBOOMのCoreMark値はそれなりに高く、普通にパイプラインを組むだけではおよそ出すことのできないくらいの性能が出ている。これがどこから来ているのか解析したいという話があったので、少し見てみることにした。
ツールチェインのビルド
まずはChipyardを使ってSonicBOOMのシミュレーション環境を構築することにした。Chipyardの環境は1.4.0を使っている。
git clone git@github.com:ucb-bar/chipyard.git -b 1.4.0
ツールチェインは、少し最新版を使う必要がある。私の環境ではGCC7.2ベースの環境しかないので、Chipyardの環境を構築しておく。
./scripts/init-submodules-no-riscv-tools.sh
./scripts/build-toolchains.sh --ignore-qemu riscv-tools
これには結構な時間がかかる。一晩くらい待たないとダメだろう。また、QEMUは使わない割にビルドに時間がかかるので、--ignore-qemu
を設定した。
全てのビルドが完了すると、source ./env.sh
(このenv.sh
はツールチェインのビルドが完了すると自動的に作られる)を実行して環境を整える。
BOOMのビルド
BOOMのサイクル情報を取得したいので、以下の変更を施してログを取りやすくした。
以下の変更は、WithBoomCommitLogPrintf
を追加してBOOMの実行ログを生成する。
diff --git a/src/main/scala/common/config-mixins.scala b/src/main/scala/common/config-mixins.scala index fc20726c..8482bc5e 100644 --- a/src/main/scala/common/config-mixins.scala +++ b/src/main/scala/common/config-mixins.scala @@ -131,6 +131,7 @@ class WithNSmallBooms(n: Int = 1, overrideIdOffset: Option[Int] = None) extends */ class WithNMediumBooms(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config( new WithTAGELBPD ++ // Default to TAGE-L BPD + new WithBoomCommitLogPrintf ++ new Config((site, here, up) => { case TilesLocated(InSubsystem) => { val prev = up(TilesLocated(InSubsystem), site) @@ -178,6 +179,7 @@ class WithNMediumBooms(n: Int = 1, overrideIdOffset: Option[Int] = None) extends */ class WithNLargeBooms(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config( new WithTAGELBPD ++ // Default to TAGE-L BPD + new WithBoomCommitLogPrintf ++ new Config((site, here, up) => { case TilesLocated(InSubsystem) => { val prev = up(TilesLocated(InSubsystem), site)
さらに、以下のようにprintf()
を修正して、ログの解析をし易くする。CSR.time
を追加してサイクル情報を取得する。
diff --git a/src/main/scala/exu/core.scala b/src/main/scala/exu/core.scala index 579fce89..014b31d8 100644 --- a/src/main/scala/exu/core.scala +++ b/src/main/scala/exu/core.scala @@ -1334,14 +1334,15 @@ class BoomCore(usingTrace: Boolean)(implicit p: Parameters) extends BoomModule // 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 ", + csr.io.time, priv, Sext(rob.io.commit.uops(w).debug_pc(vaddrBits-1,0), xLen)) printf_inst(rob.io.commit.uops(w))
RISC-V Coremarkのビルド
RISC-V CoremarkはChipyardのsoftware/coremark
に格納されている。build.sh
を実行すれば自動的にビルドが行われるのだが、シミュレーション時間を短縮するためITERATIONS=10
に設定する。
diff --git a/build-coremark.sh b/build-coremark.sh index 2449d2d..8f77f98 100755 --- a/build-coremark.sh +++ b/build-coremark.sh @@ -9,8 +9,8 @@ cd $BASEDIR/$CM_FOLDER # run the compile echo "Start compilation" -make PORT_DIR=../riscv64 compile +make PORT_DIR=../riscv64 ITERATIONS=10 compile mv coremark.riscv ../ -make PORT_DIR=../riscv64-baremetal compile +make PORT_DIR=../riscv64-baremetal ITERATIONS=10 compile mv coremark.bare.riscv ../
cd software/coremark
./build.sh
BOOMのビルドとRISC-V CoremarkのRTLシミュレーション
まず、BOOMのビルドを行い、シミュレーションを実行する。
cd sims/verilator make CONFIG=MediumBoomConfig debug ./simulator-chipyard-MediumBoomConfig-debug --verbose ../../software/coremark/riscv-coremark/coremark.bare.riscv 2>&1 | tee coremark.medium.log
シミュレーションが完了すると、coremark.medium.log
が生成される。命令情報を除去すると、Coremarkの実行結果を見ることができる。
grep -v DASM coremark.medium.log
using random seed 1618643897 This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1. Listening on port 64406 2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 2605475 Total time (secs): %f Iterations/Sec : %f ERROR! Must execute for at least 10 secs for a valid result! Iterations : 10 Compiler version : GCC9.2.0 link.ld Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0xe9f5 [0]crclist : 0xe714 [0]crcmatrix : 0x1fd7 [0]crcstate : 0x8e3a [0]crcfinal : 0xfcaf Errors detected *** PASSED *** Completed after 2797178 cycles [UART] UART0 is here (stdin/stdout).
2,605,475サイクルなので、CMK/MHz的には3.83CMK/MHzだな。まあ、論文の値に近い。
命令数を取得する。start_time
からstop_time
までの値を取得すれば良かろう。
0000000080002218 <start_time>: 80002218: c00027f3 rdcycle a5 8000221c: 00001717 auipc a4,0x1 80002220: 64f73a23 sd a5,1620(a4) # 80003870 <start_time_val> 80002224: 8082 ret 0000000080002226 <stop_time>: 80002226: c00027f3 rdcycle a5 8000222a: 00001717 auipc a4,0x1 8000222e: 62f73f23 sd a5,1598(a4) # 80003868 <stop_time_val> 80002232: 8082 ret
grep -n -e 80002218 -e 80002226 coremark.medium.log
13705: 10976 3 0x0000000080002218 DASM(0xc00027f3) x15 0x0000000000002adf 3689644: 2616451 3 0x0000000080002226 DASM(0xc00027f3) x15 0x000000000027ec82
3,689,644 - 13,705 = 3,675,939 命令となっている。2,605,475 サイクルなので、IPCは1.410となっている。
全体的なIPCを観察する
Coremark全体のログから、1000命令毎にサイクル数を抽出してIPCを算出する。
IPCの高い所だと最大の2.0に近いところまで来ている。最初の方に注目すると、matrix_mul_matrix()
のあたりがIPC=2に近いようだ。
確かに、この辺は殆どストールなく2命令を同時に完了することができているようだ。
48494 3 0x000000008000189a c.beqz a0, pc + 102 48513 3 0x000000008000189c c.li t4, 0 x29 0x0000000000000000 48514 3 0x000000008000189e addw t3, t4, t5 x28 0x0000000000000000 48515 3 0x00000000800018a2 c.slli t3, 32 x28 0x0000000000000000 48516 3 0x00000000800018a4 srli t3, t3, 30 x28 0x0000000000000000 48517 3 0x00000000800018a8 c.add t3, t6 x28 0x0000000080003c68 48517 3 0x00000000800018aa c.mv a2, t4 x12 0x0000000000000000 48518 3 0x00000000800018ac c.mv a3, t5 x13 0x0000000000000000 48518 3 0x00000000800018ae c.li a1, 0 x11 0x0000000000000000 48519 3 0x00000000800018b0 slli a4, a3, 32 x14 0x0000000000000000 48519 3 0x00000000800018b4 slli a5, a2, 32 x15 0x0000000000000000 48520 3 0x00000000800018b8 c.srli a4, 32 x14 0x0000000000000000 48520 3 0x00000000800018ba c.srli a5, 32 x15 0x0000000000000000 48521 3 0x00000000800018bc c.slli a4, 1 x14 0x0000000000000000 48521 3 0x00000000800018be c.slli a5, 1 x15 0x0000000000000000 48534 3 0x00000000800018c0 c.add a4, t1 x14 0x0000000080003b24 48534 3 0x00000000800018c2 c.add a5, a7 x15 0x0000000080003bc6 48535 3 0x00000000800018c4 lh a4, 0(a4) x14 0x0000000000000014 48535 3 0x00000000800018c8 lh a5, 0(a5) x15 0x0000000000000002 48536 3 0x00000000800018cc c.addiw a3, 1 x13 0x0000000000000001 48536 3 0x00000000800018ce c.addw a2, a0 x12 0x0000000000000009 48540 3 0x00000000800018d0 mulw a5, a4, a5 x15 0x0000000000000028 48546 3 0x00000000800018d4 c.addw a1, a5 x11 0x0000000000000028 48547 3 0x00000000800018d6 bne a6, a3, pc - 38 48548 3 0x00000000800018b0 slli a4, a3, 32 x14 0x0000000100000000 48549 3 0x00000000800018b4 slli a5, a2, 32 x15 0x0000000900000000 48549 3 0x00000000800018b8 c.srli a4, 32 x14 0x0000000000000001 48550 3 0x00000000800018ba c.srli a5, 32 x15 0x0000000000000009 48550 3 0x00000000800018bc c.slli a4, 1 x14 0x0000000000000002 48551 3 0x00000000800018be c.slli a5, 1 x15 0x0000000000000012 48551 3 0x00000000800018c0 c.add a4, t1 x14 0x0000000080003b26 48552 3 0x00000000800018c2 c.add a5, a7 x15 0x0000000080003bd8 48552 3 0x00000000800018c4 lh a4, 0(a4) x14 0x0000000000000017 48553 3 0x00000000800018c8 lh a5, 0(a5) x15 0x0000000000005f0a 48553 3 0x00000000800018cc c.addiw a3, 1 x13 0x0000000000000002 48554 3 0x00000000800018ce c.addw a2, a0 x12 0x0000000000000012 48554 3 0x00000000800018d0 mulw a5, a4, a5 x15 0x00000000000889e6