DPI-C接口的使用
为了方便与C、C++等语言的交互,uvm中引入了DPI接口,自定义的函数需要写函数主体,然后再import后声明和使用,验证环境中便可以像调用system verilog中的函数一样使用这些函数。而且,对于C语言中内置的函数,不需要写函数主体,直接声明使用。同理c语言也可以调用sv里面的函数或者task,需要export后申明使用,下面详细讲一下具体的过程。
DPI 数据类型映射
当验证环境中systemverilog与C发生数据交换时, 数据类型需要match,否则数据交互会失败。systemverilog和C之间的数据交换通常使用DPI-C接口完成,大多数SystemVerilog数据类型在C语言中具有直接的对应关系,完整的数据类型映射关系如下表
System Verilog | C (input) | C (output) |
---|---|---|
byte | char | char* |
shortint | short int | short int* |
int | int | int* |
longint | long long int | long int* |
shortreal | float | float* |
real | double | double* |
string | const char* | char** |
string [N] | const char** | char** |
bit | svBit or unsigned char | svBit* or unsigned char* |
logic,reg | svLogic or unsigned char | svLogic* or unsigned char* |
bit[N:0] | const svBitVecVal* | svBitVecVal* |
reg[N:0], logic[N:0] | const svLogicVecVal* | svLogicVecVal* |
unsized array[] | const svOpenArrayHandle | svOpenArrayHandle |
chandle | const void* | void* |
DPI 导入函数的分类
注意! 正确的声明导入的函数为pure还是context是用户的责任。缺省情况下,DPI函数假定是generic函数。调用一个不正确声明成pure的C函数可能返回不正确或者不一致的结果,导致不可预测的运行时错误,甚至于让仿真崩溃。
同样,如果一个C函数访问Verilog PLI库或者其他API库,却没有声明为context函数,会导致不可预见的仿真结果甚至仿真崩溃。三者的比较说明如下:
申明类型 | 说明 |
---|---|
pure | 作为pure函数,函数的结果必须仅仅依赖于通过形参传递进来的数值。Pure函数的优点在于仿真器可以执行优化以改进仿真性能。Pure函数不能使用全局或者静态变量,不能执行文件I/O操作,不能访问操作系统环境变量,不能调用来自Verilog PLI 库的函数。只有没有输出或者inout的非void函数(必须有return值)可以被指定成pure。Pure函数不能作为Verilog任务导入。example:import "DPI" pure function real sine(real in); |
context | context C函数明确函数声明所在工作域的Verilog的层次。可以是void函数,可以有输出和inout参数,可以从C库调用函数(用于文件I/O等),可以调用PLI库中的许多函数,这使得被导入的C函数能够调用来自PLI或者VPI库的函数,从而DPI函数可以充分利用PLI的优势特性,比如写仿真器的log文件以及Verilog源代码打开的文件。import "DPI" context task delay_ms(input int n); |
generic (缺省pure/contect) | 那些既没有明确声明为pure,也没有声明为context的函数称为generic函数(SystemVerilog标准没有给除了pure或context之外的函数特定的称呼)。generic C函数可以作为Verilog函数或者Verilog任务导入。任务或者函数可以由输入、输出以及inout的参数。函数可以有一个返回值,或者声明为void。generic C函数不允许调用Verilog PLI函数,不能访问除了参数以外的任何数据,只能修改这些参数。 |
从C向SV导入函数
从SV向C导入函数
import过程中还可以修改函数名,本质是不同字符串链接c函数的句柄:
export 过程同理。