自作RISC-Vアウトオブオーダコアの実装、FPUを実装している。変換命令についてテストパタンを通しながらデバッグしている。
- FFLAGSとFRMの関係性について
浮動小数点演算に必要な主要なフラグはいくつか定義されているが、重要なのはFFLAGS
, FRM
, FCSR
であろう。
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};
一応ここまでで何とか標準的なパタンは動作するようになってきている。後は、