16 |
BSVの設計トライアル (8) |
Caller Saved
今回GameFSMを開発するにあたり、過去記事で開発したコール方式を踏襲しますが、今回はCaller Saved方式に変えてみたいと思います。これを図示すると、呼び出し側では、必ずリーフと思ってリターンレジスタにネクストステートを格納して共通シーケンスをコールします。BSVコードで書けば、コール先をtarget_state、戻り先ステートをnext_stateとして、
return <= next_state;
state <= target_state;
となります。
リーフシーケンス
呼ばれた側は、さらにサブ共通シーケンスをコールするかどうかは分かっているので、さらに呼ばない場合、つまりリーフシーケンスである場合は何もせずに
state <= return;
を実行して戻ります。
非リーフシーケンス
他方、さらにサブ共通シーケンスの場合は、呼ばれた側ではまずリターンレジスタをプッシュします。
return_stack[sp] <= return;
sp <= sp + 1;
呼び出し元と同様に、サブ共通シーケンスをコールします。
return <= next_state2;
state <= sub_sequence;
戻る場合は、本来はリターンレジスタを回復してからそれをステートに入れるのですが、処理を簡略化して、
state <= return_stack[sp - 1];
sp <= sp - 1;
として戻ります。
最後に、前稿で実施したCaller Savedと今回実施予定のCallee Savedの方式の違いを図でまとめます。Caller Savedの利点は前述のとおり、呼ぶ側では同じシーケンスで良いことです。さらにreturnレジスタを壊すか壊さないかは自分の情報なので、判断し易いことが挙げられます。