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