对象只有在对于一个class句柄使用new方法来可以被创造。
packet pkt_1;
pkt_1 = new();
packet pkt_2;
pkt_2 = pkt_1;
在上面的代码我们可以看出,只是为句柄pkt_1创建了对象,而pkt_2仅仅只是类packet的一个句柄。随后pkt_1被赋值给pkt_2,由于只有一个对象被创造,因此pkt_1和pkt_2这两个句柄都指向同一个对象。因此两者时相互影响的,一个句柄对对象做出了改动,那么也会影响另一个句柄。如下图所示:
下面举一个类赋值的例子:
class packet;
//class properties
bit [31:0] addr ;
bit [31:0] data ;
bit write ;
string pkt_type;
//constructor
function new();
addr = 32'h10 ;
data = 32'hFF ;
write = 1 ;
pkt_type = "GOOD_PKT" ;
endfunction
//method to display class properties
function void display();
$display("---------------------------------------------");
$display("\t addr = %0d", addr);
$display("\t data = %0h", data);
$display("\t write = %0d", write);
$display("\t pkt_type = %0s", pkt_type);
$display("---------------------------------------------");
endfunction
endclass
module class_assignment;
packet pkt_1 ;
packet pkt_2 ;
initial begin
pkt_1 = new();
$display("\t*** calling pkt_1 display ***");
pkt_1.display();
//assign pkt_1 to pkt_2
pkt_2 = pkt_1;
$display("\t*** calling pkt_2 displlay ***");
pkt_2.display();
//changing value with pkt_2 handle
pkt_2.addr = 32'hAB;
pkt_2.pkt_type = "BAD_PKT";
//changes made with pkt_2 handle will reflect on pkt_1
$display("\t*** calling pkt_1 display ***");
pkt_1.display();
end
endmodule
输出结果是:
由这个例子可以看出通过句柄pkt_2对对象的改动的影响可以同步到pkt_1加载的对象上。
shallow copy 浅拷贝
上例子的赋值并没有创造出新的存储空间,而浅拷贝可以重新分配新的存储空间,一个例子如下:
packet pkt_1;
pkt_1 = new();
packet pkt_2;
pkt_2 = new pkt_1;
浅拷贝可以分配存储空间,并且拷贝变量的值,并且可以返回这块memory的句柄。但是需要注意的时不会赋值对象,只是赋值句柄。
但是这样又存在一个问题,但一个类的实例作为另一个类的成员时,就会出现不足。在下面的例子中,类packet又一个address_range的实例ad_r。对于pkt_1 new之后,就会分配addr,data和一个句柄的内存空间。但是当使用浅拷贝时,pkt_2的句柄只会单纯的拷贝句柄值,但是pkt_2的成员ad_r仍然指向原来pkt_1中的成员ad_r指向的内存空间,因此这样就会相互影响。
// --- class ----
class address_range;
bit [31:0] start_address ;
bit [31:0] end_address ;
function new();
this.start_address = 10;
this.end_address = 50;
endfunction
endclass
//--- class ---
class packet;
//class properties
bit [31:0] addr ;
bit [31:0] data ;
address_range ar ; //class handle
//constructor
function new();
addr = 32'h10 ;
data = 32'hFF ;
ar = new() ; //creating object
endfunction
//method to display class properties
function void display();
$display("---------------------------------------------------");
$display("\t addr = %0h", addr);
$display("\t data = %0h", data);
$display("\t start_address = %0d", ar.start_address);
$display("\t end_address = %0d", ar.end_address);
$display("---------------------------------------------------");
endfunction
endclass
//--- module ---
module class_assignment;
packet pkt_1 ;
packet pkt_2 ;
initial begin
pkt_1 = new(); //creating pkt_1 object
$display("\t *** calling pkt_1 display ***");
pkt_1.display();
pkt_2 = new pkt_1; //creating pkt_2 object and coping pkt_1 to pkt_2
$display("\t *** calling pkt_2 display ***");
pkt_2.display();
//changing values with pkt_2 handle
pkt_2.addr = 32'h68;
pkt_2.ar.start_address = 60;
pkt_2.ar.end_address = 80;
$display("\t *** calling pkt_1 display after changing pkt_2 properties ***");
//changing made to pkt_2.ar properties reflected on pkt_1.ar,so only handle of the object get copied, this is called shallowed copy
pkt_1.display();
$display("\t *** calling pkt_2 display after changing pkt_2 properties ***");
pkt_2.display();
end
endmodule
其输出结果是:
深拷贝
systemverilog的深拷贝拷贝它所有的类成员和嵌套拷贝,浅拷贝只是拷贝句柄。为了实现这样的机制,需要用户自己增加自定义方法,编译器没这么智能。下图,类address_range定义了返回句柄的方法copy,他会创建新的存储区域,并把指针返回。类packet定义了拷贝方法copy,该方法创建新的packet实例,并把调用实例的addr和data值赋给copy的addr和data,同时调用addr_range的copy方法,从而新建存储区域。
其描述代码如下:
//-- class ---
class address_range;
bit [31:0] start_address;
bit [31:0] end_address ;
function new();
start_address = 10;
end_address = 50;
endfunction
//copy method
function address_range copy;
copy = new();
copy.start_address = this.start_address;
copy.end_address = this.end_address;
return copy;
endfunction
endclass
//-- class ---
class packet;
//class properties
bit [31:0] addr;
bit [31:0] data;
address_range ar; //class handle
//constructor
function new();
addr = 32'h10;
data = 32'hFF;
ar = new(); //creating object
endfunction
//method to display class prperties
function void display();
$display("---------------------------------------------------------");
$display("\t addr = %0h",addr);
$display("\t data = %0h",data);
$display("\t start_address = %0d",ar.start_address);
$display("\t end_address = %0d",ar.end_address);
$display("---------------------------------------------------------");
endfunction
//copy method
function packet copy();
copy = new();
copy.addr = this.addr;
copy.data = this.data;
copy.ar = ar.copy;//calling copy function of tr
return copy;
endfunction
endclass
// -- module ---
module class_assignment;
packet pkt_1;
packet pkt_2;
initial begin
pkt_1 = new(); //creating pkt_1 object
$display("\t**** calling pkt_1 display ****");
pkt_1.display();
pkt_2 = new(); //creating pkt_2 object
$display("\t**** calling pkt_2 display ****");
pkt_2.display();
pkt_2 = pkt_1.copy(); //calling copy method
//changing values with pkt_2 handle
pkt_2.addr = 32'h68;
pkt_2.ar.start_address = 60;
pkt_2.ar.end_address = 80;
$display("\t**** calling pkt_1 display after changing pkt_2 properties ****");
pkt_1.display();
$display("\t**** calling pkt_2 display after changing pkt_2 properties ****");
pkt_2.display();
end
endmodule
其输出结果为:
**** calling pkt_1 display ****
---------------------------------------------------------
addr = 10
data = ff
start_address = 10
end_address = 50
---------------------------------------------------------
**** calling pkt_2 display ****
---------------------------------------------------------
addr = 10
data = ff
start_address = 10
end_address = 50
---------------------------------------------------------
**** calling pkt_1 display after changing pkt_2 properties ****
---------------------------------------------------------
addr = 10
data = ff
start_address = 10
end_address = 50
---------------------------------------------------------
**** calling pkt_2 display after changing pkt_2 properties ****
---------------------------------------------------------
addr = 68
data = ff
start_address = 60
end_address = 80
---------------------------------------------------------