systemverilog中的DPI-C用例介绍


前言

本文主要基于VCS内置的三个关于DPI-C的使用用例,记录一下DPI-C的使用方法。测试用例的路径为$VCS_HOME/doc/examples/testbench/sv/。测试用例包括:dpi_longint,dpi_packed_array,dpi_structure。


一、dpi_longint

这个例子主要介绍,利用DPI-C,在C代码中,修改SV中一个长整型的数据。在SV中,利用DPI-C,将长整型数据,通过指针传递到C函数中,并在C函数中进行修改打印,返回到SV时,数据已经被C修改。

如下为SV代码。

program p1;
	longint i1;
	
	import "DPI" function void mydisplay(inout longint i1);
	initial begin
		i1=64'h1234_5678_9abc_def0;
		$display("SV: i1 is %0h",i1);
		mydisplay(i1);
		$display("SV(after DPI call): i1 is %0h",i1);
	end

endprogram

如下为C代码,函数的参数为指针类型,利用指针实现C代码与SV代码共享内存空间,从而实现C代码中,修改SV代码中的变量。

#include "svdpi.h"
#include "vcsuser.h"

extern "C" {
	void mydisplay(long long *i1) {
		io_printf("C: size of long long is %0d bytes\n",sizeof(long long));
		io_printf("C: i1 is %llx\n",*i1);
		(*i1) = (*i1) * 2;	
		io_printf("C: change i1 to %llx\n",*i1);
		
	}
}

如下为仿真log,可以看到C代码中修改值后,回到SV中,该变量的值也发生了改变。

SV: i1 is 123456789abcdef0
C: size of long long is 8 bytes
C: i1 is 123456789abcdef0
C: change i1 to 2468acf13579bde0
SV(after DPI call): i1 is 2468acf13579bde0

二、dpi_packed_array

这个例子主要演示,将SV中的数组传递给C,并在C中进行使用。

下面为SV代码,对数组a进行初始化并打印,然后将a传递给C。

program p1;
	import "DPI" function void mydisplay(input bit[4:2] a[]);
	bit[4:2] a[8];

	initial begin
		for(int i=0;i<8;i++) a[i]= 15+i;
		for(int i=0;i<8;i++) $display("SV: a[%0d]=%0d",i,a[i]);
		mydisplay(a);
		
	end


endprogram

如下为C代码,利用svOpenArrayHandle接收SV传递过来的数组,通过svLow获取数组的最低索引,通过svHigh获取数组的最高索引,然后通过svGetBitArrElemVec32获取数组里边的值,并循环打印该数组。

#include "vcsuser.h"
#include "svdpi.h"

extern "C" {

	void mydisplay(const svOpenArrayHandle a) {
		
		svBitVec32 c;

		int low = svLow(a,1);
		int high = svHigh(a,1);

		for(int i=low;i<=high;i++) {
			svGetBitArrElemVec32(&c,a,i);
			io_printf("C: a[%d]=%d\n",i,c);
		}
	}
}

如下为仿真结果。

SV: a[0]=7
SV: a[1]=0
SV: a[2]=1
SV: a[3]=2
SV: a[4]=3
SV: a[5]=4
SV: a[6]=5
SV: a[7]=6
C: a[0]=7
C: a[1]=0
C: a[2]=1
C: a[3]=2
C: a[4]=3
C: a[5]=4
C: a[6]=5
C: a[7]=6

三、dpi_structure

这个例子主要演示SV中的结构体,如何通过DPI-C传递到C代码中进行修改。

以下是SV代码,对SV中的结构体初始化打印后,传递给C。

program p1;
	typedef struct {
		int a;
		int b;
	} mystruct;

	import "DPI" function void mydisplay(inout mystruct s1);
	mystruct s1;
	initial begin
		s1.a =10;
		s1.b =20;
		$display("SV: s1.a=%0d,s1.b=%0d",s1.a,s1.b);

		mydisplay(s1);
		$display("SV after DPI call: s1.a=%0d,s1.b=%0d",s1.a,s1.b);
	end 
	
endprogram

以下是C代码,参数传递是结构体指针。

#include "stdio.h"
#include "svdpi.h"

extern "C" {

	typedef struct {
		int a;
		int b;
	}  mystruct;

	void mydisplay(mystruct *s1) {
		int s2;
		printf("C: gets values from SV, s1.a=%d, s1.b=%d\n",s1->a,s1->b);
		s1->a = 100;
		s1->b = 200;
		printf("C: set values,  s1.a=%d, s1.b=%d\n",s1->a,s1->b);
	}	
}

仿真结果如下:

SV: s1.a=10,s1.b=20
C: gets values from SV, s1.a=10, s1.b=20
C: set values,  s1.a=100, s1.b=200
SV after DPI call: s1.a=100,s1.b=200

四、相关参考

SV和C之间的参数索引表
SV和C之间的参数索引表
4状态类型SV与C之间的对应关系
4状态类型SV与C之间的对应关系

C中提供的队列访问函数。
在这里插入图片描述
在这里插入图片描述


总结

本文主要通过VCS自带的三个DPI-C测试用例,记录一下SV中DPI-C的使用方法。

DPI-C(Direct Programming Interface - C)处理复杂数据类型如struct,需要遵循一些特定的规则来确保数据能够在SystemVerilog和C之间正确传递。以下是处理这些复杂数据类型的步骤: 1. 定义C语言的结构体(struct): 首先在C语言代码定义你需要传递的数据结构。这个结构体应该包含所有需要在SystemVerilog和C之间传递的数据。 ```c // C语言的结构体定义 typedef struct { int a; float b; char c; } complex_data_t; ``` 2. 在SystemVerilog声明DPI函数和数据类型: 接着在SystemVerilog代码,你需要声明一个C语言函数,这个函数将使用之前定义的结构体。同时,你也需要在SystemVerilog声明一个与C语言结构体对应的数据类型。 ```systemverilog // SystemVerilog声明DPI函数和数据类型 import "DPI-C" context function void process_complex_data(input complex_data_t c_data, output complex_data_t result); typedef struct { int a; real b; string c; } complex_data_t; // 注意SystemVerilog的数据类型可能需要根据C语言的结构体进行调整 ``` 3. 在C函数处理数据: 在C代码,你需要编写处理输入数据并返回结果的函数。在调用这个函数之前,通常需要将SystemVerilog的数据类型转换成C的结构体类型。 ```c // C语言对应的函数实现 void process_complex_data(complex_data_t c_data, complex_data_t *result) { // 在这里处理数据 result->a = c_data.a; result->b = c_data.b; // 注意SystemVerilog的real可能需要转换成C的float或double // string类型在SystemVerilog不直接支持,可能需要使用字符数组处理 strcpy(result->c, c_data.c); } ``` 4. 从SystemVerilog调用C函数: 最后,你可以在SystemVerilog调用这个函数,并传递结构体数据。 ```systemverilog // SystemVerilog调用C函数 complex_data_t sv_data = {1, 2.0, "string"}; complex_data_t result; process_complex_data(sv_data, result); ``` 在编写代码时,需要特别注意数据类型在SystemVerilog和C之间的对应和转换,以确保数据的正确传递。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值