SystemVerilog引入了面向对象(object-oriented)的类(class) 抽象数据类型。
可以通过对象句柄动态创建,删除,赋值和访问对象。
类中包含了数据和对该数据进行操作的子例程(functions 和tasks)。类中的数据称为类属性(properties),其子例程称为方法(methods)。类属性和方法一起定义了某种对象的内容和功能。
Objects
对象(object )是类的实例(instance )。
对象的使用首先需要声明对象所属的类的类型(包含object handle),然后创建该类的对象(使用new函数),并对其进行赋值和访问。
program class_t;
class packet;
// members in class
integer size;
integer payload [];
integer i;
// Constructor
function new (integer size);
begin
this.size = size;
payload = new[size];
for (i=0; i < this.size; i ++) begin
payload[i] = $random;
end
end
endfunction
// Task in class (object method)
task print ();
begin
$write("Payload : ");
for (i=0; i < size; i ++) begin
$write("%x ",payload[i]);
end
$write("\n");
end
endtask
// Function in class (object method)
function integer get_size();
begin
get_size = this.size;
end
endfunction
endclass
packet pkt;
initial begin
pkt = new(5);
pkt.print();
$display ("Size of packet %0d",pkt.get_size());
end
endprogram
输出
Payload : 12153524 c0895e81 8484d609 b1f05663 06b97b0d
Size of packet 5
Static class members
当一个对象在多个地方使用并且我们希望该对象的某个成员在所有实例中具有相同的值。假设我们在第一个对象实例中修改了变量,并且我们希望将值反映在其余实例中。为此,SystemVerilog提供了静态类成员。
前面有static的任何成员都成为静态(static)类成员
`define PRINT task print (); \
begin \
$write("%s -> Size is %0d\n",this.name, this.size); \
end \
endtask
program class_static;
// Class with constructor, with no parameter
class A;
// Make size as static
static integer size;
string name;
// Constructor
function new (string name);
begin
this.name = name;
this.size = 0;
end
endfunction
// Increment size task
task inc_size();
begin
this.size ++;
$write("%s -> size is incremented\n",this.name);
end
endtask
// Task in class (object method)
`PRINT
endclass
A a,b,c;
initial begin
a = new("A");
b = new("B");
c = new("C");
a.inc_size();
a.print();
b.print();
c.print();
c.inc_size();
a.print();
b.print();
c.print();
end
endprogram
输出
A -> size is incremented
A -> Size is 1
B -> Size is 1
C -> Size is 1
C -> size is incremented
A -> Size is 2
B -> Size is 2
C -> Size is 2
constant class members
类属性可以像任何其他SystemVerilog变量一样通过const声明read-only。constants 变量只能在声明时或者类构造函数中赋值。
`define PRINT task print (); \
begin \
$write("%s -> Size is %0d\n",this.name, this.Lsize); \
$write("%s -> Size is %0d\n",this.name, this.Gsize); \
end \
endtask
program class_constant;
class A;
const integer Gsize = 64; // constant value
const integer Lsize;
string name;
// Constructor
function new (string name);
begin
this.name = name;
this.Lsize = 100; // only one assignment in new
end
endfunction
// This is not allowed
task modify();
begin
// This is wrong
//this.Lsize ++;
// This is wrong
//this.Gsize ++;
end
endtask
`PRINT
endclass
A a;
initial begin
a = new("A");
a.print();
end
endprogram
输出
A -> Size is 100
A -> Size is 64
Assignments
将一个对象复制给另一个对象与将变量复制给另一个变量相同。在对象复制中,副本是shallow copy,因为它不会复制任何嵌套对象。
要进行deep copy,需要自定义task。 下面的示例显示了如何进行自定义复制。
program class_copy;
class A ;
integer j = 5;
task print();
begin
$display("j is %0d",j);
end
endtask
endclass
class B ;
integer i = 1;
A a = new;
task print();
begin
$display("i is %0d",i);
a.print();
end
endtask
// custom deep copy task
task copy(ref B bb);
begin
bb = new this;
bb.a = new this.a;
end
endtask
endclass
initial begin
B b1,b2,b3;
$display("Testing shallow copy");
b1 = new; // Create an object of class B
b1.print();
b2 = new b1; // Create an object that is a copy of b1
b2.print();
b2.i = 10; // i is changed in b2, but not in b1
b2.a.j = 50; // change a.j, shared by both b1 and b2
b2.print();
b1.print(); // Updated due to shallow copy
// Now do a deep copy
$display("Testing deep copy");
b1.copy(b3) ; // Create an object that is a deep copy of b1
b3.print();
b3.i = 100; // i is changed in b3, but not in b1
b3.a.j = 500;// j is changes in b3, but not in b1
b3.print();
// i and J should not change due to deep copy
b1.print();
end
endprogram
输出
Testing shallow copy
i is 1
j is 5
i is 1
j is 5
i is 10
j is 50
i is 1
j is 50
Testing deep copy
i is 1
j is 50
i is 100
j is 500
i is 1
j is 50
本文转载自公众号:芯片数字实验室
原文链接:https://mp.weixin.qq.com/s/y8bbYmnM7aNS\_VjTLrEUDA
未经作者同意,请勿转载!
推荐阅读
想了解更多内容,欢迎关注芯片数字实验室专栏