FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.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

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/ より)