FireSimの環境で、どうにかRocketシングルコアを動かすことができた。ここまでできれば、今度は様々なハードウェアをf1インスタンスで動かしてみたい。RocketはChiselというハードウェア記述言語で設計されているが、ChiselでオリジナルのモジュールをRocketに追加して、オリジナルのRocketコアを作れば、f1インスタンス上で動作させることができると思う。
FireSimのコアデザイン"Firechip"
FireSimは、RISC-Vコアを動作させるための環境そのものを指す。FireSimのリポジトリにはChiselで記述されたいくつかのデザインは入っているが、コアそのものではなく、周辺IPだったり、SoCを構成するための部品がメインになる。一方で、シミュレーションするコア自体は別のリポジトリで管理されている。それが"firechip"というリポジトリになる。
FireSimのリポジトリのサブリポジトリとして、"firechip"リポジトリが配置されている。
firesim ├── deploy ├── docs ├── platforms │ └── f1 ├── riscv-tools-install ├── scripts ├── sim ├── sw ├── target-design │ ├── firechip │ └── switch
このfirechipリポジトリは、Rocket-Chipのリポジトリと同様、単体でRTLシミュレーションを行うことができる。また、Rocket-Chipと同様、カスタマイズも可能だ。
cd firesim cd target-design/firechip/verisim # Verilatorを使う。VCSを使う場合はtarget-design/firechip/vsim make clean && make run-regression-tests
つまり、FireChipを改造すればAWS f1インスタンス上でFireSimを使い、オリジナルに改造したRISC-Vコアを走らせることができる。どのように進めればよいか見ていく。
FireChipにカスタマイズアクセレレータを実装する
さて、実装方針が決まったので、FireChipに行列積アクセラレータを実装する。あらかじめ、今回はGitHubに公開されているfirechipのリポジトリをforkし、msyksphinz/firechip.git
で作業を行う。FireChipリポジトリをcloneし、セットアップを行う。この作業はAWSインスタンス上で行う必要はなく、ローカルマシンで実行しても問題ない。
git clone https://github.com/msyksphinz/firechip.git cd firechip git submodule update --init cd rocket-chip git submodule update --init cd ..
行列アクセラレータを実装するために、以下のファイルを作成・修正する。
src/main/scala/example/Configs.scala src/main/scala/example/MatrixMul.scala
src/main/scala/example/Configs.scala
class RoccMatrixMulConfig extends Config( new WithRoccMatrixMul ++ new DefaultExampleConfig)
src/main/scala/example/MatrixMul.scala
class MatrixMul(opcodes: OpcodeSet, val n: Int = 4)(implicit p: Parameters) extends LazyRoCC(opcodes) { override lazy val module = new MatrixMulModuleImp(this) } class MatrixMulModuleImp(outer: MatrixMul, n: Int = 4)(implicit p: Parameters) extends LazyRoCCModuleImp(outer) with HasCoreParameters { ...
コンフィグレーションはRoccMatrixMulConfig
を指定した。Verilog生成時に、CONFIG
オプションでRoccMatrixMulConfig
を指定すると、所望のVerilogが生成される。
cd firechip/verisim make CONFIG=RoccMatrixMulConfig
そして、上記で示したテストプログラムを実行する。プログラムは自前でコンパイルしても良いだが、firechip/tests
に配置してMakefileを追加すると自動的にコンパイルしてくれる。
diff --git a/tests/Makefile b/tests/Makefile index a199743..1102ecf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,7 +3,7 @@ OBJDUMP=riscv64-unknown-elf-objdump CFLAGS=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall LDFLAGS=-static -nostdlib -nostartfiles -lgcc -PROGRAMS = pwm blkdev accum charcount nic-loopback pingd big-blkdev input-stream +PROGRAMS = pwm blkdev accum charcount nic-loopback pingd big-blkdev input-stream matrixmul default: $(addsuffix .riscv,$(PROGRAMS))
RTLシミュレーションを実行する。SW実行と比べて、ハードウェアアクセラレータを付加した場合にどれくらい高速化されるか検証した。
make CONFIG=FireSimRocketChipMatrixMulConfig
./simulator-example-RoccMatrixMulConfig ../tests/matrixmul.riscv
シミュレーションで正しく実行されることを確認した。
SW HW ---------------------------------- 2 x 2 x 2 : 278 152 4 x 4 x 4 : 1238 521 8 x 8 x 8 : 9185 2691 16 x16 x16 : 70288 17621 18 x24 x28 : 209390 47615