FPGA開発日記

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

自作RISC-Vアウトオブオーダコアの実装 (FPNewとデータ変換命令のデバッグ)

自作RISC-Vアウトオブオーダコアの実装、FPUを実装している。変換命令についてテストパタンを通しながらデバッグしている。

  • FFLAGSとFRMの関係性について

浮動小数点演算に必要な主要なフラグはいくつか定義されているが、重要なのはFFLAGS, FRM, FCSRであろう。

f:id:msyksphinz:20220402235304p:plain
f:id:msyksphinz:20220402235356p:plain

FCSRレジスタはFFLAGSとFRMを合わせたものであり、実体としてはそれぞれのレジスタを定義しておいて、FCSRレジスタを複合して定義しておけばよあろう。

always_ff @ (posedge i_clk, negedge i_reset_n) begin
  if (!i_reset_n) begin
    r_fflags  <= 'h0;
  end else begin
    if (fflags_update_if.valid) begin
      r_fflags <= fflags_update_if.fflags;
    end else if (write_if.valid & (write_if.addr ==  `SYSREG_ADDR_FFLAGS)) begin
      r_fflags <= write_if.data[ 4: 0];
    end else if (write_if.valid & (write_if.addr ==  `SYSREG_ADDR_FRM)) begin
      r_frm    <= write_if.data[ 2: 0];
    end else if (write_if.valid & (write_if.addr ==  `SYSREG_ADDR_FCSR)) begin
      r_fflags <= write_if.data[ 4: 0];
      r_frm    <= write_if.data[ 7: 5];
    end
  end
end
    `SYSREG_ADDR_FFLAGS         : read_if.data = {27'h0, r_fflags};
    `SYSREG_ADDR_FRM            : read_if.data = {29'h0, r_frm};
    `SYSREG_ADDR_FCSR           : read_if.data = {24'h0, r_frm, r_fflags};
  • FPNewの取り扱いについて

FPNewのopgroud_multifmt_sliceを使用しているが、いくつか注意点があって、Box化しておくこと、フラグの回収に注意するところなどがある。

logic w_cvt_in_valid;
logic [ 2: 0] [63: 0] w_multifmt_rs;
logic [ 4: 0] [ 2: 0] w_multifmt_boxed;
logic                 w_cast_out_valid;
logic [63: 0]         w_cast_result;
fpnew_pkg::status_t   w_cast_status;

assign w_cvt_in_valid = i_valid & w_cvt_valid;
assign w_multifmt_rs[0] = (i_pipe_ctrl.op == OP_FCVT_W_S || i_pipe_ctrl.op == OP_FCVT_WU_S) ? {{32{1'b1}}, i_rs1[31: 0]} : i_rs1;
assign w_multifmt_rs[1] = (i_pipe_ctrl.op == OP_FCVT_W_S || i_pipe_ctrl.op == OP_FCVT_WU_S) ? {{32{1'b1}}, i_rs2[31: 0]} : i_rs2;
assign w_multifmt_rs[2] = (i_pipe_ctrl.op == OP_FCVT_W_S || i_pipe_ctrl.op == OP_FCVT_WU_S) ? {{32{1'b1}}, i_rs3[31: 0]} : i_rs3;
assign w_multifmt_boxed[0] = 3'b111;
assign w_multifmt_boxed[1] = 3'b111;
assign w_multifmt_boxed[2] = 3'b111;
assign w_multifmt_boxed[3] = 3'b111;
assign w_multifmt_boxed[4] = 3'b111;


fpnew_opgroup_multifmt_slice /* #(
  .OpGroup       ( OpGroup          ),
  .Width         ( Width            ),
  .FpFmtConfig   ( FpFmtMask        ),
  .IntFmtConfig  ( IntFmtMask       ),
  .EnableVectors ( EnableVectors    ),
  .NumPipeRegs   ( REG              ),
  .PipeConfig    ( PipeConfig       ),
  .TagType       ( TagType          )
) */
  #(
    .NumPipeRegs(1),
    .PipeConfig (fpnew_pkg::BEFORE),
    .TagType    (logic)
    ) fpnew_cvt (
  .clk_i           ( i_clk     ),
  .rst_ni          ( i_reset_n ),
  .operands_i      ( w_multifmt_rs    ),
  .is_boxed_i      ( w_multifmt_boxed ),
  .rnd_mode_i      ( i_rnd_mode       ),
  .op_i            ( w_fpnew_op       ),
  .op_mod_i        ( w_fpnew_op_mod   ),
  .src_fmt_i       ( w_src_fp_fmt     ),
  .dst_fmt_i       ( w_dst_fp_fmt     ),
  .int_fmt_i       ( w_int_fmt        ),
  .vectorial_op_i  (  ),
  .tag_i           (  ),
  .in_valid_i      ( w_cvt_in_valid  ),
  .in_ready_o      (                 ),
  .flush_i         ( 1'b0            ),
  .result_o        ( w_cast_result   ),
  .status_o        ( w_cast_status   ),
  .extension_bit_o (  ),
  .tag_o           (  ),
  .out_valid_o     ( w_cast_out_valid ),
  .out_ready_i     ( 1'b1 ),
  .busy_o          (  )
);

ビックリすることに、Verilatorのコンパイル結果によりfflagsの位置が変わってしまったような気がしているので、きちんと配置し直した。

  // Status flags
  typedef struct packed {
    logic NV; // Invalid
    logic DZ; // Divide by zero
    logic OF; // Overflow
    logic UF; // Underflow
    logic NX; // Inexact
  } status_t;
assign w_fma32_out_fflags = {w_fma32_fflags.NV,
                            w_fma32_fflags.DZ,
                            w_fma32_fflags.OF,
                            w_fma32_fflags.UF,
                            w_fma32_fflags.NX};

一応ここまでで何とか標準的なパタンは動作するようになってきている。後は、

  • RV32におけるD拡張の対応(`XLEN=32, FLEN=64の場合。レジスタ長のパラメータを新たに追加する必要がある)。
  • FMAパイプラインをもっと長くしてより実用的なものにする。