process
SystemVerilogには、processというクラスがあります。
今週は、このprocessについて、4連続でアップしていきます。
IEEE 1800-2005では、このprocessクラスは、つぎのように宣言されています(実装は別です)。
class process;
enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED };
static function process self();
function state status();
function void kill();
task await();
function void suspend();
task resume();
endclass
各プロセスに対するアクセスをする前に、かならずプロセスのハンドルを'''self'''関数で獲得する必要があります。
process pid;
pid = process::self();
self 関数は、宣言の最初に static がついているのでクラス関数になります。
なので、process::self() のようにクラス名( process )の後に :: を付け、
その後に関数名( self() )が続きます。
各プロセスは、状態を持ちます。この状態を state で表現しています。
プロセスの状態を知りたいときは、 status 関数を呼びます。
各状態は、次のようになります。
FINISHED :プロセスが正常終了した
RUNNING :プロセスが現在、動作中である(ブロッキングされていない)
WAITING :プロセスがブロッキング文で待ち状態である
SUSPENDED :プロセスが停止中である(復帰を待っている状態)
KILLED :プロセスが強制的に終了した(強制終了、あるいは、disableが実行された)
各プロセスに対して、次の4つの関数あるいはタスクが用意されています。
kill() : プロセス(このプロセス内で生成した子プロセスも)を終了する。
await() : 他のプロセスが終了するのを待ちます
(自分自身に対してこのawait()を実行することはできません)
suspend() : 自分あるいは他のプロセスを一時的に停止します。
resume() : 停止しているプロセスを復帰させます
processの例として、IEEE 1800-2005から引用です。
task do_n_way( int N );
process job[1:N];
for ( int j = 1; j <= N; j++ )
fork
automatic int k = j;
begin job[j] = process::self(); ... ; end
join_none
for( int j = 1; j <= N; j++ ) // wait for all processes to start
wait( job[j] != null );
job[1].await(); // wait for first process to finish
for ( int k = 1; k <= N; k++ ) begin
if ( job[k].status != process::FINISHED )
job[k].kill();
end
endtask
fork/join_none 部でプロセスがN個生成されます。
生成されたプロセスのハンドルは、 job に格納します。
wait 文で各プロセスが起動したかどうか確認します。
プロセスが起動できれば、 job[j] には process のハンドラが代入されるので
null ではありません。ここでハンドラが null でないことを確認しないと、
それ以降、ハンドラにアクセスした場合、null である可能性があり、そうなると
null に対するアクセスになり、エラーになるので注意してください。
次の job[1].await() では、 job[1] が終了するまで待ちます。
最後の for 文では、各プロセスが正常終了していないときに job[k].kill() で
プロセスを強制的に終了しています。
このように process を使うことで、 fork/join で生成したプロセスの制御ができます。
============================================================
OVM 2.1の中でも使われている場所については、こちら。
VMM 1.2の中でも使われている場所については、こちら。