FPGA開発日記

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

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