惠城网站制作,天津网站建设要多少钱,app开发软件公司,wordpress记录修改文章时间本笔记使用的Vitis HLS版本为2022.2#xff0c;在windows11下运行#xff0c;仿真part为xcku15p_CIV-ffva1156-2LV-e#xff0c;主要根据教程#xff1a;跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习
从这一篇开始正式进入HLS对C代码的优化笔记
目录
1.循环优化中的基…本笔记使用的Vitis HLS版本为2022.2在windows11下运行仿真part为xcku15p_CIV-ffva1156-2LV-e主要根据教程跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习
从这一篇开始正式进入HLS对C代码的优化笔记
目录
1.循环优化中的基本参数2.PIPELINE UNROLL 2.1.PIPELINE 2.2.UNROLL3.LOOP_MERGE 1.循环优化中的基本参数
以如下程序为例top.h
#include ap_int.h#define N 3#define XW 8
#define BW 16typedef ap_intXW dx_t;
typedef ap_intBW db_t;
typedef ap_intBW1 do_t;void func(dx_t xin[N], dx_t a, db_t b, db_t c, do_t yo[N]);top.cpp
#include top.hvoid func(dx_t xin[N], dx_t a, db_t b, db_t c, do_t yo[N])
{int i 0;loop:for (i 0; i N; i){yo[i] a * xin[i] b c;}
}从本篇开始top函数更改为通用的func这样只改其中的逻辑和参数就行记得第一次运行要在设置中更改Top函数更改方式请参考上一篇笔记。
从程序代码出发对loop标签下的for循环进行分析可以得到其全过程时序如下其中每个属性的含义
1 clock cycle一个基本操作需要一个时钟周期
Loop Trip Count循环次数N3所以为3
Loop Iteration Latency一轮循环执行所需时间
Loop Iteration Interval(Loop II)两轮循环相隔的时间这里和循环执行时间相等的原因1.HLS识别到循环次数为常数省略了对变量i的操作如果N是变量则这个时间会相应增加。2.在编程中并未让其流水线操作或展开UNROLL否则这个时间会减少或直接为0。
Loop Latency循环总执行时间等于Loop Iteration Latency * Loop Trip Count
Function Latency函数的执行时间这里应该是Rd a,b,c这三个变量传进来之后不再改变读一次就行
Function Initial Interval(II)两轮函数的执行间隔这里应该放在Rd之前函数放在一个循环内时1.如果函数执行结束到下一轮该函数执行之间有操作的话这一时间会增加2.如果对循环和函数进行优化函数可能并发执行多个函数实例间隔为0、流水线执行间隔减小2.PIPELINE UNROLL
2.1.PIPELINE
For循环最常见也是最常用的优化就是PIPELINE可以右键Directive中循环的标签进行添加所有循环都应添加标签便于进行优化和DEBUG也可以在循环的左大括号下一行添加#pragma HLS PIPELINE
loop:for (int i 0; i N; i){
#pragma HLS PIPELINE/* 函数体 */}添加PIPELINE后第一节提到的Loop Iteration Interval (Loop II)循环迭代间隔就变为了1因为3次循环间没有数据依赖所以间隔为一个cycle循环耗时从9减少到5 2.2.UNROLL
UNROLL会将循环全部展开如循环次数为3则将原本1组电路进行3次运算更改为3组电路分别进行1次计算通过消耗N倍资源换取N倍效率其添加方法与PIPELINE相同
#pragma HLS UNROLL有时循环的次数实在过多全部展开会用光板子的资源那么我们可以将其部分展开使用UNROLL的参数factor进行配置如factor3时会将循环展开为3组电路消耗3倍资源换取3倍效率
// factor为复制份数消耗资源倍数
#pragma HLS UNROLL factor3我们之前提到过将C原本的数据类型换为HLS的任意精度数据类型可以增加资源利用率那么我们复制了这么多循环for()中i的类型是否要考虑更换呢事实上vitis会考虑i的最大值也就是N来对其实际占用的空间进行资源优化int i 0;和ap_int4 i 0;实际没有区别如果iN的N是变量那么N的数据类型是很重要的这一点在以后会讲到。
3.LOOP_MERGE
考虑如下图中的情况add循环和sub循环都用到了a[i]和b[i]并且循环上限都为N从硬件设计的角度上讲这两个循环完全可以合并如右图中的逻辑 在这里我们引入loop region的概念它实际上就是对一段大括号括起的代码块声明的标签在这里用作LOOP_MERGE的作用域。
然后我们对loop region添加LOOP_MERGE约束与for添加约束的逻辑相同通过图形界面Directive右键添加或者在代码块第一行编写#pragma HLS LOOP_MERGE就可以实现两个循环的并发执行
void func(data_t a[N], data_t b[N], data_t c[N], data_t d[N])
{int i;loop_region:{
#pragma HLS LOOP_MERGEadd:for (i 0; i N; i){c[i] a[i] b[i];}sub:for (i 0; i N; i){d[i] a[i] - b[i];}}
}这样不仅能提高效率并且在代码编写的过程中可以更好的区分逻辑让代码有更好的可读性和可维护性。
如果两个循环的边界不同如下图 合并时将根据更大的循环决定循环次数这没有问题较少的那个循环之后就不会获取这个循环模块的sub输出了。 需要注意的是如果两个或多个循环的循环上限有常量也有变量那么LOOP_MERGE会报错 而如果循环上限有2个及以上的变量那么即便变量的范围相同LOOP_MERGE也会报错 如何避免这样的问题如果编程者可以通过设计预先确定多个变量中哪个变量最小那么就可以LOOP_MERGE最小变量次数的循环然后在loop region外执行剩余的循环如下是能确定KJ的情况 下一篇笔记将对For循环的DATAFLOW、嵌套和其他优化进行介绍。