Automatic/static
automatic/staticは、task/functionの前、あるいは変数の前に付けることができ、変数のライフタイムに影響を与える。
task/functionの前に付けた場合は、その中で宣言される変数全てに影響を与える。何も指定しない場合は、staticが指定されたのと同じ動作をする。変数の前に付けた場合、その変数個々のライフタイムに影響を与える。
automatic/staticともC言語のauto/staticと同様である。automaticの場合は、そのtask/functionが呼ばれる毎に変数の領域が確保される。従って、そのtask/functionが呼び出されるたびに、変数の初期化をしてやらなければならない。staticの場合は常に同じ領域が使用される。二回目以降にtask/functionを呼んだときは、前回の結果が保持されている。
Verilog95では全てがstatic扱いになっており、Verilog2001でtask/functionに対するautomatic宣言が追加された。SystemVerilogでは、変数個々に対してstatis/automaticが宣言できるようになった。
それぞれのライフタイムを確認するためのサンプルコードを以下に示す。
module test1();
initial begin
$display("Test1 -- No lifetime Specified.");
lifeTimeTest1(); lifeTimeTest1(); lifeTimeTest1();
$display("Test2 -- Static Task(Should be same as no spec).");
lifeTimeTest2(); lifeTimeTest2(); lifeTimeTest2();
$display("Test3 -- Automatic Task.");
lifeTimeTest3(); lifeTimeTest3(); lifeTimeTest3();
$display("Test4 -- Automatic Task with static int i.");
lifeTimeTest4(); lifeTimeTest4(); lifeTimeTest4();
end
function void lifeTimeTest1();
int i = 0, j = 0;
$display(" i = %d, j = %d", i, j);
i++; j++;
endfunction
function static void lifeTimeTest2();
int i = 0, j = 0;
$display(" i = %d, j = %d", i, j);
i++; j++;
endfunction
function automatic void lifeTimeTest3();
int i = 0, j = 0;
$display(" i = %d, j = %d", i, j);
i++; j++;
endfunction
function automatic void lifeTimeTest4();
static int i = 0; int j = 0;
$display(" i = %d, j = %d", i, j);
i++; j++;
endfunction
endmodule
結果は以下のとおり。
# 6.5e
# vsim -do {run -all; quit} -c test1
# Loading sv_std.std
# Loading work.test1
# run -all
# Test1 -- No lifetime Specified.
# i = 0, j = 0
# i = 1, j = 1
# i = 2, j = 2
# Test2 -- Static Task(Should be same as no spec).
# i = 0, j = 0
# i = 1, j = 1
# i = 2, j = 2
# Test3 -- Automatic Task.
# i = 0, j = 0
# i = 0, j = 0
# i = 0, j = 0
# Test4 -- Automatic Task with static int i.
# i = 0, j = 0
# i = 1, j = 0
# i = 2, j = 0
# quit
通常は、シミュレーション時のメモリ消費量が大きくなるということを除けば、全てデフォルトのstaticのままで困ることはないだろう。
automaticが重要になるのは、以下のように同じタイミングで、複数の箇所からtaskが呼ばれたときの振る舞いになる。以下のサンプルコートを見てほしい。
module test2();
initial begin
$display("Static Task Call");
fork
lifeTimeTestA1(0);
lifeTimeTestA1(1);
join
$display("Automatic Task Call");
fork
lifeTimeTestA2(0);
lifeTimeTestA2(1);
join
end
task lifeTimeTestA1(int i);
int tmp;
tmp = i + 5;
#1 $display(" value = %d", tmp);
endtask
task automatic lifeTimeTestA2(int i);
int tmp;
tmp = i + 5;
#1 $display(" value = %d", tmp);
endtask
endmodule
lifeTimeTestA1では変数tmpがstaticであるため、同時に複数回呼び出されると、その結果が意図しないものになってしまう。lifeTimeTestA2では、automaticを宣言しているため、同時に呼び出されても、task間での干渉が発生することは無い。
# 6.5e
# vsim -do {run -all; quit} -c test2
# Loading sv_std.std
# Loading work.test2
# run -all
# Static Task Call
# value = 6
# value = 6
# Automatic Task Call
# value = 5
# value = 6
# quit