
Passing Structure Example
DPI allows to pass the structs and Unions . This can be done by passing pointers or by packing.
In the following example, a "struct" is passed from SystemVerilog to C and also from C to Systemverilog using import and export functions.
While passing the "struct" data type, the data is packed in to array and passed from SV to C and then the array is decoded back to Struct in C. The same when the Struct is passed from C to SystemVerilog.
CODE: C_file.c
#include "stdio.h"
#include "vc_hdrs.h"
#include "svdpi.h"
extern "C" {
typedef struct{
int a;
int b;
char c;
} C_struct;
extern void export_func(svBitVec32 x[3] );
void import_func()
{
C_struct s_data;
unsigned int arr[3];
s_data.a = 51;
s_data.b = 242;
s_data.c = 35;
printf( "C : s_data.a = %d\n", s_data.a );
printf( "C : s_data.b = %d\n", s_data.b );
printf( "C : s_data.c = %d\n\n", s_data.c );
arr[0] = s_data.a ;
arr[1] = s_data.b ;
arr[2] = s_data.c ;
export_func(arr);
}
}
CODE: SV_file.sv
program main;
export "DPI-C" function export_func;
import "DPI-C" function void import_func();
typedef struct packed{
int a;
int b;
byte c;
} SV_struct;
function void export_func(input int arr[3]);
SV_struct s_data;
s_data.a = arr[0];
s_data.b = arr[1];
s_data.c = arr[2];
$display("SV: s_data.a = %0d", s_data.a );
$display("SV: s_data.b = %0d", s_data.b );
$display("SV: s_data.c = %0d \n", s_data.c );
endfunction
initial
begin
import_func();
end
endprogram
RESULTS:
C : s_data.a = 51
C : s_data.b = 242
C : s_data.c = 35
SV: s_data.a = 51
SV: s_data.b = 242
SV: s_data.c = 35
Passing Openarray Structs
CODE: C_file.c
#include "svdpi.h"
typedef struct {int p; int q} PkdStru;
void send2c(const svOpenArrayHandle dyn_arr)
{
int i;
PkdStru Sele;
printf("\n \n Array Left %d, Array Right %d \n\n", svLeft(dyn_arr,1), svRight(dyn_arr, 1) );
for (i= svLeft(dyn_arr,1); i <= svRight(dyn_arr,1); i++) {
Sele = *(PkdStru*)svGetArrElemPtr1(dyn_arr, i);
printf("C : %d : [%d,%d]\n",i, Sele.q,Sele.p );
}
printf("\n\n");
}
CODE: SV_file.sv
program open_array_struct ();
typedef struct packed { int p; int q; } PkdStru;
import "DPI-C" function void send2c (input PkdStru arr []);
PkdStru arr_data [0:4];
initial begin
foreach (arr_data[i]) begin
arr_data[i] = {$random,$random};
$display("SV: %0d : [%0d,%0d]",i,arr_data[i].p,arr_data[i].q);
end
send2c(arr_data);
end
endprogram
RESULTS:
SV: 0 : [303379748,-1064739199]
SV: 1 : [-2071669239,-1309649309]
SV: 2 : [112818957,1189058957]
SV: 3 : [-1295874971,-1992863214]
SV: 4 : [15983361,114806029]
Array Left 0, Array Right 4
C : 0 : [303379748,-1064739199]
C : 1 : [-2071669239,-1309649309]
C : 2 : [112818957,1189058957]
C : 3 : [-1295874971,-1992863214]
C : 4 : [15983361,114806029]
Passing Union Example
CODE:SV_file
module m;
typedef bit [2:0] A;
typedef union packed { A a; S s; } U;
U u;
A a;
// Import function takes three arguments
import "DPI-C" function void foo8(input A fa, input U fu);
initial begin
a = 3'b100;
u.a = 3'b100;
foo8(a, u);
end
endmodule
CODE:C_file
#include "svdpi.h"
void foo8(
const svBitVecVal* fa,
const svBitVecVal* fu)
{
printf("fa is %d, fu is %d\n", *fa, *fu);
}