不想错过我的推送,记得右上角-查看公众号-设为星标,摘下星星送给我
欢迎大家加入2022届数字IC交流群,QQ群号 1060380138
前面提到,可以显式调用 sample() 方法,而不是在声明覆盖组的时候定义时钟事件。但是,如果想参数化内置的 sample() 方法并将想要采样的数据准确地传递给它呢?换句话说,需要一种从包含覆盖组声明的范围以外的采样覆盖率数据的方法。
例如,可以使用不同的参数调用覆盖的采样方法,将task或者function或者并发断言中的数据直接传递到覆盖组。
并发断言具有特殊的sample语法,即在preponed区域中对数据值进行采样。这一点可以用将来自并发断言的采样数据作为参数传递给覆盖的sample方法,反过来说,又有助于管理断言覆盖的各个方面,例如通过一个属性对多个覆盖组进行采样、通过同一覆盖组对多个属性进行采样或对不同的采样方法采样任意覆盖组的序列或属性(包括局部变量)的分支。
自定义的sample方法的语法如下:
自定义采样方法
下面是一个简单的例子:
covergroup coverSample with function sample (int X);
coverpoint X;
endgroup : coverSample
coverSample cS = new ( );
property propertySample;
int pX; //local variable
//iSig1, iSig2, iSig3 are some internal signals of your design
@(posedge clk) (iSig1, pX = iSig2) |=> (iSig3, cS.sample(pX));
endproperty : propertySample
在这个例子中,我们首先声明一个名为coverSample的covergroup,并使用关键字“with function sample”声明一个名为sample()的函数。这意味着函数示例是用户定义的并且具有形式参数“int X”。有了这样的声明,现在可以从任务或函数内或从并发断言的序列或属性内调用 sample() 函数。
上面的例子里,进一步定义了一个名为 propertySample 的属性,我们在其中声明了一个名为“int pX”的局部变量。这是我们要在covergroup coverSample 中采样的变量。因此,我们在某些条件下从 propertySample 中调用函数 sample(),并将变量 pX(实际)传递给covergroup coverSample 的形式“X”。这样我们就可以在我们想要覆盖的时候覆盖我们想要覆盖的变量数据。用户定义的 sample() 方法可以有任何类型的程序代码来操作我们在组合域和时间域中传递给 sample() 的数据。
下面是一个使用systemverilog的function实现的例子
function fSample;
int fS;
….
cS.sample (fS);
endfunction
请注意,覆盖组的形式参数和sample的形式参数不能重名。下面是一个例子:
covergroup X1 (int cV) with function sample (int cV);
coverpoint cV; //Compile ERROR
endgroup
编译错误:“int cV”被声明为“covergroup X1”的形式参数,和sample的形式参数重名,编译会报错。
下面是另一个例子(Prakash),说明了如何将类对象传递给覆盖组。现在要解决的问题是,如果covergroup参数是一个类对象,那么在实例化covergroup时该对象不能指向NULL。data_ obj 是代码中的一个类。
class coverage;
covergroup cg_abc (data_obj obj);
coverpoint obj.mode {
bins range = {[3:'hB]};
}
endgroup
function new ( );
data_obj obj;
cg_abc = new (obj);
endfunction
endclass
module tb;
initial begin
coverage m_cov = new( );
for (int i = 0; i < 10; i++) begin
data_obj obj = new( );
obj.randomize( ); // How do I assign obj to covergroup inst ?
m_cov.cg_abc.sample( );
end
$display ("Coverage : %0.2f %%", m_cov.cg_abc.get_coverage());
end
endmodule
Simulation Log:
ncsim> run
ncsim: ∗E,TRNULLID: NULL pointer dereference.
所以,问题是当你在没有“with function”的情况下调用 sample() 并且你的covergroup 需要data_obj 句柄(obj)时,你如何传递它?如调用 sample() 时的代码所示,不能传递覆盖组“cg_abc”所需的参数。运行的时候会报出NULL指针错误。
下面是正确的代码:
class coverage;
covergroup cg_abc with function sample (data_obj obj);
coverpoint obj.mode {
bins range = {[3:'hB]};
}
endgroup
function new ( );
data_obj obj;
cg_abc = new( );
endfunction
endclass
module tb;
initial begin
coverage m_cov = new( );
for (int i = 0; i < 10; i++) begin
data_obj obj = new( );
obj.randomize( );
m_cov.cg_abc.sample(obj);
end
$display ("Coverage : %0.2f %%", m_cov.cg_abc.get_coverage());
end
endmodule
Simulation Log:
ncsim> run
Coverage : 100.00 %
ncsim: ∗W,RNQUIE: Simulation is complete.
END