目录
[1. 介绍](#1. 介绍)
[2. 示例一](#2. 示例一)
[2.1 HLS 代码](#2.1 HLS 代码)
[2.2 Report 解读](#2.2 Report 解读)
[2.2.1 General Information](#2.2.1 General Information)
[2.2.2 Timing Estimate](#2.2.2 Timing Estimate)
[2.2.3 Performance & Resource Estimates](#2.2.3 Performance & Resource Estimates)
[2.2.4 HW interfaces](#2.2.4 HW interfaces)
[2.2.4.1 硬件接口报告](#2.2.4.1 硬件接口报告)
[2.2.4.2 导出至 Vivado 中的 IP](#2.2.4.2 导出至 Vivado 中的 IP)
[2.2.4.3 Port-Level Protocols 端口级协议](#2.2.4.3 Port-Level Protocols 端口级协议)
[2.2.4.4 Block Level Control 块级控制协议](#2.2.4.4 Block Level Control 块级控制协议)
[2.2.5 SW I/O Information](#2.2.5 SW I/O Information)
[2.2.6 Bind Op Report](#2.2.6 Bind Op Report)
[2.2.7 Bind Storage Report](#2.2.7 Bind Storage Report)
[3. 示例二](#3. 示例二)
[3.1 HLS 代码](#3.1 HLS 代码)
[3.2 Report 解读](#3.2 Report 解读)
[3.2.1 HW interfaces](#3.2.1 HW interfaces)
[3.2.1.1 硬件接口报告](#3.2.1.1 硬件接口报告)
[3.2.1.2 导出至 Vivado 中的 IP](#3.2.1.2 导出至 Vivado 中的 IP)
[3.2.2 SW I/O Information](#3.2.2 SW I/O Information)
[3.2.3 Pragma Report](#3.2.3 Pragma Report)
[4. 示例三](#4. 示例三)
[4.1 HLS 代码](#4.1 HLS 代码)
[4.2 Report 解读](#4.2 Report 解读)
[4.2.1 HW interfaces](#4.2.1 HW interfaces)
[4.2.1.1 硬件接口报告](#4.2.1.1 硬件接口报告)
[4.2.1.2 导出至 Vivado 中的 IP](#4.2.1.2 导出至 Vivado 中的 IP)
[4.2.1.3 Block Level Control 块级控制协议](#4.2.1.3 Block Level Control 块级控制协议)
[4.2.2 Pragma Report](#4.2.2 Pragma Report)
[5. 总结](#5. 总结)
1. 介绍
综合报告是Vitis HLS工具链中一个关键的输出,它为开发者提供了关于其HLS设计的重要信息,包括时序估计、性能和资源使用情况、硬件接口细节以及软件到硬件的映射信息。
本文通过三个简单的示例,详细解读这些报告,以便更好地理解 Vitis HLS 工具的输出,并利用这些信息来优化和调试硬件设计。
2. 示例一
2.1 HLS 代码
cpp
#include <ap_int.h>
void func(ap_fixed<1,1> *led_o, char reg_in)
{
if(reg_in == 'o')
*led_o = 1;
else
*led_o = 0;
}
这段代码的功能非常简单,根据输入字符(reg_in)来控制一个LED的开关状态。如果输入是'o',则LED打开;否则,LED关闭。
func 函数接受两个参数:
- reg_in:一个char类型的变量,用来接收控制指令。
- led_o:一个ap_fixed<1,1>指针,用法见《Vitis HLS 学习笔记--ap_int.h / ap_fixed.h(1)》。
执行综合后,IDE会自动打开报告,这里介绍两种进入报告的途径。
方法一:
方法二:
第二种方法可以打开文本的报告,比较方便复制。以下的内容从文本报告中复制。
2.2 Report 解读
2.2.1 General Information
cpp
+ General Information:
* Date: Fri Apr 10 12:00:50 2022
* Version: 2022.1 (Build 3526262 on Mon Apr 18 15:47:01 MDT 2022)
* Project: example
* Solution: solution1 (Vivado IP Flow Target)
* Product family: zynquplus
* Target device: xck26-sfvc784-2LV-c
2.2.2 Timing Estimate
cpp
+ Timing:
* Summary:
+--------+----------+----------+------------+
| Clock | Target | Estimated| Uncertainty|
+--------+----------+----------+------------+
|ap_clk | 10.00 ns| 0.849 ns| 2.70 ns|
+--------+----------+----------+------------+
关于Timing的详细解释,请参照下图:
其中,Vitis HLS使用的有效时钟周期,可以理解为Target减去Uncertainty。
2.2.3 Performance & Resource Estimates
cpp
+ Performance & Resource Estimates:
PS: '+' for module; 'o' for loop; '*' for dataflow
+--------+------+------+---------+--------+----------+---------+------+----------+------+----+---+----------+-----+
| Modules| Issue| | Latency | Latency| Iteration| | Trip | | | | | | |
| & Loops| Type | Slack| (cycles)| (ns) | Latency | Interval| Count| Pipelined| BRAM | DSP| FF| LUT | URAM|
+--------+------+------+---------+--------+----------+---------+------+----------+------+----+---+----------+-----+
|+ func | -| 6.45| 0| 0.000| -| 1| -| no| -| -| -| 11 (~0%)| -|
+--------+------+------+---------+--------+----------+---------+------+----------+------+----+---+----------+-----+
2.2.4 HW interfaces
2.2.4.1 硬件接口报告
cpp
================================================================
== HW Interfaces
================================================================
* REGISTER
+-----------+---------+----------+
| Interface | Mode | Bitwidth |
+-----------+---------+----------+
| led_o | ap_none | 1 |
| reg_in | ap_none | 8 |
+-----------+---------+----------+
* TOP LEVEL CONTROL
+-----------+------------+-----------------------------------+
| Interface | Type | Ports |
+-----------+------------+-----------------------------------+
| ap_ctrl | ap_ctrl_hs | ap_done ap_idle ap_ready ap_start |
+-----------+------------+-----------------------------------+
2.2.4.2 导出至 Vivado 中的 IP
默认块级协议为ap_ctrl_hs,故生成的Vivado IP包含ap_ctrl端口。
2.2.4.3 Port-Level Protocols 端口级协议
端口级协议,即 func 函数的参数:
- reg_in(标量类型),作为输入,默认是ap_none协议
- led_o(指针类型),作为输出,默认是ap_vld协议,故包含led_o_ap_vld信号
2.2.4.4 Block Level Control 块级控制协议
Top/Block Level Control:块级控制协议,或者顶层控制协议,也即顶层 func 函数 return 控制的部分。
其modes有四个选项:
- ap: access protocol,hs: handshake
- 对于控制驱动的 TLP,ap_ctrl_chain 协议和 ap_ctrl_hs 协议支持顺序执行和流水打拍执行。
- 对于数据驱动的 TLP,ap_ctrl_none 是必需的控制协议。
- ap_ctrl_hs 控制协议与 ap_ctrl_chain 具有相同信号,但它将 ap_continue 信号设为 1 以保持高电平。此控制协议支持顺序执行模式和流水打拍执行模式,但不提供来自下游设计模块的反压以控制数据流动。
- ap_ctrl_none 同样与 ap_ctrl_chain 具有相同信号,但握手信号端口(ap_start、ap_idle、ap_ready 和ap_done)设为高电平并且会被优化掉(不综合成硬件)。
ap_ctrl_chain 接口的行为:
2.2.5 SW I/O Information
cpp
================================================================
== SW I/O Information
================================================================
* Top Function Arguments
+----------+-----------+-------------------------------------+
| Argument | Direction | Datatype |
+----------+-----------+-------------------------------------+
| led_o | out | ap_fixed<1, 1, AP_TRN, AP_WRAP, 0>* |
| reg_in | in | char |
+----------+-----------+-------------------------------------+
* SW-to-HW Mapping
+----------+--------------+---------+
| Argument | HW Interface | HW Type |
+----------+--------------+---------+
| led_o | led_o | port |
| led_o | led_o_ap_vld | port |
| reg_in | reg_in | port |
+----------+--------------+---------+
软件 I/O 信息,显示顶层函数实参:
- 方向信息,输入或者输出
- 参数类型
2.2.6 Bind Op Report
此例不涉及此报告。
2.2.7 Bind Storage Report
此例不涉及此报告。
3. 示例二
3.1 HLS 代码
cpp
void basic_interface(ap_fixed<1,1> *led_o, char reg_in)
{
#pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=reg_in
if(reg_in == 'o')
*led_o = 1;
else
*led_o = 0;
}
指令 #pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=reg_in 的作用:
- 指定 port=reg_in 端口级控制协议为 s_axilite
- 指定接口命名为 BUS_A
3.2 Report 解读
对于重复报告内容不再分析,重点对比与示例一的差异。
3.2.1 HW interfaces
3.2.1.1 硬件接口报告
cpp
================================================================
== HW Interfaces
================================================================
* S_AXILITE Interfaces
+-------------+------------+---------------+--------+----------+
| Interface | Data Width | Address Width | Offset | Register |
+-------------+------------+---------------+--------+----------+
| s_axi_BUS_A | 32 | 5 | 16 | 0 |
+-------------+------------+---------------+--------+----------+
* S_AXILITE Registers
+-------------+----------+--------+-------+--------+-----------------------+
| Interface | Register | Offset | Width | Access | Description |
+-------------+----------+--------+-------+--------+-----------------------+
| s_axi_BUS_A | reg_in | 0x10 | 32 | W | Data signal of reg_in |
+-------------+----------+--------+-------+--------+-----------------------+
* REGISTER
+-----------+---------+----------+
| Interface | Mode | Bitwidth |
+-----------+---------+----------+
| led_o | ap_none | 1 |
+-----------+---------+----------+
* TOP LEVEL CONTROL
+-----------+------------+-----------------------------------+
| Interface | Type | Ports |
+-----------+------------+-----------------------------------+
| ap_clk | clock | ap_clk |
| ap_rst_n | reset | ap_rst_n |
| ap_ctrl | ap_ctrl_hs | ap_done ap_idle ap_ready ap_start |
+-----------+------------+-----------------------------------+
相比于示例一,增加的内容:
- S_AXILITE Interfaces
- S_AXILITE Registers
其中 S_AXILITE Interfaces 和 S_AXILITE Registers 部分参数解释:
- Data Width: s_axi数据宽度为32位
- Address Width: 地址宽度是5位,接口寻址的地址空间为2的5次方,即32个不同的地址
- Offset: 偏移量,16,即0x10
3.2.1.2 导出至 Vivado 中的 IP
与示例一相比:
- 缺少了 reg_in[7:0] 接口
- 新增了 s_axi_BUS_A 接口
- 新增了 ap_clk 和 ap_rst_n 信号
3.2.2 SW I/O Information
cpp
================================================================
== SW I/O Information
================================================================
* Top Function Arguments
+----------+-----------+-------------------------------------+
| Argument | Direction | Datatype |
+----------+-----------+-------------------------------------+
| led_o | out | ap_fixed<1, 1, AP_TRN, AP_WRAP, 0>* |
| reg_in | in | char |
+----------+-----------+-------------------------------------+
* SW-to-HW Mapping
+----------+--------------+----------+----------------------------------+
| Argument | HW Interface | HW Type | HW Info |
+----------+--------------+----------+----------------------------------+
| led_o | led_o | port | |
| led_o | led_o_ap_vld | port | |
| reg_in | s_axi_BUS_A | register | name=reg_in offset=0x10 range=32 |
+----------+--------------+----------+----------------------------------+
与示例一相比,reg_in 的 HW Type 由 port 变更为 register,表示 reg_in 不再是一个端口,而是总线 s_axi_BUS_A 的一组寄存器。
3.2.3 Pragma Report
cpp
================================================================
== Pragma Report
================================================================
* Valid Pragma Syntax
+-----------+-----------------------------------------+-------------------------------------+
| Type | Options | Location |
+-----------+-----------------------------------------+-------------------------------------+
| interface | mode=s_axilite bundle=BUS_A port=reg_in | mult/src/func.cpp:5 in func, reg_in |
+-----------+-----------------------------------------+-------------------------------------+
生效的自定义端口,汇总在此报告中。
4. 示例三
4.1 HLS 代码
cpp
#include <ap_int.h>
void func(ap_fixed<1,1> *led_o, char reg_in)
{
#pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=reg_in
#pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=return
if(reg_in == 'a')
*led_o = 1;
else
*led_o = 0;
}
指令 #pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=return 的作用:
- 指定 port=return 块级控制协议为 s_axilite
- 指定接口命名为 BUS_A
4.2 Report 解读
对于重复报告内容不再分析,重点对比与示例一、二的差异。
4.2.1 HW interfaces
4.2.1.1 硬件接口报告
cpp
================================================================
== HW Interfaces
================================================================
* S_AXILITE Interfaces
+-------------+------------+---------------+--------+----------+
| Interface | Data Width | Address Width | Offset | Register |
+-------------+------------+---------------+--------+----------+
| s_axi_BUS_A | 32 | 5 | 16 | 0 |
+-------------+------------+---------------+--------+----------+
* S_AXILITE Registers
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| Interface | Register | Offset | Width | Access | Description | Bit Fields |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| s_axi_BUS_A | CTRL | 0x00 | 32 | RW | Control signals | 0=AP_START 1=AP_DONE 2=AP_IDLE 3=AP_READY 7=AUTO_RESTART 9=INTERRUPT |
| s_axi_BUS_A | GIER | 0x04 | 32 | RW | Global Interrupt Enable Register | 0=Enable |
| s_axi_BUS_A | IP_IER | 0x08 | 32 | RW | IP Interrupt Enable Register | 0=CHAN0_INT_EN 1=CHAN1_INT_EN |
| s_axi_BUS_A | IP_ISR | 0x0c | 32 | RW | IP Interrupt Status Register | 0=CHAN0_INT_ST 1=CHAN1_INT_ST |
| s_axi_BUS_A | reg_in | 0x10 | 32 | W | Data signal of reg_in | |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
* REGISTER
+-----------+---------+----------+
| Interface | Mode | Bitwidth |
+-----------+---------+----------+
| led_o | ap_none | 1 |
+-----------+---------+----------+
* TOP LEVEL CONTROL
+-----------+------------+-----------+
| Interface | Type | Ports |
+-----------+------------+-----------+
| ap_clk | clock | ap_clk |
| ap_rst_n | reset | ap_rst_n |
| interrupt | interrupt | interrupt |
| ap_ctrl | ap_ctrl_hs | |
+-----------+------------+-----------+
4.2.1.2 导出至 Vivado 中的 IP
与示例一相比:
- 缺少了 reg_in[7:0] 接口
- 缺少了 ap_ctrl 接口
- 新增了 s_axi_BUS_A 接口
- 新增了 ap_clk 和 ap_rst_n 信号
- 新增了 interrupt 信号
与示例二相比:
- 缺少了 ap_ctrl 接口
- 新增了 interrupt 信号
4.2.1.3 Block Level Control 块级控制协议
指令 #pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=return 指定了块级控制协议为 s_axilite。
cpp
* S_AXILITE Registers
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| Interface | Register | Offset | Width | Access | Description | Bit Fields |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| s_axi_BUS_A | CTRL | 0x00 | 32 | RW | Control signals | 0=AP_START 1=AP_DONE 2=AP_IDLE 3=AP_READY 7=AUTO_RESTART 9=INTERRUPT |
| s_axi_BUS_A | GIER | 0x04 | 32 | RW | Global Interrupt Enable Register | 0=Enable |
| s_axi_BUS_A | IP_IER | 0x08 | 32 | RW | IP Interrupt Enable Register | 0=CHAN0_INT_EN 1=CHAN1_INT_EN |
| s_axi_BUS_A | IP_ISR | 0x0c | 32 | RW | IP Interrupt Status Register | 0=CHAN0_INT_ST 1=CHAN1_INT_ST |
| s_axi_BUS_A | reg_in | 0x10 | 32 | W | Data signal of reg_in | |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
与示例二相比,新增了几组寄存器:
- CTRL,Control signals
- GIER,Global Interrupt Enable Register
- IP_IER,IP Interrupt Enable Register
- IP_ISR,IP Interrupt Enable Register
这些寄存器的作用,后续博文单独详解。
4.2.2 Pragma Report
cpp
================================================================
== Pragma Report
================================================================
* Valid Pragma Syntax
+-----------+-----------------------------------------+-------------------------------------+
| Type | Options | Location |
+-----------+-----------------------------------------+-------------------------------------+
| interface | mode=s_axilite bundle=BUS_A port=reg_in | mult/src/func.cpp:5 in func, reg_in |
| interface | mode=s_axilite bundle=BUS_A port=return | mult/src/func.cpp:6 in func, return |
+-----------+-----------------------------------------+-------------------------------------+
生效的自定义端口,汇总在此报告中。
5. 总结
在本文中,通过三个不同的示例,我们深入探讨了Vitis HLS IDE的综合报告(Synthesis Report),并详细解读了其中的关键部分:
示例一
- 功能:展示了一个基本的HLS代码,该代码根据输入字符控制LED的开关状态。
- 报告解读:
- General Information:提供了综合环境的基本信息,如日期、版本、项目名称等。
- Timing Estimate:展示了时钟周期的估计,包括目标时钟周期、估计时钟周期和不确定性。
- Performance & Resource Estimates:提供了性能和资源使用的估计,如模块的发行类型、延迟、流水线间隔等。
- HW interfaces:描述了硬件接口的详细信息,包括寄存器模式和顶层控制信号。
- SW I/O Information:展示了软件到硬件的映射信息,包括函数参数的方向、数据类型和硬件接口类型。
示例二
- 功能增强:通过添加
#pragma HLS INTERFACE
指令,指定了端口级控制协议为s_axilite
,并将端口命名为BUS_A
。 - 报告差异:
- 引入了
S_AXILITE Interfaces
和S_AXILITE Registers
,提供了关于AXI Lite接口的详细信息,包括数据宽度、地址宽度、偏移量和寄存器。 - SW-to-HW Mapping:展示了reg_in参数现在映射到AXI Lite接口的寄存器上。
- 引入了
示例三
- 功能增强:进一步通过
#pragma HLS INTERFACE
指令,将块级控制协议也设置为s_axilite
,并通过port=return
指定了返回值的接口。 - 报告差异:
- 新增了中断信号和相关的控制寄存器,如
CTRL
、GIER
、IP_IER
和IP_ISR
,这些寄存器用于控制信号、全局中断使能、IP中断使能和IP中断状态。 - TOP LEVEL CONTROL:现在包括了中断信号,表明设计支持中断功能。
- 新增了中断信号和相关的控制寄存器,如
通过这三个示例,我们学习了如何在Vitis HLS中使用端口级和块级控制协议来定制硬件接口,并通过综合报告来验证这些自定义设置。这些自定义设置对于FPGA逻辑交互至关重要,因为它们定义了数据和控制信号的交互方式。 可以看到Vitis HLS提供了强大的工具来帮助设计者理解、定制和优化他们的HLS设计,从而在硬件实现中达到预期的性能和功能。