每个类实例通常都具有其每个内部变量的副本。
class Packet;
bit [15:0] addr;
bit [7:0] data;
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
$display ("addr=0x%0h data=0x%0h", addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new (16'hdead, 8'h12);
p2 = new (16'hface, 8'hab);
p3 = new (16'hcafe, 8'hfc);
end
endmodule
Simulation Log
ncsim> run
addr=0xdead data=0x12
addr=0xface data=0xab
addr=0xcafe data=0xfc
ncsim: *W,RNQUIE: Simulation is complete.
每个类对象p1,p2,p3都将具有addr和data变量。
静态变量Static Variables
当类中的变量声明为静态时,该变量将是所有类实例中的唯一副本。 为了演示一个示例,我们将比较静态计数器与非静态计数器。 静态计数器使用static关键字声明,并命名为static_ctr,而普通计数器变量命名为ctr。 这两个计数器将在new()函数中递增,以便每次创建对象时更新它们。
class Packet;
bit [15:0] addr;
bit [7:0] data;
static int static_ctr = 0;
int ctr = 0;
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
static_ctr++;
ctr++;
$display ("static_ctr=%0d ctr=%0d addr=0x%0h data=0x%0h", static_ctr, ctr, addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new (16'hdead, 8'h12);
p2 = new (16'hface, 8'hab);
p3 = new (16'hcafe, 8'hfc);
end
endmodule
您会看到静态计数器在所有类对象p1,p2和p3之间共享,因此当创建三个数据包时它将增加到3。 另一方面,普通计数器变量ctr没有声明为静态,因此每个类对象都有其自己的副本。 这就是为什么在创建所有三个对象后ctr仍为1的原因。
Simulation Log
ncsim> run
static_ctr=1 ctr=1 addr=0xdead data=0x12
static_ctr=2 ctr=1 addr=0xface data=0xab
static_ctr=3 ctr=1 addr=0xcafe data=0xfc
ncsim: *W,RNQUIE: Simulation is complete.
想要知道直到特定时间之前生成的数据包总数的情况下,将变量声明为静态变量可能非常有用。
静态功能
静态方法遵循所有类作用域和访问规则,但是唯一的区别是,即使没有类实例化,也可以在类外部调用它。 静态方法无法访问非静态成员,但可以直接访问静态类的属性或调用同一类的静态方法。 静态方法也不能是虚拟的。 使用类名称的静态函数调用需要通过作用域运算符::进行。
class Packet;
static int ctr=0;
function new ();
ctr++;
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d", ctr);
endfunction
endclass
module tb;
Packet pkt [6];
initial begin
for (int i = 0; i < $size(pkt); i++) begin
pkt[i] = new;
end
Packet::get_pkt_ctr(); // 使用::操作符进行静态调用
pkt[5].get_pkt_ctr(); // Normal call using instance
end
endmodule
Simulation Log
ncsim> run
ctr=6
ctr=6
ncsim: *W,RNQUIE: Simulation is complete.
让我们添加一个名为mode的非静态成员,并尝试从我们的静态函数中调用它。
class Packet;
static int ctr=0;
bit [1:0] mode;
function new ();
ctr++;
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d mode=%0d", ctr, mode);
endfunction
endclass
不允许这样做,将导致编译错误。
$display ("ctr=%0d mode=%0d", ctr, mode);
|
ncvlog: *E,CLSNSU (static-function.sv,10|40): A static class method cannot access non static class members.
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-static-variables-functions