第二章:HLS开发环境搭建
说实话,很多初学者一上来就急着写代码,结果卡在环境搭建上大半天。我见过不少同事,明明代码逻辑没问题,就是跑不通——最后发现是License没配好。这一章,咱们就把环境彻底搞定。
2.1 Vivado HLS安装:别踩这些坑
Vivado HLS是Xilinx的工具,现在叫Vitis HLS了。但底层逻辑没变。我个人习惯用2019.2版本,稳定,坑少。
安装前注意三点:
- 磁盘空间:至少留50GB。别问我怎么知道的——我第一次装的时候C盘爆了,折腾了一下午。
- 路径不要有中文:Vivado对中文路径支持很差。我曾经因为用户名是中文,编译死活过不去。
- 关闭杀毒软件:安装过程中会写注册表,杀毒软件经常误拦。
安装步骤其实很简单:
- 去Xilinx官网下载Vivado HLx安装包(选WebPACK或Enterprise版)
- 双击运行,一路Next。注意选“Vivado HLS”组件就行,不用全装
- 安装路径建议:
C:\Xilinx\Vivado\2019.2(纯英文) - 等...大概40分钟。去喝杯咖啡吧
2.2 License配置:最容易翻车的地方
License配置,说白了就是让工具认识你。我见过最离谱的bug——有人把License文件放桌面上,结果工具死活不认。
正确做法:
- 申请License:Xilinx官网注册账号,生成Node-Locked License
- 把
.lic文件放到固定路径,比如C:\Xilinx\Licenses\ - 打开Vivado HLS → Help → Obtain License → Load License
验证License是否生效:打开Vivado HLS,看Help → About → License Status。如果显示“Feature: Vivado_HLS, Expiration: Permanent”,那就对了。
2.3 创建第一个HLS工程
好,环境搭好了。咱们来建个工程试试手。我选一个最简单的例子——矩阵乘法。别怕,代码就几行。
步骤:
- 打开Vivado HLS,点击Create New Project
- 工程名:
matrix_mul_hls,路径选英文 - Top Function:填
matrix_mul(这是顶层函数名) - Solution Name:默认
solution1就行 - Clock Period:10ns(对应100MHz)
- 添加源文件:新建一个
matrix_mul.cpp
代码长这样:
// matrix_mul.cpp
#include <hls_stream.h>
#include <ap_int.h>
#define N 4
void matrix_mul(int A[N][N], int B[N][N], int C[N][N]) {
#pragma HLS INTERFACE s_axilite port=return bundle=CTRL
#pragma HLS INTERFACE bram port=A
#pragma HLS INTERFACE bram port=B
#pragma HLS INTERFACE bram port=C
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
#pragma HLS PIPELINE II=1
int sum = 0;
for (int k = 0; k < N; k++) {
sum += A[i][k] * B[k][j];
}
C[i][j] = sum;
}
}
}
嗯,这里要注意:#pragma HLS PIPELINE II=1是告诉工具,内层循环要流水线化,启动间隔为1个时钟周期。这是HLS优化的核心手段之一。
2.4 C仿真:先跑通再说
写完了代码,别急着综合。先做C仿真,验证功能对不对。你想想看,如果C代码逻辑都错了,综合出来的硬件能对吗?
操作:
- 右键工程 → Run C Simulation
- 会弹出一个控制台窗口,显示仿真结果
- 如果输出正确,会看到“PASS”字样
我习惯写一个简单的testbench:
// testbench.cpp
#include <iostream>
#include "matrix_mul.h"
int main() {
int A[N][N] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}};
int B[N][N] = {{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}};
int C[N][N] = {0};
matrix_mul(A, B, C);
// 验证结果:C应该等于A(因为B是单位矩阵)
bool pass = true;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (C[i][j] != A[i][j]) {
pass = false;
std::cout << "Mismatch at [" << i << "][" << j << "]" << std::endl;
}
}
}
if (pass) {
std::cout << "PASS!" << std::endl;
return 0;
} else {
std::cout << "FAIL!" << std::endl;
return 1;
}
}
运行仿真,看到“PASS”就对了。如果报错,检查一下数组维度或者接口定义。
2.5 C综合:看看工具怎么理解你的代码
C综合是HLS的核心步骤。说白了,就是把C代码翻译成RTL(寄存器传输级)硬件描述。工具会生成综合报告,告诉你用了多少资源、能达到多高频率。
操作:
- 右键工程 → Run C Synthesis → Active Solution
- 等几分钟(取决于代码复杂度)
- 综合完成后,自动打开报告
报告里重点看这几个指标:
| 指标 | 说明 | 我的经验值 |
|---|---|---|
| Latency | 从输入到输出需要的时钟周期数 | 越小越好,但别盲目追求 |
| II (Initiation Interval) | 两次启动之间的最小间隔 | II=1是理想值 |
| BRAM_18K | 使用的块RAM数量 | 别超过芯片总量80% |
| DSP48E | 使用的DSP单元 | 乘法多的话会占用很多 |
| FF/LUT | 逻辑资源 | 超过70%就要小心布线了 |
对于咱们这个矩阵乘法,综合后大概会看到:Latency在几十个周期,BRAM用了几个,DSP用了16个(因为4x4矩阵乘法需要16个乘法器)。
2.6 本章小结
这一章咱们把HLS开发环境彻底搞定了。从安装到License配置,从创建工程到C仿真和综合,每一步我都踩过坑,也把经验分享给你了。
记住几个关键点:
- 路径必须纯英文,否则各种玄学bug
- 先仿真再综合,别跳过验证
- 综合报告是优化指南针,一定要学会看
下一章,咱们会深入HLS的优化指令,比如PIPELINE、UNROLL、ARRAY_PARTITION这些。到时候你会发现,同样的C代码,加上几个pragma,性能能翻好几倍。
可可精品资料库