使用 Python 與 Jupyter Notebook 快速建立 FPGA 架構設計並進行編程
資料提供者:DigiKey 北美編輯群
2019-04-03
設計人員傳統上已轉用現場可編程閘級陣列 (FPGA),以加速運算密集型應用的硬體設計效能,例如電腦視覺、通訊、工業嵌入式系統,以及日益普及的物聯網 (IoT)。然而,傳統 FPGA 編程所涉及的詳細步驟令人卻步,導致設計人員目前都還在尋求替代的處理解決方案。
目前興起的 Python Productivity for Zynq (PYNQ) 開發環境以 Jupyter Notebook 為基礎,可解決 FPGA 編程能力的問題。使用專為支援 PYNQ 而設計的開發板,即便是 FPGA 經驗較少的開發人員,也可快速實作能充分發揮 FPGA 效能優勢的設計,加速運算密集型應用的開發。
本文將介紹常見的 FPGA 方法,然後介紹並說明如何開始使用 Digilent 的開發板,其提供功能強大的開放原始碼替代方案,可加速開發 FPGA 架構系統。
為何使用 FPGA?
若需要採用複雜的運算密集型演算法,工程人員在嚴格的功率預算下,通常會依靠 FPGA 來提升執行速度。事實上,FPGA 已經在邊緣運算系統中成為加速人工智慧演算法的主要平台 (請參見《使用 FPGA 打造具備機器學習能力的高效能嵌入式視覺應用》)。
更為先進的 FPGA 系統單晶片 (SoC) 裝置則專為嵌入式應用而設計,內建可編程邏輯 (PL) 結構及微控制器。例如,Xilinx 的 Zynq-7000 SoC 在整合式可編程邏輯 (PL) 結構中結合雙核心 Arm® Cortex®-A9 處理器系統,以及多達 444,000 個邏輯元件 (圖 1)。除了內建的處理器和豐富的周邊裝置,Zynq SoC 還提供多達 2,020 個數位訊號處理 (DSP) 區塊,亦稱片段 (slice)。開發人員只要使用這些資源,就能將 PL 結構配置為專用的處理鏈,以滿足在複雜運算密集型演算法中加快數據傳輸量的需求。
圖 1:Xilinx 的 Zynq-7000 SoC 整合了雙核心 Arm Cortex-A9 處理器、可編程邏輯結構,以及許多嵌入式應用所需的大量周邊裝置與介面。(圖片來源:Xilinx)
處理器與 PL 結構的整合,除了能減少零件數量,還可跨晶片上匯流排進行操作,無需透過晶片外的存取。在啟動或重置程序中,此整合還能進一步簡化載入 PL 結構的關鍵工作。
在採用 FPGA 打造的典型微控制器架構系統中,開發人員需要管控程序和安全性,以載入 FPGA 編程位元流。藉由 Zynq SoC,整合式處理器可執行傳統的微控制器工作,包括管理 PL 結構和其他晶片上周邊裝置。因此,FPGA 載入流程更貼近於傳統微控制器的開機流程,而不是傳統的 FPGA 位元流初始化方式。
此開機流程涵蓋少許步驟順序,並由其中一個 Zynq 處理器進行管理 (圖 2)。在啟動或重置後,開機流程就算開始,此時 Zynq 處理器會執行其內部唯讀 BootROM 中的一小段程式碼,以從開機裝置擷取實際的開機程式碼。除了用來設定處理器系統元件的程式碼,開機程式碼還包括 PL 位元流及使用者應用程式。開機程式碼載入完成後,處理器會使用內含的位元流來設定 PL。在設定和 PL 組態完成後,裝置便會開始執行開機程式碼所含的應用程式。
圖 2:Xilinx 的 Zynq-7000 SoC 採用類似傳統微控制器的開機順序,首先會執行開機唯讀記憶體中的程式碼,載入及執行開機載入器,然後由其處理後續階段,包括使用開機程式碼所含的位元流來設定可編程邏輯結構。(圖片來源:Xilinx)
即使透過簡化的 PL 載入處理,開發人員過去仍需自行處理複雜的 FPGA 開發流程,才能產生所需的位元流。對於期望利用 FPGA 效能的開發人員來說,傳統的 FPGA 開發流程仍是重大的實作障礙。Xilinx 憑藉其 PYNQ 環境有效排除此障礙。
PYNQ 環境
在 PYNQ 中,PL 位元流會囊括到預先建構的函式庫中 (稱為重疊),這些重疊扮演的角色類似開發流程和執行環境中的軟體函式庫。在開機載入流程中,與所需重疊相關的位元流會設定 PL 結構。但是,如果開發人員透過與每個重疊相關聯的 Python 應用程式開發介面 (API) 來利用此重疊功能,則此流程對他們而言仍是透明可見。在開發過程中,工程人員可以依照需求,合併軟體函式庫與重疊,並透過自己的 API 來實作應用。在執行期間,處理器系統會照常執行軟體函式庫的程式碼,同時 PL 結構會實作重疊所提供的功能。結果便是效能得以提升,進一步引發人們對 FPGA 架構設計的興趣,藉此滿足日益嚴苛的應用需求。
顧名思義,PYNQ 利用 Python 程式語言所帶來的開發效率優勢。Python 之所以竄起成為最受歡迎的語言之一,不僅是因為本身相對簡單,也受惠於其龐大且持續發展的生態系統。開發人員有機會在開放原始碼 Python 模組的儲存庫中,找到支援服務或專用演算法所需的軟體函式庫。同時,由於 PYNQ 使用通用的 C 語言實作 Python 解譯器,所以開發人員也能以 C 語言實作關鍵功能。這種實作可輕鬆存取許多現有的 C 函式庫,並可輕鬆使用開發人員所提供的 C 語言函式庫。雖然有經驗的開發人員可以透過專門的硬體重疊和 C 語言軟體函式庫擴充 PYNQ,但 PYNQ 的優勢在於能提供高生產力的開發環境,供任何能建立 Python 程式的開發人員使用。
PYNQ 本身是開放原始碼專案,並以另一個 Jupyter Notebook 開放原始碼專案為基礎建構。Jupyter Notebook 提供一個特別有效的環境,能以互動方式探索演算法,並以 Python 或其他任何支援的程式語言 (目前超過 40 種) 製作複雜應用的原型。Jupyter Notebook 是在 Project Jupyter 社群的共識下進行開發,其中結合了數行可執行的程式碼,以及描述性文字和圖形。如此即可讓每位開發人員更有效地記錄進度,而不必移至其他開發環境。例如,開發人員可以使用 Notebook,將檢視資料所需的幾行程式碼與程式碼產生的圖形相結合 (圖 3)。
圖 3:Xilinx 範例儲存庫中的 Jupyter Notebook 由描述性文字、可執行程式碼,以及與應用程式相關的輸出組成。(圖片來源:Xilinx)
由於 Jupyter Notebook 是即時文件,並且是由 Jupyter Notebook 伺服器提供的互動式開發環境進行維護,因此可涵蓋程式碼、輸出和描述性文字。在 Jupyter 作業階段中,伺服器使用 HTTP 協定,在傳統的網路瀏覽器中呈現 Notebook 檔案,並綜合使用 HTTP 與 Websocket 協定來顯示該呈現文件中的靜態和動態內容。在後端,伺服器會使用開放原始碼 ZeroMQ (ØMQ) 訊息傳遞協定,與程式碼執行核心進行通訊。
圖 4:在 Jupyter 作業階段中,Notebook 伺服器將 Notebook 檔案的內容呈現至網路瀏覽器,同時與執行上述程式碼的後端核心互動。(圖片來源:Project Jupyter)
在編輯模式中,使用者可針對文字和程式碼進行修改。接著,伺服器會更新對應的 Notebook 檔案。此檔案是文字檔,其中包含一連串成對的 JSON 鍵/值。這些成對資料在 Jupyter 環境中稱為單元格。例如,在前述的 Jupyter Notebook 網路瀏覽器畫面中,便包含少許程式碼單元格和 Markdown 文字 (清單 1)。
複製 { "cell_type": "markdown", "metadata": {}, "source": [ "## Error plot with Matplotlib\n", "This example shows plots in notebook (rather than in separate window)."] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAA[truncated]", "text/plain": [ "<matplotlib.figure.Figure at 0x2f85ef50>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", " \n", "X = np.arange(len(values))\n", "plt.bar(X + 0.0, values, facecolor='blue', \n", " edgecolor='white', width=0.5, label=\"Written_to_DAC\")\n", "plt.bar(X + 0.25, samples, facecolor='red', \n", " edgecolor='white', width=0.5, label=\"Read_from_ADC\")\n", "\n", "plt.title('DAC-ADC Linearity')\n", "plt.xlabel('Sample_number')\n", "plt.ylabel('Volts')\n", "plt.legend(loc='upper left', frameon=False)\n", "\n", "plt.show()" ] },
清單 1:Jupyter Notebook 是文字檔,其中包含一連串成對的 JSON 鍵/值,這些配對含有程式碼區、標記和輸出,可對應到圖 3 所示的呈現頁面。請注意,為了方便展示,在此截取該圖的 .png 圖片所對應的字串。(程式碼來源:Xilinx)
除了記錄功能,Jupyter 環境之所以強大的關鍵,在於能以互動方式執行程式碼單元格。開發人員只要在瀏覽器中選取想要的程式碼單元格 (圖 3 中藍框部分),然後在瀏覽器視窗頂端的 Jupyter 功能表中按一下執行按鈕即可。接著,Jupyter Notebook 伺服器會將對應的程式碼單元格移交至程式碼執行核心,即 PYNQ 環境中的互動式 Python (IPython) 核心。程式碼執行後,伺服器會以非同步方式,使用核心產生的任何輸出,更新呈現的網頁和 Notebook 檔案。
PYNQ 在 Zynq SoC 的 Arm 處理器上嵌入 Jupyter 架構 (包括 IPython 核心及 Notebook 網路伺服器),藉此將此作法延伸到 FPGA 架構的開發環境中。此環境中的 PYNQ Python 模組可讓編程人員使用所需的 Python API,在 Python 程式中存取 PYNQ 服務。
FPGA 開發環境
Digilent 的 PYNQ-Z1 開發套件專為支援 PYNQ 而設計,開發人員只需載入可用的 PYNQ 可開機 Linux 映像,便能快速開始探索 FPGA 加速型應用程式。PYNQ-Z1 板結合了一個 Xilinx 的 XC7Z020 Zynq SoC,並內建 512 MB 記憶體、16 MB 快閃記憶體,以及一個 microSD 卡槽,可外接額外的快閃記憶體。除了開關、按鈕、LED 和多個輸入/輸出連接埠,此開發板還提供多種連接器,可透過 Digilent Pmod (周邊裝置模組) 介面、Arduino 的 擴充板,以及 Digilent 的 chipKIT 擴充板擴展到第三方硬體。此開發板還提供 Zynq SoC 的 XADC 類比數位轉換器 (ADC),作為六個單端類比輸入連接埠,或四個差動類比輸入連接埠。Digilent 也提供另外單獨購買的 PYNQ-Z1 生產力套件,其中包含一個電源供應器、一條 micro USB 纜線、一張預先載入 PYNQ 映像的 microSD 卡,以及用來更新或添加 Python 模組的乙太網路纜線。
透過 Jupyter Notebook,開發人員即可立即享受 SoC 和開發板的完整功能。例如,在回送測試中,若要存取開發板的 Pmod 介面來讀取 ADC 數據並寫入數位類比轉換器 (DAC) 的數值,只需要幾行程式碼即可完成 (圖 5)。匯入所需的 Python 模組後,SoC PL 即會初始化為「基礎」重疊 (圖 5 的第二個單元格)。如同傳統的開發板支援套件,此基礎重疊可存取開發板的周邊裝置。
圖 5:Xilinx 範例儲存庫中的 Jupyter Notebook,可展示與存取硬體服務進行輸入/輸出交易相關的簡易設計模式。(圖片來源:Xilinx)
開發人員只需要調用匯入的模組,即可讀寫數值 (圖中的第三個單元格)。在顯示的 Notebook 範例中,Notebook 伺服器依序發出每個程式碼單元格,並使用產生的結果來更新 Notebook。在此例中,0.3418 是唯一的輸出值,但任何執行錯誤都會顯示為一般的 Python 回溯堆疊,並與其個別的程式碼單元格保持一致。
建構複雜的應用程式
此嵌入式應用程式開發方式整合了眾多可用的 Python 模組,雖然看似簡單,但其實是一個能夠快速實作複雜且運算密集型應用程式的強大平台。例如,開發人員可使用 PYNQ-Z1 HDMI 輸入與常見的 OpenCV 電腦視覺函式庫,快速實作臉部偵測網路攝影機。載入基礎重疊與網路攝影機介面後,開發人員會初始化 OpenCV 攝影機物件 videoIn (圖 6)。接下來,只要簡單地調用 videoIn.read() 即可取得視訊影像;在此範例中返回 frame_vga。
圖 6:Xilinx 範例儲存庫中的 Jupyter Notebook,展示了開發人員如何將 PYNQ-Z1 開發板的硬體資源與 OpenCV 函式庫 (cv2) 提供的強大影像處理功能相結合,藉此快速建構網路攝影機臉部識別系統。(圖片來源:Xilinx)
在隨後步驟中,開發人員會使用預設條件建立 OpenCV (cv2) 分類器物件,並作為 Notebook 中的獨立單元格來管理,同時添加邊界方塊以識別特徵 (在此範例中,綠色為眼睛,藍色為臉部)。在另一對單元格中,應用程式在使用開發板的 HDMI 輸出顯示輸出後就會結束。
圖 7:Xilinx 網路攝影機臉部偵測 Notebook 中的最後幾個單元格,展示了 OpenCV 分類器的使用方法。分類器的結果則會用來在原始影像中添加邊界方塊,並會使用 PYNQ-Z1 開發板的 HDMI 輸出連接埠來進行顯示。(圖片來源:Xilinx)
Jupyter Notebook 具有以互動方式建立、測試並共同討論複雜軟體的能力,對於致力於最佳化人工智慧應用演算法的科學家和工程人員而言,已成為其偏好的選擇。隨著工作的演進,Notebook 不僅能顯示程式碼及其輸出,還能顯示開發人員對結果的分析,因而能提供一種可在團隊成員和同事之間共享的運算記錄手段。
雖然如此,開發人員仍需瞭解,若是著重生產力導向的工作,Notebook 則可能不適合當作其儲存庫。例如,若納入圖像資料中大量的十六進位編碼字串 (參見清單 1 中截取的部分),不僅會增加文件的大小,也會讓典型來源版本控制系統所用差異法更加複雜。而將早期分析階段所建立的程式碼,轉移到生產層級的開發流程時,交織的程式碼和非功能性文字會進一步增添複雜度。不過,在程式碼探索和快速建立原型層面上,Jupyter Notebook 則提供了強大的開發環境。
結論
FPGA 提供必要的效能增進,可在物聯網、電腦視覺、工業自動化、汽車及其他更多應用中的嵌入式系統,滿足其與日俱增的要求。雖然傳統的 FPGA 開發方法仍舊是許多開發人員的絆腳石,但以 Jupyter Notebook 為基礎的新興 Python 架構 PYNQ 開發環境,則提供有效的替代方案。使用專為支援 PYNQ 而設計的開發板,即便是 FPGA 經驗較少的開發人員,也可快速實作能充分發揮 FPGA 效能優勢的設計,加速運算密集型應用的開發。

聲明:各作者及/或論壇參與者於本網站所發表之意見、理念和觀點,概不反映 DigiKey 的意見、理念和觀點,亦非 DigiKey 的正式原則。