如何搭建SoC项目的基本Testbench(eetop)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
先啰嗦几句。其实老早就想写这个帖子,自己犯懒一直木有写。前阵子写了一个初版,然
后发给了几个做验证的朋友看了看,普遍反映没看明白. 说是我写的东西和我搭的
环境结合的太过紧密了,不结合代码,理解的不透彻。可惜代码是公司的,我不能把代码发出来。我后来写了一个带很多代码截屏的版本,但是很抱歉没法发到论坛上来。
我个人觉得下面的文字已经能表达我的想法和思想了,希望能对帖的有一点帮助吧。
---------------------------------------------
写这个文档的目的是让大家对搭建SoC项目的Testbench有一个比较清晰的认识,可以根据这个文档来一步一步的搭建起一个SoC项目的基本的testbench。本文档重点是指导大家搭建基本环境,以及能解决搭建Testbench过程中容易遗漏的问题或者容易遇到的“地雷”。我搭的SoC项目的testbench会有一些相对特殊的点:
1)
要有嵌入式的软件。这里包括两部分,一是初始化的bootloader(一般是固化在rom或者存放在外部的flash里),一是boot起来以后放在外部易失性存储介质上的应用层的程序。2)
正常启动起来(一级boot可以切到应用程序了)以后,为了简化流程,我们要使用ISS的环境。 --- 这是比较特殊的一个点
3)
环境主要脚本的维护和修改。主要是单个仿真和批量仿真(regression)核心脚本
4)
为了优化仿真和编译速度,我们要能把不用的模块dummy掉。
5)
文件列表的处理
6)
SoC软件与Testbench都能访问的“共享空间”的处理
7)
公用函数的准备,比如根据CPU看到的地址空间直接访问外部DRAM的数组,进行初始化写、数据写和数据读操作。
8)
环境变量的维护。
9)
Define文件的维护
10)DDRC的替换(一个是AXI_SLV_VIP的替换,一个是简单AXI_SLV模型的替换)
磨刀不误砍柴工,把需要的东西提前准备好,搭建Testbench就像搭积木一样简单快速了。环境变量维护
使用module工具来维护整个项目的环境变量。目的是为了让项目上的工程师都使用统一的环境(主要是工具版本和环境变量)。
核心脚本的维护
两个脚本:run_sim 和regress。 run_sim负责提交单个仿真任务,regress负责提交批量仿真任务。两个脚本已经使用了很多项目了,脚本的具体说明我以后专门开专题讲。在这里只提醒一下,run_sim脚本通常需要根据不同的项目做微小的改变。
run_sim和regress都是比较大的perl脚本程序,大致描述一下功能。
run_sim脚本功能
1)为每个仿真产生仿真目录。仿真的目录里应该包括文件列表(硬件和软件)、编译和仿真命令(注意包括嵌入式软件的MakeFile)、提前建立需要的子目录、和单个仿真对应的文件链接(比如维护的C的测试主函数、扩展的随机类的SV文件、一级bootloader文件的链接)、define文件、本仿真的重构命令(这是一个容易忽略的,一旦你跑regression的时候某个仿真失败,你又不想在出错的目录下重新仿真,用这个重构命令文件就可以直接提交)。2)各种option的维护。比如不同仿真需要不同的define、编译和运行option、dump波形的scope以及层次
regress脚本功能
regress脚本比较简单,要吃一个由很多run_sim仿真命令组成的命令集文件。用regress 脚本把这些仿真命令提交到工作站上去。需要注意的是:有时候可能会有一些公共的option 或者define,比如打开coverage收集、某个define要应用到整个regression里。所以regress脚本要能支持对所有run_sim命令添加option的功能。
产生dummy文件
使用gen_dummy_file脚本来产生dummy文件。设计工程师可能也要维护一个module_dummy.v的文件用于做integeration,验证工程师产生的dummy文件记得名字不要和设计自己维护的文件重复了。
为什么不使用设计维护的文件?因为一个是设计维护的文件在integration以后很可能就不再维护了;另一个是设计维护的文件可能output全是assign成0的,但是对于模块输出的pready\CEN等信号最好assign成1,否则可能导致问题(例如:sram使能信号CEN赋成0,可能导致后面的sram模型认为有读写行为;pready信号赋成0,可能导致SoC软件跑起来的时候对该模块寄存器操作的时候挂死apb总线)。
这个脚本并不好写。因为verilog语法支持的模块声明实在是太多了,导致脚本很容易顾此失彼。举例来说几个复杂的地方:
module声明后面可以跟parameter的就很复杂
Module test #(parameter a = 1,
Parameter b = 2,
C = 3,
D = 4 );
这些parameter很可能要用在端口位宽的声明里。更为麻烦的是parameter里可能会有function的使用。而function有可能是以define的形式写到代码中。这样就很难用parse RTL的方法来解决。
再比如:端口声明里出现ifdef else endif这种编译宏的处理也比较麻烦。
也可以使用simulator或者debug工具提供的用户接口来编写tcl程序来获取各个端口的name、width信息。但是不同仿真(define不同)可能导致端口宽度和端口不一致,结果要针对不同define来维护不同的dummy也比较麻烦。
总之,产生dummy文件以后一定要记得检查一下。Dummy文件可以有效缩短编译的时间。
文件列表处理的维护
上述几个事情是应该提前准备好的,接下来我们要开始编译RTL了。Integration好的文件列表,首先要先编译该文件列表。有可能遇到的问题是加密文件的种类,有可能文件列表里的加密文件和你用的仿真器不一致。然后结合前面产生好的dummy文件,我们要处理出一个