FPGA開発日記

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

Rocket-Chipにおけるコンフィグレーション別の面積比較 (BlockRAMへのマッピングの問題)

Rocket Chipは構成によってどのようなコンポーネントが含まれているのかが変わっているのだが、それ以外にもリビジョンによっても結構構成が変わって、FPGAへのインプリメントに使用する面積が変わったりもする。

比較対象として、以下のリビジョンを使用した。

35d377d Merge pull request #1100 from freechipsproject/disable-local-amos (日記を執筆時点の最新のリビジョン)

  • DefaultConfig

FreeChipProjectのRocket Chipは、DefaultConfigとDefaultFPGAConfigというものが存在しており、それぞれの構成の違いは以下のようになっている。

  • src/main/scala/system/Config.scala
class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig)
class DefaultFPGAConfig extends Config(new WithNSmallCores(1) ++ new BaseFPGAConfig)
class DefaultFPGASmallConfig extends Config(new DefaultFPGAConfig)

WithNBigCores()WithNSmallCores()の違いは、パラメータの違いとして表現されているのだが、

  • src/main/scala/coreplex/Config.scala
class WithNBigCores(n: Int) extends Config((site, here, up) => {
  case RocketTilesKey => {
    val big = RocketTileParams(
      core   = RocketCoreParams(mulDiv = Some(MulDivParams(
        mulUnroll = 8,
        mulEarlyOut = true,
        divEarlyOut = true))),
      dcache = Some(DCacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nMSHRs = 0,
        blockBytes = site(CacheBlockBytes))),
      icache = Some(ICacheParams(
        rowBits = site(SystemBusKey).beatBits,
        blockBytes = site(CacheBlockBytes))))
    List.tabulate(n)(i => big.copy(hartid = i))
  }
})

class WithNSmallCores(n: Int) extends Config((site, here, up) => {
  case RocketTilesKey => {
    val small = RocketTileParams(
      core = RocketCoreParams(useVM = false, fpu = None),
      btb = None,
      dcache = Some(DCacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nSets = 64,
        nWays = 1,
        nTLBEntries = 4,
        nMSHRs = 0,
        blockBytes = site(CacheBlockBytes))),
      icache = Some(ICacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nSets = 64,
        nWays = 1,
        nTLBEntries = 4,
        blockBytes = site(CacheBlockBytes))))
    List.tabulate(n)(i => small.copy(hartid = i))
  }
})

これを見ると、だいたい分かってくるのは以下のような構成になっているということだ。主に命令キャッシュ、データキャッシュの構成を変更している。

WithNBigCores WithNSmallCores
コア機能 VM 指定なし(あり) なし
演算器 mulUnroll 8 指定なし(なし)
mulEarlyOut あり 指定なし(なし)
divEarlyOut あり 指定なし(なし)
FPU 指定なし(あり) なし
Dキャッシュ rowBits システムバスと同じサイズ システムバスと同じサイズ
セット数 指定なし(64) 64
ウェイ数 4 1
TLBエントリ数 32 4
MSHR数 0 0 MSHR: Miss Status Handling Register
ブロックバイト数 CacheBlockBytes CacheBlockBytes *
命令キャッシュ rowBits システムバスと同じサイズ システムバスと同じサイズ
セット数 64 64
ウェイ数 4 1
TLBエントリ数 32 4
ブロックバイト数 CacheBlockBytes CacheBlockBytes *

それぞれの構成において、Vivadoで論理合成して比較してみた。

なお、合成のためには以下のモジュールをRocket Chip以外に追加する必要がある。

  • plusarg_reader.v // Argument Reader シミュレーション用。ただしFPGA合成用はからのモジュールが定義される。
  • freechips.rocketchip.system.DefaultFPGAConfig.behav_srams.v // SRAMのビヘイビアモデル。一応FPGAで合成することは出来るが、あまり良い構成ではない。

というわけで、Rocket-ChipのVerilogのモジュールのうち、RocketTile_rocket から下の1階層のモジュールの面積比較を行ってみた。

f:id:msyksphinz:20171111141629p:plain

DCacheが大きすぎる。ちゃんとブロックRAMに変換できていないんじゃないか?BigCoresとSmallCoresでキャッシュの構成が違いすぎている気がする。

基本的にDCacheの大きさがダイレクトに聞いているような気がしていて、data_arrays_0_extを正しく作らなければこのようになってしまう。 これは外部のVerilogで定義されているのだが、この実装がそのまんまなのでBlockRAMに手起業させることが出来ない。 っていうかRAMBを全く使ってくれない。

  • WithNBigCoresの場合
+---------------------------------------+----------------------------+------------+------------+---------+------+--------+--------+--------+--------------+
|                Instance               |           Module           | Total LUTs | Logic LUTs | LUTRAMs | SRLs |   FFs  | RAMB36 | RAMB18 | DSP48 Blocks |
+---------------------------------------+----------------------------+------------+------------+---------+------+--------+--------+--------+--------------+
|     dcache                            |              DCache_dcache |      56796 |      56795 |       0 |    1 | 133722 |      0 |      4 |            0 |
|       (dcache)                        |              DCache_dcache |        788 |        787 |       0 |    1 |    536 |      0 |      0 |            0 |
|       data                            |            DCacheDataArray |      54494 |      54494 |       0 |    0 | 131145 |      0 |      0 |            0 |
|         data_arrays_0                 |              data_arrays_0 |      54494 |      54494 |       0 |    0 | 131145 |      0 |      0 |            0 |
|           data_arrays_0_ext           |          data_arrays_0_ext |      54494 |      54494 |       0 |    0 | 131145 |      0 |      0 |            0 |
|       tag_array                       |                  tag_array |        147 |        147 |       0 |    0 |      0 |      0 |      4 |            0 |
|         tag_array_ext                 |              tag_array_ext |        147 |        147 |       0 |    0 |      0 |      0 |      4 |            0 |
|       tlb                             |                        TLB |       1367 |       1367 |       0 |    0 |   2041 |      0 |      0 |            0 |
  • WithNSmallCoresの場合
+--------------------------------+----------------------------+------------+------------+---------+------+------+--------+--------+--------------+
|            Instance            |           Module           | Total LUTs | Logic LUTs | LUTRAMs | SRLs |  FFs | RAMB36 | RAMB18 | DSP48 Blocks |
+--------------------------------+----------------------------+------------+------------+---------+------+------+--------+--------+--------------+
|     dcache                     |              DCache_dcache |       1119 |       1119 |       0 |    0 |  482 |      1 |      1 |            0 |
|       (dcache)                 |              DCache_dcache |        880 |        880 |       0 |    0 |  482 |      0 |      0 |            0 |
|       data                     |            DCacheDataArray |        139 |        139 |       0 |    0 |    0 |      1 |      0 |            0 |
|         data_arrays_0          |              data_arrays_0 |        139 |        139 |       0 |    0 |    0 |      1 |      0 |            0 |
|           data_arrays_0_ext    |          data_arrays_0_ext |        139 |        139 |       0 |    0 |    0 |      1 |      0 |            0 |
|       tag_array                |                  tag_array |         91 |         91 |       0 |    0 |    0 |      0 |      1 |            0 |
|         tag_array_ext          |              tag_array_ext |         91 |         91 |       0 |    0 |    0 |      0 |      1 |            0 |
|       tlb                      |                        TLB |          9 |          9 |       0 |    0 |    0 |      0 |      0 |            0 |
|         pmp                    |                 PMPChecker |          9 |          9 |       0 |    0 |    0 |      0 |      0 |            0 |

以下がそのVerilogの実装だ。ちょっとひどい。ちゃんとBlockRAMに置き換えないと。

  • WithNBigCores の場合、 freechips.rocketchip.system.DefaultConfig.behav_srams.v の構成
  reg [255:0] ram [511:0];
...
  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];
      if (RW0_wmask[7]) ram[RW0_addr][63:56] <= RW0_wdata[63:56];
      if (RW0_wmask[8]) ram[RW0_addr][71:64] <= RW0_wdata[71:64];
      if (RW0_wmask[9]) ram[RW0_addr][79:72] <= RW0_wdata[79:72];
      if (RW0_wmask[10]) ram[RW0_addr][87:80] <= RW0_wdata[87:80];
      if (RW0_wmask[11]) ram[RW0_addr][95:88] <= RW0_wdata[95:88];
      if (RW0_wmask[12]) ram[RW0_addr][103:96] <= RW0_wdata[103:96];
      if (RW0_wmask[13]) ram[RW0_addr][111:104] <= RW0_wdata[111:104];
      if (RW0_wmask[14]) ram[RW0_addr][119:112] <= RW0_wdata[119:112];
      if (RW0_wmask[15]) ram[RW0_addr][127:120] <= RW0_wdata[127:120];
      if (RW0_wmask[16]) ram[RW0_addr][135:128] <= RW0_wdata[135:128];
      if (RW0_wmask[17]) ram[RW0_addr][143:136] <= RW0_wdata[143:136];
  • WithNSmallCores の場合、 freechips.rocketchip.system.DefaultFPGAConfig.behav_srams.v の構成
  reg [63:0] ram [511:0];
  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];
      if (RW0_wmask[7]) ram[RW0_addr][63:56] <= RW0_wdata[63:56];
    end

追記: fpga-zynqの構成で実行すると、BlockRAMが正しく推論されているようだ。

+-----------------------------------------+------------------------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|                 Instance                |                  Module                  | Total LUTs | Logic LUTs | LUTRAMs | SRLs |  FFs  | RAMB36 | RAMB18 | DSP48 Blocks |
+-----------------------------------------+------------------------------------------+------------+------------+---------+------+-------+--------+--------+--------------+
|     DCache                              |                                   DCache |       1659 |       1658 |       0 |    1 |   986 |      0 |     36 |            0 |
|       (DCache)                          |                                   DCache |        504 |        503 |       0 |    1 |   502 |      0 |      0 |            0 |
|       MetadataArray                     |                            MetadataArray |        283 |        283 |       0 |    0 |     7 |      0 |      4 |            0 |
|       data                              |                          DCacheDataArray |        535 |        535 |       0 |    0 |     0 |      0 |     32 |            0 |
|       fq                                |                              FinishQueue |          8 |          8 |       0 |    0 |     5 |      0 |      0 |            0 |
|       tlb                               |                                    TLB_2 |        329 |        329 |       0 |    0 |   472 |      0 |      0 |            0 |

「GPUを支える技術」を読む(第4章 後半)

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

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

今回は第4章後半。NVIDIA以外のGPUの話と、最新のGPUの新機能の話。

https://0rhsdq.bn1304.livefilestore.com/y4m3qSdO-84x6JVFksVxXo1KS1k0x5mw3GBXZN904WPBKRSOGONH-68fDXXEpj29HIDA2PwYBwz1Pc1B4yJh13_uohtSg7kdeWTr0f9EbvGI5Z8iA9HOAKg10fsY8ye-AyALgr2__O7A7l1SVoZ43jOIDfaNFfiMFpVvamFiEOthD5IboyL0h3mt0IaSMlDBDNs7e0dskBNQZ6JfQEkkJy64g?width=1414&height=3856&cropmode=none
f:id:msyksphinz:20171110003212p:plain

「GPUを支える技術」を読む(第4章 前半)

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

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

今回は第4章前半。NVIDIA P100のザックリとした構造の概要。

https://1bhydq.bn1304.livefilestore.com/y4mTd0gpgPEcVGmwQzBXpiMR3piNxs4qeQZw4ErOEwngOefHyGXoCJiD42rolDLs5rF0E3uYtFLzTcTzFLumGARG1RaYgDci4kiV9IivhBjsd9C1v94VI7UyBllyLnHkrrmnhfyqLLa41mXTqfKhitbr0gxxP5Ep04RItcSIepLVXCM18BgOcTRnc0Hkt6RzfyCz2zmqGN0OJnATZu12EKmbQ?width=1440&height=8322&cropmode=none

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

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

f:id:msyksphinz:20171109014246p:plain

「GPUを支える技術」を読む(第3章)

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

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

今回は第3章。

https://1hhtdq.bn1304.livefilestore.com/y4mni9uaWk0_UVJOhj0DUQ07fMylWrCIhCMWasnKyRWfDCPQgZp1Y2iLhqmEEbg5mH0IHHuJ5_fU7VyX8KF84vUmGJEraaswQGh_s8m1Whs_D44gj_SLPEzLkx0HWO8Zs1m97uiYY_5a649Zz9FqbzrjLzNdLUQCTdxPI6BoGFCTiTSlvPZOdwhp9bDbVqnWVTgoUcz1pS0pcvmfnXQtMoZrg?width=1440&height=5909&cropmode=none

f:id:msyksphinz:20171108005203p:plain

(https://wccftech.com/review/intel-core-i7-6700k-skylake-k-cpu-review-asus-z170-pro-gaming/3/ より)

プログラミング言語Rustに入門中 (goblinを使ってelfファイルを解析する3.)

f:id:msyksphinz:20171103203951p:plain

Rustのライブラリを使えばElfの解析だってできる。

バイナリファイルを読み込んで、HashMapにアドレスとデータの対を格納するプログラムを作成した。 各セクション毎にデータを読み込んで一つのHashMapにバイト単位でデータを書き込む。このモデルを作成すれば、Rustで簡単な命令セットシミュレータが作れるようになるはずだ。

  • training/program/rust/projects/sim_mem_elf/src/main.rs

github.com

fn memory_elf (elf_obj: goblin::elf::Elf,
               memory: &mut std::collections::HashMap<u64, u8>,
               buffer: &std::vec::Vec<u8>) -> error::Result<()>
{
    let shdr_strtab = &elf_obj.shdr_strtab;
    for section in &elf_obj.section_headers {
        println!("elf_obj.section_headers = {:#?}, file_offset = {:#x}, size = {:#x}",
                 &shdr_strtab[section.sh_name],
                 section.sh_offset,
                 section.sh_size
        );
        if section.sh_size != 0 {
            for idx in 0..(section.sh_size-1) {
                let mut offset = idx + section.sh_offset;
                memory.insert(section.sh_addr + idx, buffer[offset as usize]);
            }
        }
    }
    Ok(())
}
$ cargo run ~/work/rocket-chip-msyksphinz/riscv-tools/riscv-tests/benchmarks/qsort.riscv

f:id:msyksphinz:20171107012422p:plain

ただしまだRustとかScalaの初心者なので、MutableとかImmutableとか、まだ分かっていないことが多い。コンパイラの結果を見ながら進めている感じ。こんなので大丈夫かな?

「GPUを支える技術」読む (第2章)

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

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

今回は第2章。

https://1rhvdq.bn1304.livefilestore.com/y4mGqo8qCKInmFDMPOIy79rwY84DPKN9fWDZ24jkXV0rjjHzvmRh7bHqW-BZR074BWQzpZe5JF-WpY9l5A2cuJOcZ3eB6DlxyD2ygfqQGH4mAH1ETBCrN4N6mCEIroTgzeUmz0vVtsLSQpHp8MPA3NFwiGEFXtTw-N7J7HkdLwLdews8NsnQ_QKCdfWGDHnFevcUJj8YrBFqeVheC2EkLgx5A?width=1920&height=5696&cropmode=none

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

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

f:id:msyksphinz:20171105231317p:plain

「GPUを支える技術」読む (第1章)

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

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

一応、Jupyter Notebookでまとめを作っていく。画像などはコピーではなく、すべて自分で作成している。

これを最後までできるかな?頑張る。

https://zhhqrw.bn1304.livefilestore.com/y4m0LeEY6uHe38Rx39YNIrxDeH4IAFz_aGW0AMUAwiX8uRQl8G4RMEv3qh0Jhao6UFV7kjKU4vQvBgkIO68sjFp-W0b0FrFvIzbPgWFH--hCVgUAFzcUDUOPD5A_rJkndBrs4igCIqAwOw-O0wAM9x27zQ5oogLVaKILztmqMtGG_VRrFmq7u2ZS8AClFZJr-B0f6Blq2gLEr-q9rEt6gt0xQ?width=1423&height=2991&cropmode=none

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

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

f:id:msyksphinz:20171105011618p:plain