目录
1 概述
在进⾏芯⽚验证时,最重要的⼀个环节就是完成对dut的覆盖率收集⼯作,覆盖率主要分为下⾯三类:
- 代码覆盖率
- 功能覆盖率
- 断⾔覆盖率
如何完成覆盖率收集?
1.1 代码覆盖率收集:
代码覆盖率是衡量验证进展的最简易的⽅式。它的作⽤是检查代码是否冗余,设计要点是否遍历,被检测的对象是RTL代码,⽽代码覆盖率的检测⼀般由⼯具⾃动⽣成的。⾏覆盖率(Line coverage)、分⽀覆盖率(Branch coverage)、路径覆盖率(Path Coverage)、翻转覆盖率(Toggle coverage)、条件覆盖率(Conditional coverage)、有限状态机覆盖率(FSM coverage)。
在makefile中添加
-cm line+fsm+tgl+cond+assert
可完成相对应的代码覆盖率的收集。(在编译和运⾏时都需添加)
1.2 功能覆盖率收集:
功能覆盖率是⼀个⽤户定义的度量标准,它测量了设计规范的多少部分,通过测试计划中的特性枚举,已经被执⾏。它可以⽤来衡量是否有兴趣的场景、⾓落⽤例、规格不变量,或者其他适⽤的设计条件(作为测试计划的特性捕获)已经被观察、验证和测试。
这⾥简单介绍下如果你收集的代码覆盖率很⾼但是功能覆盖率缺很低,这个可能是:
- design没有完全按照功能spec⽂档规格实现所有功能,设计不完善;
- 验证平台monitor监视器存在漏洞,设计代码实现了功能但没有覆盖到他们;
- 功能正确,但是发送的激励不对,对应功能的覆盖率⽆法收集。
如果你收集的功能覆盖率很⾼但是代码覆盖率缺很低,这可能是:
- 设计代码没有按照spec实现功能,在design中是⽆效代码,
- ⽤户定义的功能覆盖率收集存在错误,没有完全定⽐覆盖率收集的边界,测试计划未捕获所有设计功能/场景/边界,或者缺少功能覆盖率监视器。代码覆盖率中未覆盖的设计代码可能会映射到这些功能上。
- 在实现功能覆盖率监视器时可能存在潜在的错误,导致它们收集了错误的覆盖率。因此,在验证项⽬中,对⽤户定义的功能覆盖率指标及其实现进⾏适当的检查很重要。
定义⼀个coverage class,在类中指定你要收集的coveragegroup和coveragepoint,也可指定你要收集的仓bins。
`ifndef GUARD_COVERAGE
`define GUARD_COVERAGE
class coverage;
packet pkt;
covergroup switch_coverage;
length : coverpoint pkt.length;
da : coverpoint pkt.da {
bins p0 = { `P0 };
bins p1 = { `P1 };
bins p2 = { `P2 };
bins p3 = { `P3 }; }
length_kind : coverpoint pkt.length_kind;
fcs_kind : coverpoint pkt.fcs_kind;
all_cross: cross length,da,length_kind,fcs_kind;
endgroup
function new();
switch_coverage = new();
endfunction : new
task sample(packet pkt);
this.pkt = pkt;
switch_coverage.sample();
endtask:sample
endclass
`endif
在scoreboard完成coverage模块的调⽤,coverage cov = new() 新建所要使⽤的类,cov.sample(pkt_exp)采样pkt_exp数据包。
`ifndef GUARD_SCOREBOARD
`define GUARD_SCOREBOARD
class Scoreboard;
mailbox drvr2sb;
mailbox rcvr2sb;
coverage cov = new();
function new(mailbox drvr2sb,mailbox rcvr2sb);
this.drvr2sb = drvr2sb;
this.rcvr2sb = rcvr2sb;
endfunction:new
task start();
packet pkt_rcv,pkt_exp;
forever begin
rcvr2sb.get(pkt_rcv);
$display(" %0d : Scorebooard : Scoreboard received a packet from receiver ",$time);
drvr2sb.get(pkt_exp);
if(pkt_rcv.compare(pkt_exp)) begin
$display(" %0d : Scoreboardd :Packet Matched ",$time);
cov.sample(pkt_exp);
end
else
error++;
end
endtask : start
endclass
`endif
1.3 断⾔覆盖率收集:
通过设定断⾔,⼀般完成接⼝时序相关的覆盖率收集。如AHB总线时序在对同⼀个地址先做写操作再不间隔做读操作,可使⽤property指定两次操作的地址是相同的,在cover该property。
property p_write_read_burst_trans;
logic[31:0] addr;
@(posedge clk) ($rose(penable) && pwrite, addr=paddr) |-> (##2 ($rose(penable) && !pwrite && addr==paddr));
endproperty: p_write_read_burst_trans
cover property(p_write_read_burst_trans);
2 如何查看收集后的覆盖率?
收集后的覆盖率保存在simv.vdb⽂件夹中,可使⽤urg⼯具转成可视化的html⽂件或直接使⽤dve⼯具查看simv.vdb
直接查看指令:
dve -full64 -cov -dir simv.vdb&
urg转成html⽂件:
urg -dir simv.vdb -report urgReport
相同代码不同tc的覆盖率合并:
urg -full64 -dir tc1.vdb tc2.vdb -dbname merged.vdb -report urgReport