公開日:2024/09/21
title.png

31st Season


#31-9 ROMが狭い

 Cmod A7ボード(FPGA)を使って開発しているオリジナル16ビットCPUコアMoscoviumのメモリですが、命令コードを格納するためのROMと、演算や処理に使aうデータを記憶するRAMから構成されています。
 今回のテーマは、命令コード格納用のROMに関する課題の克服です。

ROM容量

 先般、Moscoviumの開発環境にBlocklyを使用可能な様に整備したところ、コードサイズが思った以上に大きくなっていました。

  「#31-6 Moscoviumの開発環境(カスカス)

  「#31-7 Moscoviumの開発環境(モジモジ)

    コードサイズ比較: Blockly版÷アセンブラ版≒2.7倍

 これで済むならまだ良いですが、アセンブラと言う抽象度の低いプログラミング言語から、Blocklyという抽象度の高い開発環境となることで、より複雑かつ、より大規模なプログラム開発が容易になるという特徴があります。
 同じ動作のプログラムでコードサイズ×2.7倍な所に、更に大規模なプログラムを作り始めたら、ROM容量が足りなくなるのではないか?これが今回のテーマのモチベーションです。

メモリマップ

 現在のバスステートコントローラBUSC2040では、最大ROM容量16Kバイトと最大RAM容量40Kバイトを16ビットアドレス空間に配置してあります(下図)。

a282_memmap.png

※上図は、この後の議論を既に反映した新メモリマップであることに留意。旧メモリマップの解説としては、ROM(16KB)/RAM(40KB)と、なっている部分に注目。

 Moscoviumのプログラムカウンタpcは16ビット長なので、最大64Kバイト空間しかアクセスできない所へ、RAM領域とI/Oレジスタ領域を配置する必要があるため、今までのメモリマップでは、ROM容量を拡張する余地がありませんでした。
 と、言うのは正確ではなくて、ROM容量を大きくする場合、代わりにRAM容量を減らすしか手が無い、と言った方が正しいです。

マイコンのROM/RAM容量比率

 そこで、適切なROM/RAM容量比率を決定するため、手持ちのマイコンボードで使われているMCU(Micro Controller Unit)のメモリ容量について調査してみた結果が下表です。

型名 Flash
容量[KB]
RAM
容量[KB]
Flash/RAM
容量比
備考
ATtiny2313A 2 0.125 16  
ATtiny85 8 0.5 16  
ATmega16U2 16 0.5 32 UNO, USB⇔UART変換
ATmega32U4 32 2.5 13 Arduino Micro
ATmega328P 32 2 16 Arduino UNO
STM32F103C8T6 64 20 3 STM32ボード
ATmega2560 256 8 32 Arduino MEGA
SAM3X8E 512 96 5 Arduino DUE

  考察:

 そうか、ぼんやりと思い出しましたよ。Moscoviumの仕様を策定するに当たっては、PCやスマホのMPU(Micro Processing Unit)を意識してしまったのだ、と……。

PCやスマホのMPU

 PCやスマホの場合、所謂メインメモリはRAM(もっと限定すると、SDRAM)で構成されています。
 通常は、補助ストレージ(NAND型Flashメモリが多い)からプログラムコードを読み込み、メインメモリ(RAM)に展開したら、RAMからプログラムをフェッチしながら実行します。

 従って、PCやスマホ(MPU)に要求されるメモリ機能は以下の通りです。

 補助ストレージは別として、メインメモリ(RAM)内にプログラムコードと演算データの両方を保持する必要があるので、大容量のRAMが必要、かつ、大事だと解ります。


 一方、マイコン(MCU)の場合、要求されるメモリ機能は以下の様になります。

 なので、MPUと異なりMCUでは実は、RAMよりROMの方が大量に必要だったのですね。

 全然明後日の方向を眺めながら、Moscoviumの仕様を策定していたんじゃないのかい?これでは破綻するはずです。

ROM容量を拡大する

 そうと解れば、サクッと頭を切り替えて、相応にROM容量を拡大すれば良いのです(1^−^)d。

Moscovium
マイコン
ROM
容量[KB]
RAM
容量[KB]
ROM/RAM
容量比
備考
現状 16 40 0.4 逆転
案1) 32 24 1.3 ROM容量×2倍
案2) 40 16 2.5 STM32ボード(STM32F103C8T6)級
案3) 48 8 6.0 Arduino DUE(SAM3X8E)級

  考察:

 同じマイコン(MCU)である、STM32ボードやDUEのROM/RAM容量比に倣って、最大48KバイトROM、8KバイトRAMまでROM容量を拡大する事とします。

新メモリマップ

 新メモリマップは、下図を参照してください。

a282_memmap.png

 本当に大容量のRAMが必要なアプリケーションがあれば、24ビット拡張アドレス空間に配置した、E-RAM領域(最大128KB)やSRAM領域(512Kバイト)を使うことができます。従って、16ビットアドレス空間の方は、目いっぱいまで命令ROMを配置しました。
 現に、これまで、何10KバイトもRAMが必要となるアプリケーションを組む機会が無かったので、ほとんどのケースでは8Kバイトもあれば十分だと思われます。

コンパイルオプション

 Moscoviumマイコンを設定するコンパイルオプションとして、以下のマクロを追加します。

 命令フェッチ可能なI-RAMですが、「命令コードを配置しない」と決めれば、何ら遜色なく、普通にRAMとして使用可能です(ただし、シングルコア版に限る)。すなわち、RAM(8Kバイト)+I-RAM(4Kバイト)で合計12KバイトのRAMとしても使用可能と言う事ですので、うまく応用すれば、「RAMが足りないよ〜」等という困ったケースには遭遇👽しないはずです。

 コンパイルオプションの具体的な設定方法については、nsoc113by8808.vh等を参考にしてください。

VivadoのRAMマクロ

 VivadoのRAMマクロでは、2冪サイズのRAMマクロが消費されます。

 何とかならなかったのか?と言わざるを得ないショボい仕様ですが、Vivadoの仕様みたいなので致し方ありません。
 無駄を避けるためには、例えば、48Kバイト=32Kバイト+16Kバイトの様に、2冪サイズに分割して作成しなくてはなりません。しかし、何しろROMなので、ROMに記憶するデータをVerilog MEMファイルで指定する必要があります。
 無駄を避けようとROMを分割してしまうと、MEMファイルも分割して作成しなければならず、それはそれで、プログラム開発時の手間を増やし、嬉しくありません。

 64Kバイト消費するRAMマクロの内、48KバイトまではROMとして活用されるため、本当に無駄になるのは16Kバイト分です。MEMファイルの分割など、後々の不都合を考えれば高々16Kバイトの無駄は許容して良いと判断しました。

デザイン

 今回、論理検証用として、48KバイトROMと命令RAM(I-RAM)を搭載したNSOC113BY8808を作成しました。型名規則は、こちらのリンクを参照ください。
 Blockly開発環境でのプログラム開発を前提としているため、スーパスケイラ版Nihonium-SS+単精度浮動小数演算ユニットS-FPUを搭載した、CPU周りの最大強化版です。贅沢(1^^;)。

 Cmod A7ボード用Moscoviumマイコンの設計データ(Vivadoプロジェクト)は、GitHubにて配布しております。以下バナーよりアクセスしてください。

btn_moscovium.png

 Cmod A7ボード(FPGA)への書き込み手順は、こちらのリンクを参照してください。

コンパイル

 48KバイトROMを搭載した、NSOC113BY8808をコンパイル(論理合成・配置配線)してみました。結果は以下の通りです。

 コンパイル結果:

 スーパスケイラ版のNihonium-SS+S-FPUと言う事で、タイミングクリティカルな回路規模が大きいです。このためか、タイミング解析(STA)はギリギリでメットしている感じですね。ほとんど余裕度(Setup Slack)がありません。どの程度の余地があるのかは判りませんが、メットしているのでOKでは、あります。

広々と実験

 今のところ、32Kバイトや48Kバイトもの大きなプログラムは手元に有りません。従って、FPGAに書き込んで動作確認するまでも無く、シミュレーションで動作確認して終了とします。
 Cmod A7ボード(FPGA)を使ったMoscoviumマイコンのシミュレーション手順は、こちらのリンクをご参照ください。

48KバイトROMの検証用プログラム

 シミュレーション専用の、48KバイトROM動作検証用プログラムを以下にリンクしておきます。

  検証用プログラム:mcoc_rom_48k.asm

 Moscoviumマイコンのマクロアセンブラでは、デフォルトで4Kバイトの命令ROM容量を前提としたオブジェクトファイル(Verilog MEMファイル)を生成する様になっています。4Kバイト以外の命令ROMを使用する場合、以下の疑似命令を使って、ROM容量値を指定する必要があります。

  romsiz 48*1024  // 48Kバイトの命令ROM容量を指定


 Blocklyの場合、こちらの変換オプションから、「@rom_siz=48*1024@」を設定してください。
 Moscoviumマイコンは、ROM容量が判ると、RAMの最上位アドレスが判るメモリマップに、なっています。ランタイムライブラリが"@rom_siz=<size>@"変換オプションの設定値を使ってRAMの先頭アドレスを確定し、変数領域を割り当てているため、正しく正確にROM容量を設定してください。

シミュレーション結果

 こちらのプログラムと、NSOC113BY8808のデザインを使ってシミュレーションを実行し、ログを確認してみましょう。

  実験サンプル:シミュレーションログ
  113a
  0224
  5dc0
  4259
  0000
  c000
  d000
  2000
  message #1 at top of ROM
  message #2 at bottom of ROM
  Bmessage #2 at bottom of ROM
  Bmessage #1 at top of ROM
  Test Pass
  CPI: 785/ 532( 40)= 1475/1000
  finish: 51240 ns

 最初に出力された8個の16ビット16進数値は、IDREGユニットのI/Oレジスタ8個を読み出した結果です。

 辺りが、特徴的な読み出し値です。IDREGユニットを使うと、搭載されているROM容量やRAM容量、先頭アドレスなどを知ることができる仕組みです。48KバイトROM選択時のメモリマップはこちらを参照してください。

 その後、「message #1」と「message #2」がログに出力されました。「message #1」はROMの先頭(上位アドレス)付近、「message #2」は48Kバイトに拡張したROMの最下位アドレス付近にdats疑似命令で確保した文字列データを出力した物です。
 「message」と、「Bmessage」が表示されていますが、「message」を表示させるサブルーチンはROMの上位アドレス側、「Bmessage」を表示させるサブルーチンはROMの下位アドレス側に配置しました。

 つまり、上のログにて、以下のROM動作を確認できたことになります。

 詳細な動作内容については、こちらのプログラムでご確認ください。

その他検証

 サンプルプログラムとしては、以上としておきますが、他にも、ROM領域が48Kバイトに拡張したことで変化する、以下の事象についても確認してあります。


 ここまで来て漸く、ROM/RAM容量比率が間違っている、と認識したのですが、全く、何を考えて仕様策定していたんだ?って事ですね……。「間違い」に気が付ける事、「間違い」に気が付いたら臨機応変に修正できる事、そう言う事も大切、と思う今日この頃でした。


btn_arduino.png

btn_prev.png btn_next.png

home