HLS优化设计的最关键说明

对于HLS优化设计,有两个最关键的指令:一个是流水线指令,另一个是数据流指令。

正确使用这两个指令可以增强算法的并行性,增加吞吐量,并减少等待时间,但是它需要遵循某种代码风格。

unroll指令仅是for循环的unroll指令,它与流水线指令密切相关,因此我们将其放在一起。

首先,让我们看一下Xilinx官方指南中对这三个指令的定义:展开:展开循环以创建多个实例软循环体及其指令可以独立地计划调度。

管道:通过允许循环或函数在当前执行的代码/函数中优化并执行可重复执行的操作,数据流通过启用或执行可循环执行的功能来减少迭代间隔,数据流:通过启用或执行可优化的循环执行。

for循环的区域。

该指令不包括流水线执行的概念,只是展开循环主体以确保使用更多的并行硬件资源。

它们在调度过程中彼此独立。

流水线指令可以在循环和功能级别上使用,并且初始化间隔可以通过增加重复的操作指令(例如增加资源使用率等)来减少。

Dataflow指令是任务级别的流水线指令,它允许从更高的任务级别并行执行循环或功能,目的是减少延迟并提高吞吐量。

展开指令和流水线指令之间的重叠之处在于,当对函数进行流水线处理时,以下分层结构中的所有循环都将自动展开,并且使用展开指令的循环不会对II施加约束。

在最新版本的VitisHLS工具中,该工具将自动分析数据之间的流水线操作关系并以II = 1对其进行优化,但仍然会受到设计本身的算法和代码风格的限制。

下图清楚地阐明了“展开”和“管线”指令之间的关系。

Pipeline指令放置的循环级别越高,循环展开级别越高,这最终将导致使用更大面积的资源来实现,并且并行度也更高。

在此,如果循环的边界是变量,则无法扩展。

这将组织要流水线化的功能。

您可以添加行程计数之类的指令来指定综合过程中循环的最大和最小边界。

在循环流水线优化的过程中,存在完美循环,半完美循环和不完美循环的代码风格概念。

只有当管道循环完美或半完美时,嵌套循环才能完全并行展开。

完美循环:仅最内部的循环具有主要内容,在循环语句之间未指定逻辑,并且循环限制为常数。

半完美循环:只有最里面的循环具有主体(内容),在循环语句之间未指定逻辑,并且只有最外面的循环边界是可变的。

不完善的循环:循环的主要内容分布在循环的每个级别,或者内部循环的边界是变量。

在努力成功执行最大的管道循环时,我们需要手动将不完美的循环修改为完美或半完美的循环。

以下代码示例显示了VitisHLS中的完美循环(左)和不完美循环(右)的执行结果。

Perfect_loop#include“ loop_perfect.h” voidloop_perfect(din_tA [N],dout_tB [N]){inti,j; dint_tacc; LOOP_I:for(i = 0; iLOOP_J:for(j = 0; jif(j == 0)) acc = 0; acc + = A [j] * j; if(j == 19){if(i%2 == 0)B [i] = acc / 20; elseB [i] = 0;}}}} voidloop_imperfect(din_tA [N],dout_tB [N]){inti,j; dint_tacc; LOOP_I:for(i = 0; iacc = 0; LOOP_J:for(j = 0; jacc + = A [j] * j;} if (i%2 == 0)B [i] = acc / 20; elseB [i] = 0;}}综合完成后,我们可以在分析窗口和综合报告中清楚地看到完美的循环正在执行当时间到时,该工具自动将内循环LOOP_J和外循环LOOP_I合并为一个完整的大循环,并实现整个大循环的流水线操作,延迟周期数为:(400-1)* 1 + 8 -1 = 406个周期,延迟约为408 * 2.5 = 1,020ns。

在不完美的循环中,内部和外部循环没有合并,只有内部循环LOOP_J实现了流水线执行,浪费了进入和离开内部循环的时钟周期循环增加整个循环。

同时,有些命令行无法实现整个循环级别的调度优化。

这些因素导致了设计延迟的增加。

产品知识/行业、品牌资讯