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

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

定義AXI接口和添加pragma語句導致代碼行數太多,無法在這里用圖來顯示。完整的源代碼文件可以從BittWare獲得。
由于Xilinx編譯器的常量是按英特爾字節順序(little-endian),但網絡協議使用的是網絡字節順序(big-endian),因此存在一個endianness的挑戰,這并不影響性能或資源的使用,但需要在HLS處理之前改變任何輸入數據的endianness。這并不影響性能或資源使用,但要求任何輸入數據在HLS中處理之前必須改變其字節序。
本地編程與HLS的比較。結果
我們之所以有兩個FPGA RSS實現,是因為我們的初始版本是用Verilog編寫的。 這是在我們評估的假設下發生的:原生的FPGA編碼總是導致最小的資源使用。然而,一位BittWare工程師對這一決定提出了質疑,并在HLS中重新實現了RSS,以測試這一方法。他是對的,BittWare現在已經用HLS代碼替換了SmartNIC Shell中的RSS模塊和解析器模塊。

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

SmartNIC Shell框架的實例實現框圖。這里RSS塊被替換為HLS實現。
結論
當今的高級FPGA開發工具旨在縮短產品上市時間,減少對硬件工程師的依賴。 然而,認為使用這些工具總是會給應用性能帶來妥協--無論是速度還是硅資源,這種假設是錯誤的。
我們發現使用 HLS 為 BittWare 的 SmartNIC Shell 開發 IP 塊,將開發時間從一個月縮短到一周。我們還發現它實際上使用了更少的門來實現。
XUP-P3R板的所有者和SmartNIC Shell的用戶可以獲得RSS塊的源代碼。它很好地說明了如何在HLS代碼中使用AXI接口。
審核編輯:劉清
評論