本記事は以下の3部構成の一部です。
disable forkでは複数のforkしたプロセスをまとめて終了させます。どのプロセスに対する操作かを直接的に指定することはできません。一方processクラスを使用すれば対象のプロセスを直接指定して制御をすることができます。
processクラス
process クラスは特殊なクラスで、プログラムからnew()することはできません。process::self()で各プロセスへのオブジェクトハンドルを取得し、その後各種操作を行います。
クラスのプロトタイプは以下のようになっています。
class process;
typedef enum { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED } state;
static function process self();
function state status();
function void kill();
task await();
function void suspend();
function void resume();
function void srandom( int seed );
function string get_randstate();
function void set_randstate( string state );
endclass
良く使われるメソッドは以下の通りです。
- self()
- 現在のプロセスに制御をするためのオブジェクトハンドルを返します
- status()
- そのプロセスのステータスを返します。FINISHED, RUNNING, WAITING, SUSPENDED, KILLEDのいずれかです
- kill()
- そのプロセスとそこからforkされたサブプロセスを終了させます
- await()
- そのプロセスの終了を (ステータスがFINISHEDまたはKILLEDになるのを)待ちます
- 親プロセスが終了 (FINISHED)して子プロセスのみが残っている時 (RUNNING, WAITING, SUSPENDED)に、親プロセスに対してkill()した場合の動作が正しくないものがあります。本来は子プロセスも停止するべきと筆者は考えますが、停止しないものがあります
- Process classの中でstateのtypedefがされていないシミュレータがあります。この場合status()の戻り値がprocess::state型ではなく、0から4の数値で帰ってきます。
サンプルプログラム
以下がサンプルプログラムと実行結果です。
本例では親子関係にある2つのプロセスをforkしています。便宜的に親をProcess A、子をProcess Bと名付けています。proc_a =process::self()
でProcess Aの制御に使用するオブジェクトハンドルを獲得します。Process Bも同様です。後はこのハンドルを介してメソッドを呼ぶだけです。status()で随時ステータスを獲得しつつ、3ns後にProcess Aに対してkill()を行っています。Process Aとその子プロセスであるProcess Bが停止します。
`timescale 1ns/1ns
module top;
initial begin
process proc_a;
process proc_b;
$timeformat(-9, 0, " ns", 6);
fork
begin
proc_a = process::self();
fork
begin
proc_b = process::self();
delayPrint("Process B checkpoint", 2ns);
delayPrint("Process B finishing", 2ns);
end
join_none
delayPrint("Process A finishing", 4ns);
end
join_none
#2ns;
$display("%t: Process A's status is %p", $realtime, proc_a.status());
$display("%t: Process B's status is %p", $realtime, proc_b.status());
#1ns;
$display("%t: Killing Process A",$realtime);
proc_a.kill();
$display("%t: Process A's status is %p", $realtime, proc_a.status());
$display("%t: Process B's status is %p", $realtime, proc_b.status());
end
task automatic delayPrint(input string s,
input time dly = 0ns);
#dly;
$display(s);
endtask
endmodule
# KERNEL: 2 ns: Process A's status is WAITING
# KERNEL: 2 ns: Process B's status is RUNNING
# KERNEL: Process B checkpoint 1
# KERNEL: 3 ns: Killing Process A
# KERNEL: 3 ns: Process A's status is KILLED
# KERNEL: 3 ns: Process B's status is KILLED
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
本ソースコードはEDA Playground上に登録されています。
Process class example
シミュレータの非互換項目
本機能の再確認のためにEDA Playgroudで動作させてみましたが、複数のシミュレータで対応が不完全なものがありました。最新バージョンでは修正されている、もしくはシミュレータオプションにより回避できるかもしれませんがご注意ください。
参考文献
"9.7 Fine-grain process control". 1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language. pp. 229-231.