在SystemVerilog面向对象编程中,只有在类句柄执行new()函数之后才会创建对象,分配内存空间。
packet pkt_1;pkt_1 = new();packet pkt_2;pkt_2 = new pkt_1;
在上面的代码中,创建了pkt_2对象,其中的属性(properties)复制自pkt_1对象,这就是浅复制(shallow copy)
在浅复制过程中,给pkt_2分配了新的地址空间,然后将pkt_1中的属性赋值到pkt_2中。但是需要注意的是,浅复制中pkt_1的层次化对象(Objects)中是不会被复制的,只会复制这个层次化对象的句柄。所以,要想赋值层次化的类,需要编写定制化的复制函数执行深复制(deep copy).
从上图可以看出
pkt_1 = new()
为句柄pkt_1分配了地址空间0x1234,然后其中的属性变量默认初值0
pkt_1.addr = 10 ;pkt_1.data = 20 ;
为pkt_1对象中的属性变量赋值
pkt_2 = new pkt_1
完成了两个工作,给对象pkt_2分配内存空间0x5678,然后将pkt_1.addr赋值给pkt_2.addr ,将pkt_1. data赋值给pkt_2. data
但是,如果packet是一个层次化的类,pkt_1对象中还存在一个底层次的address_range类对象ad_r,浅复制就存在问题了。
在上面的图片中
pkt_1 = new()
分别给pkt_1和ad_r分配了地址空间0x1234和0xabcd,pkt_1.addr、pkt_1.data、pkt_1. ad_r. s_addr和pkt_1. ad_r. e_addr、默认初值都为0
在同样执行
pkt_2 = new pkt_1
之后,结果就存在问题了。仿真器给pkt_2分配了新的地址空间0x5678,并且将pkt_1.addr赋值给pkt_2.addr ,将pkt_1. data赋值给pkt_2. data,但是并没有给pkt_2.ad_r分配新的地址空间,其地址空间仍然为0xabcd,也就是说pkt_2.ad_r和pkt_1.ad_r指向的是同一个地方,这就是浅复制的限制之处。
下面分别用示例展示对象赋值和浅复制。
对象赋值
class packet; bit[31:0] addr; bit[31:0] data; function new(); addr = 32'h10; data = 32'hFF; endfunction function void display(); $display("---------------------------------------------------------"); $display("t addr =%0h",addr); $display("t data =%0h",data); $display("---------------------------------------------------------"); endfunctionendclass // -- module ---module class_assignment; packet pkt_1; packet pkt_2; initial begin pkt_1 = new(); //creating pkt_1object pkt_1.display(); pkt_2 = pkt_1; //creating pkt_2 object and assign pkt_1 topkt_2 pkt_2.display(); //changing values with pkt_2 handle pkt_2.addr = 32'h68; pkt_2.display(); pkt_1.display(); endendmodule
上面依次创建了pkt_1和pkt_2对象,然后将pkt_1的句柄赋值给pkt_2。可以发现pkt_2.addr的改变也改变了pkt_1.addr,因为pkt_2和pkt_1共享地址空间,也就是一样东西两个名头而已。
#---------------------------------------------------------# addr =10# data =ff#---------------------------------------------------------#---------------------------------------------------------# addr =10# data =ff#---------------------------------------------------------#---------------------------------------------------------# addr =68# data =ff#---------------------------------------------------------#---------------------------------------------------------# addr =68# data =ff#---------------------------------------------------------
浅复制
class address_range; bit[31:0] s_address; bit[31:0] e_address ; function new(); s_address = 10; e_address = 50; endfunctionendclass class packet; bit[31:0] addr; bit[31:0] data; address_range ad_r; //class handle function new(); addr = 32'h10; data = 32'hFF; ad_r = new(); //creating object endfunction function void display(); $display("---------------------------------------------------------"); $display("t addr =%0h",addr); $display("t data =%0h",data); $display("t s_address =
",ad_r.s_address); $display("t e_address =
",ad_r.e_address); $display("---------------------------------------------------------"); endfunctionendclass module class_shallow_copy; packet pkt_1; packet pkt_2; initial begin pkt_1 = new(); //creating pkt_1object pkt_1.display(); pkt_2 = new pkt_1; //creatingpkt_2 object and shallow copying pkt_1 to pkt_2 pkt_2.display(); pkt_2.addr = 32'h68; pkt_2.ad_r.s_address = 60; pkt_2.ad_r.e_address = 80; pkt_2.display(); pkt_1.display(); endendmodule
上面依次创建了pkt_1和pkt_2对象,然后将pkt_1的浅复制给pkt_2。可以发现pkt_2. addr的改变没有改变pkt_1.addr,pkt_2.ad_r.s_address和pkt_2.ad_r.e_address的改变也改变了pkt_1.ad_r.s_address和pkt_1.ad_r.e_address,因为pkt_2和pkt_1的低层次类对象pkt_2.ad_r和pkt_1.ad_r共享地址空间。
# ---------------------------------------------------------# addr =10# data =ff# s_address = 10# e_address = 50#---------------------------------------------------------#---------------------------------------------------------# addr =10# data =ff# s_address = 10# e_address = 50#---------------------------------------------------------#---------------------------------------------------------# addr =68# data =ff# s_address = 60# e_address = 80# ---------------------------------------------------------#---------------------------------------------------------# addr =10# data =ff# s_address = 60# e_address = 80#---------------------------------------------------------