FPGA開発日記

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

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

自作RISC-Vアウトオブオーダコアの実装、FPUを実装している。FPNewのデータ変換命令は、また別のユニットが担当するらしい。

fpnew_opgroup_multifmt_sliceというモジュールを使う。 基本的な動かし方は一緒なのだが、データの変換元と変換先の指定にop_mod_i, src_fmt_i, dst_fmt_i, int_fmt_iというのを使用している。

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      ( fpnew_pkg::RNE   ),
  .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          (  )
);

各命令に応じて入出力フォーマットを指定する。

とりあえず命令に応じてFPNew向けに入力信号を制御するデコーダを作った。

  case (i_pipe_ctrl.op)
    OP_FCVT_S_D  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FCVT_D_S  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP64, fpnew_pkg::FP32};
    OP_FCVT_W_D  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT32, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FCVT_WU_D : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT32, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FCVT_D_W  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP64, fpnew_pkg::FP32};
    OP_FCVT_D_WU : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT32, fpnew_pkg::FP64, fpnew_pkg::FP32};
`ifdef RV64
    OP_FCVT_L_D  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FCVT_LU_D : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FMV_X_D   : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT32, fpnew_pkg::FP32, fpnew_pkg::FP64};
    OP_FCVT_D_L  : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP64, fpnew_pkg::FP64};
    OP_FCVT_D_LU : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT64, fpnew_pkg::FP64, fpnew_pkg::FP64};
    OP_FMV_D_X   : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b1, fpnew_pkg::INT32, fpnew_pkg::FP64, fpnew_pkg::FP64};
`endif // RV64
    default      : {w_cvt_valid, w_int_fmt, w_dst_fp_fmt, w_src_fp_fmt} = {1'b0, fpnew_pkg::INT64, fpnew_pkg::FP32, fpnew_pkg::FP64};
  endcase // case (i_pipe_ctrl.op)

何となく動くようになったが、まだテストが落ちる。もう少し解析していこう。

f:id:msyksphinz:20220402004948p:plain