[验证百花筒] 聊聊vcs的分块编译(partition compile)
引言
实际验证过程中,我们常常遇到这样的烦恼,就是明明环境中只修改了一个文件,例如testcase中增加了一行打印,但是编译却需要将所有的文件都编译一遍,这严重影响了我们的仿真效率,对此常用的解决方法有两种。
1、充分利用UVM的runtime cmdline传递参数机制
无需重新编译,直接通过命令行的方式动态修改UVM相关参数设置,例如UVM_TESTNAME、UVM_VERBOSITY这类参数都可以动态的在运行时传递到UVM环境中,而无需重新编译代码。
2、增量编译
我们查阅各种网上资料,每当提到如何提高仿真效率时,都会提到一个增量编译的方法,理想情况下即只会重新编译修改过的文件,而没有修改过的文件无需编译,但即使我们在vcs后添加了增量编译的参数
-Mupdate
实际当我们修改部分文件的时候,仿真器还是会编译很多我们并未修改过的文件,这受限于仿真器的优化做的还不够充分,无法完整识别我们修改过的文件项。
今天我们要讲的分块编译就是对增量编译的一种补充,既然仿真器无法准确识别我们修改了哪些文件内容导致其重新编译的时候又重复编译了很多我们并未修改过的内容,那么我们是不是可以通过别的方式来减轻仿真器识别文件更新的工作量呢?这就用到了分块编译(partition compile)。
vcs分块编译(partition compile)参数讲解
分块编译的本质就是将需要编译的代码文件拆分成独立的块,只有当块中的文件更新的时候才会重新编译该块中的文件,理论上我们拆的块越细,需要重新编译的文件就少,但造成的结果就是仿真器遍历这些块的时候要消耗额外的系统时间,所以说在块分的最粗(只分成1块)和最细(所有文件都独立分成1个块)之间需要寻求一个折中。
可以在vcs后添加-partcomp参数来实现自动分块编译,参考如下:
vcs –partcomp
还可以使用如下编译选项来指定自动划分Partition的大小和数量,但一般不用设置,即推荐使用默认就好。
-partcomp=autopart_[low|medium|high]
vcs官方ug中对上面几种自动分块编译选项的描述如图1所示。
图1 自动分块编译选项描述
还可以手动指定Partition,如下图所示:
vcs -partcomp -top -topcfg topcfg.v
指定的Partition在topcfg.v文件中描述如下图所示
config topcfg;
partition instance top.dut;
partition package uvm_pkg;
partition cell module_name;
endconfig
下面我们以一个实际的项目实例,来比较下每种分块编译选项的执行效率的异同。
项目实例
我们实例中包含了五种编译选项,分别是:
- 纯粹的增量编译,不带分块编译
- 默认的分块编译
- 小块的自动分块编译
- 大块的自动分块编译
- 手动分块编译
对应到项目实例中vcs中的选项对应的Makefile代码如图2所示。
图2 项目实例中不同分块编译对应的vcs选项代码
其中变量COMP_DECL中包含了vcs需要吃的编译参数,我们增加了参数
-pcmakeprof
把编译过程中的每一步所花费的时间做分析打印,并在编译日志的结尾进行输出,这样方便比较不同编译参数所花费的编译时间的区别。
首次编译
我们创建5个仿真目录来依次运行上面5种编译选项,每种编译在相同的服务器上运行相同的场景。对应的编译报告如下。
1. 纯粹的增量编译,不带分块编译
编译时间如图3所示。
图3 不带分块编译的编译时间
2. 默认的分块编译
编译时间如图4所示。
图4 默认的分块编译时间
3. 小块的自动分块编译
编译时间如图5所示。
图5 小块的自动分块编译时间
4. 大块的自动分块编译
编译时间如图6所示。
图6 大块的自动分块编译时间
5. 手动分块编译
手动分块对应的分块config文件如图7所示,只是简单的分了几个package和dut。
图7 手动分块config文件
编译时间如图8所示。
图8 手动分块编译时间
根据上面的初次编译结果可以得出如下结论:
-
对于初次编译,不做分块编译要比做分块编译消耗更少的编译时间,这是因为需要进行划分Partition块的动作,需要耗费更多的时间,这也是使用该技术的代价。
-
默认分块比其他集中分块需要消耗更多的编译时间。
-
手动编译相比较而言消耗更少的编译时间。
下面我们尝试修改can_txrx_pkg里某个文件的内容,比如增加一个空行,看看各种编译选项的编译时间结果如何。
修改文件后编译
1. 纯粹的增量编译,不带分块编译
编译时间如图9所示。
图9 不带分块编译的编译时间
2. 默认的分块编译
编译时间如图10所示。
图10 默认的分块编译时间
3. 小块的自动分块编译
编译时间如图11所示。
图11 小块的自动分块编译时间
4. 大块的自动分块编译
编译时间如图12所示。
图12 大块的自动分块编译时间
5. 手动分块编译
编译时间如图13所示。
图13 手动分块编译时间
根据上面的修改文件后的编译时间结果可以得出如下结论:
-
没有进行分块编译修改文件对仿真时间的改善不大
-
自动分块编译和手动分块编译在优化仿真时间的效率方面相差不大(对于设计规模很大、验证环境很复杂的场景才会体现出手动分块的优势),是否进行手动分块需要跟设计、验证的复杂度来进行判断。
-
任何一种分块编译相比较没有进行分块编译对编译时间的提升非常明显
这里还有一点需要注意的是,如果验证环境中没有进行任何的修改,不要重复执行分块编译,否则会报如图14所示的编译错误。
图14 没有任何文件修改时执行分块编译报错
总结
使用分块编译能够大大提高仿真的效率,自动分块编译推荐使用默认的分块参数即可,是否需要使用手动分块编译需要根据设计、验证的复杂度来判断。
在手动分块编译时,写config文件推荐在验证环境中将验证相关的代码根据逻辑功能合理的划分到SystemVerilog 的package里,对不同的package分别进行分块编译,只import需要用到的package,这样就可以避免修改该package时导致对多个partition的重新编译。
切忌在 u n i t 空间里 i m p o r t p a c k a g e ,这样相当于在顶层全局空间的范围进行导入,以后只要修改被 i m p o r t 在 unit空间里import package,这样相当于在顶层全局空间的范围进行导入,以后只要修改被import在 unit空间里importpackage,这样相当于在顶层全局空间的范围进行导入,以后只要修改被import在unit空间的package包,那么就会编译几乎整个项目文件,导致增量编译失效,效率降低,尤其对于大型项目来说更是如此,即可以理解为避免在 u n i t 空间写代码。这里的 unit空间写代码。这里的 unit空间写代码。这里的unit层次,简单理解是package…endpackage、module…endmodule、interface…endinterface之外的地方。