Czy wolisz polską wersję strony elektroda?
Nie, dziękuję Przekieruj mnie tamadd c function call and run with questa
• Use the SystemVerilog Direct-Programming-Interface for C (DPI-C).
• Write your C function, compile it into a 64-bit position-independent shared object (*.so on Linux, *.dll on Windows).
• Declare the function in your SystemVerilog test-bench using import "DPI-C" ….
• Compile both the C and SV files with Questa vlog, link (or autolink) the shared object, and start the simulation with vsim … -sv_lib <lib_name>.
Key commands (Linux, Questa 2023.3 or newer):
vlib work
vlog -dpiheader dpi_hdr.h dpi_func.c tb_top.sv # compile & autolink
vsim -c work.tb_top -do "run -all; quit" # or vsim -sv_lib dpi_func …
Why DPI-C
• Lowest overhead: no VPI start-up registration, direct function call semantics.
• Part of IEEE-1800-2023; supported by all current Questa/ModelSim editions.
| Data type mapping (extract of the official table) | SystemVerilog type | C type in svdpi.h |
Notes |
|---|---|---|---|
byte |
signed char / PLI_INT8 |
8-bit | |
int |
int / PLI_INT32 |
32-bit | |
bit/logic [31:0] |
unsigned int |
≤32 | |
| dynamic / unpacked array | const svOpenArrayHandle |
use helper accessors |
Complete minimal example
3.1 C domain (dpi_func.c)
#include <stdio.h>
#include "svdpi.h" // always include!
/* Simple checksum over byte array */
unsigned char calc_cksum(const svOpenArrayHandle data, int n)
{
unsigned char crc = 0;
for (int i = 0; i < n; ++i) {
unsigned char *b = (unsigned char *) svGetArrElemPtr1(data,i);
crc ^= *b;
}
printf("[C] calc_cksum(%d) returns 0x%02X\n", n, crc);
return crc;
}
3.2 SystemVerilog domain (tb_top.sv)
import "DPI-C" function byte calc_cksum(input byte pkt[], input int n);
module tb_top;
byte pkt[]; // dynamic array
byte sv_crc, c_crc;
initial begin
pkt = new[8]; pkt = '{8'hA1,8'hB2,8'hC3,8'hD4,8'hE5,8'hF6,8'h01,8'h02};
sv_crc = ^pkt; // SV side reference
c_crc = calc_cksum(pkt, pkt.size()); // DPI-C call
$display("[SV] crc(SV)=0x%02h crc(C)=0x%02h", sv_crc, c_crc);
if (sv_crc!==c_crc) $fatal(1,"Mismatch");
$finish;
end
endmodule
Build + run (Linux, gcc):
export MTI_HOME=/opt/questa # adjust
vlib work
vlog -cc gcc \ # let Questa invoke gcc
-dpiheader dpi_hdr.h \
-sv tb_top.sv dpi_func.c # both sources
vsim -c work.tb_top -do "run -all; quit"
Output excerpt:
[C] calc_cksum(8) returns 0x5E
[SV] crc(SV)=0x5e crc(C)=0x5e
The same flow works on Windows by replacing gcc with cl and the shared object with a .dll.
Alternative linking method (manual)
gcc -fPIC -shared -I$MTI_HOME/include -o libdpi.so dpi_func.c
vlog tb_top.sv
vsim work.tb_top -sv_lib libdpi
Debugging & stepping
• From Questa 2022.4 upwards the GUI can single-step into imported DPI functions when they were compiled with -g and vsim –debugdb.
• Use setenv LD_PRELOAD or export MTI_DPI_DEBUG=1 for run-time symbol diagnostics.
Typical pitfalls
• Signature mismatch (wrong types/order) → linker error: “undefined import”.
• 32-bit versus 64-bit library mismatch; make sure to compile with -m64 if your Questa is 64-bit.
• Blocking forever inside C code stalls the whole simulator time wheel.
• Forgetting #include "svdpi.h" means you lose the portable typedefs.
When DPI-C is not enough
• Need callback into simulation time or hierarchical access → use VPI (PLI-1) or FLI (VHDL).
• Mixed-language with SystemC → use SLI (vsim -sc), or co-simulation tools.
• Siemens EDA (Questa 2023.4) adds automatic C++ name-mangling resolution (-dpicpp).
• The new -dpi_tb_compile switch lets you pre-compile DPI code once and cache it for regressions.
• Growing adoption of portable test-benches that re-use DPI models inside cocotb / Verilator → keep your API clean and stateless.
• svGetArrElemPtr1 is zero-copy: the C code manipulates the simulator’s memory directly—fast but dangerous; never keep a dangling pointer after the call returns.
• svOpenArrayHandle can handle multi-dimensional arrays via svDimensions(handle) and svLeft/Right/Size.
• To export a SystemVerilog task to C, write export "DPI-C" task sv_task; and call it from C, remembering to set the correct scope with svSetScope.
• Proprietary IP inside C models may require encryption or obfuscation—ensure your usage complies with NDAs and export regulations.
• Simulator licences (Questa Core vs. Questa Prime) have different DPI capability levels; distributing pre-compiled .so to partners might violate EULA.
• Always disclose in safety-critical projects that parts of the functional model execute outside strict RTL semantics.
• Keep DPI libraries modular: one shared object per verification domain (e.g. math, codec, crypto).
• Version-stamp your library (printf("Build: %s %s\n", __DATE__,__TIME__)).
• Add -Wextra -Wall -pedantic -g while developing; drop -g for regression speed.
• Use CI scripts (Makefile, CMake, pyflow) to rebuild automatically whenever SV imports change.
| Potential challenges & mitigation | Issue | Mitigation |
|---|---|---|
| Simulator cannot find .so | LD_LIBRARY_PATH=. vsim -sv_lib … |
|
| Mixed stdc++ ABI | Compile with the same gcc major version as the simulator. | |
| Memory leaks | Run under valgrind --tool=memcheck vsim … |
• Examples assume Linux 64-bit. File extensions .so ↔ .dll (Win) ↔ .dylib (macOS, limited support).
• Older ModelSim PE (<= 10.5) lacks the integrated gcc front-end; use manual compilation.
• Some university editions disable DPI entirely.
• IEEE 1800-2023 Clause 35 (DPI): definitive reference.
• Siemens App-Note UG900720 “DPI-C Cookbook” (2023).
• Explore co-simulation frameworks (SystemC TLM-2.0, Python cocotb) that reuse the same DPI mechanism.
• Investigate the foreign_lib mechanism in VHDL-2008 for mixed VHDL/C designs within Questa.
Directly call C from SystemVerilog in Questa by
svdpi.h, import "DPI-C"), vlog, and vsim while loading the shared object.