"Hello World" for SV/C++ DPI-C integration
— Kaushal ModiA little example demonstrating calling a C++ written function in SystemVerilog.
Let’s say we want to call a C++ function named hello_from_cpp
in
SystemVerilog, and for simplicity, let’s say that this is a void
returning function and takes no arguments.
C++ Header #
So that function signature would look like:
void hello_from_cpp();
We need to export that function from the C++ compiled library. So we
need to prefix that signature with the extern
keyword and wrap it
with extern "C"
as shown below, in libdpi.h
:
// libdpi.h
#ifdef __cplusplus
extern "C" {
#endif
extern void hello_from_cpp();
#ifdef __cplusplus
}
#endif
C++ Source Code #
And here’s the implementation of that hello_from_cpp
function in
C++:
// libdpi.cpp
#include <iostream>
using namespace std;
#include "libdpi.h"
void
hello_from_cpp() {
cout << "Hello from C++!\n";
}
Creating shared object (.so
) #
Cadence Xcelium uses a libdpi.so
by default as an “SV/DPI Lib”
(-sv_lib
switch) if it is present in the compilation directory. So
we will simply compile the above to a libdpi.so
.
g++ -c -fPIC libdpi.cpp -o libdpi.o
g++ -shared -Wl,-soname,libdpi.so -o libdpi.so libdpi.o
Verifying that the .so
actually contains that exported function #
This is a wonderful SO answer that taught me the existence of a CLI
GNU development tool called nm
. From its man page, this utility nm
list symbols from object files.
Here, I need to know which symbols from the text/code section got
exported to the libdpi.so
. When I did nm libdpi.so
, it listed
about two dozen symbols, most of which were gibberish to me. But the
symbol that I cared about: hello_from_cpp
has a T before it.
man nm
says this about that T:
"T"
"t" The symbol is in the text (code) section.
So after kind of understanding that, I do:
nm libdpi.so | rg '\bT\b'
and I get:
0000000000000888 T _fini
0000000000000698 T _init
00000000000007cc T hello_from_cpp
SystemVerilog test bench #
With the libdpi.so
object containing the exported hello_from_cpp
ready, we just need to DPI-C import it into the SystemVerilog test
bench.
program top;
import "DPI-C" function void hello_from_cpp();
initial begin
hello_from_cpp();
$finish;
end
endprogram : top
Result #
And running:
xrun -64bit tb.sv
gives:
xcelium> run
Hello from C++!