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