HLS的FPGA開(kāi)發(fā)方法是只抽象出可以在C/C++環(huán)境中輕松表達(dá)的應(yīng)用部分。通過(guò)使用Vivado(Xilinx)或Intel(Quartus)工具,HLS工具流程基本上可用于任何BittWare板。
要想成功申請(qǐng)HLS,認(rèn)清自己申請(qǐng)的部分很重要。準(zhǔn)則包括:
- 目標(biāo)用途,一般來(lái)說(shuō),都是用高級(jí)語(yǔ)言開(kāi)始定義的IP塊。數(shù)學(xué)算法就很好用,或者像我們的RSS塊一樣,進(jìn)行一些網(wǎng)絡(luò)協(xié)議處理。
- 另一類(lèi)用途是定義不清的塊,因此可能需要多輪實(shí)現(xiàn)。這里最大的好處是允許HLS工具自動(dòng)將產(chǎn)生的原生FPGA代碼進(jìn)行流水線處理,往往比快速手工編碼流水線發(fā)出的階段更少。另外,當(dāng)需要修改手工編碼的流水線時(shí),一個(gè)并行路徑上的延遲變化會(huì)對(duì)所有的東西產(chǎn)生連鎖反應(yīng)。 使用HLS工具從頭開(kāi)始第二次自動(dòng)流水線,可以消除這種頭痛的問(wèn)題。
- 最后,HLS 流程可以更容易地在不同品牌和速度等級(jí)的 FPGA 之間移植代碼。這是因?yàn)?HLS 會(huì)自動(dòng)生成適當(dāng)數(shù)量的流水線階段--在使用 Verilog 或 VHDL 時(shí)需要手動(dòng)指定。
HLS目前的局限性很明顯,它的范圍僅限于IP塊。應(yīng)用團(tuán)隊(duì)仍然需要為其他組件提供RTL,盡管利用類(lèi)似于BittWare的SmartNIC Shell這樣的RTL部分,用戶(hù)可以完全在HLS中定義他們獨(dú)特的應(yīng)用。還應(yīng)該注意的是,對(duì)于最簡(jiǎn)單的代碼或主要由預(yù)優(yōu)化組件組成的大型設(shè)計(jì)來(lái)說(shuō),HLS是一個(gè)糟糕的選擇。
我們的應(yīng)用。在FPGA上實(shí)現(xiàn)RSS網(wǎng)絡(luò)化
什么是RSS?RSS是"Receiver Side Scaling"的縮寫(xiě)。它是一種散列算法,用于有效地在多個(gè)CPU之間分配網(wǎng)絡(luò)數(shù)據(jù)包。RSS是現(xiàn)代以太網(wǎng)卡上的一個(gè)功能,一般實(shí)現(xiàn)了微軟定義的特定Toeplitz哈希。
我們的RSS應(yīng)用的環(huán)境是BittWare的SmartNIC Shell。SmartNIC Shell的設(shè)計(jì)是為了讓用戶(hù)在構(gòu)建基于FPGA的網(wǎng)絡(luò)應(yīng)用時(shí)有一個(gè)良好的開(kāi)端。它為用戶(hù)提供了一個(gè)優(yōu)化的基于FPGA的100G以太網(wǎng)管道,包括用于主機(jī)交互的DPDK。用戶(hù)只需將其應(yīng)用作為一個(gè)IP塊放入即可。
在這種情況下,BittWare也是用戶(hù),我們創(chuàng)建了一個(gè)RSS的FPGA實(shí)現(xiàn)應(yīng)用。使用傳統(tǒng)RTL方法創(chuàng)建RSS的團(tuán)隊(duì)和HLS團(tuán)隊(duì)都能夠使用SmartNIC Shell作為他們的FPGA以太網(wǎng)框架,并專(zhuān)注于RSS應(yīng)用本身。
BittWare的RSS實(shí)施
我們基于FPGA的RSS實(shí)現(xiàn)是專(zhuān)門(mén)基于DPDK源代碼樹(shù)中的C代碼,該代碼的測(cè)試函數(shù)也可以在該樹(shù)中找到。我們的RSS應(yīng)用還使用了一個(gè)64個(gè)entry的indirection表,而不是更常見(jiàn)的128個(gè)entry的表。對(duì)于這個(gè)HLS研究來(lái)說(shuō),最重要的是我們要把函數(shù)移到FPGA中,開(kāi)始時(shí)是用C語(yǔ)言定義的,這符合我們HLS成功的第一標(biāo)準(zhǔn)--用C或C++定義。
使用圖元組對(duì)數(shù)據(jù)包進(jìn)行分組
RSS功能的目標(biāo)是在CPU之間分配數(shù)據(jù)包,使相關(guān)的數(shù)據(jù)包流保持在一起。不同的Toeplitz密鑰集提供了不同的分配模式。然而,無(wú)論密鑰集是什么,我們的RSS函數(shù)都使用每個(gè)數(shù)據(jù)包的源和目的IP地址以及源和目的端口作為輸入。這四個(gè)部分組合起來(lái)稱(chēng)為4-tuple。
請(qǐng)注意,對(duì)于我們的RSS應(yīng)用,我們假設(shè)4-tuple已經(jīng)被解析并添加到數(shù)據(jù)包的元數(shù)據(jù)中。另一個(gè)SmartNIC Shell模塊處理這個(gè)數(shù)據(jù)包分類(lèi)功能。我們稱(chēng)該模塊為"解析器",并將在另一篇BittWare白皮書(shū)中介紹。
我們的RSS實(shí)現(xiàn)目前接受96位的分類(lèi)字段--足以滿足IPv4源/目的地和端口的4元組。解析器為數(shù)據(jù)包中不可用的字段提供零;如果一個(gè)數(shù)據(jù)包不包括任何IP有效載荷,那么整個(gè)96位元組字段為零。
許多RSS實(shí)現(xiàn)使用5元組而不是4元組。 這樣做需要額外的8位來(lái)容納協(xié)議號(hào)。RSS的HLS用戶(hù)可以很容易地通過(guò)修改源代碼來(lái)適應(yīng)這種變化。這種從4-tuple到5-tuple的快速適應(yīng)能力是HLS成功的第二個(gè)標(biāo)準(zhǔn)的例子--對(duì)多輪實(shí)施的要求。
HLS性能編碼
雖然使用HLS提供了一個(gè)類(lèi)似軟件的工具流,但開(kāi)發(fā)人員仍然必須學(xué)習(xí)以硬件為中心的概念,如流水線和迭代間隔,這些概念是他們?cè)跒閭鹘y(tǒng)處理器編寫(xiě)C代碼時(shí)可能沒(méi)有接觸過(guò)的。
HLS代碼主要用于開(kāi)發(fā)嵌入式設(shè)計(jì)的IP組件,通常是流水線式的。我們的RSS應(yīng)用也不例外。對(duì)于RSS,最低的性能要求是每個(gè)512位輸入字的處理速度要足夠快,以跟上100Gb/s的飽和網(wǎng)絡(luò)接口。這相當(dāng)于每一個(gè)時(shí)鐘周期以300MHz的頻率處理一個(gè)新字。這個(gè)頻率很有挑戰(zhàn)性,因?yàn)榧词故亲羁斓腇PGA,其運(yùn)行頻率也不會(huì)超過(guò)400MHz。顯然,我們必須在每個(gè)時(shí)鐘處理一個(gè)新的字。
這里介紹了迭代間隔(II)的概念,它指的是流水線中給定的邏輯完成所需的時(shí)鐘周期數(shù),對(duì)于RSS模塊,我們要求每隔一個(gè)時(shí)鐘就有一個(gè)結(jié)果,II為1。對(duì)于RSS模塊來(lái)說(shuō),我們要求每隔一個(gè)時(shí)鐘就有一個(gè)結(jié)果,II為1,因此,我們需要了解如何編寫(xiě)代碼來(lái)避免破壞這個(gè)要求。
導(dǎo)致高二的原因包括以下幾點(diǎn):
- 當(dāng)流水線的下一個(gè)輸出需要流水線中另一個(gè)變量的未來(lái)結(jié)果時(shí),就會(huì)引起循環(huán)間的依賴(lài),例如遞歸。簡(jiǎn)單的遞歸運(yùn)算符如累加器是允許的,因?yàn)镕PGA包含的邏輯可以在一個(gè)時(shí)鐘周期內(nèi)完成這些計(jì)算。然而,更復(fù)雜的遞歸將需要更高的II值。
- RSS設(shè)計(jì)要求管道的每個(gè)階段在3.3ns內(nèi)完成。HLS工具將在需要的地方插入注冊(cè),以確保每個(gè)階段滿足這一時(shí)序要求。然而,如果組合邏輯不能被流水線化,就不一定能做到這一點(diǎn)。例如,深度組合邏輯可以是多個(gè)嵌套循環(huán)的索引計(jì)算。
- 如果目標(biāo)時(shí)鐘頻率過(guò)高,而FPGA結(jié)構(gòu)的路由路徑實(shí)在太長(zhǎng),無(wú)法滿足時(shí)序要求,II就會(huì)增加。 解決這個(gè)問(wèn)題的辦法是將邏輯分成兩條路徑,以一半的時(shí)鐘頻率運(yùn)行。
代碼的主體在所需的輸入元組字?jǐn)?shù)上循環(huán),創(chuàng)建一個(gè)新的哈希值。在這里的例子中,我們使用3個(gè)字的輸入元組,哈希值為96位。

這段代碼實(shí)現(xiàn)了RSS計(jì)算的核心。它與從DPDK源碼中提取的原始代碼保持不變。 樹(shù)。因此,在這個(gè) RSS 模塊中,所有的移植工作都是在定義模塊的 AXI 接口和添加 Pragma 語(yǔ)句到定語(yǔ)如二。
如果輸入長(zhǎng)度是一個(gè)常數(shù),F(xiàn)PGA可以完全展開(kāi)兩個(gè)循環(huán),創(chuàng)建完全流水線的代碼。
為了將IP組件集成到智能NIC框架工作中,需要定義接口和控制平面,以及任何讀寫(xiě)外部接口的邏輯。智能網(wǎng)卡框架使用AXI接口協(xié)議來(lái)進(jìn)行組件之間的通信。

定義AXI接口和添加pragma語(yǔ)句導(dǎo)致代碼行數(shù)太多,無(wú)法在這里用圖來(lái)顯示。完整的源代碼文件可以從BittWare獲得。
由于Xilinx編譯器的常量是按英特爾字節(jié)順序(little-endian),但網(wǎng)絡(luò)協(xié)議使用的是網(wǎng)絡(luò)字節(jié)順序(big-endian),因此存在一個(gè)endianness的挑戰(zhàn),這并不影響性能或資源的使用,但需要在HLS處理之前改變?nèi)魏屋斎霐?shù)據(jù)的endianness。這并不影響性能或資源使用,但要求任何輸入數(shù)據(jù)在HLS中處理之前必須改變其字節(jié)序。
本地編程與HLS的比較。結(jié)果
我們之所以有兩個(gè)FPGA RSS實(shí)現(xiàn),是因?yàn)槲覀兊某跏及姹臼怯肰erilog編寫(xiě)的。 這是在我們?cè)u(píng)估的假設(shè)下發(fā)生的:原生的FPGA編碼總是導(dǎo)致最小的資源使用。然而,一位BittWare工程師對(duì)這一決定提出了質(zhì)疑,并在HLS中重新實(shí)現(xiàn)了RSS,以測(cè)試這一方法。他是對(duì)的,BittWare現(xiàn)在已經(jīng)用HLS代碼替換了SmartNIC Shell中的RSS模塊和解析器模塊。

兩種實(shí)現(xiàn)之間最大的區(qū)別是Verilog/RTL版本使用了FIFO,而HLS C++版本沒(méi)有。 我們很驚訝地看到,轉(zhuǎn)到HLS后,資源使用量居然下降了--這是我們?cè)谒星闆r下都無(wú)法預(yù)料的。
時(shí)間上的節(jié)省呢?粗略的說(shuō),我們看到原生RTL版本的時(shí)間線為一個(gè)月,而HLS代碼在一周內(nèi)完成。
英特爾HLS與Xilinx HLS的比較
這個(gè)例子使用的是Xilinx HLS。然而,使用高級(jí)語(yǔ)言的一個(gè)關(guān)鍵優(yōu)勢(shì)是它們能夠在一定程度上抽象出不同技術(shù)架構(gòu)之間的潛在差異。英特爾也有一個(gè)等效的編譯器,也可以將C++編譯成門(mén)RTL代碼。
為了使用英特爾i++編譯器編譯相同的代碼,需要對(duì)數(shù)據(jù)類(lèi)型進(jìn)行一些細(xì)微的改變,并對(duì)#pragmas進(jìn)行修改。英特爾和Xilinx之間最大的區(qū)別是英特爾使用Avalon流媒體接口,Xilinx使用AXI。這就需要一個(gè)簡(jiǎn)單的shim接口來(lái)從一個(gè)轉(zhuǎn)換到另一個(gè)。
協(xié)同模擬
一旦功能上得到驗(yàn)證,調(diào)用協(xié)同仿真環(huán)境進(jìn)行周期精確的RTL仿真就是一件小事。Vivado-HLS自動(dòng)生成一個(gè)RTL測(cè)試平臺(tái),該測(cè)試平臺(tái)由原始C++代碼生成的向量驅(qū)動(dòng)。 用戶(hù)唯一需要修改的是處理設(shè)計(jì)中的任何無(wú)限循環(huán)或阻塞接口。RSS模塊被設(shè)計(jì)為作為固件流水線的一部分無(wú)限期運(yùn)行。因此,仿真將永遠(yuǎn)無(wú)法完成,協(xié)同仿真將掛起。為了避免這種情況,我們將RSS代碼的"while(1)"主循環(huán)改為一個(gè)固定的長(zhǎng)度,長(zhǎng)度足以消耗掉測(cè)試臺(tái)的所有輸入,并且長(zhǎng)度足以產(chǎn)生所有需要的輸出。
協(xié)同仿真使人們對(duì)工具正確生成的RTL和模塊的時(shí)序特性符合原始設(shè)計(jì)參數(shù)有了額外的信心。
協(xié)同仿真流程也可作為英特爾HLS工具棧的一部分。
按IP塊構(gòu)建HLS
HLS工具流需要對(duì)所使用的接口協(xié)議有內(nèi)置的認(rèn)識(shí)。BittWare的IP塊一般使用高級(jí)可擴(kuò)展接口(AXI)進(jìn)行通信。具體來(lái)說(shuō),就是用AXI4-Stream來(lái)傳遞數(shù)據(jù)包數(shù)據(jù),用AXI4-Lite作為控制平面。
對(duì)于100GbE,BittWare使用一個(gè)512位寬、時(shí)鐘頻率為300MHz的AXI4-Stream接口。與每個(gè)數(shù)據(jù)包相關(guān)聯(lián)的元數(shù)據(jù)在其自身的總線上跟蹤,當(dāng)數(shù)據(jù)包數(shù)據(jù)的TLAST信號(hào)被確認(rèn)時(shí),該總線在數(shù)據(jù)包結(jié)束時(shí)有效。數(shù)據(jù)包元數(shù)據(jù)在區(qū)塊之間和發(fā)布之間不斷變化。 它通常包括以下信息:
- 數(shù)據(jù)包到達(dá)的物理以太網(wǎng)連接器的編號(hào)。
- MAC識(shí)別出的與數(shù)據(jù)包相關(guān)的任何錯(cuò)誤。
- 80位IEEE-1588格式的時(shí)間戳,有時(shí)也有縮短的64位格式。
- 一個(gè)"刪除"位,表示數(shù)據(jù)包需要在下一次機(jī)會(huì)從數(shù)據(jù)流中刪除。
- 一個(gè)我們通常稱(chēng)之為"隊(duì)列"的數(shù)字,用來(lái)表示數(shù)據(jù)包的目的地。它是由管道中的一個(gè)IP塊(甚至可能是這個(gè)塊)計(jì)算出來(lái)的。
我們對(duì)RSS塊的控制平面包括:
- 啟用/禁用位
- 托普利茲哈希的20個(gè)16位密鑰
- 64個(gè)條目的間接表
?

SmartNIC Shell框架的實(shí)例實(shí)現(xiàn)框圖。這里RSS塊被替換為HLS實(shí)現(xiàn)。
結(jié)論
當(dāng)今的高級(jí)FPGA開(kāi)發(fā)工具旨在縮短產(chǎn)品上市時(shí)間,減少對(duì)硬件工程師的依賴(lài)。 然而,認(rèn)為使用這些工具總是會(huì)給應(yīng)用性能帶來(lái)妥協(xié)--無(wú)論是速度還是硅資源,這種假設(shè)是錯(cuò)誤的。
我們發(fā)現(xiàn)使用 HLS 為 BittWare 的 SmartNIC Shell 開(kāi)發(fā) IP 塊,將開(kāi)發(fā)時(shí)間從一個(gè)月縮短到一周。我們還發(fā)現(xiàn)它實(shí)際上使用了更少的門(mén)來(lái)實(shí)現(xiàn)。
XUP-P3R板的所有者和SmartNIC Shell的用戶(hù)可以獲得RSS塊的源代碼。它很好地說(shuō)明了如何在HLS代碼中使用AXI接口。
審核編輯:劉清
評(píng)論