先明确下基本的概念
- block:块。一些关键字组成的一个范围区间,就叫做块。如 module … endmodue / task … endtask / begin … end / fork … join
- static lifetime:存活于整个仿真过程
1. 变量的范围(scope )
- module、interface、program、checker都提供了一个本地(local)的命名空间用于变量的声明。不同 block中命名同名的变量并不会冲突。
- 通过在building block中import package,可以共享package的声明空间(declaration space)。
- 引用一个变量时,会一层层往上找,找不到就会出错,找得到就没问题,但是可能想要的层次不对。
- 声明在module、program、interface、checker、task、function块外的变量的范围覆盖整个编译单元,即全局
【1】 下图中有四处声明了变量“a”并赋值,在begin…end块中,找到了a,故打印结果为1
【2】注释掉initial块中的声明,则在begin…end外围,my_top内查找变量a,故打印结果为2(可以看到my_top块中的声明的优先级是高于package中的)
【3】 注释掉module中的声明,则找到了package,故打印结果为3
【4】 注释掉package中的声明,结果报错,显示找不到a,这说明了两个module中的变量是不相关的
【5】在块的外围声明变量int a=5;发现打印结果为5。
2. 变量的声明周期(lifetime)
- 声明在module、program、interface、checker、task、function块外的变量的范围可以到整个编译单元,并且是static lifetime
例如上例5
对,你没看错,checker ... endchecker也是一个block
- 声明在module、program、interface、checker内,但是在task、process(begin…end等)、function外的变量,是局部范围,并且是static lifetime
例如上例2
- 声明在 static task、function、block的变量是局部范围的。default to static lifetime,其中的变量可以被automatic关键字显示地声明,那么将 have the lifetime of the call or block(随用随生成)
- 声明在 automatic task、function、block的变量是局部范围的。default to the lifetime of the call or block。其中的变量默认为automatic,但是可以被关键字static显示地声明,则have a static lifetime
2.1 总结
(1) scope和lifetime主要看变量在哪个“块”中声明,如果不在module、program、interface、checker、task、function中声明,则就是在最外层,所以范围就是全局的,是static lifetime
(2) 如果在module、program、interface、checker内,但是是在这些块中的task、function、process块外的,范围是局部的,是static lifetime
(3)在task、function、block中的则范围是局部的。lifetime默认与这些块是static/automatic一致,但是也可以对变量进行加static/automatic关键字进行显示声明,则lifetime与申明时加的关键字一致。
2.2 一个例子
3. 变量的初始化
- static变量在整个仿真时间内存在,所以static变量只会在仿真初期进行一次初始化。
- automatic变量是随时调用随时产生,所以每次调用时就会执行初始化。
4. 变量的存储
- static变量是静态分配的,被存放在固定位置
- automatic变量被存储在堆栈中
- 当多个线程调用同一个任务中的静态变量时,由于静态变量使用静态存储区,所以不同线程之间会串用这些静态变量。
【程序1说明】 下图中 task show()默认为static,repeat(5)时,共调用五次,起了五个线程,但是每个线程都阻塞在wait(a==6);不会有打印。继续往下执行,#10后,再起一个线程,此时传入给task show()的a的值为6。调用的6次show()中,因为show()为static,所以show()中的a为static,为同一静态存储区,所以前面五个线程现在a也为6了,故会打印6次。
所有调用static show()函数的线程,show()函数中的a都是同一个。
【程序2说明】 当将program声明为program automatic my_program;(或者声明 task automatic show(input int a); ),则为automatic,6个线程中的a为不同的存储区。故只有最后一个会打印,前面5个线程会一直阻塞在wait(==6);但整个initial 已经到底了,故仿真自动结束了。
所有调用automatic show()函数的线程,show()函数中的a都是独立的
5. for循环的循环变量
- for循环中的循环变量默认就是automatic。例如:在program 中声明的for循环,不管program是static还是automatic,for的循环变量都为 automatic。
program my_program;
initial begin
for(int i=0,i<3;i++) begin //i为automatic
automatic int k = i; //k为automatic,所以 automatic才能赋值给automatic
...
end
end
endprogram
program automatic my_program;
initial begin
for(int i=0,i<3;i++) begin //i为automatic
int k = i; //k为automatic,所以 automatic才能赋值给automatic
...
end
end
endprogram