自作RISC-Vアウトオブオーダコアの実装、FPUを実装している。現在整数側のパイプラインをベースとしてFPUのレイテンシを1としているが、そんなことはあり得ないので、レイテンシを伸ばしていこうと思う。
ただし、すべてのFPU命令のレイテンシを伸ばしていくとそれは問題がある。FPU命令群の中にはFMVやFSGNJなどの非常にシンプルな命令が入っており、これらは1サイクルで計算してしまって構わない。
これらを区別するために、パイプライン終了の信号とレジスタの書き込みポートを2つに拡張してしまおうと思う。
このために、まずパイプラインの完了、レジスタの書き込みポートを2つに増やす。
output msrh_pkg::early_wr_t o_ex1_mv_early_wr, output msrh_pkg::phy_wr_t o_ex3_mv_phy_wr, done_if.master ex3_mv_done_if, output msrh_pkg::phy_wr_t o_fpnew_phy_wr, done_if.master fpnew_done_if
2つのパイプラインは、デコード時にどちらを使うかを指定する。データ移動系命令は1サイクルで完了し、それ以外のFPNewを使う算術演算命令はより長いレイテンシで完了できるようにする。
always_comb begin o_ex3_mv_phy_wr.valid = r_ex3_wr_valid & (r_ex3_pipe_ctrl.pipe == PIPE_FAST); o_ex3_mv_phy_wr.rd_rnid = r_ex3_issue.wr_reg.rnid; o_ex3_mv_phy_wr.rd_type = r_ex3_issue.wr_reg.typ; o_ex3_mv_phy_wr.rd_data = r_ex3_res_data; ex3_mv_done_if.done = r_ex3_issue.valid & (r_ex3_pipe_ctrl.pipe == PIPE_FAST); ex3_mv_done_if.index_oh = r_ex3_index; ex3_mv_done_if.payload.except_valid = 1'b0; ex3_mv_done_if.payload.except_type = msrh_pkg::except_t'('h0); ex3_mv_done_if.payload.fflags_update_valid = 1'b0; ex3_mv_done_if.payload.fflags = 'h0; o_fpnew_phy_wr.valid = w_fpnew_result_valid; o_fpnew_phy_wr.rd_rnid = w_fpnew_rnid; o_fpnew_phy_wr.rd_type = w_fpnew_reg_type; o_fpnew_phy_wr.rd_data = w_fpnew_result_data; fpnew_done_if.done = w_fpnew_result_valid; fpnew_done_if.index_oh = w_fpnew_sched_index; fpnew_done_if.payload.except_valid = 1'b0; fpnew_done_if.payload.except_type = msrh_pkg::except_t'('h0); fpnew_done_if.payload.fflags_update_valid = w_fpnew_result_valid; fpnew_done_if.payload.fflags = w_fpnew_result_fflags; end // always_comb
fpnew_wrapperのパイプライン側も変更して、サイクル数を伸ばしていく。さらにtagポートを使用して、書き込み時に必要な情報を一緒にパイプラインに流していく。
以下の実装のTagTypeの部分と、NumPipeRegsの部分を変更した。
fpnew_fma
#(
.FpFormat (fpnew_pkg::FP64),
.NumPipeRegs(msrh_conf_pkg::FPNEW_LATENCY),
.PipeConfig (fpnew_pkg::BEFORE),
.TagType (aux_fpnew_t),
.AuxType (logic)
)
fpnew_64
(
.clk_i (i_clk ),
.rst_ni (i_reset_n),
// Input signals
.operands_i (w_fma64_rs ), // input logic [2:0][WIDTH-1:0] // 3 operands
.is_boxed_i (w_fma64_boxed ), // input logic [2:0] // 3 operands
.rnd_mode_i (i_rnd_mode ), // input fpnew_pkg::roundmode_e
.op_i (w_fpnew_op ), // input fpnew_pkg::operation_e
.op_mod_i (w_fpnew_op_mod ), // input logic
.tag_i (w_aux_fpnew_in ), // input TagType
.aux_i (w_aux_fpnew_in ), // input AuxType
// Input Handshake
.in_valid_i (w_fma64_in_valid ), // input logic
.in_ready_o (o_ready ), // output logic
.flush_i (1'b0 ), // input logic
// Output signals
.result_o (w_fma64_result ), // output logic [WIDTH-1:0]
.status_o (w_fma64_fflags ), // output fpnew_pkg::status_t
.extension_bit_o ( ), // output logic
.tag_o (w_fma64_aux ), // output TagType
.aux_o ( ), // output AuxType
// Output handshake
.out_valid_o (w_fma64_out_valid), // output logic
.out_ready_i (1'b1 ), // input logic
// Indication of valid data in flight
.busy_o ( ) // output logic
);
また、それぞれのコンフィグレーションでFPUパイプラインの長さを変えて、それぞれのパイプライン長で検証できるようにした。
ag FPNEW_LATENCY ../src/*_conf_pkg.sv ../src/msrh_big_conf_pkg.sv 39: localparam FPNEW_LATENCY = 6; ../src/msrh_giant_conf_pkg.sv 39: localparam FPNEW_LATENCY = 6; ../src/msrh_small_conf_pkg.sv 39: localparam FPNEW_LATENCY = 2; ../src/msrh_standard_conf_pkg.sv 39: localparam FPNEW_LATENCY = 4; ../src/msrh_tiny_conf_pkg.sv 39: localparam FPNEW_LATENCY = 1;