<- Click here to Toggle

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

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.