九、覆盖率

功能覆盖率

验证证的目的就是为了确保设计在实际环境中的行为正确。
功能覆盖率是对测试执行了设计的哪些功能/特性的度量,这在约束随即验证(CRV)中很有用,可以了解回归中的一组测试已经覆盖了哪些特征。

覆盖组 covergroup

systemverilog covergroup时一种用户定义的类型,它封装了覆盖模型的规范。特们可以定义一次,并通过new函数在不同的地方实例化多次。
covergroup 可以在包、模块、程序、接口或类中定义,通常封装以下信息:

1、一组覆盖点
2、覆盖点之间的交叉覆盖
3、定义何时对覆盖组进行采样的事件
4、配置覆盖对象的其他选项

module tb;
	// Declare some variables that can be "sampled" in the covergroup
	bit [1:0] mode;
	bit [2:0] cfg;
	// Declare a clock to act as an event that can be used to sample
	//coverage points within the covergroup
	bit clk;
	always #20 clk = ~clk;
	
	// "cg" is a covergroup that is sampled at every posedge clk
	covergroup cg @(posedge clk);
		coverpoint mode;
	endgroup
	// Create an instance of the covergroup
	cg cg_inst;
	
	initial begin
		//Instantiate the covergroup object similar to a class object
		cg_inst = new();
		// Stimulus:Simply assign random values to the coverage variables
		// so that different values can be sampled by the covergroup object
		for(int i = 0; i < 5; i++) begin
			@(negedge clk);
			mode = $random;
			cfg = $random;
			$display("[%0t] mode=0x%0h cfg=0x%0h", $time, mode, cfg);
		end
	end

	//At the end of 500ns,terminate test and print collected coverage
	initial begin
		#500 $display("Coverage = %0.2f %%", cg_inst.get_inst_coverage());
		$finish;
	end
endmodule

覆盖点 coverpoint

一个covergroup可以包含一个或者多个覆盖点,一个覆盖点指定需要覆盖的整数表达式。coverpoint对表达式进行评估时covergroup会进行采样。SV中覆盖点可以选择用冒号标记:。

module tb;
	
	bit [1:0] mode;
	bit [2:0] cfg;
	
	bit clk;
	always #20 clk = ~clk;
	
	// "cg" is a covergroup that is sampled at every posedge clk
	covergroup cg @(posedge clk);
		// Coverpoint can optionally have a name before a colon ":"
		cp_mode		:	coverpoint mode;
		cp_cfg_10	:	coverpoint cfg[1:0]
		cp_cfg_1sb	:	coverpoint cfg[0];
		cp_sum		:	coverpoint	(mode + cfg)
	endgroup
	// Create an instance of the covergroup
	cg cg_inst;
	
	initial begin
		//Instantiate the covergroup object similar to a class object
		cg_inst = new();
		// Stimulus:Simply assign random values to the coverage variables
		// so that different values can be sampled by the covergroup object
		for(int i = 0; i < 5; i++) begin
			@(negedge clk);
			mode = $random;
			cfg = $random;
			$display("[%0t] mode=0x%0h cfg=0x%0h", $time, mode, cfg);
		end
	end

	//At the end of 500ns,terminate test and print collected coverage
	initial begin
		#500 $display("Coverage = %0.2f %%", cg_inst.get_inst_coverage());
		$finish;
	end
endmodule

仓 bins

bins允许为覆盖点变量给定可能值范围内的每个值创建单独的bin

用法

...
coverpoint mode {
	// manully create a separeta bin for each value
	bins zero = {0};
	bins one  = {1};
	//Allow SystemVerolog to automatically create separate bins for each value 
	// values from 0 to max possible value is split into separate bins
	bins range[] = {[0:$]};
	//Create automatic bins for both the given ranges
	bins c[] = {[2:3], [5:7]};
	//Use fixed number of automatic bins. Entire range is broken up into 4 bins
	bins range[4] = {[0:$]};
	// If the number of bins cannot be equally divided for the given range, then 
	// the last bin will include remaining items;  Here there are 13 values to ber 
	// distributed into 4 bins which yields:
	// [1,2,3] [4,5,6] [7,8,9] [10, 1, 3, 6]
	bins range [4] = [[1:10], 1, 3, 6);
	// A single bin to store all other values that don't belong to any other bin 
	bins others = default;
}

例子

module tb;
	bit [2:0] mode;
	//This covergroup does not get sample automatically because 
	//the sample event is missing in declaration
	covergroup cg;
		coverpoint mode {
			bins one = {1};
			bins five = {5};
		}
	endgroup

	//Stimulus:simply randomize mode to have different values and manually sample each time
	initial begin
		cg cg_inst = new();
		for(int i = 0; i < 5; i++)begin
			#10 mode = $random;
			$display("[%0t] mode = 0x%0h", $time, mode);
			cg_inst.sample();
		end
		$display("Coverage = %0.2f %%", cg_inst.get_inst_coverage());
	end
	
endmodule

综合说明

翻转覆盖率

coverpoint也可以用来记录变量从A值到B值的跳转情况
除了在bins中定义数值,还可以定义数值之间的跳转,操作符 =>

covergroup CoverPort;
	coverpoint port{
		//满足其中任何一个,就会记录一次
		bins t1 = (0 =>1), (0 => 2), (0 => 3);
		//跳转次序为3->4->5,如果没有执行这个次序,则这个bins没有覆盖
		bins t2 = (3 => 4 => 5);
	}
endgroup

wildcard覆盖率

除操作符外,还可使用关键词wildcard和通配符 ? 来表示状态和状态跳转;

wildcard来创建多个状态或者翻转
在表达式中,任何x,z或者 ? 都会被当成0或1的通配符

wildcard bins abc = {2'b1?};//覆盖10,11
//覆盖 10=>00, 10=>10,11=>00,11=>10
wildard bins abc = {2'b1x => 2'bx0};

bit [2:0] port;
covergroup CoverPort;
	coverpoint port{
		wildcard bins even = {3'b??0};//偶数
		wildard bins odd = {3'b??1};//奇数
	}
endgroup

忽略的bin

有些coverpoint可能始终无法得到全部的阈值
对于那些不计算功能的阈值可以使用ignore_bins来排除,最终它们并不会计入coverpoint的覆盖率

coverpoint port{
	ignore_bins hi = {[6,7]};//忽略数值6~7
}

非法的bin

有些采样值不仅想要忽略,并且出现还应该报错,可以用illegal_bins

coverpoint port{
	illegal_bins hi = {[6,7]};//出现6~7就停止仿真,报错
}

限制自动建仓上限

SV会自动创建仓,当可能取值过大时只会建64个仓,并将变量取值平均分配到这些仓中。我们可以手动限制。

covergroup CovPort;
    options.auto_bin_max = 8;   		 //所有的coverpoint auto_bin数量是8
    coverpoint tr.port
        {    option.auto_bin_max = 2}    //特定的covepoint auto_bin数量2
endgroup

交叉覆盖率

  • coverpoint是记录单个变量或者表达式的观测值。
  • 如果像记录在某一时刻,多个变量之间值的组合情况,需要使用交叉(cross)覆盖率。
  • cross 语句只允许带coverpoint或者简单的变量名
class Transaction ;
    rand bit [3:0] kind;
    rand bit [2:0] port;
endclass

Transaction tr;

covergroup CovPort;
    kind: coverpoint tr.kind;
    port: coverpoint tr.port;
    cross kind, port;
endgroup

排除部分cross bin

  • 通过使用 ignore bins、binsof 和 intersect 分别指定coverpoint口值域,这样可以清除很多不关心的cross bin。
covergroup covport;
    port: coverpoint tr.port{
        bins port[] = { [O:$] };
    }
    kind: coverpoint tr.kind{
        bins zero = { 0 };
        bins lo = { [1:3] };
        bins hi[] = { [8:$] };
        bins misc = default;
    }
    cross kind, port{
        ignore_bins hi = binsof(port)intersect { 7 };
        ignore_bins md = binsof(port)intersect { 0 } &&
                         binsof(kind) intersect { [ 9:11] };
        ignore_bins lo = binsof(kind.lo);
    }
endgroup

精细的交叉覆盖率指定

  • 随着cross覆盖率越来越精细,可能需要花费不少的时间来指定哪些bin应该被使用或者被忽略。
  • 更适合的方式是不使用自动分配的cross bin,而自己声明感兴趣的cross bin。
  • 假如有两个随机变量a和b,它们带着三种感兴趣的状态,{ a=0,b=0}、{ a=1,b=0}和{b=1}。
class Transaction;
    rand bit a, b;
endclass

covergroup CrossBinNames;
    a : coverpoint tr.a
    {bins a0 = { 0 };
     bins a1 = { 1 };
     option.weight=0;} //权重设置为0,忽略覆盖点的采样
    b: coverpoint tr.b
    {bins b0 = { 0 };
     bins b1 = { 1 };
     option.weight=0;} //权重设置为0,忽略覆盖点的采样
    ab: cross a, b
    {bins a0b0 = binsof( a.a0) && binsof ( b.b0 );
     bins a1b0 = binsof( a.a1) && binsof ( b.b0 );
     bins b1 = binsof( b.b1 );}
endgroup
class Transaction;
    rand bit a, b;
endclass

covergroup CrossBinsofintersect;
    a : coverpoint tr.a
    { option.weight=0 ; }//Do not count this coverpoint
    b: coverpoint tr.b
    { option.weight=0; } //Do not count this coverpoint
    ab : cross a, b
    { bins a0b0 = binsof(a) intersect{0} && binsof(b) intersect{0};
      bins alb0 = binsof(a) intersect{1} && binsof(b) intersect{0};
      bins b1 = binsof(b) intersect{1};
    }
endgroup

采样触发

covergroup由采样的数据和数据被采样的事件构成,两个条件都准备好,测试平台便会触发covergroup
直接使用 sample() 函数完成

class myCov;
	covergroup CovGrp;
		...
	endgroup

	function new ();
		CovGrp = new;	// Create an instance of the covergroup
	endfunction
endclass

module tb_top;
	myCov myCov0 = new ();// Create an instance of the class

	initial begin
   		myCov0.CovGrp.sample();
   	end
endmodule

事件触发

与直接调用sample()相比,使用事件触发的好处在于你能够借助已有的事件

covergroup CovGrp @ (posedge clk);  // Sample coverpoints at posedge clk
covergroup covGrp @ (eventA);		// eventA can be triggered with ->eventA

有条件覆盖方法

有两种方法可以有条件地启用覆盖

  • 使用iff
covergroup CovGrp;
		coverpoint mode iff (!_if.reset){
			// bins for mode
		}
endgroup
  • 使用start和stop功能
CovGrp cg = new;

initial begin
	#1 _if.reset = 0;
	cg.stop();
	#10 _if.reset = 10;
	cg.start();
end
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值