如何在sv中使用DPI函数

巧妙的使用DPI函数能够给你的验证环境搭建提供很多便利,相当于sv中直接调用c函数,简直不要太爽,节省很多时间。

1.DPI -- sv调用c系统库函数

下面以一个验证环境的class中使用DPI的math库中的函数为例:首先定义一个package,在package中将使用到的DPI函数导入进来,math_pkg可以自定义名字

package math_pkg;

  //import dpi 
  import "DPI" function real cos (input real in_data);

  import "DPI" function real sin (input real in_data);

  import "DPI" function real log (input real in_data);

  import "DPI" function real log10 (input real in_data);

endpackage

在class类中来使用这个math_pkg,下面是以生成一个正弦sin数据为例:

    1.要将package导入到类中,可以使用域作用符和通配符把所有的package的函数导入

    2.按变量类型正常使用即可

class exam_transaction ;
    
    import math_pkg::*;

    rand bit [31:0] freq;
    rand bit [ 7:0] ampl;
    rand bit [15:0] ploda[];

    function void post_randomize();//call back randomize
        this.ploda.delete();
        this.ploda = new[freq];
        sine_wave;
    endfunction

    task sine_wave;
        const real pi=3.1416;
        real sin_out;
        int cnt,i;
        cnt = 0;
        i = 0;
        repeat(freq) begin
            sin_out = ampl*sin(2*pi*cnt/freq);
            this.ploda[i] = $itor(sin_out);//real data to bit data
            if(cnt == freq - 1'd1) begin
                cnt = 'd0;
            end
            else begin
                cnt = cnt + 1'd1;
            end
        end
    endtask

endclass

2.DPI -- sv调用自定义c函数 

前面调入的是系统c的math库函数,那如果是自定义的一个c的函数要怎么办呢?其实是类似的,

如果有一个c的函数文件test_c.c

#include<stdio.h>
void c_print(char* str){
  printf("c_print in running ,input srting is %s\n",str);  
}

那么只需要在vcs进行编译时c文件也添加到文件列表中即可,这样vcs在编译文件时,会自动使用默认的gcc进行对c文件编译,可通过对vcs设定指定不同的编译器。

在sv中使用时,  也是先使用import将c函数导入进来import "DPI" function void c_print(string str);这里有一点需要注意,就是我们再c中定义的是char*类型但是在sv中就是srting类型了。DPI-C传递的每个变量都有两个相应匹配的定义,一边面向SystemVerilog,一边面向C/C++。这里需要确保每个数据类型必须匹配兼容。其一一对应关系如下图所示

package math_pkg;

  //import dpi 
  import "DPI" function real cos (input real in_data);

  import "DPI" function real sin (input real in_data);

  import "DPI" function real log (input real in_data);

  import "DPI" function real log10 (input real in_data);

  import "DPI" function void c_print(string str);

endpackage

class exam_transaction ;
    
    import math_pkg::*;

    rand bit [31:0] freq;
    rand bit [ 7:0] ampl;
    rand bit [15:0] ploda[];

    function void post_randomize();//call back randomize
        this.ploda.delete();
        this.ploda = new[freq];
        sine_wave;
        c_print("example_trans input at post_randomize");//use DPI test_c function
    endfunction

    task sine_wave;
        const real pi=3.1416;
        real sin_out;
        int cnt,i;
        cnt = 0;
        i = 0;
        repeat(freq) begin
            sin_out = ampl*sin(2*pi*cnt/freq);
            this.ploda[i] = $itor(sin_out);//real data to bit data
            if(cnt == freq - 1'd1) begin
                cnt = 'd0;
            end
            else begin
                cnt = cnt + 1'd1;
            end
        end
    endtask

endclass

3.DPI -- sv和c互传数据 

继续往下,我们已经可以从sv传递一个字符串到c中了,那如果是需要从sv中传递一个数据到c中,经过c的处理再把结果从c中返回给sv要怎么实现呢?下面以一个两输入加法器为例:

c函数中输入变量类型为了和sv中的bit匹配需要为const svBitVecVal 输出变量为svBitVecVal *

#include<svdpi.h>
void c_add(const svBitVecVal in1,const svBitVecVal in2,svBitVecVal * outdata){
    static unsigned char tmp =0;
    tmp = in1+in2;
    *outdata = tmp;
}

 

package math_pkg;

  //import dpi 
  import "DPI" function real cos (input real in_data);

  import "DPI" function real sin (input real in_data);

  import "DPI" function real log (input real in_data);

  import "DPI" function real log10 (input real in_data);

  import "DPI" function void c_print(string str);
  
  import "DPI" function void c_add(input bit[6:0] in1,input bit[6:0] in2,output bit[7:0] out);

endpackage

class exam_transaction ;
    
    import math_pkg::*;

    rand bit [31:0] freq;
    rand bit [ 7:0] ampl;
    rand bit [15:0] ploda[];

    bit [7:0] out_data;
    function void post_randomize();//call back randomize
        this.ploda.delete();
        this.ploda = new[freq];
        sine_wave;
        c_print("example_trans input at post_randomize");//use DPI test_c print function
        c_add(12,55,out_data);//use DPI test_c add function
        $display("add data is %d\n",out_data);
    endfunction

    task sine_wave;
        const real pi=3.1416;
        real sin_out;
        int cnt,i;
        cnt = 0;
        i = 0;
        repeat(freq) begin
            sin_out = ampl*sin(2*pi*cnt/freq);
            this.ploda[i] = $itor(sin_out);//real data to bit data
            if(cnt == freq - 1'd1) begin
                cnt = 'd0;
            end
            else begin
                cnt = cnt + 1'd1;
            end
        end
    endtask

endclass

 

如果是传递数组可参考:http://testbench.in/DP_08_ARRAYS.html

posted @ 2022-06-07 10:34  验证cc  阅读(2238)  评论(0编辑  收藏  举报