FPGA開発日記

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

Chiselを使ってMNISTハードウェアアクセラレータを実装(FPGAでデバッグ中)

MNISTを、ハードウェアアクセラレータを使って高速化したい。 前回はFPGAで動作確認をしたが、MNISTは動いてくれなかった。

RTLシミュレーションで動いてFPGAで動かないというのは、なかなかデバッグがつらい。 まずは演算気の部分にパイプラインを挿入するのと、 Chiselでデバッグレジスタ群を搭載してデバッグしてみる。

関連記事 目次

MNISTアクセラレータにパイプラインレジスタ挿入

演算器に対してパイプラインレジスタを挿入する。 これはChiselで記述するのだが、WireをRegに変えるだけである。あとは計算結果を格納するタイミングを変える。

f:id:msyksphinz:20180123012222p:plain

diff --git a/src/main/scala/tile/DotProductF16_RoCC.scala b/src/main/scala/tile/DotProductF16_RoCC.scala
index e81e5ad..fd565ff 100644
--- a/src/main/scala/tile/DotProductF16_RoCC.scala
+++ b/src/main/scala/tile/DotProductF16_RoCC.scala
@@ -44,9 +44,11 @@ class DotProductF16Module(outer: DotProductF16, n: Int = 4)(implicit p: Paramete
   val r_cmd_state  = Reg(UInt(width = 3), init = s_idle)
   val r_recv_state = Reg(UInt(width = 3), init = s_idle)

-  val w_ah_bh       = Wire(SInt(width=32))
-  val w_ah_bl_al_bh = Wire(SInt(width=32))
-  val w_al_bl       = Wire(UInt(width=32))
+  val w_ah_bh       = Reg(SInt(width=32))
+  val w_ah_bl_al_bh = Reg(SInt(width=32))
+  val w_al_bl       = Reg(UInt(width=32))
+
+  val r_recv_valid  = Reg(init = {Bool(false)})

まあ結果的にこのタイミング改善は役に立たなかった。ここはクリティカルパスではない。

Chiselでデバッグレジスタを記述する

Chiselでデバッグレジスタを搭載して、計算結果を格納する。32ビットのレジスタを128本搭載し、動作を確認してみる。

1回DotProductの更新があるたびに、128本のレジスタFIFOの要領で使っていき、外部から参照できるようにした。

+
+
+  //=================================================
+  // Logger
+  //=================================================
+  val log_regfile_in = Wire(SInt(width=32))
+  log_regfile_in := r_total + w_result
+  when (r_recv_valid) {
+    log_regfile(r_recv_log_count) := log_regfile_in.asUInt()
+    r_recv_log_count := r_recv_log_count + UInt(1)
+  }
+
+  when (io.cmd.fire() && doCalc) {
+    r_recv_log_count := UInt(0)
+  }

実際にこれでRTLシミュレーションし動作確認を行い、FPGAに持って行ったのだが、やはりうまく動作しない。

root@zynq:~# ./fesvr-zynq train_twolayernet_fix16_hw_full
=== TestNetwork ===
=== TestNetwork ===
 === start ===
Final Result : Correct = 27 / 200
Time = 261373756 - 37204703 = 224169053

f:id:msyksphinz:20180123012606p:plain

デバッグレジスタの値を取り出してみたのだが、明らかにおかしな値が入っていた。なんだこりゃ?

=== TestNetwork ===
=== TestNetwork ===
 === start ===
mem_log[0] = 00028f64
mem_log[1] = 00028f64
mem_log[2] = 00028f64
mem_log[3] = 00028f64
mem_log[4] = 00028f64
mem_log[5] = 00028f64
mem_log[6] = 00028f64
mem_log[7] = 00028f64
mem_log[8] = 00028f64
mem_log[9] = 00028f64
mem_log[10] = 00028f64
mem_log[11] = 00028f64
mem_log[12] = 00028f64
mem_log[13] = 00028f64
mem_log[14] = 00028f64
mem_log[15] = 00028f64
mem_log[16] = 00028f63
mem_log[17] = 00029c55
mem_log[18] = 00029cae
mem_log[19] = 00029cae

まだちゃんと動いてくれないなあ。。。ってか、こういうデバッグがいちいち複雑で、ChiselからFPGAの合成も時間がかかりすぎている。

もう少し楽にデバッグする方法を、Rocket-Chipは確立してほしい。

2018/01/23 追記。デバッグレジスタを挿入して計算結果を確認すると、全然違う計算結果になっているようだ。 Chiselからの変換がおかしいのか? FPGAでの論理合成がおかしいのか?でもRTLシミュレーションでうまく行っているからなあ。 さらにデバッグレジスタを挿入して確かめてみよう。

f:id:msyksphinz:20180123234845p:plain