芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

芯片验证中的编译和仿真加速(1)

1.前言

随着芯片设计规模的不断扩大和复杂度的增加,特别是在RTL以及后仿的验证阶段,EDA工具的编译和仿真速度经常拖累设计和验证人员的工作效率。因此,编译仿真加速已经成为缩短设计周期、提高设计验证效率的关键技术。本系列集中探讨VCS和Xcelium在芯片设计验证中编译和仿真的加速技术。本文重点探讨VCS的编译仿真加速,后续会有Xcelium的编译和仿真加速汇总。欢迎大家提出自己的想法。

2.VCS编译仿真加速方法

随着电路规模的不断变大,编译时间也成为了仿真过程中重要因素,如何加快/重用编译数据库,是加速整个仿真过程不可缺少的部分。VCS提供了很多好的技术来加速编译过程。

2.1增量编译(Incremental Compilation)
增量编译是指在代码变更后,只重新编译受影响的部分,而不是重新编译整个代码库的一种优化编译方式。其流程包括首次全量编译、变更检测、增量编译及链接生成。启用增量编译能在复杂硬件设计中缩短验证周期,提高开发效率。但需注意模块化设计、依赖管理及中间文件完整性,以确保结果的正确性。VCS支持增量编译的命令:
使用 -fast 选项可以加快编译速度;
使用 -Mupdate 选项开启增量编译支持。示例命令如下
vcs -Mupdata design.v tb.v -o simv
2.2 分块编译(Partition Compilation)

当设计比较大,我们需要对某一个模块反复修改代码,进行debug的时候,如果每次都从头开始编译,那么会耗费大量的时间,分块编译(Partition Compilation)可以有效解决这个问题。

2.2.1分块编译介绍
分块编译(Partition Compilation)是一种针对大型设计的优化技术。它将设计分割成多个独立的逻辑块或模块,分别编译这些模块,然后在链接阶段合并生成最终的仿真文件。这种方法适用于设计规模庞大且模块化良好的项目,能显著提高编译效率和资源利用率。下面看看官方的解释:

图片[1]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.2 Autopartitioning(Ease of Adoption)

自动分块编译,只需要加入-partcomp的编译选项即可,应用起来比较简单。

图片[2]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.3 Specifying Partitions Manually(Recommended)

推荐使用手动的方式去指定分块编译。

2.2.3.1 topcfg.v file

首先需要编辑一个指定分块的文件,文件格式如下:

图片[3]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.3.2 Two step commands for partition compile

vcs两步法分块编译的方法如下:

图片[4]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.3.3 Three step commands for partition compile

vcs三步法分块编译的方法如下:

图片[5]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.3.4 Profiling of Compilation Time

可以通过-pcmakeprof这个选项,来查看每个块编译所用的时间,从而进一步方便对时间久的块进行拆分。

图片[6]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.4 Best Practice with Partition Compile

用分块编译时的几个建议。

图片[7]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.2.1~2.2.4主要介绍了VCS的分块编译。分别从自动和手动两种方法,记录了VCS分块编译的方法,最后给了应用分块编译时的几点建议。

2.2.5下面给一个实例

功能:将DUT和TB分成若干partition,调用多核分别编译。对于二次编译,只编译修改的partition。
命令
vcs -lca -partcomp=autopartdbg -fastpartcomp=j4 -partcomp_dir=pc_dir -pcmakeprof [other options]
-partcomp:自动分割成若干partition。
-partcomp=autopart_low: 分割粒度更小
-partcomp=autopart_high:分割粒度更大
-partcomp=autopartdbg:debug,生成vcs_partition_config.file包含partitioning information。

-fastpartcomp:调用多核并行编译。

配置了4个CPU core:
图片[8]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug
-partcomp_dir:指定中间数据存放目录。
-pcmakeprof:生成时间消耗的log 如下图:
图片[9]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug
注意:

首先使用auto-partition,查看每个partition的时间消耗,对于较大的partition, 再人为分割。每个partition不宜过大过小。对于Cross-Module References (XMRs) 跨模块的引用,一个partition改动都会引起另一个partition重新编译。Partition Complie 还是lca功能,debug时可以禁用,排除EDA工具的影响。

2.3并行编译

基本上我们的服务器都能提供多核支持,VCS多线程并行编译是一种利用现代多核处理器加速编译的技术。通过将编译任务拆分成多个线程同时运行,可以有效减少编译时间,尤其是在设计规模较大时,这种方法能显著提升效率。VCS 的编译流程包括多个独立的子任务,例如,分析设计文件、编译各个模块、生成中间文件、链接阶段的任务。通过多线程方式,这些任务可以同时在多个CPU核心上运行,从而缩短整体编译时间。

启用多线程并行编译的命令:
使用-j[no_of_processes] 参数,其中no_of_processes指定线程的数量。

示例命令:

vcs -j4 design.v -o simv

以上命令表示使用 4 个线程进行并行编译。推荐设置为机器物理 CPU 核心数的 50%-100%,视负载而定。

2.4快速编译

VCS提供了一系列快速编译选项,旨在加速编译过程,尤其适用于快速验证和调试周期。这些选项通过简化某些编译步骤、减少优化工作或跳过不必要的处理来显著缩短编译时间。

下图是常用的快速编译选项及其特点:

图片[10]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.5使用预编译库

预编译库(Precompiled Library)是VCS提供的一种加速编译的方法。通过将常用的模块、设计文件或标准库预先编译为对象文件,可以避免重复编译这些文件,从而显著提高整体编译效率。下面介绍VCS中使用预编译库加速编译流程。

2.5.1.创建预编译库

使用 -o指定生成的预编译对象文件,包含需要预编译的设计文件。编译需要预编译的设计文件:

vcs -sverilog -o lib.o library_file1.sv library_file2.sv
其中· lib.o 是生成的预编译库文件。· library_file1.sv 和 library_file2.sv 是待预编译的库文件。如果有多个库,可以为每个库单独生成对应的对象文件:
vcs -sverilog -o lib1.o library1.svvcs -sverilog -o lib2.o library2.sv

2.5.2使用预编译库

在后续编译中直接链接预编译的库文件。
vcs -sverilog -lib lib.o design.sv tb.sv -o simv
其中 -lib lib.o指定了预编译的库文件。design.sv和tb.sv是主设计文件和测试文件。simv是生成的仿真可执行文件。

2.5.3多个预编译库的链接

如果设计使用多个预编译库,可以通过多个 -lib 参数指定这些库。示例如下:
vcs -incr -lib lib.o design.sv -o simv

以上是部分常见的加速VCS编译的方法,通过在不同场景下结合这些方法,可以显著减少VCS编译时间,从而提高验证的整体效率。

2.6 VCS编译及仿真时间分析及优化方法

VCS提供了一套对编译时间和仿真时间分析优化的工具,在compile 和simulation option中加入相应的option,在simulation log path会多出simulation profile log:profileReport.html,使用firefox打开html会显示出各类方法消耗掉的仿真时间,如constraint solver, function coverage, PLI等。

针对不同的env,可能时间消耗占比不太一样,通过simulation profile infor分析可以为加速提供帮助。下面介绍该工具的用法。

2.6.1Compile & Simulation Efficiency

使用simprofile 示例,compile选项如下:  

-lca -simprofile mem+time

simulation选项如下:

-simprofile time+mem +ntb_solver_debug=profile

2.6.2 CPU resource consumption:

–reportstats

具体请参考vcs userguid的5.The Unified Simulation Profiler   9.Performance Tuning。

2.6.3查看资源消耗的选项总结

show the summary time and mem of compile and runtime.,参考下面的选项

vcs –reportstats <OTHER_OPTS>simv -reportstats
查看详细的各个模块(module,package,pli等)占用时间和内存,参考下面的选项。(html txt格式报告)
vcs -simprofile simv -simprofile [time|mem]:
查看UVM相关的资源消耗,参考下面的选项。(html txt格式报告)
vcs -simprofile=uvm
2.6.4 Simulation时间优化的几点小建议

优化resource_db/config_db使用wildcard;debug_xx Option优化;debug_xx会对simulation速度造成影响,如果没有使用ucli的需求,最好不要加任何debug_xx。即使需要使用ucli,也可以最好开到debug_pp,不要在ucli中使用force;在大量regression时,不要dump fsdb;Assertion, array的dump会更耗仿真速度;在chip level的仿真中,可以选择性dump fsdb,如选择某一段时间,选择某个或某几个需要关心的partition。

 

2.7其他加速

2.7.1 Debug参数

VCS支持-debug_pp/–debug/–debug_all参数,其中-debug_pp用于只进行波形保存后处理模式,而debug用于交互式,debug_all交互式仿真同时可以开启单步调试模式,不同的调试粒度带来更多方便的同时,也会带来性能的消耗。对于前期testbench开发,建议开启debug_all/debug参数,用于我们自己的验证环境的调试以及单步/断点调试等;当验证环境已经稳定以后,目的是进行DUT的验证一般就只开启debug_pp/debug来进行波形保存之后再调试。进入回归测试后,主要依赖验证环境中的检查器来做检查,当发现错误的时候才会打开debug_pp或者debug/debug_all来进行进一步的调试。

VCS 2014 后加入了debug_access, 之前的-debug_pp, -debug, -debug_all不再建议使用。为了更好的平衡仿真速度和debug功能,建议 配合-debug_region 使用,提供更精准的仿真控制。vcs -debug_access 时,不需要再手动配置PLI的tab file verdi.tab 和静态库pli.a,只需设置 $VERDI_HOME,vcs会自动查找所需文件,$fsdbDumpfile可以直接使用。

需要注意的是:-debug_access+all 并不包含library(-v -y指定)和cell(`celldefine编译原语标记的module是cell module),无法PLI访问(如uvm_hdl_write)和波形dump。加上-debug_region=cell+lib才可以正常访问。而-debug_all则是默认包含library和cell。(一般library和cell为标准单元,特别是在后仿,RTL综合成stdcell,被celldefine标记,而且PR也加入很多buf和inv, 降低仿真速度,增加波形文件size,如果不需要可以加上+nocelldefinepli+2,只dump module instance上的port波形)。

图片[11]-芯片验证中的编译和仿真加速(1)-Anlogic-安路社区-FPGA CPLD-ChipDebug

2.7.2 波形保存的方法

在影响仿真的性能参数中,文件I/O是占很大比重的一部分,所以对于性能的提升,可以从减少磁盘I/O读取来入手,比较多的磁盘I/O访问操作就是波形保存的动作。

(1)尽量只保存需要的层次结构的波形而不要总是保存所有芯片的波形

(a)FSDB波形保存

$fsdbDumpvars(1, tb_top);

$fsdbDumpvars(2, tb_top.design_inst);

(b)VPD波形保存

$vcdpluson (level|”LVL=integer”,scope*,signal*); 

(2)可以指定波形保存的时间来进行波形保存  

(a)在VCS运行时参数行进行指定(以FSDB为例) 

+fsdb+dumpon+time[+htime ]  

+fsdb+dumpoff+time[+htime]  

(b)在验证环境中进行指定(以VPD为例)  

$vcdpluson; // Enable Dumping  

#5 $vcdplusoff; //Disable Dumping after 5ns

另外基于不同的验证阶段,建议使用不同调试粒度的仿真参数,也可以节省很多的仿真时间/内存消耗。

2.8 最后补充几点

1).修改设计 有些testbench里面的特殊语法会导致仿真时间变化巨大,不同的仿真阶段用不同的Memory Model也很重要,减少不必要的IO操作;

2).一般debug_all之类的去掉,关掉debug_pp;
3).调节gcc编译选项,可以设置CFLAGS;

4).用vcs的profile,仿真结束后可以查看仿真中哪些模块占用的时间和内存最多,可以的话做个优化;

5).在analyze代码时,加入-j参数,比如 -j4, -j10, j后面的参数表示并发采用多个cpu core进行compile;
6). vcs2012.09提供了1个lca feature, vcs -lca -fastcomp=x,x为0或者1,快速编译;
7). 指定-Mdir为本地硬盘,通常服务器会把home挂在一台服务器上方便管理,每次你登陆上去,都位于那个服务器的home下,所有你的文件也都存在home下,这时你需要利用-Mdir localdisk/dir来让vcs存储中间数据到仿真所在服务器的本地硬盘;
8). 移除-debug, -debug_pp, -debug_all参数,以及禁止function coverage;当然,这样你也dump不到波形了;
9). 减少编译文件的数量,可以采用宏定义来不编译不需要的testbench代码;
10). 减少代码中的逻辑翻转,比如,你不得不带着所有的tb来跑仿真,这是你需要保证在run某个case时,和该case无关的testbench以及信号全都是不翻转的;这样可以减少runtime时间;
11). 采用vcs的segment compile策略,其实就是把代码中已经不会在修改的那部分编译到一个lib中去,下回不在编译这部分而直接使用编译好的,但这方法实在是实用性不高,特别是在初期debug阶段,代码不断在动,仿真控制脚本也会不停的变,是用人力换去时间的做法,不怎么样;
12). 采用增量编译的方式,也就是上次编译完,不要删除编译出来的中间文件,继续下次编译,vcs的增量编译会出现一些莫名其妙的事情,比如怎么仿都不更新,或者编译时vcs访问堆栈出错;这时就不得不删除中间文件重新从头开始编译;聊胜于无吧。
13).编译的时候加上-partcomp这个选项,就会将编译分成几个块,之后修改的代码属于哪个块,就会只编译那个块。所以从第二次编译开始,都会变快很多。而且可以主动划分块。比如将uvm的lib独放一个块,tb放一个块,rtl放一个块。因为有些万年不动,有些要经常修改。把他们分开,就不会编译经常修改的部分的时候还会连带着编译万年不动的部分。

config topcfg;
partition package uvm_pkg;
partition instance top.dut;
endconfig

partion编译也是有风险的。比如在part A中新加了一个宏定义,这个宏定义本应该对part B有影响。但是因为是加在了part A中,vcs会重新编译part A,但可能不会编译part B,因而宏定义对part B不会生效,导致错误。
14).Synopsys提供了包括fgp在内一些加速选项,但是有概率会让DUT行为异常,需要注意。

请登录后发表评论

    没有回复内容