Vivado_HLS 学习笔记3-循环的pipeline与展开
优化手段
1 优化之:循环展开
- 对某个标记的循环进行Directive-> Unroll.
- 对循环展开的越彻底(Directive-> Unroll -> complete),消耗的资源数和端口数越多,带来的吞吐量越大.需要trade-off.
- 那么该展开到什么程度呢? 可以全部展开(complete),可以部分展开(factor:8,展开为8份);
可以学习ug871的Ch4 lab3 and lab4.
2 优化之:移位寄存器
- 如果使用C数组实现移位寄存器,那么综合出来的会是memory.
- 对某个array(shift_reg)进行Directive-> Array_Partition -> type: complete
3 优化之: 循环PipeLine
- 对于循环, 可以选择Pipeline优化-> II (Initiation Interval)保持不填,即为Interval=1 -> 选择enable loop rewinding(告诉HLS当实现为RTL时,该循环不间断运行)
- Pipeline将把循环内的操作进行流水设计.
4 工程文件组织
- top.cpp: 顶层模块, 例化一个object,并调用一系列的methods.
- top.h: 使用宏定义,对top.cpp中的object进行配置;
- class.h(.cpp): 类的定义与实现,建议使用模板;
- test.c: testbench要包括 输入激励,对照结果,测试结果,对比打分.
5 循环合并
- 相同迭代次数(常数)的循环,如果可以并行(无数据依赖), 可以使用loop merging;
- 相同迭代次数(变量)的循环,如果可以并行(无数据依赖), 可以使用loop merging;
ROM的综合
1 要综合出来MEMORY,需要使用static关键词来定义数组,并一定要使用{}进行初始化.
- static关键词的作用是保证初始化数组在函数执行时只被初始化一次,避免了每次调用函数时都需要初始化数组都要占用时间的问题。
2 const关键字,当数组只可以被读取时(会被综合为ROM). 例如`const coef_t coef[N] = {1,2,4,5,7,8}; - 当ROM内容较大时,可以使用#include的方式,注意只能这样使用(#include "coef.h"语句必须单独成一行)!
const coef_t coef[N] = {
#include "coef.h"
};
此时,"coef.h"内容为
1,
2,
3,
4 //注意最后一行的逗号用空格替代
3 复杂的情况请参考以下代码
// This template function selects the coefficient equation specific to the
// window function type chosen at class object instantiation.
template<int SZ, win_fn_t FT>
double coef_calc(int i)
{
double coef_val;
switch(FT) {
case RECT:
coef_val = 1.0;
break;
case HANN:
coef_val = 0.5 * (1.0 - cos(2.0 * M_PI * i / double(SZ)));
break;
case HAMMING:
coef_val = 0.54 - 0.46 * cos(2.0 * M_PI * i / double(SZ));
break;
case GAUSSIAN:
const double gaussian_sigma = 0.5;
double x = (i - SZ / 2) / (gaussian_sigma * (SZ / 2));
coef_val = exp(-0.5 * x * x);
break;
}
return coef_val;
}
// This template function is used to initialize the contents of the
// coefficient table. Currently, in order for the table to be mapped to
// a ROM it must be defined at file (global) scope, i.e. it cannot be
// a class method (member function).
template<class TC, int SZ, win_fn_t FT>
void init_coef_tab(TC *coeff)
{
for (int i = 0; i < SZ; i++) {
coeff[i] = coef_calc<SZ,FT>(i);
}
};
template<class TI, class TO, class TC, int SZ, win_fn_t FT>
void window_fn<TI,TO,TC,SZ,FT>::apply(TO *outdata, TI *indata)
{
TC coeff_tab[SZ];
// To ensure coeff_tab is implemented as a ROM on the FPGA, it must
// be initialized by a separate function. No hardware is synthesized
// for ROM initialization.
init_coef_tab<TC,SZ,FT>(coeff_tab);
winfn_loop:
for (unsigned i = 0; i < SZ; i++) {
//#pragma AP PIPELINE // implemented as TCL directive in this example
outdata[i] = coeff_tab[i] * indata[i];
}
}