FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (14. FMA命令の実装)

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

とりあえず簡単なFMA命令は動くようになりたい。ベクトル演算器のオペランドに、ベクトル・レジスタからのデータを3つ取ってきて書き込むだけだ。

// --------------
// FPU Pipeline
// --------------
fpnew_top
  #(
    // FPU configuration
    .Features       (scariv_vec_pkg::FPNEW_VEC_CONFIG),
    .Implementation (scariv_vec_pkg::FPNEW_VEC_IMPL),
    .TagType        (scariv_vec_pkg::aux_fpnew_t)
    )
u_fpnew_top
(
 .clk_i  (i_clk),
 .rst_ni (i_reset_n),
 // Input signals
 .operands_i    (w_fpnew_ex1_rs_data    ),
 .rnd_mode_i    (w_ex1_fpnew_rnd_mode   ),
 .op_i          (w_ex1_fpnew_op         ),
 .op_mod_i      (w_ex1_fpnew_op_mod     ),
 .src_fmt_i     (w_ex1_fpnew_src_fp_fmt ),
 .dst_fmt_i     (w_ex1_fpnew_dst_fp_fmt ),
 .int_fmt_i     (w_ex1_fpnew_int_fmt    ),
 .vectorial_op_i(1'b1                   ),
 .tag_i         (w_ex1_fpnew_tag_in     ),
 .simd_mask_i   (1'b0                   ),
 // Input Handshake
 .in_valid_i (w_ex1_fpnew_valid ),
 .in_ready_o (                  ),
 .flush_i    (w_ex1_commit_flush),
 // Output signals
 .result_o (w_fpnew_calc_result),
 .status_o (w_fpnew_status     ),
 .tag_o    (w_fpnew_tag_out    ),
 // Output handshake
 .out_valid_o (w_fpnew_out_valid),
 .out_ready_i (1'b1              ),
 // Indication of valid data in flight
 .busy_o ()
);

簡単なテストで、FMA命令が動作していることを確認した。

4879 : 397 : PC=[000000008000204e] (M,17,01) d2078553 fcvt.d.w fa0, a5
FPR[10](74) <= 4056000000000000
4879 : 398 : PC=[0000000080002052] (M,17,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_
4879 : 399 : PC=[0000000080002056] (M,17,04) d2058553 fcvt.d.w fa0, a1
FPR[10](46) <= 4059000000000000
4880 : 400 : PC=[000000008000205a] (M,18,01) 5e055cd7 vfmv.v.f v25, fa0
VPR[25](44) <= 40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_
4884 : 401 : PC=[000000008000205e] (M,19,01) b39c1f57 vfmacc.vv v30, v25, v24
VPR[30](45) <= 46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_40e9c800_00000000_40e9c800_00000000_40e9c800_00000000_
4884 : 402 : PC=[0000000080002062] (M,19,02) 00009fb9 c.addw  a5, a4
GPR[15](99) <= 0000000000000060
4884 : 403 : PC=[0000000080002064] (M,19,04) fef651e3 bge     a2, a5, pc - 30
4885 : 404 : PC=[0000000080002046] (M,20,01) 40f5873b subw    a4, a1, a5
GPR[14](17) <= 0000000000000004
4886 : 405 : PC=[000000008000204a] (M,21,01) 05877757 vsetvli a4, a4, e64, m1, ta, mu
GPR[14](152) <= 0000000000000004
4887 : 406 : PC=[000000008000204e] (M,22,01) d2078553 fcvt.d.w fa0, a5
FPR[10](0) <= 4058000000000000
4887 : 407 : PC=[0000000080002052] (M,22,02) 5e055c57 vfmv.v.f v24, fa0
VPR[24](56) <= 40560000_00000000_40560000_00000000_40560000_00000000_40560000_00000000_40580000_00000000_40580000_00000000_40580000_00000000_40580000_00000000_
4887 : 408 : PC=[0000000080002056] (M,22,04) d2058553 fcvt.d.w fa0, a1
FPR[10](2) <= 4059000000000000
4889 : 409 : PC=[000000008000205a] (M,23,01) 5e055cd7 vfmv.v.f v25, fa0
VPR[25](46) <= 40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_40590000_00000000_
4896 : 410 : PC=[000000008000205e] (M,24,01) b39c1f57 vfmacc.vv v30, v25, v24
VPR[30](47) <= 46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_46ff7800_40ee7800_00000000_40ee7800_00000000_40ee7800_00000000_
4896 : 411 : PC=[0000000080002062] (M,24,02) 00009fb9 c.addw  a5, a4
GPR[15](126) <= 0000000000000064