ベクトル命令の実装検討、リプレイキューの構造について考え直す。
ベクトル命令は1命令で複数のuopに分解されるが、一度ハザードが発生してそれ以降のuopをすべてリプレイキューに格納すると、必要なリプレイキューの大きさが非常に大きくなってしまう。 そこで、リプレイキューに格納するのは、1命令内の複数のuopのうち、最初のuopのみをリプレイキューに格納し、それ以外を破棄するようにする。
これをサポートするためには、リプレイキューからの再実行においても、命令をuopに分解する機構が必要になる。 これまでは命令キュー内に命令をuopに分解する機能を実装していたが、これを移動し、パイプラインの直前のステージに移動する。
always_comb begin case (r_state) INIT : begin w_uop_next = i_issue; if (i_issue.valid & i_ready) begin if (!w_is_last_uop) begin w_state_next = UOP_GEN; w_uop_next.vec_step_index = i_issue.vec_step_index + 'h1; w_uop_next.vec_lmul_index = i_issue.vec_lmul_index + (w_uop_next.vec_step_index == mycpu_vec_pkg::VEC_STEP_W-1); for (int rs_idx = 0; rs_idx < NUM_OPERANDS; rs_idx++) begin if (i_issue.rd_regs[rs_idx].valid & i_issue.rd_regs[rs_idx].typ == mycpu_pkg::VPR) begin w_uop_next.rd_regs[rs_idx].rnid = i_issue.rd_regs[rs_idx].rnid + 'h1; end end w_uop_next.wr_old_reg.rnid = i_issue.wr_old_reg.rnid + 'h1; w_uop_next.wr_reg.rnid = i_issue.wr_reg.rnid + 'h1; end // else: !if(i_issue.vec_lmul_index == (1 << i_issue.vlvtype.vtype.vlmul)-1) end // if (i_issue.valid) end // case: INIT UOP_GEN : begin if (i_ready) begin w_uop_next.vec_step_index = r_uop.vec_step_index + 'h1; if (r_uop.vec_step_index == mycpu_vec_pkg::VEC_STEP_W-1) begin if (r_uop.vec_lmul_index == mycpu_vec_pkg::calc_num_req(i_issue)-1) begin w_state_next = INIT; w_uop_next.vec_lmul_index = r_uop.vec_lmul_index + 'h1; end for (int rs_idx = 0; rs_idx < NUM_OPERANDS; rs_idx++) begin if (r_uop.rd_regs[rs_idx].valid & r_uop.rd_regs[rs_idx].typ == mycpu_pkg::VPR) begin w_uop_next.rd_regs[rs_idx].rnid = r_uop.rd_regs[rs_idx].rnid + 'h1; end end w_uop_next.wr_old_reg.rnid = r_uop.wr_old_reg.rnid + 'h1; w_uop_next.wr_reg.rnid = r_uop.wr_reg.rnid + 'h1; end // else: !if(r_uop.vec_lmul_index == (1 << r_uop.vlvtype.vtype.vlmul)-1) end // if (i_ready) end // case: UOP_GEN default : begin end endcase // case (r_state) end // always_comb