劉 鵬,劉 杰,賈 訊
(江南計算技術研究所,江蘇 無錫 214215)
在高端服務器或低功耗嵌入式產品中,調試機制雖然不受關注但不可或缺。已經通過驗證測試的成熟芯片產品一般提供非入侵式、入侵式這兩種或其中一種調試機制[1]。入侵式調試機制主要通過軟件或硬件中斷陷入調試模式[2],主要以斷點和單步調試為代表。用戶在斷點和步進調試過程中,可以控制應用程序代碼運行到代碼中的指定點,然后Halt 標識的處理器,此時,用戶可以選擇檢查或更改內存以及寄存器內容,步進或重新啟動應用程序。非侵入式調試機制以跟蹤(Trace)模式為主,主要實現方式是將CPU 狀態及指令流信息壓縮導入存儲器,協同軟件解壓縮開展現場或性能分析,能夠幫助用戶查證CPU 在全速運轉下才出現的或偶然發生而不可預測的錯誤[3]。
本文針對某自主國產SoC 芯片(下文簡稱為GCXP),設計一個保證用戶可調試觀測和安全性的用戶調試解決方案。調試行為通過中斷及其處理程序來實現,保證在調試中斷監控下開展調試行為。兼容開源上位機OpenOCD 調試軟件生態,從而支持Eclipse等IDE。不同于ARM、Sivife 等需要進行CPU 設計,本文方案向CPU IP 核已經設計完備的SoC 中增加硬件輔助調試功能,不需要修改CPU 設計。
目前,大多數處理器都獨立設計了一套調試體系結構,以便于用戶進行片上調試。例如,x86 體系結構提供了6 個調試寄存器來支持硬件斷點和調試異常[1],同時Intel Processor Trace[2]也是一個備受關注的硬件輔助調試特性[3-4]。Arm 架構的處理器具有調試和非調試兩種狀態,并設計了一組調試寄存器來支持自主機調試和外部調試[5-6]。同時,ARM[7-9]還引入了硬件組件,如Embedded Trace Macrocell[10]和Embedded Cross Trigger[11],以完成各種硬件輔助調試目的。相應地,硬件供應商通過片上調試端口將上述調試特性暴露給外部調試器,比較常用的調試端口是IEEE 1149.1[12]定義的聯合測試工作組(Joint Test Action Group,JTAG)端口,主要用來支持調試目標和外部調試工具之間的通信。使用JTAG端口和外部調試工具(如Intel System Debugger[13]、ARM DS-5[14]、OpenOCD[15]),開發人員能夠有效、方便地訪問目標的內存和寄存器。
ARM 的調試基礎架構稱為CoreSight,主要實現調試和跟蹤這2 個功能:
1)調試功能,運行處理器的控制,允許啟動和停止程序單步調試源碼和匯編代碼,在處理器運行時設置斷點,即時讀取/寫入存儲器內容和外設寄存器,讀寫內部和外部FLASH 存儲器。
2)跟蹤功能,提供程序計數器采樣、數據跟蹤、事件跟蹤等,實現CPU 歷史序列調試、軟件性能分析和代碼覆蓋率分析。
開源SoC 硬件輔助調試解決方案主要有RISCV Debug Spec 0.11/0.13[16]、Open SoC Debug(OSD)[17],兩者都描述了基于Run-Stop、Trigger、System Bus Access調試的具體規范細節,后者著重描述Trace 模式并給出了基于Rocket-Core 的參考設計實現,需要在Core 內實現Core Debug Unit 邏輯,前者有獨立的Trace-Spec[18],依賴CPU 預留Core Trace IO。
在GCXP 系列中,用戶通過片外維護控制模塊訪問I/O 和存儲空間,CPU 片內狀態通過掃描鏈硬件邏輯來觀測調試[19-20]。同時,特有的HMCODE 機制也可以在核心驅動調試以承擔調試功能,但一般不對用戶開放。與商業SoC 調試功能相比,現階段GCXP 系列產品的調試機制缺少安全性[21]以及交互、斷點、靈活讀寫功能,同時缺乏上位機調試軟件IDE 工具生態[22],尤其在安全性和嵌入式用戶調試工具生態上,存在較大缺陷,如基于掃描鏈重用的調試機制,因掃描鏈在芯片上留下一個獨立的邏輯接口,不受任何權限檢查,可以在任何時刻獲取芯片內部的狀態信息,相當于為芯片增加了一個“后門”。同時,文獻[21]中也提到了一種JTAG 掃描鏈攻擊的逆向技術,黑客可以獲取掃描鏈上芯片架構設計相關細節信息。在嵌入式用戶調試工具方面,ARM、Sifive 都配備對應的上位機IDE 或兼容主流開源IDE,如Eclipse、Keil 等,與硬件調試輔助機制相結合,可以提供便捷豐富的寄存器以及內存觀測讀寫、斷點、程序下載、性能分析功能。
GCXP 硬件輔助調試配套軟件部署要求較高(可參見文獻[20]),且只提供觀測功能,目前沒有與商業SoC 產品類似的用戶環境。此外,交互式調試設計需要CPU 設計配合,是流水線設計的重要一環,且目前沒有向已有成熟CPU 設計的SoC 環境中增加交互調試的方法。
GCXP-1A 是一款面向低功耗嵌入式領域、采用精簡GCXP 指令集的國產通用處理器核心,實現了全獨立自主指令集嵌入式子集,是GCXP 架構下面向嵌入式領域的處理器核心,該核心采用IP 化設計,指令、數據存儲器工作模式、TLB 條目數等關鍵微結構參數化設計,并實現標準AXI 接口,便于通用SoC 集成。
GCXP-1A 設計主要參考RISCV Debug Spec 0.13.2 規范及Sifive U500K 開源SoC源碼,兼容RISCV OpenOCD 軟件調試工具及OpenOCD 的IDE生態,結合GCXP 軟硬件架構開展調試模塊設計,結合GCXP 特權架構開展用戶調試工具的硬件設計,同時在OpenOCD 軟件端開辟GCXP 分支,兼容RISCV Debug Spec 0.13.2 流程,實現完整的Run-Stop 侵入式調試機制以及OpenOCD 接口下的基本調式、程序下載功能,相較于無感知的掃描鏈重用調試信息獲取,該方法處于調試中斷語義監控環境中,安全性更高,并且對CPU 核內無設計要求,借助OpenOCD,可直接與GDB、開源IDE 產品對接,可以向前擴展CPU 產品的通用調試生態,同時開展模擬驗證及FPGA 驗證,從而證明功能的正確性。
RISCV Debug Spec 0.13.2 Spec 中 對CPU 設 計提出了諸多要求,例如,需要2 條調試專用指令EBREAK、DRET,Trigger 硬件斷點寄存器,以及調試模式與配套的DPC、DCSR 寄存器等,同時,在流水線控制上也需要對應的設計。在GCXP 特權架構下,為了不對原有CPU 設計、操作系統核軟件接口及編譯工具鏈設計進行改動,取消調試模式(調試模式在RISCV 開源CPU 中實現,特權層級還是處于M 模式,嚴格上來說并不算是一種獨立的特權層級),同時,EBREAK 與DRET 分別設計成GCXP 指令集中的SYSCALL,并分別約定特定的調用號,將DPC、DCSR 放入Debug Module(IO 地址空間)中。同時,因為GCXP HM 特權架構不響應中斷,所以將RISCV Trigger 調試中斷、單步調試、硬件調試中斷都進行重新設計,并設置對應的HMCODE 處理軟件程序,以實現Spec 中調試中斷處理的硬件邏輯部分。
由于GCXP-1A 面向低功耗MCU 場景,因此調試機制設計主要考慮用戶調試應用程序的Run-Stop調試以及外設I/O、Memory 內容讀寫功能這些需求,從而實現中斷調試模式、總線訪問調試。GCXP-1A的具體硬件邏輯架構如圖1 所示。

圖1 GCXP-1A 用戶調試模塊的邏輯架構Fig.1 Logical architecture of GCXP-1A user debugging module
RISCV Debug Spec 0.13.2 中主要規范了一套抽象調試命令,便于不同架構具體實現與調試工具及生態解耦,其Run-Stop 調試機制基于DM 模塊接管PC 來實現,分為Trigger 中斷(由硬件斷點觸發)、上位機調試中斷、軟件斷點陷入調試中斷這3 類,最終通過Debug ROM 程序與調試模塊(Debug Module,DM)狀態機協同路由,決定CPU PC 取指地址,從而執行從抽象命令解析、翻譯、預裝填到抽象命令相關字段所指定的不同存儲空間的調試命令。
GCXP-1A 用戶調試模塊的邏輯架構主要實現用戶程序異常中斷調試、提供斷點環境通用寄存器及CSR 寄存器的訪問、提供SoC 總線上外設I/O 寄存器或存儲器的訪問。具體如下:
1)DM_TRANSPORT 模塊負責JTAG TAP 狀態機的實現,以及上位機指令操作向DM_ROUTER模塊內部總線的轉寫,主要分為DM_TRASNPORT寄存器訪問和DM 內部總線訪問,前者主要是標識調試協議實現版本,后者用于交互具體的調試任務。
當TAP 狀態機進入Update-DR 狀態,IR 寄存器的值為DMI_ACCESS(5’h11),且當前調試系統總線(Debug Message Interface,DMI)接口沒有錯誤信息時,開始執行dmi.op 指定的操作。
如圖2 所示,當dmi.op=0x1,dmi 狀態機進入Read 狀態。在Read 狀態中,先將dmi_req_valid 信號拉高,再等待dmi_req_ready 信號為高時進入WaitReadValid 狀態。在WaitReadValid 狀態中等待dmi_resp_valid 信號為高,當該信號為高時,dmi 讀取DM 模塊回應的數據(dmi_resp.data),并返回Idle 狀態。當dmi.op=0x2,dmi 狀態機進入Write 狀態。在Write 狀態中,先將dmi_req_valid 信號拉高,再等待dmi_req_valid 信號為高時返回Idle 狀態。

圖2 JTAG 轉DMI 內部總線狀態機Fig.2 JTAG to DMI internal bus state machine
2)DM_ROUTER 模塊負責上位機通過JTAG DMI_ACCESS 訪問填充的抽象調試寄存器內容,圖3 為其功能邏輯圖,將調試任務依據抽象命令對應標志位,通過內部總線發送到具體部件執行。

圖3 DM_ROUTER 功能流程Fig.3 Procedure of DM_ROUTER function
3)DM_EXE 模塊接收并處理處理器內部信息的調試指令,圖4 為其功能邏輯圖,根據用戶Halt 指令、軟件配置的硬件斷點是否等于CPU Trace 信號中PC 值、單步調試指令標志情況,向外發出調試中斷信號,同時完成調試目的寄存器訪問路由,分別組織指令架構下通用寄存器訪問、CSR 寄存器訪問的指令編碼,并依據調試任務中標識的執行空間進行指令填充(結果目的地址為內部DATA 寄存器),等待PC 正確跳入取指執行,執行完畢標記完成位,上位機將DATA 寄存器中的結果掃回。DM_EXE 模塊中的關鍵點是CPU、上位機、DM 模塊的三方協同狀態機,從而保證作業正常流轉。

圖4 DM_EXE 解析ABSTRACT_CMD 以及填充指令槽位邏輯Fig.4 DM_EXE parsing ABSTRACT_CMD and filling instruction slot logic
三方協同狀態機設計如圖5 所示,其中,左圖主要描述DM_EXE 硬件狀態機,右圖主要描述Debug Rom 軟件中斷處理程序。中斷可以由軟件陷入或上位機調制命令通過DM 發出,任何一種調試中斷發起,即觸發調試中斷,PC 跳入調試中斷入口程序(Debug Rom),首先挪用一個通用寄存器,再將標定調試的Core_Id 寫入DM Halted 寄存器,硬件狀態機確認選中的CPU 已經被停住,此時,若上位機發送了調試命令,則DM 將CMD_BUSY 拉高,進入下一狀態,否則停留在IDLE,在Debug Rom 程序go 與resume 都等于0 的情況下會在Debug Rom 程序空間死循環,等待調試指令到來。

圖5 DM_EXE 軟硬協同狀態機Fig.5 DM_EXE software and hardware collaborative state machine
當上位機調試指令到來,CMD_BUSY 信號隨即拉高,DM_EXE狀態機進入GO狀態,此時等待Debug Rom程序填寫DM 寄存器going 為1,此處設計是因為調試指令一般由1~2 條組成,并且為硬件寄存器裝填,1 個CLK 周期就能完成,在GCXP-1A 5 級流水線設計下,一條指令執行周期即可保證指令硬件裝填完畢,Debug Rom執行DM go寄存器判斷這條指令周期就足以滿足,因此,這里不再做DM 指令槽位填充完畢握手機制。狀態機檢測到Going 地址有寫操作后,隨即PC 獲取一條跳轉指令,跳入DM_EXE 取指入口(where to go),根據上位機指令標記獲取跳入不同DM 內部指令槽入口的跳轉指令,從而執行調試任務,指令槽位最后一條指令必然為跳回Debug Rom 首地址,通過再次寫Halted地址進入Idle 狀態。復位三方握手流程類似,不再詳細描述。
4)DM_SBA 模塊實現一個總線的Master 端,從而使得DM 模塊能夠訪問SoC 總線下編址地址信息讀寫。DM_SBA 的總體功能邏輯結構如圖6所示。

圖6 DM_SBA 模塊功能邏輯Fig.6 DM_SBA module function logic
DM_SBA 模塊的讀寫過程用一個狀態機實現,有idle、write、read、waite_write、waite_read 這5 種狀態。狀態機的轉換示意圖如圖7 所示,Idle 為master接口處于空閑狀態,write 為master 接口往內存寫數據,read 為master 接口向內存讀取數據,waite_write和waite_read 分別為master 接口的讀、寫等待狀態。

圖7 DM_SBA 工作狀態機Fig.7 DM_SBA working state machine
GCXP 軟件特權架構有3 種特權級:1)硬件模式(Hadware Mode,HM),是最高權限模式,為特權程序運行環境;2)內核模式(Kernel Mode,KM),是次低級模式,為操作系統運行環境;3)用戶模式(User Mode,UM),是最低級模式,為用戶程序運行環境。
特權程序運行程序(SW-HMCODE)為代替硬件邏輯的軟件代碼,定義了平臺SYS_CALL,注冊了操作系統核心對應的特權異常、中斷處理入口地址,在擴展處理器功能實驗、規避硬件錯誤以及OS 調試上都有重要的地位,是一種GCXP 獨有的軟硬件協同機制,默認為絕對正確,保證程序不會掛死在HM 模式下,且對用戶透明。
RISCV Debug Spec 中所涉及的CPU 硬件中斷處理、調試模式及其配套的DPC、DCSR,在GCXP GCXP-1A 軟硬件環境下都進行了重新設計,與GCXP-1A HMCODE 相結合,調試中斷改為普通中斷,通過HMCODE 中斷處理流程,實現現場保護和復原,并在HMCODE 中設置專用SYS_CALL 入口,結合中斷控制器,與普通中斷跳入操作系統核心注冊處理程序不同,調試中斷處理程序(DM_ROM)在HMCODE 內部進行調試中斷識別并完成跳轉,從而實現軟硬件調試陷入。
在上位機OpenOCD 中,由于兼容RISCV Debug Spec 0.13.2,因此按照RISCV Debug Spec 0.13.2 的軟件流程,添加th1a-013 target 分支,注冊寄存器讀寫、內存地址讀寫以及programbuf、abstract commad函數讀寫等,從而完善用戶調試流程。
如圖8 所示,GCXP-1A 調試模塊模擬驗證環境由3 個部分組成,分別為:1)SimJTAG.sv 包含Jtag_tick DPI-C 接口,負責路由來自DPI-C 的JTAG引腳信號,并與GCXP-1A SOC DM JTAG 橋接;2)DPI-C 接口具體實現本機socket 注冊、監聽和鏈接接受服務,使用bitbang 協議將socket 調試請求轉換成JTAG 信號;3)上位機調試軟件通過DPI-C 暴露的本地端口鏈接,開展調試流程。

圖8 調試模塊模擬驗證環境邏輯結構Fig.8 Debugging module simulation verification environment logical structure
如圖9 所示,在模擬驗證環境下,激勵時鐘起震、復位撤銷前使用HMCODE+TEST_CODE HEX進行約定地址空間布數。軟件流程具體如下:1)CPU 從HMCODE 開始取指運行,跳轉到TEST_CODE 地址;2)TEST_CODE 配置CSR 寄存器打開調試中斷使能;3)跳出HM 模式,運行死循環;4)HMCODE 根據CPU 捕獲的中斷(CPU 保證流水線硬件沖刷),將PC 跳轉到Debug ROM HALT 地址執行;5)上位機執行調試作業;6)Debug 退出,執行Debug ROM resume 程序段,恢復現場,跳轉PC 到保留PC。

圖9 模擬驗證環境軟件邏輯結構Fig.9 Simulation verification environment software logical structure
基于Synopsys VCS 2018.09-SP2 開展GCXP-1A SoC 模擬驗證,針對dm 開展OpenOCD test_compliance測試集驗證,針對所設計的功能,波形日志如下:
1)調試中斷流程。
如圖10 所示,當上位機中斷請求發起,dm 模塊io_debug_req_o 信號拉高,由HMCODE 中斷現場保護,并跳轉PC 到0x100 調試處理程序首地址,執行118 地址的寫hart id(0)到dm 0x400(Halted_aligned)地址,dm狀態機檢測到該寫操作后隨即拉高halted_q 信號,標識CPU 已經成功響應調試中斷。

圖10 模擬環境調試中斷響應波形圖Fig.10 Simulated environment debugging interrupt response waveform
2)CPU 內部寄存器讀寫。
如圖11所示,state_q為上文描述的三方交互狀態機狀態寄存器,分別標識idle(0)、go(1)、resume(2)、excuting(3),調試指令下達后,由idle->go 狀態,并等待debug rom 程序寫going 地址,期間硬件完成abstract_cmd 任務指令轉譯和填充,在going 拉高后跳入excuting 階段,執行完畢后(指令槽位最后一條固定位回到debug rom 首地址),等待debug rom 再次寫halted_align 地址,從而回到Idle 狀態。

圖11 模擬環境abstract cmd CPU 內部寄存器讀寫Fig.11 Simulated environment abstract cmd CPU internal register read and write
3)SBA 總線地址訪問。
如圖12 所示,上位機通過OpenOCD 對總線上的地址進行讀寫訪問,dm_sba 模塊從dm_csr 路由信號操作axi4 master 讀寫時序,從而完成讀寫任務。

圖12 模擬環境SBA 時序Fig.12 Simulation environment SBA time limit
FPGA 驗證環境為KCU105,將設計中的JTAG引腳約束到FMC XM105 擴展卡引腳,鏈接JLink v9,DM 模塊掛在系統總線下。在Vivado 2019.2 環境下開展SoC 綜合仿真實驗,運行頻率為100 MHz。
在仿真過程中,需要HMCODE 邏輯配合,在不依賴linux kernel 的情況下識別響應調試中斷。實驗環境如圖13 所示。

圖13 GCXP SoC DM+JLINKV9+OpenOCD 驗證平臺Fig.13 GCXP SoC DM+JLINKV9+OpenOCD verification platform
在圖14 中,使用OpenOCD 客戶端鏈接JLNK 開展DM 功能測試實驗,圖14(a)測試內容為通用寄存器或CSR 寄存器讀寫功能,圖中示例使用OpenOCD寄存器讀寫命令讀寫寄存器,圖14(b)測試內容為SoC 總線地址空間存儲器讀寫功能,使用OpenOCD SBA 模式測試字讀寫。

圖14 OpenOCD 命令行操作示例Fig.14 OpenOCD command line operation example
覆蓋率是判斷DUT 驗證是否完備的重要指標,在數字集成電路設計中,覆蓋率分為代碼覆蓋率和功能覆蓋率,代碼覆蓋率表征每行代碼的執行情況,功能覆蓋率表征具備一定功能的代碼組合的執行情況。從圖15 可以看出,本文DM 模塊的代碼及功能覆蓋率都能達到100%,能夠滿足流片要求。

圖15 代碼及功能覆蓋率Fig.15 Code and function coverage rate
本文在RISCV 調試協議規范的基礎上,結合GC,使用GCXP的HMCODE機制實現一套輕量級且對CPU無設計需求的調試方案,該方案可以兼容GCXP 全系列CPU IP 產品以及RISCV 的調試軟件和轉接器,從而豐富自主芯片的調試生態。下一步將協同CPU 設計Trace 模式,實現CPU 非入侵式調試機制,完成可控可過濾的指令流、數據流跟蹤,此外,配套上位機程序開發,實現性能可分析觀測、功能完備且安全的用戶調試機制,也是今后的研究方向。