26 |
GameFSMの改良 (10) |
前記事でコール順位3位のwait_timerを最適化します。
元のwait_timerは単純に60Hzの外部信号ticに同期して動作する関数です。これをまずwait_timer_orgにリネームします。
// 時間待ち
function Stmt wait_timer_org(
UInt#(12) count
);
return (seq
repeat(pack(extend(count))) seq
await(tic == 0 || (foa && fbutton));
await((tic == 1 && sreq == 0) || (foa && fbutton));
endseq
endseq);
endfunction
これに対して、FSM wt_fsmを作成し、さらにそれを起動する汎用マクロを用いたタイマFSM起動関数を元の名前で作成します。
// ラッパ用:引数をラッチするだけ(Reg は1本)
Reg#(UInt#(12)) wt_count <- mkReg(0);
// 本体は org を mkFSM 化(count は Reg 値を読ませる)
FSM wt_fsm <- mkFSM( wait_timer_org(wt_count) );
// 同名の薄ラッパ:値ラッチ → 1サイクル待つ → start → done 待ち
function Stmt wait_timer (UInt#(12) count);
return (seq
action wt_count <= count; endaction
`RUN_FSM(wt_fsm)
endseq);
endfunction
このようにすれば、wait_timerを読んでもStmtがほとんど増加せずにFSMに起動をかけ、終了を待つだけになります。本体のStmtとしてはやや小さいものの、前ページのように16回呼ばれているため多少の効果はあるようです。
この関数だけのFSM化効果を調べたら以下のようにverilog量(byte数)で10.6%の削減となったので、そこそこの効果はありました。
wait_timerを最適化前後 | 前 | 後 | 比較 | |
---|---|---|---|---|
BSV合成 | コンパイル時間 | 2:36 | 2:10 | ▲16.7% |
Verilog合成 | ファイルサイズ[KB] | 9,394 | 8,395 | ▲10.6% |
合成時間 | 0:51 | 0:51 | 0.0% | |
Vivado LUT数 | 5,992 | 5,901 | ▲1.5% | |
Vivado FF数 | 1,871 | 1,812 | ▲3.2% |