Vivado HLS(High-level Synthesis)筆記一:HLS基本流程

前言

實驗室項目需要,需要將在服務器段跑出的網絡參數配置到FPGA上,一種方法是直接利用verilog或者vhdl直接去寫一個網絡的前向傳播模型,另一種就是用 C/C++ 來描述網絡的前向傳播模型,然後利用Vivado的HLS將其轉化爲硬件描述語言——verilog或者vhdl。第一種方法資源利用率高,但需要考慮時序和並行性(硬件語言設計的兩個重要因素),這一點比較困難;第二種方法相對高效且容易一點;作爲一個新手,本着先將流程跑通的想法,我選擇了第二種方法作爲首次嘗試的方法,通過高亞軍老師的視頻課來學習的,附上鍊接:https://www.bilibili.com/video/av41246874

先來談談CPU、GPU、DSP、FPGA之間的區別:https://blog.csdn.net/Qiuoooooo/article/details/81779583

對於一個軟件工程師,應該掌握的程度:

  1. FPGA內部每個單元的功能;
  2. 具體的算法操作和每個單元之間的對應關係;
  3. 算法模型中資源的利用率;
  4. 算法模型的優化方法;

總結起來就一句話“怎樣能使得我們用C/C++轉化成的HDL代碼可以高效運行?

一. Vivado HLS的工作原理

1. History of ESL(Electronic System Level)

 CAD-CAE-EDA
 - Computer Aided Design
 - Computer Aided Engineering
 - Electronic Design Automation

在EDA這個階段,最典型的特徵就是出現了硬件描述語言——VHDL和Verilog;

到了現在,就出現了ESL(電子系統級設計方法)這個概念,它的本質是在說在ESL這個階段我們希望採用具有更高抽象度的方式去描述系統行爲,所以在這個階段有兩個顯著特徵:

  • 使用高級語言(例如C或者C++),XILINX有Vivado HLS這個工具;
  • 使用基於模型的設計工具——System Generator;

2. High-level Synthesis Benefits

  • 對於硬件工程師,提高項目效率,不需要考慮並行性和時序的問題,直接在算法級考慮優化;
  • 對於軟件工程師,可以提高系統性能,原來需要CPU、GPU或者DSP才能實現的算法現在都可以通過FPGA來實現,一方面提高了吞吐率,另一方面也改善了功耗;
  • 在C/C++這個層面開發算法並且驗證;
  • 通過優化工具來高效指導轉化過程;

在算法描述完成後,需要一個相應文本來測試我們的算法,

3. Vivado HLS的綜合流程

在這裏插入圖片描述

  • Scheduling:確定每個時鐘週期應該做什麼操作,同時這個操作大概需要幾個時鐘週期完成,以及是否可以並行執行;
  • Control Logic Extraction:控制邏輯的提取通常會生成一個狀態機,這個可以在HDL代碼中看到;
  • Binding:確定每個操作需要用什麼資源去實現,完成這樣的一個從操作到資源映射過程;

下面來看一下對於這幾個過程的實例:
Scheduling and Binding Example的例子如下,下面這個例子比較簡單,所以只有一個狀態C0;
在這裏插入圖片描述
擴至邏輯的提取例子,有四個狀態,在C0狀態執行b+c,C1狀態產生x和數組的地址,C2狀態執行相應的乘法操作,C3狀態將結果寫入y數組的對應位,如此循環幾次,直到到達循環邊界退出循環。需要注意的是,生成的控制狀態(左下)和狀態機(右下)不是一一對應的,但它們之間非常接近。
在這裏插入圖片描述

4. Vivado HLS設計流程

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

  • Vivado HLS的設計輸入包括Test bench、C/C++和Directives,相應的設計輸出有IP(在Vivado的IP Catalog中)、DCP(RTL代碼綜合後的網表文件)、SysGen(HLS之後的結果可以導入SysGen中使用)。
  • Test bench的作用有兩點:一是驗證C/C++代碼的正確性;二是在與RTL的協同仿真階段,生成用於RTL級驗證的Test bench;
  • 對於一個工程,只可以有一個頂層的函數用於綜合,這個函數下面的子函數也可以被綜合,通常情況下C/C++綜合後的RTL代碼的結構和原始的C函數描述的結構一致(除了子函數所需要的邏輯量很小、算法功能很簡單時,綜合階段不會單獨有這個結構,將HLS INLINE off關掉時就會完全一致)。
  • 並不是所有的C/C++語言風格的代碼都能被綜合,有兩點需要注意:一是動態內存分配,二是操作系統層面
  • 一個C/C++代碼最後映射到RTL代碼有三大類接口,包括Block-level IO Handshake(握手信號)、C Inputs、C Outputs;

Directives的兩種方式

  • 將每個directive以directives.tcl格式作爲一個Tcl命令單獨存放,以"#"作爲標識;
    優勢在於:每個solution都有獨立的directives,如果這個solution需要重新綜合,那麼只有這個solution下面的directive會起到作用;不足之處在於:如果C source code文件需要被給到第三方,那麼需要將directives.tcl包含其中,對於一個代碼需要獲得同樣的綜合結果,那麼同樣的directives.tcl必不可少。

  • 將每個directive嵌入到C/C++源碼中,以pragma格式出現,"%"作爲標識;
    優勢在於:如果C source code文件需要被給到第三方,不需要單獨將directives.tcl交付,對於一個代碼需要獲得同樣的綜合結果,也不需要額外的directives.tcl;不足之處在於:如果一個solution需要重新綜合,那麼所有的directives都要被執行。

幾點小技巧

  • 爲C/C++代碼中的for循環單獨創建標籤,這會使得在創建directives時非常方便;
  • 最好將directives單獨存放,不要將其和源碼放在一起;
  • Test bench中的main()函數的返回結果值爲int類型,仿真通過返回值爲0,不通過纔是1;
  • 通常情況下RTL代碼的層次和原始的C/C++代碼層次一致;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章