在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 14979|回复: 20

[原创] SoC功能仿真验证技术分享

[复制链接]
发表于 2017-12-26 16:18:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 lshj98115 于 2017-12-27 09:18 编辑

这篇文章算是《我对验证的一些理解》http://bbs.eetop.cn/thread-318775-1-1.html

的一个续篇.


功能验证技能树

建议去摩尔直播app里看爱芯人Tu老师的验证公开课“SOC验证全局观”,那个视频里介绍的非常的详细。


SoC基本仿真环境介绍

我在论坛上写过一个。http://bbs.eetop.cn/thread-442797-1-1.html
如何搭建SoC项目的基本Testbench(我的流程)》,这里挑重要的和有改变的地方说一下。

假设这个SoCcpu系统、内存控制器、总线拓扑、PADClockreset和一些逻辑功能模块。

1 仿真环境中有嵌入式软件(firmware)。这里包括两部分,一是初始化的bootloader(一般是固化在rom或者存放在外部的flash里),一是boot起来以后放在外部易失性存储介质上的应用层面的程序。

2 使用指令集模拟器(ISS)来代替CPU-IP.  有开源的也有不开源免费的arm多款处理器IPISS.  考虑到ISS本身并不真实,如果不是为了验证bootrom代码的话,个人建议找一个开源的就可以了。 ISS可以编译成.so的库文件,这样在仿真的时候就不用编译整套ISSC代码了(需要设置LD_LIBRARY_PATH,告诉仿真器仿真的时候去哪里找;编译过程中需要告诉链接库地址和库名称)

         ISS需要一个配置文件来告诉它CPU的地址访问空间,像程序区、堆栈区是ISS管理的空间(假设叫memory空间),像DUT的内存地址以及DUT的寄存器空间就是DUT管理的空间(假设叫IO空间),ISS要能看到所有的地址空间,并且根据地址来判断是memory空间还是IO空间来做不同的操作。

3 共享空间  CPUISS)和Testbench交互的时候可以指定一块地址空间(比如0x3000_0000 ~ 0x3100_0000),这块空间就是testbench中的一个数组。 比如要实现对寄存器的随机配置,由于ISSC程序不方便做约束随机,可以在Testbench组件中把约束随机产生好的数值写入到这块共享空间中,然后让ISSC读出共享空间的数值再配到寄存器中。

4  Define文件的维护   SoC项目中Testbench的一个define可能同时在汇编程序、嵌入式C程序、CmodelC程序、TestbenchSV代码都要使用。 同时维护多个类似的define文件肯定容易出错,所以只维护一个,其他的由脚本程序自动产生。

5  内存控制器模块(DDRC)的替换    DDRC是系统中最主要BUS-Slaver,通常需要初始化过程(也有的ddrc不需要),还通常需要DDR-PHY的模型,这些都比较影响仿真速度。而且在验证功能模块的时候,使用DDRC也不容易模拟带宽不同变化的场景。因此验证的时候可以考虑用一个BUS-SlaverBFM来代替DDRC.

6 打印的实现
SoC环境的Testcase的嵌入式C语言程序中没有标准的stdio,所以要实现printf. printf是“不定参数个数的函数”,利用“参数从右向左压栈,最开始的参数在最接近栈顶的位置,字符串最后一个字符是\0”来实现printf.  C端只需要把第一个参数的地址(肯定不是0)传到共享空间指定位置,在SVTB中获取到地址以后按照%和参数地址来实现(SV端的实现和C语言里printf的实现很类似),需要注意的是1C端程序要保证参数地址及时写入到共享空间中,不要停在cache或者传输太长;2)使用ISS要打印的信息存在memory空间里,要能让SV端看到memory空间。当使用多核CPU-RTL的时候,注意不同core的打印控制(可以为每个core分配一个共享的空间,在print函数中根据不同的core-id来执行不同的操作)。

malloc等函数的实现也可以利用共享空间来实现。

7 多个模块的协同验证
在系统级下经常要跑系统级case来模拟整个系统一起工作起来的场景(一般该case也适用于power分析)。这种case可能要花比较大的精力在Testcase的构造上,如果有硬件仿真加速器还好,如果只能在纯粹的仿真环境下做的话,尽量做简化处理。

8 单一case流程
编译duttestbenchà编译firmwareà开始仿真(在合适的时机loadfirmware和产生随机控制数据写入到共享空间。如果要把firmware loadddr model中,并且DDRC初始化流程会做data-training这种写数据的操作,那要保证初始化的数据不要被冲掉)


模块级验证相对于系统(子系统)级仿真环境的优势:

1)
仿真速度快

2)
随机可控性好

3)
更容易做Error-Injection

4)
更容易做开关切换和模式切换

仿真工具(2010年以后的版本)都支持模块级和系统级的覆盖率合并,可以加速收敛。

需要注意的是:虽然模块级环境理论上可以覆盖所有的系统级环境里的情况,但是在有限的人力和时间资源的情况下,很可能达不到100%的覆盖。举个例子: 视频外同步的dataenable信号变化情况过多,以至于random不到实际系统中可能出现的情况。 总之:关键是模块级环境有可能没有覆盖到实际中可能出现的情况。


模块级环境基础结构

模块级基础环境中除了有验证组件(monitor driver scoreboard等),还有一条总线连接MasterSlaveCPU-Model控制DUT. 注意:这里所说的模块级环境里的DUT是一个完整的模块,不考虑一个模块内部的子模块.


假定DUT是一个总线的Master设备,会发起访存操作。CPU-Model负责配置寄存器和一些访存,模块级环境为了简化,让CPU-Model不用通过总线而是直接访问Bus-Slaver的空间。


模块级环境Testcase在系统级上的重用


在人员和时间资源有限的情况,要保证模块级代码在系统级上的重用。一般来说Testbench组件(Driver Monitor Model Scoreboard等)重用比较简单,比较麻烦的是testcaseSoC系统级(CPU上的C程序)环境下的重用比较麻烦。 Testcase构建是由TB架构中CPU-Model的实现方法决定的。下面两种我主要用的方案Testcase都是C.


方案一:


使用ISS实现。SoC基本仿真环境比较一致。


方案二:

使用DPI实现。CPU-Model是一个SVmodel,实现寄存器访问和内存地址空间访问的task,比较复杂的是对中断的模拟。可以使用sv fine-grain-process(process::self())来实现main-taskirq-task,模拟“CPU进入中断以后挂起主程序,执行完中断以后返回主程序”(main_task.suspend(); ….; main_task.resume();)的行为。使用DPI来把底层硬件接口的SV-Task传递给C程序。


     DPI实现的方案中要注意底层硬件接口的代码,以及C代码中直接访问的代码(例如指向DUT内存的指针的操作),尤其是IP-Vendor提供的参考代码里很可能有类似代码。比如,usb ethernet的软硬件交互的协议栈放在内存中,软件代码中一般会维护一个数据结构,然后指针指向数据结构地址操作。dpi环境下这样的代码就没法直接用了(指针的操作就不行了,得换成硬件底层代码实现)。这样模块的firmware代码可能是现成的,仿真应该尽量复用。简单的方案就直接放弃模块级环境,上系统级环境里验证,或者用ississ环境下,firmware代码可能也要修改,比如上述的数据结构地址就要注意分配到dut内存地址上去(比如一个大的struct的赋值操作,先malloc出一块空间,然后向这个空间填数。只要mallocdut内存地址上就可以了)。


其他方案:

         Testcase不用C直接使用SV实现;或者把CPU-Model换成真实的CPU-IP,带上boot-romboot-ram



架构评估


个人首推还是硬件加速器,需要注意的是架构评估最好保证频率的比例关系(访存模块的总线访问频率、总线拓扑中各组件频率、内存控制器和内存工作频率),个人感觉可能PalladiumVeloce这种方案的硬件加速器更加适合。


如果采用仿真的方法做评估的话,需要注意:

1pattern的真实性。
现成的模块RTL虽然可以反映真实的访存行为和latency的容忍度,但是构建环境偏复杂,仿真速度偏慢,通常还需要有初始化流程才能工作。个人建议构造BFM模拟访存行为:BFM可以吃配置文件,从而模拟比较真实的场景。

2)基础架构的自动集成。
稍微复杂一点的SoC架构中,总线拓扑的集成可能就很复杂了(统一的组件不太方便用emacs自动集成的功能来做,而且一些特殊信号位宽的匹配手动做起来很容易出错)。多年前就有自动化的工具来实现这个集成。但是商业化的工具虽然提供了很多的功能,但是未必能直接满足个体项目的需求,建议考虑开发自动集成的工具。
目前的low-powerflow里已经不用在架构集成的RTL中写入多少额外的代码了,简化了自动集成的难度。


架构评估环境里还需要有内存控制器和总线架构模块的performance-monitor,来统计吞吐量、内存控制器效率、功能模块访存行为的latency等,根据吞吐量来看架构评估环境是否和期望的访存数据量比较一致,在这个前提下看内存控制器的效率达到了多少,以及系统中哪个模块会出现不合理的比较大的latency(导致该模块可能设计的时候需要加大fifo深度)。通过调整内存控制器和总线拓扑模块的优先级策略、时钟频率或者增减总线拓扑组件以及Master/Slave口的数量来做不同的仿真。

VIP的使用

通常我们对复杂的标准接口协议的数通模块采用vipbfm来验证。

   vip的好处是不用特别开发bfm,有完整的tb组件,有的文档中有比较完善的测试计划和实例,随机性和error-injection完备。坏处是代码不可见,遇到问题容易抓瞎;vip作为工具安装使用可能挑OS和仿真器;EDA vendor本地support人员不足等问题,通常VIP跑的速度比较慢。

能力和资源允许的情况下可以自己开发bfm.一种比较快的方案是reuse靠谱的rtl ip比如我们要验证usbhost,那就找一个usb device或者uotgrtl ipbfm.这种方法的优势:BFM代码质量比较高,debug可见性高,将来在硬件加速器上可以更好的移植(有的可以不用phy,数字接口直接连)劣势:开发代码量也不小,有的phy模型可能是个问题(比如一些单向数据传输的,Master端是并行数据转LVDSSlave端是LVDS转并行数据,这样的PHY model可能需要另外开发),rtl通常需要初始化过程,随机性和error-injection不够友好。

我觉得如果DUT是内部开发的话,因为代码质量可能不够,用商用的vip更合适。如果DUT是买的已经silicon-verificationIP的话,我觉得自己开发的BFM就够了。


Coverage-Driven Assertion-Based

个人认为代码覆盖率是最重要的,是一定要统计和仔细的检查的。

功能覆盖率(包括assertion的覆盖率)应该是Testplan的反映,我觉得只是提供对Testplan覆盖的数据统计,Testplan本身可能是不完备的,所以功能覆盖率的100%并不能代表验证充分了。

Assertion对于一些不太复杂的协议时序验证还是比较适合的,但是感觉最近几年EDA公司都不太在assertion上投入资源了。我觉得对于一个大模块内部的子模块,assertion是非常适合的,可以针对子模块的接口具体的做assertion的描述和验证。


仿真层面的加速


最快的加速技术肯定是硬件仿真加速器。

在“SoC基本仿真环境介绍”中的CPUDDRC的替换都有加速仿真的功能。除此之外还有一些我在用的加速方法:

1)
系统级仿真环境中把不需要的模块dummy掉。 ----- 需要两个脚本程序,一个是自动产生dummy文件,一个是自动把dummy文件替换掉原有的RTL.

2)
缩短SoC上电启动仿真时间。---- 通常是一个状态机根据若干个counter的技术来实现状态跳转。方法是更改counter的初始值或者跳转需要的数值,RTL级比较容易实现,门级仿真找信号比较麻烦,最好提前和flow的同事沟通好,把信号名保持住。

3)
有些DUT里的IP比较耗仿真资源,可以考虑用简化的model代替。比如PLLDCM以及某些PHY-Model.

4)
某些RTL代码的写法可能很耗仿真资源。 比如在clock的每个上升沿当reset有效的时候把一个比较大的二维数组附初始值。 这种代码最好加ifdefelse endif来改写成Initial-block.

5)
减少DPI过于频繁的交互

6)
谨慎使用separate-compilepartition-compile等技术,也许带来负面效果。


门级仿真

功能仿真中一般有如下几类门级仿真:

1)
综合后网表仿真

2)
DFT后网表仿真

3)
PR后反标SDF的网表仿真

4)
FPGA综合后网表仿真

5)
Gtech网表的仿真

综合后和DFT后的网表比较类似,一般跑DFT以后的就可以了。除PR后的网表要反标SDF以外,其他的都是跑0delay的门级仿真。一般额外做几个处理:

1)
std-lib cell库文件中给时序逻辑(dff等)加上clk2qdelay

2)
保证SRAM model的输出端在不工作的时候不要输出X.

3)
门级网表中如果有不带reset端的dff,一般要找出来做$deposit处理(找的方法可以请flow的同事拿对应的网表出一版sdf,然后parser sdf文件就可以得到对应instance里的dff)。

4)
反标SDF的门级仿真如果checktiming的话,要注意把2dff等跨时钟域的逻辑的timingcheck去掉。


FPGA综合后的网表仿真一般不用做,但是当FPGA timing报告、FPGA功能仿真、CDCLint-check都没有问题,怀疑FPGA综合有问题的时候值得做一下。我在做FPGA综合后网表仿真中发现过几个问题: 1Xilinx-V7默认把RTL中复杂的case语句用blockram实现,结果实现的时候时序差了一拍 2FPGARTL里的一些运算直接用内部的dsp来实现,结果DSP的功能综合错误。 FPGA综合网表的信号名太乱,Testbench如果拉了一些内部信号进行观测或者force的话,很难编译通过。

Gtech网表的仿真很少需要做,如果FPGA上跑Gtech网表来代替RTL的话,需要注意FPGA版本Gtech单元的行为描述要保证和asic的一致,否则容易有“坑”.

PR后门级仿真重点是出比较准确的IR-DropPower数据,以及保证时序约束的完整和正确性,建议只跑典型的case就可以了。


仿真验证自动化

举例一些Testbench的自动检查机制以外的自动化技术(很多是用crontab自动执行)。

1)
每天自动checkout出一份代码做mini-regression,并且把结果自动发email通知给项目组。

2)
每隔几个小时一旦检查到有新tag就自动update到新tag上做mini-regression并自动发email

3)
每天自动把所有checkin的代码列出来并自动发email

4)
每天自动把未解决的问题总结并发邮件(bug-zillaissue-trackerJirabug-tracking系统有的自带这个功能,有的可能没有需要自己实现)

5)
自动代码备份(有的代码可能还在开发过程中,所以不想checkin到代码库里去,如果MIS没有针对这类代码做自动备份,可能需要一个自动备份的程序,)

6)
除了自动比对环境以外,还要有一个parse 编译和仿真log的程序在regression的时候调用。


如果某个功能上没有自动检查机制,也要尽量想办法减少人工比对的工作量。例如,有一个图像算法模块的c-code找不到了,但是RTLgolden的,跑实际图形pattern一幅图一幅图看会比较耗时间,可以把regression中产生的图像打包到一个网页中,然后用浏览器去看。

脚本语言是仿真工作中非常重要的一环。 我们一般会用到shell\perl\tcl\python等脚本语言,建议在学习脚本语言期间,强迫自己遇到问题使用正在学的语言来实现。

验证项目管理

http://bbs.eetop.cn/thread-581216-1-1.html  多媒体类SoC项目Verification Project Leader工作内容介绍(讨论)
我在这个帖子里列的比较详细了,VerificationEngineer的工作基本上是Verification Project Leader的子集。

帖子里是按照
项目开始前的准备à项目启动但未提供第一版integration代码à0.5版本à0.75版本à0.9版本à1.0版本àTO前到TO
的项目开发时间来写的。我在这里列一下帖子里几个没有提到的内容。


Leader要注意把握验证流程,上FPGA验证前除了仿真和检查FPGA时序以外,还要做CDCLint等静态验证检查。

Leader及时给项目组内新同事培训工作环境基本技能,避免组内同事出现因为工作环境影响工作效率(比如不同的工具对机器的要求侧重点不同,有的要求cache大,有的要求memory大,可能要综合考虑 cache\memory\cpu-core-num\cpu-frequency等因素。如果MIS没有按照机器性能来进行LSF计算资源划分的话,使用LSF预先配置的分配策略可能会把任务提交到不合适的机器上.


注意避免验证工程师过度依赖模块级环境。比如FPGA上报了问题,模块级上复现不出来就认为没有功能问题了。

         Leader一定要及时总结所有仿真遗漏的bug,开发阶段通常是设计工程师项目后期模块级环境跑仿真暴露以及FPGA上发现的bug.  有的bug可能是由于FPGA在仿真验证过之前就开始导致遗漏的,对于的确是验证工程师遗漏的bug要特别关注。


一般Power数据是来源于门级仿真的VCD或者Saif文件,随着设计越来越大,有可能导致VCD文件过大,这种情况下及时与跑power分析的同事沟通,看有没有合适的手段解决。有的硬件加速器可以内部分析哪段时间翻转剧烈,可以根据这个信息来dump vcd.注意一点:当要dump的信号特别多的时候,其实dump vcddump fsdb这种压缩格式的文件大小是差不多的(大量的存储用来构建信号名的表了),这种情况下直接dump vcd就可以了,还可以避免引入dump波形的PLI和后面的格式转换工作。


理论上说验证是做不完的,有所为有所不为。leader不能把事情大包大揽,有些事情在资源有限的情况下要推出去。


及时总结记录和分析。


重用程度高的项目很容易犯经验错误,千万谨慎。改动的地方加强review.

发表于 2017-12-29 21:58:49 | 显示全部楼层
这么好的帖子没人回复,准备发到EETOP公众号推一下,lshj98115  没问题吧?
发表于 2017-12-30 13:32:52 | 显示全部楼层
回复 1# lshj98115


   thank you for sharing such good post, learning
 楼主| 发表于 2018-1-2 10:19:38 | 显示全部楼层
回复 2# jackzhang


   没问题的,谢谢
发表于 2018-1-2 10:27:29 | 显示全部楼层
支持,写的好
发表于 2018-1-2 14:57:19 | 显示全部楼层
写得好。一看就是多少个项目走下来的
发表于 2018-1-4 14:42:07 | 显示全部楼层
拜读拜读了~~~
受益匪浅~~~
发表于 2018-1-5 18:52:11 | 显示全部楼层
Interesting
发表于 2018-1-10 11:27:28 | 显示全部楼层
受益匪浅!!!
发表于 2018-1-22 17:42:15 | 显示全部楼层
写的非常好,受教了,一直从事ASIC/FPGA相关的功能验证,没有机会接触SoC的验证,但是非常希望了解SOC的验证流程。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-29 19:42 , Processed in 0.030431 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表