RISC-VのLinuxブート環境を構築したので、次にこれをRTL環境で実行している。
ChipyardやSpikeの環境では、BootROMに、最初のブートシーケンス及びDevice Treeの情報がバイナリ形式で格納されている。 これをどのように作成するのかについてまとめておく。
- ブートシーケンスを用意する。今回はRV64用のみ。
.section .text _init: .word 0x00000297 # auipc t0,0x0 .word 0x02028593 # addi a1,t0,24 # 1018 <dtb> # la a1, dtb csrr a0, mhartid ld t0, 24(t0) jr t0 .word 0 .word 0x80000000 # start PC .word 0x00000000 # start PC dtb:
ちなみに、AUIPC
とADDI
をアセンブリ命令ではなく機械語で挿入したのは、Spikeと完全動作を一致させるために中間変数で使用されるレジスタが変わることを防ぐため。
以下のコマンドでブートシーケンスを含んだbinaryファイルを用意する。
riscv64-unknown-elf-as bootrom.S -o bootrom.o riscv64-unknown-elf-ld bootrom.o -o bootrom.elf -Tlink.ld objcopy -I elf64-little -O binary --only-section .text bootrom.elf bootrom.bin
- Device Treeファイルを作成する
テンプレートとなるDevice Tree Fileを用意しておく。
dts_skeleton.dts
/dts-v1/; ... #size-cells = <0>; timebase-frequency = <10000000>; CPU0: cpu@0 { device_type = "cpu"; reg = <0>; status = "okay"; compatible = "riscv"; riscv,isa = "rv|XLEN||EXTENSION|"; mmu-type = "riscv,|SVMODE|"; riscv,pmpregions = <16>;
テンプレートの一部を置き換えて、コンフィグレーションにあったDevice Treeファイルを置き換える。
sed 's/|XLEN|/64/g' dts_skelenton.dts | \ sed 's/|EXTENSION|/imc/g' | \ sed 's/|SVMODE|/sv39/g' > dts_skelenton_tmp.dts dtc -@ -O dtb dts_skelenton_tmp.dts -o dts_rv$(XLEN)$(EXT).dtb
- ブート用バイナリの作成
最後に、これをつなぎ合わせてブート用のバイナリを作成する。ダミーファイルを入れているのは自分のRTLシミュレーション環境の問題で、本来は必要ないはず。
cat bootrom.bin dts_rv64imc.dtb dummy.txt > bootrom.img objcopy -I binary -O verilog --verilog-data-width 16 bootrom.img bootrom.hex
こうして、ブート用のHEXファイルが作成されるので、$readmemh
によりROMに格納するわけだ。