sv调用c程序
大专栏后端前端人工智能DevOps移动端测试程序人生SystemVerilog——SV与C的接口发表于20212019-11-10|分类于测试|没有评论8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?在Verilog中,通过VPI可以引用C程序,听说挺复杂的(,当然我不会)。在SV中引入了DPI(direct programming Interface),可以通过在SV
SystemVerilog——SV与C的接口
8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
在Verilog中,通过VPI可以引用C程序,听说挺复杂的(,当然我不会)。在SV中引入了DPI(direct programming Interface),可以通过在SV中简单的设置,就可以引用C语言。
1. SV简单引用C
先看一个例子
| |
用VCS直接编译这两个文件就行了。
1.1 导入声明
import将C函数引入SV,但使用的数据类型是SV的,这里就需要将C的类型转化成对应的SV数据类型。
如果函数名跟SV中已有的函数冲突,还可以改名,如下:
| |
如果c程序的类型是void,那么可以将C函数映射成task或者返回类型为void的function。
在SV中允许声明子程序的地方都可以导入函数,可以将导入函数理解成定义了一个函数,只不过是用C语言写的。
也可以将import声明放在package中,如后导入package就可以。
1.2 参数方向
在import函数时可以设置的参数的输入输出方向有 input、output,不支持ref类型。
input:一般情况下参数方向是input;
output:当参数是指针(可以对输出数据进行修改)的时候,方向为output。但如果是const指针参数,说明不会改变输入对象,那么参数是input。
1.3 参数类型
通过DPI传递的每个变量都有两个数据类型,一个是C类型,一个是SV类型,必须确保兼容。
SystemVerilog | C(输入) | C(输出) |
---|---|---|
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]orlogic[N:0] | const svLogicVecVal* | svLogicVecVal* |
open array[] | const svOpenArrayHandle | svOpenArrayHandle |
chandle | const void* | void* |
对于函数的返回类型,SV LRM中规定只能是void、byte、shortint、int、longint、real、shortreal、chandel和string、bit、logic。不能是bit[6:0]这样的向量。
C的结构类型定义在头文件svdpi.h中,比如svBit。如果在C代码中使用了这些类型,那么需要在C中#include svdpi.h
1.4 导入数学库函数
| |
如上面的方式导入sin函数,可以直接在SV中使用。
2. 连接简单的C子程序
2.1 使用静态变量的计数器
下面是一个7位计数器。
| |
在本例中7位的计数器保存在8位的字符型变量中,所以要使最高位无效。
| |
输出:
| |
2.2 chandle数据类型
上面计数器保存在静态变量中,如果只需要一个计数器,可以这样;但如果需要多个计数器,那么下一个计数器会覆盖之前的计数值,所以在C代码中不要把变量保存在静态变量中。需要动态申请
在SV中chandle类型可以存储一个C/C++指针,这个指针指向对象的类型是任意的,可以是结构体。。。
C中如果返回void*指针类型,那么在SV中对应chandle。
C中的参数是结构体指针类型,那么SV中对应chandle。(这一条不是很确定,可以定义为chandle,也可以如下面第6节中所述)
| |
上面程序中定义了一个结构体来保存计数器;counter7_new()函数用来动态申请计数器的内存,保证每个计数器唯一。调用counter7函数的时候将相应的计数器指针(inst)作为参数传入其中。
| |
计数器结构体的指针,在SV中对应chandle数据类型。
3. 调用C++子程序
在SV中可以使用DPI调用CC++子程序,模型的抽象层次不同调用方式不同。
3.1 C++中的计数器
用类实现计数器
| |
3.2 静态方法
| |
通过DPI只能调用静态的C、C++方法,即链接时已经存在的方法。C++对象在链接的时候还不存在,那么方法也就不存在。
解决方法:通过创建与C++动态对象和方法通信的静态方法,也就是上面的两个方法。将对象的指针传入函数。
extern “C”告诉C++编译器,送入链接器的外部信息应当使用C调用风格,并且不能执行名字调整name mangling。(基本支持函数重载的语言都需要进行name mangling。mangling的目的就是为了给重载的函数不同的签名,以避免调用时的二义性调用。)
可以直接使用第2节中的tb。
3.3 和事务级C++模型通信
事务级通信中用的是方法,而不是信号和时钟。
1.先用C++实现事务级的计数器。
| |
2.将动态方法包装成静态方法。
| |
3.在测试平台中将方法引入
注意get()函数的返回值,它应该返回bit[6:0] 7位数据,但是规定导入函数只能返回void、byte、shortint、int、longint、real、shortreal、chandel和string、bit、logic。不能是bit[6:0]这样的向量。
| |
4.为了方便使用,将引入的方法封装成类
| |
在测试平台中使用计数器的时候,定义一个Counter7对象,然后调用它的方法就行了。
5.测试平台
| |
6.输出
两个计数器并行计数,各记各的,互不干扰。
| |
4. 共享简单数组
4.1 双状态一维数组
| |
这里的参数是svBitVecVal,没有星号。
| |
5. 开放数组 open array
开放数组定义在svdpi.h中,在C代码中,可以通过开放数组,操作任何大小的数组。
6. 传递特殊结构
6.1 SV和C之间传递结构体参数
| |
| |
6.2 传递字符串
从C程序向SV返回字符串。
最简单的方法是字符串返回值;
还有一种是char类型的参数。**
下面程序同时用了这两种方法。
| |
| |
输出
| |
从输出看一看到,test函数既返回了string值,也修改了传入的参数s2.
7. C也可以调用SV的函数。
© - 2021 大专栏|粤ICP备18064926号-2
更多推荐
所有评论(0)