FPGA開発日記

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

自作RISC-Vコアにおける浮動小数点命令サポートの実装 (3. レジスタの実装と基本的な符号命令)

浮動小数点命令とレジスタをサポートするために、リネームと物理レジスタの実装を変更する。

物理レジスタについては、x0(=ft0)レジスタに書き込みができるように変更する。また、リネームにおいてはx0(=ft0)もリネームを実行する。

汎用レジスタに対する特殊な条件を挿入する必要がある。

  // When instruction commit normally, return old RNID
  // even thouhg instruction is dead, newly allocated RNID should be return
  assign w_push_freelist = r_commit_rnid_update_dly.commit &
                           r_commit_rnid_update_dly.rnid_valid[d_idx] &
                           (r_commit_rnid_update_dly.rd_typ[d_idx] == REG_TYPE) &
                           ((REG_TYPE == GPR) ? (r_commit_rnid_update_dly.rd_regidx[d_idx] != 'h0) : 1'b1);

こちらも同様。汎用レジスタに対してのみ特殊な条件を挿入する。

generate for (genvar r_idx = 0; r_idx < msrh_pkg::RNID_SIZE; r_idx++) begin : reg_loop
  if ((REG_TYPE == GPR) & (r_idx == 0)) begin
    assign r_phy_regs[r_idx] = {riscv_pkg::XLEN_W{1'b0}};
  end else begin
    logic w_wr_valid;
    logic [riscv_pkg::XLEN_W-1:0] w_wr_data;
    select_oh #(
        .SEL_WIDTH (msrh_pkg::TGT_BUS_SIZE),
        .KEY_WIDTH (msrh_pkg::RNID_W),
        .DATA_WIDTH(riscv_pkg::XLEN_W)
    ) wr_data_select (
        .i_cmp_key(r_idx[msrh_pkg::RNID_W-1:0]),
        .i_valid(wr_valid),
        .i_keys(wr_rnid),
        .i_data(wr_data),
        .o_valid(w_wr_valid),
        .o_data(w_wr_data)
    );
    always_ff @(posedge i_clk, negedge i_reset_n) begin
      if (!i_reset_n) begin
        r_phy_regs[r_idx] <= {riscv_pkg::XLEN_W{1'b0}};
      end else begin
        if (w_wr_valid) begin
          r_phy_regs[r_idx] <= w_wr_data;
        end
      end
    end
  end // else: !if((REG_TYPE == GPR) & (r_idx == 0))
end
endgenerate

これに基づいて、いよいよ少しずつFPUのパイプラインを実装して行く。

logic [ 63: 0]       w_ex2_rs1_canonical;
logic [ 63: 0]       w_ex2_rs2_canonical;
assign w_ex2_rs1_canonical = !(&w_ex2_rs1_selected_data[63:32]) ? 64'hffffffff_7fc00000 : w_ex2_rs1_selected_data;
assign w_ex2_rs2_canonical = !(&w_ex2_rs2_selected_data[63:32]) ? 64'hffffffff_7fc00000 : w_ex2_rs2_selected_data;


always_comb begin
  case (r_ex2_pipe_ctrl.op)
    OP_FMV_X_W  : w_ex2_res_data = {{32{w_ex2_rs1_selected_data[31]}}, w_ex2_rs1_selected_data[31: 0]};
    OP_FMV_W_X  : w_ex2_res_data = w_ex2_rs1_selected_data;
    OP_FMV_X_D  : w_ex2_res_data = w_ex2_rs1_selected_data;
    OP_FMV_D_X  : w_ex2_res_data = w_ex2_rs1_selected_data;
    OP_FSGNJ_D  : w_ex2_res_data = { w_ex2_rs2_selected_data[63], w_ex2_rs1_selected_data[62:0]};
    OP_FSGNJN_D : w_ex2_res_data = {~w_ex2_rs2_selected_data[63], w_ex2_rs1_selected_data[62:0]};
    OP_FSGNJX_D : w_ex2_res_data = { w_ex2_rs1_selected_data[63] ^ w_ex2_rs2_selected_data[63],
                                     w_ex2_rs1_selected_data[62:0]};
    OP_FSGNJ_S  : w_ex2_res_data = {w_ex2_rs1_canonical[63:32],  w_ex2_rs2_canonical[31], w_ex2_rs1_canonical[30:0]};
    OP_FSGNJN_S : w_ex2_res_data = {w_ex2_rs1_canonical[63:32], ~w_ex2_rs2_canonical[31], w_ex2_rs1_canonical[30:0]};
    OP_FSGNJX_S : w_ex2_res_data = {w_ex2_rs1_canonical[63:32],
                                    w_ex2_rs1_canonical[31] ^ w_ex2_rs2_canonical[31],
                                    w_ex2_rs1_canonical[30: 0]};
    default    : w_ex2_res_data = 'h0;
  endcase // case (r_ex3_pipe_ctrl.op)
end // always_comb

とりあえずは符号変換命令までは実装できた。しかしテストベンチではfeqが実行されているようだ。ここでコケる―。

4730 : 707 : PC=[0000000080000b74] (U,15,02) f20580d3 fmv.d.x ft1, a1
FPR[01](94) <= ffffffff11111111
4731 : 708 : PC=[0000000080000b78] (U,00,01) f2060153 fmv.d.x ft2, a2
FPR[02](42) <= ffffffff11111111
4732 : 709 : PC=[0000000080000b7c] (U,01,01) 22208053 fsgnj.d ft0, ft1, ft2
FPR[00](68) <= ffffffff11111111
4745 : 710 : PC=[0000000080000b80] (U,02,01) a0002553 feq.s   a0, ft0, ft0
==========================================
Wrong GPR[10](10): RTL = 0000000000000000, ISS = 0000000000000001
==========================================
===============================
SIMULATION FINISH : FAIL (CODE=100)
===============================
f:id:msyksphinz:20220219001656p:plain
FPU命令の実行結果