日常记录(70)9章功能覆盖率

验证导向

提高覆盖率流程

无法达到100%功能覆盖率时候:

  • 更多的种子,测试现有程序。
  • 建立新的约束
  • 定向测试

建议

  • 收集信息为导向,而不是数据(如所有的数据包)
  • 只监控将要使用的数据,提高运行速度
  • 保存那些能够获得更高覆盖率的测试和种子,以备回归
  • 注意覆盖率测量结果、漏洞率的情况和趋势,漏洞出现是因为意外发现还是特意检查。(意外发现问题可能严重一点。)
  • 覆盖组应该名称足够长,能够说明该覆盖率收集的详细信息

代码覆盖率、功能覆盖率

  • 功能覆盖率很高,但是代码覆盖率不够,则功能覆盖率的验证计划可能有问题,需要更新
  • 功能覆盖率不够,但是代码覆盖率很高,则检查测试用例,完备的情况下,可能需要形式验证工具,提取状态、创建激励。

行覆盖率等选项设置

Makefile文件

编译和运行

  • 其中的编译和运行,都需要添加-cm选项,才能在编译的时候出现-cm_dir指定的功能覆盖率文件
  • +ntb_random_seed在这里没有作用,配置seed选用程序内的代码,并注意细节。

覆盖率合并

使用urg的-dir,配合-dbname,输出一个合并后的覆盖率。

set -e

set -e是bash的命令,不能放到Makefile开头。set -e用于报错后不再往下执行。

seed_value=101
seed0=+ntb_random_seed=$(seed_value) -cm_dir seed$(seed_value).vdb

all: compile run

compile:
	vcs -sverilog -cm line -debug_all taa.sv -cm line+cond+fsm+branch+tgl+assert  $(seed0)


compile_b:
	vcs -sverilog -cm line -debug_all tbb.sv -cm line+cond+fsm+branch+tgl+assert  $(seed0)

run:
	./simv -cm line+cond+fsm+branch+tgl+assert

cov:
	dve -covdir simv.vdb &

clean:
	@rm -rf *.log simv* *.key csrc DVEf* work tags *.vdb urgReport

merge:
	urg -dir seed101.vdb seed10.vdb -dbname merge.vdb

tcc:
	set -e
	vcs -sverilog -cm line -debug_all tcc.sv
	./simv
	dve -covdir simv.vdb &

tdd:
	set -e
	vcs -sverilog -cm line -debug_all tdd.sv
	./simv
	dve -covdir simv.vdb &

功能覆盖率与小型工程

  • 下面的taa是DUT,test是驱动,top是上层连接。使用的.*进行了默认连接过程
  • tr.tr.srandom(022)更改,seed变更,其中的随机化过程会变动。但是不影响$random
  • $srandom(111)变更,对什么也不影响。
  • \(display(\)random(11));中的seed变更,则对后续的$random产生影响。
  • class中定义功能覆盖率,无需再次指定实例化名称,直接将类实例化,而下述在module/program中的cg,则需要再指定实例化名称,再进行实例化。
module taa (data, addr, clk, rst_n);
    input clk, rst_n;
    input [3:0] data;
    output reg [4:0] addr;
    integer count;

    always @(posedge clk, rst_n) begin
        if(!rst_n) begin
            addr <= 0;
            count <= 0;
        end
        else begin
            addr <= data+count;
            count <= count + 1;
        end
    end
endmodule

program automatic test (data, addr, clk, rst_n);
    input clk, rst_n;
    output reg [3:0] data;
    input [4:0] addr;

    class Transaction;
        // data or class properties
        rand bit [3:0] data;
        rand bit [4:0] addr;
    endclass : Transaction
 
    Transaction tr=new;
    covergroup CovData;
        coverpoint tr.data;
    endgroup
 
    initial begin
        CovData cd=new;
        tr.srandom(022);
        $srandom(111);
        repeat(32) begin
            tr.randomize();
            data = tr.data;
            $display("data random is :%d", data);
            @(posedge clk);

            tr.addr = addr;
            cd.sample();
        end
        repeat (10) begin
            $display($random(1));
        end
        $display($random(11));
        repeat (10) begin
            $display($random());
        end
        $display("finished!");
        $display("final cov value: %f", cd.get_coverage());
    end
     
endprogram : test

module top ();
    reg clk, rst_n;
    reg [4:0] addr;
    wire [3:0] data;

    initial begin
        clk = 0;
        forever begin
            #10 clk = ~clk;
        end
    end

    initial begin
        rst_n = 0;
        #30
        rst_n = 1;
        #500
        rst_n = 0;
        #10
        rst_n = 1;
    end

    taa dut(.*);
    test tb(.*);
endmodule

覆盖率的事件触发

直接使用事件触发

  • 定义好cg,然后在其中定义好@的量,sample_a中实现了事件触发

断言触发

  • 使用cover property(@(posedge clk) xxx),等待断言满足条件,触发一个事件,出现覆盖率收集。
module tbb ();
    bit clk;
    event evt_as;
    bit b_value;
    bit [3:0] c;

    cover_name: cover property
    (@(posedge clk) b_value==1) 
    -> evt_as;

    covergroup groe @(evt_as);
        coverpoint c;
    endgroup : groe

    class cov_test;
        // data or class properties
        bit [2:0] a;
        bit clk;
        event evt;
        covergroup test_cg @(evt);
            coverpoint a;
        endgroup : test_cg

        function new();
            test_cg = new();
        endfunction: new

        function void sample_a();
            a = 1;
            -> evt;
            a = 0;
            -> evt;
        endfunction: sample_a
    endclass : cov_test

    initial begin
        clk = 0;
        fork
            begin
                forever begin
                    #1 clk=~clk;
                end
            end
            begin
                b_value = 0;
                #10
                c = 1;
                b_value = 1;
                #3
                c = 2;
                #3
                c = 3;
                #10;
                b_value = 1;
            end
        join_none
    end

    initial begin
        cov_test ct = new();
        groe gr = new();
        ct.sample_a();
        #100;
        $finish;

    end
endmodule

结果:
image
image
image

覆盖率选项

设置最大的bin的个数

option.auto_bin_max
设置最大的bin的个数,而默认是64

设置某些情况下才进行覆盖率收集

iff(!a==0)
image

手动设置bins

使用bins bin_name = {range_, [range_]}

设置除外后的其它bins

使用bins xxx = default在手动设置bin中
image

设置翻转覆盖率收集

例如:
bins t1 = (0=>1),(0=>[8:15]),([0:8]=>[8:15]);
image

使用通配符

?表示0或者1,以下是一个偶数的bin覆盖。wildcard作为说明关键字
wildcard bins even = {3'b??0};

small large

是sv/v的关键字,不可使用。
image

忽略一些取值范围

使用ignore_bins,和bins是同级的用法
image

声明非法的bins

使用illegal_bins,得到非法值则终止程序

交叉覆盖率取消一些排列组合

  • ignore_bins ig1 = binsof(a4)intersect{0};取消了a4的数字0的排列组合。
  • ignore_bins ig3 = binsof(a4.a05) &&binsof(a5.a20);取消a4.a05和a5.a20的排列组合
  • binsof(a4)intersect{[2:7]} && binsof(a5)intersect{1};取消a4的数字2-7与a5的数字1的相关排列组合。
    image

stop和start

暂停和启动覆盖率收集功能。

module tcc ();
    class cov_test;
        // data or class properties
        bit [3:0] a;
        int b;
        int c;
        covergroup cgxx ;
            option.auto_bin_max = 4;
            coverpoint a;
            coverpoint b;
            coverpoint a+b;
            coverpoint c iff(!a==0);
            c2:coverpoint c 
            {
                bins small1 = {[$:0]};
                bins array[4] = {[0:99999000]};
                bins large1 = {[99999:$]};
                bins misc=default;
                // don't have effect
                /* option.weight = 0; */
                // option.goal = 50;
            }
            a2:coverpoint a{
                bins t1 = (0=>1),(0=>[8:15]),([0:8]=>[8:15]);
                bins t2 = (3,[4:10] => 2,3,4,5,6);
                wildcard bins even = {3'b??0};
                wildcard bins odd = {3'b??1};

            }
            a3:coverpoint a{
                option.auto_bin_max = 4;
                ignore_bins high = {[10:$]};
                /* illegal_bins high_ill = {9}; */
            }
            a4:coverpoint a{
                bins a00 = {[0:1]};
                bins a01 = {[2:3]};
                bins a02 = {[4:5]};
                bins a03 = {[6:7]};
                bins a04 = {[8:9]};
                bins a05 = {[10:11]};
            }
            a5:coverpoint b{
                bins a20 = {[$:0]};
                bins a21 = {[0:$]};
            }
            crs:cross a4, a5{
                ignore_bins ig1 = binsof(a4)intersect{0};
                ignore_bins ig2 = binsof(a4)intersect{[2:7]} && binsof(a5)intersect{1};
                ignore_bins ig3 = binsof(a4.a05) &&binsof(a5.a20);
            }
            weight_a: coverpoint a{
                bins low = {[0:8]};
                bins high = {[9:15]};
                bins none = {[16:20]};
            }
        endgroup : cgxx
        
        // initialization
        function new();
            cgxx = new();
        endfunction : new

        function void sample();
            /* cgxx.stop(); */
            /* cgxx.start(); */
            repeat (100) begin
                {a, b, c} = {$random(), $random(), $random()};
                cgxx.sample();
            end
            repeat (100) begin
                {a, b, c} = {$random(), $random(), $random()};
                a = 0;
                cgxx.sample();
            end
        endfunction: sample

    endclass : cov_test


    initial begin
        cov_test ct = new();
        ct.sample();
    end
endmodule

weight使用

  • 设置了per_instance为1,
  • 使用option.weight = 0;
  • 最终的cg_inst1.get_inst_coverage()的结果为100.
module tb;
    bit [3:0] mode1, mode2;
    covergroup cg;
        option.per_instance=1;
        /* option.per_instance=0; */
        m1: coverpoint mode1 {
            bins range1[] = {[0:1],[2:3],[4:15]};
        }
        m2: coverpoint mode2 {
            bins range2[] = {[0:1],[2:3],[4:15]};
        }
        m1xm2:cross m1,m2{
            option.weight = 0;
        }
    endgroup

    initial begin
        cg cg_inst1 = new();
        for (int i = 0; i < 50; i++) begin
            #10 
            mode1 = i;
            mode2 = 5-i;
            cg_inst1.sample();
        end

        $display("coverage result b is %f",cg_inst1.get_coverage());
        $display("coverage result d is %f",cg_inst1.get_inst_coverage());
        $display("coverage result f is %f",$get_coverage());  
    end
endmodule

输出:
weight是生效了。

coverage result b is 68.750000
coverage result d is 100.000000
coverage result f is 68.750000
posted @ 2022-03-05 19:37  大浪淘沙、  阅读(520)  评论(0)    收藏  举报