BOOMと自作CPUの合成結果を比較して、ボトルネックになっている部分を調査したい。まずは面積から。
まず気になったのは、LDQとSTQのサイズが異常にでかい。LDQに比べてSTQの大きさが異常に大きいのも気になるので、余計なFFが入っている可能性を調査する。


とりあえずSTQの不要なエントリを削除しても意味がなかった。そういう最適化は最初からやられているらしい。

次に、Verilogファイルを生成して具体的にどんなFFが使われているのかを見てみる。
write_verilog -cell scariv_stq_entry stq_entry.sv
(* STRUCTURAL_NETLIST = "yes" *) module scariv_stq_entry (\r_entry_reg[is_rmw]_0 , \w_stq_entries[0][except_valid] , \w_stq_entries[0][inst][rd_regs][1][ready] , \r_entry_reg[inst][rd_regs][0][predict_ready]_0 , \r_entry_reg[inst][rd_regs][0][ready]_0 , \r_entry_reg[inst][rd_regs][1][typ]_0 , \r_entry_reg[inst][rd_regs][0][typ]_0 , \w_stq_entries[0][is_amo] , \w_stq_entries[0][vaddr] , \r_entry_reg[vaddr][6]_0 , \r_entry_reg[vaddr][7]_0 , \r_entry_reg[vaddr][8]_0 , \r_entry_reg[vaddr][9]_0 , ...
たぶんFDxxというセルがFlip Flopに相当しているものと思う。
grep FD stq_entry.sv | wc -l 826
とりあえずセル名をリストアップする。
$ grep -A2 FD stq_entry.sv | grep -v FD | grep -v INIT | grep -v -- --
...
\stq_snoop_if\.resp_s1_data_reg[85]
\stq_snoop_if\.resp_s1_data_reg[86]
\stq_snoop_if\.resp_s1_data_reg[87]
\stq_snoop_if\.resp_s1_data_reg[88]
\stq_snoop_if\.resp_s1_data_reg[89]
\stq_snoop_if\.resp_s1_data_reg[8]
\stq_snoop_if\.resp_s1_data_reg[90]
\stq_snoop_if\.resp_s1_data_reg[91]
\stq_snoop_if\.resp_s1_data_reg[92]
\stq_snoop_if\.resp_s1_data_reg[93]
\stq_snoop_if\.resp_s1_data_reg[94]
\stq_snoop_if\.resp_s1_data_reg[95]
\stq_snoop_if\.resp_s1_data_reg[96]
\stq_snoop_if\.resp_s1_data_reg[97]
\stq_snoop_if\.resp_s1_data_reg[98]
\stq_snoop_if\.resp_s1_data_reg[99]
\stq_snoop_if\.resp_s1_data_reg[9]
さらに解析する。どの種類のレジスタがどれだけ定義されているかが示される。
$ grep -A2 FD stq_entry.sv | grep -v FD | grep -v INIT | grep -v -- -- | sed 's/[0-9]//g' | sort | uniq -c
4 \FSM_sequential_r_entry_reg[state][]
3 \FSM_sequential_r_entry[state][]_i___
1 (.I(\FSM_sequential_r_entry[state][]_i____n_ ),
1 i____i_
1 (.I(Q[]),
1 (.I(\r_entry_reg[cmt_id][]_ ),
1 (.I(\r_entry_reg[state] ),
2 (.I(\r_entry_reg[vaddr][]_rep_ ),
1 (.I(\r_entry_reg[vaddr][]_rep___n_ ),
1 (.I(\stq_snoop_if\.resp_s_data[]_i__n_ ),
1 (.I(\w_stq_entries[][size] []),
2 (.I(\w_stq_entries[][vaddr] []),
5 \r_entry_reg[another_flush_cmt_id][]
5 \r_entry_reg[another_flush_grp_id][]
1 \r_entry_reg[another_flush_valid]
16 \r_entry_reg[br_mask][]
6 \r_entry_reg[cmt_id][]
4 \r_entry_reg[except_type][]
1 \r_entry_reg[except_valid]
5 \r_entry_reg[grp_id][]
1 \r_entry_reg[inst][oldest_valid]
1 \r_entry_reg[inst][rd_regs][][predict_ready]
2 \r_entry_reg[inst][rd_regs][][ready]
16 \r_entry_reg[inst][rd_regs][][rnid][]
2 \r_entry_reg[inst][rd_regs][][typ]
1 \r_entry_reg[inst][rd_regs][][valid]
1 \r_entry_reg[is_amo]
1 \r_entry_reg[is_committed]
1 \r_entry_reg[is_lr]
1 \r_entry_reg[is_rmw]
1 \r_entry_reg[is_rs_get]
1 \r_entry_reg[is_sc]
1 \r_entry_reg[is_uc]
1 \r_entry_reg[is_valid]
8 \r_entry_reg[missu_haz_index_oh][]
1 \r_entry_reg[oldest_ready]
27 \r_entry_reg[paddr][]
1 \r_entry_reg[paddr_valid]
5 \r_entry_reg[rmwop][]
64 \r_entry_reg[rs_data][]
1 \r_entry_reg[sc_success]
3 \r_entry_reg[size][]
39 \r_entry_reg[vaddr][]
5 \r_entry_reg[vaddr][]_rep
7 \r_entry_reg[vaddr][]_rep__
6 \stq_snoop_if\.resp_s_be[]_i___
64 \stq_snoop_if\.resp_s_be_reg[]
1 \stq_snoop_if\.resp_s_data[]_i___
512 \stq_snoop_if\.resp_s_data_reg[]
なるほど、Snoopインタフェースが冗長かな?調べてみるとSTQの中にレスポンスのための大きなFFが入っていた。これは除去できる。
結果、FFの数はかなり減らしたが、LUTは相変わらず大きいな!

