前言
systemverilog中,可以通过DPI、PLI来与外部其它语言进行交互。PLI又分为三类,TF、ACC和VPI,可以认为是PLI技术的三代演进:
其中VPI(PLI3.0)是TF/ACC的一个超集,目前使用的PLI基本上都是VPI。
与PLI技术相独立的另一个技术就是DPI,DPI技术简化了systemverilog与foreign language的交互步骤,对于开发者相对友好,所以使用相对广泛一些。
本文不对DPI中程序调用/数据交互展开讨论(这部分可以参考绿皮书),只简单介绍下vcs中关于DPI接口的使用步骤。
方式1:使用vcs编译systemverilog和c/c++
使用时直接把c/c++的源代码放到我们的filelist里面即可,systemverilog侧直接import对应的function/task。
可以看到,当我们执行vcs时,实际上是先编译verilog/systemverilog(step1),再调用gcc/g++编译c/c++(step2),最后使用g++(step3)来链接得到可执行文件simv。
可以通过在vcs中添加编译选项来传递参数给gcc/g++,比如指定c/c++编译器。这部分参考vcs user guide的"Options for Controlling the C Compiler"这一节。
方式1变种:独立使用gcc/g++编译c/c++
既然vcs也是调用gcc/g++来编译c/c++代码,那么这部分工作自然也可以独立出来。我们可以自行完成c/c++代码的编译,然后再和verilog/systemverilog进行链接。
这种方法的好处在于,一是可能c/c++代码保密,vcs仿真时拿不到c/c++源码;二是独立的c/c++编译流程比较清晰。
当然,代价就是多余的操作步骤以及链接失败时的调试工作。
方式2:在仿真阶段载入DPI的动态库
除了在编译阶段嵌入c/c++程序外,vcs还提供了另外一种方式:在Runtime时动态加载DPI库文件。
当然,首先你需要编译c/c++代码得到一个.so的动态库。
然后在simv运行时加载这个动态库,vcs提供了两种加载方式:bootstrap file和-sv_lib指定动态库的方式:
比如我的Makefile就是这么写的:
后言:
网上关于DPI的资料比较少,这里补充点资料途径:
1、绿皮书中"Systemverilog与C语言的接口"一章
2、systemverilog2012标准里面的第35章“Direct programming interface”
3、vcs2017用户手册的小节“Using DirectC”和“Dynamic Loading of DPI Libraries at Runtime”
4、DOULOS关于DPI的教程:SystemVerilog DPI Tutorial
5、vcs中关于DPI的例程
6、文章"The Verilog PLI Is Dead (maybe) Long Live The SystemVerilog DPI!"
这篇文章是有中文翻译的:“Verilog PLI已死(可能),SystemVerilog DPI当立”