-
Notifications
You must be signed in to change notification settings - Fork 101
jp arch binary
このドキュメントでは,RSDのバイナリに関する様々な情報について説明します.
RSDはバイナリに一般的なelfファイルではなくhex形式のメモリイメージを使用します. これは,elfファイルを直接メモリに展開するプログラムローダーが存在しないためです.
hex形式メモリイメージは,1行あたり16Bのhex値を持ち,1行目から順にLMA(Load Memory Address) 0x0以降にロードされるフォーマットで作成されます. 1行あたりのデータ量が16Bである理由は,このメモリイメージがシミュレーション時に直接ロードされるメインメモリのデータアレイの幅が16Bで,それに合わせるためです.
RSDのバイナリ生成は以下のフローでソースコードをhex形式のメモリイメージにすることを意味します.
- gccとldを用いてソースコードからelfファイル(code.elf)を生成
- objcopyを用いてelfファイルからバイナリのメモリイメージ(code.bin)を生成
- Pythonスクリプトを用いてcode.binからhex形式のメモリイメージ(code.hex)を生成
詳細はMakefile(Asmプログラム用)およびMakefile(Cプログラム用)を参照してください.
バイナリの構成はリンカースクリプトに定義されています.
バイナリは.textや.dataなど複数のセクションから構成され,それぞれがVMA(Virtual Memory Address)空間の特定の領域にマップされます. RSDのVMA空間にはROM領域とRAM領域があり,バイナリの.textセクションなどの読み出し専用セクションはROM領域に,.dataなどの読み書きセクションはRAM領域に割り当てられます. 具体的なVMA空間のアドレスと領域,割り当てられるセクションの関係は以下の通りです.
Virtual Address | 内容 | 割り当てられるセクション |
---|---|---|
0x0000_1000 ~ 0x0000_FFFF | ROM | .text, .rodata, .srodata |
0x8000_0000 ~ 0x8003_FFFF | RAM | .data, .bss |
バイナリのすべてのセクションは,まず始めにRSD外のプログラムローダーによってROM領域にロードされます. つまり,VMA空間ではRAM領域に割り当てられた.dataセクションなどもすべてROM領域にロードされます. ここで各セクションがROM領域にロードされる際のアドレスをLMA(Load Memory Address)と呼びます. RSD外部のプログラムローダーの実装は,RSDの動作環境ごとに以下の通りです.
動作環境 | プログラムローダー |
---|---|
QuestaSim | SystemVerilog test bench code initializes the ROM using $readmemh |
Verilator | C++ test bench code directly initializes the ROM |
Vivado(Functional) | SystemVerilog test bench code initializes the ROM using $readmemh |
Vivado(Post-synthesis) | Vivado synthesizes the ROM with a code.hex using $readmemh |
Xilinx Zynq FPGA | C++ loader on an ARM host processor loads a code.hex |
この仕様によりRAM領域に割り当てられたセクションはVMA≠LMAとなるため,バイナリがロードされた後にROM領域からRAM領域へのコピーが必要になります. 具体的には,RSDはmain関数に入る前のスタートアップルーチンで.dataセクションをROM領域からRAM領域にコピーし,.bssセクションが割り当てられたRAM領域を初期化します. このコピー操作の実装はこのファイルにあります. 一方,ROM領域に割り当てられるセクション(.textなど)はVMA=LMAとなるように設定されるため,コピーなどは不要です.
まとめると,RSDの起動時のバイナリ(code.hex)のロードは以下のフローで行われます.
- RSD外部のプログラムローダーがcode.hexをLMAで設定されたROM領域に展開しRSDをリセット
- RSDがcode.hex内のスタートアップルーチンで.dataセクションをLMAで設定されたROM領域からVMAで設定されたRAM領域にコピー
- RSDが同スタートアップルーチンで.bssセクションのVMAで設定されたRAM領域を初期化
- RSDがmain関数へジャンプしてプログラム実行スタート