目录
1. 介绍
2. 示例一
2.1 HLS 代码
2.2 Report 解读
2.2.1 General Information
2.2.2 Timing Estimate
2.2.3 Performance & Resource Estimates
2.2.4 HW interfaces
2.2.4.1 硬件接口报告
2.2.4.2 导出至 Vivado 中的 IP
2.2.4.3 Port-Level Protocols 端口级协议
2.2.4.4 Block Level Control 块级控制协议
2.2.5 SW I/O Information
2.2.6 Bind Op Report
2.2.7 Bind Storage Report
3. 示例二
3.1 HLS 代码
3.2 Report 解读
3.2.1 HW interfaces
3.2.1.1 硬件接口报告
3.2.1.2 导出至 Vivado 中的 IP
3.2.2 SW I/O Information
3.2.3 Pragma Report
4. 示例三
4.1 HLS 代码
4.2 Report 解读
4.2.1 HW interfaces
4.2.1.1 硬件接口报告
4.2.1.2 导出至 Vivado 中的 IP
4.2.1.3 Block Level Control 块级控制协议
4.2.2 Pragma Report
5. 总结
1. 介绍
综合报告是Vitis HLS工具链中一个关键的输出,它为开发者提供了关于其HLS设计的重要信息,包括时序估计、性能和资源使用情况、硬件接口细节以及软件到硬件的映射信息。
本文通过三个简单的示例,详细解读这些报告,以便更好地理解 Vitis HLS 工具的输出,并利用这些信息来优化和调试硬件设计。
2. 示例一
2.1 HLS 代码
#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
+ 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
+ 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
+ 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 硬件接口报告
================================================================
== 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
================================================================
== 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 代码
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 硬件接口报告
================================================================
== 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
================================================================
== 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
================================================================
== 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 代码
#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 硬件接口报告
================================================================
== 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。
* 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
================================================================
== 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设计,从而在硬件实现中达到预期的性能和功能。