FPGA開発日記

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

オープンソースRISC-VコアHummingBirdについて調査(5. パイプライントレーサを追加して内部情報を取得)

RISC-Vの実装であるHummingBirdを調査していくことにした。

https://camo.githubusercontent.com/f393ca23a6df9f640c1e4a43b78f2a503fdc47e8/68747470733a2f2f66647661643032316173666438712e6f73732d636e2d68616e677a686f752e616c6979756e63732e636f6d2f4c696368656554616e672f626f6f6b7069632e6a7067

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
f:id:msyksphinz:20191107232341p:plain
最後のテストベンチの実行結果をストアする様子。

0x80001000に値をストアすると停止するので、この条件を取得して書き出す。その時のストア値がベンチの実行結果なので、ついでにそれも表示する。 これで、最終的なテストベンチの結果を取得することができる。

Count = 198000
Finish. Result =          1

- /home/msyksphinz/work/riscv/e200_opensource/vsim/run/../install/tb/tb_top.v:601: Verilog $finish