前言

systemverilog中,可以通过DPI、PLI来与外部其它语言进行交互。PLI又分为三类,TF、ACC和VPI,可以认为是PLI技术的三代演进:

vesc 编译 vcs编译system verilog_c++

vesc 编译 vcs编译system verilog_g++_02

其中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。

vesc 编译 vcs编译system verilog_g++_03

可以看到,当我们执行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的动态库。

vesc 编译 vcs编译system verilog_动态库_04

然后在simv运行时加载这个动态库,vcs提供了两种加载方式:bootstrap file和-sv_lib指定动态库的方式:

vesc 编译 vcs编译system verilog_c++_05

比如我的Makefile就是这么写的:

vesc 编译 vcs编译system verilog_动态库_06

后言:

网上关于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的例程

vesc 编译 vcs编译system verilog_动态库_07

6、文章"The Verilog PLI Is Dead (maybe) Long Live The SystemVerilog DPI!"

这篇文章是有中文翻译的:“Verilog PLI已死(可能),SystemVerilog DPI当立