system verilog与C语言的接口(包含使用方法以及实例)

资料来源

(1) sv绿皮书;

(2) vcs user guide;

(3) https://www.cnblogs.com/studyforever/p/5169243.html

(4) system verilog与功能验证

(5) https://www.cnblogs.com/GrootStudy/p/16559418.html

注1:注意dpi使用过程中的svSetScope()函数与svGetScopeFromName()函数; 

1.verilog与C语言的接口(另外单独详细描述)

1.1 PLI-Programming Language Interface

(1) verilog使用编程语言接口(PLI)与C语言程序交互;

(2) PLI先后经历三代:TF->ACC->VPI;

1.2 PLI的优缺点(暂略)

2.system verilog与C语言的接口与交互

2.1 DPI-Direct Programming Interface

(1) system verilog使用DPI实现与C,C++,SystemC以及其他非verilog编程语言的交互;

2.2 导入(import)声明

注1:在sv中,凡是允许声明子程序的地方都可以导入子程序,例如program, module, interface, package或者编译单元空间$unit;

注2:被导入的子程序将只在它被声明的空间中有效;

注3:如果需要在代码的多个地方调用同一个导入函数,可以将import声明放在一个package中,并在需要的地方导入package;

注4:任何C函数都可以被引入到sv中,包括标准的C的函数库,如malloc()、free()、strlen();

(1) 导入时,不改变C函数名

1 import "DPI-C" function int factorial(input int i);

(2) 导入时,改变C函数名(如果C函数名与sv中的命名冲突)

1 //改变C函数名"test"为"my_test"
2 import "DPI-C" test=function void my_test();
3 
4 //C函数名与sv关键字expect同名,需要修改函数名
5 import "DPI-C" \expect=function int fexpect();

2.3 导出(export)声明

3.使用方法以及实例(vcs仿真)

3.1 system verilog代码使用C子程序

3.1.1 编辑C文件,定义所需函数,注意在文件头部添加#include <svdpi.h>语句;

注1:要导入的C子程序可以有多个参数或者没有参数,参数的方向可以是input, output, inout,但不可以是ref;

注2:要导入的C子程序可以有返回值,也可以没有返回值;

注3:可以将要导入的C子程序的输入参数定义为const类型,这样如果对输入变量进行修改,C语言编译器会报错;

注4:注意system verilog和C语言子程序输入输出之间的数据类型的映射关系(详见sv绿皮书12.1.4参数类型);

 1 //参数方向
 2 import "DPI-C" function int addmul (input int a,b, output int sum);
 3 
 4 //返回值
 5 import "DPI-C" function void stop_model();
 6 
 7 //const类型输入参数
 8 int factorial(const int i) {
 9    if(i<=1) return 1;
10    else return i*factorial(i-1);  
11 
12 }

3.1.2 sv代码中采用特定的import语法引入C文件中子程序;

注1:在不同的使用场景下,import格式有所不同;

注2:约束中调用DPI函数,如果import语句中没有指明pure function,而只是function, vcs仿真工具将会报错;

注3:在import C函数时,不是所有的C函数实现都可以用import "DPI-C" pure function方式导入;

(1) 纯导入(在sv约束中使用纯导入-pure)

注1:纯函数严格根据其输入计算输出,跟外部环境没有任何其他交互,即纯函数不会访问任何全局或静态变量,不会进行文件操作,不会跟函数体以外的事务如操作系统、进程等有交互;

 1 使用格式(注意pure关键字):
 2 import "DPI-C" pure function int func1();
 3 import "DPI-C" pure function int func2(int a, int b);
 4 
 5 使用示例:
 6 step1:C文件dpi_func.c的构建
 7 #include <svdpi.h>
 8 
 9 int dpi_func(int a, int b)  {
10    return (a+b);
11 }
12 
13 step2:sv代码中调用C函数
14 import "DPI-C" pure function int dpi_func(int a, int b);
15 
16 class C;
17     
18    rand int ii;
19    constraint cstr{
20       ii==dpi_func(10,20);
21    }
22 endclass
23 
24 program tb;
25     C cc;
26     cc=new;
27     cc.randomize();
28 endprogram

(2)通用导入-generic

注1:如果导入方法中使用全局变量,但没有调用任何PLI,它就不需要承受context方法带来的额外开销,这类函数为通用的;

1 使用格式:
2 import "DPI-C" function int dpi_func(int a, int b);

(3)关联导入-context

注1:调用关联导入方法时,需要记录调用的上下文环境以决定调用PLI TF\ACC还是VPI方法或者导出的system verilog任务,会给仿真器带来额外的开支;

注2:导入函数的上下文是该函数定义所在的位置,比如$unit、模块、program或者package;

1 使用格式:
2 import "DPI-C" context task call_sv(bit[31:0] data);

3.1.3 vcs仿真时添加编译option: +vc C/C++ source files;

(1) +vc选项后面跟的源文件必须是.c后缀;

(2) 注意现在如果使用+vc选项,vcs log中会报warning,说vc已经弃用了,可以使用+DPI代替;

1 vcs +DPI dpi_func.c -sverilog tb.sv -R -l run.log

3.2 C代码使用system verilog子程序

3.2.1 使用export语法导出一个system verilog函数;

1 示例:
2 export "DPI-C" function sv_display;
3 export "DPI-C" task mem_read;

3.2.2 完整示例

 1 #include <svdpi.h>
 2 #include <stdio.h>
 3 
 4 extern void mem_write(int);
 5 
 6 int read_file(char * fname) {
 7    int cmd;
 8    FILE * file=NULL;
 9    int hi;
10 
11    file=fopen(fname, "r");
12    if(file==NULL) {
13       printf("cannot open this file\n");
14       exit(0);
15    }  
16 
17     while(!feof(file)) {    //这种方法判断文件是否读完,会导致文件最后一行读两遍;
18        fscanf(file, "%d", &hi);
19        printf("%0d\n",hi);
20        mem_write(hi);
21      }
22 
23 }
 1 //sv文件
 2 module memory;
 3    import "DPI-C" context function  read_file(string fname);  //该处必须用context function,因为C程序的read_file内用到了sv的导出函数;
 4    export "DPI-C" function mem_write;
 5 
 6    int mem[$];
 7    
 8    function mem_write(int num);
 9        mem.push_back(num);
10    endfunction
11 
12    initial begin
13        read_file("mem.txt");
14        foreach(mem[i]) begin
15           $display("mem[%0d]=%0d",i,mem[i]);
16        end
17    end
18 
19 
20 endmodule:memeory
1 //txt文件
2 32
3 8
4 16
5 128
6 2
7 8

 

posted on 2022-06-30 14:30  知北游。。  阅读(3014)  评论(0编辑  收藏  举报

导航