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回同じデータを出力します。

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