目录
1. 简介
2. Schedule Viewer详解
2.1 视图说明
2.1.1 Operation\Control Step
2.1.2 周期关系图
2.1.3 Schedule Viewer 菜单栏
2.1.4 属性视图
2.2 内容说明
2.2.1 实参(b)解释
2.2.2 实参(a)解释
2.2.3 变量(i)解释
2.2.4 数组操作解释
2.2.5 a*xin[i] 解释
3. 总结
1. 简介
Schedule Viewer 是一个非常有用的工具,它用于展示高级合成过程中算法的执行时间表(即调度)。它有助于您识别阻碍并行化的任意循环依赖关系、时序违例以及数据依赖关系。
大体上,schedule viewer 的用途包括:
可视化展示:Schedule viewer以图形化的方式展示了算法的执行顺序和并行执行的操作,可以看到各个操作是如何在时间线上被安排和执行的。
性能分析:分析设计中的性能瓶颈,设计者可以了解到哪些操作是并行执行的,哪些操作是顺序执行的。
资源利用:Schedule viewer还展示了各个操作使用的资源(如加法器、乘法器等),这有助于优化设计,以减少资源消耗,提高资源利用效率。
调试与优化:当设计未能达到预期性能或存在问题时,schedule viewer可用来识别问题(如数据依赖导致的延迟),并对设计进行相应的调整和优化。
2. Schedule Viewer详解
2.1 视图说明
2.1.1 Operation\Control Step
- 在视图左侧,显示的是将在 RTL 层级中作为逻辑来实现的操作和循环的名称。
- 括号里的名称表示操作名称。
- 操作按拓扑顺序执行。
2.1.2 周期关系图
- 竖轴虚线,由时钟不确定性而保留的时钟周期部分。
- 每项操作在表中均显示为灰框。
- 多周期操作的灰框,中间有一条水平线贯穿。
- 灰框长度,由操作延迟占总时钟周期百分比来设置。
- 运算符数据依赖关系显示为蓝色实线,选中时可见。
2.1.3 Schedule Viewer 菜单栏
- 在报告视图右上角,可提供许多便捷功能。
- 焦点控制
- 筛选
按类型筛选可根据操作的功能来限制显示的操作。例如,仅将加法器、乘法器和函数调用可视化会移除“和”与“或”之类的所有小操作。
按集群筛选的作用是充分利用调度程序的功能对基本操作进行分组,然后将其作为单个组件来调度。可启用集群筛选设置来为集群上色,甚至可在查看器内将集群折叠为单一大型操作。这样即可提供更简洁的调度视图。
2.1.4 属性视图
可查看“Schedule Viewer”中选中的特定函数、循环或操作的详细信息。
对于函数或循环,属性视图会显示:
- Initiation Interval (II)(启动时间间隔)。
- Loop Iteration Latency(循环迭代时延):表示完成循环的单次迭代所需的时钟周期数。
- Latency(时延):表示函数计算所有输出值或者循环完成所有迭代所需的时钟周期数。
- Pipelined(流水打拍):表示在 RTL 设计中对函数或循环进行流水打拍。
- Slack(裕量):表示函数或循环的时序裕量。
- Tripcount(循环次数):表示循环完成的迭代数。
- Resource Utilization(资源利用):显示用于实现函数或循环的 BRAM、DSP、LUT 或 FF 的数量。
对于运算和存储映射,属性视图会显示:
- Name(名称):对应包含代码的位置。
- Op Code(运算码):表示调度的运算,例如,add、sub 和 mult。
- Op Latency(运算时延):显示运算或存储的绑定的默认时延或指定时延。
- Bitwidth(位宽):对应运算的位宽。
- Impl(实现):定义用于指定运算或存储的实现。
2.2 内容说明
以下示例HLS加速代码,实现了一个简单的线性函数y = ax + b,对输入数组xin中的每个元素应用这个函数,然后将结果存储在输出数组yo中。
#include <ap_int.h>
void func(ap_int<8> xin[3],
ap_int<8> a,
ap_int<8> b,
ap_int<17> yo[3])
{
int i = 0;
loop:
for(i = 0; i < 3; i++)
{
yo[i] = a * xin[i] + b;
}
}
完成C Synthesis后,单击Schedule Viewer可启动视图。
2.2.1 实参(b)解释
实参(b)共包含三个操作:
- 读取操作,8bit
- 带符号的位宽扩展(sign extension),16bit
- 加法操作,Impl=dsp48,Op Latency=1
注:名称sext_In10,命名包含了此代码的位置信息,虽然此信息可能不准^_^。。。
2.2.2 实参(a)解释
实参(a)同样包含三个操作:
- 读取操作,8bit
- 带符号的位宽扩展,16bit
- 乘法操作,Impl=dsp48,Op Latency=2
lhs(left-hand side),左值是指赋值语句中被赋值的变量。lhs(sext)结合起来表示,将符号扩展后的值赋值给一个变量或表达式。
2.2.3 变量(i)解释
变量(i)共包含五个操作:
- load操作,2bit
- 整数比较icmp,输出1bit,Impl=auto,用于决定执行分支(br)
- 加法操作,2bit,Impl=fabric,变量i的自增
- 强制类型转换(zero extension),输出64bit,用于寻址xin数组
- 回写操作
注:零扩展(zero extension)是一种常见的操作,用于将无符号数的低位扩展到更高的位数上,以便进行算术或逻辑运算。
关于分支(br, branch)的分析:
- for(i = 0; i < 3; i++),i是循环变量
- i最大值3(i=2时有效),所以占2bit
- i被扩展为64bit,只是在HLS工具中生效,并不代表硬件实现
2.2.4 数组操作解释
从C综合报告来看,xin和yo均被映射为存储器。与FIFO的直接读取不通,操作存储器牵涉到寻址操作。
* SW-to-HW Mapping
+----------+--------------+---------+----------+
| Argument | HW Interface | HW Type | HW Usage |
+----------+--------------+---------+----------+
| xin | xin_address0 | port | offset |
| xin | xin_ce0 | port | |
| xin | xin_q0 | port | |
| a | a | port | |
| b | b | port | |
| yo | yo_address0 | port | offset |
| yo | yo_ce0 | port | |
| yo | yo_we0 | port | |
| yo | yo_d0 | port | |
+----------+--------------+---------+----------+
存储器操作步骤:
- xin_addr(getelementptr), get element pointer, 获取指针的偏移量,即xin数组的寻址地址。
- rhs(load),右值是指赋值语句中的值或表达式。
该操作通常用于访问数组、结构体或其他复合数据类型中的元素,以实现指针的偏移和访问。
对于yo的操作遵循同样的逻辑。
2.2.5 a*xin[i] 解释
a*xin[i]共包含五个操作:
- 从lhs(sext)_In10(sext)中取得a的值
- 从sext_In232(sext)中取得xin[i]的值
- ret_V(*)执行乘法运算
3. 总结
简而言之,Vitis HLS中的schedule viewer是设计和优化硬件加速器过程中的一个关键工具,它通过提供算法执行的详细视图,帮助设计者理解、分析和优化他们的设计。