SystemVerilog DPI:调用 C/C++ 参考模型
更新时间:2026-10-01。参考模型若是复杂算法(加解密、编解码、DSP),用 SV 写又慢又绕。DPI 让你直接调用成熟的 C/C++ 代码,兼顾平台集成与执行效率。
本文要回答的问题
- SV 怎么直接调一个 C 函数,需要改 C 代码吗?
- 参数怎么对得上,数组、位向量怎么传?
- C 能不能反过来调 SV、感知仿真时间?
- 编译链接和常见崩溃怎么处理?
一、import:SV 调 C
C 侧就是普通函数:
c
// ref.c
#include <stdint.h>
uint32_t crc32_ref(const uint8_t *p, int n) {
uint32_t crc = 0xFFFFFFFFu;
for (int i = 0; i < n; i++) { crc ^= p[i]; for (int b=0;b<8;b++)
crc = (crc>>1) ^ (0xEDB88320u & (-(int32_t)(crc&1))); }
return ~crc;
}SV 侧声明后直接调用:
systemverilog
import "DPI-C" function int unsigned crc32_ref(input byte p[], input int n);
byte data[];
data = new[4]{8'h1,8'h2,8'h3,8'h4};
exp = crc32_ref(data, 4); // 就像本地函数DPI 的好处是 C 函数完全不知道自己被仿真器调用,可直接复用现有算法库、黄金参考。
二、纯函数与 context
import "DPI-C"(默认 pure 无关上下文):C 函数不回调 SV、不碰仿真,调用开销最小。import "DPI-C" context task/function:C 侧需要回调 SV、访问仿真(如$display、消费时间),必须声明 context,开销更大。
三、类型映射与 open array
| SystemVerilog | C |
|---|---|
int/byte/int unsigned | int/char/uint32_t |
bit [31:0] | uint32_t(用 svLogicVecVal 处理 X) |
byte p[] 开放数组 | const svOpenArrayHandle |
传变长数组用 open array,C 侧用标准头文件 svdpi.h 的 API 取地址和尺寸:
c
#include "svdpi.h"
uint32_t sum_ref(const svOpenArrayHandle h) {
int n = svSize(h, 1);
const uint8_t *p = (const uint8_t*)svGetArrayPtr(h);
uint32_t s = 0; for (int i=0;i<n;i++) s += p[i]; return s;
}SV 端声明 import "DPI-C" function int sum_ref(input byte a[]);,任意长度数组都能传。要传播 X/Z 时用 svLogic/svLogicVecVal 而非纯 C 整型。
四、export:C 回调 SV
systemverilog
export "DPI-C" function note_error;
function void note_error(input int code);
uvm_report_error("DPI", $sformatf("code=%0d", code));
endfunctionC 侧 extern 声明后即可调用,用于把 C 模型内部检测到的错误上报到平台。export 的函数必须在 context 调用链中。
五、数据流图

六、编译与常见坑
- C 代码要和仿真器一起编译(VCS 加 C 源、Xcelium 用
-sv_lib链接共享库),漏链接报 undefined symbol。 - 32/64 位、有符号/无符号不匹配,返回值出现诡异大数。
- 用普通整型收
bit向量导致 X 信息丢失;需要 X 时必须用svLogicVecVal。 - 在非 context 函数里回调 SV 或访问
$time,运行报错。 - C 侧持有 SV 数组指针超出当次调用生命周期,内存失效。
小结
总结
DPI 让 SystemVerilog 直接复用成熟的 C/C++ 算法做高速参考模型:用 import "DPI-C" 调 C(默认纯函数开销最小,需回调 SV/碰仿真时间则声明 context),标量按 int/char 映射、变长数组用 open array 配 svdpi.h 的 svGetArrayPtr/svSize、需传播 X 用 svLogicVecVal;C 还能经 export "DPI-C" 反向把检测到的错误上报平台,C 源要与仿真器一起编译链接。