Rocket Chipは構成によってどのようなコンポーネントが含まれているのかが変わっているのだが、それ以外にもリビジョンによっても結構構成が変わって、FPGAへのインプリメントに使用する面積が変わったりもする。
比較対象として、以下のリビジョンを使用した。
35d377d Merge pull request #1100 from freechipsproject/disable-local-amos
(日記を執筆時点の最新のリビジョン)
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階層のモジュールの面積比較を行ってみた。
DCacheが大きすぎる。ちゃんとブロックRAMに変換できていないんじゃないか?BigCoresとSmallCoresでキャッシュの構成が違いすぎている気がする。
基本的にDCacheの大きさがダイレクトに聞いているような気がしていて、data_arrays_0_ext
を正しく作らなければこのようになってしまう。
これは外部のVerilogで定義されているのだが、この実装がそのまんまなのでBlockRAMに手起業させることが出来ない。
っていうかRAMBを全く使ってくれない。
+---------------------------------------+----------------------------+------------+------------+---------+------+--------+--------+--------+--------------+
| 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 |
+--------------------------------+----------------------------+------------+------------+---------+------+------+--------+--------+--------------+
| 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 |