目录
今天在写验证环境的时候碰到一处自定义的copy函数,对其中的transaction哪里需要初始化理解出现偏差,因此查看整理了sv中关于对象得赋值以及copy的各种操作,总结如下
一、sv中类,声明,例化,初始化的概念
- 首先在sv中你可以创建一个class类,类中可以含有变量以及方法,也可以引用别的class类;
- 类需要声明和例化才能正常使用该类对应的对象,声明是声明一个变量,其中保存类对象的句柄。
- 例化是通过构造函数,创建对象,分配内存空间,并将声明的句柄指向这段内存空间。
- 初始化主要指的是一些变量,数组的初始化
二、类的句柄复制
类在声明时只是指定了一个指针句柄给变量,因此此时没有实体对象,当句柄指向另一个句柄指向的对象时,便构成了句柄复制,此时并未创建实体对象,举例代码如下
class a;
bit a = 1;
endclass
class b;
a a_1;
bit b = 0;
endclass
b b_1 b_2;
initial begin
b_1 = new();
b_2 = b_1; //此时b_2未创建对象,指向b_1对象,b_2中只能看到b_1中变量b,而且b_1改变 b_2也随
之改变,因为他们指的是同一个对象
b_1.b = 1;
$display("b_2.b = %0d,b_2.a_1.a = %0d",b_2.b,b_2.a_1.a);
end
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
result:b_2.b = 1,b_2.a_1.a = 1
三、类的浅拷贝
深拷贝和浅拷贝都是指拷贝一个对象,而不是句柄复制中的句柄。浅拷贝时,只会拷贝对象中的 成员变量句柄,而不会拷贝句柄所指向的对象中的内容;深拷贝时,不仅仅会拷贝当前对象的成员变量,还会拷贝实例中的句柄的对象内容,即进行深层次的复制直接代码举例:
module tb;
class trans1;
int A = 1,B = 2;
endclass
class trans2;
int A1 = 3,B1 = 4;
trans1 a = new(); // trans2 里边套一个trans1
endclass
initial begin
trans2 b = new();
// 浅拷贝
trans2 d = new b; // d浅拷贝b,只会拷贝b中的变量和a的句柄。
d.A1 = 23; // 更改d句柄指向的trans中的元素
d.a.A = 21; // 更改d句柄指向的trans中a句柄指向的对象的元素
#20;
$display("d.A1 = %0d , d.a.A = %0d",d.A1,d.a.A);
$display("b.A1 = %0d , b.a.A = %0d",b.A1,b.a.A);
end
endmodule
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
results:d.A1 = 23 ,d.a.A = 21 b.A1 = 3 , b.a.A = 21
可以看到,得出以下结论:
- 浅拷贝创建了另一个对象,类中的数据都被复制放到另一个对象中,与原来对象无关
- 而类中的引用并没有创建新对象,两个引用类的句柄指向同一个对象,共享改变
四、类的深拷贝
深拷贝需要自己定义copy方法并调用
class Transaction;
bit [31:0] addr,crc,data[8];
statistics stats;
static int count=0;
int id;
function new;
stats=new();
id=count++;
endfunction
function Transaction copy;
copy=new();
copy.addr=addr;
copy.data=data;
copy.crc=crc;
copy.stats=stats.copy();
id=count++;
endfunction
endclass
Transaction src,dst;
initial begin
src=new();
src.stats.startT=42;
dst=src.copy();
dst.stats.startT=96;
$display(src.stats.startT);
end
五、 clone函数
注意:类的多态,父类和子类同名函数必须保持(函数名一致,参数类型一致,返回类型一致)。
父类clone()是产生一个父类对象,子类clone()产生一个子类对象。
父类与子类clone()的返回值都是父类句柄!因此有时需要$cast()
class trans;
bit[31:0] data[];
int pkt_id;
int data_nidles;
int pkt_nidles;
bit rsp;
function trans clone(trans t = null); //传进来的都是父类句柄
if(t == null) t = new();
t.data = data;
t.pkt_id = pkt_id;
t.data_nidles = data_nidles;
t.pkt_nidles = pkt_nidles;
t.rsp = rsp;
return t;
endfunction
endclass
class chnl_trans extends trans;
int ch_id; // new member in child class
//clone function-1
function trans clone(trans t = null); //传进来的都是父类句柄
chnl_trans ct;
if(t == null)
ct = new();
else
void'($cast(ct, t)); //为了父类句柄指向子类对象,将父类句柄转化为子类句柄
ct.data = data;
ct.pkt_id = pkt_id;
ct.data_nidles = data_nidles;
ct.pkt_nidles = pkt_nidles;
ct.rsp = rsp;
ct.ch_id = ch_id; // new member
return ct;
initial begin: member_override
trans t1, t2;
chnl_trans ct1, ct2;
wait(b_member_override == 1); $display("b_member_override process block started");
ct1 = new();
ct1.pkt_id = 200;
ct1.ch_id = 2;
// t1 pointed to ct1's trans class data base t1-->ct1
t1 = ct1;
// t2 copied ct1's trans class data base t2--->ct1返回的子类
t2 = ct1.clone();
void'($cast(ct2, t2));//ct2 --->t2--->ct1返回的子类
$display("hahah ct1.pkt_id=%d",ct2.pkt_id);
$display("hahah ct2.ch_id =%d",ct2.ch_id);