陸 松,蔣句平,任會峰
(1.無錫學院,江蘇 無錫 214105;2.國防科技大學計算機學院,湖南 長沙 410073)
處理器作為信息處理的引擎,推動了人類社會數字化、信息化和智能化的進程。人們對處理器性能的追求永無止境。在特定領域的硬件加速,需要使用ASIC芯片、協處理器或加速卡來擴展處理器功能[1]。過去由于指令集的封閉性,這些加速部件的設計和應用軟件的開發通常滯后于處理器設計[2,3]。

Figure 2 RISC-V base opcode map,inst[1:0]=11
隨著開放指令集RISC-V的流行[4-6],其已應用于IoT智能硬件[7]、嵌入式系統[8]、信號處理[9]、人工智能[10]、安全設備[11]及高性能計算[12-14]等不同領域。大量開源和商業IP軟核[15]的出現,使RISC-V處理器的快速定制化成為可能,讓軟硬件協同設計更加高效,大幅縮短了軟硬件系統設計周期[16]。
本文基于FPGA設計了蜂鳥E203上[17,18]的計算向量內積的自定義指令,以加速矩陣運算。按照增加自定義指令、擴展ALU功能單元、連接控制信號和數據通路、FPGA原型驗證和應用程序測試的流程開展了以下工作:
(1)在RV32IMAC指令集基礎上增加計算向量內積的指令,確定指令類型和編碼;
(2)擴展蜂鳥E203軟核ALU部件,實現向量內積運算的硬件邏輯;
(3)連接控制信號和數據通路,完成向量內積指令的譯碼、派遣、執行、交付和寫回;
(4)完成自定義指令的功能仿真,并在FPGA平臺上進行原型驗證;
(5)定制GCC編譯器,增加對向量內積指令的支持,與硬件設計同步進行軟件開發。
蜂鳥E203軟核是使用Verilog語言實現的,支持RV32IMAC指令集。每條指令由操作碼、功能碼和操作數組成,具有6種基本指令格式[4,17],如圖1所示,分別是:用于寄存器-寄存器操作的R型指令、用于短立即數和訪存load操作的I型指令、用于訪存store操作的S型指令、用于條件跳轉操作的B型指令、用于長立即數的U型指令和用于無條件跳轉的J型指令。

Figure 1 Instruction format for base 32-bit RISC-V
有2種擴展RISC-V指令集的方法:
(1)模塊標準化方法。使用RISC-V的標準擴展模塊,包括B、E、H、J、L、N、P、Q等多種可選擴展[4]。
(2)在標準指令集基礎上加入定制指令。與ASIC芯片相似,指令集可裁剪,具有更高的性能,但需要注意與標準指令的編碼沖突問題。
為加速矩陣運算,本文采用了第2種方法,在RV32IMAC指令集基礎上引入一條向量內積R型指令vec_inner_prod,選擇標準指令編碼空間(如圖2所示)中的一個保留編碼1101011作為向量內積的指令操作碼,其指令格式如圖 3所示。

Figure 3 Instruction format for vec_inner_prod
蜂鳥E200系列是兩級流水線結構[17],如圖4所示,指令的譯碼、執行、交付和寫回均處于流水線的第2級,由EXU單元完成。

Figure 4 Two-stage pipeline of Hummingbird E203 IP
EXU的微架構如圖5所示,其執行過程如下:
(1)取指單元IFU通過IR寄存器將指令發送給EXU進行譯碼;
(2)通過譯碼出的操作數寄存器索引來讀取Regfile;
(3)維護指令的相關性;
(4)將指令派遣給不同的運算單元執行;
(5)交付指令;
(6)將運算結果寫回Regfile。

Figure 5 Microarchitecture of EXU in Hummingbird E203 IP
增加向量內積指令需要對指令執行路徑上的各個部件進行擴展,主要涉及“譯碼與派遣”部件、ALU、寄存器文件等。
待增加的向量內積運算部件vec_mul用于計算向量A=[A0,A1,A2,A3]和B=[B0,B1,B2,B3]的內積,向量長度為4,存放于寄存器中,其計算結果如式(1)所示:
result=A0×B0+A1×B1+
A2×B2+A3×B3
(1)
向量內積運算部件vec_mul使用4個乘法器組成計算陣列,其邏輯結構如圖6所示。

Figure 6 Logical structure of vec_mul unit
指令譯碼部件根據向量內積指令中的操作碼和功能碼來產生控制信號,并發送至ALU部件的控制信號總線上,如圖 7中①所示。當執行的指令為vec_inner_prod時,譯碼部件產生相應的operation選擇信號發送到ALU的多路選擇器,最后輸出向量內積運算部件vec_mul的計算結果。
向量內積運算部件需要掛接在ALU內部,并將其輸入端口連接至寄存器X10~X17,如圖 7中②所示。
另外,為了防止與其它長指令目的寄存器之間有沖突,需要進行數據相關性檢測,并記錄向量內積指令,如圖7中③所示。

Figure 7 Control signals for vec-inner-prod
定制化RISC-V的驗證分為3個部分:硬件平臺的驗證[19]、交叉編譯環境的驗證[20]和應用軟件的驗證。硬件平臺和交叉編譯環境的驗證用于保證硬件設計和軟件開發環境的正確性,應用軟件的驗證用于測試軟硬件的性能。驗證流程如圖8所示,定制化的RISC-V處理器設計通過EDA工具Vivado生成配置FPGA的比特流文件;應用測試程序通過定制化的交叉編譯器生成與硬件相匹配的二進制可執行文件;兩者加載到FPGA后即可在定制RISC-V處理器上運行二進制應用程序。

Figure 8 Validation procedure on FPGA
本文采用Perf-V Artix-7 35T開發板[21],如圖8所示,使用的板載FPGA型號為XC7A35T-1FTG256C,FPGA外部時鐘頻率為50 MHz。
操作系統為Ubuntu 16.04 LTS,硬件開發環境為Vivado 2018.3。
根據前述分析,在E203各部件對應的Verilog代碼中添加向量內積指令的相關運算和控制邏輯,其層次結構如圖 9所示,原理如圖10所示。

Figure 9 Hierarchy of the customized RISC-V core

Figure 10 Schematic diagram of the customized RISC-V core
在Vivado中進行綜合、布局布線(如圖11所示),最終生成配置FPGA的比特流文件并通過JTAG下載。未使用 FPGA DSP單元的情況下,增加向量內積指令及相關控制邏輯會多使用FPGA內9.3%的LUT硬件資源,增加向量內積指令前后硬件資源占用情況如表1所示。

Figure 11 Floorplan of FPGA prototype

Table 1 Resource utilization comparison for customized/non-customized RISC-V
應用測試程序必須使用定制化的交叉編譯器才能生成與硬件相匹配的二進制可執行文件。在基于64位x86架構的Ubuntu 16.04 LTS主機上定制交叉編譯器的步驟如下:(1)根據自定義指令的操作碼計算指令碼、指令掩碼并描述指令格式;(2)將其加入到編譯器源代碼RISC-V的機器描述文件[22,23]中;(3)在主機上編譯支持定制RISC-V指令的交叉編譯器。
在開發板BSP(Board Support Package)[21,24]的支持下,可將C標準庫printf等函數輸出轉發到串口。測試程序以內聯匯編的方式調用向量內積計算匯編指令,該指令匯編助記符為vec_inner_prod,編譯產生的二進制可執行文件使用OpenOCD[25]通過USER JTAG下載到flash存儲器。
測試程序為三重循環的矩陣乘法運算,外層的兩重循環對應于結果矩陣中的每個元素,內層循環用于計算2個向量的內積,未使用自定義向量內積指令的C語言代碼如程序1所示。
程序1未使用向量內積指令vec_inner_prod的矩陣乘法
for(i=0;i for(j=0;j for(k=0;k { c[i*C_COL+j]+=a[i*A_COL+k]*b[k*B_COL+j]; } 由于向量內積指令的向量長度為4,因此需要改造上述程序1中的代碼,讓內層循環中的每4個元素組成1個向量,即內層循環以4為步長進行遞增,如程序2代碼所示。對于長度不為4倍數的向量內積,可通過補零處理使其長度成為4的倍數。 程序2使用向量內積指令vec_inner_prod的矩陣乘法 for(i=0;i for(j=0;j for(k=0;k { asm volatile( "lw x10,%[a0]
lw x14,%[b0]
" "lw x11,%[a1]
lw x15,%[b1]
" "lw x12,%[a2]
lw x16,%[b2]
" "lw x13,%[a3]
lw x17,%[b3]
" "vec_inner_prod %[reg_output],x10,x14
" :[reg_output]"=r"(result) :[a0]"m"(a[i*A_COL+(k+0)]), [b0]"m"(b[(k+0)*B_COL+j]), [a1]"m"(a[i*A_COL+(k+1)]), [b1]"m"(b[(k+1)*B_COL+j]), [a2]"m"(a[i*A_COL+(k+2)]), [b2]"m"(b[(k+2)*B_COL+j]), [a3]"m"(a[i*A_COL+(k+3)]), [b3]"m"(b[(k+3)*B_COL+j]) :"x10","x11","x12","x13", "x14","x15","x16","x17" ); c[i*C_COL+j]+=result; } 對程序2最內層循環代碼進行了如下改造:使用內嵌匯編指令,將2個向量分別載入到寄存器,然后執行向量內積指令 vec_inner_prod,運算結果保存在變量result中,最后將其累加到結果矩陣中相應的元素上。 分別對程序1和程序2進行交叉編譯生成目標平臺的二進制可執行文件,兩者在FPGA平臺上的計算結果一致,對于不同規模的矩陣乘法,其所需時間如表2所示,最大加速比為7.6,最小加速比為5.3。 Table 2 Speedup of matrix multiplication on the customized RISC-V 本文基于FPGA在開源IP蜂鳥E203上通過增加自定義指令、擴展ALU功能單元、連接控制信號和數據通路、FPGA原型驗證、定制交叉編譯環境和應用程序測試的流程,設計了擴展RV32IMAC指令集的向量內積指令,實現了加速矩陣運算的定制化RISC-V處理器。對矩陣乘法測試程序上,定制化RISC-V處理器的計算性能有顯著提升,性能加速比達到了5.3~7.6。同時,基于定制化的交叉編譯器,軟件開發與硬件設計可同步進行,大幅縮短了軟硬件協同設計周期。5 實驗結果

6 結束語