Overtone NSL Support

NSLサポートページ



7.状態変数


状態変数の宣言

状態変数は状態遷移マシンを定義するための構文で、ステート”state”と呼びます。
ステートの宣言を行うことでアクション記述に状態変数を持つことができます。
ステートの宣言は共通アクション記述部分とプロシージャアクションで宣言ができます。
また、ステートは宣言したプロシージャアクションでのみ使用可能です。

そして宣言の先頭に記述したステートがモジュール起動と同時に起動します。
ステートの宣言方法は以下の様に行います。

state_name ステート名

ステートの宣言では、最初に宣言したステートがモジュール起動直後に起動します。
ステートアクションを記述する場合は以下の方法を用います。

state ステート名 アクション記述

/

起動したステートは別のステートに遷移するまでアクションを続けます。

ステートを複数宣言してステート間を遷移する場合は、goto文を使います。
goto文の使用方法を以下に示します。

goto ステート名

この”goto文”により、別のステートを起動することが可能です。
別のステートに移動すると、元のステートは停止します。
ステートの遷移には1クロックかかります。

また、プロシージャアクションの遷移でステートが中断した場合、
元のプロシージャアクションが起動すると、中断したときと同じステートから開始します。

また、ステートは宣言を行った場所でのみアクション記述を記述することが可能です。
ステートの宣言は、共通アクション記述かプロシージャアクションで行います。

ステートとプロシージャとの違いは、
ステートは共通動作部分やプロシージャアクションでも使用できる点にあります。

また、プロシージャアクションで使用した場合は、
プロシージャアクションの終了時のステートを記憶しているという点で異なります。

そして、プロシージャアクションでステートを使用した場合、別のプロシージャアクションに遷移しても、
ステートは元のプロシージャが遷移した時のステートの状態を記憶しています。
これにより、プロシージャが遷移した時と同じステートから動作を開始することができます。

共通アクション記述でのステート使用例として、例題36を見てみましょう。

【例題36.状態遷移例(共通アクション記述内)】
declare ex36 {
}
module ex36 {
reg r1[4]=0 ;
{
state_name st1, st2, st3 ; //式1

state st1 { //式2
r1 := 0b0010 ;
goto st2 ;
}
state st2 { //式3
r1 := 0b0011 ;
goto st3 ;
}
state st3 { //式4
r1 := 0b0001 ;
goto st1 ;
}
}
}

例題36は、式1でステートst1,st2,st3を宣言しています。
この時、初めに宣言したステートst1が最初に起動します。
また、st1のステートアクションでgoto文を使った場合、
st2,st3といった、別のステートに遷移します。

では、例題36のシミュレーション結果を見てみましょう。

次に、プロシージャアクションでのステート使用例として、例題37を見てみましょう。

【例題37 状態遷移例(プロシージャブロック内)】

declare ex37 {
   func_in do ;
}
module ex37 {
   proc_name proc1() ;
   function do proc1() ;

   proc proc1 {
      state_name st1,st2,st3 ; //式1

      state st1 goto st2 ;     //式2
      state st2 goto st3 ;     //式3
      state st3 {  //式4
         goto st1;
         finish ;
      }
   }
}

例題37は、プロシージャアクション内で、ステートを使用しています。
式1はステートst1,st2,st3を宣言しています。
この時、式1で初めに宣言しているステートst1から最初に起動します。
また、st1のステートアクションで、goto文を使った場合、
st2,st3といった別のステートに遷移します。

例題37のシミュレーション結果を見てみましょう。

次に、プロシージャアクションでのステート例2として、例題38を見てみましょう。

【例題38.状態遷移例(プロシージャブロック内)2】

declare ex38 {
    func_in interrupt ;
    func_out cnt_start_call ;
    func_out cnt_end_call ;
}
module ex38 {
    reg r1=0, r2=0, r3=0 ;
    reg reg_cnt[8] = 0 ;
    reg cnt_buff[8] = 0 ;

    proc_name proc_count, proc_exec ;

    r1:=0b1; r2:=r1; r3:=r2;

    if(~r3 & r2 & r1) proc_count() ;

    proc proc_count {
        //ステートの宣言
        state_name st1_start, st2_count, st3_end ;

        //ステートアクション外の並列動作する部分
	    if(interrupt) proc_exec() ;

        //ステートst1_start
        state st1_start {
            cnt_start_call() ;
            goto st2_count ;
        }

        //ステートst2_count
        state st2_count {
            //カウント中
            any {
                reg_cnt == 0xFF : {
                    reg_cnt := 0x00 ;
                    goto st3_end ;
                }
                else : reg_cnt := reg_cnt + 0x01 ;
            }
        }

        //ステートst3_end
        state st3_end {
            cnt_end_call() ;
            goto st1_start ;
        }
    }

    proc proc_exec {
        cnt_buff := reg_cnt ;
        proc_count() ;
    }
}

例題38は、proc_countとproc_execという2個のプロシージャアクションを持っています。
また、proc_countの中では、ステートアクションst1_start,st2_count,st3_endの3つがあります。
例題38のモジュールは初めにプロシージャアクションproc_countが起動します。
proc_countは起動中、レジスタreg_cnt上でカウントアップを続けます。
そして、制御入力端子interruptが立ち上がると、proc_countからproc_execに遷移します。

例題38のシミュレーション結果を見てみましょう。


PAGE TOP