Direct Programming Interface

Proposal Details

  • Who Updates: PeterFlake
  • Date Proposed:
  • Date Last Updated:
  • Priority:
  • Complexity:
  • Focus:

Current Situation

The FLI allows foreign language subprograms to be called, but has two deficiencies which limit its use. It does not allow foreign language data types returned by one subprogram call to be passed to the next subprogram call, and it does not allow VHDL subprograms to be called from the foreign language.

Furthermore, the single attribute FOREIGN does not allow more than one foreign language, and the format of the string is not standardized.


It should be simple to import a subprogram, i.e. have VHDL calling a C function. This requires that data types of arguments can be easily converted between languages.

It should be simple to export a subprogram, i.e. have a C function calling VHDL. This should take place in the context of an imported subprogram. The VHDL may be a procedure with a wait.

The DPI should support the Accellera SCE_MI interface to hardware emulators in a similar way to the SystemVerilog DPI.

There has also been a request for VHDL to import a SystemVerilog subprogram, and for VHDL to export a subprogram to SystemVerilog.

Implementation details

A new foreign language attribute is proposed. The attribute should include the language name, so that multiple languages can be supported by multiple attributes. In the case of C the name DPI_C is proposed to minimize clashes with existing code. This is to be used with strings of C for data types and subprogram import and export. In the case of SystemVerilog the name DPI_SV is proposed.

When a DPI_C imported subprogram is called, the scope ( i.e. which declaration in which instance or package called it) is recorded. This scope can be accessed and used for for calling VHPI functions. This functionality requires a new VHPI data type vhContext, as well as new VHPI functions vhGetContext and vhSetContext.

The parameter passing is by copy in and copy out. Therefore the formal parameters of an imported or exported subprogram cannot be signals or protected types. In the case of out or inout modes the corresponding C formal parameter must be a pointer. Note that the number and types of parameters are fixed, so that printf-style flexibility cannot be used (varargs).

The foreign language equivalent of a VHDL data type can be specified as a DPI_C attribute string. It is up to the tool to check the mapping between the types. The tool may require the user to specify C header files for user-defined C data types in the VHDL analysis, or SystemVerilog files for user-defined SystemVerilog types. If no attribute is specified, the tool should use its default C data type or SystemVerilog data type. There are two possible default mappings for C:

1) A simple default mapping for standard VHDL types to C99 types is:


BIT _Bool


INTEGER long int

REAL double

TIME long long int

STRING char [ ]

2) The alternative default mapping is to use the corresponding VHPI types

BOOLEAN vhpiSmallEnumT

BIT vhpiSmallEnumT



REAL vhpiRealT

TIME vhpiTimeT

STRING vhpiCharT [ ]

These (2) have the disadvantage that some are more complicated to access.

There is one obvious default mapping for SystemVerilog


BIT bit



REAL real

TIME time

STRING string

It is possible to declare a foreign language data type that has no VHDL equivalent, using a DPI_C attribute of an incomplete type. The tool should recognize the data type and determine its size. The only operations allowed are copying and testing for (in) equality.

Exporting a VHDL function or procedure requires a unique linker name. If the export is declared in a package there is only one instance of the subprogram, so it can be called from anywhere. If the export is declared in an entity, there can be multiple instances of the subprogram. The tool has to select which one to use based on the scope of the import declaration which called the C code. This means that the exported subprogram can only be used by imported subprograms from the same entity instance. Note that an exported procedure can only be called by an imported procedure.

An imported C procedure, that calls an exported VHDL procedure containing a wait, may be called by several VHDL processes at the same time, and therefore should be written to be multi-thread safe. Rules for re-entrant C coding include care with static variables and library calls.

Code Examples

These show the use of C syntax for DPI_C data types. Note that these attributes are not required if the C syntax is provided in the subprogram attribute.

type T1 is NATURAL;

attribute DPI_C of T1: type is "unsigned long int"; -- user defined type, could be composite 

type FILE_OPEN_KIND is (
    READ_MODE, -- Resulting access mode is read-only
    WRITE_MODE, -- Resulting access mode is write-only
    APPEND_MODE); -- Resulting access mode is write-only

attribute DPI_C of FILE_OPEN_KIND: type is "char*"; -- C string
attribute DPI_C of READ_MODE: FILE_OPEN_KIND is "””r””"; -- C “r”
attribute DPI_C of WRITE_MODE: FILE_OPEN_KIND is "””w””"; -- C “w”
attribute DPI_C of APPEND_MODE: FILE_OPEN_KIND is"””a””"; -- C “a”

type : C_POINTER; -- incomplete type

attribute DPI_C of C_POINTER: type is "void*"; -- tool determines storage for pointer.

A function or procedure is imported as follows, similar to the existing FLI, but with the string format standardized to the corresponding C syntax. Note that the function name may be changed e.g. to lower case.

package P is

    function F (x:INTEGER) returnINTEGER; -- user C function
    attribute DPI_C of F: function is "extern int f(int x)"; 

    function rand return INTEGER; -- C library function
    attribute DPI_C of rand: function is "extern int rand(void)"; 

    procedure srand (seed:in NATURAL); -- C library void function
    attribute DPI_C of srand: procedure is "extern void srand(unsigned int seed)"; 

    function FFI_PUTS (s:STRING) return INTEGER; -- use Libffi to call C library
    attribute DPI_C of FFI_PUTS: function is "extern int f(char *s)";

end package;

The C code is as follows, with thanks to the Red Hat Libffi documention:

#include <stdio.h>
#include <ffi.h>

int f( int x) { return x*x; }
int ffi_puts( char *s)

    ffi_cif cif;
    ffi_type *args[1];
    void *values[1];
    int rc = 0;

    /* Initialize the argument info vectors */

    args[0] = &ffi_type_pointer;
    values[0] = s;

    /* Initialize the call interface */

    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args) == FFI_OK)

    ffi_call(&cif, puts, &rc, values); /* rc now holds the result of the call to puts */
    return rc;

A function or procedure is exported as follows, again with the attribute string of the corresponding C syntax. It must be exported from a point in the package where the function name is visible.

   package Q is
      function G (x:INTEGER) return INTEGER is
      beginend -- body
      attribute DPI_C of G: function is "int g(int)";
   end package Q;

Use Cases

These enhancements will aid integration of a VHDL simulation with other tools and models, such as verification languages, instruction set simulators and hardware emulators. Libffi provides a means of integration with scripting languages.

Arguments FOR

These enhancements will make VHDL more useful as a simulation language because it will be easier and quicker to integrate it with other simulation and programming environments including operating systems and middleware.

Arguments AGAINST

The functionality can be provided in the foreign language using customised code for wrapping subprograms and for interacting with the simulation using the VHPI.

Might be better to have a way to specify the linker level interfaces for the VHDL rather than defining stuff at user level, e.g. you just tell you VHDL compiler to import/export according to a particular ABI for given functions outside the language itself. Handling plumbing is usually easier on the C/C++ side.

General Comments

  • JohnShields - 2011-06-09 - Comments from Collect Requirements page
  • develop a DPI for VHDL to support easy creation of foreign procedures
    • aids integration with other tools
    • simple export/import of subp declaration
    • subprogram calling C function and vice versa
    • basic types can be marshalled
    • any ref type that need to be read/updated when assigned, when time is consumed require API (and we may choose not to support)
    • ?Interface between VHDL & Verilog/SystemVerilog as well as C?
  • TristanGingold - 2015-08-07 - How do you make the difference between an imported subprogram and an exported subprogram ? Looks like for dpi_c, it's the presence of "extern" in the attribute. This is not very apparent, and I'd prefer to have two different attribute names (eg: C_IMPORT and C_EXPORT).
  • TristanGingold - 2015-08-07 - I don't see the issue with the FOREIGN attribute (in order to import a subprogram. The language name can appear in the attribute as it is certainly strange to import one subprogram from two different implementation. The last sentence in 'current situation' ('the single attribute FOREIGN does not allow more than one foreign language') doesn't seem correct.
  • TristanGingold - 2015-08-07 - It would be nice not to have to define the body (in vhdl) of an imported subprogram. Currently, even with FOREIGN, the user has to write a dummy body - which is stupid.
  • TristanGingold - 2015-08-07 - Allowing suspension (wait statement) in exported subprogram may not be a good idea, given the implementation burden.
  • TristanGingold - 2015-08-07 - The code example about file_open_kind is overly complex. I am not sure we want to map one type to a very different one.
  • TristanGingold - 2015-08-07 - The first line of 'code example' is not valid VHDL!
  • DavidKoontz - 2016-02-13 - int isn't a guaranteed 32 bit integer in C. Nor is VHDL integer guaranteed to be 32 bits (it's a minimum size). A long int isn't guaranteed to map to integer, either (and the same for unsigned long it). A VHDL string should map to an unsigned char[], and a character should map to an unsigned char. (the C char size is guaranteed to be at least 8 bits, VHDL uses ISO 8859-1, C 8 bit char is common).

I don't know that you have any business passing pointers across the C <=> VHDL interface. In SystemVerilog for instance the C memory space and VHDL memory space are separate (that would infer you'd have to use PLI/VPI, or in our case VHPI). Protecting the simulator and model memory resources sounds like a really good idea. C doesn't have what you could call a VHDL procedure equivalent with a parameter association list. Parameters of mode out imply an intermediary wrapper and passed pointers to a C function.

Note that VHDL can be otherwise implemented using interpretation rather than compiling and it's not outside the real of inserting foreign subprograms into a memory based model. That sort of implies worrying about implementation (e.g. IEEE Std 1800-2012 Annex J Inclusion of foreign language code) may be a bit out of bounds (which also makes it hard to claim a DPI-SV or the System C equivalent).

There's likely no easy (compact) way to pass VHDL context (scope and visibility based on where the FOREIGN declaration or specification is made) to a foreign language subprogram supplying the subprogram body (as much as Tristan hates the dummy bodies they could do that). I think Jim was commenting on something anecdotal from a particular vendor (starts with Mo) who wanted configurations to be analyzed into a different library than the entity and architecture they reference. This is the same issue, where does the context supplying scope and visibility come from? The way to recreate context is to re-analyze (even if you don't submit to a design library, the idea is that the design description is not updated nor is the reference library). In the case of DPI (or VHPI) how is that context conveyed? (like for a FOREIGN architecture, and ghdl doesn't do that yet.).

There are obvious issues with foreign subprograms containing wait statements which theoretically can cause an enclosing process to wait. That's real VHPI stuff instead, Signal parameters? What do signals look like? That's either implementation dependent or VHPI-ish and not Direct Programming Interface. Implementing signals likewise requires wrappers to do formal/actual translation between memory spaces for mode out (inout, buffer). Signals have different inward and outward references, read from an effective value, write to a particular driver's projected output waveform, for concurrent procedure calls there's an implicit sensitivity list. There's delay mechanism, pulse rejection limit, and after time expression plus some other out of band stuff (null, unaffected), and as Tristan notes do you really want call backs for waits in DPI?

There's bound to be a line you should draw between VHPI and DPI for feature support. Documenting could take more standard pages than SystemVerilog uses, VHDL is more complex. There's also an issue with supported VHDL types. You need something extensible beyond supported types. How much the types for packages standard, std_logic_1164, numeric_bit and numeric_std should be predefined? This stuff needs some cerebral attention. You really ought to have an implementation before standardization. If it ain't working now it may be too late for -2017, depending on supported features.


Add your signature here to indicate your support for the proposal

-- DavidSmith - 2012-09-26 David Smith Synopsys, Inc. - I support this as long as it is coordinated with 1076.1. We have had this request from user's of the language and I am pleased to see 1076 starting to address it.

-- Brent Hayhoe - 2012-10-09

-- RadoslawNawrot - 2015-04-28

Topic attachments
I Attachment Action Size Date Who Comment
PDFpdf Direct_Programming_Interface_for_VHDL_201x_Proposal_Update2.pdf manage 93.6 K 2013-12-04 - 09:07 RadoslawNawrot Direct Programming Interface for VHDL 201x Proposal Update uploaded. Co-existance with Sv and SystemC, type mapping, OpenArrays
Topic revision: r30 - 2020-02-17 - 15:34:52 - JimLewis
Copyright © 2008-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback