FPGA開発日記

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

Chipyardで独自コアシミュレーション環境構築方法の調査 (5. シミュレーションエラー解析)

自作CPUをChipyardの環境で動かすために、何が必要かを久しぶりに確認した。

前回、Sensitivity List関連で何故シミュレーションが失敗するのかを見つけるために、デバッグビルドで再実行したのだった。

./simulator-chipyard-MSRHConfig-debug +verbose -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add

これを見ると、FPU周りだということが分かってくるが、まだ詳細がつかめない。もう少し詳細をつかむために、FPUも搭載していない最小構成でChipyardシミュレーションを作り直してみて、問題が発生するか確認した。

-V{t1,96}+    VTestHarness___024root___change_request_880
-V{t1,97}+    VTestHarness___024root___change_request_879
-V{t1,98}+    VTestHarness___024root___change_request_878
-V{t1,99}+    VTestHarness___024root___change_request_877
-V{t1,100}+    VTestHarness___024root___change_request_876
-V{t1,101}+    VTestHarness___024root___change_request_875
-V{t1,102}+    VTestHarness___024root___change_request_874
-V{t1,103}+    VTestHarness___024root___change_request_873
-V{t1,104}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,105}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,106}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,107}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,108}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,109}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,110}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,111}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,112}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,113}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,114}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
-V{t1,115}        CHANGE: /home/msyksphinz/work/riscv/chipyard_msrh/generators/msrh/src/main/resources/vsrc/MSRHCoreBlackbox.preprocessed.sv:20803
%Error: /home/msyksphinz/work/riscv/chipyard_msrh/sims/verilator/generated-src/chipyard.TestHarness.MSRHConfig/chipyard.TestHarness.MSRHConfig.harness.v:3849: Verilated model didn't DC converge
- See https://verilator.org/warn/DIDNOTCONVERGE
Aborting...

やはり同じエラーで落ちるようになった。しかし今度は場所が違い、リネーム論理辺りで問題が発生する。やはり同じサブモジュール内で問題が発生しているようだ。しかしこのモジュールは単体シミュレーションでも使っており、何故問題が発生するのか分からない。

VL_INLINE_OPT QData VTestHarness___024root___change_request_17(VTestHarness___024root* vlSelf) {
     if (false && vlSelf) {}  // Prevent unused
     VTestHarness__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
     VL_DEBUG_IF(VL_DBG_MSGF("+    VTestHarness___024root___change_request_17\n"); );
     // Body
     // Change detection
     QData __req = false;  // Logically a bool
     __req |= ((vlSelf->TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__18__KET____DOT__genblk1__DOT__bit_rnid_or__DOT__w_selected_array
                [1U] ^ vlSelf->__Vchglast__TOP__TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__18__KET____DOT__genblk1__DOT__bit_rnid_or__DOT__w_selected_array
                [1U])
          | (vlSelf->TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__extract_latest_rd_bit__DOT__u_bit_tree__DOT__in_shift_array
             [0U] ^ vlSelf->__Vchglast__TOP__TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__extract_latest_rd_bit__DOT__u_bit_tree__DOT__in_shift_array
             [0U])
          | (vlSelf->TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__extract_latest_rd_bit__DOT__u_bit_tree__DOT__in_shift_array
             [1U] ^ vlSelf->__Vchglast__TOP__TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__extract_latest_rd_bit__DOT__u_bit_tree__DOT__in_shift_array
             [1U])
          | (vlSelf->TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__bit_rnid_or__DOT__w_selected_array
             [0U] ^ vlSelf->__Vchglast__TOP__TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__bit_rnid_or__DOT__w_selected_array
             [0U])
          | (vlSelf->TestHarness__DOT__dut__DOT__system__DOT__MSRH_tile__DOT__core__DOT__u_msrh_tile__DOT__u_msrh_int_rename__DOT__u_msrh_rename_map__DOT__map_loop__BRA__19__KET____DOT__genblk1__DOT__bit_rnid_or__DOT__w_selected_array

問題の論理は、Arrayから1つのエントリを選択する論理なのだが、これ自体は問題はいハズだ。

module select_oh #(
    parameter SEL_WIDTH  = 5,
    parameter KEY_WIDTH  = 8,
    parameter DATA_WIDTH = 32
) (
    input logic [KEY_WIDTH-1: 0]   i_cmp_key,
    input logic [SEL_WIDTH-1:0]    i_valid,
    input logic [KEY_WIDTH-1: 0]   i_keys [SEL_WIDTH],
    input logic [DATA_WIDTH-1: 0]  i_data [SEL_WIDTH],

    output logic                   o_valid,
    output logic [DATA_WIDTH-1: 0] o_data
);


  /* verilator lint_off UNOPTFLAT */
  logic [SEL_WIDTH-1:0] valid_tmp;

  generate
    for (genvar i = 0; i < SEL_WIDTH; i++) begin
      always_comb begin
        if (i_valid[i] && i_keys[i] == i_cmp_key) begin
          valid_tmp[i] = 1'b1;
        end else begin
          valid_tmp[i] = 1'b0;
        end
      end  // always_comb
    end
  endgenerate
/* 以下略 */

うーん、何が良くないんだ?