第2章:HLS工具链入门:Vitis HLS安装与配置、C/C++综合流程、接口综合与协议、仿真与调试

好,咱们直接进入正题。这一章我打算带大家把HLS的工具链捋一遍。说白了,就是让你知道怎么装、怎么用、怎么调。很多初学者一上来就盯着算法看,结果工具报错卡半天——这种事我见得太多了。

2.1 Vitis HLS安装与配置

先说说安装。Vitis HLS现在集成在Vitis统一平台里,不再单独发布了。我个人习惯用2022.2版本,比较稳定。你下载的时候注意选对操作系统,Linux和Windows我都试过,Linux下综合速度快不少。

注意:安装路径不要带中文和空格。我曾经有个同事,装在了“D:\程序\Vitis”下面,结果综合时死活找不到库文件,折腾了两天才发现是路径问题。

安装完成后,有几个环境变量必须配好:

  • XILINX_VITIS:指向Vitis安装根目录
  • XILINX_VIVADO:指向Vivado安装目录
  • PATH:添加$XILINX_VITIS/bin和$XILINX_VIVADO/bin

配置好之后,在终端敲vitis_hls -version,能看到版本信息就说明装好了。嗯,这一步很简单,但很多人会忘。

2.2 C/C++综合流程

综合流程,我把它拆成三步走:

  1. 编写C/C++源码——注意风格,后面细说
  2. 运行C仿真——验证功能正确
  3. 执行综合——生成RTL

你想想看,这三步其实和软件编译很像。但有个关键区别:HLS综合对代码风格有要求。比如循环要加#pragma HLS PIPELINE,数组要指定存储类型。

我给大家看个最简单的例子:

#include <hls_stream.h>

void add(hls::stream<int> &in1, hls::stream<int> &in2, hls::stream<int> &out) {
    #pragma HLS INTERFACE axis port=in1
    #pragma HLS INTERFACE axis port=in2
    #pragma HLS INTERFACE axis port=out
    int a = in1.read();
    int b = in2.read();
    out.write(a + b);
}

这段代码综合后,会生成一个AXI4-Stream接口的加法器。注意看,我用了hls::stream,这是HLS里处理数据流的推荐方式。

小技巧:综合时加上-O3优化选项,能显著提升性能。我在做图像处理加速时,开优化和不优化,吞吐量能差3倍。

2.3 接口综合与协议

接口综合,说白了就是告诉工具:你的函数参数怎么和外部世界连接。HLS支持多种接口协议:

接口类型 适用场景 我踩过的坑
ap_none 纯组合逻辑 容易产生毛刺,慎用
ap_vld 带有效信号 握手逻辑要自己处理
ap_fifo FIFO接口 深度不够会丢数据
axis AXI4-Stream 我最常用的,稳定
m_axi AXI4主接口 带宽瓶颈常在这

为什么会这样?因为不同的协议对应不同的硬件握手方式。比如axis协议,它自带valid/ready握手,你不需要自己写控制逻辑。而ap_vld只有valid信号,ready要自己实现。

我曾经在一个项目中,把ap_fifo的深度设成了2,结果数据流稍微一波动就丢包。后来改成axis,问题就解决了。所以我的建议是:能用axis就用axis,省心。

2.4 仿真与调试

仿真调试这块,我分成C仿真和RTL协同仿真两个阶段。

C仿真:跑得飞快,适合验证算法逻辑。你写个testbench,给几个测试向量,看看输出对不对。这一步我建议多测边界情况,比如数据全零、全最大值、随机数。

RTL协同仿真:慢,但准。它会调用Vivado的仿真器,生成波形文件。我一般用这个来排查时序问题。

调试时,我最常用的三个命令:

  • csim:运行C仿真
  • csynth:执行综合
  • cosim:运行RTL协同仿真

嗯,这里要注意:cosim默认只跑1000个时钟周期,如果你的设计需要更长时间,记得加-ldflags "-Wl,--stack,16777216"来增大堆栈。

避坑指南:我曾经在调试一个卷积加速器时,C仿真结果完全正确,但RTL协同仿真就是不对。查了两天,最后发现是数组没有指定#pragma HLS RESOURCE,工具默认用了LUTRAM,导致读写冲突。改成BRAM后问题解决。

最后,给大家画个流程图,把整个工具链串起来:

Vitis HLS 工具链流程 C/C++ 源码 C 仿真验证 综合 (C Synth) RTL 优化迭代 RTL协同仿真 导出IP/封装 虚线表示优化迭代路径,实线表示正向流程

这张图把整个流程串起来了。你从C/C++源码开始,先做C仿真验证功能,然后综合生成RTL。如果综合结果不理想,就回到C仿真那一步优化代码。最后通过RTL协同仿真确认时序,再导出IP。

好了,这一章的内容就到这。工具链这东西,光看没用,你得动手敲一遍。我建议你找个简单的例子,比如矩阵乘法,从头到尾跑一遍流程,遇到问题再回来看这一章。

可可精品资料库