一个成功的百万门级芯片验证平台
A Successful Verification Platform for Millions of Gates Chip
摘 要:
随着芯片复杂度的增加,快速搭建一个强大、高效、灵活、可扩展性好的验证平台是芯片成功的关键因素之一。本文以一个成功的百万门级芯片项目为背景,介绍了一种基于文件的层次化验证平台,使用OpenVERA,C++和Perl,在方法学上具有一定通用性。本文同时也介绍了整个验证过程中涉及的其它一些重要方面和实践经验。
缩略语清单:


1 引言
芯片规模的不断增大导致验证对象空间的组合爆炸,步入百万门级后,验证能力和设计能力间的鸿沟已越来越明显。虽然Synopsys公司主席兼首席执行官Aart de Geus曾说过只有3%的设计错误用现有的验证技术无法确认,但现实情况是受项目进度和资源投入制约,工程师们往往没有足够的时间和资源去发现并改正所有的设计问题,因此如何在有限的时间内尽量有效地验证成为一个很大的挑战。本文以一个实际的成功芯片项目为背景,介绍一种强大、高效、灵活、可扩展性好的层次化验证平台,该平台使用Synopsys的VCS和OpenVERA,并大量采用纯文本形式的文件,方法学上具有一定通用性。文中同时也涉及验证过程中的一些个人经验。
2 项目简介及分析
2.1 项目简介
该芯片项目(以下称SDXXX)完成WCDMA下行物理信道调制,SDXXX除RAM外的总逻辑约400万门,由于部分模块实例化了多次,真实逻辑近百万门,现已作为华为公司WCDMA基站产品的核心部件之一在海外商用。

SDXXX的大致结构如图1所示,包含3个输入,其中定时接口承载主时钟和WCDMA帧定时,DSP接口承载下行物理信道配置和待调制的下行物理信道数据,上行接口承载上行物理信道传来的下行物理信道控制信息。SDXXX输出所有下行物理信道调制后合路的数据。SDXXX的逻辑主体是下行公共物理信道调制模块和下行专用物理信道调制模块,这两个模块几乎是独立的,只存在极少的联系,另外在下行公共物理信道调制中不同种类的信道也几乎是独立的。
2.2 验证分析:
SDXXX的验证难点在于:
● 静态地看,支持的各类信道总数超过一百个,平均每个信道约10个配置项,平均每个配置项约10种配置值,因此静态配置组合是大量的(全组合为104量级);动态地看,很多性能是通过重配置才能反映的(如信道的删建,功控的开启、关闭,码资源的重配等),重配的组合也是大量的(全组合时相比静态的情况还要多很多)
● 部分下行物理信道受上行物理信道的控制信息序列影响,这种影响由人工较难考虑周全 (比如功控过程受上行控制信息和多个配置项影响,且和历史的控制信息相关,相关深度可能多达几十个值,人工很难计算清楚)
● 不同的信道定时不同,输入激励需较精确地控制发送时刻,且三个输入接口上的激励存在内容和时序上的约束(比如配置某些项后,需要送相应的上行控制信息,且配置时刻点和上行控制信息送入时刻点间存在时间约束)
2.3 验证策略
2.3.1 针对验证难点的策略
上节中提到的验证难点对于许多同类型芯片也是适用的,我们的相应策略如下(其中涉及Harness的内容参见本文3.2节):
针对静态/动态配置大量组合的难点,要求TC必须能方便地表征各种配置组合。我们认为纯文本形式在定义其格式后可以作为TC的载体(使用纯文本的好处还在于绝大多数工具都提供纯文本的处理功能,因此通过纯文本可以方便地将各工具连接起来)。验证环境必须能兼容地识别各种配置组合下的TC,这可以由一个通用的Harness将TC用意转化成芯片接口上的实际激励。
针对人工较难考虑周全的难点,受约束的随机验证成为必不可少的验证环节。同时这也是静态/动态配置大量组合的需求,因为人工不可能去遍历组合,只能选取我们认为重要的,但往往容易忽略某些组合(SDXXX前期验证曾经认为同一类型的多个信道间是相互独立,互不干扰的,但后来随机验证就发现信道编号相隔3的两个某类型信道间存在干扰)。
针对激励间存在内容和时序约束的难点(主要是时序约束困难),我们没有采用传统的通过信号来传递约束信息的方法,也没有单纯依赖OpenVERA提供的同步机制(sync,mailbox等),因为这两种方法的处理都比较繁杂。我们的方法是在Harness内实例化一个timebase类的对象“center_cnt” (需要new函数来实际分配内存空间),它主要实现一个定时计数器,然后我们在Harness的其它部件中也分别实例化一个timebase类的对象,但是不new,而是直接将center_cnt赋值,这是OpenVERA的一个特定语法,作用相当于类指针,这样Harness中的各部件就有了一个统一的定时基准——center_cnt,时序约束的处理在这个统一定时基准上变得简便多了。
2.3.2 相关的其它验证策略
1. 随机TC和直接TC的结合
随机验证的前期投入是巨大的,往往随机环境还未准备好(此时还没有验证任何一条TC),项目就已迫近一些关键时刻点,并且随机验证涉及到的一些技术和理念需要验证工程师具备相当的经验,因此通常直接的TC也是必要的。SDXXX采用先直接TC后随机TC的策略。图2反映了随机验证和直接验证间的效果对比。

SDXXX的随机验证环境是通过random engine实现的,random engine的工作量约1.5人月,为方便random debug开发的monitor和script约0.5人月(参见本文3.4节对random的描述),平均debug一个随机TC的时间是直接TC的2倍多,但一个随机TC覆盖的特性往往相当于数十个直接TC,因此从全程来看随机验证的效率更高。
2. RM的必要性
SDXXX可以简单地看成一个巨大而复杂的扩频加扰计算器,其输出靠人工是难以计算的,因此需要一个RM替我们计算期望,随机验证也要求必须能自动产生期望,因此RM对于SDXXX的验证是必须的。
3. 顶层验证环境和模块验证环境的复用
针对SDXXX的并行独立结构,同时也考虑到项目进度和人力投入,我们的策略是集中人力做一套顶层验证环境,这套顶层验证环境也可用于单独验证下行公共物理信道模块和下行专用物理信道调制模块,只要将不用的模块用空模块替代即可。另外对于一些比较复杂或比较重要的小模块单独做详尽的单元验证,这类模块数目不多,并不占很大工作量。
3 解决方案
3.1 验证平台概述
为支持各种TC的验证,我们需搭建一个“通用”的验证平台,它是非常复杂的,相当于一个不小规模的软件项目(实际仅总的OpenVERA代码就有近万行),需要模块化、层次化。verilog作为一种主要针对硬件的描述语言佷难完成这一任务,Synopsys的OpenVERA作为一种专门的验证语言,提供了诸如“类”这样的强大数据结构和方便的进程间控制等软件功能,同时又支持众多的硬件特性,所以我们选用OpenVERA构造了一个层次化验证平台,平台结构如下:

3.2 层次化的Harness
图3中的Harness按照抽象程度可分三个层次,层1(I/O级),层2(task级),层3(信道级),

层1为紧贴SDXXX管脚的各BIM,它们封装了所有SDXXX的管脚时序。BIM用OpenVERA的类实现,层2通过实例化BIM对象,调用其提供的激励控制函数才能影响芯片的激励。层2包括:DSP_Eng和UL_Eng,用于模拟DSP接口和上行接口行为;timebase主要用于为整个Harness提供统一定时,同时也实现了定时接口的激励;monitor用于深入SDXXX内部设置“探针”;checker用于检查SDXXX输出;层2中的模块也都是用OpenVERA的类实现。层3为一个parser,用于解释TC用意,内部实例化了层2的各部件(也是通过不new而直接赋值的方法),这样parser中就能使用层2各部件的成员变量(主要是邮箱)。
仿真时,Harness parser读入TC文件,顺序解析配置文件中各配置时刻点的配置信息,将解析结果封装成一个个消息(消息也是类形式)发给层2中的各部件,两个Engine的激励约束在消息中已解耦,因此是独立工作的,这样可以简化engine的处理机制。层2中的各部件再通过各自实例化的层1对象发送激励或采集输出。输出和RM在仿真前计算好的期望文件对比,判断正误。
各层部件的类定义较复杂,这里举一个消息类的简单例子(DSP_Eng接收的关于信道配置的消息):

3.3 RM
3.3.1 基于比特流vs基于数据流
基于比特流的RM在感兴趣的接口时序上可以做的和RTL一致,并且可以和RTL同时仿真,实时比对。基于数据流的RM没有时序概念,仅在数据层次上和RTL一致,不能和RTL同时仿真。采用OpenVERA就可以实现基于比特流的RM,但更流行的是SystemC,现在的仿真器也已支持SystemC和Verilog的混合仿真。SDXXX的RM设计时,考虑到工具和人员经验,采用C/C++设计了基于数据流的RM。RM的输入和Harness相同,均为TC的文件。RM的核心模块为各下行物理信道行为级模型,由RM Parser解释TC意图。仿真时先运行RM计算某TC的期望文件,然后再运行Harness,Harness采集SDXXX的输出后和期望文件对比,并记录错误信息。
3.3.2 RM设计要点
RM的设计结构和RTL的结构应很类似,目的是可以输出一些中间采样结果用于RTL的单元验证和便于debug。RM在哪些采样点上需输出中间结果要事先规划好,相邻两采样点间的RM部分可以采用和RTL不相似的算法和结构,这样工作量会小。采样点密集了,工作量大但对debug的支持性好;采样点稀疏了则反之。
值得注意的是采用RM后,TC的通过与否就完全依赖于和期望文件的比对。通常RM和RTL错成一样的几率是很小的,但是如果RM设计者受RTL设计者影响,几率就会大大增加,因此RM设计者必须保持自己对芯片规格的独立理解。SDXXX就曾有一个bug遗留到样片测试阶段,其原因就是RM设计者没有透彻理解某处规格,直接采用了RTL的设计思路。
3.4 随机验证
3.4.1 概述
直接TC的有效性很大程度上取决于验证工程师对设计规范的理解,构造直接TC只是在验证对象空间中选取了感兴趣的点,工程师总是为可能忽略了某些关键点而不安。随机TC在一定程度上缓解了这种不安,甚至如果自信随机是覆盖广泛且均匀的,就有理由认为验证充分了。SDXXX在充分检视随机规则并连续运行数周没有bug报告后,我们就建立了对芯片成功的信心。
基于上述SDXXX验证平台,随机验证只需采用一个random engine随机生成TC文件即可(一些发送时序上的随机已经在Harness中实现),SDXXX的random engine采用C++。当然OpenVERA中也有类似的随机引擎 ,但我们的目的只是随机地产生文件,C++已足够。
3.4.2 随机配置(参数随机)
random engine的输入是一个配置文件,在其中描述了当前使用的随机规则。一个典型单信道(以SCH为例)的配置文件如下:
SCH# en tstd pow_p pow_s sscs pccpch_ind
0 1 0 100 100 32 1
以#起始的为注释行。不同类型的信道需要的参数数目和顺序不同, 其定义第一个参数是配置的帧号(即配置生效时刻,本例为仿真的第0帧生效),后面的参数顺序同Harness要求的配置文件(具体参数含义略)。
参数支持r(随机值)和d(缺省值),随机值的大小是根据该参数可能的取值范围决定的。随机和for变量是相互独立的。利用这个特点,可以结合随机和for变量写出一些比较随机的配置,例如:
sch i=0,50,1
i r 0 r r r 0
表示在50帧内,sch 的en pow_p pow_s sscs取随机值,而tstd pccpch_ind固定为0。
3.4.3 随机约束(过程随机)
SDXXX的配置间存在一定约束,通过在随机配置文件中加入规则可以定义部分约束,另有部分约束是通过random engine的内部机制实现。某些约束是比较隐晦的,常常是随机TC出错后发现是约束问题,于是便重新添加约束。并且某些约束的添加是十分困难的,需仔细分析(比如多信道情况下总的信道输入数据量有个极限值,但影响这个极限值的因素就比较复杂)。
利用random engine也可以产生一些“庞大”的直接TC(如所有信道均打开的TC)。芯片的验证对象空间是巨大的,完全随机通常效率不高,通过定义不同随机规则,可以将随机TC约束在我们感兴趣的区域,比如一类是信道全打开但仿真时间不长;一类是信道相对较少但仿真时间很长;还有一类是信道删建频繁;等等。
3.4.4 功能覆盖率预分析
通常100%的语句覆盖率是必须保证的,至于分支覆盖率和表述覆盖率则很难达到高数值,因此并无很大实用意义。验证人员最关心应是功能覆盖率,而且是芯片应用层次的功能。SDXXX的功能主要体现在信道的配置组合上,而这些又完全表征在配置文件里,因此通过分析配置文件就可以分析功能覆盖率(这种分析是预处理的,既在仿真前就能进行分析)。我们使用perl开发了一个功能覆盖率工具,该工具同时也可检查random engine是否真的产生了所期望的随机TC。
功能覆盖率工具的输入是一个功能覆盖率关注点规则文件,规则如下:
1、单一元素规则格式:信道名称 功能 步长(区间/单一值)
例如:
DPCH channel_no=13 1
表明分析所有tc,如果存在专用信道信道号等于13(信道使能有效)的配置,则该条功被覆盖。
2、配置转换规则格式:信道名称 功能(起始值/终了值) 步长
例如:
SCH tstd(0,1) 1
表明分析所有的TC,如果SCH的tstd配置曾经从0变到1,则该条功能被覆盖。
3、多元素规则格式:由单一元素通过&&连接组成
例如:
DPCH ch_no=1 1 && DPCH slot_format=15 1
表明分析所有的TC,如果第1号DPCH的slot_format曾经配置成15,则该条功能被覆盖。
功能覆盖率分析工具根据设定的关注点规则集合,分析指定TC集合的配置文件,输出各关注点的覆盖情况。完善的规则集合的定义是个难点,可以通过各方专家的review使之尽量完善。有了这个集合后除了可以分析功能覆盖率,还能分析每条TC对功能的覆盖,从而可以归并TC,按功能点覆盖范围排序TC和根据功能点选择回归集。考虑到项目进度和投入产出比,SDXXX实际并没有做的这么深入,但这是个值得借鉴和研究的内容。
3.4.5 随机调试
随机TC通常是难以debug的,工程师们无法通过TC意图来推测最可能出错的部位。SDXXX的输出是众多信道的合路,任何一个信道的错误都会导致合路出错。为此我们开发了一些monitor,通过OpenVERA提供的hdl_node功能深入到RTL代码内部采集单个信道的输出,同时RM也支持输出单个信道的期望数据,然后通过script比对,可以快速定位错误所在。进一步地,我们还可采集单个信道调制过程中不同阶段的输出,更加方便了debug。
3.5 异常验证
3.5.1 异常验证分析
异常验证是颇让人头痛的,其情形千差万别,激励行为很难归类。更为糟糕的是在项目初期通常没有时间和能力过多地考虑异常,等到项目中后期验证平台已经成熟时,会发现很难再将异常激励考虑进去。因此验证平台在规划时就要留有一定灵活性。很多情况下,异常验证的处理需要有针对性的逐个实现,利用功能强大的硬件验证语言可以预先保留对异常处理的灵活性,更好的完成所需的异常验证。但在现阶段,一个通用的异常验证方法似乎还未出现。
3.5.2 异常处理方式简析
1. 异常激励实现
一些异常比较容易实现,如某个配置项配了定义外的值,这只需在配置文件相应行上填入异常配置值即可。再如很短的时间内发生了同一信道的两次配置(即配置覆盖),这只需在配置文件中的同一配置时刻参数段中加入相同信道的又一次配置即可,按Harness中定义的engine行为后加的配置将后配入SDXXX(即会覆盖前次配置)。
一些异常需利用SDXXX的文件系统留有的保留段来定义异常行为,如数据帧头校验错,再如定时接口的帧定时出现丢失等。SDXXX验证平台的部件都是采用OpenVERA类,通过在类中定义异常处理函数,可以支持文件中异常行为项解析后的激励需求。
还有些异常要考虑等价的激励办法。比如时钟通断异常,由于Harness中的timebase受时钟控制,时钟通断将导致timebase工作紊乱,而timebase又是整个Harness的定时基础,它的紊乱将导致验证平台也不能正常工作。并且实际的时钟通断将带来时钟线上的毛刺,这种激励也不易描述清楚。经过分析后认为时钟通断带来的真实后果是扰乱了RTL内部的寄存器状态,因此通过在EDA环境中人为扰乱寄存器值也可以达到相同效果。VCS提供了CLI功能,利用CLI可以方便地控制仿真在特定时刻强制更改内部寄存器,更改值可设成随机,这样就等效地模拟了真实的时钟通断异常。
2. 异常观测
一些异常只关心能否发出告警,这只需观测告警寄存器即可,如上节提到的配置值异常。
一些异常除观察告警外还要看输出数据是否正确,如上节中的配置覆盖异常,除观测告警外还要观测输出是否采用了覆盖后的配置。
还有某些异常,并不太关心异常期间的输出,而主要关心能否从异常情况下恢复,此时可以在原有checker的基础上,添加mask模式,使得checker不比对或有选择的比对某些时段的输出,利用配置文件仿真参数域中的保留字段可以扩展checker的mask模式定义。
3. 异常对RM的影响
异常验证对RM也是考验。一些异常RM无法实现,如需观测告警的异常,SDXXX的RM设计时并不考虑告警行为,此时需人工将期望的告警写成期望文件。
一些需观测输出数据的异常,RM需尽量支持生成异常情况下的期望文件,如果实现困难,也可以为RM单独准备一套配置文件/数据文件,使得期望能和芯片输出比对上。如配置覆盖异常,为RM准备的配置文件中将只含后次的配置(即实际生效的配置)。当然这样做必须非常小心,避免为使数据比对上而忽略了芯片应该的异常处理。
3.6 一些验证技巧
3.6.1 激励生成
SDXXX的所有输入激励(配置、待调制数据、上行物理信道控制信息)都有一定的发送时间要求,为此我们定义了一个发送允许时间窗的概念,即激励在窗内发送是合理的。发送允许时间窗基于timebase提供的定时,由Harness parser解析文件时计算,计算结果封装在消息中发给engine。Engine的处理机制比较复杂,在其中定义了一些队列来接收消息,根据消息中的时间窗信息在特定时间调用BFM送入激励,具体选择时间窗内的那一点发送有不同策略,以此可以达到激励发送时序上的一些随机(当然最方便且保险的方法是采用时间窗的前点)。队列类是自己开发的,但OpenVERA 4.4.3版本以后就提供队列类库,用户可以方便地实现队列的基本操作。
3.6.2 OpenVERA代码结构
Harness的OpenVERA代码结构参考Qualis公司ATM SWICH的demo,OpenVERA主函数中先new Harness,此new操作将分别地逐层new Harness中各个部件,层2中部件new后将启动一个demon进程,不断监视Harness parser发来的消息。
Harness new后将调用一个外部函数testbench(),绝大多数TC采用一个通用testbench(),在此通用testbench()中调用Harness parser解析TC文件。少量TC不便采用此通用Harness parser(如测试模式下的统计功能),则可以另行编写testbench()。另行编写时只需在vera_load时的vera文件列表中用另写的testbench()路径替代通用的testbench()路径,但函数名不变,这样的好处是替换后OpenVERA主函数并没改变任何代码,因此vshell也没变,仿真器无需重新编译vshell。
另外,通过OpenVERA中定义的interfase可以直接操纵管脚激励,这提供了最强大的平台灵活性和可扩展性。如果将配置文件看成编写TC的“高级语言”(验证平台相当于编译器和链接器),那么这种方式可看作“汇编语言”,即支持“高级语言”又方便地支持“汇编语言”使得SDXXX的平台即高效灵活又强大可扩展。
3.6.3 文件规范
SDXXX使用一组配置文件和数据文件的组合来表征某特定TC的用意,通常一个TC对应一个配置文件,同时根据TC中涉及的下行物理信道的不同使用不同的数据文件。数据文件包括:各下行物理信道待调制数据的文件(SDXXX对此并不敏感,可用随机的0/1序列);上行物理信道传来的控制序列数据的文件。配置文件的格式定义很重要,需考虑支持所有的特性表征,并需具有相当的灵活性和可扩展性。对于相互约束的特性要考虑尽量减小其耦合,以便于随机约束。由于直接TC所需的配置文件是需要人工输入的,因此还要考虑用户界面的友好。SDXXX的配置文件格式定义如下:

配置文件是不定长的,根据配置次数、每次配置涉及的下行物理信道个数不同可以任意扩展,每个信道都有自己的一个参数表,参数表长均为10的整数倍,不足的部分用保留字段补足,这一方面使得人工写起来好对齐参数,另一方面为未来留了一些扩展位。
4 验证过程涉及的其它方面
4.1 Script
Script可以大大增强工作效率。SDXXX验证平台中的script采用unix shell/perl,主要包括:
TC单机运行:控制verilog、vera的增量编译、运行、波形和log存储等
TC网络运行:利用网络管理工具grid engine,自动为批量TC分配空闲机器运行
TC回归:根据回归TC列表提交回归任务,并实时报告回归结果
4.2 FPGA原形验证
FPGA原形验证可以在样片出来前就提供一个硬件平台,利用FPGA原形平台仿真的快速性,SDXXX验证过程中主要用它做TC回归、遍历性仿真和长时间TC仿真。FPGA原形验证的输入和Harness的输入文件一致,由FPGA平台中的软件解析成其所需激励。这样TC可以方便地在EDA验证和FPGA验证间共享,保持了验证用例的一致性,并极大地方便了两套平台间的问题定位。
4.3 验证管理和质量保证
复杂芯片的验证平台已相当于一个不小的软件项目,我们借鉴了一些软件CMM的思想来管理验证过程,举例如下:
验证平台的代码用CVS管理,由验证负责人控制版本发布,在log文件里记录版本信息。
每个待验证功能特性都有一个编号,形如FXXXX,其中XXXX是数字0~9,前两位代表类别,比如SCH、DPCH等,后两位代表该类别下的特性(SDXXX每种类别的特性不超过100个,两位编号足矣)。TC的命名形如tcXX_X,其中红色的XX与特性编号中的XX对应,一个TC相关的所有文件均存在TC的同名目录下,文件的命名也类似TC。这样通过名称就可以方便的知道功能特性、TC、文件的对应关系,也方便了scripts的编写。华为自行开发了一个需求跟踪工具rManager,录入功能特性、TC及其连接关系后,可以方便的跟踪各功能特性的验证状态。
华为的notes平台专门为SDXXX项目设立问题单跟踪库,验证人员发现问题后,提交问题单,由验证负责人审核并转开发人员定位,开发人员修改完毕后转验证人员回归,回归通过则关闭该问题单。
5 结论
验证的挑战在于不存在标准的验证方法,一个芯片的验证成功取决整个验证过程的方方面面。就某些和SDXXX结构、特性相似的芯片而言,本文所描述的方法具有一定通用性。
使用OpenVERA编写的层次化验证平台强大、灵活、扩展性好,便于直接TC和随机TC的实施,也很好地支持了异常验证需求。文件形式使得TC的生成变得高效,SDXXX的直接TC有近千个,但TC文件整个验证group(3~4人)1周左右就完成了。另外由于文件格式并不复杂,非验证环境设计人员花少许时间熟悉格式后也可以方便的补充TC。文件形式还方便地支持了随机TC生成和功能覆盖率分析。
利用这个基于文件的层次化验证平台,我们在项目进度较紧,验证人员经验有限、人力投入不是很充足的情况下成功地完成了SDXXX的验证,并且在笔者的后续验证项目中继续借鉴了这一方法。
6 致谢
本文所阐述的方法并非一人所得,而是来源于华为公司许多同事的指点和实践,在此特别感谢童朝伍、林坚、彭云、周辉。
参考资料清单:
1、Writing Testbenches:Functional of HDL Models,Janick Bergeron,Kluwer Academic Publishers, 2000
2、VERA User’s Guide,Synopsys
3、VCS User’s Guide,Synopsys
4、在设计过程早期发现并解决问题,Gabe Moretti,EDN China,2004-03



