FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

SpikeのPLICとCLINTの実装を確認する

最新のSpikeの実装にアップデートして、PLICとCLINTを動かすためにいろいろやってみる。

LiteXのBIOSを動かしたくて、いろいろやっている。

../spike_dpi/riscv-isa-sim/spike -l --log-commits --dtb=../dts/rv64imafdc.dtb --pc=0 -m0x0:0x100000,0x10000000:0x1000000 ../tests/litex_soc/software/bios/bios.elf

rv64imafdc.dtsは以下のようにして、PLICとCLINTを認識させている。こうしないと、SpikeがPLICとCLINTを識別してくれない。

  soc {
    #address-cells = <2>;
    #size-cells = <2>;
    compatible = "ucbbar,spike-bare-soc", "simple-bus";
    ranges;
    clint@2000000 {
      compatible = "riscv,clint0";
      interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 >;
      reg = <0x0 0x2000000 0x0 0xc0000>;
    };
    PLIC: plic@c000000 {
      compatible = "riscv,plic0";
      #address-cells = <2>;
      interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 >;
      reg = <0x0 0xc000000 0x0 0x1000000>;
      riscv,ndev = <0x1f>;
      riscv,max-priority = <0xf>;
      #interrupt-cells = <1>;
      interrupt-controller;
    };
  };

それでも、0x5b90へのアクセスでトラップが発生してしまう。ここは、アクセス許可しているはずなんだけど...

core   0: 0x0000000000000124 (0x00628c63) beq     t0, t1, pc + 24
core   0: 3 0x0000000000000124 (0x00628c63)
core   0: 0x0000000000000128 (0x0003be03) ld      t3, 0(t2)
core   0: exception trap_load_access_fault, epc 0x0000000000000128
core   0:           tval 0x0000000000005b90
core   0: >>>>  trap_entry
core   0: 0x0000000000000020 (0xfe113c23) sd      ra, -8(sp)
core   0: 3 0x0000000000000020 (0xfe113c23) mem 0x0000000010001ff8 0x0000000000000000
core   0: 0x0000000000000024 (0xfe513823) sd      t0, -16(sp)
core   0: 3 0x0000000000000024 (0xfe513823) mem 0x0000000010001ff0 0x0000000010000000
core   0: 0x0000000000000028 (0xfe613423) sd      t1, -24(sp)
core   0: 3 0x0000000000000028 (0xfe613423) mem 0x0000000010001fe8 0x00000000100001e0
core   0: 0x000000000000002c (0xfe713023) sd      t2, -32(sp)
core   0: 3 0x000000000000002c (0xfe713023) mem 0x0000000010001fe0 0x0000000000005b90
core   0: 0x0000000000000030 (0xfca13c23) sd      a0, -40(sp)
core   0: 3 0x0000000000000030 (0xfca13c23) mem 0x0000000010001fd8 0x0000000000000000

これはいろいろ調べたら、デバイスの登録順序に基づくメモリアクセス領域のオーバラップによるものだった。

0x0000:0x10000にメモリを登録した後、ブートROMとして0x1000を登録して、0x5000あたりを検索すると0x1000のブートROMが引っかかってアクセスエラーとなる。 これの解決策としては、ハードコードされたメモリアクセス領域を無理やり変更して、自分の所望のメモリマップにするしかない。

diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 1a0c8307..8d2c8c76 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -121,9 +121,9 @@ reg_t reg_from_bytes(size_t len, const uint8_t* bytes)

 bool mmu_t::mmio_ok(reg_t paddr, access_type UNUSED type)
 {
-  // Disallow access to debug region when not in debug mode
-  if (paddr >= DEBUG_START && paddr <= DEBUG_END && proc && !proc->state.debug_mode)
-    return false;
+  // // Disallow access to debug region when not in debug mode
+  // if (addr >= DEBUG_START && addr <= DEBUG_END && proc && !proc->state.debug_mode)
+  //   return false;

   return true;
 }
diff --git a/riscv/platform.h b/riscv/platform.h
index 7fffdc84..d85e271f 100644
--- a/riscv/platform.h
+++ b/riscv/platform.h
@@ -3,7 +3,7 @@
 #define _RISCV_PLATFORM_H

 #define DEFAULT_KERNEL_BOOTARGS "console=ttyS0 earlycon"
-#define DEFAULT_RSTVEC     0x00001000
+#define DEFAULT_RSTVEC     0x20000000
 #define CLINT_BASE         0x02000000
 #define CLINT_SIZE         0x000c0000
 #define PLIC_BASE          0x0c000000
@@ -16,6 +16,6 @@
 #define NS16550_REG_IO_WIDTH 1
 #define NS16550_INTERRUPT_ID 1
 #define EXT_IO_BASE        0x40000000
-#define DRAM_BASE          0x80000000
+#define DRAM_BASE          0x00000000

 #endif
diff --git a/riscv/sim.cc b/riscv/sim.cc
index f4919c91..f005db9b 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -69,7 +69,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
   for (auto& x : mems)
     bus.add_device(x.first, x.second);

-  bus.add_device(DEBUG_START, &debug_module);
+  // bus.add_device(DEBUG_START, &debug_module);

   socketif = NULL;
 #ifdef HAVE_BOOST_ASIO

これで一応メモリアクセスエラーを回避して進めることができるようになった。 しかし、新しいSpikeはハードコードな部分が結構あって、面倒くさいな...