Cmod A7ボード(FPGA)で開発しているオリジナル16ビットCPUコアMoscoviumシリーズでは、デュアルコアCPUに対応したラインアップを用意しています(下図)。
※上図で例えば、エディションコード"DC"がSMPデュアルコア版です。2か所の同じCPU種に「〇」が付いています。
今までのMoscoviumシリーズに於けるデュアルコア版は、対称並列処理(SMP;Symmetric Multi-Processing)システムを採用していました。今回追加するラインアップは、非対称並列処理(AMP;Asymmetric Multi-Processing)システムです。
SMPとAMPの違いは、Symmetric(対称)か、Asymmetric(非対称)か、の差です。残りはMulti-Processing(並列処理)なので、複数のCPUが同時並列に処理を進めるシステムの事を指します。
今まで作ってきたMoscoviumシリーズのデュアルコア版は、すべてSMPに分類されるマイコンでした。つまり、2個搭載されたCPUが、双方とも同じ機能・性能を持った同じCPUだったのです。
同じ機能・性能を持ったCPUが複数搭載されていて、複数のCPU間に、主従関係も、上も下も、用途の違いなども存在せずに使用可能なのが、SMPです。
PC💻やスマホ📱などのプロセッサ(MPU)の場合、OS上で複数のアプリケーションを複数のCPUに分散させて処理するため、全てのCPUが同じ機能・性能である方が制御し易いので、SMPを使う事が一般的です。
この様な背景から、Moscoviumシリーズでも、SMP型のデュアルコア版をラインアップしていました。
一方、何らかの意図をもって、「○○用途にCPU1、□□用途にCPU2」等と、用途を限定したり、複数のCPU間に主従関係があって分業したりする用途では、AMPにした方が効率が高い場合が多いのです。
マイコンなどの組み込み用途で使う並列処理システムに於いて、CPU1はデータ処理、CPU2は周辺回路・モジュールの制御、など、分業体制で処理しようとする場合には、複数のCPUが必ずしも同じ機能・性能である必要がありません。
AMPの使い所(例):
それぞれに最適な、別種類のCPUを適材適所で使う事によって、論理規模縮小、消費電力低減などの恩恵を得ることができて有利となります。
リソースは有限なのです。ここで着目するリソースとは、主に論理規模のことを指します。
ただ、マイコンの処理能力を上げようとすると、論理規模が増大する傾向にあるため、処理能力の高低と論理規模の大小は切り離して議論することができません。また、一般に、論理規模の増大 → 実装面積の増大 → 既成容量の増大 → 充放電電流の増大 → 消費電力の増大、という連鎖があるので、論理規模の大小と消費電力の高低も、切り離すことができません。
なお、Cmod A7ボード(FPGA)の論理規模(LUT数)は、最大20,800個です。その数を超える論理は、このFPGAボードへ実装することができません。
想像してみてください。複雑な信号処理は、高機能・高速なNihonium-SSが専念して処理、周辺回路やモジュールの制御は別なCPUにやらせたい、と考えてみます。
Nihonium-SSは、下表の通り巨大なコアです。
CPUコア | 論理規模 | |
Tennessineコア | 8ビットデータパス | 約1,000LUT |
Moscoviumコア | 16ビットデータパス | 約2,500LUT |
Moscovium-SSコア | 16ビットデータパス、スーパスケイラ | 約5,200LUT |
Nihoniumコア | 32ビットデータパス | 約3,500LUT |
Nihonium-SSコア | 32ビットデータパス、スーパスケイラ | 約8,500LUT |
上表はCmod A7ボード(Xilinx XC7A35T FPGAチップ)に於ける、CPUコア1個当たりのLUT数です。もし、SMPデュアルコアにすると、×2倍のLUT数が消費されます。
最大のNihonium-SSコアは、CPUを2個使うだけで17,000LUTにもなりますが、Cmod A7ボードの最大LUT数20,800個ですので、周辺のバスステートコントローラ、割り込みコントローラ、その他I/Oユニットで必要となるLUT数を鑑みると、論理規模的にはギリギリ載るかどうか??と言ったところです。
ここで、2個目のCPUは、周辺回路の制御だけ実行すれば良く、それほどパフォーマンスは要らないとしたらどうでしょうか?2個目のCPUとしては、小さなCPUコアである、オリジナル8ビットCPUコアTennessineで十分ではないでしょうか?
Nihonium-SSコア+Tennessineコア≒9,500LUTですので、Cmod A7ボードの最大20,800LUTに対して十分余裕ができます。これが、MoscoviumシリーズでAMPデュアルコアを実装する最大の利点です。
AMPデュアルコアでは、CPU1側がメインCPU、CPU2側をサブCPUという位置づけとします。
Moscoviumマイコンは既に現時点でSMPデュアルコアに対応できているので、2個目のサブCPUを1個目のメインCPUと異なる種類のコアで実装できるコンパイルオプションを追加するだけで終了です。
等と油断していたところ、命令ROMユニットが引っ掛かりました。
命令ROMは、スーパスケイラ版CPUでは32ビットフェッチ、通常版CPUでは16ビットフェッチである必要があり、fbcmdlと言う信号で切り替えていました。fbcmdl信号はCPU1側とCPU2側で共通して1本しか用意していなかったため、スーパスケイラ版と通常版のAMPデュアルコアを構成した時に干渉してしまいました。
幸い、fbcmdl信号を、fbcmdl1,fbcmdl2の2本に拡張する小修整で対処できました。
そもそも、サブCPU側に高性能なCPUコアが必要なケースならばSMPと大差ないので、従来通りSMPデュアルコア版を使うのが吉です。通常は、サブCPU側には処理能力が求められず、小規模・低消費電力等が求められるため、TennessineまたはMoscoviumを想定しておくこととしました。
この時、サブCPUとしてのMoscoviumでは、コプロセッサなどのコンパイルオプションには対応せず、乗算コプロセッサMULC16だけは搭載しておくこととします。
また、これまでTennessineのSMPデュアルコアには対応していませんでしたが、今回、TennessineがサブCPU側となるAMPデュアルコアに使用される場合があるため、状態レジスタsrのID[1:0]フィールドを新設します。
以上まとめて、設定可能なデュアルコアの組み合わせは以下表の通りとなります。
Dual core | CPU1 | Compile option | |||||
Ts | Mc | Mc-SS | Nh | Nh-SS | |||
CPU2 SMP |
Ts | × | − | − | − | − | |
Mc | − | ○ | − | − | − | MCOC_DUAL | |
Mc-SS | − | − | ○ | − | − | MCOC_DUAL | |
Nh | − | − | − | ○ | − | MCOC_DUAL | |
Nh-SS | − | − | − | − | △ | MCOC_DUAL | |
CPU2 AMP |
Ts | × | ○ | ○ | ○ | ○ | MCOC_DUAL & MCOC_DUAL_AMP_TS |
Mc | × | ○ | ○ | ○ | ○ | MCOC_DUAL & MCOC_DUAL_AMP_MC | |
Mc-SS | − | − | − | − | − | ||
Nh | − | − | − | − | − | ||
Nh-SS | − | − | − | − | − |
凡例:
表の作成中、どこまで「△」を付けるべきか?と言う点には引っ掛かりました。周辺I/Oユニットの論理規模次第では、MoscoviumのSMPデュアルコアだって、LUT数を超過してしまう場合は有り得るためです。「△」は、「LUT数超過の可能性が高い」と言うのが、より正確な表現かと思われます。
更に言うなら、「○」でも、「周辺I/Oユニットの構成次第では、LUT数超過の場合有り」です。
コンパイルオプションは、表の「Compile option」欄に示しておきました。MCOC_DUAL_AMP_*オプションを設定する時には、同時にMCOC_DUALの設定も必要です。また、MCOC_DUAL_AMP_*オプションを複数設定した場合の優先順位は、MCOC_DUAL_AMP_TS>MCOC_DUAL_AMP_MCとしてあります。
Moscoviumマイコンのデュアルコアでは、メインCPUをCPU1、サブCPUをCPU2とナンバリングして呼称します。
CPU状態レジスタsrのID[1:0]フィールドからは、定数としてID番号が読み出せる機構となっており、CPUnのnに相当する数値を読み出すことができます。更に、シングルコア版とデュアルコア版を切り分けられる様、シングルコア版ではSr[ID]=0が読み出されるようにしてあります。
今回追加したAMPデュアルコアですが、シングルコア版とも、SMPデュアルコア版とも、プログラムを含めて使い方が根本的に異なるため、AMPデュアルコアであることを判別できる様、メインCPUのSr[ID]=3が読み出せる様に変更しました(下表参照)。
Sr[ID]フィールド | メインCPU | サブCPU |
シングルコア | 0 | − |
SMPデュアルコア | 1 | 2 |
AMPデュアルコア | 3 | 2 |
Sr[ID]=3が読み出せた場合、「トリプルコアのCPU3」では無いのでご注意ください。なお、ID=3が読み出せても、呼称は従来通りCPU1(メインCPU)とします。
上の表を言葉に起こしてみると、以下の通りです。
AMPデュアルコア版として、以下2型名を新規に追加しました。
搭載しているI/Oユニットに関しては、こちらの型名一覧表でご確認ください。
Cmod A7ボード用Moscoviumマイコンの設計データ(Vivadoプロジェクト)は、GitHubにて配布しております。以下バナーよりアクセスしてください。
ダウンロード方法などについては、トップのREADME.mdをご覧ください。
デザイン(回路)をCmod A7ボードに書き込む手順については、こちらをご確認ください。
なお、今回までに以下のI/Oユニットを移植してリリースしました。
今回リリースしたI/Oユニットによって、以下の型名が解禁されました。
これにて、コプロセッサを含むCPU周りの移植については、全て終了しました。
新たに追加したAMPデュアルコア版の2型名について、コンパイルして確認しておきます。まずは、Nihonium-SSとTennessineのAMPデュアルコア、NSOC113NT0816です。
コンパイル結果:
Nihonium-SSが約8,500LUT、S-FPUが約1,400LUTなので。SMP化すると全体で約22,500LUTとなり、Cmod A7ボードではLUT数が不足、実装不可能(もっと論理規模の大きなFPGAが必要)です。
一方、2個目のCPUをTennessineとしたことで、上に示した結果の通りです。Tennessineが約1,000LUTなので、デュアルコア化してもLUT数に不足なく、実装可能と、なりました。
今度は、Moscovium-SSとMoscoviumのAMPデュアルコア、MSOC115MM4408です。
コンパイル結果:
Moscovium-SSが約5,200LUT、MULC16が約50LUT(+乗算器マクロ×3個)、DIVC32が約600LUT、H-FPUが約650LUT、Moscoviumが約2,500LUTなので、SMP化も、まだ何とか可能な組み合わせです。AMP化したことで論理規模が小さくなり、他のユーザ論理などを追加できる余地が広がりました。
以下リンクの通り改訂したAMPデュアルコア対応のCPU判定プログラムを使ってシミュレーション確認だけしておきたいと思います。
CPU判定プログラム:mcoc_cpu_recg.asm
AMPデュアルコアでも、SMPデュアルコアと同様にROMデータは共通で、かつ、Moscoviumシリーズはリセット解除後、0x0000番地のプログラムをフェッチして実行開始します。リセット解除後、メインCPU/サブCPU共、同じ命令ROMの同じアドレスからフェッチして実行するため、上にリンクしたプログラムでCPU種を判定し、適切なプログラムコードに分岐させます。
シングルコア版CPU種の判定方法はこちらに解説があります。上にリンクしたプログラムはデュアルコア版に拡張した物です。
以下、シミュレーション結果です。Vivadoを使ったシミュレーション実行方法は、こちらをご確認ください。
シミュレーションサンプル:nsoc113nt0816.vh
CPU1: Nihonium-SS core
CPU2: Tennessine core
Test Pass
CPI: 571/ 232( 158)= 2461/1000
finish: 42680 ns
シミュレーションサンプル:msoc115mm4408.vh
CPU1: Moscovium-SS core
CPU2: Moscovium core
Test Pass
CPI: 563/ 239( 164)= 2355/1000
finish: 42360 ns
どのCPUと、どのCPUのAMPまたはSMPかを知っていてプログラミングする場合は、CPU種の判定までしなくても、状態レジスタsrのIDフィールドだけで判定して分岐可能です。その辺はお好みで使い分けてください。
組み込み用途のマイコンとしては、SMPよりもAMPの方が使い易いのではないでしょうか?その割には、ESP32に象徴されるように、SMPデュアルコアが多いのですよね……。2個のCPUコアが異なってしまう事によって、開発環境が複雑化するのを嫌っているのでしょう。Moscoviumシリーズは同じ命令コード(開発環境)が使用できるので、その点の心配は無用です。