这些不同变成语言之间的调用主要包括以下几种方式:
1、verilog和c之间的相互调用;
2、systemverilog和c之间的相互调用;
3、systemverilog中调用systmc;
4、通过CPU执行c代码,从而实现Verilog和c的交互
第一种,verilog中调用c函数
verilog通过PLI(Program Language Interface)调用c函数。这些用户定义的系统任务和函数的名称必须以美元符号"$" 开头。大家用得比较多的PLI函数有$display, $finish等。
例如:
c函数如下:
#include <stdio.h>
void hello () {
printf("\nHello, world\n");
}
调用c函数的verilog代码如下:
module hello_verilog ();
initial begin
$hello;
#100 $finish;
end
endmodule
第二种,c中调用verilog函数
在实际的验证中,会有在c/c++代码中对DUT中的寄存器进行读写的需求。verilog提供VPI接口,可以将DUT的层次结构开放给外部c/c++代码;
常用的VPI接口主要有两个:
vpi_get_value(obj, p_value);
用于从RTL中得到一个寄存器的值。
vpi_put_value(obj, p_value, p_time, flags);
用于将RTL中的寄存器设置为某个值。
第三种,systemverilog中调用c函数
systemverilog 引入了DPI(Direct Programming Interface)。只要使用import声明和使用,导入一个C子程序,就可以像调用System Verilog中的子程序一样来调用它。
c函数如下:
#include <stdio.h>
void hello () {
printf("\nHello, world\n");
}
调用c函数的systemverilog代码如下:
module hello_sv ();
import "DPI-C" function void hello();
initial begin
hello();
#100 $finish();
end
endmodule
第四种,c中调用systemverilog函数
systemverilog代码如下:
module hello_sv ();
export "DPI-C" function adder;
function int adder(int a, int b);
return a + b;
endfunction
endmodule
调用systemverilog函数的c代码如下:
#include <stdio.h>
extern int adder(int a, int b);
void hello() {
int c;
c = adder(1, 2);
}
第五种,systemverilog中调用systmc代码
systemc代码
#include <uvmc.h>
using namespace uvmc;
#include <cnn.h>
int sc_main(int argc, char * argv[]) {
cnn cnn_inst("cnn_inst");
uvmc_connect(cnn_inst.in, "cnn_inst");
sc_start(-1);
return 0;
}
调用systemc的systemverilog代码如下:
import uvm_pkg::;
import uvmc_pkg::;
module sim_top();
cpu_top cpu_inst = new("cpu_inst");
initial begin
uvmc_tlm#()::connect(cpu_inst.out, "cnn_inst");
end
endmodule
第六种,通过CPU执行c代码,从而实现Verilog和c的交互
C代码通过工具链编译成CPU可以执行的汇编指令,再将汇编指令转成对应的指令代码,然后通过CPU读取指令代码产生激励,实现C代码所描述的功能。