static 和 automatic 修饰(systemverilog)

全局变量和局部变量

在讨论静态变量和动态变量之前,我们先说全局变量和局部变量的概念。

  • 局部变量的生命周期同其所在域,例如function/task中的变量,在方法调用结束后,这些变量的也将消失,所以它们是动态生命周期;
  • 全局变量是从仿真开始到结束一直存在的,例如module中的变量默认情况下全部为全局变量,这也可以理解为module中的变量是硬件电路中实际存在的信号和连接,所以它们是静态生命周期;

静态变量和动态变量

变量可以分为动态(automatic)和静态(static),静态变量的特点:

  • 该变量将被这个类的所有实例所共享,并且使用范围仅限这个类
  • 静态变量在声明时就应该对其初始化,它只初始化一次,也就是在仿真0时刻就存在。
  • 可以认为声明在类中的静态成员变量,它是保存在类中,而不是在对象中,它会一直存在的,不会因为对象被销毁而消失。
  • 静态变量可以在类没有被实例化的时候调用,通过 class::static_variable 的方式获取静态变量。

动态变量的特点:

  • 动态变量是类在实例化时,即调用构造函数new( )才会初始化。
  • 它的声明周期随着对象而存在,当对象被销毁时,这个变量就也就消失了。
  • 必须要在类被实例化之后才可以调用。

如下,使用静态变量count来计数所创建的实例数目:

class Transaction;
	static int count = 0;
	int id;
	function new();
		id = count++;
	endfunction 
endclass

Transaction t1,t2;
initial begin
	t1 = new(); // t1 中:count = 1,id =0
	t2 = new(); // t2 中:count = 2,id =1
	$display("t2中count=%0d和id=%0d",t2.count,t2.id);
	$display("Transaction中count=%0d",Transaction::count);	
end//Transaction类中:count = 2

解释代码:

  • 每例化一次transaction,count就自加1
  • 第一次在例化时,cout值为0,所以对象 t1 中的 id = 0;
  • 类的构造函数调用完后,使得count自加1,count = 1;
  • 第二次在例化时,cout值为1,所以对象 t2 中的 id = 1;
  • 可以通过Transaction::count的方式,访问类中的静态变量,此时类中的count = 2;

静态方法和动态方法

static 和 automatic 除了可以修饰类中的成员变量,还可以修饰 function 和 task,被static修饰的方法称为静态方法。
静态方法的特点:

  • 如果方法被static修饰,那么其内部所有的声明的变量都是 static 的;
  • 静态方法可以在类没有被实例化时被调用,通过 :: 操作符获取,具有全局的静态生命周期;
  • 如果方法被声明为static,那么在仿真开始时即会被创建,且可以被多个进程和方法共享;

动态方法的特点:

  • 如果方法被修饰为 automatic,那么其内部所有的声明的变量默认都是 automatic的;
  • 如果被修饰为 automatic,那么在进入该方法后,automatic变量会被创建,而离开该进程/方法后就被销毁;

静态方法和动态方法的区别,如下:

module static_test;
	function automatic int cnt1(input a);  // 函数内所有的变量均为automatic	
		int cnt = 0//这个变量在每次调用时都会初始化
	    cnt += a ;
	    return cnt;
	endfunction
	
	function static int cnt2(input a);  // 函数内所有的变量均为static
	    static int cnt = 0//这个static 变量 cnt只会初始化一次
	    cnt += a ;
	    return cnt;
	endfunction
	
	function int cnt3(input a);  // module中的方法默认为static
	    int cnt = 0//这个static 变量 cnt只会初始化一次
	    cnt += a ;
	    return cnt;
	endfunction
endmodule

initial begin
	$display("%0d",cnt1(1));  // 输出1
	$display("%0d",cnt1(1));  // 输出1
	$display("%0d",cnt2(1));  // 输出1
	$display("%0d",cnt2(1));  // 输出2
	$display("%0d",cnt3(1));  // 输出1
	$display("%0d",cnt3(1));  // 输出2
end

解释代码:

  • 函数声明为automatic或static时,其块内所有的变量都是automatic或static的;
  • automatic类型的变量随函数调用结束后就销毁了,下次再调用时,又会初始化;
  • static类型的变量随函数调用结束后不会被销毁,下次调用时也不需要重新初始化;
  • module内的方法默认是static的

SV中的规定

  • 在module、program、interface、task和function之外声明的变量拥有静态的生命周期,即存在于整个仿真阶段,这同C定义的静态变量一样。
  • 在module、interface和program内部声明,且在task、process或者function外部声明的变量也是static变量,且作用域在该块中。
  • 在module、program和interface中定义的task、function默认都是static类型。
  • 在过程块中(task、function、process)定义的变量均跟随它的作用域,即过程块的类型,如果过程块为static,则它们也默认为static,反之亦然。这些变量也可以由用户显式声明为automatic或者static。
  • 23
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小verifier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值