四、DPI-C机制
1. DPI-C的介绍
DPI-C(Direct Programming Interface for C) 是允许SystemVerilog与C或C++代码交互的接口。虽然是SystemVerilog的内容,但是许多Verilog仿真器也支持。
2. VCS使用DPI-C示例
我们使用VCS仿真框架搭建一节中的示例,进行修改。
2.1 创建C文件
创建csrc文件夹,并在此文件夹下创建dpi.c文件:
#include <svdpi.h>
#include <stdbool.h>
#define SIZE 3
//检测101
const char series[SIZE] = {1,0,1};
static int count = 0;
static char buf[SIZE] = { 0 };
void demo_difftest(char out){
static diff_out_last=false; //存储上一次的结果
bool diff_out = true;;
if(count < SIZE)
return;
for(int i=0; i<SIZE; i++){
if(buf[(count-SIZE+i)%SIZE] != series[i]){
diff_out = false;
break;
}
}
if(diff_out_last != out)
printf("\e[1;31m" "ERROR at count = %d" "\e[0m" "\n", count);
diff_out_last = diff_out;
}
void catch_in(char in){
buf[count%SIZE] = in;
count++;
}
2.2 修改tb/demo_tb文件:
`timescale 1ns/1ns
import "DPI-C" function void catch_in(byte);
import "DPI-C" function void demo_difftest(byte);
module demo_tb();
reg clk;
reg rst;
reg input_;
wire output_;
demo demo_dut(
.clk(clk),
.rst(rst),
.a(input_),
.w(output_)
);
//生成波形文件
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, demo_tb);
end
//生成时钟
initial begin
#5
clk = 1'b0;
forever #5 clk = ~clk;
end
//difftest
always @(posedge clk) demo_difftest(output_);
//生成输入测试信号
initial begin
forever begin
#10 input_ = $random % 2;
catch_in(input_);
end
end
//生成复位信号和设置仿真时长
initial begin
rst = 1; //使能复位
#15 rst = 0;
#200 $finish; //停止仿真
end
endmodule
在上面的代码中,要尤其注意import "DPI-C"这两行以及对两个函数的使用部分。
2.3 修改Makefile文件
使得vcs支持SystemVerilog语法,只需在下面的语句最后添加-sverilog即可:
VCS_FLAGS = -full64 -notice -kdb -lca -debug_acc+all \
+dmptf +warn=all +libext+.v+v2k+acc -sverilog
将C文件添加到编译中,则添加:
CSRC = $(shell find $(abspath $(./csrc)) -name "*.c")
同时,修改下面的代码,增加$(CSRC),注意增加了两处:
$(BIN): $(FILE_LIST_F) $(CSRC)
vcs $(INC_FLAGS) -l $(VCS_LOG) $(VCS_FLAGS)\
-P $(VERDI_HOME)/share/PLI/VCS/$(PLATFORM)/novas.tab\
$(VERDI_HOME)/share/PLI/VCS/$(PLATFORM)/pli.a\
-f $(FILE_LIST_F) $(CSRC)\
-Mdir=$(OBJ_CSRC_DIR) -o $(BIN)
2.3尝试仿真
执行make sim, 如果正常的话,调用的c代码不会有任何报错的输出。
尝试注入错误,如将vsrc/demo.v中:
assign w = (buffer == 3'b101);
改为:
assign w = (buffer == 3'b111);
此时将会输出:
ERROR at count = 5
ERROR at count = 6
ERROR at count = 7
ERROR at count = 8
ERROR at count = 10
ERROR at count = 13
ERROR at count = 16
ERROR at count = 18
ERROR at count = 20
说明硬件描述代码有错误。
3. 总结
DPI-C其中一个很有用的地方就是用于芯片验证,在上面的例子中,就可以看到,我们用C语言实现了一个101序列检测器(假如可以确定C代码是正确的话),然后通过Verilog与C进行比较(difftest),就可以得出Verilog代码的逻辑是否正常。