FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (34. スカラ・ロード命令の順序違反検出の実装)

前回の続き。マイクロコードを変更して再実験を行う。今回の再実験で考え直さなければならないのは以下の通りだった。

テストケースを動かすためには、アウト・オブ・オーダ実行のメモリ・アクセスの順序入れ替えを考慮しなければならない。 これまではスカラ命令同士であったが、今回はベクトル命令とスカラ命令同士のアクセス順序の入れ替えを考慮する。

このために、以下のインタフェースを追加して、スカラ命令の投機実行されたロード命令の記録を調査する。

interface scalar_ldq_haz_check_if;
  logic                valid;
  scariv_pkg::paddr_t  paddr;
  scariv_pkg::cmt_id_t cmt_id;
  scariv_pkg::grp_id_t grp_id;

  logic                haz_valid;
  scariv_pkg::cmt_id_t haz_cmt_id;
  scariv_pkg::grp_id_t haz_grp_id;

  modport master (
    output valid,
    output paddr,
    output cmt_id,
    output grp_id,
    input  haz_valid,
    input  haz_cmt_id,
    input  haz_grp_id
  );

  modport slave (
    input  valid,
    input  paddr,
    input  cmt_id,
    input  grp_id,
    output haz_valid,
    output haz_cmt_id,
    output haz_grp_id
  );

endinterface // scalar_ldq_haz_check_if

このインタフェースを経由して、スカラ命令のLDQを調査し、同じアドレスにアクセスしたより若いロード命令の存在を調査する。

  // Vector Store --> Scalar Load, memory disambiguation check
  logic       w_vstore_sload_same_dlen;
  logic       sload_is_younger_than_vstore;
  scariv_rough_older_check
  vst_sld_older_check
    (
     .i_cmt_id0 (scalar_ldq_haz_check_if.cmt_id),
     .i_grp_id0 (scalar_ldq_haz_check_if.grp_id),

     .i_cmt_id1 (w_ldq_entries[l_idx].inst.cmt_id),
     .i_grp_id1 (w_ldq_entries[l_idx].inst.grp_id),

     .o_0_older_than_1 (sload_is_younger_than_vstore)
     );
  assign w_vstore_sload_same_dlen = scalar_ldq_haz_check_if.paddr[scariv_pkg::PADDR_W-1: $clog2(scariv_vec_pkg::DLENB)] ==
                                    w_ldq_entries[l_idx].addr[scariv_pkg::PADDR_W-1: $clog2(scariv_vec_pkg::DLENB)];
  assign w_vstore_sload_haz_vld[l_idx] = scalar_ldq_haz_check_if.valid &
                                         !w_ldq_entries[l_idx].dead &
                                         w_ldq_entries[l_idx].is_valid &
                                         sload_is_younger_than_vstore &
                                         w_ldq_entries[l_idx].is_get_data &
                                         w_vstore_sload_same_dlen;
// ==================
// Vstore --> sload Flush Hazard
// ==================
generate if (scariv_vec_pkg::VLEN_W != 0) begin : vlsu_haz_check
  logic [scariv_conf_pkg::LDQ_SIZE-1: 0] w_vstore_sload_haz_vld_oh;

  scariv_entry_selector
    #(
      .ENTRY_SIZE (scariv_conf_pkg::LDQ_SIZE)
      )
  u_entry_selector
    (
     .i_oh_ptr       (w_out_ptr_oh),
     .i_entry_valids (w_vstore_sload_haz_vld),
     .o_entry_valid  (w_vstore_sload_haz_vld_oh)
     );

  ldq_entry_t w_sel_ldq_entry;

  bit_oh_or
    #(
      .T     (ldq_entry_t),
      .WORDS (scariv_conf_pkg::LDQ_SIZE)
      )
  u_flush_sel
    (
     .i_oh   (w_vstore_sload_haz_vld_oh),
     .i_data (w_ldq_entries),
     .o_selected(w_sel_ldq_entry)
     );

  always_comb begin
    scalar_ldq_haz_check_if.haz_valid  = |w_vstore_sload_haz_vld;
    scalar_ldq_haz_check_if.haz_cmt_id = w_sel_ldq_entry.inst.cmt_id;
    scalar_ldq_haz_check_if.haz_grp_id = w_sel_ldq_entry.inst.grp_id;
  end

end endgenerate // block: vlsu_haz_check

もし当該アドレスにヒットするスカラ命令が存在したら、それを打ち消すためのレポートを通知する。