29 |
BSVの設計トライアル (17) |
レジスタ配列によるリターンスタック
前稿のリターンスタックrsはベクター配列で構成しましたが、最初に戻りレジスタ配列を試してみます。当初から配列で試したところ、うまく行っていませんでしたが、成功したのでその方法を記述します。まずリターンスタックrsを配列宣言します。
// return stack
Reg#(State_t) rs[3];
次に、リターンスタックrsを3段レジスタによりインスタンシエートします。これが無かったため、今まで動作しませんでした。ちなみにverilogでは宣言しただけで使用できますが、BSVでは宣言し、次にインスタンシエートが必要です。
for (int i = 0; i < 3; i = i + 1)
rs[i] <- mkRegU;
マクロ命令定義はベクター配列と同じ配列によるアクセス法を用います。
`define call(SUB) `_pushNext; state <= State_t {func:SUB, step:S0}
`define _pushNext rs[sp] <= State_t {func:state.func, step:nextStep()}; sp <= sp + 1
`define return state <= rs[sp-1]; sp <= sp - 1
`define next state.step <= nextStep()
説明は表248.1と同一です。これを用いて、前稿の検証FSMを実行してみます。
$ bsc -sim -u TestFSM4.bsv
checking package dependencies
compiling TestFSM3.bsv
code generation for mkTestFSM starts
Elaborated module file created: mkTestFSM.ba
All packages are up to date.
$ bsc -sim -e mkTestFSM -o mkTestFSM
Bluesim object created: mkTestFSM.{h,o}
Bluesim object created: model_mkTestFSM.{h,o}
Simulation shared library created: mkTestFSM.so
Simulation executable created: mkTestFSM
$ ./mkTestFSM -m 15 -V dump.vcd | tee result
L1 S0
L1 S1
L2 S0
L2 S1
L2 S2
L3 S0
L3 S1
L4 S0
L4 S1
L3 S2
L2 S3
L2 S4
L1 S2
L1 S2
$
正しく実行することが検証できました。波形を図250.1に示します。内部信号を見ると、ベクター配列と同様、rs_0, rs_1, rs_2という3個のレジスタインスタンスが生成されています。
合成結果
Vivadoによる合成結果は21 LUTのサイズでした。レジスタ配列とベクター配列は同様のサイズであったため、今後は最も素直なこの方式を採用します。
ソフトウェアの場合は高速なレジスタと低速なメモリがあるため、リターンレジスタ等の実装が必要ですが、FSMではよほどのことが無い限り全てレジスタなので、リターンレジスタを使用しない、この実装を基本的に使用していきます。