FPGA開発日記

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

BOOM RISC-V実装RTLにてベンチマークを計測する

この記事は ハードウェア開発、CPUアーキテクチャ Advent Calendar 2016 - Qiita の16日目の記事です。

Advent-Calendarを埋めてくれるかた、今からでも募集中です!是非参加してください! 僕一人では、クオリティのある記事を続けられそうにありません。。。(弱音)

14日目の記事で、RocketChipを使ったCoremarkの計測を行った。今回は、RISC-VのOut-of-OrderコアであるBOOMを使って、同様の実験をしてみよう。

1. BOOMのコンパイル方法

BOOMのダウンロードおよびコンパイル方法は、Rocketのそれと殆ど同じだ。基本的には以下のリポジトリをダウンロードして、書いてあるとおりにコマンドを叩けば良い。

github.com

毎回riscv-toolsとかコンパイルするのはかなり面倒なので、おそらくriscv-toolsのコンパイルは一度実行しておけば省略できるはずだ。Rocketでコンパイルしていればもう一度再コンパイルする必要もない。 ただし、ブランチをboomに切り替えるので、サブモジュールのアップデートを忘れないこと。

2. Verilatorを使ったBOOMプロセッサのシミュレーション

emulatorディレクトリに移動して、BOOMのコンフィグレーションでコンパイルする。デフォルトだと2-wayのBOOMプロセッサが生成されるようだ。

デフォルトでは、シミュレーションを実行してもトレースログが表示されないので、boom/src/main/scala/consts.scalaを編集して、トレースファイルが生成されるようにしておく。

val O3PIPEVIEW_PRINTF = true  // dump trace for O3PipeView from gem5

次に、BOOMのプロセッサを生成する。

cd emulator
make run CONFIG=BOOMConfig

ちなみに、上記のようにmake runを実行してしまうとリグレッションテストが走りだして、いろんなパタンを実行し始めて時間がかかるので、とりあえずCtrl+Cで止めて、coremarkだけ実行したい。

emulator/output ディレクトリに、前回生成したCoremarkバイナリを置いてシミュレーションを実行しよう。

make output/coremark.riscv.out

前回と同じで、ITERATIONS=5バイナリを実行した。また、シミュレーション時間を短縮するために、Makefragを調整した。

diff --git a/Makefrag b/Makefrag
index a70bd10..5ee00c2 100644
--- a/Makefrag
+++ b/Makefrag
@@ -38,7 +38,8 @@ ifneq ($(which_disasm),)
        disasm := 3>&1 1>&2 2>&3 | $(which_disasm) $(DISASM_EXTENSION) >
 endif

-timeout_cycles = 100000000
+# timeout_cycles = 100000000
+timeout_cycles = 5000000

2-way BOOMプロセッサでのCoremark測定結果

測定結果だが、BOOMはO3トレース形式でログを表示するようになっている。とりあえずgrepstart_time(), stop_time()が実行されたサイクル数を特定しよう。

$ grep -e  80002a1c -e 0080002a28 output/coremark.riscv.out
    116241; O3PipeView:fetch:           274339000:0x0080002a1c:0:    116241:DASM(00003797)
    116244; O3PipeView:fetch:           274341000:0x0080002a28:0:    116244:DASM(00003797)
    117703; O3PipeView:fetch:           275971000:0x0080002a28:0:    117703:DASM(00003797)
    120380; O3PipeView:fetch:           278512000:0x0080002a28:0:    120380:DASM(00003797)
    121167; O3PipeView:fetch:           279214000:0x0080002a28:0:    121167:DASM(00003797)
   2179329; O3PipeView:fetch:          1709189000:0x0080002a28:0:   2179329:DASM(00003797)
   2182670; O3PipeView:fetch:          1712010000:0x0080002a28:0:   2182670:DASM(00003797)

だいたいこのあたりだ。アバウトにCoremarkスコアを計算する。

{ \displaystyle
\text{CMK/MHz} = 1000000 / \left(2182670- 121167\right) = 2.43
}

あれ?カタログスペックと随分違うなあ。カタログ値では3.91なんだが...

3. -O3オプションでコンパイルしたCoremarkをBOOMで実行する

という訳で、-O3オプションでCoremarkをコンパイルし直して実行してみた。ってか、BOOMの資料を読むとちゃんとgcc -O3って書いてあったな。。。失敗。

RocketChip/BOOMでの実行結果

コンパイルしたバイナリをRocketChip/BOOMで実行してみると、RocketChipは途中で例外を吐いてしまい、BOOMはエラーを吐いて止まってしまった。 どちらともストア命令の実行時に問題があったようだ。メモリ領域不足か、Misalignか。。。ちょっと解析するのは時間切れ。

  • Rocketの場合
C                   0:     555692 [1] pc=[0080005e20] W[r 1=0000000080005e24][1] R[r31=0000000000000003] R[r21=0000000080007e83] inst=[fd5ff0ef] jal     pc - 0x2c
C                   0:     555693 [1] pc=[0080005df4] W[r 2=0000000080002030][1] R[r 2=0000000080002040] R[r16=0000000080007e83] inst=[ff010113] addi    sp, sp, -16
C                   0:     555694 [1] pc=[0080005df8] W[r15=0000000080007ec4][1] R[r10=0000000080007e80] R[r12=0000000000000044] inst=[00c567b3] or      a5, a0, a2
C                   0:     555731 [1] pc=[0000000800] W[r 0=0000000000000804][1] R[r 0=0000000000000000] R[r28=0000000080005e27] inst=[03c0006f] j       pc + 0x3c
C                   0:     555732 [1] pc=[000000083c] W[r 0=0000000080007e80][1] R[r 8=0000000080007e80] R[r18=0000000080005e27] inst=[7b241073] csrw    dscratch, s0
C                   0:     555765 [1] pc=[0000000840] W[r 8=00000000400000e3][1] R[r 0=0000000000000000] R[r16=0000000080005e27] inst=[7b002473] csrr    s0, dcsr
C                   0:     555768 [1] pc=[0000000844] W[r 8=00000000000000c0][1] R[r 8=00000000400000e3] R[r 0=0000000000000000] inst=[1c047413] andi    s0, s0, 448
C                   0:     555769 [1] pc=[0000000848] W[r 8=0000000000000000][1] R[r 8=00000000000000c0] R[r 0=0000000000000000] inst=[f4040413] addi    s0, s0, -192
C                   0:     555770 [1] pc=[000000084c] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[00041663] bnez    s0, pc + 12
C                   0:     555771 [1] pc=[0000000850] W[r 0=0000000000000438][0] R[r 0=0000000000000000] R[r 9=0000000000000000] inst=[42903c23] sd      s1, 1080(zero)
C                   0:     555772 [1] pc=[0000000854] W[r 0=0000000000000858][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[40000067] jalr    zero, zero, 1024
C                   0:     555803 [1] pc=[0000000400] W[r 8=0000000000000410][1] R[r 0=0000000000000000] R[r16=0000000000000003] inst=[41003403] ld      s0, 1040(zero)
  • BOOMの場合
$ make output/coremark.riscv.o3.out
./emulator-rocketchip-BOOMConfig +max-cycles=5000000 +verbose output/coremark.riscv.o3 2> output/coremark.riscv.o3.out && [ $PIPESTATUS -eq 0 ]
[462578] %Error: rocketchip.BOOMConfig.v:764442: Assertion failed in TOP.TestHarness.ExampleTop_1.coreplex.legacy
%Error: /home/vagrant/rocket-chip/emulator/generated-src/rocketchip.BOOMConfig.v:764442: Verilog $stop
Aborting...

4. 終わりに

ちょっと中途半端になってしまったが、BOOMでCoremarkベンチマークを測定する方法について紹介した。

もうちょっとBOOMの論文の再現性を上げるために、UC Berkeleyには是非コンパイル済のCoremarkバイナリを公開して欲しいところだ。そうすると、僕も自作CPUで検証がやりやすい(笑)。