嵌入式技术
一般来说,每个类实例都有它自己的变量,也就是说类的内存空间是动态分配和释放的。同一个类的不同实例,即使变量名称相同,实际上也是不同的东西。
有时候,我们希望一些变量在一个类的所有实例中共享,那么在声明这个变量时就需要使用关键字static。
可以理解为静态属性隶属于这个类,而不是某个类的实例,这个静态属性的内存空间在编译时就已经完成了分配,而不需要等待类的实例化。
静态属性内存空间的分配在仿真时间0之前就已经完成了。
下面是一个在不同类实例之间共享的静态属性示例
module class_TOP( ); class base; static logic [31:0] data; //static property endclass : base base base1, base2; initial begin; base1 = new( ); base2 = new( ); base1.data = 32'h f00_f0f0; $display("base2.data = %h",base2.data); end initial #10 $fnish(2); endmodule
在这个例子中,我们将“data”声明为静态属性。然后,实例化为" base1 "和" base2 "。然后我们赋值“base1”实例中的“data”的值,并从“base2”实例访问。
仿真Log:
base2.data = ff00f0f0 $fnish at simulation time 10 V C S S i m u l a t i o n R e p o r t
从仿真log中可以看出,使用对象句柄“base1”赋值的属性,可以通过句柄“base2”访问到。这是因为“data”被声明为static,被所有实例共享。
如果把“static”去掉会发生什么?最终句柄“base2”访问的“data”值就是“XXXXXXXX”
下面是类中静态属性的最经典用法,统计这个类实例化了多少次?
module class_TOP( ); class packet; static int packet_cnt; function new( ); packet_cnt = packet_cnt+1; $display("From new ( ) :: packet_cnt = %0d",packet_cnt); endfunction endclass initial begin packet p1 = new; packet p2 = new; end endmodule
仿真log:
From new ( ) :: packet_cnt = 1 From new ( ) :: packet_cnt = 2 V C S S i m u l a t i o n R e p o r t
在第二次实例化时,packet_cnt会在第一次实例化的基础上加1.
下面是展示静态属性和动态属性区别的一个例子:
class PCIe; static int addr = 0; //Static property int data = 0; //Dynamic property function new (); addr++; data++; $display ("addr=%0d data=%0d", addr, data); endfunction endclass module tb; initial begin PCIe p1, p2, p3; p1 = new (); p2 = new (); p3 = new (); end endmodule
仿真log:
addr=1 data=1 addr=2 data=1 addr=3 data=1 V C S S i m u l a t i o n R e p o r t
我们可以看到addr被声明为static,而data默认是automatic。所以每一次实例化时,addr都会在前一个实例化的基础上加1,而data则每次都是1(因为每个实例化都有自己的data内存分配)
下面再看一个相对绕一点的例子:
module class_TOP( ); class packet; static int packet_cnt; //Static property int tag; //Dynamic property function new( ); packet_cnt = packet_cnt+1; tag = packet_cnt; endfunction function void disp( ); $display("packet_cnt = %0d tag = %0d",packet_cnt, tag); endfunction endclass initial begin packet p1 = new; packet p2 = new; p1.disp; p2.disp; end endmodule
仿真log:
packet_cnt = 2 tag = 1 packet_cnt = 2 tag = 2
我们在packet实例化两次(p1和p2)之后分别执行p1和p2的disp函数。
此时packet_cnt已经被加到2,所以最后打印的packet_cnt均为2,因为tag是automatic的,所以p1的tag为1,不被p2影响。
全部0条评论
快来发表一下你的评论吧 !