Xilinx HLS基础介绍(一)
本期主题:
HLS的基础介绍
目录
- 1.HLS是什么
- 2.HLS开发流程
- 3.HLS接口管理
- 1.块级I/O协议
- 2.端口级I/O协议
1.HLS是什么
- Vitis HLS (High Level Synthesis)是一种高层次综合工具,支持将 C、C++ 和 OpenCL 函数硬连线到器件逻辑互连结构和 RAM/DSP 块上。(即可以用这些方式来设计IP);
- Vitis HLS 可在Vitis 应用加速开发流程中实现硬件内核,并使用 C/C++ 语言代码在 Vivado® Design Suite 中为赛灵思
器件设计开发 RTL IP;- 使用这种方式有很多现成的库,开发效率比RTL更高;
2.HLS开发流程
总体可以将HLS开发流程概括为4个步骤:
- C/C++仿真: 添加一个顶层函数,这个函数将来就会映射成RTL电路,之后用一个C testbench对这个函数功能进行验证,在算法层面,
检验我们的函数是否能够正常工作
; - C综合: 综合实际是
把C/C++源码综合成RTL实现
,产生对应的电路,综合阶段会对各种接口的约束(Directive)十分关心,不同的约束会导致在生成电路时的不同实现; - C/RTL协同仿真: 目的是
为了确认C的逻辑和RTL的逻辑是否一致
,所以这一步会将RTL仿真的生成结果跟第一步的C仿真结果进行对比; - 导出IP: 最后一步就是export导出IP了
3.HLS接口管理
HLS设计的顶层函数的所有实参都需要综合到端口和接口内
,在 RTL 设计中,同样这些输入和输出操作必须通过设计接口中的端口来执行,并且通常使用特定 I/O(输入/输出)协议
来进行操作。
对顶层函数进行综合时,函数的实参(或参数)将综合到RTL端口中,此流程称为接口综合(interface synthesis)。
看一个简单的例子:
#include "sum_io.h"
dout_t sum_io(din_t in1, din_t in2, dio_t *sum) {
dout_t temp;
*sum = in1 + in2 + *sum;
temp = in1 + in2;
return temp
}
以上示例包括:
- 2个输入:in1、in2,这两个输入是按值传递(pass-by-value)
- 可以进行读取和写入的指针 sum
- 返回temp
经过默认接口综合,综合到RTL中,得到结果:
Vivado HLS 会在 RTL 设计上创建 3 种类型的端口:
• 时钟和复位端口:ap_clk 和 ap_rst。
• 块级接口协议。在前图中已显示并展开这些端口:ap_start、ap_done、ap_ready 和 ap_idle。
• 端口级接口协议。这些端口是针对顶层函数和函数返回(如果函数返回值)中的每
其中 HLS 会在 RTL 设计上创建 3 种类型的端口:
- 时钟和复位端口(clock and reset interface)这种我们一般是改不了,暂时先不用关心;
- 块级接口协议(block level interface): ap_start、ap_done、ap_ready、ap_idle;
- 端口级接口协议(port level interface):针对顶层函数和返回值的每个实参而创建的,包括:in1、in2、sum_i、sum_o、sum_o_ap_vld、ap_return;
1.块级I/O协议
Vivado HLS 使用接口类型 ap_ctrl_none、ap_ctrl_hs 和 ap_ctrl_chain 来指定是否使用块级握手信号实现
RTL。
- ap_start:用于控制块开始处理数据的时间;
- ap_ready:用于指示是否已经准备好开始接受输入;
- ap_idle:用于指示设计是否是处于空闲状态;
- ap_done:是否已完成操作;
2.端口级I/O协议
创建的端口I/O取决于顶层函数的参数类型以及默认值,端口级IO协议用于对进出块的数据进行排序。
根据前面的例子,得出一些结论:
- 默认的输入情况下:如果是按值传递(pass-by-value)的实参和指针,都使用
简单线性端口来实现,无关联的握手信号
,例如前面例子中的in1和in2;- 默认的输出情况下:如果是用指针来实现的输出,
需要指示输出数据何时有效
,因此有一个关联的输出有效端口 (sum_o_ap_vld) ;- 同时支持读取和写入的实参:例如前面例子中的sum,就需要将其
拆分成独立的输入端口和输出端口
;- 如果函数具有返回值,实现输出端口ap_return来提供返回值;