10 |
BSVの設計トライアル (4) |
サウンドFSMの作成(2)
階層化ステートマシンを解説します。基本的にBluespecにおいてはrule文のガードによりステートに入る条件を定義し、rule文の内部でステートの処理を定義します。そこで、ruleを構造化することで、ステートの構造化を実現します。具体的には以下のような構造となります。
rule ruleSOUND (state.cat == SOUND);
rule ruleFORMAT (state.func == FORMAT);
rule ruleS0 (state.step == S0);
// call readcount();
state <= State_t {cat:SOUND, func:READCOUNT, step:S0};
ret <= State_t {cat:SOUND, func:FORMAT, step:S1};
case (code)
'h1: romaddr <= 0 + 16;
'h2: romaddr <= 4318 + 16;
'h9: romaddr <= 13094 + 16;
endcase
endrule
rule ruleS1 (state.step == S1);
state <= State_t {cat:SOUND, func:DATA, step:S0};
romaddr <= romaddr + extend(dcount);
endrule
endrule // FORMAT
ruleS0ではcodeによりROMアドレス先頭を決定します。wave formatの16バイト目からフォーマット長取得を行います。readcount()をコールしており、そのリターンはruleS1ステートです。readcount()ではdcount変数に4バイトの数値が得られます。
rule ruleDATA (state.func == DATA);
rule ruleS0 (state.step == S0);
// call readcount();
state <= State_t {cat:SOUND, func:READCOUNT, step:S0};
ret <= State_t {cat:SOUND, func:DATA, step:S1};
romaddr <= romaddr + 4; // skip "data"
endrule
rule ruleS1 (state.step == S1);
state <= State_t {cat:SOUND, func:PLAY, step:S0};
romaddr <= romaddr - 1;
endrule
endrule // DATA
dcountにデータ長が得られたので、実際のサウンドデータを出力するため、PLAYに移行します。