SystemVerilog DPI Tutorial

Previous: Introduction | Next: Import declaration

DPI - two sides

DPI as an interface consists of two sides - the SystemVerilog layer and the C layer. As mentioned earlier, theoretically, it is possible to interface SystemVerilog with any arbitrary foreign language using DPI framework. However, for the time being, semantics for only C language interface is defined.

The two layers of the interface remain independent. For example, how some data is interpreted in the received side is not a concern for the sending side. The interpretation of data or any conversion internal to one side is independent of the other side and is implementation dependent.

This part of the DPI tutorial focusses on the SystemVerilog side of the interface. The next part will discuss the C side of the interface.

Imported tasks and functions

As we already know, thanks to DPI, your SystemVerilog code can now call a task or function written in C in the same manner that you will call any other native SystemVerilog task or function. (If you are unfamiliar with SystemVerilog task or function here is a quick update: they are similar to native Verilog task or function with extended capabilities to support rest of the SystemVerilog language. The basic concepts, however, remain the same: tasks can consume time, functions can not; tasks do not return a value, functions do).

When your SystemVerilog code calls a C function, it is called an imported function. Similarly, when a task implemented in C is called from the SystemVerilog side, the task is called imported task. For the rest of this tutorial, unless mentioned otherwise, a specific property of an imported function is equally valid for an imported task.

An important point to note here is that any C function can be imported. This include standard C library functions, such as malloc(), free() or strlen(). DPI thus brings you the entire power of C libraries to SystemVerilog without any extra effort on your behalf.

Calling an imported C function from SystemVerilog needs 3 components. They are:

  • A declaration for the imported function. It is also known as an import declaration.
  • The actual function implementation (in C).
  • Finally, calling the imported function from your SystemVerilog code.
Let us look into them in the reverse order.

(a) Calling the imported function from SystemVerilog: Calling an imported function from SystemVerilog is identical in form to calling a native SystemVerilog function. Just from the function call itself, it is impossible to tell if the function is written in C or SystemVerilog.

   integer t1, t2;
   logic [31:0] q;
   // It is impossible to say if my_function() and my_function2() 
   // are written in C or SystemVerilog
   if (p == 1'b1) begin 
      t1 = my_function();   
      t2 = my_function2(q); 

(b) The actual function implementation in C: As mentioned earlier, SystemVerilog layer is independent of the actual function implementation on the C layer. We will see more on how to handle SystemVerilog datatype when we will discuss the C layer. A word of caution here! Just like a native Verilog task, an imported task may consume time. This may result in a situation when an imported task will be called before the execution of the previous call to the same task is completed. You must be careful to take care of such re-entrancy situations.

(c) The import declaration: The import declaration defines the complete behavior of the imported function on the SystemVerilog side. It is, by far, the most important part of the SystemVerilog layer of the DPI. This is why we devote a separate section on this.

Previous: Introduction | Next: Import declaration


Verification Management
Join Verification Management Group

Shop Amazon - Contract Cell Phones & Service Plans

Book of the Month