c 动态数组_SV中如何调用C函数

在仿真验证中,SV语言不能很好的描述复杂的计算或者流程关系,使用软件语言(比如C)就比较方便。那么当我们使用C描述了这些关系后,如何在基于SV的仿真环境中使用呢?有两种方式,一种是将C编译为可执行文件,利用系统函数进行调用。另外一种方式利用SV提供的 DPI-C接口。第一种方式并不是严格意义上的SV和C的对接,只是通过命令行执行了C程序。比如我们写了一个hello world的c程序:

int main(){

       printf(“hello world!\n”);

return 0;

}

我们将其编译为可执行文件gcc -o hello hello.c

我们就可以在我们的SV函数中直接执行:

function void exe();

       $system(“./hello”);

Endfunction

除了这个方式,SV还提供了和C/C++直接的接口DPI。DPI接口允许用户用C编写程序,并和SV实现对接,也可以用SV写程序,将SV程序导出到c中。二者实现了相互调用。如何要在SV中使用自己定义的C函数,需要在SV中导入函数。比如:

module Bus(input In1, output Out1);
  import "DPI" function void slave_write(input int address,
                                         input int data);
  export "DPI" function write;  // Note – not a function prototype
  // This SystemVerilog function could be called from C
  function void write(int address, int data);
    // Call C function
    slave_write(address, data); // Arguments passed by copy
  endfunction
  ...
endmodule

C中为:

#include "svdpi.h"
extern void write(int, int);    // Imported from SystemVerilog
void slave_write(const int I1, const int I2)

  buff[I1] = I2;
  ...
}

C函数slave_write在SV中被调用,其有两个参量 address和data。在C函数中通常要包含两个头文件:svdpi.h和svdpi_src.h。

C和SV的数据类型有以下几种对应关系:

53f7cdfb93dd62953953f61a83b35a79.png

我们需要注意SV和C之间参量传递有两种方式,一种是值传递,比如byte-char,shortint-short int等,另外一种方式是通过指针传递,比如在SV中packed和unpacked的数组,是通过引用传递到C的,那么C中就使用指针来进行接收。比如bit[n:0]作为packed数组,传递到C中是用svBitVecVal*来接收的,svBitVecVal是一个宏定义,实际上就是32bit数据。在这里需要注意的是,n bit的SV数据在C中是以32bit数据存放的,按照小端排列。比如bit[127:0] a,对应的C中数据svBitVecVal* b,有以下对应关系:

a[31:0] = b[0]

a[63:32] = b[1]

这点初学者很容易掉坑里,我一开始在传递这个变量的时候以为是一个svBitVecVal存储1bit数据。在SV测的多维数据也都可以在C中使用1维指针接收,比如有以下函数:

Void write(svBitVecVal* data){

}

SV中可以为:

Import “DPI-C” function void write(bit[127:0] data[16][16]);

这样在C中读写data数据的时候就需要通过指针来确认数据位置。指针指向了数据data的第一个32bit数据,即data[0][0][31:0],之后数据往后增加指针即可得到。

对于unpacked的数组数据,在C中可以使用指针直接访问,但是在packed中的数据,却只允许使用定义的函数来读写。这些函数有:

svBit svGetSelectBit(const svBitPackedArrRef s, int i);

svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i);

void svPutSelectBit(svBitPackedArrRef d, int i, svBit s);

void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s);

/* canonical

void svGetPartSelectBit(svBitVec32* d, const svBitPackedArrRef s, int i,

int w);

svBitVec32 svGetBits(const svBitPackedArrRef s, int i, int w);

svBitVec32 svGet32Bits(const svBitPackedArrRef s, int i); // 32-bits

unsigned long long svGet64Bits(const svBitPackedArrRef s, int i); // 64-bits

void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s, int i,

int w);

/* actual

void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s, int i,

int w);

void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s, int i,

int w);

除了可以向C中传递固定维度数组,还可以传递不固定维度数组,即动态数据。在C中通过svOpenArrayHandle来获取这些数据,这些数据的操作也需要通过一些函数,不能直接操作。比如以下函数可以获得动态数组的位置:

int svLeft(const svOpenArrayHandle h, int d);

int svRight(const svOpenArrayHandle h, int d);

int svLow(const svOpenArrayHandle h, int d);

int svHigh(const svOpenArrayHandle h, int d);

比如定义一个数组bit[3:0] data[3:9],那么

svLeft(data, 1)是3,svRight(data, 1)是9。

在SV中有如下形式:

Import “DPI-C” function void write(bit[3:0] data[])

C中为:

Void write(svOpenArrayHandle data)

47004b7021a7e34fd0ed1f99ae9d5a0b.png
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值