FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (15. 浮動小数点比較マスク命令の実装)

現在自作CPUではFPUの演算器としてIPのcvfpu(FPNew)を使用している。これはかなりまともに使える演算器IPだと思うので、現在サポートしようとしているベクトル命令のFPU演算命令もFPNewを使ってサポートしていきたい。

次は浮動小数点の比較命令の実装だ。比較の結果はベクトル・マスクの形式で生成されるため、すべての比較結果を下位のマスクビット位置に持ってくる必要があることに注意する。

always_comb begin
  w_fpnew_mask_result = 'h0;
  case (w_fpnew_tag_out.vsew)
    scariv_vec_pkg::EW32 : begin
      for (int d_idx = 0; d_idx < riscv_vec_conf_pkg::DLEN_W / 32; d_idx++) begin
        w_fpnew_mask_result [d_idx] = w_fpnew_tag_out.op == OP_FNE ? ~w_fpnew_calc_result[32*d_idx] : w_fpnew_calc_result[32*d_idx];
      end
    end
    scariv_vec_pkg::EW64 : begin
      for (int d_idx = 0; d_idx < riscv_vec_conf_pkg::DLEN_W / 64; d_idx++) begin
        w_fpnew_mask_result [d_idx] = w_fpnew_tag_out.op == OP_FNE ? ~w_fpnew_calc_result[64*d_idx] : w_fpnew_calc_result[64*d_idx];
      end
    end
    default : begin
      w_fpnew_mask_result = 'h0;
    end
  endcase // case (r_ex1_issue.vlvtype.vtype.vsew)
end // always_comb

VLEN == DLENの場合は、単純にマスクの結果を下位に持ってくる。

  always_comb begin
    case (w_fpnew_tag_out.vsew)
      scariv_vec_pkg::EW32 :
        w_fpnew_mask_wr_result_next = {w_fpnew_tag_out.old_wr_data[riscv_vec_conf_pkg::DLEN_W   -1: scariv_vec_pkg::VLENB/4],
                                       w_fpnew_mask_result[riscv_vec_conf_pkg::DLEN_W/32-1: 0]};
      scariv_vec_pkg::EW64 :
        w_fpnew_mask_wr_result_next = {w_fpnew_tag_out.old_wr_data[riscv_vec_conf_pkg::DLEN_W   -1: scariv_vec_pkg::VLENB/8],
                                       w_fpnew_mask_result[riscv_vec_conf_pkg::DLEN_W/64-1: 0]};
      default : w_fpnew_mask_wr_result_next = 'h0;
    endcase // case (w_fpnew_tag_out.vsew)
  end // always_comb

VLEN != DLENの場合は、マスクの結果を下位にもってきて、最後のステップまでスタックしていく。

  always_comb begin
    case (w_fpnew_tag_out.vsew)
      scariv_vec_pkg::EW32 :
        w_fpnew_mask_wr_result_next = {w_fpnew_tag_out.old_wr_data[riscv_vec_conf_pkg::DLEN_W   -1: scariv_vec_pkg::VLENB/4],
                                       w_fpnew_mask_result        [riscv_vec_conf_pkg::DLEN_W/32-1: 0],
                                       r_fpnew_mask_wr_result     [scariv_vec_pkg::VLENB/4 -1: riscv_vec_conf_pkg::DLEN_W/32]};
      scariv_vec_pkg::EW64 :
        w_fpnew_mask_wr_result_next = {w_fpnew_tag_out.old_wr_data[riscv_vec_conf_pkg::DLEN_W   -1: scariv_vec_pkg::VLENB/8],
                                       w_fpnew_mask_result        [riscv_vec_conf_pkg::DLEN_W/64-1: 0],
                                       r_fpnew_mask_wr_result     [scariv_vec_pkg::VLENB/8 -1: riscv_vec_conf_pkg::DLEN_W/64]};
      default : w_fpnew_mask_wr_result_next = 'h0;
    endcase // case (w_fpnew_tag_out.vsew)
  end // always_comb

  always_ff @ (posedge i_clk) begin
    r_fpnew_mask_wr_result <= w_fpnew_mask_wr_result_next;
  end

これで、一応簡単なベクトル比較マスク命令が動作するようになった。

VPR[24](53) <= 40540000_00000000_40540000_00000000_40540000_00000000_40540000_00000000_40540000_00000000_40540000_00000000_40540000_00000000_40540000_00000000_
4907 : 392 : PC=[0000000080002046] (M,19,04) d2058553 fcvt.d.w fa0, a1
FPR[10](45) <= 4059000000000000
4908 : 393 : PC=[000000008000204a] (M,20,01) 5e055cd7 vfmv.v.f v25, fa0
VPR[25](39) <= 40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_
4914 : 394 : PC=[000000008000204e] (M,21,01) 678c9f57 vmfle.vv v30, v24, v25
VPR[30](40) <= 42c80000_42c80000_42c80000_42c80000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_0000ffff_
4914 : 395 : PC=[0000000080002052] (M,21,02) 00009fb9 c.addw  a5, a4
GPR[15](30) <= 0000000000000058
4914 : 396 : PC=[0000000080002054] (M,21,04) fef651e3 bge     a2, a5, pc - 30
4915 : 397 : PC=[0000000080002036] (M,22,01) 40f5873b subw    a4, a1, a5
GPR[14](113) <= 000000000000000c
4916 : 398 : PC=[000000008000203a] (M,23,01) 05877757 vsetvli a4, a4, e64, m1, ta, mu
GPR[14](148) <= 0000000000000008
4917 : 399 : PC=[000000008000203e] (M,24,01) d2078553 fcvt.d.w fa0, a5
FPR[10](74) <= 4056000000000000
4917 : 400 : PC=[0000000080002042] (M,24,02) 5e055c57 vfmv.v.f v24, fa0
VPR[24](54) <= 40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_
4917 : 401 : PC=[0000000080002046] (M,24,04) d2058553 fcvt.d.w fa0, a1
FPR[10](46) <= 4059000000000000
4918 : 402 : PC=[000000008000204a] (M,25,01) 5e055cd7 vfmv.v.f v25, fa0
VPR[25](41) <= 40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_
4922 : 403 : PC=[000000008000204e] (M,26,01) 678c9f57 vmfle.vv v30, v24, v25
VPR[30](42) <= 42c80000_42c80000_42c80000_42c80000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_0000ffff_
4922 : 404 : PC=[0000000080002052] (M,26,02) 00009fb9 c.addw  a5, a4
GPR[15](9) <= 0000000000000060
4922 : 405 : PC=[0000000080002054] (M,26,04) fef651e3 bge     a2, a5, pc - 30