FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (5. vlを用いたマスク生成の検討)

自作CPUにベクトル実行エンジンを追加する試行をしている。

vsetvli命令で決定したvl値を使ってベクトル演算を行う場合、VLがVLMAXよりも小さい場合、過去の値をキープする必要がある。 アウトオブオーダ実行の場合古い値をもう一度とってきて書き込みをするのでハードウェアが複雑になるのだが、とりあえず複雑さの部分はさておきナイーブに作りこんでおきたい。

ちょっとややこしいことをしているが、VLの値が自分のレーンIDよりも大きければ、マスクなしで全要素実行してもよい、 VLの値が自分のレーンIDよりも小さければ、マスクをその場で作って演算に適用する。

generate for (genvar d_idx = 0; d_idx < riscv_vec_conf_pkg::DLEN_W / 64; d_idx++) begin : datapath_loop
  logic [ 7: 0] w_ex1_en_mask;
  logic [ 3: 0] temp_vl;
  always_comb begin
    unique case (r_ex1_issue.vlvtype.vtype.vsew)
      scariv_vec_pkg::EW8 : begin
        temp_vl = r_ex1_issue.vlvtype.vl > d_idx*8 ? r_ex1_issue.vlvtype.vl - d_idx*8 : 0;
        w_ex1_en_mask = r_ex1_issue.vlvtype.vl > (d_idx+1) * 8 ? {8{1'b1}} : (1 << temp_vl) - 1;
      end
      scariv_vec_pkg::EW16: begin
        temp_vl = r_ex1_issue.vlvtype.vl > d_idx*4 ? r_ex1_issue.vlvtype.vl - d_idx*4 : 0;
        w_ex1_en_mask = r_ex1_issue.vlvtype.vl > (d_idx+1) * 4 ? {4{1'b1}} : (1 << temp_vl) - 1;
      end
      scariv_vec_pkg::EW32: begin
        temp_vl = r_ex1_issue.vlvtype.vl > d_idx*2 ? r_ex1_issue.vlvtype.vl - d_idx*2 : 0;
        w_ex1_en_mask = r_ex1_issue.vlvtype.vl > (d_idx+1) * 2 ? {2{1'b1}} : (1 << temp_vl) - 1;
      end
      scariv_vec_pkg::EW64: begin
        temp_vl = r_ex1_issue.vlvtype.vl > d_idx*1 ? r_ex1_issue.vlvtype.vl - d_idx*1 : 0;
        w_ex1_en_mask = r_ex1_issue.vlvtype.vl > (d_idx+1) * 1 ? {1{1'b1}} : (1 << temp_vl) - 1;
      end
      default             : begin
        temp_vl = 0;
        w_ex1_en_mask = 'h0;
      end
    endcase // unique case (i_sew)
  end

  scariv_vec_alu_datapath
  u_vec_alu_datapath
    (
     .i_op      (r_ex1_pipe_ctrl.op),
     .i_sew     (r_ex1_issue.vlvtype.vtype.vsew),
     .i_vs1     (r_ex1_vpr_rs_data[0][d_idx*64 +: 64]),
     .i_vs2     (r_ex1_vpr_rs_data[1][d_idx*64 +: 64]),
     .i_rs1     (r_ex1_rs1_data),
     .i_wr_old  (r_ex1_vpr_wr_old_data[d_idx*64 +: 64]),
     .i_en_mask (w_ex1_en_mask),
     .i_v0      ('h0),
     .o_res     (w_ex1_vec_result [d_idx*64 +: 64])
     );
end endgenerate // block: datapath_loop

一応簡単なvmv.v.x命令が動くようになった。まずは基本を突破だ!

5116 : 477 : PC=[0000000080002078] (M,03,04) fef659e3 bge     a2, a5, pc - 14
5117 : 478 : PC=[000000008000206a] (M,04,01) 40f5873b subw    a4, a1, a5
GPR[14](44) <= 0000000000000024
5120 : 479 : PC=[000000008000206e] (M,05,01) 04077757 vsetvli a4, a4, e8, m1, ta, mu
GPR[14](24) <= 0000000000000020
5124 : 480 : PC=[0000000080002072] (M,06,01) 5e07cc57 vmv.v.x v24, a5
VPR[24](40) <= 40404040_40404040_40404040_40404040_40404040_40404040_40404040_40404040_
5124 : 481 : PC=[0000000080002076] (M,06,02) 00009fb9 c.addw  a5, a4
GPR[15](91) <= 0000000000000060
5124 : 482 : PC=[0000000080002078] (M,06,04) fef659e3 bge     a2, a5, pc - 14
5125 : 483 : PC=[000000008000206a] (M,07,01) 40f5873b subw    a4, a1, a5
GPR[14](167) <= 0000000000000004
5128 : 484 : PC=[000000008000206e] (M,08,01) 04077757 vsetvli a4, a4, e8, m1, ta, mu
GPR[14](168) <= 0000000000000004
5132 : 485 : PC=[0000000080002072] (M,09,01) 5e07cc57 vmv.v.x v24, a5
VPR[24](43) <= 40404040_40404040_40404040_40404040_40404040_40404040_40404040_60606060_
5132 : 486 : PC=[0000000080002076] (M,09,02) 00009fb9 c.addw  a5, a4
GPR[15](92) <= 0000000000000064
5132 : 487 : PC=[0000000080002078] (M,09,04) fef659e3 bge     a2, a5, pc - 14
5152 : 488 : PC=[000000008000207c] (M,29,01) 00004501 c.li    a0, 0
GPR[10](161) <= 0000000000000000
5152 : 489 : PC=[000000008000207e] (M,29,02) 00008082 ret