FPGA開発日記

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

「リーダブルコード」を読む (「第1章: 理解しやすいコード」「第2章: 名前に情報を埋め込む」)

諸事情で週末はネットワークをあまり使えないので、RISC-Vに関連する調査は中止。 あまりやることが無いので例によって一人読書会をしている。 今回は「リーダブルコード」。名著と呼ばれており、私も一度さっくりと読んだ。 ただし忘れていることもあるし、体系的に学びたいので読み直す。

例によってJupyter Notebookに書いて、スクリーンショットをキャプチャする形で公開していく。

今回は「第1章: 理解しやすいコード」「第2章: 名前に情報を埋め込む」までをまとめた。

まとめるといっても、本書は言いたいことを非常に簡潔に要約しており、ほぼほぼそれを写経したようなものになっているが、まあ自分で手を動かさないと分からないということで。。。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

https://zrhudq.bn1304.livefilestore.com/y4m8bAtmXdGSh0VXsFlgf80nuyh4YYYHkzzx8LpGsQWB4TNXPHcbnl8b3sf4UWFHTiuVdkUdl3wYahmFNdlNqWMTtH6D450O4gHDzMngTW09GMQiUGVsjRs1oza_bdM4Uuj-Hd-GxXTzgMCDILBqRyiFzA1Wnzp-9mUXooKtO6R0H6WQR4bJK2ofLdXK_q4gfKSVd6c7dLTMrz4HB4ITITcjg?width=1670&height=5053&cropmode=none

Rocket-Chipにおけるコンフィグレーション別の面積比較 (BOOMConfigで同様の合成調査)

前回のRocket Chipの面積比較に続いて、BOOMでも同様のことを実施した。

BOOMはVersion 1とVersion 2があり、それぞれでVerilogを生成してVivadoで合成してみる。

まだ集計できていないが、だいたいの面積の概要は以下のようになっている。BOOM v1の方が少し大きいかなあ。階層構成が違うので少しわかりにくい。

  • BOOM v1
|   RocketTile                        |                     RocketTile |     115065 |     110560 |    4478 |   27 | 43418 |      9 |      8 |           40 |
|     core                            |                       BoomCore |     108816 |     104369 |    4422 |   25 | 38958 |      0 |      0 |           40 |
|     dcache                          |       NonBlockingDCache_dcache |       2723 |       2674 |      48 |    1 |  1460 |      5 |      4 |            0 |
|     dcacheArb                       |              HellaCacheArbiter |          0 |          0 |       0 |    0 |     2 |      0 |      0 |            0 |
|     frontend                        |              Frontend_frontend |       3002 |       2993 |       8 |    1 |  2526 |      4 |      4 |            0 |
|     ptwOpt                          |                            PTW |        524 |        524 |       0 |    0 |   472 |      0 |      0 |            0 |
  • BOOM v2
+----------------------------------------------+------------------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|                   Instance                   |               Module               | Total LUTs | Logic LUTs | LUTRAMs | SRLs |  FFs  | RAMB36 | RAMB18 | DSP48 Blocks |
+----------------------------------------------+------------------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|   (Top)                                      |                              (top) |          0 |          0 |       0 |    0 |     0 |      0 |      0 |            0 |
|   tileList_0                                 |                           BOOMTile |     113074 |      99582 |   13470 |   22 | 32276 |      0 |      0 |           40 |
|     PTW_1                                    |                                PTW |        286 |        286 |       0 |    0 |   471 |      0 |      0 |            0 |
|     core                                     |                           BOOMCore |      93773 |      91919 |    1834 |   20 | 26971 |      0 |      0 |           40 |
|     dcArb                                    |                  HellaCacheArbiter |          1 |          1 |       0 |    0 |     2 |      0 |      0 |            0 |
|     dc_shim                                  |                         DCacheShim |        554 |        554 |       0 |    0 |   737 |      0 |      0 |            0 |
|     dcache                                   |                         HellaCache |       9987 |       4086 |    5900 |    1 |  2120 |      0 |      0 |            0 |
|     icache                                   |                           Frontend |       8473 |       2736 |    5736 |    1 |  1975 |      0 |      0 |            0 |
|   uncore                                     |                             Uncore |     196636 |      91747 |  104888 |    1 |  5443 |    128 |      0 |            0 |
|     (uncore)                                 |                             Uncore |          6 |          6 |       0 |    0 |     7 |      0 |      0 |            0 |
|     DebugModule_1                            |                        DebugModule |        300 |        236 |      64 |    0 |   138 |      0 |      0 |            0 |
|     LevelGateway_1_1                         |                       LevelGateway |          0 |          0 |       0 |    0 |     1 |      0 |      0 |            0 |
|     LevelGateway_2                           |                     LevelGateway_0 |          0 |          0 |       0 |    0 |     1 |      0 |      0 |            0 |
|     PLIC_1                                   |                               PLIC |         38 |         38 |       0 |    0 |    42 |      0 |      0 |            0 |
|     PRCI_1                                   |                               PRCI |        205 |        205 |       0 |    0 |   210 |      0 |      0 |            0 |
|     ROMSlave_1                               |                           ROMSlave |        169 |        169 |       0 |    0 |    14 |      0 |      0 |            0 |
|     TileLinkRecursiveInterconnect_2          |      TileLinkRecursiveInterconnect |         52 |         52 |       0 |    0 |     7 |      0 |      0 |            0 |
|     outmemsys                                |                  OuterMemorySystem |     195866 |      91041 |  104824 |    1 |  5023 |    128 |      0 |            0 |

BOOM v2の合成結果の階層表示。

f:id:msyksphinz:20171117025701p:plain

Rocket-Chipにおけるコンフィグレーション別の面積比較 (BlockRAMを推論させる方法調査)

前回のRocket Chipの標準論理合成では、FPGA向けにVivadoで合成してもBlockRAMが正常に推論されず、Dcacheが面積のほとんどを消費してしまう構成になってしまっていた。

msyksphinz.hatenablog.com

どうにかしてBlockRAMを使うように変更することはできないだろうか。 そもそも、なぜSRAMの部分がLUTで作られてしまうかというと、Rocket Chipの標準フローで合成すると、ASIC用にSRAMは外部定義に変更される。 rocket-chip/emulator/freechips.rocketchip.system.DefaultConfig.behav_srams.v というのがそれだ。 ASICを作る場合は、このモジュールを各プロセスに対応するSRAMに置き換える。 ただしこれは標準的なSRAMのように、WMEMのようなビット単位のWrite Maskが付いているSRAMを前提としており、BlockRAMを推論するのには不向きな構成になっている。

module data_arrays_0_ext(
  input RW0_clk,
  input [8:0] RW0_addr,
  input RW0_en,
  input RW0_wmode,
  input [31:0] RW0_wmask,
  input [255:0] RW0_wdata,
  output [255:0] RW0_rdata
);

  reg reg_RW0_ren;
  reg [8:0] reg_RW0_addr;
  reg [255:0] ram [511:0];
  `ifdef RANDOMIZE_MEM_INIT
    integer initvar;
    initial begin
...
  always @(posedge RW0_clk)
    if (RW0_en && RW0_wmode) begin
      if (RW0_wmask[0]) ram[RW0_addr][7:0] <= RW0_wdata[7:0];
      if (RW0_wmask[1]) ram[RW0_addr][15:8] <= RW0_wdata[15:8];
      if (RW0_wmask[2]) ram[RW0_addr][23:16] <= RW0_wdata[23:16];
      if (RW0_wmask[3]) ram[RW0_addr][31:24] <= RW0_wdata[31:24];
      if (RW0_wmask[4]) ram[RW0_addr][39:32] <= RW0_wdata[39:32];
      if (RW0_wmask[5]) ram[RW0_addr][47:40] <= RW0_wdata[47:40];
      if (RW0_wmask[6]) ram[RW0_addr][55:48] <= RW0_wdata[55:48];

そこでどうにかしてこの外部SRAM向けのWrapperが生成されるのを防がなければならないのだが、SiFive社の提供するFreedom環境ではSRAM Wrapperは生成されていない。どうやっているんだろう。

いろいろ調査した結果、SRAM Wrapperを作らない方法としては、FIRRTLでのVerilogファイルを生成する際、--repl-seq-mem を付加しないことがポイントなのではないかと思えてきた。

  • rocket-chip/emulator/Makefrag-verilator の抜粋
%.v: %.fir $(FIRRTL_JAR)
    echo $(FIRRTL)
    mkdir -p $(dir $@)
    $(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$*.conf -faf $*.anno -ffaaf
  • freedom/common.mk の抜粋
$(verilog): $(firrtl) $(FIRRTL_JAR)
    $(FIRRTL) -i $(firrtl) -o $@ -X verilog

したがって、Rocket-Chipのリポジトリ内の Makefrag-verilatorを以下のように改造した。これでfreechips.rocketchip.system.DefaultConfig.vを再生成すると、外部SRAM Wrapperを生成しなくなっていた。成功だ!

diff --git a/emulator/Makefrag-verilator b/emulator/Makefrag-verilator
index 021e131..86fdea6 100644
--- a/emulator/Makefrag-verilator
+++ b/emulator/Makefrag-verilator
@@ -3,8 +3,9 @@
 #--------------------------------------------------------------------
 firrtl = $(generated_dir)/$(long_name).fir
 verilog = \
-  $(generated_dir)/$(long_name).v \
-  $(generated_dir)/$(long_name).behav_srams.v \
+  $(generated_dir)/$(long_name).v
+
+# $(generated_dir)/$(long_name).behav_srams.v \

 .SECONDARY: $(firrtl) $(verilog)

@@ -12,9 +13,12 @@ $(generated_dir)/%.fir $(generated_dir)/%.d: $(FIRRTL_JAR) $(chisel_srcs) $(boot
        mkdir -p $(dir $@)
        cd $(base_dir) && $(SBT) "run-main $(PROJECT).Generator $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"

-%.v %.conf: %.fir $(FIRRTL_JAR)
+%.v: %.fir $(FIRRTL_JAR)
+       echo $(FIRRTL)
        mkdir -p $(dir $@)
-       $(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$*.conf -faf $*.anno -ffaaf
+       $(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog
+
+#   $(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $*.v -X verilog --infer-rw $(MODEL) --repl-seq-mem -c:$(MODEL):-o:$*.conf -faf $*.anno -ffaaf

freechips.rocketchip.system.DefaultConfig.v をVivadoで合成し、Utilizationを出力させてみた。よっしゃ!しっかりBlockRAMが使われている!

+---------------------------------------+----------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|                Instance               |           Module           | Total LUTs | Logic LUTs | LUTRAMs | SRLs |  FFs  | RAMB36 | RAMB18 | DSP48 Blocks |
+---------------------------------------+----------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|     dcache                            |              DCache_dcache |       2585 |       2584 |       0 |    1 |  2577 |      0 |     36 |            0 |
|       (dcache)                        |              DCache_dcache |        898 |        897 |       0 |    1 |   536 |      0 |      4 |            0 |
|       data                            |            DCacheDataArray |        324 |        324 |       0 |    0 |     0 |      0 |     32 |            0 |
|       tlb                             |                        TLB |       1363 |       1363 |       0 |    0 |  2041 |      0 |      0 |            0 |

合成結果の効果は見ての通りだ。BlockRAMを活用したことで、しっかり面積が削減できている。

これで、公平な評価が取れそうだな。

f:id:msyksphinz:20171116023808p:plain

「GPUを支える技術」を読了

Hisa Ando氏の「GPUを支える技術」を、とりあえず読了した。最後の方はだいぶ適当に省略してしまったが、メインの部分はかなりちゃんと読み込んだと思う。

GPUの基礎を分かっていない私にとって、一から解説してくれる良い本だった。詳細までは触れることはないが、全般的な技術の概要をイラストや写真を使って分かりやすく解説してくれる。

これ以降、GPUのニュース記事やネット上の解説記事を読んで、「???この用語の意味が分からない」となっても、この本を読み直せばきちんと理解できる気がする。 そんな感じの、GPUの辞典として使うことが出来るのではないか。とりあえず、良本として保管。

次は何の本を読もうかな。

GPUを支える技術 ――超並列ハードウェアの快進撃[技術基礎] (WEB+DB PRESS plus)

GPUを支える技術 ――超並列ハードウェアの快進撃[技術基礎] (WEB+DB PRESS plus)

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

Verilog-HDLで記述されたオープンソースのハードウェアライブラリ"BaseJump"

HotChips29 で発表された、学生が開発したRISC-V SoC ”Celerity”について資料を読んだ。

news.mynavi.jp

Celerityは学生の作ったRISC-Vのメニーコアチップで、4大学が共同して9か月で作成したチップとなっている。

9か月という短期間で作るための秘訣として、

  • 再利用
  • モジュール化設計
    • 部品レベルで設計を最適化し、ツールの処理時間を短くするため階層化設計を行った。
    • 詳細な中身を知らなくても利用できるブラックボックス設計を行った。
  • 自動化設計
    • 実装とテストのフローを抽象化して、色々な設計に適用できるようにした。
    • 確認済みのIPコンポーネントを利用し、インテグレーションのテストだけで済むようにした。
    • ハイレベル合成ツールを使用した。
    • アナログ設計が行われていた部分についてもディジタル設計のフローを使うようにした。

ということらしい。

BaseJump: Components for Open Source Hardware

この中で注目したのは、”BaseJump”とよばれるオープンソースのハードウェア部品を使ったということ。

BaseJumpは、オープンソースなハードウェアコンポーネントで誰でも使用することが出来る。 また、ホームページを見てみるとBGAパッケージも開発されており、これらもコンポーネント化されているのだろうか。

System Verilog のハードウェアコンポーネントは、BaseJump STLとして以下のBitbucketのページにまとめられている。

bitbucket.org

中身を見てみると、NoCのようなネットワークルータの部品から、標準的なMuxや非同期FIFOなど、一通りの部品はそろっている。かなり有用そうだ。

オープンソースのハードウェアコンポーネントというと、ParallelaのOH!が有名だが、こちらよりも部品点数は多いのではないだろうか?

github.com

「GPUを支える技術」を読む(第6章 GPUの周辺技術)

Hisa Ando氏の著書「GPUを支える技術」を買っていたのだが、ずいぶんと積ん読にしているのだった。

なので、一応最後まで読んでいきたい。こういうのは、きちんと宣言しないと途中で辞めちゃうので宣言する。頑張って最後まで読んでいこう。

今回は第6章。PCI ExpressやNVLink, さらにはCAPIのようなコヒーレンシプロトコルの話。

https://zxhzdq.bn1304.livefilestore.com/y4m8XR4_mlTlpRFEy37jWwiwEyyhLJq-neFv64D8kjepGTOfWQPf-c5FcFtHeGpH_zEfKXlfvOjsArRfTgBdufc1epH6SjsU6fZabZAWCQXwdfE-1BouEHsk5kiTGF_OnPW84P8G87EuNxgprNNenOutkbvRBWubmLi2cNRQYxCpItWHBbPWoryBdi08VYmENlbxcUwpJs4Yk_HAtTFMDvgTw?width=1440&height=3611&cropmode=none
f:id:msyksphinz:20171112233525p:plain:w200

「GPUを支える技術」を読む(第5章 GPUプログラミングの基本)

Hisa Ando氏の著書「GPUを支える技術」を買っていたのだが、ずいぶんと積ん読にしているのだった。

なので、一応最後まで読んでいきたい。こういうのは、きちんと宣言しないと途中で辞めちゃうので宣言する。頑張って最後まで読んでいこう。

今回は第5章。NVIDIAのCUDAおよびOpenACC、OpenMP4の話。

https://zxhqdq.bn1304.livefilestore.com/y4mXy1kmhgJbtVTyEjO8GZc2wWmXDdjUpFx99NBlBMdJPX_eqy5hHyEYslu_gGOIl00FR6KsGNf47ZRQYQbVZsQJikn6ZFX4UjYu4AlKW2VtMSC-ODlwOmkLKRIEV3gOb7X0Hw6WibJrFMhaygHXbMGdAz_mOqwUoyXNDHigsBMhUPISlFmmbvl9N02XyFMalTuvgpkW_oe3sd9ns4jBkfojA?width=1920&height=10108&cropmode=none
f:id:msyksphinz:20171112003820p:plain