「#20-8 スーパスケイラ」では、オリジナル32ビットCPUコアNihoniumをスーパスケイラに対応したCPUコアを設計しました。
スーパスケイラとは、CPUの命令スロット(実行ユニット)を複数(2個)持って、複数命令を同時並列に実行可能なCPU方式の事です。スロットはまさにCPU「そのもの」と言って過言ではないので、もし、2個のスロットを備えたスーパスケイラ方式のCPUがあったなら、その論理規模は通常の(スーパスケイラではない→シングルスロット)CPUに比べて約×2倍の大きさとなります。
実際、Nihoniumのシングルスロット版とスーパスケイラ版で論理規模(LUT)を比べてみたところ、以下の様になりました。
Nihonium(シングルスロット版): 約4,700LUT
Nihonium-SS(スーパスケイラ版): 約11,500LUT
元々、オリジナル16ビットCPUコアMoscoviumが約2,100LUT、乗除算コプロセッサ込みで約3,000LUTの所、32ビット化によって論理規模が拡大していたところに、更にスーパスケイラ化による論理増大で、とてつもなく大きなCPUコアとなってしまいました。
手持ちのFPGAボード(Sipeed Lichee Tang Primer)では、使用可能なLUT数が最大19,800LUTとなっているため、Nihonium-SS×1個でほぼ6割方使い切ってしまう計算です。当然、Nihonium-SSのデュアルコア化はLUTの上限を超えてしまうため、FPGAボードへの書き込みはできません。
今回は、そんな「スーパスケイラ ❌ デュアルコア」というお話です。
マイコンの最上位モジュールの話から始めます。
Moscovium/Nihoniumシリーズのマイコンは、ダウンスケールと言う考え方で、常に最新の回路記述を使い、過去に作ったマイコンと同等機能となる様に最上位モジュールを維持しています(下図、再掲)。
そのため、最上位モジュールの先頭付近には以下の様なコンパイルオプションが並んでいて、`defineマクロを有効化/無効化することで、様々なコンフィギュレーションのマイコンを得ることが可能となっています。
// compile option
//`define MCOC_CORE_NH
//`define MCOC_CORE_NHSS
//`define MCOC_CORE_MCSS
//`define MCOC_PORT_HIZO
`define MCOC_NO_INTC
`define MCOC_NO_TIM0
`define MCOC_NO_TIM1
`define MCOC_NO_LOGA
`define MCOC_NO_STWS
`define MCOC_NO_FNJP
`define MCOC_NO_UAR1
`define MCOC_NO_POR1
`define MCOC_NO_ADC
//`define MCOC_RAM_16K
//`define MCOC_RAM_24K
//`define MCOC_RAM_32K
//`define MCOC_RAM_40K
//`define MCOC_ROM_8K
//`define MCOC_ROM_16K
//`define MCOC_IRAM_4K
//`define MCOC_IRAM_BYTE_WRITE
//`define MCOC_SDRAM_8M
//`define MCOC_CACHE_4K
//`define MCOC_DUAL
`define MCVM_COPR_NOMUL
`define MCVM_COPR_NODIV
`define MCVM_COPR_NOFPU
コメントになっている`defineマクロは定義されず、コメントの外れた`defineマクロは定義されていて、下方では`ifdefディレクティブを使って、デザインを条件付きでコンパイルしています。上のコード例は現時点でのMCOC115MN0408用の記述(mcoc115mn0408.v)となっています。
※定義するとユニットが無効化されるマクロ(*_NO_*)と、定義するとユニットが有効化されるマクロが混在していて統一感が無いのだけど、今から修正するのも難儀な話なので放置(1^u^;)。
スーパスケイラ版Nihonium-SSを選択するマクロはMCOC_CORE_NHSS、デュアルコアCPU版を選択するマクロはMCOC_DUALです。Nihonium-SSのデュアルコア化は、以下2点の理由により設定できないようにしてあります。
同時に設定できない様、以下の通りの記述が挿入されています。
`ifdef MCOC_CORE_NHSS
`undef MCOC_DUAL
`undef MCOC_IRAM_4K
`define MCOC_ROM_SS
`endif // MCOC_CORE_NHSS
もし、MCOC_CORE_NHSS(スーパスケイラ、Nihonium-SS)が`defineされていたならば、MCOC_DUAL(デュアルコア)を無効化する記述(`undef)となっています。つまり、これまでの最上位モジュールでは、スーパスケイラとデュアルコアは同時には設定できないような仕組みになっていました。
※同時に、現時点で32ビットフェッチバス版に未対応の命令フェッチ用RAM(I-RAM)ユニットも、無効化してあります(`undef MCOC_IRAM_4K)。
スーパスケイラとデュアルコアの両立には、まず、命令フェッチ用ROMをデュアルコア用に改造する必要がありました。
デュアルコア用の命令フェッチROMとしては、2個のCPUから同時に1個のROMへフェッチアクセスがあるので、デュアルポートROMマクロを使って同時アクセスを可能とする必要がありました。
詳細: 「#17-1 双頭の狼」に解説有り。
スーパスケイラでは、32ビットフェッチを実行するためにデュアルポート機能を使ってしまったため、デュアルコア版との同時使用が不可能となっていました。
詳細: 「#20-8 スーパスケイラ」に解説有り。
そこで、勿体ないのですが、内容の全く同じROMを2個インスタンスすることで、解決することにしました(下図、右側)。
同じ内容のROMを2個使うということは、チップ上のROM面積が×2倍になるという事なので、ちと無駄ですね……。他に良い手が思いつかなかったため、許容しました。
※ソフトウェアのプログラミング(やハンドリング)が面倒になるので、あまり好みではないのですが、2個のCPUが異なるROMからフェッチできることで、将来的にはCPU毎に全く異なるプログラムを実行させることも可能なので、前向きに考えておきたいと思います。
ネットリスト上に、同じ内容のROMが2個存在することになるため、iverilogなどでシミュレーションする時、$readmemh()システムタスクを使ってROMデータを読み込む場合、2個のROMへデータをロードしてください。
このため、テストベンチ(test.v)に、SIM_CORE_RMDCという`defineマクロを追加してあります(下コード抜粋)。
$readmemh ("mcoc_irom.mem", top.rom.romwr.inst.memory);
`ifdef SIM_CORE_RMDC
$readmemh ("mcoc_irom.mem", top.rom.romwr2.inst.memory);
`endif // SIM_CORE_RMDC
2個の命令フェッチ用ROMに同じROMデータ(mcoc_irom.mem)をロードするような記述となっています。スーパスケイラかつデュアルコアでシミュレーションする場合には、テストベンチ(test.v)先頭付近の「`define SIM_CORE_RMDC」を有効にして使ってください。
最後に、CPU自体を何とかしないと、手持ちのFPGAボードに書き込むことができません。
簡単に言ってしまうと、手持ちのCPUコアの中で一番小さいオリジナル16ビットCPUコアMoscoviumをスーパスケイラ化して、以下のマトリクスを埋めてみようという事です。
通常版 シングル スロット |
スーパ スケイラ版 |
|
16ビットCPU | Moscovium | Moscovium-SS |
32ビットCPU | Nihonium | Nihonium-SS |
ピンク色着色セルが、現在存在しないMoscovium(16ビット)のスーパスケイラ版、Moscovium-SSとなります。
以下リンクより、オリジナル16ビットCPUコアのスーパスケイラ版Moscovium-SSを搭載したデュアルコアMSOC115DC0416のデザインをダウンロードできます。FPGAボード(Sipeed Lichee Tang Primer)への書き込み手順はこちらを参照してください。
マイコン型名(MSOC115DC0416等)の解釈については、こちらの表を更新しておきました。
以下に、コンパイル(論理合成・配置配線)結果をまとめておきます。
論理規模(LUT数)は、ギリギリFPGAボードの最大値(19,600LUT)を下回りました。「現時点では」Moscovium-SSコアを使ったデュアルコアをFPGAボードに書き込むことが可能です。
ただし、現時点でギリギリなので、もし今後、Moscovium/Nihoniumの機能(命令等)を拡張して、より論理規模が大きくなった場合には、FPGAボード(Sipeed Lichee Tang Primer)へ書き込みできなくなってしまう可能性は有ります。その場合は、あきらめるか、より大きい論理に対応したFPGAボードを使うか、してくださいm(1__)m。
今回、正式にスーパスケイラ × デュアルコアに対応したので、各CPUコアのデュアルコア版を`defineマクロで設定可能となっています。
つまり、Nihonium-SSのデュアルコアなども設定可能です。論理的に正常動作するので、iverilog等を使ったシミュレーションは実行可能です。ただし、FPGAボードのLUT数が足りないため、FPGAボードへの書き込みはエラーとなる場合があります。
シミュレーションを実行して、有効性を確かめておきましょう。
一部、LUT数オーバでFPGAボードに書き込みできないデザインがあるので、実機(FPGAボード)を使って比較することができないためです。
評価に使用するプログラムは、円周率計算プログラム(calc_pi.asm)です。
今回設計したスーパスケイラ版Moscovium-SS用に、命令の実行順番を入れ替えて最適化したcalc_pi_ms.asmを使います。
完成プログラム:calc_pi_ms.asm
※Moscoviumは16ビットなので、Nihonium-SS(32ビット)用に最適化したcalc_pi_ss.asmとは異なるコードとなります。
今回はシミュレーションでの確認となるので、プログラム先頭付近の「def s,""」としてアセンブルしてください。シミュレーションの実行方法はこちらをご確認ください。
シミュレーションには時間がかかるので、円周率の桁数は抑えつつ、シミュレーションでパフォーマンスの検証が十分可能な様に、円周率を32桁まで計算してシミュレーション時間で実行速度を比較します。
LUT数オーバでFPGAボードへの書き込みができない、Nihonium-SSのデュアルコア版などでもシミュレーションは可能なので、同じ条件で各CPUコアのパフォーマンスを評価しました。
以下表に、各CPUコアによる円周率(32桁)の計算時間とLUT数のまとめ表を示します。
CPU |
円周率32桁 計算時間 [サイクル] |
CPUの LUT数 |
速度順 | |||
16ビット | 通常版 | シングルコア | Moscovium | 59,272 | 3,452 | 8 |
デュアルコア | Moscovium×2 | 32,862 | 6,904 | 4 | ||
スーパスケイラ版 | シングルコア | Moscovium-SS | 48,274 | 7,530 | 7 | |
デュアルコア | Moscovium-SS×2 | 26,838 | 15,060 | 3 | ||
32ビット | 通常版 | シングルコア | Nihonium | 44,834 | 5,254 | 6 |
デュアルコア | Nihonium×2 | 25,174 | 10,508 | 2 | ||
スーパスケイラ版 | シングルコア | Nihonium-SS | 36,038 | 12,753 | 5 | |
デュアルコア | Nihonium-SS×2 | 20,360 | 25,506 | 1 |
以下、解説と考察です。
16/32ビット × シングルスロット/スーパスケイラのマトリクスを埋めてみました。