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 forkdisable 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は、スタティックに決まった名前付きブロックを強制終了させる。