MNISTを、ハードウェアアクセラレータを使って高速化したい。 前回はFPGAで動作確認をしたが、MNISTは動いてくれなかった。
RTLシミュレーションで動いてFPGAで動かないというのは、なかなかデバッグがつらい。 まずは演算気の部分にパイプラインを挿入するのと、 Chiselでデバッグレジスタ群を搭載してデバッグしてみる。
関連記事 目次
- RISC-V ISS Spike を使ってMNISTのハードウェアアクセラレーションをシミュレーションしたい
- RISC-V ISS Spike を使ってMNISTのハードウェアアクセラレーションを実装する
- Chiselを使ってMNISTハードウェアアクセラレータを実装(実装中)
- Chiselを使ってMNISTハードウェアアクセラレータを実装(FPGAで確認)
MNISTアクセラレータにパイプラインレジスタ挿入
演算器に対してパイプラインレジスタを挿入する。 これはChiselで記述するのだが、WireをRegに変えるだけである。あとは計算結果を格納するタイミングを変える。
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
デバッグレジスタの値を取り出してみたのだが、明らかにおかしな値が入っていた。なんだこりゃ?
=== 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シミュレーションでうまく行っているからなあ。 さらにデバッグレジスタを挿入して確かめてみよう。