1丶为什么这么做?
我们将一些公共函数封装进Package,方便我们重用,尤其是继承项目,好处尤为明显;
其次,这样做更符合高内聚,低耦合的编码要求。
2丶问题
package comm_utils_pkg;
`include "uvm_macros.svh"
import uvm_pkg::*;
function void bits2byte(bit qin[$], output bit[7:0] qout[$]);
bit[7:0] tmp;
int bs = qin.size();
`uvm_info("bits2byte", $sformatf("input queue size is %0d.", bs), UVM_LOW)
while(qin.size() > 0) begin
for(int i = 0; i < 8; i++)
tmp[i] = qin.pop_front();
qout.push_back(tmp);
end
endfunction
endpackageSystemVerilog调试:
comm_utils_pkg::bits2byte({0, 0}, qout0);
$display(qout0);
comm_utils_pkg::bits2byte({1, 1}, qout0);
$display(qout0);
/*
*打印结果:
*UVM_INFO comm_utils_pkg.sv(8) @ 100000: reporter [bits2byte] input queue size is 0.
*'{'h0}
*UVM_INFO comm_utils_pkg.sv(8) @ 100000: reporter [bits2byte] input queue size is 0.
*'{'h0, 'h3}
*/SystemVerilog从输出结果来看有两个问题:
- function
bits2byte中的输入队列的大小打印结果为0。我们明明输入的队列不为空,它为什么输出会是0? - 第二次输出的
qout0,期望结果应该是'{'h3},为什么会是'{'h0, 'h3}?而且多出来的那一个元素貌似是上一次执行输出的结果。
3丶原因
Package中声明的function和变量(包括function内部声明的变量) 默认是static修饰的,是静态的,而静态变量在编译阶段就赋初值了,此时qin队列当然是空的,变量bs初值被赋为了0,所以我们打印bs出来的自然是0。
同样Package中function的输出形参qout也是静态的,它会把多次调用function输出的结果都保存下来,然后再复制给我们传入的队列。所以可以看到我们打印的队列是在不断累加。
4丶解决
1.考虑其静态属性,在function中使用qout队列前,将其delete(),删除之前缓存的结果。不好,容易埋下隐患。
2.将Package中的function显式声明为automatic类型的,将其声明为动态的。
package comm_utils_pkg;
`include "uvm_macros.svh"
import uvm_pkg::*;
function automatic void bits2byte(bit qin[$], output bit[7:0] qout[$]);
bit[7:0] tmp;
int bs = qin.size();
`uvm_info("bits2byte", $sformatf("input queue size is %0d.", bs), UVM_LOW)
while(qin.size() > 0) begin
for(int i = 0; i < 8; i++)
tmp[i] = qin.pop_front();
qout.push_back(tmp);
end
endfunction
endpackageSystemVerilog5丶结论
Package中声明的function和变量(包括function内部声明的变量)默认是静态的;确切的说,除了在class中声明的funciton和变量默认是动态的,其他位置声明默认都是静态的。