IC验证工程师高效战斗手册--高效验证平台搭建和冒烟测试要注意什么?

前面我们一起探讨了“如何制定高效的验证方案”,方案和战略有了,便到了具体执行。执行的第一步,即是验证平台的搭建和冒烟测试,本篇我们就一起聊聊,高效的搭建验证平台和冒烟过程中需要注意什么?

**

1.高效搭建验证平台

**
根据验证方案的规划,我们将在某个合适的时间节点,焚香沐浴更衣,开始动手搭建验证,高效的平台搭建需要注意什么呢?

1.开局怎么开?
一般有2种思路:一种是从复杂的核心的组件的编写和调用为起始,然后逐步建立完善文件结构,扩展成完整平台;另一种是先把整个平台的框架和文件结构建立起来,然后再逐个组件的编写和精雕。

哪种方式更加高效呢?

建议“白手起家”的选择第一种,有“意大利炮”的用第二种。

这里“意大利炮”指的是你是否有一个没有语法错误的初始版本的验证平台的“架子”,帮你快速的搞定平台框架结构。所以很多验证团队会开发适用于自己团队验证对象的通用初始版本验证平台生成的脚本,通过输入项目特定的参数信息,瞬间输出完整的验证平台结构和初始代码,这样确实可以省去很大一部分“体力劳动”。

如果没有这样的工具,其实第一种思路会更推荐,先着手开发最关键的某个组件,例如某个可能很难调试的agent,刚开始平台简单到就这一个agent先调通,然后慢慢的拓展其他简单的组件,这样一个明显的好处是:调试这个agent的时间可以更少,因为相比于第二种方式的文件数量以及平台的复杂度,这种方式就显的很“轻量”,调试时修改代码重新编译和运行时间就更少,干扰因素也更少,调试这个agent会更快。此外,平台的结构生长每一步都把握在手中,会更加踏实。对于初学者来说,这种方式也可以碰到更多的坑学到更多。

当然了,这两种方式也可以中和一起用,关键的难调的组件单独先调,调好后用脚本生成完整的初始版本平台,把调好的组件集成进去再进一步完善。不管怎么样,找到最适合你的高效开局方式。

2.保持合适的编译运行调试频率
接着上一个问题,我们再思考一个问题:搭建验证平台的时候,是一口气写很多代码、甚至全写完再编译运行和调试更高效,还是写一定的代码量就进行一次编译运行和调试更高效?

这里应该是后者。

一方面如第一点所说,随着平台文件数量和复杂度的增加,平台编译和运行的时间就会更大,同样问题后面编译和运行时间就会越长。

更重要的一点是代码很多的时候,对于有些耦合问题你可能需要花成倍的时间去定位,但是如果新增代码不多的时候就跑一次,出错范围就会很小很容易锁定。举一个不常见的例子,某些语法问题,仿真工具是报不出来具体的出错代码行数和问题原因的!(大家可以评论区分享出你遇到过的这种坑~)遇到这种情况可能需要通过“二分法”屏蔽代码的方式缩小范围,正向检查代码问题,此时新添加的未调试代码如果很少便可以更快的定位。

所以在搭建验证平台时,保持一个合适的编译运行调试频率可以更加高效。

3.复用性和可移植性考虑

这个问题在验证方案阶段已经有所考虑,例如团队中哪些组件可以复用和公用等,但在具体搭建的过程中可以保持这个思想进一步思考,比如平台内部,哪些代码可以通过参数化实现一次编写多次例化、哪些代码可以独立和复用、哪些代码比较典型可以抽象出来做成公共组件作为团队积累等。

4.保持好的代码风格

保持一个良好的代码风格,可以减少出错的概率,减少debug时间,别指望回过头来再“优化”,你大概率不会回来的。我们简单举几个例子:

1)代码对齐。
通过控制缩进对齐不同层级代码,例如多层if嵌套或者多层循环,同层begin end应该严格对齐,否则你看代码的时候很难梳理清楚逻辑。

2)适当的注释。
对于例如你带有技巧性设计的代码或特殊场景打的补丁要加注释说清楚,否则过段时间很可能你自己也看不懂了,增加debug的难度。

3)使用ifndef-define-`endif结构包裹文件,防止文件的重复包含和编译

`ifndef FILE_NEMA   //如果没有定义FILE_NAME宏才会进入后面程序
`define FILE_NAME   //宏定义了FILE_NAME,意味着此后上一行`ifndef条件不会再被满足,保证了文件内容不会二次包含和编译  
         【文件正式内容】
`endif 

4)文件命令尽量与class命名保持一致,减少搜索低效等问题。

5)合理分割,同一文件代码行数尽量不要太长、方法也不要太长。
如果文件代码行数太长,维护和debug会不方便,可以适当地分割,例如分件例化交互、使用`include嵌套等。同理,function和task也尽量不要太长,太长可以再进一步划分其他方法。

6)增加平台运行时间的打印信息,超时timeout机制。
例如UVM平台可以在run_phase中设定过一段时间打印一次已运行时间,既可以实时掌握平台的运行时间,还可以轻松识别是软件进入死循环还是硬件挂死。此外,超过某设置时间报fatal让平台停下来,节省不必要的等待时间。

7)使用宏定义、数据类型定义。
例如平台中多次使用的位宽、数据类型等都可以使用`define、typedef等统一定义和维护,可以减少编码时的工作量,更重要的是一旦因为需求变动等原因需要修改参数时,可以一键修改防止漏改。

8)充分合理的打印信息。
在验证平台搭建时就顺手在合适的地方加上打印信息,如进出不同phase、关键transaction信息等。

……

5.考虑后期验证case构造的快速性和简洁性

例如涉及时序协议的agent,在编写时就要想清楚,提取出哪些参数可以进行时序的精细化控制,轻松构造出各种corner场景,比如某些信号的极限delay等,可以使用plusargs等方式清晰完备的定义好,如此一来,构造相关case便更简单,甚至可以用脚本批量产生,为后面造case阶段节省时间。

2.冒烟测试

“冒烟测试(smoke test)”这个概念最早是哪里来的?有很多种说法,比较主流的有2种:

一种说是源于制造业中的管道的测试。测试的时候,用鼓风机往管道里灌烟,看管壁外面是否有烟冒出来,以此来检验管道是否有缝隙。这种人肉眼可见的简单地测试过了之后,再进一步渗油测试、带压测试等等。

另一种说是源于电路板的测试。当电路板做好以后,第一步会进行加电测试,看板子是否有因为过载或短路等问题导致“冒烟”,如果没有再进行其它测试,否则就必须重新来过。

值得一提的是,对于软件测试领域中“冒烟测试”的来源几乎没有争议的源于微软公司。微软提倡“每日build”(即每天构建一个新版本代码),冒烟测试就是在每日build之后,对系统的基本功能进行简单的测试。这种测试强调程序的主要功能进行的验证,而不会对具体功能进行更深入的测试。软件测试中冒烟测试也叫做BVT(build verification testing)或者BAT(build acceptance tesitng)。

而IC验证领域中提到的冒烟测试,大概率借鉴于软件测试领域,用若干最简单可驱动设计基本功能的测试用例,来测试和调试新建立版本的rtl设计,在此过程中打通rtl基本数据流,解决掉一部分rtl的初级bug。

IC前端验证中的冒烟测试也是rtl bug是否开始进行记录管理的节点,一般约定冒烟测试阶段的rtl bug不进行记录,冒烟测试完成之后的rtl bug才开始进行记录。

那么,从高效验证角度,在冒烟测试过程中有哪些值得注意的呢?

1.验证平台和rtl联调前,至少各自独立编译通过再联调。

仿真工具编译和运行是独立的, rtl单纯地编译解决基本的语法问题是不需要依赖验证平台的,如果带上验证平台反而增加了调试时间。所以在冒烟联调之前至少rtl和验证平台各自独立编译通过再进行,可以减少部分调试时间。

2.冒烟case要尽量“小”且覆盖核心功能。

一般可以确定多个冒烟定向case,分别覆盖住rtl的几个最核心功能。每个case都要尽量简单,要跑的快,且不要耦合很多条feature,这样才能更快的迭代调试和收敛。

让rtl bug从基本到复杂递进式层层暴露和解决,显然比一上来就解决复杂bug更高效,因为当解决复杂bug的时候发现基本bug还耦合其中这无疑是更增加了调试难度。如果冒烟测试时直接上来一个很大的case,里面涉及很多cross feature,估计rtl设计同事要抓狂了。

3.冒烟测试时验证平台随机范围也要尽量缩小。

如同上一条,还是简单原则,验证平台中除了定向参数之外的随机部分也要尽量缩小范围,可以约束在一个合适的极小的范围内。不要在这个阶段随机出很corner的特殊场景,此阶段分大量精力解决一个特殊场景的corner bug是低效的,且对整体验证进度不利。

4.冒烟阶段不要着急结束,冒烟case循环很多次都稳定pass了再往下走。

刚才提到,冒烟case虽然非常定向,但是可能还是有其他参数小范围的随机。建议刚开始冒烟调试的时候验证设计双方都固定某个种子进行调试,等到这个case pass之后,放开种子多次随机运行,如跑100次看是否都能pass。借助这些小case,清理的不只是一些rtl基础bug,也是验证平台的基础bug,此阶段尽可能的暴露一些低级问题,后面就会更顺利。

5.步步检查验证平台组件是否正确“动”起来了,谨防“假pass”。

我们应该经常保持这样一种怀疑:“看到打印出的case pass是不是真的pass了?”。我们应该在一些时间点有意识检查一下平台是否有“假pass”现象,让验证者本人更放心,而处于验证前期的冒烟阶段就是一个很好的时间点,在冒烟阶段验证平台可以多打开一些打印信息,通过log确认是不是每个组件都正常例化并“动”起来了?平台结束机制是不是符合预期?checker是不是真的生效起到了拦截的作用?平台运行时间是不是正常?

此外,多确认波形,肉眼确认激励时序、地址、数据是否符合预期?寄存器配置是否正确?波形体现出的行为是否与case想要的行为一致?关键信号位宽是不是正确?……

6.验证前期如果遇到一些很“深”的配置问题,可以加一些报错机制。

有一种场景:假如有一个case验证平台报的是最终的数据对比错误,然后追了很长时间发现还不是rtl问题,而是验证平台给的配置有问题,这个配置问题还不是直接某个参数配错了,可能更复杂,比如是某种组合情况导致的。

对于这种情况,你需要判断是否可以根本性彻底解决这个问题,或者不会出现其他组合触发类似问题。因为你需要考虑这次定位这么久结果还不是rtl问题,下次万一出现是不是还需要定位很久。除非你真的可以确保一次解决干净不会有类似问题了,像这种debug很长时间才发现,藏的很深的配置问题其实可以顺手加一个断言或报错语句,监视住相关的配置或rtl信号异常行为,再次出现就可以瞬间定位到源头。

注意我们添加这个报错语句的目的不是为了“检查平台”,而是加速定位。我们不需要专门加很多这种“检查平台”的语句,这样的语句大部分是没有意义的,因为大部分问题可以轻易暴露,只有这种很“深”的特殊情况才有必要加一句。

如果你无法预判哪些情况会导致这么“深”的问题,那就不要预判了,随着随机量的增加,这次遇到的场景下次大概率还会遇到,碰到一个处理一个就可以了~

结语

今天我们依然从“高效”为出发点,一起讨论了高效的搭建验证平台的注意事项,又谈了冒烟测试的来源和内涵、冒烟测试过程中有哪些提高验证效率的细节等。

篇幅有限,欢迎大家共同探讨交流!

验证高效之道,乃细节之道,【杰瑞IC验证】与你同在,加油!

欢迎关注同名公 ~ 众 ~ 号!

你可能感兴趣的:(IC验证工程师高效战斗手册,芯片)