本文是關於Xilinx HLS的簡單介紹,從HLS是什么以及HLS的優勢出發,進一步闡述了其功能,並針對Xilinx官方的例子對其進行了分析。關鍵觀點包括
- HLS采用C/C++等高級語言描述功能,可以降低FPGA代碼的開發時間
- HLS的應用對象是硬件工程師,IP的架構設計依舊由工程師自行指定
- Vivado HLS提供了一套較為完整的代碼開發、性能分析和優化、C/RTL仿真、IP導出流程
1.使用HLS的動機
HLS(High Level Synthesis,高層次綜合)是一種代碼的綜合技術,特別的,本文中描述的HLS特指Xilinx FPGA上應用的HLS。FPGA的基本知識可以從FPGA學習之基本結構得到。Xilinx的文檔《Introduction to FPGA Design with Vivado High-Level Synthesis》中的兩幅圖可以很好的回答這一問題。
上圖表明,雖然FPGA具有的高的性能,然而采用RTL設計FPGA代碼需要較長的開發時間。
然而,采用HLS之后,FPGA開發的時間大大降低了,甚至可能低於DSP和GPU;這大大加速的FPGA的開發時間,使得開發具有了更強的靈活性和高效性,HLS的逐步完善使得FPGA的開發高效性更進一步。技術的發展使得人們可以把精力放在設計上,而更少的去關注底層的具體實現。
2.HLS是什么?
Vivado的HLS工具的前世今生可以從AutoESL與Xilinx那些人和事中看到,這篇文章寫得很有趣。HLS是高層次綜合的的簡稱,“綜合”即“Synthesis”,在ug627《XST User Guide》中解釋綜合是將程序代碼翻譯為稱為NGC的特殊網表文件中,這樣才能夠對其進行實現。
至於“層次”,或許可以這樣理解。書中一般把FPGA設計分為以下幾個級別(對於這個分級實際上沒有一個特定的說法,可以參考第13章抽象級別的描述):
- 系統級
- 算法級
- RTL級
- 門級、開關級
一般認為RTL級及以下設計是可用的,“層次”即從什么角度去描述想要實現的功能。譬如,a xor b采用門級描述就是a,b是一個異或門的輸入;而采用高一點層次描述就是a+b。顯然,越低層次的描述越困難,后文例子中也能發現這一點。
HLS就是從高層次描述,之后綜合成可用的網表文件的技術。這里的“高”指采用C、C++等編寫程序,而不是傳統的HDL語言。然而,實際上Vivado套件中是預先采用Vivado HLS這個軟件將C程序轉換成為Verilog HDL或者VHDL代碼,之后進行下一步操作的,並不是直接綜合C代碼。
3.Vivado HLS的使用
《Vivado Design Suite Tutorial :High-level Synthesis》是一本針對Xilinx HLS的很好的入門指南。通過幾個具體的例子,文檔手把手的介紹了Vivado HLS的使用方式以及功能。本節將更進一步的對其進行補充
3.1 C代碼編寫
Vivado HLS實現的最基本的功能是將C/C++代碼綜合為HDL代碼。所以編程使用的語言是C/C++語言。下面是其中的一個例子(代碼為Xilinx例程)

1 *******************************************************************************/ 2 #include "fir.h" 3 4 void fir ( 5 data_t *y, 6 coef_t c[N], 7 data_t x 8 ) { 9 #pragma HLS INTERFACE ap_vld port=x 10 11 #pragma HLS RESOURCE variable=c core=RAM_1P_BRAM 12 13 14 static data_t shift_reg[N]; 15 acc_t acc; 16 data_t data; 17 int i; 18 19 acc=0; 20 Shift_Accum_Loop: for (i=N-1;i>=0;i--) { 21 if (i==0) { 22 shift_reg[0]=x; 23 data = x; 24 } else { 25 shift_reg[i]=shift_reg[i-1]; 26 data = shift_reg[i]; 27 } 28 acc+=data*c[i];; 29 } 30 *y=acc; 31 }
代碼實現了一個FIR濾波器,輸入輸出關系如下式所示
和編寫一般的C代碼不同,編寫HLS代碼依舊需要保留硬件的思想,時刻注意硬件的限制。這一點也可以從工具的名字看出,Vivado這套設計套件是提供給硬件工程師使用的。在進行C代碼設計之前,我們需要對數據從哪來,寫到哪里去,計算過程中的並行度/流水線和各類存儲的訪問有明確的設計。C代碼實際上只是具體設計的描述,其編寫方式不是隨意的。
3.2 Pragma
和一般C代碼不同,HLS里有特定的Pragma來對代碼進行進一步指定,這是因為從C代碼中,編譯器往往得不到足夠的信息來完成優化工作,譬如
- 數據的輸入輸出采用何種接口
- 程序內部的計算並行度是多少
- 計算過程中是否需要進行流水線設計
這一些無法在C代碼中指定的內容,可以采用Pragma進行指定,以對綜合過程進行更高的控制。
譬如在上述FIR濾波器的例子中,可以使用采用更多的資源進行乘加操作,以達到更高的性能,同時對存儲進行設計以防止訪存的沖突,具體的pragma為
#pragma HLS UNROLL
#pragma HLS ARRAY_PARTITION variable=shift_reg complete dim = 1
3.3 性能分析
可以在綜合后的報告中對Performance進行評估,也可以在Analysis窗口進行其調度的進一步分析,以判斷性能是否滿足預期,如下圖所示
可以看到當了UNROLL LOOP操作后,吞吐量得到了提升(solution3 v.s. solution1)。上述優化以吞吐量為目標的,利用流水結構以及Unrolled loop可以優化吞吐量,原因如下圖所示
3.4 C/RTL仿真
在HLS中進行仿真較為簡單,采用testbench完成c語言的仿真后,RTL的仿真過程可由綜合器自動完成,點擊按鈕即可。也可具體查看仿真波形。
3.5 導出IP
略
4. 參考資料
ug902《Vivado Design Suite User Guide:High-level Synthesis》
ug871《Vivado Design Suite Tutorial :High-level Synthesis》