RISC-V の実装であるFreedom E300 Everywhere を改造して、外部にSRAMを接続してそこにプログラムを置き、RISC-V Rocket-Chipからプログラムをフェッチして実行できるようにする。
オリジナルの構成では、Freedom E300 EverywhereではQSPIが乗っていた部分を取り払って、SimpleSRAMというChiselで記述したモジュールを置き、そこにプログラムを配置してRISC-V Rocket-Coreからフェッチしてもらう。
RISC-Vプログラムの記述
あまり詳しいことはよくわかっていないが、 Freedom E300 Everywhereに搭載されているRocket-Chipは以下の2ステップでプログラムを実行するようになっている。
- リセット後は0x10000に配置されたBootROMから初期プログラムをフェッチする(だいたい、外部メモリ領域へのメモリフェッチが入るような、ジャンプコードが入っている)
- 外部AXIメモリやDDR3-SDRAMなどの領域から、プログラムをフェッチする。
オリジナルのE300では、QSPIの領域(0x2000_0000)にジャンプし、Linuxなりベアメタルなりのプログラムをロードするようになっている訳だ。
この部分にSimpleSRAMという自作のChiselモジュールを置き、RAMの部分を$readmemh
でhexファイルをロードして、プログラムを読み込めるようにしよう。
- 記述したプログラム (simple_main.c) ※ ちょっとだけFizzBuzzっぽい。
int simple_main () { (*(volatile unsigned int *)0x20000100) = 0xdeadbeef; int total = 0; for (int i = 0; i < 100; i++) { if ((i % 3) == 0) total += 3; if ((i % 5) == 0) total += 5; total += i; } (*(volatile int *)0x20000104) = total; return 0; }
これをコンパイルし、SimpleSRAMにロードするようにしておく。
initial begin $readmemh("../../../program/simple_main/simple_main.hex", tb_sifive_freedom.duv.simpleRAMs_0.memory); end
注意点1. SimpleSRAMに接続されるTileLinkはExecutable属性を付けておく
TileLinkの実装に慣れないと、本当にどこで設定されているのかわからない。SimpleSRAMのTileLinkの設定で、executable
属性をtrueにしておく。
Seq(TLManagerParameters( address = AddressSet.misaligned(c.address, c.depth*beatBytes), resources = new SimpleDevice("ram", Seq("msyksphinz,simpleRAM")).reg("mem"), regionType = RegionType.UNCACHEABLE, executable = true, supportsGet = TransferSizes(1, beatBytes), supportsPutPartial = TransferSizes(1, beatBytes), supportsPutFull = TransferSizes(1, beatBytes), fifoId = Some(0))), // requests are handled in order
注意点2. SimpleSRAMを$readmemh
を使用する場合は、RANDOMIZE_MEM_INIT
define属性を解除する
これを解除しないと、せっかく$readmemh
でメモリを初期化したのに、またランダム値で初期化されてしまう。これも最初気がつかなくてハマった。
実行結果
上記の設定を施した上でプログラムをコンパイルしSRAMに配置、RTLシミュレーションを行った。 Rocket-Chipではシミュレーション結果が表示されるようになっている。
ちょっとわかりにくいが、8220 cycle で最後の計算をしてメモリ領域にストアしている。きちんと実行できていることが確認できた。
しかし、8000サイクル程度かかっているのはちょっとヒドいなあ。
C0: 31 [1] pc=[00010000] W[r10=00000000][1] R[r 0=00000000] R[r20=e4a715cb] inst=[f1402573] csrr a0, mhartid C0: 32 [1] pc=[00010004] W[r 5=20000000][1] R[r 0=00000000] R[r 0=00000000] inst=[200002b7] lui t0, 0x20000 C0: 33 [1] pc=[00010008] W[r 0=0001000c][1] R[r 5=20000000] R[r 0=00000000] inst=[00028067] jr t0 C0: 34 [0] pc=[00010008] W[r 0=0001000c][0] R[r 5=00000000] R[r 0=e4a715cb] inst=[00028067] jr t0 C0: 35 [0] pc=[00010008] W[r 0=0001000c][0] R[r 5=00000000] R[r 0=e4a715cb] inst=[00028067] jr t0 ... C0: 8217 [0] pc=[20000028] W[r 0=00000000][0] R[r12=000013bd] R[r 0=00000007] inst=[0000e211] bnez a2, pc + 4 C0: 8218 [0] pc=[20000028] W[r 0=00000000][0] R[r12=000013bd] R[r 0=00000007] inst=[0000e211] bnez a2, pc + 4 C0: 8219 [0] pc=[20000028] W[r 0=00000000][0] R[r12=000013bd] R[r 0=00000007] inst=[0000e211] bnez a2, pc + 4 C0: 8220 [1] pc=[2000002c] W[r14=00001420][1] R[r14=000013bd] R[r15=00000063] inst=[0000973e] add a4, a4, a5 C0: 8221 [1] pc=[2000002e] W[r15=00000064][1] R[r15=00000063] R[r 1=00000063] inst=[00000785] addi a5, a5, 1 C0: 8222 [1] pc=[20000030] W[r 0=00000000][0] R[r15=00000064] R[r11=00000064] inst=[feb796e3] bne a5, a1, pc - 20 C0: 8223 [1] pc=[20000034] W[r15=20000000][1] R[r 0=00000000] R[r 0=00000000] inst=[200007b7] lui a5, 0x20000 C0: 8224 [1] pc=[20000038] W[r 0=20000104][0] R[r15=20000000] R[r14=00001420] inst=[10e7a223] sw a4, 260(a5) C0: 8225 [1] pc=[2000003c] W[r10=00000000][1] R[r 0=00000000] R[r 0=00001423] inst=[00004501] jr a0 C0: 8226 [1] pc=[2000003e] W[r 0=20000040][1] R[r 1=00000000] R[r 0=00000000] inst=[00008082] mv ra, zero