Posts Issued on April 10, 2020

BSVの設計トライアル (4)

posted by sakurai on April 10, 2020 #237

サウンド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バイトの数値が得られます。

図%%.1
図237.1 FORMAT機能ステート遷移図
dcountにフォーマット長が得られたので、次にデータ長を取得します。
     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に移行します。

図%%.2
図237.2 DATA機能ステート遷移図
PLAYにおいては4倍のインターポレーションを行うため、4回同じデータを出力します。

左矢前のブログ 次のブログ右矢