浮點具有更大的數(shù)據(jù)動態(tài)范圍,從而在很多算法中只需要一種數(shù)據(jù)類型的優(yōu)勢。 本文介紹如何使用Vivado HLS實現(xiàn)浮點復(fù)數(shù)矩陣分解。使用HLS可以快速,高效地實現(xiàn)各種矩陣分解算法,極大地提高生產(chǎn)效率, 降低開發(fā)者的算法FPGA實現(xiàn)難度。
?
void matrix_dcmp
(
cf_t in_u[(R_DIM+Y_DIM)/DIV_NUM][DIV_NUM],
cf_t pd_err_in,
float lamda,
float lamda_sqrt,
float diag[R_DIM],
cf_t r[R_DIM][X_DIM],
cf_t p[R_DIM]
)
{
coef_cal(lamda_sqrt,lamda,diag[i],pre_in_u,pd_err_in,&s_o,&s_conj_o,&la
mda_sqrtxs_o,&c_o,&lamda_sqrtxc_o,&diag_out,&p_o,&pd_err);
cal_core(u_tmp, r_tmp, s_n, i, j, k, c_o, lamda_sqrtxc_o, lamda_sqrtxs_o,
s_conj_o, &in_u_w2, &r[i][r_addr]);
}
void coef_calc
(
float lamda_sqrt,
float lamda,
float r_diag,
cf_t u_diag,
cf_t pd_err_in,
cf_t *s,
cf_t *s_conj,
cf_t *lamda_sqrtxs,
float *c,
float *lamda_sqrtxc,
float *diag,
cf_t *p_o,
cf_t *pd_err
)
void calc_core
(
cf_t in_u,
cf_t r,
int s_n,
int i,
unsigned char j,
unsigned char k,
float c_o,
float lamda_sqrtxc_o,
cf_t lamda_sqrtxs_o,
cf_t s_conj_o,
cf_t* u_ret,
cf_t* r_ret
)
Vivado-HLS生成的RTL代碼在默認(rèn)情況下保留原有c代碼的層次結(jié)構(gòu),在構(gòu)建c代碼層次時,可以采用由上至下,從下至上相結(jié)合的模塊劃分方式。對基本的浮點運算如加,減,乘,除,平方根等寫成最底層的子函數(shù),并對其加pipeline, 甚至對輸出打一拍register以獲得更好的時序性能。如下例:
template T reg(T x) {
#pragma HLS inline self off
#pragma HLS interface ap_none register port=return
return x;
}
cf_t mult( cf_t in1, cf_t in2 ) {
#pragma HLS PIPELINE
cf_t out;
float in1_re_in2_re, in1_im_in2_im, in1_re_in2_im, in1_im_in2_re;
in1_re_in2_re = hfmult(in1.re,in2.re);
in1_im_in2_im = hfmult(in1.im,in2.im);
in1_re_in2_im = hfmult(in1.re,in2.im);
in1_im_in2_re = hfmult(in1.im,in2.re);
out.re = (in1_re_in2_re - in1_im_in2_im);
out.im = (in1_re_in2_im + in1_im_in2_re);
return reg(out);
}
float hfmult
(
float in1,
float in2
)
{
#pragma HLS PIPELINE
float out;
out = in1 * in2;
return reg(out);
}
另外為了提高運算的并行度,需要對matrix_dcmp中in_u及r數(shù)組(HLS綜合成FPGA的BRAM或分布式RAM)加數(shù)組分割這個directive,這樣數(shù)據(jù)才可以并行進(jìn)來到并行處理單元。
#pragma HLS ARRAY_PARTITION variable=in_u complete dim=2
#pragma HLS ARRAY_PARTITION variable=r complete dim=2
3,Vivado-HLS矩陣分解時序優(yōu)化
為了使in_u綜合出的RAM時序更好,可以對in_u綜合的RAM加resource directive來控制其為3 stage,這樣生成的RAM輸入,輸出都會打一拍register。
#pragma HLS RESOURCE variable=in_u core=RAM3S
同樣我們也可以通過設(shè)置充足的latency directive給DSP48,這樣有足夠的時鐘節(jié)拍給到DSP48內(nèi)部打拍register。
如果對上述的單精度浮點乘法hfmult latency設(shè)置為3,這樣分配到每個DSP48 內(nèi)部只有2級latency, 那么綜合總合出來代碼DSP48內(nèi)部的A_reg 或 P_reg不會打一拍, 這樣對時序性能有很大下降。
derive_core fmul_der -base FMul_maxdsp -latency 3 -fixed
set_directive_resource -core fmul_der hfmult out
?
或
?
為了達(dá)到較好的時序性能,對上述的單精度浮點乘法hfmult latency至少設(shè)置為4,這樣分配到每個DSP48 內(nèi)部只有3級latency, 那么綜合總合出來代碼DSP48內(nèi)部的A_reg 或 P_reg都會各打一拍。
derive_core fmul_der -base FMul_maxdsp -latency 4 -fixed
set_directive_resource -core fmul_der hfmult out
?
4,Vivado-HLS矩陣分解設(shè)計結(jié)果
這個設(shè)計中矩陣的大小是128x128的單精度浮點,復(fù)數(shù)。
采用了串行與并行結(jié)合的實現(xiàn)方式。
評論