優化手段
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];
}
}