当前位置: 首页 > news >正文

【IC每日一题:SVA和覆盖率知识点】

IC每日一题:SVA和覆盖率知识点

  • 3 SVA和覆盖率知识点
    • 3.1 代码覆盖率、功能覆盖率和断言覆盖率的区别
    • 3.2 coverage一般不会直接达到100%,当发现condition未cover到的时候,该怎么做?
    • 3.3 function coverage和code coverage的区别,以及他们分别对项目的含义?
    • 3.4 代码覆盖率和功能覆盖率,一高一低分别意味着什么?
    • 3.5 交叉覆盖率的优点?
    • 3.6 covergroup在类中使用和类外分别如何使用?
    • 3.7 断言 and 和intersect的区别?
    • 3.8 写一个断言:a为高的时候,b为高,且a为高的时候,下一个周期b也为高;
    • 3.9 什么是立即断言和并发断言?简述一下assert的用法
    • 3.10 a[*3]、a[->3]和a[=3]的区别

【博客首发与微信公众号《漫谈芯片与编程》,欢迎专注一下】

3 SVA和覆盖率知识点

断言:是对设计违例的一种严查,能够在违例时立刻报出错误;
覆盖率:是定量衡量IC验证质量的指标和指导提高验证质量;

3.1 代码覆盖率、功能覆盖率和断言覆盖率的区别

这三个覆盖率是在验证过程中用于定量衡量验证的具体指标;
代码覆盖率:衡量的是设计代码中哪些部分已经被测试到了。
行覆盖率(line):多少行代码被执行。
分支覆盖率(path):代码中的分支被执行到;
翻转覆盖率(toggle):哪些单bit的值为0或1
有限状态机覆盖率(FSM):状态机中哪些状态和状态转换已经被访问过了

功能覆盖率:设计的功能特性是否被充分验证–通过定义一组覆盖点(cover points)来衡量设计的功能特性是否被测试到。
事务覆盖率 (Transaction Coverage): 检查特定类型的事务(如读写操作)是否被执行。
状态覆盖率 (State Coverage): 检查设计的状态机是否遍历了所有可能的状态。
交叉覆盖率 (Cross Coverage): 检查多个功能点之间的组合是否被测试到。
边界覆盖率 (Boundary Coverage): 检查设计在边界条件下的行为是否被测试到。

断言覆盖率:设计中的断言语句被触发的比例。
断言语句用于检查设计的内部状态或信号是否符合预期。

【总结】
代码覆盖率关注的是代码的执行情况,确保每一行代码都被执行过。
功能覆盖率关注的是设计的功能特性是否被充分验证。
断言覆盖率关注的是设计中的断言语句是否被触发,以检查设计的内部状态是否符合预期。

3.2 coverage一般不会直接达到100%,当发现condition未cover到的时候,该怎么做?

查看覆盖率报告去定位哪些条件没有被覆盖到,是因为没有满足该条件的前提条件还是因为根本就遗漏了这些情况,根据这个我们去编写相应的case,进而将其覆盖到。还要找设计人员一块review看一下,看看哪些未覆盖到的点需要怎样构造激励; 当然最暴力的一种方式是:加大种子随机轮数回归;
具体步骤来说:

  1. 分析未覆盖的条件
    确定未覆盖的具体条件:使用覆盖率报告工具提供的详细报告,找出哪些条件未被覆盖。确定这些条件的具体位置和上下文。
    理解未覆盖的原因:分析未覆盖条件的原因,可能是由于某些特定的输入组合、状态转换或其他条件难以触发。
  2. 修改或增强测试用例
    增加新的测试用例:根据未覆盖的条件,编写新的测试用例来专门覆盖这些条件。例如,如果某个分支条件未被覆盖,可以编写一个测试用例来触发该条件。
    修改现有测试用例:检查现有的测试用例,看看是否可以通过修改输入数据或配置来触发未覆盖的条件。例如,调整随机化约束或增加特定的激励模式。
  3. 使用约束和定向测试
    约束随机化:使用约束来指导随机化生成器,使其更有可能生成能够覆盖未覆盖条件的测试用例。例如,在 UVM 中,可以使用 constraint 来限制随机化生成的值范围,以提高特定条件被覆盖的概率。
    定向测试:编写定向测试用例,专门针对未覆盖的条件。例如,手动构造特定的输入序列来触发未覆盖的条件;

3.3 function coverage和code coverage的区别,以及他们分别对项目的含义?

代码覆盖率:关注的是代码的执行情况,确保每一行代码都被执行过。
功能覆盖率:关注的是设计的功能特性是否被充分验证。

功能覆盖率coverpoint和covergroup的代码示例:

// 定义covergroup
covergroup my_covergroup @(posedge clk);// 定义coverpointcoverpoint my_module.a {bins a_values[] = {[0:255]}; // 覆盖a的所有可能值}// 定义另一个coverpointcoverpoint my_module.b {bins b_values[] = {[0:255]}; // 覆盖b的所有可能值}// 定义交叉覆盖率cross a_values, b_values; // 覆盖a和b所有可能的组合
endgroup

3.4 代码覆盖率和功能覆盖率,一高一低分别意味着什么?

1.代码覆盖率低 + 功能覆盖率高

1.1)有可能是cover group写得不完备,进一步地,测试点分解和test plan可能也不完备,遇到这种现象,应当警觉,需要明确是否存在测试点,test plan, cover group不完备的情况。

1.2)DUT中有大量冗余代码。或者集成进来的公共IP只用到其中一部分功能。

2.代码覆盖率高 + 功能覆盖率低

2.1) 功能覆盖率的sample有问题,即相关的场景都打到了,但cover group没有采样到,这个对于新开发的验证环境容易出现。

2.2)cover group中的一些cross bin或者conner点没覆盖到,需要增加direct case,修改随机约束或者增加回归次数。项目经过这个过程是比较正常的。

3.5 交叉覆盖率的优点?

交叉覆盖率(Cross Coverage)是功能覆盖率(Functional Coverage)的一种扩展,它通过组合多个覆盖点(Cover Points)来确保设计的不同部分之间的交互也得到了充分的验证。

3.6 covergroup在类中使用和类外分别如何使用?

covergroup可以在类中使用,也可以在类外使用。在类中使用时,covergroup可以访问类的成员变量和方法;在类外使用时,covergroup可以访问模块或程序块中的信号和变量;一般更多还是在类外使用covergroup;

1.在类内使用covergroup:
在类内定义 covergroup 通常用于将覆盖率模型与特定的验证组件(如监视器、驱动器等)关联起来。这种方式可以更好地封装和管理覆盖率数据。
假设我们有一个总线接口,并且我们想在监视器中定义一个 covergroup 来测量总线事务的功能覆盖率。

class bus_transaction extends uvm_sequence_item;rand bit [31:0] address;rand bit [⅛:0] data;rand bit is_read;  // 0 for write, 1 for read`uvm_object_utils_begin(bus_transaction)`uvm_field_int(address, UVM_DEFAULT)`uvm_field_int(data, UVM_DEFAULT)`uvm_field_int(is_read, UVM_DEFAULT)`uvm_object_utils_endfunction new(string name = "bus_transaction");super.new(name);endfunction
endclassclass bus_monitor extends uvm_monitor;`uvm_component_utils(bus_monitor)// 定义覆盖组covergroup bus_cg with function sample(bit [31:0] addr, bit [⅛:0] dat, bit is_rd);// 定义 coverpointcp_is_read: coverpoint is_rd {bins read = {1};bins write = {0};}cp_address: coverpoint addr {bins low = {[0:1023]};bins high = {[1024:2047]};}cp_data: coverpoint dat {bins low = {[0:127]};bins high = {[128:255]};}// 定义交叉覆盖率cp_is_read_x_address: cross cp_is_read, cp_address;cp_is_read_x_data: cross cp_is_read, cp_data;cp_address_x_data: cross cp_address, cp_data;endgroup// 实例化覆盖组bus_cg cg;// 构造函数function new(string name, uvm_component parent);super.new(name, parent);cg = new();  // 实例化覆盖组endfunction// 监视器的主要任务virtual task run_phase(uvm_phase phase);bus_transaction tr;forever begin// 假设这里从总线上捕获事务// 例如:tr = bus_transaction::type_id::create("tr");//       tr.address = ...;//       tr.data = ...;//       tr.is_read = ...;// 更新覆盖组cg.sample(tr.address, tr.data, tr.is_read);endendtask
endclass

2.在类外使用covergroup
在类外定义 covergroup 通常用于更通用的覆盖率模型,或者在多个组件之间共享同一个覆盖率模型。这种方式可以提高覆盖率模型的重用性;
示例:在类外定义 covergroup 通常用于更通用的覆盖率模型,或者在多个组件之间共享同一个覆盖率模型。这种方式可以提高覆盖率模型的重用性。

// 定义覆盖组
covergroup bus_cg with function sample(bit [31:0] addr, bit [⅛:0] dat, bit is_rd);// 定义 coverpointcp_is_read: coverpoint is_rd {bins read = {1};bins write = {0};}cp_address: coverpoint addr {bins low = {[0:1023]};bins high = {[1024:2047]};}cp_data: coverpoint dat {bins low = {[0:127]};bins high = {[128:255]};}// 定义交叉覆盖率cp_is_read_x_address: cross cp_is_read, cp_address;cp_is_read_x_data: cross cp_is_read, cp_data;cp_address_x_data: cross cp_address, cp_data;
endgroupclass bus_monitor extends uvm_monitor;`uvm_component_utils(bus_monitor)// 实例化覆盖组bus_cg cg;// 构造函数function new(string name, uvm_component parent);super.new(name, parent);cg = new();  // 实例化覆盖组endfunction// 监视器的主要任务virtual task run_phase(uvm_phase phase);bus_transaction tr;forever begin// 假设这里从总线上捕获事务// 例如:tr = bus_transaction::type_id::create("tr");//       tr.address = ...;//       tr.data = ...;//       tr.is_read = ...;// 更新覆盖组cg.sample(tr.address, tr.data, tr.is_read);endendtask
endclass

【总结】
在类内使用 covergroup:
优点:更好的封装性,覆盖率模型与特定组件紧密关联。易于管理和维护。
适用场景:当覆盖率模型与特定组件高度相关时。当需要对覆盖率模型进行更多控制和定制时。

在类外使用 covergroup:
优点:更高的重用性,可以在多个组件之间共享。代码更简洁,覆盖率模型与组件分离。
适用场景:当覆盖率模型较为通用,可以在多个地方使用时。当需要在多个组件之间共享同一个覆盖率模型时

3.7 断言 and 和intersect的区别?

断言(Assertions)用于验证设计的正确性,而and和intersect是用于组合多个条件的逻辑运算符;
and运算符:and运算符用于逻辑与操作,它要求所有的条件都为真时,整个表达式才为真。在断言中,and用于连接多个条件,确保它们同时满足

chk_a_and_b: assert property (@(posedge clk) a and b and c);

intersect运算符:intersect运算符用于定义一个时间窗口,在这个窗口内,两个或多个事件必须同时发生。在断言中,intersect用于确保多个事件在特定的时间范围内同时满足;

chk_a_intersect_b: assert property  (@(posedge clk) a intersect b);

and用于连接多个条件,确保它们同时满足;而intersect用于定义一个时间窗口,确保多个事件在这个窗口内同时发生。

3.8 写一个断言:a为高的时候,b为高,且a为高的时候,下一个周期b也为高;

// 断言property p_a_high_b_high;@(posedge clk) (a && b) |-> (a && b)[=>1];endpropertyassert property (p_a_high_b_high)else $error("Assertion failed: When a is high, b should be high and in the next cycle as well.");

3.9 什么是立即断言和并发断言?简述一下assert的用法

立即断言 (Immediate Assertions):立即断言是在执行流程中立即计算和检查的断言。它们通常用于在过程块(如 initial 或 always 块)中检查条件。

// 带成功分支的立即断言assert (a == 1) $display("a is 1")  // 成立,输出 "a is 1"else $error("a is not 1");assert (b == 1) $display("b is 1")  // 不成立else $error("b is not 1");  // 输出错误消息

并发断言 (Concurrent Assertions):并发断言是在仿真过程中始终处于活动状态的断言,在设计的任何地方都可以使用的断言,它们不会阻塞仿真的执行,它们通常用于检查时序行为。并发断言使用 property 和 sequence 语法来描述复杂的行为。

// 序列sequence s_a_high;a ##1 b;  // a 发生后的一个周期 b 必须发生endsequence// 属性property p_a_high_b_high;@(posedge clk)  s_a_high;endproperty// 并发断言assert property (p_a_high_b_high)else $error("Assertion failed: When a is high, b should be high in the next cycle.");

【总结】
立即断言:在过程块中立即计算和检查。适用于简单的条件检查。
并发断言:在仿真过程中始终处于活动状态。适用于复杂的时序行为检查。

3.10 a[*3]、a[->3]和a[=3]的区别

a[*3]、a[->3]和a[=3]是用于描述序列(sequences)的操作符;

  1. a[*3]
    语法: a[*3]
    含义: a 在连续的 3 个周期内保持不变。
    解释: 这表示 a 信号在 3 个连续的时钟周期内保持相同的值。这个值可以是 0 也可以是 1,只要在这 3 个周期内保持不变即可。
    示例
sequence s_a_stable_3;a[*3];
endsequenceproperty p_a_stable_3;@(posedge clk) s_a_stable_3;
endpropertyassert property (p_a_stable_3) $display("a is stable for 3 cycles");

在这个示例中,a 信号在 3 个连续的时钟周期内必须保持相同的值。

  1. a[->3]
    语法: a[->3]
    含义: a 在 3 个连续的周期内至少有一次为 1。
    解释: 这表示在 3 个连续的时钟周期内,a 信号至少有一个周期为 1。a 可以在任意一个或多个周期内为 1。
sequence s_a_one_in_3;a[->3];
endsequenceproperty p_a_one_in_3;@(posedge clk) s_a_one_in_3;
endpropertyassert property (p_a_one_in_3) $display("a is 1 at least once in 3 cycles");

在这个示例中,a 信号在 3 个连续的时钟周期内必须至少有一个周期为 1。

  1. a[=3]
    语法: a[=3]
    含义: a 在 3 个连续的周期内都为 1。
    解释: 这表示 a 信号在 3 个连续的时钟周期内都必须为 1。
sequence s_a_high_3;a[=3];
endsequenceproperty p_a_high_3;@(posedge clk) s_a_high_3;
endpropertyassert property (p_a_high_3) $display("a is high for 3 cycles");

在这个示例中,a 信号在 3 个连续的时钟周期内必须都为 1。

以上是对IC验证中SVA和覆盖率的小结;

【REF】

1.https://blog.csdn.net/graymount/article/details/121391722


http://www.mrgr.cn/news/70359.html

相关文章:

  • Python---re模块(正则表达式)
  • Springboot 微信小程序定位后将坐标转换为百度地图坐标,在百度地图做逆地址解析
  • Aippyy如何写论文?ai人工智能写作哪家好?
  • 安卓aab包的安装教程,附带adb环境的配置
  • Unity编辑器的高级扩展技术
  • 第七部分:2. STM32之ADC实验--AD多通道(AD采集三路传感器模块实验:光敏传感器、热敏传感器、反射式传感器附赠温湿度传感器教程)
  • HTB:Photobomb[WriteUP]
  • 【安全测试】sqlmap工具(sql注入)学习
  • 【微服务】Docker 容器化
  • 【go从零单排】WaitGroup
  • FBX福币交易所 “马斯克概念股”爆发! 特斯拉涨4%,DXYZ涨28%
  • Django SSE 高并发分析与解决
  • docker安装jdk8
  • Android Framework 框架层主要功能类的基本介绍
  • 周报8<自学>
  • 第1章 初识Kubernetes
  • 记录学习react的一些内容
  • 华为ISC供应链服务运营:流程、组织、治理与绩效管理的综合框架
  • find 命令是 Linux 系统中用于在文件系统中查找文件和目录的强大工具
  • 智能量化交易的核心应用与中阳发展前景
  • RTSP播放器EasyPlayer.js无插件直播流媒体音视频播放器使用http与https的区别
  • 【SpringBoot】——Spring Validation之用户注册、JWT令牌之用户登入
  • Debezium日常分享系列之:debezium3模块
  • ubuntu 22.04 server 安装 mysql 5.7.40 LTS
  • 优化时钟网络之时钟抖动
  • java -jar`命令详解:运行JAR文件、传递参数与性能调优