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に移行します。