FPGA開発日記

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

Chiselでのprintfデバッグの方法

f:id:msyksphinz:20170830023047p:plain

Chisel、コンセプトとしてはいいのかもしれないが、マジで書きにくいなあ。 一度Scalaでシミュレーションすればよいのかもしれないが、Rocket CoreのScalaシミュレーションとかどうやるんだろう? RTLシミュレーションするのだとしても一度Verilogに変換してからシミュレーションするのですごく遅いし、今現在ではフリーのツールではverilatorでvcdしか出力できないので、すごく遅い。

今現在でできることと言えば、念入りにprintfデバッグをすることだ。Chiselの開発環境においてprintfデバッグとはどうやって行うのか、調べた。

まず、本家の説明はこのようになっている。

Printing in Chisel · freechipsproject/chisel3 Wiki · GitHub

こちらの説明では、Chiselで普通にprintfを埋め込むことができるようになっている。実際。自作のアクセラレータ上で、printfを埋め込むことができた。

上記のWikiの説明では、以下のようになっているが、

val myUInt = 33.U
printf(p"myUInt = $myUInt") // myUInt = 33

どちらかというとこっちの方がしっくりくるなあ。

    printf("MemTotalExample: Command Received. %x, %x\n", io.cmd.bits.rs1, io.cmd.bits.rs2)

という訳で、ガンガンprintf()を入れて自作アクセラレータのデバッグを行っているわけだが、まだ時間がかかりそうだ。。。

ちなみに、Verilogに変換されると、このprintf()は以下のようにVerilogのシミュレーション用に埋め込まれ、Verilatorの実行中にも出力することができる。

RocketCoreの構成はRoccExampleConfig、シミュレーションは以下のようにして実行している。

make CONFIG=RoccExampleConfig
./emulator-rocketchip-RoccExampleConfig +verbose  ~/riscv64/riscv64-unknown-elf/riscv64-unknown-elf/bin/pk ../../rocket-rocc-examples/build/test-accumulator 2> rocc.log
  • emulator/generated-src/rocketchip.RoccExampleConfig.v
...
        end
      end
    end
    `ifndef SYNTHESIS
    `ifdef PRINTF_COND
      if (`PRINTF_COND) begin
    `endif
        if (_T_1526 & _T_1528) begin
          $fwrite(32'h80000002,"MemTotalExample: Command Received. %h, %h\n",io_cmd_bits_rs1,io_cmd_bits_rs2);
        end
    `ifdef PRINTF_COND
      end
    `endif
    `endif
    `ifndef SYNTHESIS
    `ifdef PRINTF_COND
      if (`PRINTF_COND) begin
    `endif
        if (io_mem_resp_valid & _T_1528) begin
          $fwrite(32'h80000002,"MemTotalExample: IO.MEM Received %h %h\n",io_mem_resp_bits_data,r_state);
        end
    `ifdef PRINTF_COND
      end
    `endif

すると、rocc.logにアクセラレータが呼び出されると以下のデバッグ分が表示される。

C                   0:    4493955 [1] pc=[000001012c] W[r12=0000000000000064][1] R[r 0=0000000000000000] R[r 4=0000000000000003] inst=[06400613] DASM(06400613)
C                   0:    4493956 [1] pc=[0000010130] W[r10=000000008ffffac0][1] R[r11=000000008ffffac0] R[r12=0000000000000064] inst=[00c5f55b] DASM(00c5f55b)
MemTotalExample: Command Received. 000000008ffffac0, 0000000000000064
C                   0:    4493957 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=0000000000000064] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
C                   0:    4493958 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
C                   0:    4493959 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
...

C                   0:    4493991 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
C                   0:    4493992 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
MemTotalExample: IO.MEM Received 0000000000000000 1
C                   0:    4493993 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
MemTotalExample: IO.MEM Received 0000000000000000 1
C                   0:    4493994 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
C                   0:    4493995 [0] pc=[0000010130] W[r 0=000000008ffffac0][0] R[r11=000000008ffffac0] R[r12=000000008ffffac0] inst=[00c5f55b] DASM(00c5f55b)
...

まあ便利と言えば便利だけど、Rocketの場合は特に、一回のシミュレーションで時間がかかりすぎる。 もうちょっと何とかならないかなあ。