Article #1127

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on September 22, 2026 #1127

4. 1箇所からしか呼ばれないseqのFSM化

seqをFSMに切り出す第一の理由は再利用で、記事#1035のdrawLivesがそれです。6箇所から呼ばれるseqを1個のFSMにまとめ、コンパイル時間を25%減らしました。記事#1036からは別の狙いで、1箇所からしか呼ばれないseqでも巨大なメインのseqから外せば競合条件の計算量が減るはず、という試みが始まります。記事#1036のdrawTitle1は1度しか呼ばれず本体も薄く、コンパイル時間が1%しか動かなかったので撤回されました。記事#1037のupdateAlienBulletと記事#1038のupdatePlayerBulletは本体が厚く、コンパイル時間がそれぞれ14%と16%、Verilogが11%と19%減って採用され、記事#1039のinitAllも同様に採用されました。つまり効くかどうかは呼び出し回数ではなく本体の厚さで決まる、というところまでが8/3版の時点で分かっていました。

ここではその続きとして、同じ基準で残っていたupdateAliens、updatePlayer、updateSaucerの3つをFSMにしました。本体の厚いseqはメインから切り出す方がbscの負担が軽い、という記事#1037と記事#1038で見えていた傾向に従ったものです。動作はVRAM書き込みの系列がサイクル番号を除いて一致しました。

教科書版の最終形

以上から、教科書版は次の2つの基準で決めました。複数箇所から呼ばれるseqは、共有するためにFSM化します。1個のインスタンスを作り、RUN_FSMマクロで各所から呼びます。メインループから呼ぶ大きなseqは、1箇所からしか呼ばれなくても、メインを小さくするためにFSM化します。仕組みは同じで、動機が違います。前者は規則の複製を消し、後者はメインFSMの状態数を減らします。モジュール境界は、42箇所から呼ばれ自前のレジスタを持つブリッタだけに使います。

seq 呼び出し箇所 扱い 置き場所
copyAreaなど描画プリミティブ6種 42 共有するためのFSM化 mkBlitter
drawLives 6 共有するためのFSM化 メイン
waitTicks 4 共有するためのFSM化 メイン
initAll 2 共有するためのFSM化 メイン
drawScores 2 共有するためのFSM化 メイン
updateAliens、updatePlayer、updatePlayerBullet、updateAlienBullet、updateSaucer 各1 メインを小さくするためのFSM化 メイン
updateBonus、checkClear、erasePlayerBulletなど小さなseq 1から5 展開のまま メイン

FSMはmkBlitterの1個とメインの9個で、メインループは各サブシステムのFSMをstartしてdoneを待つだけの短い列になります。教科書版の各FSMの状態数は次のとおりです。

FSM 状態数
メイン 90
updatePlayerBullet_fsm 54
updateSaucer_fsm 36
updateAlienBullet_fsm 33
updatePlayer_fsm 30
initAll_fsm 22
blit_fsm、mkBlitterの中 22
drawScores_fsm 18
updateAliens_fsm 18
drawLives_fsm 9
wt_fsm 6
合計 338

メインFSMの状態数は8/3版の193から90になりました。FSM全体の合計では、8/3版の418から338です。コンパイル時間と物量の前後は記事#1129の表にまとめます。


左矢前のブログ 次のブログ右矢

Leave a Comment

Your email address will not be published.

You may use Markdown syntax. If you include an ad such as http://, it will be invalidated by our AI system.

Please enter the numbers as they are shown in the image above.