1. 定义coverage文件,文件名ut_cov.sv
//文件名可和class名字不一样,以防找不到命名为一致,找不到环境会报错
class ut_cov extends uvm_component;
`uvm_component_utils(ut_cov)
cpu_transfer cpu_tr;
virtual interface cpu_if cfgif;
covergroup top_cfg @(cfgif.cpu_cast_sample_cov);
// cpu_cast_sample_cov 为自定义的触发事件,定义在cup_if 中
option.per_instance = 1;
cpu_addr: coverpoint cpu_tr.addr
// cpu_addr为cpu_tr.addr的别名,cpu_tr.addr对应cpu_transfer的addr信号
{
bins addr0 = {32'h00};
bins addr1 = {32'h04};
bins addr2 = {32'h08};
bins addr3 = {32'h0c};
... // 根据验证需求设置bins 个数和取值
}
cpu_wd: coverpoint cpu_tr.datain
{
bins datain = {[32'h0:32'hffff]};
}
.... //根据验证需求添加coverpoint
endgroup
function new(string name="ut_cov", uvm_component parent);
super.new(name, parent);
top_cfg = new(); //一定要创建covergroup,否则覆盖率收集会失败,并且不显示error
if(!uvm_config_db#(virtual cpu_if)::get(null, "*", "cfgif", cfgif))begin
//该uvm_config_db 与top 层相连
`uvm_fatal(get_type_name(), "no virtual interface specified for cpu_cast")
end
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
endclass
2. 完善top.sv文件的uvm_config_db
//在top.sv 里,uvm_config_db必须写进initial begin中
initial
...// 验证平台所需的其它uvm_config_db
uvm_config_db#(virtual cpu_if)::set(uvm_root::get(), "*", "cfgif", cfgif);
begin
3. 在env.sv中实例化ut_cov.sv文件
class ut_env extends uvm_env;
... //给env其它成员创建句柄
ut_cov ut_fcov;//句柄名字随意定义,后续实例化保持一致即可
`uvm_component_utils(efuse_env)
function new(string name = "cov_env", uvm_component parent = null)
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.connect_phase(phase);
...//实例化env其它句柄
ut_fcov = ut_cov ::type_id::create("ut_fcov", this);
uvm_config_db#(ut_cov)::set(null, "*", "ut_fcov", ut_fcov);
//在哪里收覆盖,哪里就设置get()操作,本文在sequnce中收覆盖率
endfunction
... //环境所需其它phase
endclass
4. 在cpu_if .sv 中 定义触发事件
interface cpu_if(input clk, input rst_n);
...//定义Interface 信号
event cpu_cast_sample_cov; //名字与ut_cov.sv中一致
endinterface
5. 在tb1_seq.sv 中触发覆盖率收集事件
class tb1_seq extends base_sequence;
`uvm_object_utils(tb1_seq)
ut_cov ut_fcov;
cpu_transfer cpu_tr;
virtual cpu_if cfgif;
function new(string name="tb1");
super.new(name);
cpu_tr = cpu_transfer::type_id::create("cpu_tr");
if(!uvm_config_db#(ut_cov)::get(null, "*", "ut_fcov", ut_fcov))begin
`uvm_fatal(get_type_name(), "no ut_fcov getted for tb1_seq")
end
if(!uvm_config_db#(virtual cpu_if)::get(null, "*", "cfgif", cfgif))begin
// 与env相连
`uvm_fatal(get_type_name(), "no virtual interface getted for tb1_seq")
end
endfunction
virtual task usr_body();
bit [31:0] rdata;
assert(cpu_tr.randomize() with {addr==`REG_0;});//`REG_0是宏定义,可直接设置值
CPU_RD(cpu_tr.addr, rdata); //CPU_RD 为自定义的发激励task
//发激励一定要用到coverpoint中的cpu_tr信号,否则收不到
$cast(ut_fcov.cpu_tr, cpu_tr);//类型转换
-> cfgif.cpu_cast_samplele_cov; //触发覆盖率收集事件
...
endtask
endclass
6. 启动环境运行tb1_seq对应的test case,即可收到覆盖率