前回、Chipyardで自作CPUが動かないのを解析していたのだが、波形を見ても全然分からないので、正しく動くリファレンスデザインと比較することにした。
比較対象は全く同じ構成でRocket-Chipを接続したもの。 FSTで波形を取って観測する。
diff --git a/sims/verilator/Makefile b/sims/verilator/Makefile index a1186acc..923abafb 100644 --- a/sims/verilator/Makefile +++ b/sims/verilator/Makefile @@ -107,7 +107,7 @@ RUNTIME_PROFILING_VFLAGS := $(if $(filter $(VERILATOR_PROFILE),all),\ VERILATOR_THREADS ?= 1 RUNTIME_THREADS := --threads $(VERILATOR_THREADS) --threads-dpi all -VERILATOR_FST_MODE ?= 0 +VERILATOR_FST_MODE ?= 1 TRACING_OPTS := $(if $(filter $(VERILATOR_FST_MODE),0),\ --trace,--trace-fst --trace-threads 1) TRACING_CFLAGS := $(if $(filter $(VERILATOR_FST_MODE),0),,-DCY_FST_TRACE)
./simulator-chipyard-RocketConfig-debug +verbose -v rv64ui-p-add.rocket.fst $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm
取得した波形は以下。
まず、TileからTileLinkのAチャネルを通じて命令を取得する。その結果はすぐに帰ってくるが、これは単純にBootROMから読みだしているから。ここの部分は自作CPUでは省略している。
そこからしばらく応答が無くなった後、突然コアが立ち上がって命令の実行が始まる。
命令トレースで見ると、おそらくWFIで割り込みを待っているんだろうなあ。
C0: 19 [1] pc=[0000000000010040] W[r10=0000000000010040][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[00000517] auipc a0, 0x0 C0: 20 [1] pc=[0000000000010044] W[r10=0000000000010000][1] R[r10=0000000000010040] R[r 0=0000000000000000] inst=[fc050513] addi a0, a0, -64 C0: 21 [1] pc=[0000000000010048] W[r 0=0000000000000000][1] R[r10=0000000000010000] R[r 0=0000000000000000] inst=[30551073] csrw mtvec, a0 C0: 26 [1] pc=[000000000001004c] W[r 5=800000000094112d][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[301022f3] csrr t0, misa C0: 29 [1] pc=[0000000000010050] W[r 5=ffffe00000000025][1] R[r 5=800000000094112d] R[r 0=0000000000000000] inst=[4122d293] srai t0, t0, 18 C0: 30 [1] pc=[0000000000010054] W[r 5=0000000000000001][1] R[r 5=ffffe00000000025] R[r 0=0000000000000000] inst=[0012f293] andi t0, t0, 1 C0: 31 [1] pc=[0000000000010058] W[r 0=0000000000000000][0] R[r 5=0000000000000001] R[r 0=0000000000000000] inst=[00028463] beqz t0, pc + 8 C0: 32 [1] pc=[000000000001005c] W[r 0=0000000000000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[30301073] csrw mideleg, zero C0: 37 [1] pc=[0000000000010060] W[r10=0000000000000008][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[00800513] li a0, 8 C0: 38 [1] pc=[0000000000010064] W[r 0=0000000000000000][1] R[r10=0000000000000008] R[r 0=0000000000000000] inst=[30451073] csrw mie, a0 C0: 43 [1] pc=[0000000000010068] W[r 0=0000000a00001800][1] R[r10=0000000000000008] R[r 0=0000000000000000] inst=[30052073] csrs mstatus, a0 C0: 48 [1] pc=[000000000001006c] W[r 0=0000000000000000][0] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[10500073] wfi C0: 51 [0] pc=[0000000000010070] W[r 0=0000000000000000][0] R[r31=0000000000000008] R[r 0=0000000000000000] inst=[ffdff06f] j pc - 0x4 C0: 70 [1] pc=[0000000000010000] W[r11=0000000002000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[020005b7] lui a1, 0x2000 C0: 71 [1] pc=[0000000000010004] W[r10=0000000000000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[f1402573] csrr a0, mhartid C0: 74 [1] pc=[0000000000010008] W[r 0=0000000000000000][0] R[r10=0000000000000000] R[r 0=0000000000000000] inst=[00050463] beqz a0, pc + 8 C0: 78 [1] pc=[0000000000010010] W[r12=0000000002000004][1] R[r11=0000000002000000] R[r 0=0000000000000000] inst=[00458613] addi a2, a1, 4 C0: 79 [1] pc=[0000000000010014] W[r13=0000000000000001][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[00100693] li a3, 1 C0: 80 [1] pc=[0000000000010018] W[r 0=0000000000000000][0] R[r12=0000000002000004] R[r13=0000000000000001] inst=[00d62023] sw a3, 0(a2)
どうも割り込みを待っている間、L2キャッシュに命令やデータなどを大量に取り込んでいるっぽい。 L2のAチャネルを見てみると、大量のデータ転送を確認することができる。
最後にどこからか割り込みが入って、コアが起動するという流れになっているようだ。
ポイントは、L2が埋まるまでコアを停止して待っておかなければならないということだろう。いくつか疑問がある。
- L2のフィルは誰がやっているのか?
- 割り込みを立ち上げているのはだれか?
この辺を解析するのと、まずは自作CPUの設定を変更して、スタートアドレスをブートROMに設定してみようか。