基于Questasim的SystemVerilog DPI使用流程

1. 前言

DPI是Direct Programming Interface的缩写,它提供了SystemVerilog与其它编程语言(特别是C语言)交互的接口。它允许编程人员轻松地从SystemVerilog调用C函数,且在C函数也可以调用Systemverilog的函数。

DPI极大地方便了使用现有的C代码,可以使用import “DPI-C”声明从SystemVerilog调用C实现的函数,这样的函数称为导入任务或函数,所有导入的任务或函数都必须声明。在SystemVerilog中实现并通过export "DPI-C"导出的函数或任务可以被C调用,这些任务和函数称为导出任务或函数。其它具体的DPI语法这里不多说,本文讲述在Questasim中如何编译和使用Systemverilog的DPI流程。正确的使用流程如下:

基于Questasim的SystemVerilog DPI使用流程_第1张图片

2. 代码举例

举个简单的Questasim DPI例子来演示如何在SystemVerilog和C语言中互相对象对方的函数。

首先,我们需要创建1个C函数,将其放在一个名为"dpi_example.c"的文件中:

#include "dpi_example.h"  
void c_func(int a, int b, int* c) {  
    *c = a + b;  
    sv_func();
}

第一行include文件将使用Questasim的vlog自动从根据export/import “DPI-C”内容生成出来的,我们只需要在vlog参数-dpiheader里指定生成文件名为dpi_example.h就好了,当然也可以是其它名字,只要能和c文件里include后的文件名匹配上就行了。第四行的sv_func()在后文中介绍,它是一个SystemVerilog函数,通过export “DPI-C”提供给C函数调用。c_func函数计算了a加b的值,并调用了sv_func函数。

接下来,在SystemVerilog中使用DPI调用C函数。将以下代码放在名为"dpi_example.sv"的文件中:

module dpi_example;  
    import "DPI-C" context function void c_func(int a, int b, output int c);
    export "DPI-C" function sv_func;
    initial begin  
        int a = 600;  
        int b = 66;  
        int c;  
        c_func(a, b, c);  
        $display("c_func result: The sum of a(%0d) and b(%0d) is c(%0d)", a, b, c);  
    end  
    function void sv_func();
        $display("sv_func is called by c code");
    endfunction
endmodule

第2和3行是DPI的关键,import "DPI-C"是将C函数导入到SystemVerilog作用范围内,export "DPI-C" 是将SystemVerilog的函数或任务导出到C的作用范围内。在第8行调用了C函数c_func去计算变量a和变量b的相加,并将结果传递给变量c,第9行将c_func的结果打印出来。这里的sv_func通过export "DPI-C"导出给之前C代码使用。

3. 运行命令

确保工作站下有Questasim和C编译器的license,使用Questasim进行仿真,在terminal中运行以下命令:

步骤一:运行vlog命令生成dpi_example.h头文件

vlog -dpiheader dpi_example.h dpi_example.sv

这个文件定义了C和Questasim之间的接口,用于导出和导入任务和函数。dpi_example.h其实不是必须的文件,但在C代码中包含dpi_example.h可以更快解决由不正确定义的接口引起的问题。创建dpi_example.h的示例命令是:

vlog会自动提取dpi_example.sv中的export/import “DPI-C”内容去生成dpi_example.h头文件,大家生成后可以打开这个文件看看下。

Questasim建议任何export/import “DPI-C”的用户DPI C代码都应该包含在dpi_example.h中,方便C编译器验证C和Questasim之间的接口。

步骤二:运行vlog命令编译C代码

vlog dpi_example.c

可以在vlog命令行中指定c/c++文件,该命令根据传入的文件类型调用正确的c/c++编译器。vlog命令将所有Systemverilog文件和c/c++文件编译到work库中。vsim命令在elaboration阶段自动加载编译好的c代码。可以使用-ccflags选项将指定的C编译器选项传递给vlog,vlog不会检查您用-ccflags指定的选项的有效性。这些选项直接传递给编译器,如果它们无效,则由C编译器生成错误消息。还可以在-f文件中指定c/c++文件和选项,它们将以与-f文件中的Systemverilog文件和选项相同的方式处理。也可以使用-ldflags选项将指定的c/ c++链接器选项传递给vsim,vsim会将指定的选项传递给链接器去解析。

步骤三:开始仿真,运行vsim命令

vsim dpi_example -c -do "run -all; quit"

步骤四:总结以上步骤和运行结果

# 执行命令:
vlib work
vlog -dpiheader dpi_example.h dpi_example.sv
vlog dpi_example.c
vsim dpi_example -c -do "run -all; quit"
# 运行结果:
run -all
sv_func is called by c code
c_func: The sum of a(600) and b(66) is c(666)
quit

4. 其它

额外话题,Questasim支持将外部已经编译好的C代码直接传递给vsim去仿真,不需要vlog再重复编译了。使用以下vsim参数可以将DPI库指定给vsim命令。

参数 描述
-sv_lib 指定要搜索和使用的库名称。不需要指定文件名扩展名。(Questasim预期的扩展名是:.dll用于Win32/Win64, .so用于所有其他平台。)
-sv_root 为shared object指定一个新的前缀,由-sv_lib指定
-sv_liblist 指定要使用的"bootstrap file",的格式如下:
#!SV_LIBRARIES
///
//

shared library上不需要任何扩展。

当仿真器发现imported的task或function时,它会在使用这些参数指定的shared objects集合中查找。例如你可以指定以下的DPI库:

vsim -sv_lib dpiapp1 -sv_lib dpiapp2 -sv_lib dpiappn top

另外在PLI/VPI shared object中指定DPI导入的函数和任务是错误。但是DPI导入函数和任务可以调用PLI/VPI代码,前提是使用vsim -gblso以全局可见方式标记PLI/VPI shared object。

基于Questasim的SystemVerilog DPI使用流程_第2张图片

你可能感兴趣的:(EDA工具,Systemverilog,DPI,Questasim,PLI/VPI,DPI-C)