<- Click here to Toggle
Chapter 1-5
Chapter 5-10
Chapter 10-15
Chapter 15-20
Chapter 20-25
Chapter 25-30
Direct Programming Interface (DPI) - Introduction
Introduction
Direct Programming Interface (DPI) is an interface between SystemVerilog and a foreign programming language. It consists of two separate layers: the SystemVerilog layer and a foreign language layer. Both sides of DPI are fully isolated.
Different programming languages can be used and supported with the same intact SystemVerilog layer. The methodological requirement is that the interface should allow a heterogeneous system to be built (a design or a testbench) in which some components can be written in a language (or more languages) other than SystemVerilog, hereinafter called the foreign language, usually written in C or C++, without the knowledge and the overhead of PLI or VPI.
DPI follows the principle of a black box the specification and the implementation of a component is clearly separated and the actual implementation is transparent to the rest of the system. The separation between SystemVerilog code and the foreign language is based on using functions as the natural encapsulation unit in SystemVerilog. By and large, any function can be treated as a black box and implemented either in SystemVerilog or in the foreign language in a transparent way, without changing its calls.
Tasks & Functions
DPI allows direct inter-language function calls between the languages on either side of the interface. Specifically, functions implemented in a foreign language can be called from SystemVerilog, such functions are referred to as imported functions.
SystemVerilog functions that are to be called from a foreign code shall be specified in export declarations. DPI allows for passing SystemVerilog data between the two domains through function arguments and results. There is no intrinsic overhead in this interface.
Foreign code can call SystemVerilog tasks, and native Verilog code can call imported tasks. An imported task has the same semantics as a native Verilog task: It never returns a value, and it can block and consume simulation time.
Every imported task and function needs to be declared. A declaration of an imported task or function is referred to as an import declaration. Import declarations are very similar to SystemVerilog task and function declarations. Import declarations can occur anywhere where SystemVerilog task and function definitions are permitted. An import declaration is considered to be a definition of a SystemVerilog task or function with a foreign language implementation.
Datatypes
SystemVerilog data types are the sole data types that can cross the boundary between SystemVerilog and a foreign language in either direction i.e when an imported function is called from SystemVerilog code or an exported SystemVerilog function is called from a foreign code. It is not possible to import the data types or directly use the type syntax from another language.
A rich subset of SystemVerilog data types is allowed for formal arguments of import and export functions.
The following SystemVerilog types are the only permitted types for formal arguments of import and export tasks or functions
- void, byte, shortint, int, longint, real, shortreal, chandle, and string
- scalar values of type bit and logic
- packed one dimensional arrays of type bit and logic
- enumeration types interpreted as the type associated with that enumeration.
- types constructed from the supported types with the help of the constructs:
struct , typedef, unpacked array
The following caveats apply for the types permitted in DPI:
Enumerated data types are not supported directly. Instead, an enumerated data type is interpreted as the type associated with that enumerated type.
Open arrays:
The size of the packed dimension, the unpacked dimension, or both dimensions can remain unspecified; such cases are referred to as open arrays (or unsized arrays). Open arrays allow the use of generic code to handle different sizes.
Formal arguments of imported functions can be specified as open arrays. Although the packed part of an array can have an arbitrary number of dimensions, in the case of open arrays only a single dimension is allowed for the packed part.
Here are examples of types of formal arguments
logic
bit [9:1]
bit[]
bit [7:0] array10x10 [1:10] // array10x10 is a formal arg name
logic [31:0] array32xN [] // array32xN is a formal arg name
logic [] arrayNx7 [7:1] // arrayNx3 is a formal arg name
bit [] arrayNxN [] // arrayNxN is a formal arg name
Example of complete import declarations:
import "DPI" function void add(input logic [227:0]);
import "DPI" function void sub(logic [12:0] i []); // open array of 13-bit
Formal arguments of an imported function can be specified as open arrays. A formal argument is an open array when a range of one or more of its dimensions, packed or unpacked, is unspecified. An open array is like a multi-dimensional dynamic array formal in both packed and unpacked dimensions, and is thus denoted using the same syntax as dynamic arrays, using [] to denote an open dimension.
