Bootstrap

芯片验证-DPI-C

SystemVerilog 和 C 语言的 DPI (Direct Programming Interface) 使得这两种语言可以直接互操作。这在硬件设计与验证中提供了极大的灵活性和强大功能。以下是 SystemVerilog 和 C 语言通过 DPI-C 接口互操作的应用场景:

1. 性能优化

在某些情况下,使用 C 语言编写的算法或计算比在 SystemVerilog 中编写的等效代码要快得多。通过 DPI-C 接口,可以调用高效的 C 函数来处理计算密集型任务,从而提高仿真性能。

示例
需要快速执行的复杂数学运算,如FFT(快速傅里叶变换)、图像处理算法等。

2. 现有代码重用

大量已有的C/C++库和代码可以直接用于硬件验证,不用重新编码。这大大减少了开发时间和维护成本。

示例
使用已有的C库来处理文件I/O、字符串操作、数据压缩等。

3. 测试平台集成和外部工具调用

可以在验证环境中调用外部工具或平台,例如脚本语言解释器、数据库访问等。

示例
调用外部Python脚本来生成测试向量,或者访问SQL数据库来验证设计的特定参数。

4. 硬件验证中的功能建模

在设计验证中,为了验证硬件的行为,可以使用C/C++来构建高层次的功能模型。这些模型可以用来对比硬件实现的行为,进行参考结果校验。

示例
用C语言实现参考模型(参考黄金模型),通过DPI接口调用它来验证硬件设计的正确性。

5. 与硬件驱动程序和操作系统交互

在一些复杂的SoC设计中,需要运行操作系统和驱动程序。通过DPI,可以在仿真中运行这些软件来验证硬件设计。

示例
在仿真环境中,调用C编写的硬件驱动程序,以验证新的硬件接口。

6. 测试数据和结果分析

在测试过程中,可能需要处理和分析大量数据。使用C语言可以更灵活和高效地处理这些数据,并可以利用现有的数据处理库。

示例
在验证过程中的日志分析、数据统计和结果汇总。

示例应用场景

1. 高效数学计算

在SystemVerilog中调用C语言函数来完成计算密集型任务。

C语言函数 (example.c)

#include <math.h>

double compute_sin(double angle) {
    return sin(angle);
}

SystemVerilog代码 (example.sv)

module test;
    import "DPI-C" function real compute_sin(input real angle);
    
    initial begin
        real angle = 1.5708; // 90 degrees in radians
        real result;
        result = compute_sin(angle);
        $display("The sine of %0.4f is %0.4f", angle, result);
        $finish;
    end
endmodule
2. 调用外部工具

在SystemVerilog中调用一个用C编写的外部工具来生成测试数据。

C语言生成数据 (generate_data.c)

#include <stdio.h>

void generate_data(int size, int data[]) {
    for (int i = 0; i < size; i++) {
        data[i] = i * i; // 生成简单的平方数列举
    }
}

SystemVerilog代码 (generate_data.sv)

module test;
    import "DPI-C" function void generate_data(input int size, output int data[]);
    
    int data[10];
    
    initial begin
        generate_data(10, data);
        $display("Generated data:");
        foreach(data[i]) begin
            $display("%0d: %0d", i, data[i]);
        end
        $finish;
    end
endmodule

总结

SystemVerilog和C语言的DPI-C接口在硬件设计和验证中提供了很大的灵活性和高效性。通过这种互操作,可以充分利用C语言的高效计算能力、现有的C/C++库以及外部工具,提高验证和设计的效率。DPI-C在各种场景中都有重要应用,从性能优化到测试平台集成,再到复杂系统的验证和数据处理等等。

准备代码

假设我们有以下示例代码:

C语言函数 (example.c)
#include <math.h>

double compute_sin(double angle) {
    return sin(angle);
}
void (*vlog_startup_routines[])()={0};
SystemVerilog代码 (example.sv)
module test;
    import "DPI-C" function real compute_sin(input real angle);
    
    initial begin
        real angle = 1.5708; // 90 degrees in radians
        real result;
        result = compute_sin(angle);
        $display("The sine of %0.4f is %0.4f", angle, result);
        $finish;
    end
endmodule

1. VCS一起编译SV和C语言(真实有效)

完整过程

下面是整个编译和运行过程的命令示例:

bsub -Is vcs -sverilog example.sv  example.c

# 运行仿真
./simv

查看仿真结果

如果代码和运行环境没有问题,运行仿真命令后,应输出如下结果:

The sine of 1.5708 is 1.0000

### 1. VCS一起编译SV和C语言(真实有效)
### 完整过程
下面是整个编译和运行过程的命令示例:

```sh
bsub -Is vcs -sverilog example.sv  example.c

# 运行仿真
./simv

查看仿真结果

如果代码和运行环境没有问题,运行仿真命令后,应输出如下结果:

The sine of 1.5708 is 1.0000

2. 将c语言编译成动态库,在使用vcs编译sv时指定.so(真实有效)

bsub -Is gcc -shared -o example.so example.c -fPIC
bsub -Is vcs -sverilog -full64 -sv_lib example.so example.sv
bsub –Is ./simv

3. 将c语言编译成静态库,在使用vcs编译sv时指定.a(真实有效)

C语言函数 (example.c)
#include <math.h>

double compute_sin(double angle) {
    return sin(angle);
}
//void (*vlog_startup_routines[])()={0}; 注意静态不需要这行
bsub -Is gcc -c example.c -o example.o
ar rcs libexample.a example.o  //注意.a最前面加lib
bsub -Is vcs -sverilog -full64 -L.. lexample example.sv //-L..的第二个点指的时静态库的路径
bsub –Is ./simv