The short answer: The SystemVerilog Direct Programming Interface (DPI) lets SystemVerilog call C functions (import “DPI-C”) and lets C call SystemVerilog functions and tasks (export “DPI-C”), with no wrapper code. Simple types like int, byte, longint, real and string map directly to C types; bit and logic vectors use the svBitVecVal and svLogicVecVal types from svdpi.h. It’s widely used to plug C or C++ reference models, golden algorithms and software into a testbench.
DPI is how a testbench borrows existing software. If the architecture team already has a C model of a DSP block, or the firmware team has a driver, DPI lets you run it next to the RTL instead of rewriting it in SystemVerilog. This post combines my older posts on DPI and DPI with foreign languages.
- The four ideas
- Calling C from SystemVerilog
- Calling SystemVerilog from C
- Type mapping
- Other languages
- Tips
Table of Contents
Part 1: The four ideas

Part 2: Calling C from SystemVerilog
// ---- model.c ----
#include "svdpi.h"
int sat_add(int a, int b) {
long long s = (long long)a + b;
if (s > 2147483647LL) return 2147483647;
if (s < -2147483648LL) return -2147483647 - 1;
return (int)s;
}
// ---- tb.sv ----
import "DPI-C" function int sat_add(input int a, input int b);
initial begin
int r;
r = sat_add(32'sd2_000_000_000, 32'sd2_000_000_000);
$display("saturated: %0d", r);
end
Compile the C file with your simulator (most accept .c files on the command line, or a shared library) and the function is available like any other.
Part 3: Calling SystemVerilog from C
// ---- tb.sv ----
export "DPI-C" task wait_clks;
task wait_clks(input int n);
repeat (n) @(posedge clk);
endtask
import "DPI-C" context task run_firmware();
// ---- fw.c ----
extern void wait_clks(int n);
void run_firmware(void) {
/* write registers through other exported tasks ... */
wait_clks(100); // consumes simulation time
}
An imported task that calls exported SystemVerilog code must be declared context, so the simulator knows which scope it runs in. Imported tasks can consume time only through exported tasks.
Part 4: Type mapping
| SystemVerilog | C |
|---|---|
| byte | char |
| shortint | short int |
| int | int |
| longint | long long |
| real | double |
| string | const char * |
| chandle | void * |
| bit (scalar) | svBit |
| logic (scalar) | svLogic |
| bit [N:0] | svBitVecVal * (array of 32-bit words) |
| logic [N:0] | svLogicVecVal * (aval/bval pairs) |
| open arrays (int a[]) | svOpenArrayHandle |
Pass wide vectors and arrays carefully: check the svdpi.h helper functions for accessing bits and array elements rather than guessing the memory layout.
Part 5: Other languages
DPI speaks C, but C is the bridge to almost everything: C++ through extern "C" functions, Python through its C API or libraries built on it, and other simulators or virtual platforms through sockets. Many teams use this to run Python reference models or to co-simulate RTL with a SystemC or QEMU-based virtual platform.
Part 6: Tips
- Keep the DPI boundary narrow: pass simple values, keep complex state on one side.
- Mark pure functions with
pureonly when they really have no side effects; the simulator may optimise calls away. - Free memory you allocate in C; long regressions expose leaks.
- Seed C random number generators from SystemVerilog so failures stay reproducible.
Practise this on VLSI Forge
I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.
Previous in my SystemVerilog series: Testbench architecture. Next: Design patterns.
FAQ
What is DPI in SystemVerilog?
The Direct Programming Interface: a standard way for SystemVerilog to call C functions and for C to call SystemVerilog functions and tasks.
What is the difference between import and export in DPI?
import makes a C function callable from SystemVerilog; export makes a SystemVerilog function or task callable from C.
Can a C function consume simulation time?
Only by calling an exported SystemVerilog task, and the imported routine must be declared as a context task.
Can I use C++ with DPI?
Yes, by exposing C-linkage functions with extern “C” from your C++ code.
