前回まででPLICについては結構仕様を勉強して、じゃあ次にRTLを作ってみて、テストしてみようということになったのだが、 とりあえず簡単なテストを動かしてみたい。PLICのメモリマップは0xc00_0000なので、ここにアクセスする簡単なテストパタンを作ってみる。
#define PLIC_BASE_ADDR 0xc000000 #define PLIC_SOURCE_BASE_ADDR (PLIC_BASE_ADDR) #define PLIC_PENDING_BASE_ADDR (PLIC_BASE_ADDR + 0x1000) #define PLIC_ENABLE_BASE_ADDR (PLIC_BASE_ADDR + 0x2000) #define PLIC_THRESHOLD_ADDR (PLIC_BASE_ADDR + 0x200000) int plic_reg_rw_test() { *((volatile unsigned int *)(PLIC_SOURCE_BASE_ADDR)) = 0xdeadbeef; *(volatile unsigned int *)(PLIC_SOURCE_BASE_ADDR); *((volatile unsigned int *)(PLIC_PENDING_BASE_ADDR)) = 0xdeadbeef; *(volatile unsigned int *)(PLIC_PENDING_BASE_ADDR); return 0; }
が、Spikeの挙動が異なっており、Spikeは当該メモリ領域へのメモリアクセスは例外処理になっていた。
core 0: 3 0x00000000800025f0 (0x4581) x11 0x0000000000000000 core 0: 3 0x00000000800025f2 (0x4501) x10 0x0000000000000000 core 0: 3 0x00000000800025f4 (0x142000ef) x 1 0x00000000800025f8 core 0: 3 0x0000000080002736 (0xdeadc7b7) x15 0xffffffffdeadc000 core 0: 3 0x000000008000273a (0xeef78793) x15 0xffffffffdeadbeef core 0: 3 0x000000008000273e (0x0c0006b7) x13 0x000000000c000000 // 0xc00_0000へのメモリストアを試行した // ここで例外が発生している core 0: 3 0x0000000080000090 (0x716d) x 2 0x0000000080022780 core 0: 3 0x0000000080000092 (0xe406) mem 0x0000000080022788 0x00000000800025f8 core 0: 3 0x0000000080000094 (0xe80a) mem 0x0000000080022790 0x0000000080022780 core 0: 3 0x0000000080000096 (0xec0e) mem 0x0000000080022798 0x0000000080002f70 core 0: 3 0x0000000080000098 (0xf012) mem 0x00000000800227a0 0x0000000080002940 core 0: 3 0x000000008000009a (0xf416) mem 0x00000000800227a8 0x0000000080000090 core 0: 3 0x000000008000009c (0xf81a) mem 0x00000000800227b0 0x0000000000000000 core 0: 3 0x000000008000009e (0xfc1e) mem 0x00000000800227b8 0x0000000000000000 core 0: 3 0x00000000800000a0 (0xe0a2) mem 0x00000000800227c0 0x0000000000000000
これをどうやって直せばいいのかすっかり忘れていたのだが、とりあえずDTSを改造してみても駄目なようだ。 これはDTSを追加するだけではなく、ちゃんとデバイスを追加しないと駄目なようだ。CLINTがその例である。
void *fdt = (void *)dtb.c_str(); //handle clic clint.reset(new clint_t(procs, CPU_HZ / INSNS_PER_RTC_TICK, real_time_clint)); reg_t clint_base; if (fdt_parse_clint(fdt, &clint_base, "riscv,clint0")) { bus.add_device(CLINT_BASE, clint.get()); } else { bus.add_device(clint_base, clint.get()); }
したがって、同じようにPLICの領域に仮想的なデバイスを作って追加する必要があるようだ。Spikeの挙動をやっと理解できるようになってきた。