22 |
BSVの設計トライアル(12) |
マクロ命令の使用
過去記事のCalee Savedコールリターンを前稿で作成したマクロ命令を使用して書き直すと、図245.1のようになります。青字がマクロ命令です。Caller Savedでは入らなかった余分なpushRetがルーチン先頭に入っています。あるいは次のcallとまとめてしまい、非リーフからのcallを別に設ければこれは見かけ上無くなります。こうすれば、リーフと非リーフで、コールもリターンも別になるのでかえってすっきりするかもしれません。

検証用FSMソースコード
検証用FSMのBSVの全ソースコードを示します(既紹介部分は除く)。
import RegFile::*; (* synthesize, always_ready, always_enabled *) module mkTestFSM(); Reg#(State_t) state <- mkReg(State_t{func:L1, step:S0}), ret <- mkRegU; // L1 rule rule_L1 (state.func == L1); rule rule_S0 (state.step == S0); $display("L1 S%d", state.step); `next; endrule // S0 rule rule_S1 (state.step == S1); $display("L1 S%d", state.step); `call(L2); endrule // S1 rule rule_S2 (state.step == S2); $display("L1 S%d", state.step); endrule // S2 endrule // L1 // L2 rule rule_L2 (state.func == L2); rule rule_S0 (state.step == S0); $display(" L2 S%d", state.step); `pushRet; // L2 is not a leaf routine `next; endrule // S0 rule rule_S1 (state.step == S1); $display(" L2 S%d", state.step); `next; endrule // S1 rule rule_S2 (state.step == S2); $display(" L2 S%d", state.step); `call(L3); endrule // S2 rule rule_S3 (state.step == S3); $display(" L2 S%d", state.step); `next; endrule // S3 rule rule_S4 (state.step == S4); $display(" L2 S%d", state.step); `popRet; endrule // S4 endrule // L2 // L3 rule rule_L3 (state.func == L3); rule rule_S0 (state.step == S0); $display(" L3 S%d", state.step); `pushRet; // L3 is not a leaf routine `next; endrule // S0 rule rule_S1 (state.step == S1); $display(" L3 S%d", state.step); `call(L4); endrule // S1 rule rule_S2 (state.step == S2); $display(" L3 S%d", state.step); `popRet; endrule // S2 endrule // L3 // L4 (Leaf) rule rule_L4 (state.func == L4); rule rule_S0 (state.step == S0); $display(" L4 S%d", state.step); `next; endrule // S0 rule rule_S1 (state.step == S1); $display(" L4 S%d", state.step); `return; endrule // S1 endrule // L4 endmodule: mkTestFSM
Leave a Comment