6.プロシージャ

プロシージャの宣言

プロシージャは状態遷移や、パイプライン、順序回路を用いた制御を提供する構文です。
共通アクション記述以外でプロシージャ専用の単位アクションを記述する領域があります。
プロシージャは一度起動すると他のプロシージャに遷移するか、終了を宣言するまで動作し続けます。
プロシージャを宣言するには、以下のような記述方法を行います。
宣言時に仮引数を付帯することも可能で、カンマで区切って複数の仮引数を与えることもできます。

proc_name プロシージャ名(仮引数, 仮引数2, 仮引数3, …)

プロシージャに付帯することができる仮引数はレジスタに限ります。

プロシージャを起動する場合、
またはプロシージャアクションで別のプロシージャに遷移する場合は以下のように記述します。

プロシージャ名()

上記のコマンドはプロシージャアクション内で使用した場合、
元のプロシージャが終了し、遷移先のプロシージャが起動します。
プロシージャは起動を実行した次クロックから実際に起動を始めます。

また、プロシージャを終了せずに別のプロシージャを起動する場合は、invokeを使用します。
invokeは以下の記述方法で使用します。

プロシージャ名.invoke()

また、invokeは指定したプロシージャに実引数を渡すことができます。
invokeで実引数を使用する場合は以下のように使用します。

プロシージャ名.invoke(<実引数>
<実引数>, <実引数>, <実引数>… )

プロシージャを終了する場合は、プロシージャアクションで以下のように記述します。

プロシージャ名.finish()

finishはプロシージャ名を指定して終了することが可能です。
プロシージャは”finish”を宣言した次クロックで、アクションを停止します。

また、プロシージャアクションを記述する場合は以下のように記述します。

proc プロシージャ名 {
   単位アクション1
   単位アクション2
   単位アクション3
   …
   単位アクションX
}

プロシージャの起動例として例題34を見てみましょう。

【例題34.プロシージャ起動例】
declare ex34 {
   func_out cnt_end_call ;
}
module ex34 {
   reg r1=0, r2=0, r3=0 ;
   reg cnt_reg[4]=0;

   proc_name proc_count ; //式1

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

   if(~r1&r2&r3) proc_count() ; //式2

   proc proc_count { //式3
      any {
         cnt_reg == 0b1000 : {
            cnt_reg := 0b0000 ;
            cnt_end_call() ;
         }
         else : cnt_reg++ ;
      }
   }
}

例題34はプロシージャの起動例です。
ex34は内部にプロシージャproc_countを持っています。
proc_countの宣言は式1で行っています。
式2はif条件文が真の場合、proc_countを起動するという意味のアクションです。
式2で起動したproc_countのプロシージャアクションは式3から開始します。

proc_countのプロシージャアクションは、レジスタのカウントアップしています。
まず、anyブロックによりレジスタcnt_regを0b0000から1ずつカウントアップします。
次にcnt_regが0b1000に到達すると、cnt_regに0b0000を書き戻してから、
制御出力端子cnt_end_callを呼び出します。
ex34には、proc_countを終了するアクションを記述していないので、
proc_countは一度起動すると、プロシージャアクションを実行し続けます。

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

次にプロシージャの引数を利用した例として、
以下の例題35を見てみましょう。

【例題35.プロシージャ引数使用例】
declare ex35 {
   output f[4] ;
}
module ex35 {
   wire w_result[4] ;

   reg r1=0, r2=0, r3=0 ;
   reg opr1[4], opr2[4] ;
   reg result[4] ;

   proc_name proc_fetch() ; //式1
   proc_name proc_add(opr1, opr2) ; //式2
   proc_name proc_writeback(result) ; //式3

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

   if(~r1&r2&r3) proc_fetch() ; //式4

   proc proc_fetch { //式5
      proc_add(0b0101, 0b1010) ;
   }

   proc proc_add { //式6
      w_result = opr1 + opr2 ;
      proc_writeback(w_result) ;
   }

   proc proc_writeback { //式7
      f = result ;
      finish ;
   }
}

例題35は、プロシージャの引数使用例です。
モジュールex35は3つのプロシージャを持っていて、
式1・2・3はそれぞれプロシージャproc_fetch,proc_add,proc_writebackの宣言です。
式2・3は宣言と同時に、レジスタを仮引数として宣言しています。

ex35では、式4がきっかけとなってproc_fetchを起動します。
式4は、if条件文が真の場合、proc_fetchを起動するアクションです。

式6のproc_fetchが起動すると、プロシージャアクションを実行します。
proc_fetchのプロシージャアクションは、proc_addを実引数0b0101,0b1010をつけて起動します。
proc_addの実引数は仮引数で宣言したレジスタに代入します。

式6のproc_addが起動すると、プロシージャアクションを実行します。
式6のプロシージャアクションは、
・opr1,opr2の加算結果をw_resultに代入
・proc_writebackを実引数w_resultをつけて起動
の2つを実行しています。

そして、式7から始まるproc_writebackのプロシージャアクションは、
resultをfに代入するアクションです。

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