sv中句柄复制,浅拷贝深拷贝详解以及clone函数

目录

一、sv中类,声明,例化,初始化的概念

二、类的句柄复制

三、类的浅拷贝

四、类的深拷贝

五、 clone函数

今天在写验证环境的时候碰到一处自定义的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);