草庐IT

(十五)覆盖率数据采样、交叉覆盖率_覆盖选项

小白菜~ 2023-07-12 原文

一、数据采样

当在覆盖点上指定一个变量或表达式时,SystemVerilog便会创建很多的“仓(bin)"来记录每个数值被捕捉到的次数,仓(bin)是衡量功能覆盖率的基本单位。

  • SystemVerilog会自动为覆盖点创建仓,它通过被采样的表达式的域来确定可能值的范围。
  • 每次覆盖点/组采样后,SV都会在一个或者多个仓中留下标记,在每次仿真的末尾,所有带标记的仓会被汇聚到一个新创建的数据库中。
  • 在仿真之后,分析工具会读取这些数据库来生成覆盖率报告,包含了各部分和总体的覆盖率。

为了计算一个覆盖点coverpoint上的覆盖率,首先需要确定可能数值的个数,这也被称为。覆盖率就是采样值的数目除以域中仓的数目, 所有的覆盖点的覆盖率最终构成一个覆盖组的覆盖率,所有的覆盖组的覆盖率构成了整体的功能覆盖率。

覆盖组选项auto_ bin_ max 指明了自动创建仓的最大数目,缺省值是64。如果覆盖点变量或表达式的值域超过指定的最大值.SV会把值域范围平均分配给auto_bin_ max个仓。在实际操作中,这个方法可能不太实用.因为你会发现在一大堆自动创建的仓里寻找覆盖不到的点简直就如大海捞针,所以一般自定义最大的数量限制到8或16或者自定义仓

示例1:限制最大数量

covergroup covport;

option.auto_bin_max = 8;   // 所有coverpoint auto_bin数量=8
coverpoint tr.data ;

coverpoint tr.port{
    option.auto_bin_max = 2;// 特定coverpoint auto_bin数量=2
 }   
  
endgroup

示例2:自定义仓

covergroup CovKind;
coverpoint tr.kind {
    bins zero = {0};      // 1个仓代表kind==0
    bins lo = {[1:3], 5}; // 1个仓代表1,2,3,5
    bins hi[] = {[8:$]};  // 8个独立的仓代表8~15
    bins misc = default;  // 1个仓代表剩余的所有值4,6,7
}     // 没有分号
endgroup

//覆盖率报告
Bin #  hits  at least
=============================
hi_8    0      1
hi_9    5      1
hi_a    3      1
hi_b    4      1
hi_c    2      1
hi_d    2      1
hi_e    9      1
hi_f    4      1
lo      16     1
misc    15     1
zero    1      1

说明:

  •  注意coverpoint定义使用{ }而不是begin...end,因为它是声明性语句。
  •  大括号的结尾没有带分号”;”
  • 当自定义仓时,SV不再自动创建仓,它会忽略掉那些不被事先定义的仓所涵盖的数值,计算功能覆盖率时也只会使用你创建的仓。所以自定义仓时,使用default仓来标识那些可能已经被忘记的数值。

1、条件覆盖率

covergroup CoverPort;
    coverpoint port iff(!bus_if.reset);//当reset==1时不要收集覆盖率数据
endgroup
initial begin
    covport ck = new();//实例化覆盖组
    #1ns;
    ck.stop();         //停止收集覆盖率数据
    bus_if.reset = 1;
    #100ns bus_if.reset = 0;
    ck.start();       //开始收集覆盖率数据
...
end

 说明:

  • 可以使用关键词 iff给coverpoint添加条件,常用于在复位期间关闭覆盖以忽略不合理的条件触发
  • 也可以使用start和stop函数来控制covergroup各个独立实例。

2、枚举类型覆盖率

SystemVerilog 会自动为枚举类型的每个可能值的仓命名,但对于其他变量需要自定义状态命名。

typedef enum{IDLE,SETUP,BUSY} fsmstate_e;
fsmstate_e pstate,nstate;
covergroup cg_fsm;
    coverpoint pstate;//每个枚举类型值创建一个仓
    coverpoint nstate{
                       bins n={0,1};//自定义将前两个枚举值放入一个仓中
                     }
endgroup

3、翻转覆盖率

 coverpoint可以用来记录变量从A值到B值的跳转情况和确定任何长度的翻转次数

covergroup CoverPort;
coverpoint port {
    bins t1 = {(0 => 1), (0 => 2), (0 => 3)};
    bins t2 = (1,2=>3,4);
    bins t3 = (0=>1=>2);
    bins t4 = (0=>1=>1=>2);
    bins t6 = (0=>1=>1=>1=>2);//等效于form: (0=>1[*3]=>2)
}
endgroup

 说明:

  • 范围表达式(1,2=>3,4)创建了四个翻转过程,分别是(1=>3)、(1=>4)、(2=>3)和(2=>4)。
  • 确定任何长度的翻转次数,注意必须对转换过程中的每个状态都进行一次采样。上面t3,t4,t5是不一样的。对数值1进行3次、4次或5次重复可以使用1[*3:5]。

4、wildcard 覆盖率

  • 可以使用关键字wildcard来创建多个状态或者翻转。
  • 在表达式中,任何 X,Z或者? 都会被当成0或1的通配符。
bit [2:0] port;
covergroup CoverPort;
coverpoint port {
    wildcard bins even = {3'b??0};
    wildcard bins odd = {3'b??1};
}
endgroup

5、忽略的bin、非法的bin

在某些coverpoint可能始终无法得到全部的域值,对于那些不计算功能的域值可以使用 ignore_bins来排除,最终它们并不会计入coverpoint的覆盖率。有些采样值不仅应该被忽略,而且如果出现还应该报错,需要使用 illegal_bins对特定的bin进行标示

示例:

bit [2:0] low_ports_0_5; // 只使用数值0-5
covergroup CoverPort;
coverpoint low_ports_0_5 {
    ignore_bins hi = {[6,7]}; // 忽略数值6-7
}
endgroup

bit [2:0] low_ports_0_5;       // 只是用数值0-5
covergroup CoverPort;
coverpoint low_ports_0_5 {
    illegal_bins hi = {[6,7]}; // 如果出现6-7便报错
}
endgroup

二、交叉覆盖率

  • 关键词:cross
  • coverpoint是记录单个变量或者表达式的观测值。
  • 交叉覆盖率记录在某一时刻多个变量之间值的组合情况。
  • cross语句只允许带coverpoint或者简单的变量名。
  • 使用ignore_bins、binsof和intersect分别指定coverpoint和值域,用于清除很多不关心的cross bin。

示例1:

covergroup Covport;

    port: coverpoint tr.port{
    bins port[] = {[0:$]};
}
    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

说明:

  • kind、port是覆盖点的标号,便于分析报告等。
  • binsof、intersect分别指定coverpoint、值域。

示例2:

1、随着cross覆盖率越来越精细,需要花费不少的时间来指定哪些bin应该被使用或者被忽略。更适合的方式是不使用自动分配的cross bin, 自己声明感兴趣的cross bin。示例:

//示例一
class Transaction;
    rand bit a, b;
endclass
covergroup CrossBinNames;
a: coverpoint tr.a{ 
    bins a0 = {0};
    bins a1 = {1};
    type_option.weight=0;// 不计算覆盖率
} 
b: coverpoint tr.b{ 
    bins b0 = {0};
    bins b1 = {1};
    type_option.weight=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{ 
    type_option.weight=0; // 不计算覆盖率
} 
b: coverpoint tr.b{ 
    type_option.weight=0; // 不计算覆盖率
} 
ab: cross a,b{ 
    bins a0b0 = binsof(a) intersect {0} && binsof(b) intersect {0};
    bins a1b0 = binsof(a) intersect {1} && binsof(b) intersect {0};
    bins b1   = binsof(b) intersect {1}; 
}
endgroup

说明:

  • type_option.weight用于设置是否计算这个覆盖点的覆盖率。
  • 示例一与示例二只是实现方式不一样。

三、覆盖选项

1、option.per_instance

  • 对一个covergroup 例化多次,默认情况下SV会将所有实例的覆盖率合并到一起。单独列出每个covergroup实例的覆盖率,则设置覆盖选项option.per_instance=1;
covergroup CoverLength;
coverpoint tr.length;
    option.per_instance = 1;
endgroup

2、option.comment

  • 如果有多个covergroup实例,可以通过参数来对每一个实例传入单独注释。这些注释最终会显示在覆盖率数据的总结报告中,便于分析报告。
covergroup CoverPort(int lo,hi, string comment);
option.comment = comment;
option.per_instance = 1;
coverpoint port
{bins range = {[lo:hi]};}
endgroup
...
CoverPort cp_lo = new(0,3, "Low port numbers");
CoverPort cp_hi = new(4,7, "High port numbers");

3、option.at_least

  • 默认情况下,数值采样了1次就可以计入有效的bin。可以通过修改at_least来修改每个bin的数值 最少的采样次数,如果低于at_least数值,则不会被计入bin中。
  • option.at_least可以在covergroup中声明来影响所有的coverpoint,也可以在coverpoint中声来只影响该coverpoint下所有的bin。

4、option.goal

  • 一个covergroup或者一个coverpoint的目标是100%覆盖率。
  • 不过你也可以将其设置为低于100%的 目标,这个选项只会影响覆盖率报告,但一般不能修改这个选项。
covergroup CoverPort;
coverpoint port;
option.goal = 90;
endgroup

5、其他选项

  • sample():采样。
  • get_coverage()/get_inst_coverage():获取覆盖率,返回0-100的real数值。
  • set_inst_name(string):设置covergroup的名称。
  • start()/stop():使能或者关闭覆盖率的收集。
  • 使用$get_coverage ()可以得到总体的覆盖率。
  • 使用 covergroup_inst.get_inst_coverage ()来获取单个covergroup实例的覆盖率。

示例:

interface busifc(input bit clk);
	logic [31:0] data; 
    logic [ 3:0] port;
	
	modport TB(input clk,output data,port);
	
endinterface

class Transaction;
	rand logic [31:0] data;
	rand logic [ 3:0] port;
endclass

class Transactor;
	Transaction tr;
	mailbox mbx_in;
	virtual busifc ifc;//定义虚接口
	
covergroup CoverPort;
	port: coverpoint tr.port{
		bins pzero = {0};
		bins plo   = {[1:3],5};
		bins phi[] = {[8:$]};
		bins pmisc = default;
	}
	data_low4: coverpoint tr.data[3:0]{
		bins dzero = {0};
		bins dlo   = {[2:5],7};
		bins dhi[] = {[10:$]};
		bins dmisc = default; 
	}
	port_data_low4:cross port,data_low4{
		bins p0d0 = binsof(port.pzero)&&binsof(data_low4.dzero);
		bins p1d1 = binsof(port.plo)&&binsof(data_low4.dlo);
		bins p2d2 = binsof(port)intersect{[8:$]}&&binsof(data_low4)intersect{[10:$]};//等效于binsof(port.phi)&&binsof(data_low4.dhi);
		ignore_bins p1d2 = binsof(port.plo)&&binsof(data_low4.dhi);
		//bins pdmisc = default;//只声明感兴趣的cross bin
	}
endgroup

function new(mailbox mbx_in,virtual busifc ifc);
begin
	CoverPort   = new();
	this.mbx_in = mbx_in;
	this.ifc    = ifc;
end
endfunction
	
task main;
begin
	mbx_in.get(tr);
	ifc.port <= tr.port;
	ifc.data <= tr.data;
	CoverPort.sample();
end
endtask
	
endclass

program	automatic test(busifc ifc);

initial begin
	Transaction tr;
	mailbox mbx_in;
	Transactor tr_c;
	
	tr     = new();
	mbx_in = new();
	tr_c   = new(mbx_in,ifc);
	
	repeat(32)begin
		assert(tr.randomize);
		mbx_in.put(tr);
		tr_c.main();
		@(posedge ifc.clk);
	end
end

endprogram

module top;
	logic clk;
initial begin
	clk = 0;
	forever #5 clk =~clk;
end

	busifc ifc(clk);
	test   u_test(ifc);
	
endmodule

 随机100次:

有关(十五)覆盖率数据采样、交叉覆盖率_覆盖选项的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  4. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

  5. ruby - 覆盖相似的方法,更短的语法 - 2

    在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a

  6. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  7. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  8. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐