HLS的FPGA開發(fā)方法是只抽象出可以在C/C++環(huán)境中輕松表達(dá)的應(yīng)用部分。通過使用Vivado(Xilinx)或Intel(Quartus)工具,HLS工具流程基本上可用于任何BittWare板。
要想成功申請HLS,認(rèn)清自己申請的部分很重要。準(zhǔn)則包括:
- 目標(biāo)用途,一般來說,都是用高級語言開始定義的IP塊。數(shù)學(xué)算法就很好用,或者像我們的RSS塊一樣,進(jìn)行一些網(wǎng)絡(luò)協(xié)議處理。
- 另一類用途是定義不清的塊,因此可能需要多輪實現(xiàn)。這里最大的好處是允許HLS工具自動將產(chǎn)生的原生FPGA代碼進(jìn)行流水線處理,往往比快速手工編碼流水線發(fā)出的階段更少。另外,當(dāng)需要修改手工編碼的流水線時,一個并行路徑上的延遲變化會對所有的東西產(chǎn)生連鎖反應(yīng)。 使用HLS工具從頭開始第二次自動流水線,可以消除這種頭痛的問題。
- 最后,HLS 流程可以更容易地在不同品牌和速度等級的 FPGA 之間移植代碼。這是因為 HLS 會自動生成適當(dāng)數(shù)量的流水線階段--在使用 Verilog 或 VHDL 時需要手動指定。
HLS目前的局限性很明顯,它的范圍僅限于IP塊。應(yīng)用團(tuán)隊仍然需要為其他組件提供RTL,盡管利用類似于BittWare的SmartNIC Shell這樣的RTL部分,用戶可以完全在HLS中定義他們獨特的應(yīng)用。還應(yīng)該注意的是,對于最簡單的代碼或主要由預(yù)優(yōu)化組件組成的大型設(shè)計來說,HLS是一個糟糕的選擇。
我們的應(yīng)用。在FPGA上實現(xiàn)RSS網(wǎng)絡(luò)化
什么是RSS?RSS是"Receiver Side Scaling"的縮寫。它是一種散列算法,用于有效地在多個CPU之間分配網(wǎng)絡(luò)數(shù)據(jù)包。RSS是現(xiàn)代以太網(wǎng)卡上的一個功能,一般實現(xiàn)了微軟定義的特定Toeplitz哈希。
我們的RSS應(yīng)用的環(huán)境是BittWare的SmartNIC Shell。SmartNIC Shell的設(shè)計是為了讓用戶在構(gòu)建基于FPGA的網(wǎng)絡(luò)應(yīng)用時有一個良好的開端。它為用戶提供了一個優(yōu)化的基于FPGA的100G以太網(wǎng)管道,包括用于主機(jī)交互的DPDK。用戶只需將其應(yīng)用作為一個IP塊放入即可。
在這種情況下,BittWare也是用戶,我們創(chuàng)建了一個RSS的FPGA實現(xiàn)應(yīng)用。使用傳統(tǒng)RTL方法創(chuàng)建RSS的團(tuán)隊和HLS團(tuán)隊都能夠使用SmartNIC Shell作為他們的FPGA以太網(wǎng)框架,并專注于RSS應(yīng)用本身。
BittWare的RSS實施
我們基于FPGA的RSS實現(xiàn)是專門基于DPDK源代碼樹中的C代碼,該代碼的測試函數(shù)也可以在該樹中找到。我們的RSS應(yīng)用還使用了一個64個entry的indirection表,而不是更常見的128個entry的表。對于這個HLS研究來說,最重要的是我們要把函數(shù)移到FPGA中,開始時是用C語言定義的,這符合我們HLS成功的第一標(biāo)準(zhǔn)--用C或C++定義。
使用圖元組對數(shù)據(jù)包進(jìn)行分組
RSS功能的目標(biāo)是在CPU之間分配數(shù)據(jù)包,使相關(guān)的數(shù)據(jù)包流保持在一起。不同的Toeplitz密鑰集提供了不同的分配模式。然而,無論密鑰集是什么,我們的RSS函數(shù)都使用每個數(shù)據(jù)包的源和目的IP地址以及源和目的端口作為輸入。這四個部分組合起來稱為4-tuple。
請注意,對于我們的RSS應(yīng)用,我們假設(shè)4-tuple已經(jīng)被解析并添加到數(shù)據(jù)包的元數(shù)據(jù)中。另一個SmartNIC Shell模塊處理這個數(shù)據(jù)包分類功能。我們稱該模塊為"解析器",并將在另一篇BittWare白皮書中介紹。
我們的RSS實現(xiàn)目前接受96位的分類字段--足以滿足IPv4源/目的地和端口的4元組。解析器為數(shù)據(jù)包中不可用的字段提供零;如果一個數(shù)據(jù)包不包括任何IP有效載荷,那么整個96位元組字段為零。
許多RSS實現(xiàn)使用5元組而不是4元組。 這樣做需要額外的8位來容納協(xié)議號。RSS的HLS用戶可以很容易地通過修改源代碼來適應(yīng)這種變化。這種從4-tuple到5-tuple的快速適應(yīng)能力是HLS成功的第二個標(biāo)準(zhǔn)的例子--對多輪實施的要求。
HLS性能編碼
雖然使用HLS提供了一個類似軟件的工具流,但開發(fā)人員仍然必須學(xué)習(xí)以硬件為中心的概念,如流水線和迭代間隔,這些概念是他們在為傳統(tǒng)處理器編寫C代碼時可能沒有接觸過的。
HLS代碼主要用于開發(fā)嵌入式設(shè)計的IP組件,通常是流水線式的。我們的RSS應(yīng)用也不例外。對于RSS,最低的性能要求是每個512位輸入字的處理速度要足夠快,以跟上100Gb/s的飽和網(wǎng)絡(luò)接口。這相當(dāng)于每一個時鐘周期以300MHz的頻率處理一個新字。這個頻率很有挑戰(zhàn)性,因為即使是最快的FPGA,其運行頻率也不會超過400MHz。顯然,我們必須在每個時鐘處理一個新的字。
這里介紹了迭代間隔(II)的概念,它指的是流水線中給定的邏輯完成所需的時鐘周期數(shù),對于RSS模塊,我們要求每隔一個時鐘就有一個結(jié)果,II為1。對于RSS模塊來說,我們要求每隔一個時鐘就有一個結(jié)果,II為1,因此,我們需要了解如何編寫代碼來避免破壞這個要求。
導(dǎo)致高二的原因包括以下幾點:
- 當(dāng)流水線的下一個輸出需要流水線中另一個變量的未來結(jié)果時,就會引起循環(huán)間的依賴,例如遞歸。簡單的遞歸運算符如累加器是允許的,因為FPGA包含的邏輯可以在一個時鐘周期內(nèi)完成這些計算。然而,更復(fù)雜的遞歸將需要更高的II值。
- RSS設(shè)計要求管道的每個階段在3.3ns內(nèi)完成。HLS工具將在需要的地方插入注冊,以確保每個階段滿足這一時序要求。然而,如果組合邏輯不能被流水線化,就不一定能做到這一點。例如,深度組合邏輯可以是多個嵌套循環(huán)的索引計算。
- 如果目標(biāo)時鐘頻率過高,而FPGA結(jié)構(gòu)的路由路徑實在太長,無法滿足時序要求,II就會增加。 解決這個問題的辦法是將邏輯分成兩條路徑,以一半的時鐘頻率運行。
代碼的主體在所需的輸入元組字?jǐn)?shù)上循環(huán),創(chuàng)建一個新的哈希值。在這里的例子中,我們使用3個字的輸入元組,哈希值為96位。
這段代碼實現(xiàn)了RSS計算的核心。它與從DPDK源碼中提取的原始代碼保持不變。 樹。因此,在這個 RSS 模塊中,所有的移植工作都是在定義模塊的 AXI 接口和添加 Pragma 語句到定語如二。
如果輸入長度是一個常數(shù),F(xiàn)PGA可以完全展開兩個循環(huán),創(chuàng)建完全流水線的代碼。
為了將IP組件集成到智能NIC框架工作中,需要定義接口和控制平面,以及任何讀寫外部接口的邏輯。智能網(wǎng)卡框架使用AXI接口協(xié)議來進(jìn)行組件之間的通信。
定義AXI接口和添加pragma語句導(dǎo)致代碼行數(shù)太多,無法在這里用圖來顯示。完整的源代碼文件可以從BittWare獲得。
由于Xilinx編譯器的常量是按英特爾字節(jié)順序(little-endian),但網(wǎng)絡(luò)協(xié)議使用的是網(wǎng)絡(luò)字節(jié)順序(big-endian),因此存在一個endianness的挑戰(zhàn),這并不影響性能或資源的使用,但需要在HLS處理之前改變?nèi)魏屋斎霐?shù)據(jù)的endianness。這并不影響性能或資源使用,但要求任何輸入數(shù)據(jù)在HLS中處理之前必須改變其字節(jié)序。
本地編程與HLS的比較。結(jié)果
我們之所以有兩個FPGA RSS實現(xiàn),是因為我們的初始版本是用Verilog編寫的。 這是在我們評估的假設(shè)下發(fā)生的:原生的FPGA編碼總是導(dǎo)致最小的資源使用。然而,一位BittWare工程師對這一決定提出了質(zhì)疑,并在HLS中重新實現(xiàn)了RSS,以測試這一方法。他是對的,BittWare現(xiàn)在已經(jīng)用HLS代碼替換了SmartNIC Shell中的RSS模塊和解析器模塊。
兩種實現(xiàn)之間最大的區(qū)別是Verilog/RTL版本使用了FIFO,而HLS C++版本沒有。 我們很驚訝地看到,轉(zhuǎn)到HLS后,資源使用量居然下降了--這是我們在所有情況下都無法預(yù)料的。
時間上的節(jié)省呢?粗略的說,我們看到原生RTL版本的時間線為一個月,而HLS代碼在一周內(nèi)完成。
英特爾HLS與Xilinx HLS的比較
這個例子使用的是Xilinx HLS。然而,使用高級語言的一個關(guān)鍵優(yōu)勢是它們能夠在一定程度上抽象出不同技術(shù)架構(gòu)之間的潛在差異。英特爾也有一個等效的編譯器,也可以將C++編譯成門RTL代碼。
為了使用英特爾i++編譯器編譯相同的代碼,需要對數(shù)據(jù)類型進(jìn)行一些細(xì)微的改變,并對#pragmas進(jìn)行修改。英特爾和Xilinx之間最大的區(qū)別是英特爾使用Avalon流媒體接口,Xilinx使用AXI。這就需要一個簡單的shim接口來從一個轉(zhuǎn)換到另一個。
協(xié)同模擬
一旦功能上得到驗證,調(diào)用協(xié)同仿真環(huán)境進(jìn)行周期精確的RTL仿真就是一件小事。Vivado-HLS自動生成一個RTL測試平臺,該測試平臺由原始C++代碼生成的向量驅(qū)動。 用戶唯一需要修改的是處理設(shè)計中的任何無限循環(huán)或阻塞接口。RSS模塊被設(shè)計為作為固件流水線的一部分無限期運行。因此,仿真將永遠(yuǎn)無法完成,協(xié)同仿真將掛起。為了避免這種情況,我們將RSS代碼的"while(1)"主循環(huán)改為一個固定的長度,長度足以消耗掉測試臺的所有輸入,并且長度足以產(chǎn)生所有需要的輸出。
協(xié)同仿真使人們對工具正確生成的RTL和模塊的時序特性符合原始設(shè)計參數(shù)有了額外的信心。
協(xié)同仿真流程也可作為英特爾HLS工具棧的一部分。
按IP塊構(gòu)建HLS
HLS工具流需要對所使用的接口協(xié)議有內(nèi)置的認(rèn)識。BittWare的IP塊一般使用高級可擴(kuò)展接口(AXI)進(jìn)行通信。具體來說,就是用AXI4-Stream來傳遞數(shù)據(jù)包數(shù)據(jù),用AXI4-Lite作為控制平面。
對于100GbE,BittWare使用一個512位寬、時鐘頻率為300MHz的AXI4-Stream接口。與每個數(shù)據(jù)包相關(guān)聯(lián)的元數(shù)據(jù)在其自身的總線上跟蹤,當(dāng)數(shù)據(jù)包數(shù)據(jù)的TLAST信號被確認(rèn)時,該總線在數(shù)據(jù)包結(jié)束時有效。數(shù)據(jù)包元數(shù)據(jù)在區(qū)塊之間和發(fā)布之間不斷變化。 它通常包括以下信息:
- 數(shù)據(jù)包到達(dá)的物理以太網(wǎng)連接器的編號。
- MAC識別出的與數(shù)據(jù)包相關(guān)的任何錯誤。
- 80位IEEE-1588格式的時間戳,有時也有縮短的64位格式。
- 一個"刪除"位,表示數(shù)據(jù)包需要在下一次機(jī)會從數(shù)據(jù)流中刪除。
- 一個我們通常稱之為"隊列"的數(shù)字,用來表示數(shù)據(jù)包的目的地。它是由管道中的一個IP塊(甚至可能是這個塊)計算出來的。
我們對RSS塊的控制平面包括:
- 啟用/禁用位
- 托普利茲哈希的20個16位密鑰
- 64個條目的間接表
?
SmartNIC Shell框架的實例實現(xiàn)框圖。這里RSS塊被替換為HLS實現(xiàn)。
結(jié)論
當(dāng)今的高級FPGA開發(fā)工具旨在縮短產(chǎn)品上市時間,減少對硬件工程師的依賴。 然而,認(rèn)為使用這些工具總是會給應(yīng)用性能帶來妥協(xié)--無論是速度還是硅資源,這種假設(shè)是錯誤的。
我們發(fā)現(xiàn)使用 HLS 為 BittWare 的 SmartNIC Shell 開發(fā) IP 塊,將開發(fā)時間從一個月縮短到一周。我們還發(fā)現(xiàn)它實際上使用了更少的門來實現(xiàn)。
XUP-P3R板的所有者和SmartNIC Shell的用戶可以獲得RSS塊的源代碼。它很好地說明了如何在HLS代碼中使用AXI接口。
審核編輯:劉清
評論
查看更多