构造函数只是一种用于创建特定类数据类型的新对象的方法。
Constructors
C / C ++需要复杂的内存分配技术,并且不正确的取消分配可能导致内存泄漏和其他行为问题。 SystemVerilog虽然不是编程语言,但能够简单地构造对象并自动进行垃圾回收。
当明确定义类构造函数时
// 使用32位变量定义一个名为“ Packet”的类以存储地址
//在新函数(也称为构造函数)中将“ addr”初始化为32'hfade_cafe
class Packet;
bit [31:0] addr;
function new ();
addr = 32'hfade_cafe;
endfunction
endclass
module tb;
// 创建一个名为“ pkt”的类句柄并实例化该类对象
initial begin
// 实例化对象时,将调用类的构造函数new()fn
Packet pkt = new;
// 显示类变量-由于在实例化期间调用了构造函数,因此该变量的大小应为32'hfade_cafe
$display ("addr=0x%0h", pkt.addr);
end
endmodule
Simulation Log
ncsim> run
addr=0xfadecafe
ncsim: *W,RNQUIE: Simulation is complete.
在上面的示例中,变量声明创建了Packet类的对象,并将自动在该类中调用new()函数。 new()函数称为类构造函数,是一种使用一些值初始化类变量的方法。 请注意,它没有返回类型,并且是非阻塞的。
隐式调用类构造函数
如果该类没有显式的new()函数,则将自动提供一个隐式的new方法。 在这种情况下,addr初始化为零,因为它的类型为bit,其默认值为零。
// 用一个名为“ addr”的变量定义一个简单的类
// 请注意,此处未定义new()函数
class Packet;
bit [31:0] addr;
endclass
module tb;
// 当实例化类对象时,该工具将隐式定义构造函数并调用该构造函数。
initial begin
Packet pkt = new;
$display ("addr=0x%0h", pkt.addr);
end
endmodule
Simulation Log
ncsim> run
addr=0x0
ncsim: *W,RNQUIE: Simulation is complete.
继承类的行为
派生类的new方法将首先使用super.new()调用其父类构造函数。 基类构造函数完成后,派生类中定义的每个属性都将初始化为默认值,然后将执行新方法中的其余代码。
// 定义一个简单的类,并在new()函数中初始化类成员“data”
class baseClass;
bit [15:0] data;
function new ();
data = 16'hface;
endfunction
endclass
Pass a value as argument to the new function in this case and print
//定义从上述类扩展而来的子类,并增加成员
// 构造函数new()函数接受一个值作为参数,默认为2
class subClass extends baseClass;
bit [3:0] id;
bit [2:0] mode = 3;
function new (int val = 2);
// 子类中的new()函数使用“ super”关键字在基类中调用新函数
super.new ();
// 将通过参数获得的值分配给类成员
id = val;
endfunction
endclass
module tb;
initial begin
// 为子类创建两个句柄
subClass sc1, sc2;
//实例化子类并显示成员变量值
sc1 = new ();
$display ("data=0x%0h id=%0d mode=%0d", sc1.data, sc1.id, sc1.mode);
// 在这种情况下,将值作为参数传递给新函数并打印
sc2 = new (4);
$display ("data=0x%0h id=%0d mode=%0d", sc2.data, sc2.id, sc2.mode);
end
endmodule
在上面的示例中,创建subClass对象时,它将首先调用subClass的new()函数。 当通过super关键字调用时,它从那里分支到baseClass的new()方法。 接下来将初始化数据,然后控件返回到子类。 id初始化为4后,将执行新方法。
Simulation Log
ncsim> run
data=0xface id=2 mode=3
data=0xface id=4 mode=3
ncsim: *W,RNQUIE: Simulation is complete.
新函数声明为静态或虚拟(new function is declared as static or virtual)
class ABC;
string fruit;
// 请注意,构造函数被定义为“virtual”,这是不允许的
// 在SystemVerilog中。类构造函数也不能是“静态(static)”的
virtual function new ();
fruit = "Apple";
endfunction
endclass
//实例化类对象并打印其内容
module tb;
initial begin
ABC abc = new();
$display ("fruit = %s", abc.fruit);
end
endmodule
virtual function new ();
|
ncvlog: *E,BADQAL (testbench.sv,6|21): Lifetime or qualifier(s) 'virtual' not allowed before function new declaration.
类型化构造函数(Typed constructors)
此处的区别在于,您可以调用子类的new()函数,但可以在单个语句中将其分配给基类的句柄。 这是通过使用范围运算符::引用子类的new()函数来完成的,如下所示。
class C;
endclass
class D extends C;
endclass
module tb;
initial begin
C c = D::new;
end
endmodule
基类C的变量c引用了一个新构造的类型D的对象。这实现了与下面给出的代码相同的效果。
module tb;
initial begin
D d = new;
C c = d;
end
endmodule
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-class-constructor