FunCov intro and best practise


this blog is to introduce the concept of Funtion Coverage and the most common usage;
topic:
1.the introdutcion concept of function coverage
2.the usage of covergroup
3.the option of coverage
4.The usage in uvm_env

1 Introduction

1.1 the basic component:

covergroup: similar to class,you should declare then instance;
It can contains one or more coverpoint. and will be sampled at the same time.
It can be used in class or interface program or moudle;
a. It can sample any varible.such as varia,signal of interface,port of module.
b. A class can contain many covergroup. when you have many independent covergroup,ervery covergroup can enalbe or disable itself.
c.Every covergroup can define the sample triggle perponally,allow collect data from many source.
d.Note:covergroup must be instanted to sample data;
Eg:

covergroup cov_grp @(posedge clk iff rstn);
        cov_p1:coverpoint a;
endgroup

cov_grp cov_inst = new()

//way2
covergroup cov_grp;
        cov_p1:coverpoint a;
endcovergroup

cov_grp coc_inst = new();
@(posedge clk iff rst_n) cov_inst.sample();

The neccersy component:
1.coverage points : that is the port.
2.one clk event to trigger synamlly sample the coverpoint.
3.the choose options–tf_port list
4.Cross coverage between coverage points.
5.Coverage options.
Eg:

covergroup covergroup_identifier[(tf_port_list)||(coverage_event)]
        {coverage_spec_or_option}
endgroup:covergroup_identifier

coverage_spec_or_option ::=
{attribute_instance} coverage_spec
    |     {attribut_instance} covergae_option;

coverage_option ::=
option.member_identifier = expression
|        type_option.member_identifier = constant_expression

coverage_spec ::=
cover_point
|         cover_cross

coverage_event ::=
clocking_event
| with function sample{[tf_port_list]}

2 how to use covergroup

bin is obviously specify your interesting valur_range; which can use bin to points the some range.

//temple
covergroup cov_grp_1 @(posedge clk);
        cp_1 : coverpoint vara1 {
                                                    bins bin_1 = {range};
                                                    bins bin_2 = {range};
                                                }
        cp_2 : coverpoint vara2 {
                                                    bins bin1 = {range};
                                                    bins bin2 = {range};
                                                }
endgroup:cov_grp_1
//eg1
bin[7:0] addr;
covergroup cg @(posedge clk);
        cp1 : coverpoint addr {
                                                bins b1 = {2,7};
                                                bins b2 = {[30:40]};
                                                }
endgroup: cg

//eg2: switch to directly
value1 ->value2
range_list_1 -> range_list_2
covergroup cg @(posedge clk);
        cp1 : coverpoint addr{
                                        bins b1 = {10==>20==>30};
                                        bins b2 = {0==>2[=2]-->1};s
                                        }
endgroup

//eg3: special bins
* ignore bins: ignore the value wo dont care;
* illeagl_bins : if appear then err report;
* wildcard bins: 
* with: similar to extra_constraint;

//eg4: corss coverpoint
if want sample many varia's different group,must use cross to cover.
bit[3:0] a,b;
covergroup cg @(posedge clk);
        c1 : coverpoint a;
        c2 : coverpoint b;
        c1Xc2 : cross c1,c2;
endcovergroup

//--another way
bit[3:0] a,b;
covergroup cov@(posedge clk);
        aXb : cross a,b ; // impolicitly specify the coverpoint for a and b;
endgroup

//eg5 : covergroup with param, then pass param by new(); Note the varia(sampled) must ref type
covergroup cg1(ref logic[7:0] addr, input int low, int high) @(posedge clk);
        option.per_instance = 1;
        addr_val : coverpoint addr{
                                                        bins low = {[0:low]};
                                                        bins mid = {[low:high]};
                                                }
endgroup
addr_cov acov_low = new(addr,5,10);
addr_cov acov_mid = new(addr_11,20);
addr_cov acov_high = new(addr,21,30);

3 the option of covergroup

the option can control the behaviour of covergroup,coverpoint and cross;
There are two types of option : option && type_option;
option can pass param,but type_option only use const;

如果例化了一个covergroup cg,那么可以通过句柄cg.option来改变一些选项来改变使该实例与其他实例不同,而type_option是对整个covergroup的设置,两者之间互不干扰;
当一个covergroup被多次例化时,建议将per_instance设为1,并且将option.name=param,由new例化时传入,方便调试;

covergroup addr_cov (ref log[7:0] addr,input int low,int high,string instname) @(posedge clk);
        option.per_instance = 1;
        option.name = instname;
        addr_val : coverpoint addr{
                                                        bins low = {[0,low]};
                                                        bins mid = {[low:high]};
                                                }
endgroup:addr_cov

addr_cov acov_low = new(addr,5,10,"inst_1");
addr_cov acoc_mid = new(addr,5,10."inst_2");
addr_cov acov_high = new(addr,21,30,"inst_3");

4 The usage in UVM

4.1 funCov usage in interface

interface is the interview between tb with dut. So the covergroup inside interface can be used n interface directly.

interface apb_if (input clk, input rstn);
        logic[31:0] paddr;
        logic  pwrite;
        logic psel;
        logic pnenable;
        logic[31:0] pwdata;
        logic[31:0] prdata;
        logic pready;
        //coverage flags
        bit has_coverage = 1'b1;
        
        //APB command coverage
        covergroup cg_apb_command @(posedge clk iff rstn);
                option.per_instance = 1;
                option.name = "cov_apb_command";
                pwrite : coverpoint pwrite{
                        type_option.weight = 0;        //do ot count covergae
                        bins write = {1};
                        bins read = {1};
                }
                psel : coverpoint psel{
                        tpe_option.weight = 0;         //do no count coverage
                        bins sel = {1};
                        bins unsel= {0};
                }
                cmd : cross pwrite,psel{
                        bins cmd_write = binsof{psel.sel} && binsof{pwrite.write};
                        bins cmd_read = binsof{psel.sel} && binsof{pwrite.read};
                        bins cmd_idle = binsof{psel.unsel};
                }

        endgroup: cf_apb_command
        
        initial begin : coverage_control
                if(has_coverage) begin
                        cg_apb_command cg0 = new();
                end
        end
endinterface: apb_if

4.2 The funCov inside tb

For some occasions releated with dut, what we care about is the compination between signal and signal or signal inside dut. As a result, we need to dev specify component for collecting functionCov;

//tb_cov
//1. Create a interface to declare what we care
interface cov_if{
        input logic         clk_400M,
        input logic         reset_n,
        inut logic[6:0]   dma_cs,
        input logic[31:0] tdes0,
        input logic[31:0] tdes1

};

endinterface : cov_if;

//2.Use bind to connect the signal of dut with those of interface.   the bind.sv file should `include inside top_tb;
bind tob_tb cov_if cov_if_inst(
        .clk_400M         (clk_400M),
        .reset_n         (reset_n),
        .dma_cs        (topb_tb.dut_top_inst.dma_inst.cs),
        .tdes0        (top_tb.dut_top_inst.dma_inst.tdes0),
        .tdes1        (top_tb.dut_top_inst.dma_inst.tdse1)
);

//3 Use config_db for sending interface to the instance of cov; Note: cov_if_inst由于在bind在tb中,因此需要利//用“tob_tb.”对cov_if_inst进行索引
uvm_config_db# (virtual cov_if) :: set(uvm_root::get(),"uvm_test_top.env.cov","vif",top_tb.cov_if_inst);

//4.  1.Define a component--class for collecting function Coverage,then instant in env.
        2.In new() function, use config_db#  to get vif from tob_tb;
        3.in new() instant any covergroup;
        4.in task run_phase, use for..join to sample at the same time;
        5.define param: cov_flag. test can config_db::set to control whether covergroup smaple or not;
        Tips: config_db#() the 3th param should be the instname of covergroup for control and debug;
        6.can define param in task--sample() to do some control logic and call  .sample(), if simple sample,you can define after covergroup directly.
        7.declare the needed covergroup and sample() using vif;
        8.In the top-level to insital param ,and then using config to pass into cov.

class cov extends uvm_component();
        virtual cov_if vif;
        bit has_coverage;
        
        `uvm_component_utils(cov)
        
        function new(string name = "cov",uvm_component parent);
                super.new(name,parent
);
        //get configuration from tb
        if(!uvm_config_db#(virtual cov_if)::get(this,"","vif",vif)) begin
                `uvm_fatal("GETVIF","CANNOT get cov_if object from config DB");
        end
        //Get has_coverage from tb or test
        if(!uvm_config_db#(bit)::get(this,"","coverage_control",has_coverage)) begin
                has_coverage = 1;
        end
        this.dma_desp_tdes_group = new();
        endfunction: new
        
        task run_phase();
                fork 
                        if(has_coverage) begin
                                this.do_dma_tdes_sample();
                                //........other sample task
                        end
                join
        endtask
        
        //Macro used to get the cov_flag
        //"default" tasks affect when config config_db::get failed
        //"cov_name" is a string representing the name of covergroup
        `define GET_COV_FLAG(default_value,cov_name) \        
            bit cov_flag;
            if(!uvm_config_db #(bit)::get(this,"",cov_name,cov_flag)) begin \
                    cov_flag = default_value;
            end

        task do_dma_tdes_sample();
                `GET_COV_FLAG(0,"dma_desp_tdes_group")
                if(cov_flag) begin
                        forever begin
                                @(posedge vif.clk_400M iff vif.reset_n) begin
                                        dma_desp_tdes_group.sample();
                                end
                        end
                end        
        endtask

        
        covergroup dma_desp_tdes_group;
                desp_ic : coverpoint vif .tdes1[31];
                desp_ter: coverpoint vif.tdes2[25];
                buf2_size:coverpoint vif.tdes1[21:11];{
                    bins size_bound[] = {0,11'h7ff};
                    bins size_others  = default;    
                    }
                buf1_size : coverpoint vif.tdes1[] {
                        bins size_bound[] = {0,11'7ff};
                        bins size_others = default;
                }
        endgroup : dma_desp_tdes_group
end class

//--best practise
class child_test extends base_test;
        bit cov_flag;    
        bit has_coverage
        
        function new(string name = "child_test",uvm_component parent = null);
                super.new(name,parent);
                cov_flag = 1;
                has_coverage = 1;
                uvm_configdb #(bit) ::set(this,"env.cov","dma_desp_tdes_group",cov_flag);        //set flag to cov
                uvm_configdb#(bit):: set(this,"env.cov","covergae_control",has_coverage);
        end:new
endclass

Recommand: 建议将cov_if_inst直接bind在top_tb下,不要bind到DUT层次,以方便区分验证环境与DUT

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值