FPGA-HLS-乘法器(流水线对比普通仿真)

  • 一、函数介绍
  • 二、HLS相关
    • 2.1 简介
    • 2.2 HLS工程的编译流程
  • 三、普通仿真
    • 3.1 代码
    • 3.2 i++命令前事
    • 3.3 命令行编译
      • 1. x86模式
      • 2. 联合仿真模式
    • 3.4 仿真结果
  • 四、流水线
    • 4.1 代码
    • 4.2 命令行编译
      • 1. x86模式
      • 2. 联合仿真模式
    • 4.3 仿真结果
  • 五、报告对比
  • 总代码

一、函数介绍

ihc_hls_enqueue(void *retptr, void *funcptr,/*function arguments*/)
  • 参数:
    retptr:返回值
    funcptr:将要调用的HLS component
    这个函数对HLS组件的一次调用进行排队。返回值存储在第一个实参中,该实参应该是指向返回类型的指针。在调用ihc_hls_component_run_all()之前,组件不会运行。
ihc_hls_enqueue_noret(void* funcptr,/*function arguments*/)
  • 参数:
    funcptr:将要调用的HLS component
    这个函数对HLS组件的一次调用进行排队。当HLS组件的返回类型为void时,应该使用这个函数。在调用ihc_hls_component_run_all()之前,组件不会运行。
ihc_hls_component_run_all(void* funcptr)
  • 参数:
    funcptr:将要调用的HLS component
    这个函数接受一个指向HLS组件函数的指针。组件的所有排队调用在运行时将被推入,当组件能够接受新的调用时,HDL模拟器就能以最快的速度运行。

二、HLS相关

2.1 简介

HLS简介

HLS(High-Level Synthesis)高层综合,就是将 C/C++的功能用 RTL 来实现,将 FPGA 的组件在一个软件环境中来开发,这个模块的功能验证在软件环境中来实现,无缝的将硬件仿真环境集合在一起,使用软件为中心的工具、报告以及优化设计,很容易的在 FPGA 传统的设计工具中生成 IP。
传统的 FPGA 开发,首先写 HDL 代码,然后做行为仿真,最后做综合、时序分析等,最后生成可执行文件下载到 FPGA 使用,开发周期比较漫长。
使用 HLS,用高级语言开发可以提高效率。
因为在软件中调试比硬件快很多,在软件中可以很容易的实现指定的功能,而且做 RTL仿真比软件需要的时间多上千倍。

2.2 HLS工程的编译流程

FPGA-HLS-乘法器(流水线对比普通仿真)_第1张图片

三、普通仿真

普通仿真就是不调用以上函数,不使用流水线进行仿真。

3.1 代码

#include "HLS/stdio.h"
#include "HLS/hls.h"
#include "assert.h"
#include "stdio.h"

component int multi(int a,int b)
{
    return a*b;
}

int main()
{
    srand(0);//0是随机数的种子
    int x,y,z,i;
    for(i = 0;i<10;i++)

    {
        x = rand() % 10;
        y = rand() % 10;
        z = multi(x,y); 
        // printf("%d = %d + %d \n",z,x,y);
        // assert(z == x+y);//断言函数,出错时报错
    }
    return 0;
}

3.2 i++命令前事

  • 用win+R+cmd打开电脑终端
  • 我们以自带的counter.cpp为例 ,直接编译会报错的
    FPGA-HLS-乘法器(流水线对比普通仿真)_第2张图片
  • 这时需要返回上两级目录下,进行一个编译的初始化环境的操作。
  • 使用cd ..,使用两次,然后有一个init_hls.bat 文件,用它来初始化
    FPGA-HLS-乘法器(流水线对比普通仿真)_第3张图片
  • 之后就可以进行编译了,注意 每次都要切换到.c文件的目录下

每次打开一个终端都要进行初始化.

3.3 命令行编译

  • 先切换到.c文件所在目录。

1. x86模式

在默认情况下是生成 a.exe 文件,如果需要指定 则在后面加 -o b.exe 下一节流水线会用到

  • 命令:i++ -march=x86-64 multi.c -v
    之后:a
    FPGA-HLS-乘法器(流水线对比普通仿真)_第4张图片

  • 编译没问题就进行联合仿真。

2. 联合仿真模式

  • 命令:i++ -march=CycloneV multi.c -v -ghdl
    之后:a
    最后打开仿真:vsim a.prj\verification\vsim.wlf
    FPGA-HLS-乘法器(流水线对比普通仿真)_第5张图片

3.4 仿真结果

  • 打开ModelSim后添加自己命名函数的 _inst 文件到wave
  • 我这里为multi_inst

FPGA-HLS-乘法器(流水线对比普通仿真)_第6张图片

FPGA-HLS-乘法器(流水线对比普通仿真)_第7张图片

  • 可见是每次对每一对数值进行了计算,且有一个延时。

四、流水线

使用流水线仿真,我们不会用到第二个函数。

4.1 代码

#include "HLS/stdio.h"
#include "HLS/hls.h"
#include "assert.h"
#include "stdio.h"

component int multi(int a,int b)
{
    return a*b;
}

int main()
{
    srand(0);//0是随机数的种子
    int x[10],y[10],z,i;
    for(i = 0;i<10;i++)

    {
        x[i] = rand() % 10;
        y[i] = rand() % 10;
        
        ihc_hls_enqueue(&z,&add,x[i],y[i]);

    }
        ihc_hls_component_run_all(multi);

    return 0;
}

4.2 命令行编译

1. x86模式

在默认情况下是生成 a.exe 文件,如果需要指定 则在后面加 -o b.exe
为了方便查看生成的报告,所以我们这里的命令后会加 -o x.exe

  • 命令:i++ -march=x86-64 multi.c -v -o b.exe
    之后:b

FPGA-HLS-乘法器(流水线对比普通仿真)_第8张图片

  • 同样编译没问题就进行联合仿真

2. 联合仿真模式

  • 命令:i++ -march=CycloneV multi.c -v -ghdl -o b
    之后:b
    最后打开仿真:vsim b.prj\verification\vsim.wlf

注意这里的 b.prj ,因为前面改变了,所以这里也要变
FPGA-HLS-乘法器(流水线对比普通仿真)_第9张图片

4.3 仿真结果

  • 打开ModelSim后添加自己命名函数的 _inst 文件到wave
  • 同上我这里为multi_inst
    FPGA-HLS-乘法器(流水线对比普通仿真)_第10张图片
  • 结果
    FPGA-HLS-乘法器(流水线对比普通仿真)_第11张图片

可见同样有延时并是流水线进行,一组数据直接没有时间间隔。

五、报告对比

  • 按图分别打开 a.prjb.prj下的报告

FPGA-HLS-乘法器(流水线对比普通仿真)_第12张图片

  • a.prj
  • 初始页面资源查看

FPGA-HLS-乘法器(流水线对比普通仿真)_第13张图片

  • 资源分析详细查看
    FPGA-HLS-乘法器(流水线对比普通仿真)_第14张图片

FPGA-HLS-乘法器(流水线对比普通仿真)_第15张图片

  • b.prj
    FPGA-HLS-乘法器(流水线对比普通仿真)_第16张图片FPGA-HLS-乘法器(流水线对比普通仿真)_第17张图片

可见两者所用资源情况完全相同。

总代码

  • 两个模块放一起,用 ifdef 条件编译来分块使用
#include "HLS/stdio.h"
#include "HLS/hls.h"
#include "assert.h"
#include "stdio.h"
#define DEBUG //不注释掉时使用前面的代码

component int multi(int a,int b)
{
    return a*b;
}

int main()
{
    srand(0);//0是随机数的种子
    #ifdef DEBUG 
    int x,y,z,i;
    for(i = 0;i<10;i++)

    {
        x = rand() % 10;
        y = rand() % 10;
        z = multi(x,y); 
        // printf("%d = %d + %d \n",z,x,y);
        // assert(z == x+y);//断言函数,出错时报错
    }

    #else 
    int x[10],y[10],z,i;
    for(i = 0;i<10;i++)
    {
        x[i] = rand() % 10;
        y[i] = rand() % 10;
        // z[i] = add(x[i],y[i]); //不能赋值
        ihc_hls_enqueue(&z,&add,x[i],y[i]);
    }
        ihc_hls_component_run_all(multi);
    #endif

    return 0;

}
  • 参考文献
  1. HLS实验(二) 流水线仿真(排队函数的调用)
  2. FPGA基础之HLS

你可能感兴趣的:(FPGA,fpga开发,SOC,HLS)