如何將C / C++ / OpenCL編譯成硬件加速器
介紹
在這里,我們提供了一個(gè)關(guān)于如何生成靜態(tài)比特流的分步教程。我們以Sobel邊緣檢測(cè)算法為例來演示這一過程。但是,對(duì)于您可能想要?jiǎng)?chuàng)建的其他模塊,步驟是相同的。
設(shè)置
下面列出了我用來生成Sobel算法的靜態(tài)比特流的工具:
工具使用:
?Vivado 2018.3
?Ubuntu 16.04.5 LTS
?Avnet Ultra96v1開發(fā)板
?OpenCL, OpenCV, C/ c++
?Sobel OpenCL代碼
使用Vivado HLS創(chuàng)建自定義模塊
步驟1 -創(chuàng)建一個(gè)新項(xiàng)目
?要?jiǎng)?chuàng)建一個(gè)新項(xiàng)目,請(qǐng)轉(zhuǎn)到File > new project
?為項(xiàng)目選擇合適的名稱和位置。
?接下來,輸入程序中主函數(shù)的名稱。在我們的例子中,這是krnl_sobel。從這里您可以導(dǎo)入源文件。您還可以在稍后的過程中導(dǎo)入源文件,我將指出這一點(diǎn)。
?這同樣適用于測(cè)試臺(tái)架文件。
?該屏幕允許我們將模塊定制為特定的體系結(jié)構(gòu)。單擊下一個(gè)窗口的“部件選擇”區(qū)域中的3個(gè)點(diǎn)。從這個(gè)窗口,您可以選擇一個(gè)特定的FPGA或板。在本教程中,我們選擇一個(gè)特定的板來合成我們的模塊。需要注意的是,Vivado 2018.3不包含Ultra96平臺(tái)的入口。然而,在設(shè)計(jì)模塊時(shí),我們發(fā)現(xiàn)使用ZCU102平臺(tái)可以很好地工作,因?yàn)樗鼈兌际褂孟嗤腪YNQ FPGA。
?我們不需要擔(dān)心窗口時(shí)鐘部分的任何選項(xiàng)。您可以為您的解決方案選擇一個(gè)不同的名稱。
?最后要做的事情是選擇Finish按鈕。
?從這里右鍵單擊資源管理器菜單中的源文件,然后選擇新建文件…從這里導(dǎo)航到包含要導(dǎo)入的源文件的目錄。在同一個(gè)資源管理器菜單中的“測(cè)試臺(tái)”也是如此。應(yīng)該注意的是,您應(yīng)該包含模塊需要測(cè)試的任何頭文件或測(cè)試數(shù)據(jù)。
?您可以通過從source目錄打開該文件來查看和修改源代碼。對(duì)于本教程,源代碼將在不修改的情況下自動(dòng)合成?!半s項(xiàng)”部分包含我們對(duì)源代碼所做的修改,這樣它就可以與更大的項(xiàng)目兼容。
步驟2 - C仿真
步驟3 -合成和創(chuàng)建RTL模塊
?開始合成的按鈕是綠色三角形。
?如果合成成功,將出現(xiàn)以下選項(xiàng)卡:
?此頁(yè)簽包含生成的接口信息。例如,從和主AXI端口的總線寬度
?要?jiǎng)?chuàng)建在Vivado方框圖中使用的RTL模塊,只需按下“Export RTL”按鈕。
?對(duì)于本教程,您可以將這些選項(xiàng)保留為默認(rèn)值。
在Vivado中使用自定義模塊
步驟1 -創(chuàng)建一個(gè)新項(xiàng)目
?要?jiǎng)?chuàng)建一個(gè)新項(xiàng)目,請(qǐng)轉(zhuǎn)到File > project > new…
?按下next鍵進(jìn)入以下屏幕:
?在繼續(xù)之前,為新項(xiàng)目選擇一個(gè)合適的名稱和位置
?對(duì)于本教程,在下一個(gè)菜單中選擇RTL項(xiàng)目選項(xiàng)
?下一個(gè)窗口是將源文件添加到塊設(shè)計(jì)的一種方法:
?在本教程中,我們使用不同的方法。然而,兩者是相等的
?在本教程中,我們不會(huì)添加任何約束
?對(duì)于默認(rèn)的部件菜單,我們將轉(zhuǎn)到電路板并選擇Ultra96v1評(píng)估平臺(tái)
?如果一切正常,您可以單擊Finish按鈕并開始使用框圖
?在下一個(gè)窗口中,您可以添加sobel模塊。去工具>設(shè)置…> IP >存儲(chǔ)庫(kù)
?從這里,轉(zhuǎn)到Add,然后導(dǎo)航到存儲(chǔ)sobel模塊的位置。注意,只需要選擇文件夾,Vivado會(huì)自動(dòng)檢測(cè)其中的IP。完成后,單擊Apply和OK
步驟2 -創(chuàng)建塊設(shè)計(jì)
?從Vivado窗口的Flow Navigator菜單中,您可以選擇Create Block Design選項(xiàng)開始
?除了設(shè)計(jì)名稱外,所有內(nèi)容保持不變,設(shè)計(jì)名稱可以根據(jù)您的判斷進(jìn)行更改。
?在Vivado窗口的Diagram部分,您可以單擊,或者按CTRL + I,向圖中添加新的IP
?首先獲得代表您的處理系統(tǒng)的塊,PS.對(duì)于本教程,我們使用Zynq Ultrascale+ MPSoC PS.然后單擊彈出的“運(yùn)行塊自動(dòng)化”鏈接。確保選中PS并單擊OK
?接下來我們要設(shè)置的是一個(gè)從和主AXI端口,用于將PS連接到我們創(chuàng)建的Sobel模塊。要做到這一點(diǎn),雙擊PS塊。進(jìn)入“PS-PL Configuration > PS-PL Interfaces > Master Interface”,選擇其中一個(gè)選項(xiàng)。然后轉(zhuǎn)到Slave Interface > AXI HP并選擇其中一個(gè)選項(xiàng)
?現(xiàn)在我們添加我們創(chuàng)建的Sobel模塊。為此,導(dǎo)航到菜單,通常選擇您想要的IP并搜索您在Vivado HLS中指定的頂級(jí)函數(shù)的名稱。在我們的例子中,這是Krnl_sobel。將其添加到塊設(shè)計(jì)中。
?在彈出的窗口中單擊“Run Connection Automation”鏈接。這將添加必要的連接塊,我們需要能夠使用Sobel模塊。在按OK之前,確保所有的框都被選中了。
步驟3 -生成比特流
?生成比特流是一項(xiàng)簡(jiǎn)單的任務(wù),但首先,我們需要驗(yàn)證我們的設(shè)計(jì)。從Diagram窗口的頂部選擇Validate Design選項(xiàng),或者按F6。如果這樣做正確,它應(yīng)該告訴您從AXI端口被排除。
?這可以通過地址編輯器選項(xiàng)卡和打開sobel模塊部分,然后排除地址段來修復(fù)。要修復(fù)驗(yàn)證問題,只需右鍵單擊被排除的地址段并選擇Include segment。
重新驗(yàn)證設(shè)計(jì)
?在生成比特流之前,我們需要為我們的設(shè)計(jì)創(chuàng)建一個(gè)HDL包裝器。這很容易做到。轉(zhuǎn)到Vivado屏幕上的源菜單,右鍵單擊要?jiǎng)?chuàng)建包裝器的設(shè)計(jì)文件,然后選擇“創(chuàng)建HDL包裝器”。保持所有為默認(rèn)值并選擇OK。
?從Flow Navigator菜單中選擇Generate Bitstream。保持所有內(nèi)容為默認(rèn)值并單擊OK。這一步需要一些時(shí)間,所以去拿一杯飲料然后回來。
?要查找比特流,請(qǐng)導(dǎo)航到為項(xiàng)目創(chuàng)建的目錄。對(duì)于我們來說,我們將導(dǎo)航到sobel.runs/impl_1/design_1_wrapper.bit。注意,sobel是我們目錄的名稱,它將被您命名的目錄所替換。
?一旦你找到了。我們需要轉(zhuǎn)換可以加載到FPGA上的圖像文件。為此,我們使用Xilinx的Bootgen。這很容易做到。最好在您找到的目錄中。比特文件,創(chuàng)建一個(gè)名為bitstream.bif的文件。其內(nèi)容應(yīng)如下:
一旦比特流。如果文件已創(chuàng)建,只需執(zhí)行以下命令:
Misc
本節(jié)包含在開發(fā)過程中可能需要或想要的有用修改
32位和64位接口
采用原始的Sobel OpenCL代碼,數(shù)據(jù)總線為512位。對(duì)我們來說,這仍然是可用的,但它可以改變。為此,根據(jù)變量的不同,我們修改了函數(shù)形參列表,使其傳遞整型和整型指針。然后,我們將輸入?yún)?shù)轉(zhuǎn)換為原始類型的新變量。這使我們能夠控制數(shù)據(jù)總線的寬度。
為了使用64位數(shù)據(jù)總線,您只需要在合成前向HLS中的配置添加一個(gè)選項(xiàng)。在Vivado HLS中,單擊兩個(gè)稱為解決方案設(shè)置的黃色齒輪…,單擊“添加”,在“命令”下拉菜單中選擇“config_interface”。確保選中m_axi_addr64選項(xiàng)。
現(xiàn)在在合成之后,您的數(shù)據(jù)總線應(yīng)該是64位寬
注:請(qǐng)記住,如果您創(chuàng)建64位接口,模塊內(nèi)部寄存器將是64位。您需要將這些上32位設(shè)置為0,否則,模塊將使用存儲(chǔ)在上32位中的任何值,并導(dǎo)致潛在的任意行為。
HLS中的主、從軸Pragma
掌握語(yǔ)法
如果你發(fā)現(xiàn)你需要映射一個(gè)參數(shù)到內(nèi)存端口,基本結(jié)構(gòu)如下:
Variable_name是一個(gè)表示數(shù)組的變量。應(yīng)該注意的是,您應(yīng)該只將數(shù)組映射到內(nèi)存端口
本文編譯自hackster.io