RISC-Vの実装であるHummingBirdを調査していくことにした。
HummingBirdが何となく動くようになってきたのだが、ログファイルが生成されないので何が起きているのかよく分からない。 そこで、内部のパイプライン動作を把握するためにパイプライントレーサを追加して追いかけてみることにした。
パイプライントレーサは、HummingBirdのテストベンチtb_top.v
の中に突っ込むことにする。ファイルに書き出して、あとで参照する。
e200_opensource/tb/tb_top.v
`define E203_CORE u_e203_soc_top.u_e203_subsys_top.u_e203_subsys_main.u_e203_cpu_top.u_e203_cpu.u_e203_core `define E203_CORE_EXU `E203_CORE.u_e203_exu integer fp_log; initial begin fp_log = $fopen("core_trace.log", "w"); end always_ff @ (negedge clk) begin if (rst_n) begin $fwrite(fp_log, "%t | ", $time); if (`E203_CORE.ifu_o_pc_vld) begin $fwrite(fp_log, "PC=%08x |", `E203_CORE.ifu_o_pc); end else begin $fwrite(fp_log, " |"); end if (`E203_CORE.ifu_o_valid & `E203_CORE.ifu_o_ready) begin $fwrite(fp_log, "%08x |", `E203_CORE.ifu_o_ir); end else begin $fwrite(fp_log, " |"); end if (`E203_CORE_EXU.rf_wbck_ena) begin $fwrite(fp_log, "R%02x<=%08x |", `E203_CORE_EXU.rf_wbck_rdidx, `E203_CORE_EXU.rf_wbck_wdat); end else begin $fwrite(fp_log, " |"); end if (`E203_CORE.ifu_o_valid & `E203_CORE.ifu_o_ready) begin $fwrite(fp_log, "DASM(%08x)", `E203_CORE.ifu_o_ir); end $fwrite(fp_log, "\n"); end // if (rst_n) end
パイプライントレーサでは、命令のフェッチ、デコード結果、そしてレジスタへのライトバックの情報を出力している。
これでシミュレーションを行うと、core_trace.log
にトレースファイルが書き出されて以下のようになる。
make install && make compile && ./run/obj_dir/Vtb_top +DUMPWAVE=1 +TESTCASE=/home/msyksphinz/work/riscv/e200_opensource/vsim/run/../../riscv-tools/riscv-tests/isa/generated/rv32ui-p-add 2>&1 | tee log
197681 | PC=80000546 |fe520001 | |DASM(fe520001) 197691 | PC=80000548 |fe5240b5 |R01<=0000000d |DASM(fe5240b5) 197701 | PC=8000054a |00208f33 |R1e<=00000018 |DASM(00208f33) 197711 | PC=8000054e |00200205 |R04<=00000002 |DASM(00200205) 197721 | PC=80000550 |00204289 |R05<=00000002 |DASM(00204289) 197731 | PC=80000552 |fe5219e3 | |DASM(fe5219e3) 197741 | | | | 197751 | PC=80000556 | | | 197761 | PC=80000556 |fe524ee1 |R1d<=00000018 |DASM(fe524ee1) 197771 | PC=80000558 |02000193 |R03<=00000020 |DASM(02000193) 197781 | PC=8000055c |09df1663 | |DASM(09df1663)
spike-dasm
に突っ込むと何となくなにが起きているのかわかる。
197681 | PC=80000546 |fe520001 | |c.nop 197691 | PC=80000548 |fe5240b5 |R01<=0000000d |c.li ra, 13 197701 | PC=8000054a |00208f33 |R1e<=00000018 |add t5, ra, sp 197711 | PC=8000054e |00200205 |R04<=00000002 |c.addi tp, 1 197721 | PC=80000550 |00204289 |R05<=00000002 |c.li t0, 2 197731 | PC=80000552 |fe5219e3 | |bne tp, t0, pc - 14 197741 | | | | 197751 | PC=80000556 | | | 197761 | PC=80000556 |fe524ee1 |R1d<=00000018 |c.li t4, 24 197771 | PC=80000558 |02000193 |R03<=00000020 |li gp, 32 197781 | PC=8000055c |09df1663 | |bne t5, t4, pc + 140 197791 | PC=80000560 |09df4201 |R04<=00000000 |c.li tp, 0 197801 | PC=80000562 |09df412d |R02<=0000000b |c.li sp, 11
波形をログを取得すると、テストベンチ自体は正しく動いていることが分かった。ただし現在の状態では全く停止しないので、停止条件を入れてみる。
always_ff @ (negedge clk) begin if (`E203_CORE.lsu2itcm_icb_cmd_valid & `E203_CORE.lsu2itcm_icb_cmd_ready) begin if (`E203_CORE.lsu2itcm_icb_cmd_addr == 32'h00001000) begin $display("Finish. Result = %d\n", `E203_CORE.lsu2itcm_icb_cmd_wdata); $finish; end end end
0x80001000に値をストアすると停止するので、この条件を取得して書き出す。その時のストア値がベンチの実行結果なので、ついでにそれも表示する。 これで、最終的なテストベンチの結果を取得することができる。
Count = 198000 Finish. Result = 1 - /home/msyksphinz/work/riscv/e200_opensource/vsim/run/../install/tb/tb_top.v:601: Verilog $finish