29 |
BSVにおけるコマンドバッファ制御 (10) |
現行のインタフェースでは、SoundFSMはGameFSMから送出されたコマンドを取りこぼすことをできるだけ防ぐためにプリエンプションを実装しています。bscのready/enableハンドシェークでそれを実装できますか?
“プリエンプション(busy 中に新コマンドで上書き)” とBSC の 自動 Ready/Enable がかみ合うか?
モデル | 振る舞い | 自動 Ready/Enable で実現可? |
---|---|---|
通常ハンドシェーク | vld は busy=0 の時だけ出す → busy 中は転送が発生しない |
✅可能(can_fire=0 でルールが止まる) |
プリエンプション型 | busy 中でも新コマンドを“掲げ直し” 旧コマンドは破棄 |
⚠そのままでは不可 |
なぜ “そのままでは” 不可?
rule send_cmd; // GameFSM / Producer
soundCh.sound(code); // ← method call
endrule
*BSCはsound.can_fire
が0ならこのルールを丸ごと停止
→busy中は呼び出し自体が発生しない
→Producerが「新コードを掲げ直す」ことができない
つまり自動ハンドシェークの停止機構が、 プリエンプションで必要な“上書き送出”を妨げてしまう。
解決パターンは2通り
方針 | どうするか | Pros/Cons |
---|---|---|
①Readyを無視する経路を別途つくる | method Action soundRaw(UInt#(4) d); に always_ready, always_enabled 属性を付け、Producerはbusyに関わらず書き込む |
+既存自動handshake部を温存可 -衝突検証は手動で要注意 |
②Ready/Validを全部手書き | 先に示したRawインターフェース方式 (Producerはvld保持、Consumerはrdy=0で無視) |
+ロジックが明確 -BSCのcan_fire/スケジューラ恩恵を捨てる |
① “バイパス” 例(片側だけ属性を変える)
(* always_ready, always_enabled *)
method Action soundPreempt(Code_t d); // ← Ready 無視で必ず fire
- Producer は常に
soundPreempt(code)
を呼ぶ - Consumer 側で busy なら 最新だけラッチし直せばプリエンプション完了
- 他のメソッドは can_fire 付きのまま残せるので 競合解析は 8 割方 BSC に任せつつ 欲しい振る舞いを得られる
まとめ
- 純粋な自動 Ready/Enable だけ では “busy 中に新コマンドで上書き” は 実現できない (ready=0 が呼び出し停止を引き起こすため)。
プリエンプションを行うには
- ready を無視する専用メソッドを立てる
- ハンドシェークを完全に手書き —— のいずれかで 制御を一段階エスケープ する必要がある。
要点 BSC の自動機構は「正しく受理されること」を守るため “送り手側を止める” 動きをします。 “捨ててもいいから最新を突っ込む” というプリエンプティブ挙動は、 ready を無視する経路 を自分で設計したときのみ成立します。