你的case真的pass了吗?
来源| 杰瑞IC验证(ID:Jerry_IC)
动态仿真是芯片前端验证最常见的手段,通过给DUT施加激励,然后检查输出结果或者内部行为,确保DUT功能和性能的正确性。
验证新手经常犯的一个错误是,看到所有case都PASS就觉得万事大吉。
事实上,这个case是真的PASS了吗?
有没有可能是出错了没及时报告?
或者测试激励根本就没有成功注入,DUT根本就没有动起来或者一直在空转?
那么,如何判定一个case是真的PASS了呢?
除了人工查看log和确认波形等手段,Q哥今天主要聊一聊如何根据仿真log自动排查各种假PASS的情况。
1
TestBench错误自检
通常大家会在TestBench里检查到异常行为或者数据比对出错的时候,打印一条错误信息。
尤其是在UVM环境里,使用uvm_error、uvm_fatal、uvm_warning非常方便。
根据这些错误信息,就可以判定Cass PASS或FAIL。
单独跑一个Case的时候,人工查看没有问题。
但是大批量测试的时候,就需要使用脚本来汇总错误,生成测试报告,以及后续处理:比如Case PASS就删除仿真产生的临时文件以便节约磁盘空间,Case FAIL就删除当前case的覆盖率数据,等等。
为了便于脚本自动识别case是否PASS,Q哥比较推荐的做法是如代码片段1所示:
代码片段1 TB错误自检
UVM的好处是内部会自动记录uvm_error、uvm_fatal、uvm_warning、uvm_info的个数,通过get_severity_count即可得到它们的计数。
如果使用纯Verilog或者SV,需要大家自行添加计数,然后在TB结尾做类似的判断。
大家有没有想过,这里为何还需要判断UVM_FATAL的个数呢?在执行到这里之前,`uvm_fatal语句应该早就结束仿真了吧?
看过Q哥之前文章uvm_info高级技巧(2) 点击跳转 的朋友们应该还记得,uvm_fatal是可以被掩盖掉,或者指鹿为马当作uvm_error甚至uvm_info的。
所以并不一定会提前结束仿真。
另一个问题,这里为什么要用$display,而不用uvm_fatal和uvm_info呢?
原因同样是因为uvm_fatal和uvm_info可能会被屏蔽掉,可能影响后期离线检索。
再来一个问题(欢迎爱提问题的朋友),为什么不直接排查仿真log里的UVM_ERROR和UVM_FATAL?
而是在这里根据UVM_ERROR和UVM_FATAL的个数来打印CASE PASS,之后再查找CASE PASS?这不是多此一举吗?
别急!这是因为仿真可能在没有uvm_error和uvm_fatal的情况下异常结束,比如超时、磁盘满了,或者提交到服务器的任务被管理员kill掉了,等等。
用脚本排查仿真log很可能发现不了任何错误,最终会误判CASE PASS。
这并不是我们所期望的!
2
排查各种运行错误
TestBench自检的错误通常都是我们预先给仿真工具挖的坑,我们是心知肚明的。
实际跑仿真的时候,还有很多意想不到的错误是仿真工具给我们埋的雷,不仔细看log很容易就忽视了。
而这些错误,很可能意味着仿真激励无效甚至掩盖DUT的bug。
这里Q哥说一些常见的错误,主要手段都是用脚本在仿真log里检索错误关键字,排查各种仿真错误,进一步鉴定假PASS。
2.1 排查SVA断言错误
动态仿真过程中,检查到不符合assertion描述的异常行为时,也会打印一条Offending信息,告诉大家哪条assertion语句检查失败,如图1所示;
图1 assertion错误信息
这种错误TB自检完全发现不了。仿真结束后,需要在仿真log里面排查Offending关键字,来确保CASE FAIL。
2.2 排查随机约束错误
随机约束失败是验证新手容易忽视的一个错误。
要命的是,有些仿真器并不会因为随机失败就提前结束仿真。
如果Testbench里面没有对激励的有效性进行判断,可能会导致case最终误报PASS,原本要测试的feature并没有被测到啊!
对于显式的随机约束,只需要在randomize之前加上assert就好了,如代码片段2所示。
代码片段2 随机失败结束仿真
对于像`uvm_do_with、`uvm_rand_send等内嵌的隐式随机约束,不能直接加assert,需要在仿真log里面对随机约束失败进行排查。
另外提醒大家,这里需要根据所用的仿真器打印的log进行具体排查,比如VCS,通常会打印下面的信息,那么根据Solver failed这两个关键字进行排查就可以了。
图2 VCS随机约束失败信息
2.3 排查参考模型错误
对于使用参考模型进行bit-true match比对的case,务必要检查参考模型运行时的错误信息。
需要额外强调下,参考模型的打印信息很可能没有记录在仿真log里,需要在调用参考模型的时候,单独记录到其他log里。
比如在Testbench里面通过$system系统任务调用C-Model时,可以通过加上“|& tee ref_model.log”,把C-Model打印到屏幕的信息,同时记录到ref_model.log这个文件里;后续对这个log进行排查,确保C-Model运行无误。
2.4 排查类型转换错误
数据类型转换失败,也是验证新手容易忽视的错误。
最常见的就是把一个int变量直接赋值给一个枚举变量时,类型转换失败,如下面代码片段3所示。
代码片段3 int类型赋值给枚举
虽然VCS等仿真器在编译的时候就会警告这种赋值可能有问题,但是通常编译log里面的Warning实在太多了,根本没注意到。
图3 VCS Warning:int转枚举
跟上面提到的随机失败类似,数据类型转换失败很可能导致case的输入参数是无效的,仿真虽然没报错,但是测试点并没有被测到。
解决办法很简单,如代码片段4所示,对于不同类型赋值的时候,尽量使用$cast转换。
代码片段4 用cast转换不同数据类型
这样错误会光明正大爆出来,如图5所示。之后再排查关键字“Error-”就可以了。
图5 VCS错误提示:cast转换失败
3
预防DUT空转
除了前面提到的各种可能忽视的错误,Case仍然可能因为无效激励没有动起来,或者虽然动起来了,读写的数据都是0,也就是DUT在空转,从而出现假PASS。
那么如何预防DUT空转呢?
Q哥这里说几点思路,具体实施大家根据实际情况取舍。
首先,就是对激励的有效性做检查。这一点可能比较难,建议先对关键的输入参数进行检查。除了直接检查数据,也可以通过功能覆盖率里面定义illegal_bins 自动排查。
其次,排查assertion log。如果DUT没有动起来,那么所有的assertion都是空成功。
再次,对monitor和scoreboard里的关键信号或者数据检查进行计数,尤其是对于非0数据进行计数,然后在final_phase里判断这些计数器是不是0,就可以确定是否空转。
总结
如何确保一个case真的pass了?
就像如何确保一颗芯片没有bug, 从哲学上来说,这是不可能完成的任务,我们只能尽可能降低出错的可能性。
所以Q哥本文说的都是各种假PASS 的情况,难免有所纰漏。
希望抛砖引玉,提醒大家在验证工作中对各种潜在的风险保持警惕,把bug扼杀在摇篮里。
——The End——
历史推荐
uvm_info高级技巧(2)--- 对uvm_error 能睁一只眼闭一只眼吗?
本文分享自微信公众号 - 杰瑞IC验证(Jerry_IC)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
5千字的SpringMVC总结,我觉得你会需要
思维导图 微信公众号已开启:【java技术爱好者】,还没关注的记得关注哦~ 文章已收录到我的Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary 概述 SpringMVC再熟悉不过的框架了,因为现在最火的SpringBoot的内置MVC框架就是SpringMVC。我写这篇文章的动机是想通过回顾总结一下,重新认识SpringMVC,所谓温故而知新嘛。 为了了解SpringMVC,先看一个流程示意图: 从流程图中,我们可以看到: 接收前端传过来Request请求。 根据映射路径找到对应的处理器处理请求,处理完成之后返回ModelAndView。 进行视图解析,视图渲染,返回响应结果。 总结就是:参数接收,定义映射路径,页面跳转,返回响应结果。 当然这只是最基本的核心功能,除此之外还可以定义拦截器,全局异常处理,文件上传下载等等。 一、搭建项目 在以前的老项目中,因为还没有SpringBoot,没有自动配置,所以需要使用web.xml文件去定义一个DispatcherServlet。现在互联网应用基本上都使用SpringBo...
- 下一篇
Hyperf 发布 v2.0.9 版本,企业级的 PHP 微服务云原生协程框架
更新内容 本周主要新增了一些特性,并修复了一些组件的 🐛Bug,继续提升 Hyperf 的稳定性,发布于 2.0.9 版,建议用户使用以下命令更新此版本。 composer update "hyperf/*" -o 直接访问 官网 hyperf.io 或 文档 hyperf.wiki 查看更新内容 新增 #2331 hyperf/nacos 组件增加授权接口。 #2331 hyperf/nacos 组件增加 nacos.enable 配置,用于控制是否启用 Nacos 服务。 #2331 hyperf/nacos 组件增加配置合并类型,默认使用全量覆盖。 #2377 为 gRPC 客户端 的 request 增加 ts 请求头,以兼容 Node.js gRPC server 等。 #2384 新增助手函数 optional(),以创建 Hyperf\Utils\Optional 对象或更方便 Optional 的使用。 修改 #2331 修复 hyperf/nacos 组件,服务或配置不存在时,会抛出异常的问题。 #2356 #2368 修复 pid_file 被用户修改后,命...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Red5直播服务器,属于Java语言的直播服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS关闭SELinux安全模块