SystemVerilog
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
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 2
Introduction: C Integration Support
DPI
SystemVerilog Standard to
connect foreign-languages NTB-OV
Does not replace PLI/VPI or
Restricted Data Types NTB-SV
Little Access to Sim Database
Faster & Easier than PLI
Verilog/SV C/C++
DUT
PLI/VPI (Model)
IEEE simulation API
Waveform dump
Netlist analysis SystemC
Model
DirectC
Proprietary VCS I/F
For legacy Code. DPI for new VCSMX
applications
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 3
DPI: Direct Programming Interface
An interface between SystemVerilog and a foreign
programming language: C or C++
Simple interface to C models
Allows SystemVerilog to call a C function just like any other
native SystemVerilog function/task
Variables passed directly to/from C/C++
NO need to write PLI-like applications/wrappers
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 4
Quick Example: Import task from C
Import "DPI-C"
SystemVerilog calling C/C++ task
C code must have:
#include <svdpi.h>
// SystemVerilog code
program automatic test;
import "DPI-C" context task c_test(input int addr);
initial c_test(1000); // C code
#include <svdpi.h>
endprogram
void c_test(int addr) {
...
}
> vcs –R –sverilog top.sv c_test.c
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 5
Quick Example : Export SV Task to C
Export "DPI-C"
C calls SystemVerilog functions or blocking tasks
program automatic test;
import "DPI-C" context task c_test(input int addr);
initial c_test(1000);
c test(1000);
#include
#i l d <svdpi.h>
d i h
export "DPI-C" task apb_write; extern void apb_write(int, int);
task apb_write(input int addr, data);void c_test(int addr) {
... @(posedge ready); ... ...
endtask apb_write(addr, data);
endprogram ...
}
> vcs –sverilog top.sv c_test.c
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 6
DPI vs. TLI
TLI
Transaction Level Interface in VCS for SystemC-
SystemVerilog transaction level co-simulation
SystemC calling SystemVerilog interface functions/tasks for
class methods
SystemVerilog call SystemC interface methods
Blocking or non-blocking
Under the hood, TLI is implemented with DPI
But easier to use
Automatically synchronizes between the SystemC domain and
SystemVerilog
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 7
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 8
Importing a C routine into SystemVerilog
Before you can use a C routine in SystemVerilog,
you must import it
This declares the C routine in the current scope
Now you can call the C routine as if it were a
SystemVerilog task or function
SystemVerilog data types are passed through the
argument list and mapped into equivalent C
structures
If a C routine calls back into SystemVerilog, it
should be declared as a task, otherwise a function
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 9
Declaration of Imported Functions and Tasks
An imported task or function can be declared anywhere a native SV
function or task can be declared
import "DPI-C" pure function real sin(input real r); // math.h
Imported tasks and functions can have zero or more input, output
and inout arguments. ref is not allowed.
import "DPI-C" function void myInit();
Imported tasks always return a void value
Imported functions can return a “small” value or be a void function
void, byte, shortint, int, longint, real, shortreal, chandle, and string
Scalar values of type bit and logic
import "DPI-C" function int getStim(input string fname);
Map C routine name if it conflicts with existing SystemVerilog name
// Map the C routine “test” to “c_test” in SystemVerilog.
import "DPI-C" test = task c_test();
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 10
Argument Passing
Map arguments between SystemVerilog and C
Recommendation: use int whenever possible!
It is your responsibility to correctly declare compatible data
types
The DPI does not check for type compatibility
VCS produces vc_hdrs.h when you compile
Use it as a guide to see how types are mapped
Argument directions
input Input to C code
output Output from C code (initial value undefined)
inout Input and Output from C code
ref Not supported by LRM. Use inout instead
Function return types (<32b)
(unsigned) int, char*
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 11
Argument Direction
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?
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 13
Type mapping
Argument Data Type Mapping
Unpacked SystemVerilog types have a C-compatible
representation.
SystemVerilog C (input) C (out/inout) SystemVerilog C (input) C (out/inout)
svBit svBit*
byte char char* bit
(unsigned char) (unsigned char)
shortint short int short int* logic, reg svLogic svLogic*
int int int* bit[N:0] const svBitVecVal* svBitVecVal*
longint long int long int* reg[N:0] const
svLogicVecVal*
logic[N:0] svLogicVecVal*
shortreal float float* Open array[ ] const
svOpenArrayHandle
(import only) svOpenArrayHandle
real double double*
chandle const void* void*
string const char* char**
string[n] const char** char**
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 14
A 7-bit 2-State Counter
program automatic test;
bit [6:0] out, in;
bit load;
import "DPI-C" function void count7(output bit [6:0] o,
input bit [6:0] i,
input bit load);
initial begin
in = 42; load = 1; Structure
count7(out, in, load); // Load counter passed
$di l ( t)
$display(out); by ref
load = 0; void count7(svBitVecVal *o,
const svBitVecVal *i,
count7(out, in, load); // Increment
$display(out); const svBit load) {
static unsigned char count;
end
if (load) count = *i; // Load
endprogram else count++; // Increment
count &= 0x7f; // Mask bits
What happens when *o = count; // Copy to output
this is instantiated }
more than once?
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 15
Type Mapping - Packed types
Packed types are stored with the canonical format:
bit -> svBitVecVal, logic -> svLogicVecVal
A packed array is represented as an array of one or
more elements
Type svBitVecVal for 2-state and svLogicVecVal for 4-state
Each element is stored as a group of 32 bits.
The first element of an array contains the 32 LSBs
LSBs, next
element contains the 32 more significant bits, and so on.
C macro SV_PACKED_DATA_NELEMS(width)
Convert from bits to number of elements
typedef unsigned int svBitVecVal; /* (a chunk of) packed bit array */
typedef struct { unsigned int aval;
unsigned int bval;} svLogicVecVal;
/* (a chunk of) packed logic array */
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 16
Passing a Bit Vectors with Odd Sizes
program automatic test;
int eq32; // length = 32
bit [27:0] lt32; // length < 32 a is 10
bit [35:0] gt32; // length > 32 b is 123456
import "DPI-C" function void disp3 c[0] is 23456789
(input int x, y, bit[35:0] z); c[1] is 1
initial begin
eq32 = 10;
lt32 = 28'h12_3456;
gt32 = 36
36'h1
h1_2345_6789;
2345 6789;
disp3(eq32, lt32, gt32); C macro to
end convert from
endprogram bits to elements
#include <svdpi.h>
#include <veriuser.h>
#include “vc_hdrs.h”
void disp3(int a, int b,
svBitVecVal c[SV_PACKED_DATA_NELEMS(36)]) {
io_printf("a is %d\n",a);
io_printf("b is %x\n",b); io_printf prints to
io_printf("c[0] is %x\n",c[0]); stdout & VCS log
io_printf("c[1] is %x\n",c[1]); }
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 17
Passing 4-state Values
program automatic test;
logic scalar;
logic [31:0] vec;
import "DPI-C" function void show(input logic s,
input logic [31:0] i);
initial begin C:
System C: svLogicVecVal
scalar = ’z; vec = 32'h0000_0101; vector
$display("SV: %h %h", scalar, vec); Verilog svLogic
Data Control
show(scalar, vec); Scalar aval bval
0 0 0 0
scalar = ’x; vec = 32'h0000_zzxx; 1 1 1 0
$display("SV: %h %h", scalar, vec); Z 2 0 1
show(scalar, vec); X 3 1 1
end 4-state value map
endprogram
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
program automatic test;
logic[63:0] c;
import "DPI-C" function void disp64(input logic[63:0] c);
initial begin
c = 64'hzzzzzzzz_CafeDada;
$display("SV: c=%h", c);
disp64(c);
end
endprogram
d
void disp64(const svLogicVecVal c[2]) {
io_printf("C: c=%08x_%08x\n", c[31:0].aval
cafedada
c[0].aval, c[1].aval);
} c[31:0].bval
0
c[63:32].aval
SV: c=zzzzzzzzcafedada 0
C: c=0_cafedada c[63:32].bval
ffffffff
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 19
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 20
Passing a Fixed-Sized Array
If you use int type, it is very easy to pass arrays
program automatic test;
int a[4][4];
import "DPI-C" function void disp(input int a[4][4]);
initial begin
foreach (a[i,j])
j
a[i][j] = i+j;
disp(a);
end
endprogram
void disp(const int a[4][4]) {
int i, j;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
io_printf("C: a[%d][%d]=%d\n", i, j, a[i][j]);
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 21
Passing a Logic Array
program automatic test; a[0][31:0].aval
logic [63:0] a[2]; a[0][31:0].bval
import "DPI-C" function void arr( a[0][63:32].aval
input logic a[2]);
initial begin a[0][63:32].bval
a[0] = 64’h12345678_ABCDEF0; a[1][31:0].aval
a[1] = ’z;
a[1][31:0].bval
arr(a);
end a[1][63:32].aval
endprogram a[1][63:32].bval
void arr(const svLogicVecVal *a[4]){
int i;
for(i=0;i<2;i++)
io_printf(“C: a[%0d]=%08x_%08x\n",
i, a[i*2+1].aval, a[i*2].aval);
}
C: a[0]=12345678_abcdef0
C: a[1]=00000000_0000000
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 22
Passing a Structure
program automatic test;
typedef struct {
int a; int b;
} mystruct;
import "DPI-C" function void disp_s(inout mystruct s1);
mystruct s1;
initial begin
s1.a = 10;
s1.b = 20;
disp_s(s1);
end
endprogram
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);
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 23
Passing a Packed Structure of Bytes
program automatic test;
typedef struct packed {bit [7:0] r, g, b;} RGB;
import "DPI-C" function void disp_p(input RGB p);
initial begin
RGB pixel;
pixel.r=1; pixel.g=2; pixel.b=3;
disp_p(pixel);
end
endprogram
Be careful about big-endian (x86) vs.
little endian (Sparc) byte order issues
typedef struct {
unsigned char b, g, r; // x86 big-endian
} *p_rgb;
void disp_p(p_rgb pixel) { pixel: 1,2,3
io_printf("pixel: %x,%x,%x\n",
pixel->r, pixel->g, pixel->b);
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 24
Mapping Word Ranges Between Languages
Recommendation: Use arrays with LSB=0
int two_val[99:0], one_val[100];
The natural order of elements for each dimension in the layout
of an unpacked array is used
C index 0 SV index min(L,R)
C index abs(L-R) SV index max(L,R)
SystemVerilog: a[2:8] C: a[7]
SystemVerilog: a[2] C: a[0], SystemVerilog: a[8] C: a[6]
Packed arrays are treated as one-dimensional
An packed array with dimension size (i,j,k) is treated as
single dimension of size(i*j*k)
One bit in SV myarray[l][m][n] C: myarray(n+m*k+l*j*k)
A packed array of [L:R] is normalized as [abs(L-R):0]
bit[5:2] a a[5]=1 a[4]=0 a[3]=1 a[2]=0 C a=10
bit[2:5] a a[5]=1 a[4]=0 a[3]=1 a[2]=0 C a=5
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 25
Passing a String
SystemVerilog strings are dynamically allocated
Don’t change pointer on C side
program automatic test;
import "DPI-C" function void display(input string s);
import "DPI-C" function void replace(inout string s);
initial begin
string s = “Forty-two"; C: display 'Forty-two'
di l ( )
display(s); C: replace 'Life'
replace(s); SV: 'Life'
$display("SV: '%s'", s);
end
endprogram
void display(const char* s) {
io_printf("C: %s '%s'\n", __FUNCTION__, s);
}
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]);
void display(const int ia[10]) {
char* ba; // Byte array
ba = (char*) ia;
...
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 27
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 28
Open Array
Open arrays allow generic code to handle different
size arrays. The size of the dimension (packed or
unpacked) is unspecified: []
import "DPI-C" function void foo(input int i [][]);
/* 2-dimensional unsized unpacked array of int */
int a_10x5 [11:20][6:2];
int a_64x8 [64:1][1:8];
foo(a 10x5);
foo(a_10x5);
Not a
foo(a_64x8);
dynamic
array
Open arrays limited to a single packed dimension
C code accesses an open array and its elements
through system query and access functions
Open arrays only work with imported methods, not
exported methods
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 29
Open Array querying functions
/* h= handle to open array, d=dimension */
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);
int svIncrement(const svOpenArrayHandle h, int d);
int svSize(const svOpenArrayHandle h, int d);
int svDimensions(const svOpenArrayHandle h);
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 30
Access functions
/* A pointer to the actual representation of the whole array of any type */
/* NULL if not in C layout */
void *svGetArrayPtr(const svOpenArrayHandle);
/* Total size in bytes or 0 if not in C layout */
/* Return a pointer to an element of the array or NULL if index outside the
range or null pointer */
int svSizeOfArray(const svOpenArrayHandle);
void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...);
/* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1);
void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2);
void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2, int indx3)
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 31
Simple Open Array
program automatic test;
int a[3];
import "DPI-C" function void disp(inout int h[]);
initial begin
foreach(a[i]) a[i]=i;
foreach(a[i]) $display("SV: a[%0d]=%0d",i,a[i]);
disp(a);
foreach(a[i]) $display("SV after DPI: a[%0d]=%0d",i,a[i]);
end
endprogram
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 32
An Open Array with Multiple Dimensions
program automatic test; SV: a[6][2]=8
int a[6:4][2:3]; SV: a[6][3]=9
import "DPI-C" function void disp2(inout int h[][]); SV: a[5][2]=7
initial begin SV: a[5][3]=8
foreach(a[i,j]) a[i][j]= i+j;
foreach(a[i,j])
SV: a[4][2]=6
$display(“[%0d,%0d]=%0d”,i,j,a[i][j]); SV: a[4][3]=7
disp2(a);
foreach(a[i,j]) C: a[4][2]=6
$display(“[%0d,%0d]=%0d”,i,j,a[i][j]); C: a[4][3]=7
end
d C: a[5][2]=7
endprogram C: a[5][3]=8
C: a[6][2]=8
void disp2(svOpenArrayHandle h) {
C: a[6][3]=9
int *a, // Pointer so you can modify array
i, j;
for(i=svLow(h,1); i<=svHigh(h,1); i++) SV: a[6][2]=12
for(j=svLow(h,2); j<=svHigh(h,2); j++) { SV: a[6][3]=18
a = (int*)svGetArrElemPtr2(h,i,j); SV: a[5][2]=10
io_printf("C: a[%d][%d]=%d\n",i,j,*a); SV: a[5][3]=15
*a = i*j; SV: a[4][2]=8
} SV: a[4][3]=12
}
...
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 33
An Open Array of Bit Elements
program automatic test;
import "DPI-C" function void disp3(input bit[2:0] a[]);
bit[2:0] a[8];
initial begin
foreach(a[i]) a[i] = 15+i;
foreach(a[i]) $display("SV: a[%0d]=%0d",i, a[i]);
disp3(a); SV: a[0]=7
end SV: a[1]=0
endprogram SV: a[2]=1
SV: a[3]=2
SV: a[4]=3
void disp3(const svOpenArrayHandle a) { SV: a[5]=4
svBitVecVal c; SV: a[6]=5
int low = svLow(a,1); SV: a[7]=6
int high = svHigh(a,1), i; C: a[0]=7
for(i=low; i<=high; i++) { C: a[1]=0
C: a[2]=1
svGetBitArrElemVecVal(&c,a,i);
C: a[3]=2
io_printf("C: a[%d]=%d\n",i,c); C: a[4]=3
} C: a[5]=4
} C: a[6]=5
C: a[7]=6
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 34
An Open Array of Single Bits
program automatic test;
import "DPI-C" function void disp4(bit a[]);
bit a[5:2]; // 4 elements, one-bit each
initial begin
foreach(a[i]) a[i] = i;
disp4(a);
end
endprogram
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);
}
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 35
Canonical Open Array
program automatic test;
import "DPI-C" function void disp5(inout bit [2:0] a[]);
bit[2:0] a[8];
initial begin
for(int i=0;i<8;i++) a[i]= 15+i; // Wrap around 8
disp5(a);
end
endprogram
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);
}
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 36
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 37
Quick Example : Export SV Task to C
SystemVerilog call C methods, which can call back into
SystemVerilog
Every thread must have its own stack so it can be called
concurrently. Use context in import declaration
program automatic test;
import "DPI-C"
DPI C context
ontext task c_test(input
test(input int addr);
initial c_test(1000);
#include <svdpi.h>
export "DPI-C" task apb_write; extern void apb_write(int, int);
task apb_write(input int addr, data);void c_test(int addr) {
... @(posedge ready); ... ...
endtask apb_write(addr, data);
...
initial }
another_thread();
endprogram
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 38
Declaration of Exported Functions and Tasks
An exported task or function can be declared anywhere a
native SV function or task can be declared
An exported task or function declaration has only the routine
name. There are no arguments or return type.
This is a very common coding mistake
export "DPI-C" function my_func; // No return type,
export "DPI-C" task my_task; // args, or even ()
Map SystemVerilog method name if it conflicts with existing C
name
// Map your SystemVerilog function “fread” to “sv_fread” in C
export "DPI-C" sv_fread = function fread;
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 39
Context Tasks and Functions
Context imported tasks and functions
A DPI imported method might need to access or modify
simulator data structures using PLI or VPI calls or call back into
SystemVerilog with an exported task or function.
Extra info is saved when calling a context method, slowing
down the call compared to calling a non-context method
By
y default imported
p tasks and functions are non-context
Shall not access any data objects from SystemVerilog other
than its actual arguments. Only the actual arguments can be
affected (read or written) by its call
Not a barrier for simulator optimizations.
The effects of calling PLI or VPI functions or SystemVerilog
tasks or functions are unpredictable and can crash
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 40
Exported Functions and Tasks Declaration
Export functions/tasks are always context
If an imported task calls an exported task, the import must be
context
Class member functions/tasks cannot be exported, but all
other SystemVerilog functions/tasks can be exported.
Work-around shown in a later slide
Multiple export declarations are allowed with the same
identifier,, explicit
p or implicit,
p , as long
g as they
y are in different
scopes and have the equivalent type signature
Multiple export declarations with the same c_identifier in the same
scope are forbidden.
SystemVerilog tasks do not have return value types. The return value
of an exported task is an int value that indicates if a disable is active
or not on the current execution thread.
It is not legal to call an exported task from an imported
function. Tasks must be called from a task.
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 41
Context Tasks and Functions
There is an implicit scope for context tasks and functions
The scope of the import declaration statement
Only tasks or functions defined and exported from the same
scope as the import can be called directly.
To call any other exported SystemVerilog tasks or functions,
the imported task or function must modify its current scope
The following functions allow you to retrieve and manipulate
the current operational scope.
You can only call these from a context imported method
svScope svGetScope();
svScope svSetScope(const svScope scope);
const char* svGetNameFromScope(const svScope);
svScope svGetScopeFromName(const char* scopeName);
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 42
SystemVerilog Code with Two Contexts
module top;
import "DPI-C" context function void c_display();
export "DPI-C" task sv_display;
m1 m1_inst();
initial #1 c_display(); C: c_display
task sv_display(); SV: m1
$display("SV: top");
endtask C: c_display
endmodule SV: top
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
export "DPI-C" task delay;
import "DPI-C" context task dodelay(output int t);
int myt;
initial begin
dodelay(myt);
end
endmodule extern int delay(int *t);
int dodelay(int *t) {
delay(t);
io_printf("t is %d\n",*t);
}
Note: blocking DPI task can only be called from context import DPI task
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 45
Calling Task in a Dynamic Object
program automatic test;
class Dyn;
function void stuff(int i);
$display("In %m, i=%0d", i);
endfunction
endclass
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);
export "DPI-C" function sv_static; void c_fcn(int i) {
function void sv_static(int idx); io_printf("c_stuff(%d)\n",i);
dq[idx].stuff(idx); sv_static(i); // Call SV
endtask }
endprogram : test
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 46
Pure C Functions
Declare C functions as pure for more VCS optimizations
Calls to pure functions can be removed by VCS or replaced
with the values previously computed for the same values of the
input arguments.
A function is pure when its result depend solely on the
values of its input arguments
Only non-void functions with no output or inout arguments can
b specified
be ifi d as pure.
A pure function is assumed not to directly or indirectly
(i.e., by calling other functions) perform the following:
Perform any file operations
Read or write anything in the broadest possible meaning,
including input/output, environment variables, objects from the
operating system or from the program or other processes,
shared memory, sockets, etc.
Access any persistent data, like global or static variables
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 47
Agenda
1 Introduction
Importing C Methods
2 Scalar Arguments
Importing
p g C Methods
3 Array Arguments
4 Open Arrays
Exporting SystemVerilog methods
5 Context / Pure methods
6 Compilation & Debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 48
How to Compile and Debug with DPI
Compilation with debug of SystemVerilog code
> vcs –sverilog test.sv test.c -debug
Enable the C/C++ source code debug with –g option
vcs –sverilog case1.sv case1.cpp –debug_all –CFLAGS –g
>
Include svdpi.h in C code for DPI structures
Include vc_hdrs.h in C code
Compile-time type checking of arguments
Does your import statement match the C code?
Include veriuser.h in C code for io_printf() definition
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 49
Compilation & Linking C++ Code
1. Use extern "C" for all definitions in headers;
protect it with #ifdef __cplusplus
2. SystemVerilog classes cannot be passed as arguments
3. Provide wrapper access functions for class members
4. Use a C++ compiler; vcs will automatically invoke a C++
compiler for extensions .cpp, .cxx and .cc
// C++ code
// SystemVerilog code #include <svdpi.h>
import "DPI-C" function void f();
#ifdef _cplusplus
... extern "C" void f()
endprogram #elsif
void f()
#endif
{
...
}
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 50
Shared Object Files
How can I switch between different C tests without
recompiling?
Compile the C code into shared object files
> gcc –shared –fPIC test.c –o test/libtest.so # test 0
> gcc –shared –fPIC test1.c –o test1/libtest.so # test 1
> gcc –shared –fPIC test2.c –o test2/libtest.so # test 2
Build VCS with a shared object file
> vcs –sverilog model.v test/libtest.so
Point to shared object file and run the simulation
> setenv LD_LIBRARY_PATH test
> simv # Run with test1.so
> setenv LD_LIBRARY_PATH test
> simv # Run with test1.so
> setenv LD_LIBRARY_PATH test
> simv # Run with test1.so
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 51
Debug with DVE
DVE supports SV design/testbench and C/C++
integrated debug
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 52
Debugging Runtime Issues
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 53
gdb introduction
list: list the source code
break method: set a breakpoint on a C method
break file:line# : set breakpoint in file at line number
info break: display current breakpoints
run [args]: start program execution with command line args
c: continue execution
whatis var: display the data type of the variable
print *var: display the structure referenced by var
set output-radix 16: set output radix to hex
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 54
DPI Header Files & Examples
DPI header files
$VCS_HOME/include/svdpi.h
VCS generated prototypes for C routines
vc_hdrs.h
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 55
For more information
SystemVerilog for Verification
Based on IEEE P1800-2009 Standard
New chapter on DPI with over 50 examples
Verification-specific language features
Constrained random stimulus generation
Functional coverage
Great intro to VMM
Available June 2008
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 56
Appendix
Memory management
TF routines that should not called in DPI
VCS and the LRM
Difference between DPI and DPI-C
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 57
Memory management
The memory spaces owned and allocated by the
foreign code and SystemVerilog code are disjoint
SystemVerilog code can only use memory declared in its
own arrays. It can not use blocks of memory from C
C code must not free the memory allocated by
SystemVerilog code
SystemVerilog code must not free the memory allocated
by the C code
SystemVerilog strings are dynamically allocated
You can change the contents (same length or shorter),
but don’t change the pointers
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 58
Calling tf routines from DPI code
tf routines that can be tf routines that should not
called from DPI context: be called from DPI context:
io_printf tf_asynchon tf_spname
mc_scan_plusargs tf_asynchoff tf_ispname
tf_gettime tf_itestpvc_flag tf_expr_eval
tf_testpvc_flag tf_exprinfo
tf_imovepvc_flag tf_nodeinfo
tf_copypvc_flag tf_propagatep
tf_icopypvc_flag tf_evaluatep
tf movepv flag
tf_movepvc_flag tf strgetp
tf_strgetp
tf_imovepvc_flag tf_getp
tf_getpchange tf_getscalarp
tf_synchronize tf_getlongp
tf_rosynchronize tf_getcstringp
tf_controller tf_getrealp
tf_setlongdelay tf_putp_direct
tf_setrealdelay tf_putp
tf_clearalldelays tf_putlongp
tf_typep tf_strlongdelputp
tf_sizep tf_strrealdelputp
tf_mipname tf_setworkarea
tf_mipid tf_getworkarea
tf_imipid tf_mdanodeinfo
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 59
VCS and the LRM
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
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 60
Appendix: Difference between DPI and DPI-C
“DPI” is defined as the keyword for direct
programming interface in SystemVerilog LRM 3.1a
“DPI” and “DPI-C” are defined in SystemVerilog
LRM IEEE-P1800-2005
VCS(2006.06, 2006.06-SP1 and 2008.03) implements
both of them
Stick with “DPI-C” for portable code
import "DPI-C" task c_test(input int addr);
program automatic top;
initial c_test(1000);
endprogram
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 61
Appendix: Difference between DPI and DPI-C
Bit vector or logic vector related system functions
DPI: xxxxxVec32
svPutBitArrElemVec32
DPI-C: xxxxxVecVal
svPutBitArrElemVecVal
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 62
Appendix: Difference between DPI and DPI-C
Canonical representations
DPI svdpi.h
svBitVec32 /* (a chunk of) packed bit array */
svLogicVec32
typedef unsigned int svBitVec32;
– c are control bits /* (a chunk of) packed logic array */
typedef struct {
– d are value bits unsigned int c;
g
unsigned int d;
;
} svLogicVec32;
DPI-C
svBitVecVal /* (a chunk of) packed bit array */
typedef uint32_t svBitVecVal;
svLogicVecVal
– aval are value bits /* (a chunk of) packed logic array */
typedef struct vpi_vecval {
– bval are control bits uint32_t aval;
uint32_t bval;
} s_vpi_vecval, *p_vpi_vecval;
typedef s_vpi_vecval svLogicVecVal;
© 2008 Synopsys, Inc. All Rights Reserved VCS 2006.06-SP2-2 63