FPGA開発日記

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

BOOMの論理合成結果と自作CPUの論理合成結果比較 (3. STQの面積の解析)

BOOMと自作CPUの合成結果を比較して、ボトルネックになっている部分を調査したい。まずは面積から。

引き続きSTQの面積について調査している。LUTの量は以下まで小さくなった。Snoopを消したこと自体の効果がある。

ag -A2 LUT stq_entry3.sv | grep -v LUT | grep -v INIT | grep -v -- -- | sed 's/[0-9]//g' | sort | uniq -c
     58 -    \FSM_sequential_r_entry[state][]_i___
      1 -    \o_stq_rs_resolve[index][]_i_
      4 -    \r_entry[another_flush_grp_id][]_i___
     16 -    \r_entry[br_mask][]_i___
     39 -    \r_entry[except_tval][][]_i_
      4 -    \r_entry[except_type][]_i___
      1 -    \r_entry[except_valid]_i___
      3 -    \r_entry[grp_id][]_i___
     18 -    \r_entry[hazard_index][]_i_
     11 -    \r_entry[hazard_index][]_i___
      2 -    \r_entry[inst][oldest_valid]_i___
      7 -    \r_entry[is_committed]_i___
      1 -    \r_entry[is_rmw]_i___
      1 -    \r_entry[is_uc]_i_
      1 -    \r_entry[is_uc]_i___
      1 -    \r_entry[is_valid]_i___
      3 -    \r_entry[missu_haz_index_oh][]_i___
     13 -    \r_entry[oldest_ready]_i___
     39 -    \r_entry[paddr][]_i___
      1 -    \r_entry[paddr_valid]_i___
      5 -    \r_entry[rmwop][]_i___
      3 -    \r_entry[rs_data][]_i___
      8 -    \r_entry[size][]_i___
     27 -    \r_entry[vaddr][]_i___
      2 -    \r_entry_reg[inst][rds][][predict_ready]_i___
      6 -    \r_entry_reg[inst][rds][][ready]_i___
      2 -    \r_entry_reg[inst][rds][][valid]_i___
    115 -    \r_ex_aligned_data[]_i_
     10 -    \r_ex_aligned_data[]_i___
      1 -    \r_return_dec[]_i_
      1 -    \r_uc_wr_paddr[]_i_
     28 -    i____i_
     10 -    i____i___
     29 -    r_ex_mis_valid_i_
     16 -    r_ex_mis_valid_i___

一番大きいのが、r_ex_aligned_data[]だ。これはレジスタなのか?LUTなのか...?

もうちょっとLUTの使用頻度を絞ってみた。

$ ag LUT -A10 stq_entry3.sv | ag -A10 r_ex3_aligned_data | ag " \.O" | sed 's/[0-9]//g' | sort | uniq -c
     14 -        .O(\fwd_loop[].byte_loop[].w_ex_fwd_strb_valid ));
     40 -        .O(\r_ex_aligned_data[]_i__n_ ));
     64 -        .O(\w_aligned_rs_data_array[]_ []));
      7 -        .O(gen_dw_return[]));

w_aligned_rs_data_arrayとかr_ex_aligned_dataとかが消費量が大きいな。

// =========================
// STQ Forwarding Logic
// =========================
scariv_pkg::alen_t w_aligned_rs2_data_array[scariv_conf_pkg::STQ_SIZE];
generate for (genvar s_idx = 0; s_idx < scariv_conf_pkg::STQ_SIZE; s_idx++) begin : stq_rs2_loop
  assign w_aligned_rs2_data_array[s_idx] = w_stq_entries[s_idx].rs2_data << {w_stq_entries[s_idx].paddr[$clog2(scariv_pkg::ALEN_W/8)-1:0], 3'b000};
end
endgenerate

こういうシフタの書き方をするとVivadoのLUTは大きくなるのかな。ちょっと変えてみる。

function scariv_pkg::alen_t align_byte (scariv_pkg::alen_t data, logic [$clog2(scariv_pkg::ALEN_W/8)-1:0] pa);
  if (scariv_pkg::ALEN_W == 64) begin
    case (pa)
      'b000: return data;
      'b001: return {data[scariv_pkg::ALEN_W- 8-1: 0],  8'h00};
      'b010: return {data[scariv_pkg::ALEN_W-16-1: 0], 16'h00};
      'b011: return {data[scariv_pkg::ALEN_W-24-1: 0], 24'h00};
      'b100: return {data[scariv_pkg::ALEN_W-32-1: 0], 32'h00};
      'b101: return {data[scariv_pkg::ALEN_W-40-1: 0], 40'h00};
      'b110: return {data[scariv_pkg::ALEN_W-48-1: 0], 48'h00};
      'b111: return {data[scariv_pkg::ALEN_W-56-1: 0], 56'h00};
      default : return 'h0;
    endcase // case (pa)
  end else begin // if (scariv_pkg::ALEN_W == 64)
    case (pa)
      'b00: return data;
      'b01: return {data[scariv_pkg::ALEN_W- 8-1: 0],  8'h00};
      'b10: return {data[scariv_pkg::ALEN_W-16-1: 0], 16'h00};
      'b11: return {data[scariv_pkg::ALEN_W-24-1: 0], 24'h00};
      default : return 'h0;
    endcase // case (pa)
  end // else: !if(scariv_pkg::ALEN_W == 64)

endfunction // align_byte

多少マシになった気がする。ただ、まだまだ大きい。

ag LUT -A10 scariv_stq_entry.synth.v  | ag -A10 r_ex3_aligned_data | ag " \.O" | sed 's/[0-9]//g' | sort | uniq -c
      3 -        .O(\fwd_loop[].byte_loop[].w_ex_fwd_strb_valid ));
     16 -        .O(\r_entry_reg[rs_data][]_ ));
     12 -        .O(\r_entry_reg[size][]_ ));
     24 -        .O(\r_entry_reg[vaddr][]_ ));
      6 -        .O(\r_ex_aligned_data[]_i____n_ ));
     34 -        .O(\r_ex_aligned_data[]_i__n_ ));
      1 -        .O(\r_ex_paddr_reg[]_rep ));
      3 -        .O(\r_ex_paddr_reg[]_rep_ ));
      3 -        .O(\r_ex_paddr_reg[]_rep___ ));
      3 -        .O(\r_ex_pipe_ctrl_reg[size][] ));
      1 -        .O(\r_ex_pipe_ctrl_reg[size][]_ ));
     32 -        .O(align_byte[]));
      8 -        .O(p__in_out[]));