Systemverilog Systemverilog Dpi: (Direct Programming Interface)
Systemverilog Systemverilog Dpi: (Direct Programming Interface)
DPI
(Direct Programming Interface)
VCS 2006.06-SP2-2
Synopsys Global Technical Services
© 2008 Synopsys, Inc. All Rights Reserved, VeriSilicon Only
May not be disclosed to any 3rd party without written Synopsys consent
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
DirectC
Proprietary VCS I/F
Why DPI?
SystemVerilog users have C/C++ in designs and testbench
that they want to reuse
DPI easily connects C/C++ code to SV without the overhead or
complexity of VPI/PLI
Support both functions and tasks
SystemVerilog can call C and C can call SV
Export "DPI-C"
C calls SystemVerilog functions or blocking tasks
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Imported tasks and functions can have zero or more input, output
and inout arguments. ref is not allowed.
import "DPI-C" function void myInit();
Input argument
Small values of formal input arguments passed by value
int -> int, bit -> unsigned char
Other types (bit[7:0]) are passed by reference
Inout and output arguments passed by reference
Open arrays are always passed by a handle
Shown in next section
Protection
It’s up to the C code to not modify input parameters
Use const to double check your C code
Common mistake – forgetting argument direction
import "DPI-C" function void bug(int out);
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 12
A 32-bit 2-State Counter
program automatic test;
bit [6:0] out, in;
bit load;
import "DPI-C" function void count32(output int o,
input int i,
input bit load);
initial begin
in = 42; load = 1;
count32(out, in, load); // Load counter
$di l ( t)
$display(out);
load = 0; #include <svdpi.h>
count32(out, in, load);#include "vc_hdrs.h"
// Increment
$display(out); void count32(int *o,
const int i,
end
const unsigned char load) {
endprogram static unsigned char count;
if (load) count = i; // Load
What happens when else count++; // Increment
this is instantiated *o = count; // Copy to output
}
more than once?
svBit svBit*
byte char char* bit
(unsigned char) (unsigned char)
shortint short int short int* logic, reg svLogic svLogic*
SV: z 00000101
void show(const svLogic s, C: scalar is 2
const svLogicVecVal *vec) { C: i=101/0
io_printf("C: scalar is %x\n",s);
io_printf("C: vec=%x/%x\n", vec->aval, vec->bval); SV: x 0000zzxx
} C: scalar is 3
C: i=ff/ffff
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 18
Passing a Logic Vector > 32 bits
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
typedef struct {
int a; int b;
} mystruct;
void disp_s(mystruct *s1) {
io_printf("s1.a is %d, s1.b is %d\n",s1->a,s1->b);
}
void replace(char** s) {
strcpy(s, "Life"); // Copy of shorter string OK
io_printf("C: %s '%s'\n", __FUNCTION__, *s);
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 26
SystemVerilog Storage: Under the Hood
31:8 7:0
All values are stored in 32-bit words
A SystemVerilog byte wastes ¾ of space
So a C char array does NOT map to a SystemVerilog
unpacked array of bytes
Don’t try to use SystemVerilog string as a null value will
t
terminate
i t theth string
ti
Make a packed array of bytes or int array
import “DPI-C” task t(input int int_array[100]);
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Note:
1. If the dimension is 0, then the query refers to the packed
part (which is one-dimensional) of an array. Dimensions > 0
refer to the unpacked part of an array.
2. int a[15:0] -> svIncrement(a,1)=1
int a[0:15] -> svIncrement(a,1)=-1
SV: a[0]=0
void disp(svOpenArrayHandle h) { SV: a[1]=1
int *a, i, size; SV: a[2]=2
size = svSize(h, 1);
a = (int*)svGetArrayPtr(h); C: a[0]=0
for(i=0;i<size;i++) { C: a[1]=1
io_printf("C: a[%d]=%d\n",i,a[i]); C: a[2]=2
a[i] = size-i;
} SV after DPI: a[0]=3
} SV after DPI: a[1]=2
SV after DPI: a[2]=1
void
id disp4(svOpenArrayHandle
di ( dl a)) {
svBit c; C: Incr=1
int low = svLow(a,1); C: a[2]=0
int high = svHigh(a,1), i; C: a[3]=1
io_printf("C: Incr=%d\n",svIncrement(a,1)); C: a[4]=0
for(i=low;i<=high;i++) { C: a[5]=1
c = svGetBitArrElem(a,i);
io_printf("C: a[%d]=%d\n",i,c);
}
}
void disp5(svOpenArrayHandle a) {
svBitVecVal c;
int low = svLow(a,1); a[0]=7
int high = svHigh(a,1), i; a[1]=0
for(i=low;i<=high;i++) { a[2]=1
svGetBitArrElem1VecVal(&c,a,i); a[3]=2
io_printf("a[%d]=%d\n",i,c); a[4]=3
} a[5]=4
for(i=low;i<=high;i++) { a[6]=5
c=i; a[7]=6
svPutBitArrElem1VecVal(a,&c,i);
}
}
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
svScope svGetScope();
svScope svSetScope(const svScope scope);
const char* svGetNameFromScope(const svScope);
svScope svGetScopeFromName(const char* scopeName);
module m1;
import "DPI-C" context function void c_display();
export "DPI-C" task sv_display;
initial c_display(); extern int sv_display();
task sv_display();
$display("SV: m1"); void c_display() {
endtask io_printf("\nC: c_display\n");
endmodule sv_display();
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 43
Setting Context Explicitly
module top;
import "DPI-C" context function void c_display();
export "DPI-C" task sv_display;
m1 m1_inst(); C: c_display
initial #1 c_display();
SV: m1
task sv_display(); // Never used!
$display("SV: top");
endtask C: c_display
endmodule SV: m1
module m1;
import "DPI-C" context function void c_display();
import "DPI-C" context function void mygetscope();
export "DPI-C" task sv_display;
initial begin extern int sv_display();
mygetscope(); svScope myscope;
c_display();
end void mygetscope() {
task sv_display(); myscope = svGetScope();
$display("SV: m1"); }
endtask
endmodule
void c_display() {
svSetScope(myscope);
io_printf("\nC: c_display\n");
sv_display();
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 44
Calling an Exported Task from Context
module m1;
task delay(output int t);
#10; t = $stime;
endtask
Note: blocking DPI task can only be called from context import DPI task
Dyn dq[$];
import
p "DPI-C" context function void c_fcn(int i);
;
initial begin
Dyn d_obj;
d_obj = new(); // Construct obj
dq.push_back(d_obj); // Put in queue
c_fcn(dq.size()-1); // Call C with index
end extern void sv_static(int i);
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
gdb or ddd
Attach gdb to running simv at T=0 “gdb –p <pid>”
Set breakpoints and watchpoints
Valgrind (www.valgrind.org) for Linux
Invalid memory reads/writes
Memory leaks
Purify
Memory leak / corruption detection
SystemVerilog examples:
$VCS_HOME/doc/examples/sv/dpi/
Directory contains following two subdirectories:
export_fun – DPI export function for SV
import_fun – DPI import function for SV
Memory management
TF routines that should not called in DPI
VCS and the LRM
Difference between DPI and DPI-C
In VCS 2006.06
SystemVerilog structures are only supported in import
DPI as inout/output argument until 2006.06-SP1
VCS 2008.03 will support a majority of the DPI
See release notes for more info
Note that the SystemVerilog LRM has changed
significantly between 2005 and 2009
DPI-C: xxxxxVecVal
svPutBitArrElemVecVal
DPI-C
svBitVecVal /* (a chunk of) packed bit array */
typedef uint32_t svBitVecVal;
svLogicVecVal