SystemVerilog中的静态属性

嵌入式技术

1369人已加入

描述

一般来说,每个类实例都有它自己的变量,也就是说类的内存空间是动态分配和释放的。同一个类的不同实例,即使变量名称相同,实际上也是不同的东西。

有时候,我们希望一些变量在一个类的所有实例中共享,那么在声明这个变量时就需要使用关键字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影响。

审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分