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);
end
(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
|