forkjoin
fork/joinは、すべてのブロックが終了したら、fork/join部を抜けます。
SystemVerilogでは、Verilog HDLのfork/joinの他に、
・ fork/join_any
・ fork/join_none
の2つが追加されました。
fork/join_anyは、いずれからブロックが終了したら、fork/join部を抜けます。
fork/join_noneは、すべてのブロックを起動したら、直ちにfork/join部を抜けます。
この2つのfork/joinは、Veraから取り込まれた機能です。
forkjoinの例題です。
添付ファイル(test_forkjoin.sv)をModelSim AE 6.4a Starter Editionでシミュレーションした結果は、次のようになります。
wait fork と disable fork
wait forkは、すべての子プロセスの実行が終了するまで待ちます。
下記の例は、test_wait_forkタスクの中で最初にfork/join_anyでrun_1とrun_2を実行します。
その次に、fork/join_noneでrun_3とrun_4を実行します。join_noneを実行した時点では、
run_1あるいはrun_2が終了しているだけです。
その次の wait forkでは、まだ実行しているプロセス(run_3/run_4とrun_1あるいはrun_2)が終了するまで待ちます。
task test_wait_fork;
fork
run_1();
run_2();
join_any
fork
run_3();
run_4();
join_none
wait fork; // block until exec1 ... exec4 complete
endtask
disable forkは、すべての子プロセス(子プロセスが起動したプロセスも含む)を強制的に終了させます。
task test_disable_fork;
fork
run_test( 1 );
run_test( 3 );
run_test( 5 );
run_test( 7 );
join_any
disable fork;
endtask
test_disable_forkタスクでは、fork/join_anyで4つのrun_testタスクを起動します。
4つのrun_testタスクの内、1つでも終了するとこのfork/join_anyを抜け、disable forkを実行します。
この時点で動作している子プロセス(まだ動作している3つのrun_testタスク)を強制終了します。
実際のコードでは?
OVM 2.0.2のovm_root.svh(src/base/ovm_root.svh)で、wait fork と disable fork が使われています。
719: begin // guard process
720: fork
721: begin
722: #0; // ensures stop_process active before potential stop_request
723: m_do_phase(this,m_curr_phase);
724: wait fork;
725: end
726: begin
727: #timeout ovm_report_error("TIMOUT",
728: $psprintf("Watchdog timeout of '%0t' expired.", timeout));
729: end
730: join_any
731: disable fork;
732: end // end guard process
fork/join_anyで起動したブロックのいずれかが終了したら、fork/join_any部を強制終了させる。
注意)、
disable forkは、Verilog HDLのdisable labelとは違うので注意が必要です。
disable labelは、起動した名前付きブロックを終了させる。
disable forkは、ダイナミックに起動した子プロセスに対して強制終了させるが、
disable labelは、スタティックに決まった名前付きブロックを強制終了させる。