IC验证概念总结

摘要:
我忘了我在哪里看到了以下问题和答案。我补充了夏静的文章和我自己的验证经验,作为未来研究的参考。这是夏静的回答。这是正确的。大多数验证工作都是尽可能多地查找错误。
一份代码,在写完之后,一定要再经过一次或多次整理和打磨,才能算完成的;一份代码,一定要把其有效代码行,精简、锤炼到最少、最短、最有效,才能算完成的。
 
下面这些问题和回答是忘记是在哪里看到的了,参考夏晶的文章,和我自己的验证经验,做了补充,作为日后学习的参考。
Q:验证的目的?
A:这也是发现Bug,发现所有的Bug,或者证明没有Bug(转自夏晶的帖子),无论任何验证语言、任何验证环境、任何验证方法学、任何Feature List,都是为了达成这一目的而使用的方法,或者所手段。这是夏晶给出来的回答,很对,验证里面大部分的工作都是在尽可能的发现更多的bug。
 
注释:可是我觉得验证目的应该有更好的阐述,验证的目的是为了验证设计的可用性!发现bug,清楚掉所有的bug,只是证明这个设计是可用的,没有问题的,可是验证不应该仅仅局限于此,我们还需要验证设计的性能(performance),证明这个设计是高效的,
 
Q:对验证工程师的要求?
       Hacker mentality ,Organized testing ,Tool automation。
       如何做更多的testcase、如何覆盖更多的测试点、如何充分的利用服务器、如何尽可能最大化的自动比对
       强调一下:“注重细节”是验证工程师一个非常非常好的工作习惯。
       
       (验证人员必须要懂得代码,懂得分析逻辑,甚至能够通过代码分析出可能的疑点,更好的,能够理解整个系统的运作,理解前端后端的实现,找出设计人员视角的盲区,才能更好的发现Bug,解决Bug),从当前表面上正确运行的波形中,对照代码,寻找其他可能发现的问题,这是一种好的分析方式,值得学习!!
       当然对验证工程师的要求不仅仅是这些,还有很多附带的要求(慢慢补充):
       1. 淘金的执念,缺陷就在那里,作为验证人员,一定要有这种强烈的,不可动摇的执念或者说饥渴感
       2. 淘金的技巧,如何找关键部分,是非常讲究的事情,兼顾风水、心理、外交、直觉等多方面知识,很难给出综合性的分析。下面几点可作为Hint:
          1) 如前面所说的,只知道跑TC,跑错后让设计人员定位的验证人员负责的区域;
          2) 对实现没什么概念的设计人员设计的模块;
          3) 责任人变来变去的地方;
          4) DFT相关的地方(验证人员的DFT知识严重缺乏);
          5) 规格老是变来变去的地方及其可能影响的地方;
          6) 第一次做代码集成人员连接的顶层位置;
          7) 浮浮躁躁、毛毛糙糙的新员工负责的地方;
          8) 时钟域(几乎当前所有的验证人员都不关心时钟正确性,只要能跑TC);
          9) 所有人都认为没有问题的地方;
        10) 验证人员宣称放弃的地方;
        11) 技术难度比较高的地方;
        12) 你以前项目发生过问题的地方(相同或类似的问题很大几率存在);
        13) 整个系统中相关性非常高的一连串区域;
        14) 协议和时钟转换的区域;
        15) 其他隐藏在内心深处的秘密。
找到最后的bug的经验:
1) 反向思考。最后阶段,大部分人员的思路都已经固化了,像一条绳子一样,不断的朝一个方向缠绕、缠绕。反向的思考往往能突破这个限制。当然,反向思考这个东西,很多时候就是忽悠,难以做到。我的一个经验是可以多听取一下局外人的一些意见,例如软件人员的意见。当然,这其中大部分的意见都是无关痛痒的瞎扯,但偶尔、偶尔会出现一些能够引发进一步思索的缺口。
2) 和谐。这里没有任何问题,芯片运作一切正常,没有任何差错。但是你拿着架构图看、或者拿着时钟结构图看、或者打开最复杂的ST波形看,心中却总是有一种说不清道不明的感觉,没错,虽然一切正常,但是某个地方,却有那么一点点不和谐,就像合唱团中插入了一个走调的家伙一样。可能是非常微妙的一个路径,可能是波形上非常诡异的一个脉冲。对了,就是这个地方,追下去,即使工作正常,这里也可能存在和设计意图不符的东西存在。
 
80%的问题都可以通过20%的测试和时间去发现和解决,而剩余20%的问题需要80%的测试和时间去解决,首先会build几个最初的TC用来测试基本的通路能否pass,然后build一条复杂的Directed TC,尽量覆盖70%的feature,交付给设计人员进行初始定位问题,这条TC能够帮助设计人员定位超过70%的问题,而验证人员在这一个月中,有足够的时间完善Corner的TC、Random的TC和环境,然后集中精力完成剩下10%问题的解决。
 
检视:
     代码检视是最容易发现问题的步骤,代码检视不仅仅是设计人员的事,也是验证人员的事。所以对于新交付的代码,按照我的经验,建议验证人员先检视(尤其是设计人员是两年以内设计经验的),不过,这个检视绝对不要是傻看代码,要跑一条TC,最简单的,就一个读写就可以了,保存所有信号的波形,然后打开Verilog代码,对照着波形检视。
      1) 所有信号全部抓出来看一遍,红色的(X)、黄色的(Z),简单确认一下,然后Alt+Tab,切换到CMM页面即可(百试百灵,至今为止从未失手,nLint不是万能的)。
      2) 模块间的握手信号,全部抓出来看一下,是脉冲信号还是电平信号(98.765%的设计人员,都不会在信号名上注明是脉冲或电平),脉冲信号是必须立刻采样的,电平信号是需要鉴沿的,如果握来握去,如果还有异步,基本上,检视出问题的概率非常高。
      3) 在一个always中,对多个信号赋值的;在一个always中,elsif数量超过6个的;在一个always中,if的条件组合中包括超过5个信号的;都是高产田。
     4) 协议理解上和自己理解相异的,例如对于我,AXI相关设计未按照我《AXI总线设计的二十一条忠告》的。
代码,是设计人员思路的直接映射,而设计人员的思路,有时候真的是一根筋。通过检视,或者加上设计人员的讲解,可以直接了解一下到设计人员的思路、逻辑思维模式,非常有助于去构造一些检测其思路正确或不正确的点,验证人员的思维其实很简单,抬竹杠就好。
 
到最后阶段的检视,对于验证人员,可能需要更加地扩大视角,围绕代码为核心,TC、波形、脚本都需要涉及。对于这里,我还是再强调一遍吧。验证人员拥有设计人员所不同的视角,所以一定能够发现潜藏在其中的问题.
 
检视的经验:
OK,这里我可以再补充一下我个人检视代码的经验,我的步骤如下:
1) hdl_stat统计整个模块代码行数,及各个子模块代码行数分配;
2) 打开代码顶层,快速浏览整个代码,获取这几个信息:代码风格、设计人员的思维成熟度、代码结构、重用度、逻辑类代码和集成类的分布、关键C Path和关键D Path的位置;
3) 按照现有的经验,其实已经大致能够推断出该模块整体的缺陷数量和缺陷分布了;
4) 先简后难,先扫除直接就能够看出的Bug,这种Bug分布比较散,没什么特别的依据,但很多问题,真的很简单,就在设计人员鼻子底下(不要超过2小时);
5) 用Verilog构造最简单激励给模块,保留波形供对照,如有疑问,更改激励再仿(不要超过3小时);
6) 然后,因为我有设计经验,我就会思考如果自己是设计人员,我会怎样划分模块、描述关键控制逻辑,如果和设计者不符的地方,着重分析;对识别出来的关键控制逻辑,例如异步握手、堆栈、链表、数据拼接,静下心来,慢慢看,慢慢看。对于疑点,构造简单激励,出波形对比。
 
OK,我拿我曾经的一个模块Security Engine代码作为实例,如果我进行检视如何进行。
1) 代码行数约17000,行数最多的集中在几个整体控制模块:sec_ctrl(2235)、sec_slave(2121)、sec_channel(1669)、sec_master(1193),除了这几个大模块,几个算法都分散为非常多小模块,相互调用搭成aes_core、kasumi_core等算法模块被顶层调用。
2) 第一轮检视,快速浏览。各个算法模块的输入输出非常干净,都是通过run、done进行握手,其内部都是轮运输,通过round控制,其中aes_core还是纯复用以前项目的模块,而顶层几个ctrl模块,则相互交互非常复杂,特别是代码数量最多的模块,数据交互特别复杂的sec_ctrl和set_master,居然没有状态机,看起来设计人员是希望通过自己的逻辑思维,直接描述其控制;而sec_slave,纯寄存器描述,而且是大量复制代码搭建,技术含量低;结构上,sec_channel是一级控制,sec_ctrl和set_master是二级控制,各个算法Core是三级控制。代码风格上,设计人员部分遵守代码规范,但很多地方自以为是,为了自己方便写了不少擦边球的代码。
3) 分析,aes_core理论上缺陷将很少,而其他几个算法Core,如果round控制上没有发现错误,那么错误通过RM比对验证,效率更高;然后,sec_channel,可以着重关注状态机和状态机对应的控制信号是否正确;最后,sec_ctrl和set_master的交互,一定是关键,特别是代码量大的部分。
4) 第二轮检视,对算法Core的各个round控制信号检视,是否符合run、done控制;对sec_slave的寄存器读写控制检视,是否有笔误和拷贝的错误;检视整个代码集成和互联;简单查看其它代码中if和else比较复杂的地方,记录可能的疑点。
5) 构造一条TC,正常而言,是通过sec_channel调配sec_ctrl完成一次算法运算(用最简单的Verilog搭建TB,超过2小时是否非常失败的事情)。根据波形,将sec_channel、sec_ctrl和set_master主要逻辑,全部过一遍。
6) 关键逻辑,重点关注,关键疑点,修改TC,重点覆盖。
 
让合适的人做合适的事情,以及合适的搭配和互助。
 
Q:如何跟踪缺陷?
    A:可以考虑bug-zillar这类的工具---- 自动跟踪问题,在AMD的工具叫UBTS
 
Q:作业提交系统(lsf或grid-engine),这个工具需要继续去学习!
    A:充分和合理的利用计算资源。
 
Q:环境变量的管理?
    A:个人推荐使用Module 工具(这个工具没听说过,不过我比较倾向于使用python来进行环境变量的配置和使用)。很多公司都是用这个免费的工具
 
Q:验证工程师需要掌握的基本技术?
    A:分享一份我做的基本培训内容安排,供参考:Perl,Makefile,AMBA介绍,SVTB.pdf ,sva,几种用到的编程语言的File operation ,Low-power,C-pointer,Cshell-AWK+SED,体系结构相关的一些内容,SV-1Day training ,VMM_source_code ,Arm的嵌入式编程的基本概念
 
Q:自动化必须吗?
A:不是必须的,但是应该尽量去实现自动化。总之是多让机器跑。如果人均License太少的话,要尽量做到白天debug、晚上让机器跑。“比对”这种事情太机械了,所以尽量让机器做,做这种事情机器的效率比人高太多(wolf评论:You are right!Absolutely right!)。把精力放在构造testcase、testbench、coverage以及debug和分析上。
 
 
Q:Testplan如何做?
A:形式不重要,xls可以、word也可以、txt的也可以。但是来源于Spec!testplan里除了要罗列function-test-piont,还应该有error-injection(wolf评论:给你一个错误的激励看你有啥反应!)和random-test-point以及cover-point和assertion(wolf评论:SVA一定要掌握!)。
需要和各个team仔细逐条review testplan,有些针对具体实现的coverpoint可能只有designer能提出来,需要尽早提出。Tb搭建之前,要充分的review testplan,因为Testplan的较大修改有可能会导致整个testbench的架构调整,effort较大。Testplan是一个需要不停增加,不停迭代、不停review的东西。
Error injection要和RTL-designer逐条review,一个是看看RTL-designer是不是没有想到,一个是设计是不是本身就不允许、或者架构上本身不可能出现。Error-injection应该往深里去好好挖掘。例如:内存控制器长时间不回数据(这里本身是一个随机点)à由于长时间不回数据是否产生错误中断à产生错误中断以后如何响应à响应不过来如何恢复à必须用software reset做恢复的话,对software的时机是否有要求àsoftware前需要遵守什么要求和步骤
虽然现在有一些工具可以根据规范化描述的testplan自动生成cover-point和assertion,不过我觉得自然语言描述的testplan应该是最“自然”的。
 
注释:
 
上面的回答算是一个很非常中规中矩的回答。但是一个完整的Testplan里面我们需要考虑更多的东西,来保证我们的验证能够快速的实施,功能和覆盖要求能够快速的收敛,最后拿到verification report,这里面有个概念,叫可执行的验证计划,要覆盖到整个验证过程。简单来说,订制验证计划,需要做以下几个方面的工作:
1. 创建一个模板(如果没有的话),形式不重要,xls可以、word也可以、txt的也可以。这个工作的重要性在于保持文档的一致,另外方便验证人员订立计划,验证人员只要按照后续的要求填入对应的计划就可以了。
2. 验证计划制定:
    a 首先要评估验证需求,了解要验证的模块,验证的项目时间,最终要达到的基本目标等等。
    b 进行重用评估,这里面其实包含对DUT重用模块的分析(哪些模块是已经验证好的,这些以后都可以在覆盖率里面进行exclude的),和验证部分的分析,有哪些interface的uvc已经做好可以在build环境的时候进行复用等等
    c 验证假设,DUT的某些模块已经验证完全了,我们假设这些模块没有问题等等
    d 验证范围评估,选择合适的验证策略直接测试或者随机测试
    e 验证计划里面要包含上面提到的内容:根据spec列出要verification的feature,给这些feature编排优先级,根据每一个feature订制对应的覆盖计划,有些feature可以通过code coverage就可以看到,有些需要使用function coverage,而有些需要property coverage。验证计划里面也要包含整个TB的架构,怎么实现,需要哪些UVC,以及build的一个流程,这里面需要考虑,首先要给设计人员一个可以初始reference的TB,然后再完善整个TB进而测试完整的环境,思考整个TB的check机制,data check和assertion check。还应该有error-injection ,Error injection要和RTL-designer逐条review,一个是看看RTL-designer是不是没有想到,一个是设计是不是本身就不允许、或者架构上本身不可能出现。当然我认为,一个验证计划怎么详细都不过分,这会使你后面的工作有了参考,事半功倍! 
 
 
 
Q:哪些地方做随机?
A:1)随机配置(一般都想得到的),但是对于一个封闭的系统常常是最不重要的,因为firmware可以自己开发,从而控制配置的流程和数值
      2)随机激励数据(很重要)
      3)随机时序(通常容易被忘记)
      但是有一点要明确:随机不是全随机,是约束随机,是在合理的范围内尽量充分的随机。
 
 
Q:写约束随机哪些地方要注意?
A:推荐看snug paper。(over-constraint导致测试不完全,欠约束导致不必要的debug和资源的浪费)约束的效率:写的不好会导致随机失败
      (总结一些约束的技巧进行补充)
Q:Coverage如何做?
A:code-coverage和function-coverage(covergroup, assertion coverage)。对于constraint-random的地方用covergroup做,对于一些时序的coverage可以用assertion-coverage。
 
Q:核心脚本?
A:单个仿真的脚本---- 建立所使用的不同的目录、不同的seed(目录可以叫case_$seed这样的格式;当然对于直接的testcase,可以是case_$casename);环境变量和license的管理;如果需要做离线比对也可以让脚本来自动调用比对脚本或命令(也可以在tb的代码里使用$system或者$systemf)。
批量仿真的脚本----自动批量提交到lsf上。自动收集log信息以判断哪些case失败,对于失败的case能自动重新提交,并且自动dump波形。以及产生批量仿真结束以后的汇总信息。
 
 
Q:SV中重要的点?
A:特殊的数据类型,比如新增的三种array(动态、associate、queue)、string(match函数、backref函数,参考vcs的svtb.pdf);面向对象编程思想(handle);coverage;constraint-random。
       熟练掌握这些语言点的用法很有必要。
 
Q:是否要使用VIP?
A:VIP的使用--- 复杂仿真模型推荐用VIP,简单的建议自己做。如果自己开发仿真模型的话,也推荐看看VIP的文档,经常可以看到一些有价值的error-injection和random-test-points来完善你自己的testplan。
 
Q:要不要做门级仿真?(这个需要在进行理解一下,后仿真的时候需要)
A:如果是走design-service,不知道最终带sdf的netlist仿真是否需要做,如果做的话,最好在release 综合后netlist的时候也做一下(插完scan-chain和做完CTS以后有条件也做一下),如果需要VCD文件做power分析和指导PR工具的话,那么门仿是必须做的。如果design-service公司不负责调量产pattern的话,那么ATPG等的门仿是需要自己做的。
 
门仿并不是sign-off标准,但是推荐还是做一下,经常还是能跑出问题来的。如果做sdf反标的门仿的话,对于async的多级dff要剔除掉(VCS和NC都有option,vcs可以查手册里“+optconfigfile”,NC查”+nctfile”)。反标Sdf仿真的时候推荐notimingcheckà no_notifyà checking_timing with optconfigfile的三步走。
 
前期在评估IP的时候,有可能个别模块可能需要单独搭门级环境,比如CPU-IP有RTL,要自己做flow,那么通常是需要做门仿的(有可能主要是为了跑vcd或saif做power分析)。
 
Tb的修改:由于CTS和综合的原因,导致时钟名字和信号名字有变化,所以tb有可能要修改。另外,tb里的probe文件建议使用反沿采样,也是为了避免带sdf反标以后clk踩不到整个data-vector。除此之外,个人不太建议在门仿的时候依然使用自动化的tb。因为你的tb里抓的很多内部信号可能名字变了(或者被优化掉了),这样导致tb在门级跑的时候维护起来有些麻烦。有些信号即便名字不变,可能会反向,这样会导致你的checker误报错。毕竟在门仿的时候不用跑太多的testcase,可以靠几条和rtl仿真一一对应的仿真来覆盖。门仿毕竟不是为了function,而是为了检查timing。
       如果你的设计里用了不带reset的dff的描述,由于开始不定态的传播,可能导致你门仿失败。个人推荐的方法是:如果特别多的话,用脚本找到对应模块里所有dff,产生一个force-release文件(注意:很影响编译时间,所以能不用就不用)
 
注释:门级仿真我现在做的不多,这些意见很中肯值得借鉴!
 
Q:FPGA和仿真如何安排顺序?
A:首先是schedule优先,其次是力所能及。但是原则上是先仿真然后再上FPGA,仿真可以很快的扫清一些基本的bug。给仿真的时间充裕的话,那就仿真尽量往前赶,尽量在上FPGA之前多测一些(不是太多case的情况下,FPGA的测试速度毕竟要快一些)。即便FPGA很着急上,起码也让仿真先用几条直接testcase调试通过最基本的功能。第一版FPGA可能因为接死、悬空和信号反向导致逻辑被优化掉,这些问题有时候用仿真也不能全发现,就要结合leda等lint工具。
 
注释:上面说的很对,原则上一定是先仿真,然后再上FPGA,这个地方我需要再补充一下,仿真并不仅仅可以是RTL仿真通过,其实也可以做FPGA综合出来的网表仿真,跟ASIC综合后仿真相通,需要读入FPGA厂商提供的库文件,SoC的仿真要麻烦一些,涉及到memory的初始化。
 
Q:仿真如何复现FPGA发现的bug?
A:首先保证配置的一致性,可以考虑做一些内部的工具。仿真上要probe寄存器操作端口,FPGA上要能把firmware里的配置流程转成文本。
       如果配置一样还是不能发现的话,再去逻辑分析仪上debug时序。当然,CDC的问题在仿真上是看不到的。
       个人不建议做FPGA网表的门仿,有点得不偿失。
 
Q:FPGA不能cover的部分的验证?
A:PAD_Mux(Test_mux)、Clkrst、Power-management-unit 以及FPGA跑不到的高频所对应的功能。Clkrst这部分主要就是pll config、clock-gate、divider、soft-and-hard reset,从测试点的角度还是很明确的,RTL代码修改的少的话,可以考虑不用做太复杂的验证(但是clkrst模块里可能会有一些控制逻辑或者状态机,比如:sdram的切频,这里一般是需要一个状态机控制的,这个需要仔细和小心的验证。)
 
PAD_mux个人比较推荐使用自动化的流程,因为代码风格非常固定,所以可以用脚本生成RTL和用脚本生成testcase(一般这样的testcase是一堆的force)
 
PMU建议看看VCS的MVsim的文档,里面介绍的很清晰了。(还是要配合静态验证工具MVRC一起来做)没有MVSim的话,可以考虑用VCS的$power $isolate。
 
Q:固化的firmware如何验证?
A:个人不建议让仿真去覆盖firmware,但是对于FPGA和ASIC不一样的地方要重点覆盖到。大的流程要覆盖到,其他细节由FPGA保证。
 
Q:架构评估?
A:我经验也不多,举几个例子。比如你的总线拓扑合理不合理?内存控制器的效率(机制)是否满足你的应用?使用哪类Cache?Cache的大小?模块的FIFO深度够不够(error-injection可以测到)?算法需要多少mips(rvds等工具带的模拟器可以给出结论,但是要让模拟器能考虑到内存access的latency)?软件里如果有不少memcpy的话,要模拟系统运行起来以后memcpy的效率。
       如果没有人手专门用ESL(如Carbon的CMS)(wolf评论:what?再次老土!)工具的话,建议在验证平台上做(当然一旦有大问题,要推翻架构会很麻烦)。
 
Q:哪些资源要节省?
A:当然首先是人(数)要节省,人的成本比起计算资源成本和存储资源成本要大多了。提高技术、提高自动化程度才能节省人的成本。(低Package这种方法属于伤天害理的手段,不是正当途径)
减少硬盘需求(如果有必要)共享simv/simv.daidir csrc(包括regression过程中自动清理磁盘空间);激励数据是否可以不一下子全产生出来(对于通讯类的比较有意义,由于是floating的激励数据,所以经常很短时间就需要GB的空间)。注意对每个人每个项目设置硬盘quota,避免被个别人撑爆存储。
减少编译次数(soc项目里比较有必要,testcase基于firmware),parallel-compile or separate-compile ,vmm-test,在一个testcase里做多个功能点的覆盖,fsdb/vpd的dump层次的改变不要重新编译(fsdb有command,vpd可能得用ucli)。
 
 
Q:设计规模大了编译很慢怎么办?
A:有时候设计规模太大导致编译很慢,但是SoC项目很多情况下,功能模块彼此之间是用总线隔开的(即便在功能模块之间有硬件连线也可以考虑用仿真模型来做替代)。在仿真某一个功能模块的时候,可以考虑dummy掉不相关的模块。
但是这就引入了一个新问题“文件列表的维护”。基于这种dummy的思想,文件列表的维护就成了tb里的一个很关键的地方,要尽量避免维护太多的文件列表。我个人比较推荐利用脚本来自动产生所需要文件列表。除此之外,仿真用的文件列表里我个人比较推荐用绝对路径(避免别人debug的时候出现调错文件的问题,另外可以指定不同的工作目录)。CVS里用相对路径,相对路径转绝对路径的工作由脚本自动完成。
 
 
Q:编译还是运行option?
A:为了减少编译的次数,能使用运行的option就使用运行的option。比如使用$value$plusargs $test$plusargs
Q:Assertion谁来写?
A:建议RTL designer和IC验证工程师都写。内部实现细节的描述由RTL-designer自己写,模块之间的时序由IC验证工程师来写。(wolf评论:对头!一定找掌握该技能!)
Assertion的抽象层次有些高,写复杂了有时候极容易出现和你想象不一致的地方。而且如果spec上描述的不清楚,误报assertion-fail也会引入不必要的debug时间。
 
Q:自动化的tb搭好了,波形对验证工程师来说还那么重要吗?
A:非常非常的重要。毋庸置疑!!波形是最直接的,checker可能写错,有问题没有报出来。但是没有激励就没有所要的波形信息。(wolf评论:Right!Bench可能出错!环境可能出错!C model可能出错,总之,是要是人做的事都可能出错!所以,Design Engineer要错的第一件事是入口检测,一定要把好入口关,验证周边无误后再把自己的东西给切上去!)
 
 
Q:如何重用?
A:reuse可以分为横向和纵向。(wolf评论:尽可能充用!降低开发周期,降低风险)
   横向是指项目之间。这个reuse主要包括:文档和tb、script。
   纵向是指同一个项目内,一般是模块级和系统级(包括子系统级)。一般是tb和script。
   比如在一个项目中,所有的tb都是用run_sim和regress脚本的,只是带的filelist不同。对于tb来说,driver和generator可能不能reuse,但是一般monitor和scoreboard这类被动接收的一般都可以reuse。而且testcase通常是可以reuse的。
       对于SoC类项目,为了保持testcase的一致性,我个人比较倾向于都使用firmware做testcase,这就要求
 
1)模块的验证也要基于一个(类)soc的tb下验证。
2)cpu-ip要尽量简单,否则cpu会占用太多的仿真资源。个人推荐用iss(wolf评论:what?)做cpu-ip,负责配置寄存器。
 
Q:regression什么时候做?做多少次?
A:tb好了以后,任何时候都可以做。下班后尽量提交regression到lsf里,让机器充分的跑。如果你的环境是random的,那么随机空间实际是很大的(随着random-test-point的增长指数级增长),所以只要seed不同,其实是可以跑到各种各样的情况。
 
Q:DPI要不要用?
A:有的人很喜欢用DPI,不过我个人不喜欢用。我尽量是把C封装好(自己写wrapper),产生可执行文件,然后在tb里用$systemf(wolf评论:what?verilog里的系统函数?sv里的系统函数?sc?还是贵公司封装出来的?)来调。不喜欢用DPI的原因主要是因为如果代码里有不太安全的地方(比如C代码里你不是在堆上而是在栈上开了一个大数组,或者C和SV之间的参数传递写法不合理),很容易造成coredump。而且你也不确定到底是SV写的不安全还是C写的不安全。另外,有些大公司的算法源代码是不提供的,只给你一个.o文件,这样coredump了你debug起来会让你有砍人的冲动。
但是不用DPI也带来一些坏处:
1)
要自己写一些wrapper之类的代码
2)
静态变量处理要小心。举个例子:我是每帧调一次systemf来做比对,某个函数每次比对会被调用一次。函数里的静态变量就没什么静态的意义了。如果不做修改的话,肯定会出错。一般是要求算法组尽量少用静态变量,非用不可的话,我们会把静态变量改成全局变量,然后让systemf多一个参数。
要说明的是:DPI“天然”的就是tb的一部分。但是我觉得把时间浪费在debug 算法C代码的优劣上是一件很不值得的事情(无论什么时候都是schedule优先),当然我也很佩服有些人对任何事情都“精益求精”的态度。
       无论用不用DPI,你都可以使用DDD(wolf评论:what?)这类debug工具。DDD这种工具在非DPI情况下用起来会更加的得心应手。
 
Q:Force要不要用?
A:有的人比较抵触用Force-release,觉得如果写的不注意的话,可能会浪费时间(debug或者re-compile)。个人觉得“规定所有人把各自模块的force语句写在一个文件里,然后再被一个统一的force_prj.sv include进去,并且include前要有`ifdef保护起来”应该可以规避掉一些风险。
 
Q:IP要不要验证?
A:首先是去找业界口碑好的IP(个人觉得对数字IP来说silicon-validition一样重要)。人手不够的时候,可以考虑让FPGA多承担一些IP的验证,对于IP里一些FPGA无法cover到的测试功能点,可以考虑用直接testcase的方法覆盖。
 
Q:遗漏bug怎么办
A:开发过程(FPGA)乃至最终silicon-validition甚至已经产品化后都可能发现遗漏的bug,要重视这些被仿真遗漏掉的bug。要一个一个的做case-analysis,仔细的分析为什么testbench没有抓到这样的问题。而且对于TO(wolf评论:I see!Tap-Out!)以后发现的Bug,要在下一版里重点review,以保证不犯同样的错误。另外,对于每个bug都应该尽量加一条对应的assertion。
 
Q:分享的氛围。
A:我个人觉得验证的范围很广,一个人很难把各个方面都搞的很精通。经常的技术讨论和培训是非常有必要的。Team-leader应该营造一个很好的技术分享的氛围。
 
Q : 如何定位bug
 
X和Z,所对应的Bug,可能有如下几种:
1、 IP(包括Memory、PLL、Serdes等等)例化时,某些信号悬空未接。也许某些模型允许Power信号悬空,或者某些信号是悬空给DFT处理(当下给DFT处理的信号是接零),但大多数IP,输入信号是不可悬空的;
2、 信号位宽不匹配、信号多驱动、声明的信号名称写错、TB级互联错误或TB中遗漏的Force(额外小心隐藏的Force),不要相信nLint,特别是在芯片顶层或
3、 后仿真时序不满足时的X态传递;
4、 功能错误,某些模拟IP未能正确操作;
5、 功能错误,导致管脚冲突;
6、 功能错误,未能合理使用无复位端的寄存器和未初始化的Memory。
 
再看时钟。
很多验证人员不看时钟。经过我反复的证明,这是一个非常正确的结论(经常在项目验证后期协助定位时钟不对齐导致的环境问题)。只要TC能够打印Pass,很多验证人员不关心时钟是否有问题(甚至很多新验证人员,根本不明白∆ Delay的概念)。大多数情况下,时钟不会有问题?No,大多数情况下,系统验证,时钟都有问题。
 
怎样看波形:
如何在一个看似无限复杂的挂死波形中定位根因?
如何在后仿波形中发现可能的问题?
如何在表面上没有问题的波形中发现问题?
面对波形,首先要端正心态,不要认为看波形是浪费时间,也不要因为一时无法发现其中的问题而焦虑烦躁,更不要盲目乐观,认为已经没有任何问题。要执着、坚定,充满勇气。
先不要看波形,对,先不要看,这是我很重要的经验之一。要先思考,我的做法是对照架构图,虚拟一个芯片运转的场景,即在脑海中想像一下当前这个激励下,波形应当是怎样运作的,激励怎样进入系统,然后怎样完成协议解析和转换,怎样到达了总线,然后出现DDR的吞吐,然后CPU取指、取数,完成处理。OK,也就是说,先要在心中预留一个完美的Scenario,设想一下白雪公主和王子是怎样在城堡中幸福生活在一起的。
心中有了虚构的波形后,再使用Verdi打开波形。抓关键信号,分组,标识不同颜色,这些奇技淫巧应该不用多说,很多兄弟都比我这个验证原旨主义者来得厉害。只是需要说明的是,抓多少信号,怎样分组,很需要斟酌。其实原则只有一个,让尽可能精炼的信号在一屏内显示,这和代码的精简是一个道理。信号除了按功能分类,还要按信息量分权重。所以还是要说,很多验证人员,用着花哨的手指技法,一屏一屏的信号抓,刷刷几屏下来,跟瀑布一样,很是壮观,往往Group的数量比我总共抓的波形数量还要多。操,看个AXI总线,把arlock信号和arvalid信号一起抓出来,除了催眠看波形的人之外,有其他意思吗?以AMBA总线为例,APB先看PADDR、PSEL、PENABLE,AHB先看HADDR、HTRANS、HREADY,AXI先看各个通道ADDR、VALID、READY,如果这些信号不能说明问题,再逐步增加辅助信号观察,尽量保证在一屏中显示所有有效信号,如果信号太多,宁可删除部分。
然后,将展开的波形和脑海中已有的场景进行对照,看数据流是否按照脑海中预期的构想而流动。一般来说,实际波形和预想都不太能够对上,最开始的大多数情况下,波形是正确的,而脑海中的预想存在不足,这主要是因为我自己对架构的细节理解还不充分,对某些特殊逻辑处理方式不熟悉,或者某些逻辑相互连接后新增的耦合关系不了解等等原因导致。而这个时候,在我看来,也正是一个最好的时机,来进一步熟悉和理解芯片真实运转流程,弥补自己对系统结构、互联设计中各个细节的理解不足。在对细节的进一步理解和澄清的过程中,我会逐步修正心中虚构的波形,使其逐渐接近真实的运作。当然,在修正过程中,会出现某些确实表现异常的波形,一些明显出乎设计预期的时序出现。OK,这是一个岔路口,先记录*.rc波形现场,然后对该出乎意料的时序进行进一步深入追溯。正如前面所述,我常常在已经Pass的波形(或后仿波形)中发现Bug,通常都是从这样的岔路口开始的。也许这个岔路口最终证明逻辑没有问题,还是细节理解不足导致,但也许就是一个芯片难以发现的致命缺陷。
看到这里,也许有同志会问,挂死的波形呢?怎么还没追挂死的点呢?Yes,就是还没开始,无论是挂死的波形,Fail的波形,还是Pass的波形,在其实际波形和我大脑中虚构的波形没有完全吻合之前,我是不会开始定位问题的。这简直是浪费时间?嗯,在最开始定位的阶段确实如此,但在验证进入中后期之后,正常的波形和我虚构的波形已经调频到一个波段了,或者说,我已经确认白雪公主和王子开始幸福生活了。和波形到手,从前到后一扫,寻找那些地方异常,例如,白雪公主生下来的小王子永远长不高,那明显就是有问题嘛。然后,半小时发现问题,并不困难。当然,还是要说,我的经验,是不适合那些平时就只看Log,忽视波形的人的。
最后,我还是共享一些我定位复杂挂死波形的根因的经验。起点,定位挂死的起点在那里?或者说,从那里开始追?很多同志认为寻找一个合适的起点很重要,或者说最好直接就找到引发挂死的点。我说,No!!找到直接引发挂死的点,或者和该点直接相关的起点,是很困难的,我不做这种类似分析双色球中奖率的事情,任何挂死的波形,第一时间能够获得的信息,都是表象。我会将任意一个被阻塞的操作作为起点,开始我溯溪的旅途(请确信,无论那个溪流,最终都会汇到唯一的源头)。如有可能,用笔在沿途做下记号,保证在偏离方向的时候能够返回。溯溪的路途有艰辛、险阻,我看过太多的兄弟在中途放弃,或另寻他路,而有时候,他离最终的源头,仅一步之遥,所以,最后一个建议,请保持一颗坚定和勇敢的心。有一首我喜欢的歌,范玮琪的《最初的梦想》,艰难的时候,可以听一下。
最最后,再补充一点后仿定位的思路,供参考。
1、 还是先关注时钟,每一个模块,clk和clken相位是否正确(PR有时会对时钟取反,需要注意);
2、 关注有门控功能的时钟和复位,确认是否存在毛刺;
3、 把Top层所有管脚和oen、I、C信号抓出来。除掉红色黄色,观察有特殊变化的oen、i、c信号,尤其是和管脚值不符的,还有毛刺;
4、 观察所有异步接口的时序,基本上都会发现毛刺。例如EBI、Efuse,确认毛刺是否影响功能;
5、 观察顶层或Subsys独立处理的信号,特别针对还不够成熟的集成人员的特殊设计,例如testmode、rst_out、系统控制器特殊的配置和检测信号;
6、 关注跨团队的模块,例如功能可控的Memory BIST;
7、 以上所有这些,MAX和MIN会有不同,要仿真Typical时序,并且确认以上的内容;
8、 后仿的波形,需要结合Log中的Warning一起Check。
 
一些建议:
项目经理(或验证经理),建议在看测试报告的同时,也要看人。即使都是符合交付流程的测试报告,不同的人交付,其背后的含义都是不一样的。新员工往往注重形式而不清楚其内涵,老员工往往以完成为目的而不注重形式,有的同志会忽视条件覆盖率而只关注TC和代码行的覆盖,有的同志思考问题过于理想,以至于主动避开一些Corner Case,还有的同志重随机而轻直接,或重直接而轻随机。这些都是需要进行识别和分析的。流程解决不了这些问题,即使包括评审,亲身经历。如何进行识别呢?我的一个建议是做对比,将多份报告同时打开,多份验证环境同样打开,相互对比,分析其中的差异。这一点,在流程中,是没有的,而且,基本上,验证人员本身也都很少主动进行这种对比的。
 



来自为知笔记(Wiz)



免责声明:文章转载自《IC验证概念总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端使用lodop插件进行打印设置如何删除 SQL Server 表中的重复行下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Zabbix报错信息及遇到的问题

no#范围:128K-2G#默认值:以字节为单位。#机器历史数据请求的共享内存。#设置为0禁用值缓存。##强制:无#范围:...

Practical Shader Development: Vertex and Fragment Shaders for Game Developers (Kyle Hallady 著)

这是我们描述形状的方法之一,它将使计算机变得有意义。要定义形状,我们需要存储关于三件事的信息:顶点、边和面。顶点是三维空间中的点。边是连接顶点的最内层。面是由三个或多个角度形成的二维形状。你不能把脸想象成只有在记忆中恢复的一个网格的垂直面之间的空间,而每一个共享的需要和脸都是由垂直面顺序简单定义的。因为很多名字都不会出现在网格的“背面”,所以正面的哪一面很重...

HTTP请求报文

不仅报表样式可以传递请求参数,请求url也可以以类似于键值对的方式传递数据...

Cesium深入浅出之视频投影【转】

通常,我们使用矩形,因为视频形状是方形的。据怀疑,视频标签隐藏了这段关系。如果再次显示,视频将再次移动。此处使用VideoSynchronizer。它可以使视频元素与铯的模拟时钟同步。让我们看看它的构造函数:name type description optionsObject option子属性:name type默认值description用于驱动视频的...

【转】设置:ftl模板文件编辑器

在学习了Freemarker如何生成Word文件的知识后,博客作者使用Eclipse进行开发,并使用内置JSP框架编辑ftl文件。在编辑ftl文件之前,如果您的Eclipse没有指定ftl的编辑方法,则会提示您安装ftl模板的编辑器或使用TextEditor进行编辑。我没有选择在这里为ftl模板安装编辑器,所以我跳过了。...

隔板法

分区法用于将n个球变成m个盒子:(1)不允许为空:n个球放在m个盒子中,而n-1个球是通过用m-1个分区分隔n个球来放置的,因此Cn-1,m-1(2)可以为空:m个盒子里放n个球,可以为空。首先想象m个球被放置在m个盒子中,每个盒子一个,然后手中的n个球被分配到m个盒子。此时,箱子不能为空。此时,我们使用n+m个球,如果我们取出m个球的话,我们可以得到n个球...