FireSimの環境で、どうにかRocketシングルコアを動かすことができた。ここまでできれば、今度は様々なハードウェアをf1インスタンスで動かしてみたい。RocketはChiselというハードウェア記述言語で設計されているが、ChiselでオリジナルのモジュールをRocketに追加して、オリジナルのRocketコアを作れば、f1インスタンス上で動作させることができると思う。
前回までのFireChipのシミュレーションは、いわゆるコアの単体でソフトウェアとハードウェアの動作を確認した。今度は、AWS f1インスタンス上で動作させるために、FireChipのデザインをFireSimに乗せる必要がある。
イメージとしては、FireSimがf1インスタンスを含むFPGAイメージ+SoCと考えればよい。SoCの中にFireChipが入っており、1部品としてFireSimに埋め込む。
このためには、FireSimのデザインに、FireChipのデザインを認識させなければならない。
FireSimリポジトリにはtarget-design/firechip
としてサブリポジトリが配置されている。このfirechipリポジトリはUCBのfirechipプロジェクト公式(https://github.com/firesim/firechip)のものだ。しかしこのリポジトリをforkしてオリジナルのfirechipリポジトリを作っていた。まずはこのリポジトリをtarget-design
のディレクトリに配置しなければならない。
cd target-design git submodule add https://github.com/msyksphinz/firechip -b memory-mapped-io firechip-msyksphinz
以下のようなディレクトリ構成になる。
$ tree -L 1 target-design target-design ├── firechip ├── firechip-msyksphinz └── switch
では次にFireSimリポジトリ内で新しいコンフィグレーションを作成する。コンフィグレーションというのは、ターゲットのハードウェアの構成などを示したChiselで書かれたクラスだ。あるコンフィグレーションを指定するとコアが1つ、あるいは別のコンフィグレーションを指定するとキャッシュサイズを変えることができる、など、1つのリポジトリの中に複数のコンフィグレーションを定義することができ、Verilogの生成や論理合成時にどのターゲットを使用するか指定する。
今回はFireSimのリポジトリに以下のソースファイルを追加した。
sim/src/main/scala/firesim/TargetConfigs.scala
diff --git a/sim/src/main/scala/firesim/TargetConfigs.scala b/sim/src/main/scala/firesim/TargetConfigs.scala index d18574f..7bccd4f 100644 --- a/sim/src/main/scala/firesim/TargetConfigs.scala +++ b/sim/src/main/scala/firesim/TargetConfigs.scala @@ -9,6 +9,7 @@ import boom.system.BoomTilesKey import testchipip.{WithBlockDevice, BlockDeviceKey, BlockDeviceConfig} import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} import icenet._ +import example._ class WithBootROM extends Config((site, here, up) => { case BootROMParams => BootROMParams( @@ -90,6 +91,20 @@ class FireSimRocketChipConfig extends Config( new WithPerfCounters ++ new freechips.rocketchip.system.DefaultConfig) + +class FireSimMatrixMulConfig extends Config( + new WithBootROM ++ + new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ + new WithExtMemSize(0x400000000L) ++ // 16GB + new WithoutTLMonitors ++ + new WithUARTKey ++ + new WithNICKey ++ + new WithBlockDevice ++ + new WithRocketL2TLBs(1024) ++ + new WithPerfCounters ++ + new example.RoccMatrixMulConfig) + + class WithNDuplicatedRocketCores(n: Int) extends Config((site, here, up) => { case RocketTilesKey => List.tabulate(n)(i => up(RocketTilesKey).head.copy(hartId = i)) }) @@ -100,6 +115,9 @@ class FireSimRocketChipTracedConfig extends Config( // single core config class FireSimRocketChipSingleCoreConfig extends Config(new FireSimRocketChipConfig) +// single core config +class FireSimRocketChipMatrixMulConfig extends Config(new FireSimMatrixMulConfig) +
一番大元になるコンフィグレーション名はFireSimRocketChipMatrixMulConfig
だ。このクラスはFireSimMatrixMulConfig
を呼び出しており、これはexample.RoccMatrixMulConfig
と各種デバイスやバスを定義している。RoccMatrixMulConfig
はFireChipで定義したコンフィグレーションなので、このFireSimRocketChipMatrixMulConfig
のVerilogを生成すればアクセラレータ付きのFireSimデザインを生成することができる。
まだもう少しやることがある。先ほどサブモジュールとしてチェックアウトしたfiresim-msyksphinz
を、Chiselが参照するようにディレクトリを指定しなければならない。Chiselのソースコードの管理や、プロジェクトの管理はsim/build.sbt
で管理する。
sim.build.sbt
diff --git a/sim/build.sbt b/sim/build.sbt index daae7dc..fda246f 100644 --- a/sim/build.sbt +++ b/sim/build.sbt @@ -21,8 +21,8 @@ def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test => testGrouping in Test := isolateAllTests( (definedTests in Test).value ) -val rocketChipDir = file("target-rtl/firechip/rocket-chip") -val fireChipDir = file("target-rtl/firechip") +val rocketChipDir = file("target-rtl/firechip-msyksphinz/rocket-chip") +val fireChipDir = file("target-rtl/firechip-msyksphinz") // Subproject definitions begin // NB: FIRRTL dependency is unmanaged (and dropped in sim/lib) @@ -67,6 +67,10 @@ lazy val icenet = (project in fireChipDir / "icenet") .settings(commonSettings) .dependsOn(rocketchip, testchipip) +lazy val example = (project in fireChipDir / "src/main/scala/example") + .settings(commonSettings) + .dependsOn(rocketchip, testchipip, icenet) + // MIDAS-specific dependencies lazy val mdf = RootProject(file("barstools/mdf/scalalib")) lazy val barstools = (project in file("barstools/macros")) @@ -79,4 +83,4 @@ lazy val midas = (project in file("midas")) // Finally the root project lazy val firesim = (project in file(".")) .settings(commonSettings) - .dependsOn(rocketchip, midas, boom, icenet, sifiveip) + .dependsOn(rocketchip, midas, boom, icenet, sifiveip, example)
まず、rocketChipDir
とfireChipDir
をtarge-rtl/firechip/
からtarget-rtl/firechip-msyksphinz
に書き換えている。また、FireChipディレクトリの中でsrc/main/scala/example
内のコンフィグレーションを参照してほしいので、example
変数を定義し、さらにfiresim
変数の依存関係にexample
を追加している。
これで、sim
ディレクトリに移動してmake
を実行してみる。
make TARGET_CONFIG=FireSimRocketChipMatrixMulConfig
しばらく待つと、RTLが生成されているのが分かる。生成されたRTLを見てみると、開発したMatrixMulモジュールがしっかり組み込まれていた。
find . -name "*.v" | grep Matrix ... ./generated-src/f1/FireSim-FireSimRocketChipMatrixMulConfig-FireSimConfig/FPGATop.v
generated-src/f1/FireSim-FireSimRocketChipMatrixMulConfig-FireSimConfig/FPGATop.v
module MatrixMul( input clock, input reset, output io_cmd_ready, input io_cmd_valid, input [6:0] io_cmd_bits_inst_funct, input [4:0] io_cmd_bits_inst_rd, input [63:0] io_cmd_bits_rs1, input [63:0] io_cmd_bits_rs2, ...