Verilog与C之间进行程序交互,PLI(Programming Language Interface)经过了TF,ACC,VPI等模式。
使用PLI可以生成延时计算器,来连接和同步多个仿真器,并可以通过波形显示等调试工具。
通过PLI方式连接一个简单的C程序,需要编写很多代码,并理解多仿真阶段的同步,调用段,实例指针等概念。
PLI方式给仿真带来了额外的负担,为了保护Verilog的数据结构,仿真器需要不断的在Verilog和C之间复制数据。
SystemVerilog引入了DPI(Direct Programming Interface),能够更简洁的连接C,C++或者其他非Verilog的编程语言。
只要使用import声明和使用,导入一个C子程序,就可以像调用SystemVerilog中的子程序一样来调用它。
SystemVerilog和C语言之间传递的最基本的数据类型是int,双状态的32位的数据类型,
import "DPI-C" function int factorial(input int i);
program automatic test;
initial begin
for(int i=1;i<=10;i++)
$dispaly("%0d != %0d",i,factorial(i));
end
endprogram
通过DPI传递的每个变量都有两个相匹配的定义,一个在SystemVerilog中,一个在C语言中。 在使用中必须,确认使用的是兼容的数据类型。
SystemVerilog C(输入) C(输出)
byte char char* shortint
short int short int short int*
int int int*
longint long long int long int*
bit svBit/unsigned char svBit*/unsigned char
logic/reg svLogic/unsigned char svLogic*/unsigned char*
bit[N:0] const svBitVecVal* svBitVecVal*
reg[N:0] const svLogicVecVal* svLogicVecVal*
通过import声明定义C任务和函数的原型,带有返回值的C函数被映射成一个systemverilog的函数(function),
void类型的C函数被映射为一个systemverilog的任务(task)或者void 函数(function)
如果C函数名和SystemVerilog中的命名冲突,可以在import导入时,赋予新的函数名。
program automatic test;
import "DPI-C" test=function void my_test(); //将C中的test函数,映射为function void的my_test名字。
intial begin
my_test();
end
在systemverilog中,凡是允许声明子程序的地方都可以导入,C子程序,
例如program,module,interface,package 或者编译单元空间$unit,被导入的子程序只在它被声明的空间中有效。
被导入的C子程序,可以有多个参数或者没有参数,缺省情况下,参数的方向是input(数据从SystemVerilog流向C函数)
参数的方向也可以定义为output和inout,ref类型目前不支持。
import "DPI-C" function int addmul(input int a, b,
output int sum);
对输入的参数也可以被定义为const。这样一旦对输入的变量进行写操作,C编译器就会报错。
int factorial (const int i) {}
连接C语言的例子。
#include <svdpi.h>
void counter7(svBitVecVal * o,
const svBitVecVal * i,
const svBit reset,
const svBit load)
{ static unsigned char count = 0;
if(reset) count = 0;
else if(load) count = * i;
else count++;
count &= 0x7F;
*o = count;
}
reset和load是一个双状态的比特信号,以svBit类型进行传递。
输入i是双状态7bit 变量,用svBitVecVal类型传递。
头文件svdpi.h包含了SystemVerilog DPI结构和方法的定义。
测试平台:
import “DPI-C” function void counter7(output bit [6:0] out,
input bit [6:0] in,
input bit reset, load);
program automatic counter;
bit[6:0] out, in;
bit reset, load;
initial begin
$monitor("SV: out=% 3d, in =%3d, reset = %0d, load = %0d\n", out,in,reset,load);
reset = 0;
load = 0;
in = 126;
out = 42;
counter7(out, in, reset, load);
end
endprogram
chandle类型允许在System Verilog中存储一个C/C++的指针,
typedef struct{unsigned char cnt;} c7;
void *counter7_new() { c7* c=(c7*) malloc (sizeof(c7));
c-> cnt = 0;
return c;}
void counter7(c7* inst, ...)
测试平台:
import “DPI-C” function chandle counter7_new();
import "DPI-C" function void counter7(input chandle inst, ...)
使用关键字DPI-C表示,使用压缩值的方式来保存数据类型。