ComProcのハーバードアーキテクチャ化
命令長は固定16ビット幅
必然的に即値は16ビットより小さくなる
PUSH uimm15
CALL simm12
JZ simm12
などなど
FPGAのBRAMの特徴
多くのFPGAでBRAMは9ビット単位の幅になっている
命令長を18ビット(9×2)にするとちょうどいい!?
ということで18ビットで命令を設計してみる
code:18ビット命令の設計
mnemonic |17 12 7 0|
---------------------------------
PUSH uimm16 |11 uimm16 |
CALL uimm14 |0000 uimm14 |
JMP simm12 |000100 simm12 |
JZ simm12 |000101 simm12 |
SUB fp,uimm12|000110 uimm12 |
resv |000111xxxxxxxxxxxx|
LD1 X+uimm12 |0010xx uimm12 |
ST1 X+uimm12 |0011xx uimm12 |
LD X+uimm12 |0100xx uimm11 0|
ST X+uimm12 |0100xx uimm11 1|
PUSH X+uimm12|0101xx uimm12 |
resv |0110xxxxxxxxxxxxxx|
etc |0111xxxxxxxxxxxxxx|
binop uimm10 |10 ALU6 uimm10 |
帰りのチケットはお持ちですか?
CALL命令は関数を呼び出すのにしか使わない = 遠方に飛ぶ
JMP/JZは制御構文内でのジャンプにしか使わない = 近郊
海外旅行では往路チケット(戻り先アドレス)が必要!
メモリレイアウト
Tang Nano 9K(GW1NR-9C)に搭載のBRAMは468Kbits
468Kbits/9 = 52Kbytes (1byte = 9bits)
.data = 16Kbytes (16K×8bits)
アクセスサイズはcharおよびint
.text = 16Kwords (16K×18bits)
アクセスサイズはwordのみ
.dataのレイアウト
先頭256バイト領域は周辺機能のMMIO
その後はグローバル変数
.data末尾は関数のスタックフレーム
末尾から0方向に向かって成長
FPの初期値は0x4000(16Kbytes)
関数のプロローグで sub fp, <frame size> とする
プログラム転送
18ビットで1命令
UARTでの命令受信モード
simpleモード:3バイト受信→1命令書き込みを繰り返す
packedモード:9バイト受信→4命令書き込みを繰り返す
55 aa <pmem_size_hi> <pmem_size_lo> <dmem_size_hi> <dmem_size_lo> の4バイトをプログラム受信開始マークとする
追加で転送サイズを表す4バイトを付加する
pmem_size_hi[7:6]は転送モード
simple = 0b00
packed = 0b01
pmem_size_hi[5:0]*256 + size_loは転送ワード数
プログラム転送は18ビットを1ワードとして転送する
packedモードの場合、size_loは4の倍数でなければならない
dmem_size_hi*256+dmem_size_loは転送ワード数
データ転送は16ビットを1ワードとして転送する
55とaaの間に時間制約があるが、aaと<size_hi>の間には制約はない
用語「data」
「data」が多くの意味を持ちすぎている
UARTの受信バッファもrx_dataだし、「プログラム領域」に対する「データ領域」の意味も持つ。
オブジェクトファイル
ノイマン型の場合、同じアドレス空間にデータとプログラムを置くので、ベタバイナリで十分だった
実際、単純なhexファイルを用いていた
このhexファイルを0x4000を先頭としてRAMに読み込むだけ
ハーバード型ではデータとプログラムを異なる空間に置くので、両者を区別できるフォーマットが必要
あるいは、データとプログラムを別ファイルにするとか
例えばipl_dmem.hex, ipl_pmem.hex
セクション指定
従来、文字列リテラルはプログラムの後ろに db 命令で置いていた
プログラムメモリに置いたデータは参照できないので、データメモリに置くようにする
アセンブリファイル内でセクション指定をしたい!
code:セクション指定の例.s
section .data
STR_0:
db 0x43,0x4d,0x44,0
section .text
add fp,256
call main
…
初期値付きグローバル変数も.dataセクションに置く
セクションをオブジェクトファイルとしてどう表現するかはまた別の話
ELFやCOFFなど、よくあるやり方は1つのオブジェクトファイル内でセクションを区別する
セクションごとにファイルを分けるなどでも良いはず