FPGA開発日記

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

FPGA開発日記 カテゴリ別インデックス

RISC-VにおけるRVWMOの仕様について読み直す

続きを読む

LiteXのBIOSソフトウェアを独自に構築する方法調査 (2. SpikeのCLINTの動作確認)

  • CLINT : 0x02000000
  • PLIC : 0x0c000000

MIEを設定すると、タイマ割り込みがかかる。

core   0: 3 0x0000000000001760 (0x09313c23) mem 0x0000000010001fd8 0x0000000000000000
core   0: 0x0000000000001764 (0x0c0027b7) lui     a5, 0xc002
core   0: 3 0x0000000000001764 (0x0c0027b7) x15 0x000000000c002000
core   0: 0x0000000000001768 (0x0007a023) sw      zero, 0(a5)
core   0: 3 0x0000000000001768 (0x0007a023) mem 0x000000000c002000 0x00000000
core   0: 0x000000000000176c (0x30046073) csrsi   mstatus, 8
core   0: 3 0x000000000000176c (0x30046073) c768_mstatus 0x0000000a00000008
core   0: exception interrupt #7, epc 0x0000000000001770
core   0: >>>>  trap_entry
core   0: 0x0000000000000020 (0xfe113c23) sd      ra, -8(sp)
core   0: 3 0x0000000000000020 (0xfe113c23) mem 0x0000000010001f38 0x0000000000000170
core   0: 0x0000000000000024 (0xfe513823) sd      t0, -16(sp)
core   0: 3 0x0000000000000024 (0xfe513823) mem 0x0000000010001f30 0x0000000010000b48
core   0: 0x0000000000000028 (0xfe613423) sd      t1, -24(sp)
core   0: 3 0x0000000000000028 (0xfe613423) mem 0x0000000010001f28 0x0000000010000b48
core   0: 0x000000000000002c (0xfe713023) sd      t2, -32(sp)
core   0: 3 0x000000000000002c (0xfe713023) mem 0x0000000010001f20 0x0000000000005d70
core   0: 0x0000000000000030 (0xfca13c23) sd      a0, -40(sp)
core   0: 3 0x0000000000000030 (0xfca13c23) mem 0x0000000010001f18 0x0000000000000880
core   0: 0x0000000000000034 (0xfcb13823) sd      a1, -48(sp)
core   0: 3 0x0000000000000034 (0xfcb13823) mem 0x0000000010001f10 0x0000000020000020
core   0: 0x0000000000000038 (0xfcc13423) sd      a2, -56(sp)
core   0: 3 0x0000000000000038 (0xfcc13423) mem 0x0000000010001f08 0x0000000000000000
core   0: 0x000000000000003c (0xfcd13023) sd      a3, -64(sp)
core   0: 3 0x000000000000003c (0xfcd13023) mem 0x0000000010001f00 0x0000000000000000
core   0: 0x0000000000000040 (0xfae13c23) sd      a4, -72(sp)
core   0: 3 0x0000000000000040 (0xfae13c23) mem 0x0000000010001ef8 0x00000000000001fe
core   0: 0x0000000000000044 (0xfaf13823) sd      a5, -80(sp)
core   0: 3 0x0000000000000044 (0xfaf13823) mem 0x0000000010001ef0 0x000000000c002000

これは誰がタイマを挿入しているのか?PLICかな? riscv-isa-simの実装を確認してみる。

最初に誰かが挿入しているようだ:

mip_csr_t::backdoor_write_with_mask(origin=00000000, mask=00000080, val=00000080).
mip_csr_t::backdoor_write_with_mask. val = 00000080
warning: tohost and fromhost symbols not in ELF; can't communicate with target
core   0: 0x0000000020000000 (0x00000297) auipc   t0, 0x0
core   0: 3 0x0000000020000000 (0x00000297) x5  0x0000000020000000
core   0: 0x0000000020000004 (0x02028593) addi    a1, t0, 32
core   0: 3 0x0000000020000004 (0x02028593) x11 0x0000000020000020
  • csrs.cc
void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept {
  fprintf(stderr, "mip_csr_t::backdoor_write_with_mask(origin=%08lx, mask=%08lx, val=%08lx).\n",
          this->val, mask, val);
  this->val = (this->val & ~mask) | (val & mask);
  fprintf(stderr, "mip_csr_t::backdoor_write_with_mask. val = %08lx\n", this->val);
}

うーん、CLINTが最初にコンストラクタで書きに行っている。

Breakpoint 1, mip_csr_t::backdoor_write_with_mask (this=this@entry=0x555555e4f3a0, mask=mask@entry=128, val=128) at ./riscv/csrs.cc:746
746     void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept {
(gdb) bt
#0  mip_csr_t::backdoor_write_with_mask (this=this@entry=0x555555e4f3a0, mask=mask@entry=128, val=128) at ./riscv/csrs.cc:746
#1  0x00005555558be236 in clint_t::tick (this=this@entry=0x555555e54c00, rtc_ticks=rtc_ticks@entry=0) at ./riscv/clint.cc:115
#2  0x00005555558be354 in clint_t::clint_t (this=0x555555e54c00, sim=<optimized out>, freq_hz=<optimized out>, real_time=<optimized out>) at ./riscv/clint.cc:18
#3  0x00005555558be3f0 in clint_parse_from_fdt (fdt=<optimized out>, sim=0x7fffffffc380, base=0x7fffffffb870, sargs=...) at ./riscv/clint.cc:124
#4  0x00005555558a4fcd in sim_t::sim_t (this=0x7fffffffc380, cfg=<optimized out>, halted=<optimized out>, mems=..., plugin_device_factories=..., args=..., dm_config=..., log_path=0x0, dtb_enabled=true, dtb_file=0x7fffffffd475 "../dts/rv64imafdc.dtb", socket_enabled=false, cmd_file=0x0) at ./riscv/sim.cc:165
#5  0x000055555583daef in main (argc=<optimized out>, argv=<optimized out>) at ./spike_main/spike.cc:528
    clint@2000000 {
      compatible = "riscv,clint0";
      interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 >;
      reg = <0x0 0x2000000 0x0 0xc0000>;
    };

なるほど、mtimemtimecmpが両方ともゼロで、書き込みが割り込みの挿入が行われているのか。

  • clint.cc
void clint_t::tick(reg_t rtc_ticks)
{
  if (real_time) {
   struct timeval now;
   uint64_t diff_usecs;

   gettimeofday(&now, NULL);
   diff_usecs = ((now.tv_sec - real_time_ref_secs) * 1000000) + (now.tv_usec - real_time_ref_usecs);
   mtime = diff_usecs * freq_hz / 1000000;
  } else {
    mtime += rtc_ticks;
  }

  for (const auto& [hart_id, hart] : sim->get_harts()) {
    hart->state.time->sync(mtime);
    hart->state.mip->backdoor_write_with_mask(MIP_MTIP, mtime >= mtimecmp[hart_id] ? MIP_MTIP : 0);
  }
}

とすると、CLINTのデバイスを除去すると割り込みが掛からなくなるのか?

    /*
    clint@2000000 {
      compatible = "riscv,clint0";
      interrupts-extended = <&CPU0_intc 3 &CPU0_intc 7 >;
      reg = <0x0 0x2000000 0x0 0xc0000>;
    };
    */

こうすると、一応割り込みはかからなくなった。次は、LiteXのベンチマークと自作CPUの協調動作シミュレーションで、何が違うのかを確認していこうと思う。

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はハードコードな部分が結構あって、面倒くさいな...

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

前回の続き。exception interrupt #7というのは例外かと思っていたら割り込みだった。

つまり、この割り込みが入った時点でタイマ割り込みが掛かっていたことがわかる。 タイマ割り込みはCLINTが行うはずなので、その辺を確認してみる。

core   0: 3 0x0000000000002b2c (0x01851863)
core   0: 0x0000000000002b3c (0x00813583) ld      a1, 8(sp)
core   0: 3 0x0000000000002b3c (0x00813583) x11 0x00000000100001c0 mem 0x0000000010001e38
core   0: 0x0000000000002b40 (0x0014849b) addiw   s1, s1, 1
core   0: 3 0x0000000000002b40 (0x0014849b) x 9 0x0000000000000018
core   0: 0x0000000000002b44 (0x000b00e7) jalr    s6
core   0: 3 0x0000000000002b44 (0x000b00e7) x 1 0x0000000000002b48
core   0: >>>>  litex_putc
core   0: 0x000000000000316c (0xff010113) addi    sp, sp, -16
core   0: 3 0x000000000000316c (0xff010113) x 2 0x0000000010001e20
core   0: exception interrupt #7, epc 0x0000000000003170
core   0: >>>>  trap_entry
core   0: 0x0000000000000020 (0xfe113c23) sd      ra, -8(sp)
core   0: 3 0x0000000000000020 (0xfe113c23) mem 0x0000000010001e18 0x0000000000002b48
core   0: 0x0000000000000024 (0xfe513823) sd      t0, -16(sp)
core   0: 3 0x0000000000000024 (0xfe513823) mem 0x0000000010001e10 0x0000000010000b48
core   0: 0x0000000000000028 (0xfe613423) sd      t1, -24(sp)
core   0: 3 0x0000000000000028 (0xfe613423) mem 0x0000000010001e08 0x0000000010000b48
core   0: 0x000000000000002c (0xfe713023) sd      t2, -32(sp)
core   0: 3 0x000000000000002c (0xfe713023) mem 0x0000000010001e00 0x0000000000005d70
core   0: 0x0000000000000030 (0xfca13c23) sd      a0, -40(sp)
core   0: 3 0x0000000000000030 (0xfca13c23) mem 0x0000000010001df8 0x000000000000005f
core   0: 0x0000000000000034 (0xfcb13823) sd      a1, -48(sp)
core   0: 3 0x0000000000000034 (0xfcb13823) mem 0x0000000010001df0 0x00000000100001c0
core   0: 0x0000000000000038 (0xfcc13423) sd      a2, -56(sp)

と思ったら、最新のSpikeにはCLINTとPLICが実装されていた。気が付かなかった。 これを確認してみる。

riscv-isa-simをPC=0x0から起動するためには?

ちょっと自作CPUの検証環境を調整したくて、リセット時のPC=0として実行して検証を走らせたいのだが、どうにもSpikeがエラーを出してしまう。

0x0にブートコードを含んでいるELFをロードすると、invalid write to 0のような感じでエラーが出力して実行できない。

これを回避する方法をいろいろ調べていたのだが、どうもSpikeはデフォルトで0x0にデバッグユニットが入っていて、そこにELFを書くことはできないらしい。

bool mmu_t::mmio_ok(reg_t addr, access_type type)
{
  // 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;
}
#define DEBUG_START             0x0
#define DEBUG_END               (0x1000 - 1)

これをコメントアウトして、シミュレーションを実行した。

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

一応シミュレーションが動き始めたようだ。途中で割り込みが入っているが、入りっぱなしになっている。

core   0: 0x00000000000000a0 (0x00813f03) ld      t5, 8(sp)
core   0: 3 0x00000000000000a0 (0x00813f03) x30 0x0000000000000000 mem 0x0000000010001ec8
core   0: 0x00000000000000a4 (0x00013f83) ld      t6, 0(sp)
core   0: 3 0x00000000000000a4 (0x00013f83) x31 0x0000000000000000 mem 0x0000000010001ec0
core   0: 0x00000000000000a8 (0x08010113) addi    sp, sp, 128
core   0: 3 0x00000000000000a8 (0x08010113) x 2 0x0000000010001f40
core   0: 0x00000000000000ac (0x30200073) mret
core   0: 3 0x00000000000000ac (0x30200073) c768_mstatus 0x0000000a00000088
core   0: exception interrupt #7, epc 0x0000000000003f08
core   0: >>>>  trap_entry
core   0: 0x0000000000000020 (0xfe113c23) sd      ra, -8(sp)
core   0: 3 0x0000000000000020 (0xfe113c23) mem 0x0000000010001f38 0x0000000000001778
core   0: 0x0000000000000024 (0xfe513823) sd      t0, -16(sp)
core   0: 3 0x0000000000000024 (0xfe513823) mem 0x0000000010001f30 0x0000000010000b48
core   0: 0x0000000000000028 (0xfe613423) sd      t1, -24(sp)
core   0: 3 0x0000000000000028 (0xfe613423) mem 0x0000000010001f28 0x0000000010000b48
core   0: 0x000000000000002c (0xfe713023) sd      t2, -32(sp)
core   0: 3 0x000000000000002c (0xfe713023) mem 0x0000000010001f20 0x0000000000005d70
core   0: 0x0000000000000030 (0xfca13c23) sd      a0, -40(sp)
core   0: 3 0x0000000000000030 (0xfca13c23) mem 0x0000000010001f18 0x0000000000000880
core   0: 0x0000000000000034 (0xfcb13823) sd      a1, -48(sp)
core   0: 3 0x0000000000000034 (0xfcb13823) mem 0x0000000010001f10 0x0000000000000000
core   0: 0x0000000000000038 (0xfcc13423) sd      a2, -56(sp)
core   0: 3 0x0000000000000038 (0xfcc13423) mem 0x0000000010001f08 0x0000000000000000
core   0: 0x000000000000003c (0xfcd13023) sd      a3, -64(sp)
core   0: 3 0x000000000000003c (0xfcd13023) mem 0x0000000010001f00 0x0000000000000000
core   0: 0x0000000000000040 (0xfae13c23) sd      a4, -72(sp)
core   0: 3 0x0000000000000040 (0xfae13c23) mem 0x0000000010001ef8 0x00000000000001fe
core   0: 0x0000000000000044 (0xfaf13823) sd      a5, -80(sp)

あとは、PLICを接続するだけかな。

LiteXのBIOSソフトウェアを独自に構築する方法調査

LiteXのBIOS立ち上げ環境を、独自のRTLシミュレーション環境に移植したくて、メモしておく。

基本的に、LiteXをダウンロードしたときに登場するlitex/litex/soc/software/を丸ごと別ディレクトリに移動することになる。 さらに、ライブラリを作成するの、pythondata-software-picolibcpythondata-software-compiler_rtもコピーしておく。

LiteXのCPU環境構築用に作った、以下のファイルもすべて移動しておく。

boot-helper.S
crt0.S
csr-defs.h
irq.h
system.h

基本的にはsoftwareディレクトリでvariables.makをいじって、例えばリポジトリ管理をしているならばそこの絶対パスに置き換えるような処置をしておけばOK。これで、各ソフトウェアを順番にビルドしていけばよい。

REPO_BASE_DIR=$(shell git rev-parse --show-superproject-working-tree --show-toplevel | head -1)

PACKAGES=libc libcompiler_rt libbase libfatfs liblitespi liblitedram libliteeth liblitesdcard liblitesata bios
PACKAGE_DIRS=$(REPO_BASE_DIR)/tests/litex_soc/software/libc $(REPO_BASE_DIR)/tests/litex_soc/software/libcompiler_rt $(REPO_BASE_DIR)/tests/litex_soc/software/libbase $(REPO_BASE_DIR)/tests/litex_soc/software/libfatfs $(REPO_BASE_DIR)/tests/litex_soc/software/liblitespi $(REPO_BASE_DIR)/tests/litex_soc/software/liblitedram $(REPO_BASE_DIR)/tests/litex_soc/software/libliteeth $(REPO_BASE_DIR)/tests/litex_soc/software/liblitesdcard $(REPO_BASE_DIR)/tests/litex_soc/software/liblitesata $(REPO_BASE_DIR)/tests/litex_soc/software/bios
LIBS=libc libcompiler_rt libbase libfatfs liblitespi liblitedram libliteeth liblitesdcard liblitesata
TRIPLE=riscv64-unknown-elf
CPU=mycpu
CPUFAMILY=riscv
CPUFLAGS=-march=rv64i2p0_m     -mabi=lp64 -D__mycpu__
CPUENDIANNESS=little
CLANG=0
CPU_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/mycpu
SOC_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/
PICOLIBC_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/pythondata_software_picolibc/data
PICOLIBC_FORMAT=integer
COMPILER_RT_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/pythondata_software_compiler_rt/data
export BUILDINC_DIRECTORY
BUILDINC_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/include
LIBC_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/libc
LIBCOMPILER_RT_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/libcompiler_rt
LIBBASE_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/libbase
LIBFATFS_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/libfatfs
LIBLITESPI_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/liblitespi
LIBLITEDRAM_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/liblitedram
LIBLITEETH_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/libliteeth
LIBLITESDCARD_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/liblitesdcard
LIBLITESATA_DIRECTORY=$(REPO_BASE_DIR)/tests/litex_soc/software/liblitesata
BIOS_DIRECTORY=$(abspath $(REPO_BASE_DIR)/tests/litex_soc/software/bios)
LTO=0
BIOS_CONSOLE_FULL=1

このようなMakefileを作成して、一気通貫でビルドができるようにしておく。

all:
        $(MAKE) -C libbase
#       $(MAKE) -C libc
        $(MAKE) -C libcompiler_rt
        $(MAKE) -C libfatfs
        $(MAKE) -C liblitedram
        $(MAKE) -C libliteeth
        $(MAKE) -C liblitesata
        $(MAKE) -C liblitesdcard
        $(MAKE) -C liblitespi
        $(MAKE) -C bios

clean:
        $(MAKE) clean -C libbase
#       $(MAKE) clean -C libc
        $(MAKE) clean -C libcompiler_rt
        $(MAKE) clean -C libfatfs
        $(MAKE) clean -C liblitedram
        $(MAKE) clean -C libliteeth
        $(MAKE) clean -C liblitesata
        $(MAKE) clean -C liblitesdcard
        $(MAKE) clean -C liblitespi
        $(MAKE) clean -C bios

で、作成されたbios.elfを流してみればよいのだが、Spikeではデフォルトで動作しない。これはなんでだっけ?dtsの書き換えとか必要だったっけ。

spike -l  -m0x0:0x1000 ../tests/litex_soc/software/bios/bios.elf
Access exception occurred while loading payload ../tests/litex_soc/software/bios/bios.elf:
Memory address 0x0 is invalid

LiteXによるSoC環境構築を試行する (21. ILAを使ったデバッグ)

0x28付近でループしている。これは例外処理の部分。

0000000000000020 <trap_entry>:
      20:       fe113c23                sd      ra,-8(sp)
      24:       fe513823                sd      t0,-16(sp)
      28:       fe613423                sd      t1,-24(sp)
      2c:       fe713023                sd      t2,-32(sp)
      30:       fca13c23                sd      a0,-40(sp)
      34:       fcb13823                sd      a1,-48(sp)
      38:       fcc13423                sd      a2,-56(sp)
      3c:       fcd13023                sd      a3,-64(sp)
      40:       fae13c23                sd      a4,-72(sp)
      44:       faf13823                sd      a5,-80(sp)
      48:       fb013423                sd      a6,-88(sp)
      4c:       fb113023                sd      a7,-96(sp)
      50:       f9c13c23                sd      t3,-104(sp)
      54:       f9d13823                sd      t4,-112(sp)
      58:       f9e13423                sd      t5,-120(sp)
      5c:       f9f13023                sd      t6,-128(sp)
      60:       f8010113                add     sp,sp,-128
      64:       78d030ef                jal     3ff0 <isr>
      68:       07813083                ld      ra,120(sp)
      6c:       07013283                ld      t0,112(sp)
      70:       06813303                ld      t1,104(sp)
      74:       06013383                ld      t2,96(sp)
      78:       05813503                ld      a0,88(sp)
      7c:       05013583                ld      a1,80(sp)
      80:       04813603                ld      a2,72(sp)
      84:       04013683                ld      a3,64(sp)
      88:       03813703                ld      a4,56(sp)
      8c:       03013783                ld      a5,48(sp)
      90:       02813803                ld      a6,40(sp)
      94:       02013883                ld      a7,32(sp)
      98:       01813e03                ld      t3,24(sp)
      9c:       01013e83                ld      t4,16(sp)
      a0:       00813f03                ld      t5,8(sp)
      a4:       00013f83                ld      t6,0(sp)
      a8:       08010113                add     sp,sp,128
      ac:       30200073                mret

ずっと割り込みルーチンを回っている気がする。

0xac → 0x20 をずっと回っている気がする。

なんで0x64の飛び先が毎回変わっているんだ?

左のobjdumpでは、0x64が0x3ff0に飛んでいるが、initファイルは、

fb013423
fb113023
f9c13c23
f9d13823
f9e13423
f9f13023
f8010113
2e8040ef  # 0x64 ずれている?
07813083
07013283
06813303
06013383
05813503
05013583
04813603

なんでこれがずれるんだ?

再合成して、もう一度アセンブリコードを作り直し:

mretからの戻りが、0x10001ef8などという意味不明なアドレスからになっている。

0xac(mret)からの戻りが、どうして0x20になっているのだろう?

なんか、0x41d8の0xc002000への書き込みの時に例外が発生しているっポイ?

    41d4:       ffc6f813                and     a6,a3,-4
    41d8:       01062023                sw      a6,0(a2)
    41dc:       31c72603                lw      a2,796(a4)
    41e0:       3205a703                lw      a4,800(a1)
    41e4:       00e61a63                bne     a2,a4,41f8 <uart_write+0x54>
    41e8:       12003637                lui     a2,0x12003

0x41d8で、ST例外が発生しているようだが、tvalが0になっている。アドレス計算に失敗している?

レジスタの読み出し状況をチェックする必要がある。