一、覆盖率类型
- 覆盖率是用来衡量设计验证完备性。
- 随着测试逐步覆盖各种合理的组合,覆盖率用来衡量测试进行的程度。
- 覆盖率工具会在仿真过程中收集信息,然后进行后续处理并且得到 覆盖率报告。
- 通过报告找出覆盖盲区,然后修改现有test或者创建新的test来填补这些盲区。
- 这个过程可以一直迭代进行,直到覆盖率达到KPI要求,一般要求覆盖率100%。
覆盖率反馈环路
1、代码覆盖率
代码覆盖率是由仿真工具仿真完成后自动收集的
- 行覆盖率line coverage :所有行是否都运行到
- 路径(分支)覆盖率paths coverage/(branch coverage) :所有路径是否以cover到
- 翻转覆盖率toggle coverage :所有变量都有过静态的稳定状态0、1,和动态的0,1翻转
- 状态机覆盖率FSM coverage :状态机中所有状态都已运行到,状态之间的应该有的跳转也都已运行到
2、功能覆盖率
- 验证的目的: 确保设计在实际环境中的行为正确。
- 功能描述文档详细说明了设计应该如何 运行,而验证计划则列出了相应的功能应该如何激励、验证和测量。
- 功能覆盖率是和功能设计紧密相连的,而代码覆盖率则是衡量设计的实现情况。
- 若某个功能在设计中被 遗漏,代码覆盖率不能发现这个错误,但是功能覆盖率可以。
3、断言覆盖率
- 断言:用于一次性地或在一段时间内核对两个设计信号之间关系的声明性代码。
- 断言可以用于查找感兴趣的信号的值或者状态。最常用于 查找错误,例如两个信号间的相位关系,是否应该互斥或者请求与许可信号之间的时序等,一旦检测到问题,仿真就可以立即 停止。
- 可以使用 cover property来测量这些关心的信号的值或者状态是否发生。
- 在仿真结束时,仿真工具可以自动生成断言覆盖率数据,断言覆盖率数据以及其它覆盖率数据都会被集成在同一个覆盖率数据库中。
二、覆盖率组
1、覆盖策略
- 收集的是信息的覆盖率,而不是具体数据的覆盖率。
- 应该只测量你会用来分析并且改进测试的那部分数据,所以设定合理的覆盖率采样的事件,一方面提升采样效率,一方面也可以降低收集覆盖率的开销
-
如果功能覆盖率高但代码覆盖率低,这说明验证计划不完整,测试没有执行设计的所有代码。
-
如果代码覆盖率高但功能覆盖率低,这说明即使测试平台很好地执行了设计的所有代码,但
是测试还是没有把设计定位到所有对应的功能上,或者设计代码本身功能没有写完整。
2、覆盖组 covergroup
- covergroup可以包含一个或者多个coverpoint,且全都在同一时间采集。
- covergroup可以定义在类中,也可以定义在interface或者module中,一个类里可以包含多个covergroup。
- covergroup可以采样任何可见的变量,例如程序变量、接口信号或者设计端口。
- 当你拥有多个独立的covergroup时,每个covergroup可以根据需要自行使能或者禁止。
- 每个covergroup可以定义单独的触发采样事件,允许从多个源头收集数据。
- covergroup一次定义后可多次实例化,必须被例化才可以用来收集数据。
covergroup 的采样触发
- covergroup由采样的数据和数据被采样的事件构成。当这两个条件都准备好以后,测试平台便会自动触发covergroup,并且会去收集覆盖率。
- 这个过程可以通过直接使用sample()函数完成,也可以在covergroup中采样阻塞表达式或者使用wait或@实现在信号或事件上的阻塞来自动触发采样。
示例1:
通过事件来触发采样:
event trans_ready;
covergroup CovPort @(trans_ready);
coverpoint ifc.cb.port;
endgroup
示例2:
class Transaction;
rand bit [31:0] data;
rand bit [ 2:0] port; // Eight port numbers
endclass
interface busifc(input bit clk);
logic [31:0] data;
logic [ 2:0] port;
modport TB(input clk,output port,data);
endinterface
program automatic test(busifc.TB ifc);
covergroup CovPort;
coverpoint ifc.port; // Measure coverage
endgroup
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (32) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port <= tr.port;
ifc.data <= tr.data;
ck.sample(); // Gather coverage
@(posedge ifc.clk); // Wait a cycle
end
end
endprogram
module top;
logic clk;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
busifc ifc(clk);
test u_test(ifc);
endmodule
对sample采样分析:
方式一:port覆盖率及波形
问题:循环了5次,但采样覆盖率只有4次,波形上也出现5次data的变化
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port <= tr.port;
ifc.data <= tr.data;
ck.sample(); // Gather coverage
@(posedge ifc.clk); // Wait a cycle
end
#20;
$finish;
end
方式二:port覆盖率及波形
1、改成阻塞赋值后sample采样覆盖率变为5次
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port = tr.port;
ifc.data = tr.data;
ck.sample(); // Gather coverage
@(posedge ifc.clk); // Wait a cycle
end
#20;
$finish;
end
方式三:port覆盖率及波形
1、改成在时钟上升沿之后sample采样,覆盖率变为5次
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port <= tr.port;
ifc.data <= tr.data;
@(posedge ifc.clk); // Wait a cycle
ck.sample(); // Gather coverage
end
#20;
$finish;
end
说明:
- 通过方式二、方式三说明非阻塞赋值没有在sample()采样之前完成,所以漏采样了一次,阻塞赋值是立刻完成赋值的,这与时间片timeslot有关,但这并不能说明非阻塞赋值必须在时钟沿完成和sample()漏采的是第一次port数据和它是往时钟沿前采样的
方式四:port覆盖率及波形
1、将时钟上升沿改成延时12ns
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port <= tr.port;
ifc.data <= tr.data;
ck.sample(); // Gather coverage
#12 //delay 12ns
end
#20;
$finish;
end
说明:文章来源地址https://www.toymoban.com/news/detail-696738.html
- 数据变化按照波形所示的12ns发生变化一次,所以非阻塞赋值不是只能在时钟沿完成,应该在每个时钟片都会执行,但在时钟片中的左右赋值时间不同
方式五:port覆盖率及波形
1、在repeat循环完之后再采样一次,覆盖次数变为5次
initial begin
Transaction tr;
CovPort ck;
ck = new(); //实例化覆盖组
tr = new();
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
ifc.port <= tr.port;
ifc.data <= tr.data;
ck.sample(); // Gather coverage
@(posedge ifc.clk);
end
ck.sample();
#20;
$finish;
end
说明:
- 在最后在多采样一次,次数变为5次,且次数是在auto[4]加1,结合波形最后一次随机出的也是4,说明sample采样是往前采样的
示例3:mailbox操作
class Transaction;
rand bit [31:0] data;
rand bit [ 2:0] port; // Eight port numbers
endclass
interface busifc(input bit clk);
logic [31:0] data;
logic [ 2:0] port;
//modport TB(input clk,output port,data);
endinterface
class Transactor;
Transaction tr;
mailbox mbx_in;
virtual busifc ifc;
covergroup CovPort;
coverpoint tr.port;
endgroup
function new(mailbox mbx_in, virtual busifc ifc);
CovPort = new(); //实例化group
this.mbx_in = mbx_in;
this.ifc = ifc;
endfunction
task main;
begin
mbx_in.get(tr);
ifc.port <= tr.port;
ifc.data <= tr.data;
CovPort.sample();
end
endtask
endclass
program automatic test(busifc ifc,input bit clk);
initial begin
Transaction tr;
mailbox mbx_in;
Transactor tr_c;
tr = new();
mbx_in = new();
tr_c = new(mbx_in,ifc);
repeat (5) begin // Run a few cycles
assert(tr.randomize); // Create a transaction
mbx_in.put(tr);
tr_c.main(); // send driver and gather coverage
@posedge(clk); // Wait a cycle
end
#20;
$finish;
end
endprogram
module top;
logic clk;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
busifc ifc(clk);
test u_test(ifc,clk);
endmodule
文章来源:https://www.toymoban.com/news/detail-696738.html
说明:
- 使用mailbox操作,同步了sample函数的采样问题,覆盖采样次数就为5次
到了这里,关于(十四)覆盖率类型、覆盖率组的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!