RISC-V の実装である Rocket-Chip を改造して、外部にSRAMを接続してそこにプログラムを置き、RISC-V Rocket-Chipからプログラムをフェッチして実行できるようにする。
Rocket-Chipの概観はこうだ。 Rocket-Chip はTileと呼ばれるコアの部分と、そこから外へ出たバスで構成されている。 バスの外にはいろんなデバイスやメモリが接続されているのだが、そのうちの一つにはAXIバスで接続された巨大なメモリが存在している。
Rocket-Chipのデフォルトのメモリマップは以下のようになっている。 これは、生成時のログから取得したものだ。
Generated Address Map 0 - 1000 ARWX debug-controller@0 3000 - 4000 ARWX error-device@3000 10000 - 20000 R XC rom@10000 2000000 - 2010000 ARW clint@2000000 c000000 - 10000000 ARW interrupt-controller@c000000 60000000 - 80000000 RWX mmio@60000000 80000000 - 90000000 RWXC memory@80000000
RISC-V Rocket-Chipのブートローダ
Rocket-ChipはSiFiveのFreedom SoCと同様に、最初にブート専用のROMから命令がフェッチされ、そこから外部メモリにフェッチが飛ぶようになっている。
このブート専用のROMはBootROM.scala
で記述されていて、どのプログラムを読み込むかはcoreplex/Config.scala
に設定されている。
coreplex/Config.scala
にはイメージファイルの場所が設定されており、デフォルトではbootrom/boot.img
なので、これを切り替えることで任意のブートプログラムを実行することができる。
ただし、このBootROMはコンパイルした時点でバイナリをハードワイヤに埋め込んでしまうので、コンパイル後の修正はできない。
書き換えるときは何度も再合成する必要がある。
diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index a6d6068..06db207 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -25,7 +25,7 @@ class BaseCoreplexConfig extends Config ((site, here, up) => { case MemoryBusKey => MemoryBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes)) // Additional device Parameters case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=4096) - case BootROMParams => BootROMParams(contentFileName = "bootrom/bootrom.img") + case BootROMParams => BootROMParams(contentFileName = "../program/rocket_boot/bootrom.img") case DebugModuleParams => DefaultDebugModuleParams(site(XLen)) })
上記のデザインでは、rocket_boot/bootrom.img
を設定しているが、このコードは以下のようになっており、0x8000_0000にジャンプしてプログラムを実行するようになっている。
ちなみに、ついでにスタックポインタを設定している。sp
のデフォルト値は0x80001000だ。
- rocket_boot/bootrom.S
#define DRAM_BASE 0x80000000 .section .text.start, "ax", @progbits .globl _start _start: li s0, DRAM_BASE csrr a0, mhartid la a1, _dtb jr s0 .section .text.hang, "ax", @progbits .globl _hang _hang: csrr a0, mhartid la a1, _dtb li sp, 0x80010000 li a2, 0x80000000 jr a2 fin_loop: j fin_loop
AXI4RAMにプログラムをロードして実行する
上記のメモリマップが示している通り、接続されているAXIRAMにアクセスするためには0x8000_0000 - 0x9000_0000にアクセスすればよいし、この領域はXフラグ(フェッチ可能領域)も立っているためプログラムを配置しても問題ない。
このAXIRAMの実体は、Rocket-ChipのVerilog-HDL生成時に同時に生成されるBehavior SRAMのVerilog-HDLファイルだ。
下記のreadmemh
を追加することで、simple_main.hexが0x8000_0000から配置される。
- freechips.rocketchip.system.DefaultConfig.behav_srams.v
module mem_ext( input W0_clk, input [24:0] W0_addr, input W0_en, input [63:0] W0_data, input [7:0] W0_mask, input R0_clk, input [24:0] R0_addr, input R0_en, output [63:0] R0_data ); reg reg_R0_ren; reg [24:0] reg_R0_addr; ... initial begin $readmemh ("../../../program/simple_main/simple_main.hex", ram); end endmodule
シミュレーションすると、0x8000_0000からブートできるようになった。
... C0: 116 [1] pc=[0080000018] W[r11=0000000000000064][1] R[r 0=0000000000000000] R[r 4=ffffffffdeadbeef] inst=[06400593] li a1, 100 C0: 117 [1] pc=[008000001c] W[r 0=0000000000000003][1] R[r15=0000000000000000] R[r16=0000000000000003] inst=[0307e6bb] remw a3, a5, a6 C0: 122 [1] pc=[0080000020] W[r 0=0000000000000005][1] R[r15=0000000000000000] R[r10=0000000000000005] inst=[02a7e63b] remw a2, a5, a0 C0: 123 [1] pc=[0080000024] W[r 0=0000000000000000][0] R[r13=0000000000000000] R[r 0=0000000000000000] inst=[0000e291] bnez a3, pc + 4 C0: 124 [1] pc=[0080000026] W[r14=0000000000000003][1] R[r14=0000000000000000] R[r 3=0000000000000007] inst=[0000270d] addiw a4, a4, 3 C0: 128 [1] pc=[0080000028] W[r 0=0000000000000000][0] R[r12=0000000000000000] R[r 0=0000000000000000] inst=[0000e211] bnez a2, pc + 4 C0: 129 [1] pc=[008000002a] W[r14=0000000000000008][1] R[r14=0000000000000003] R[r 5=0000000000000007] inst=[00002715] addiw a4, a4, 5 C0: 130 [1] pc=[008000002c] W[r14=0000000000000008][1] R[r14=0000000000000008] R[r15=0000000000000000] inst=[00009f3d] addw a4, a4, a5 C0: 131 [1] pc=[008000002e] W[r15=0000000000000001][1] R[r15=0000000000000000] R[r 1=0000000000000003] inst=[00002785] addiw a5, a5, 1 C0: 132 [1] pc=[0080000030] W[r 0=0000000000000000][0] R[r15=0000000000000001] R[r11=0000000000000064] inst=[feb796e3] bne a5, a1, pc - 20 C0: 136 [1] pc=[008000001c] W[r 0=0000000000000003][1] R[r15=0000000000000001] R[r16=0000000000000003] inst=[0307e6bb] remw a3, a5, a6 C0: 141 [1] pc=[0080000020] W[r 0=0000000000000005][1] R[r15=0000000000000001] R[r10=0000000000000005] inst=[02a7e63b] remw a2, a5, a0 C0: 142 [1] pc=[0080000024] W[r 0=0000000000000000][0] R[r13=0000000000000001] R[r 0=0000000000000000] inst=[0000e291] bnez a3, pc + 4 C0: 146 [1] pc=[0080000028] W[r 0=0000000000000000][0] R[r12=0000000000000001] R[r 0=0000000000000000] inst=[0000e211] bnez a2, pc + 4 ...