王慧麗,郭 陽
(國防科技大學計算機學院,湖南 長沙,410073)
隨著基于集成電路硬件實現的深度學習算法在氣象預測、生物識別和人工智能等應用中的迅速發展,集成電路硬件設計規模逐漸擴大。作為處理器核心部件的指令流控單元,其設計復雜度日益增加,指令流控的驗證難度隨之增大。在一個控制復雜的應用場景中,指令流控錯誤可能會付出非常慘痛的代價。因此,對指令流控的高效、完備、精確的驗證,是微處理器設計及驗證中必須攻克的重要難題。
硬件設計的驗證方法主要有2種[1]:基于模擬的定向功能驗證和基于隨機激勵的形式化驗證。基于模擬的定向驗證一般采用人工編寫的方式,針對指定功能進行測試激勵,包括模塊級驗證和系統級驗證2種。定向功能驗證方法的主觀依賴性較高,其驗證的正確性、效率和完備性等與驗證人員的經驗素質密切相關,并且由于定向功能驗證往往針對特定模塊進行人工編制,導致激勵可重用性不高[2,3]?;陔S機激勵的形式化驗證能夠對設計進行狀態遍歷,驗證覆蓋率高,但是在復雜的控制系統中,隨著控制流程的增加,會出現狀態爆炸問題。并且隨機激勵約束編寫要求驗證人員具有很高的設計水平,否則可能會出現隨機激勵的驗證盲區,或者產生對驗證功能點的重復覆蓋,進而降低驗證效率[4,5]。
基于參考模型的隨機驗證方法介于傳統驗證和形式化驗證之間,該方法一般適用于數據密集型設計的模塊級驗證(如DMA、Cache和運算單元等)。對于控制復雜型的設計(如指令流控、中斷系統等),其與外部有復雜的協議,且內部功能復雜,因此很難在模塊級生成隨機激勵并構造參考模型,而是將其嵌入到整個DSP核系統級環境中,進行基于參考模型(模擬器)的驗證[6]。這種系統級的驗證存在調試不便、無法大批量運行和EDA軟件仿真速度慢等缺點。
無論采用哪種驗證方法,驗證的目標都是達到較高的覆蓋率來保證驗證的完備性和覆蓋的全面性。覆蓋率一般包括代碼覆蓋率、功能覆蓋率和斷言覆蓋率[7]。在覆蓋率驅動的驗證中,參考功能覆蓋率和代碼覆蓋率能夠快速評估當前的設計和驗證情況。如果出現2種覆蓋率不一致的情況時,可能需要考慮設計是否合理,功能點提取是否準確,是否需要形式化驗證工具輔助進行狀態遍歷等一系列問題[8]。
本文以自主高性能GPDSP處理器FT-xDSP的指令流控部件為研究對象,通過對其邏輯進行合理劃分簡化了其與外部的協議,然后經過一些侵入式驗證設計方法處理之后,降低了在模塊級進行隨機驗證的難度。最終針對難以進行定向模擬驗證的功能點,提出了一種基于指令重排參考模型的指令流控自動驗證方法。實驗及實際驗證的結果表明,該方法能夠發現隱藏的驗證邊緣情況,并針對設計中的薄弱點進行定向的隨機驗證,從而大大提高指令流控的驗證效率。
FT-xDSP是國防科技大學自主研發的高性能浮點向量DSP,采用了基于VLIW的標量/向量協同架構,40/80位可變長度指令集,單時鐘周期可并行發射1~11條指令[9]。FT-xDSP的指令流控部件主要包括一級程序Cache(L1P)、取指部件(PG,PW,IF三級流水線)、指令派發部件(DP)和流控指令處理部件(BR)。
圖1給出了其指令流水線結構。其中,PG根據分支、中斷和順序自加地址生成指令包(512 bit對齊)請求地址;L1P向外部存儲獲取指令包并提供給取指部件和DP。DP對指令包進行拼接和譯碼,將指令派發到對應功能部件;BR處理流控指令,改變程序運行的軌跡,分支指令SBR執行程序的跳轉,中斷返回指令SIERT控制程序在中斷程序執行完畢后返回主程序;其他10個功能部件負責運算或者訪存操作。

Figure 1 Instruction pipeline structure圖1 指令流水線結構
FT-xDSP包按照512 bit對齊,指令在取指包中緊密排列。指令格式如圖2所示,其中并行位P表示下一條指令是否可以與當前指令并行派發,L標記指令長度為40位或80位,Type表示該指令所對應的功能部件,Op為指令的其他操作碼。

Figure 2 Instruction format圖2 指令格式
單時鐘周期內可并行發射的指令稱為一個執行包(EP)。如圖3所示,EP0~EP2分別為連續的3個時鐘周期發射的執行包,每個執行包中可以包含多條緊密排列的80位指令或40位指令。

Figure 3 Execution package in the fetched package圖3 指令包中的執行包
FT-xDSP中的程序執行順序有3種:順序、分支跳轉和中斷響應,圖4為其所對應的程序流示意圖,其中:
(1)圖4a為順序程序流,程序運行軌跡為:EP1→EP2→EP3→…。
(2)圖4b為分支跳轉程序流:EP1中包含一條分支指令,經過6個分支延遲槽后,程序跳轉到分支目標地址(圖4b中示例為EP10)。程序運行軌跡為:EP1→EP2→EP3→…→EP7→EP10→EP11→…。
(3)圖4c為中斷響應程序流:程序執行過程中發生了中斷事務,當前程序被中斷執行并跳轉至中斷程序,直至中斷事務處理完畢后,再返回至原來程序被打斷的地方繼續執行。程序運行軌跡為:EP1→…→EP5→Int_EP1→…→Int_EPn→EP6→…。

Figure 4 Three kinds of program execution sequence圖4 3種程序流的執行順序
指令流控部件驗證的核心工作是驗證用戶程序中的所有指令是否按照預定的程序流被正確地派發到相應的功能部件中,而不需要驗證一條非流控部件指令(如運算指令、訪存指令等)是否可以被正確執行。驗證過程中難以用傳統模擬方式進行驗證的功能點主要有如下幾個:
(1)協議驗證:指令流水線中幾個控制功能部件之間存在著繁雜的通信協議,而在遇到分支與中斷時,驗證會變得很復雜,通過手工編寫測試激勵難以遍歷所有情況。

(3)程序流驗證:分支跳轉程序流中,涉及到分支延遲槽的處理、分支延遲槽或者分支目標執行包跨邊界、分支延遲槽對中斷的抑制等情況;中斷響應程序流中,當前中斷地址保存、當前流水線排空(Flush)和中斷返回地址處理等情況都是驗證過程中的難點,也是在DSP芯片單核設計中最容易出現設計缺陷的地方。尤其當分支和中斷發生頻率較高,且存在大量跨邊界執行包時,驗證工作更加艱難。
傳統模擬驗證方法,通過手工匯編用戶程序,在用戶程序中加入分支、中斷等相關配置,構造可以觸發相應功能點的測試激勵程序(指令包)。激勵輸入到DUT中,最終輸出為測試激勵程序所預定的程序軌跡和對應執行包。
表 1所示為圖4b分支跳轉程序流的人工匯編程序示例。其中EP2中僅有1條指令,EP11則包含11條指令。程序運行時,指令被派發至功能部件的時間順序如表 2所示。此激勵可驗證包括分支延遲槽計數、取指地址緩沖、各部件協議、指令包譯碼、跨邊界執行包(如EP6,EP11)、PC值維護和指令并行度等硬件邏輯,而不需要關注其中每一條指令執行結果是否正確。如果在分支延遲槽(EP2~EP7)中再插入分支指令構造多層循環嵌套,或者期間發生中斷響應,匯編程序本身變得復雜的同時,表 2中對程序正確派發順序的分析也非常耗時耗力,容易因繁瑣的細節而導致設計錯誤未被及時發現。

Table 1 Example of a branch jump program

Table 2 Execution sequence of branch jump program
綜上所述,指令流控部件的自動化驗證策略需要解決以下問題:
(1)可以自動生成執行包并行度可配置的隨機指令測試激勵,并且能夠在執行包中加入合法可控的分支指令,在程序流中插入中斷事件,構造合法的分支跳轉程序流和中斷響應程序流,縮短編寫驗證激勵的時間。
(2)需要一個高層次參考模型,能夠快速準確地得到隨機測試激勵的正確結果,減少驗證人員結果分析的時間。
(3)具有結果自動對比功能和收集覆蓋率的功能,便于錯誤定位和覆蓋率統計。
基于以上分析,本文提出基于指令重排參考模型的自動驗證方法,用于提高指令流控的驗證效率和驗證完備性。
如圖5所示:基于參考模型的自動驗證方法以抽象的參考模型為基礎,將批量自動生成的隨機測試激勵同時輸入參考模型和指令流控部件DUT,監測二者的輸出,并進行結果自動對比,然后根據覆蓋率情況調整產生隨機激勵的約束,實現功能點和代碼的快速全覆蓋。

Figure 5 Automatic verification based on reference model圖5 基于參考模型的自動驗證方法
基于參考模型的自動化驗證方法包含3個重要部分:
(1)激勵生成:生成符合條件的隨機測試指令包,并在這些測試激勵中插入合法的全局控制信號和分支/中斷操作。
(2)參考模型:對指令包進行譯碼,并根據分支指令/中斷響應進行分支/中斷程序流的處理,產生標準結果隊列。
(3)結果分析:以SVA(SystemVerilog Assertion)斷言的方式,實時監控DUT的輸出是否與參考模型的標準結果保持一致,并對覆蓋率進行統計和分析。
激勵的自動生成包括3部分:一是指令碼的生成;二是全局控制信號的生成,如全局停頓信號、中斷清空流水線信號IH_Flush等;三是取指地址生成,包括分支跳轉目標地址、中斷程序入口地址和中斷返回地址的生成。
4.1.1 指令碼生成
隨機指令碼生成主要是針對執行包并行度的驗證,以及不同指令流在遇到不同并行度執行包時,觸發其他復雜功能點的驗證。指令碼生成采用受約束的隨機方法[10],以保證執行包合法有效,其生成過程如圖6所示,分別為11個功能部件(U0~U10)建立有效指令集合,即每個功能部件中包含所有合法的Type和L組合。在隨機生成指令執行包時,根據限定的并行度P,隨機選中P個功能部件,并在這P個功能部件中隨機選擇一組有效的Type/L組合,與完全隨機值Op進行拼接,最后緊密排列構成一個執行包。重復以上過程,將生成的執行包在存儲模型中依次排列,作為參考模型和DUT的測試指令包。圖6中示例了并行度為3的執行包EP0和并行度為4的執行包EP1的產生過程。

Figure 6 Random generation of instructions with constraint圖6 受約束的指令碼隨機生成
隨機生成的指令碼直接輸入參考模型中進行指令解析,同時搭建一個存儲體模型ASRAM實現與DUT中L1P的取指包通信,將激勵輸入至DUT中,如圖5所示。
4.1.2 全局控制信號生成
流水線停頓信號G_Stall可在沒有取指缺失造成的全局暫停的情況下隨機產生;中斷事件引起的清空流水線信號IH_Flush可在程序沒有處于分支延遲槽中的情況下隨機產生。
4.1.3 取指地址產生
在基于模擬的驗證中,分支地址、中斷地址由編譯器輔助生成[11],而中斷返回地址由硬件記錄。在指令重排參考模型中,這些地址需要采用非完全隨機的方式,按照4.2節中不同程序流的處理方法而采用不同的產生策略。
4.1.4 可參數配置的定向激勵生成
為了針對特定功能進行驗證,可以通過對隨機數進行參數配置實現激勵的定向隨機產生,包括以下特征配置:
(1) 并行度可配置:可以配置激勵中執行包的并行度P為固定值,或者為一個范圍內的隨機值;
(2) 指令長度可配置:一個執行包中80位/40位指令出現的概率;
(3) 異??膳渲茫阂粋€執行包中是否出現指令派發異?;蛘吡骺夭考噶铄e誤異常;
(4) 分支指令和中斷事件發生的概率可配置。
指令重排參考模型的核心工作是對順序程序流、分支程序流和中斷程序流的處理,如圖7所示,該模型對輸入的測試程序指令包(如表 1中示例)和中斷控制信號進行執行包和程序流的分析,將解析出的執行包按程序實際運行順序在時間上進行重新排列(如表 2中示例),生成標準結果隊列。其中,分支/中斷地址的產生需要在程序流處理過程中以受約束的隨機方法產生,以保證其合法有效性。

Figure 7 Modeling for instruction flow control圖7 指令流控建模
4.2.1 順序程序流處理
當激勵中不包含分支類指令且無中斷事件發生時,參考模型根據指令的P,L,Type域,對指令包進行由低位到高位的順序譯碼,將譯碼后得到的執行包首地址PC_x(x=1,2,…)、執行包內包含的功能部件指令Uy(y=0,2,…,10)和該執行包的異常信息保存至一個順序指令隊列,如圖8所示。圖8中x為用戶程序指令包在存儲中的實際位置編號;y為功能部件標號(0~10);Mem_ptr為該指令隊列的讀指針,表示當前執行包在存儲中的絕對位置。在順序程序中,Mem_ptr與標準結果隊列讀指針DP_ptr相同。圖8的順序程序流的結果隊列中,PC_n+2的執行包包含2條屬于同一功能部件的指令U1,引發指令派發過程中的功能部件沖突異常,因此異常信息一列標注為1。

Figure 8 Instruction queues of sequential program圖8 順序程序流的指令隊列
4.2.2 分支跳轉程序流處理
在進行分支跳轉程序流處理時,先按順序程序流處理方式將指令包解析為順序排列的執行包,如圖9a所示。在此基礎上,增加一個分支控制處理隊列,如圖9b所示,分支控制隊列與順序隊列共用一個指針Mem_ptr。分支跳轉程序流處理主要包括以下幾個方面:

Figure 9 Processing of branch test program圖9 分支測試程序處理
(1)分支指令識別及分支地址產生。
在DUT中,分支指令的分支目標地址由指令Op域計算得出,或由Op域指定的寄存器中的值決定。在參考模型中,由于分支指令部分指令碼是隨機生成的,因此為了保證分支目標地址的合法性,同時降低驗證的難度,分支目標地址在所有有效的執行包地址PC_x中隨機產生,并在DUT頂層對分支目標地址進行旁路,使得DUT的分支目標地址與參考模型保持一致。如圖9a所示的測試程序,當某個Mem_ptr所指向的執行包中出現分支指令(如屬于U4功能部件的BR1和BR2)時,則在圖9b的分支控制隊列中對應Mem_ptr指向的行中標記BR_Valid為1,同時,在順序隊列中隨機選擇一行作為分支目標執行包,將其Mem_ptr保存至該行BR_ptr中。
(2)執行包重排序。
根據圖9中的信息,將分支指令流按照指令派發的順序寫入一個新的隊列中。如圖10所示。圖10a中分支指令BR1之后,經過6個延遲槽,程序跳轉至BR1的隨機分支目標地址PC_n繼續執行;分支指令BR2之后,經過6個延遲槽,程序跳轉至BR2的隨機分支目標地址PC_1繼續執行。分支跳轉程序流重排序后,分支控制處理隊列也隨之重新排序,新的隊列指針為DP_ptr。重排后的指令隊列即為分支跳轉程序流的標準指令派發結果隊列。

Figure 10 Reordering branch jump program圖10 分支跳轉程序流重排序
(3)循環次數計數。
圖10中,分支指令BR2會使程序在PC_1~PC_8這8個執行包之間不斷循環,導致其他隨機生成的執行包無法被驗證。因此,圖10b中加入分支指令執行次數Cnt的計數。Cnt對包含分支指令的執行包的派發次數進行累加,當Cnt超過某一閾值時(例如10),則將參考模型中的分支指令標志位BR_Valid置0,并通過旁路將BR_Valid輸入DUT作為分支的跳轉條件,使DUT中的分支指令不再執行,從而規避程序進入死循環的情況,確保隨機激勵的高效性。

Figure 11 Processing of interruption test program圖11 中斷測試程序處理
4.2.3 中斷響應程序流處理
在實際應用中,不同中斷事件具有不同的中斷響應程序。在本文的參考模型中,因為不需要關心中斷程序的具體功能,因此所有的中斷均采用相同的中斷響應程序,并將中斷響應程序放置于生成的隨機激勵最末端的特定地址。
中斷響應程序流的測試程序如圖11a所示,在隨機生成的測試激勵最末端,增加一段中斷服務程序(Mem_ptr=m),該程序中包含3條指令(可擴展為多條),其中IRET為中斷返回指令,NOP6為空轉指令用來填充6個延遲槽。中斷響應程序流處理時,在分支跳轉程序流的基礎上增加了一個中斷標志隊列,如圖11c所示,該隊列中隨機標記分支延遲槽以外的執行包所在行為1,表示執行當前執行包時,發生了中斷響應IH_Flush,并觸發清空流水線的操作。同時將此時的程序地址指針作為中斷返回地址指針Ret_ptr保存至圖11b的BR_ptr中。
圖12為中斷響應程序流重排序處理。當執行到IH_Flush為1的執行包時(PC_n+1),當前程序停止執行,清空在指令流水線中的所有指令,并將該執行包地址指針(Mem_ptr=n+1)作為中斷返回地址指針Ret_ptr寫入IRET指令所在行的BR_ptr中。然后,程序跳轉至激勵尾部的中斷響應服務子程序處(Mem_ptr=m)開始執行。在Mem_ptr=m+1處中斷響應程序處理完畢,執行中斷返回指令IRET,6個延遲槽后,程序流返回到保存的中斷返回地址Ret_ptr(Mem_ptr=n+1)處繼續執行主程序。IRET指令的Cnt始終為0,以確保每次中斷響應后,均可以正確地返回到主程序。圖12a即為中斷響應程序流的正確派發結果。
4.2節中測試程序經過分析處理后,生成一個按照指令派發順序排序的標準結果隊列,如圖8、圖10a和圖12a所示。為方便描述,將結果隊列中包含的3列信息分別命名如下:EP首地址為ResultPC_Mem,EP中指令為ResultU_Mem,異常信息為ResultExp_Mem。以圖10a中分支跳轉程序流的驗證為例,其波形如圖13所示,其中Ux_Inst和DP_PC分別為每個時鐘周期DUT輸出的執行包及其首地址,Ux_Inst中陰影部分表示當前時鐘周期派發了一條該部件的指令,Exprition為異常事件。在沒有全局停頓信號G_Stall時,結果隊列讀指針DP_ptr由0開始遞增讀取標準結果,并通過SVA斷言監控DUT的運行結果是否與結果隊列保持一致[12],同時對功能點覆蓋率和覆蓋次數進行統計。如下所示為部分基于SVA斷言的結果對比和功能覆蓋點。若結果對比失敗則打印錯誤發生的時間和錯誤類型,保存相應激勵進行調試和回歸驗證;功能覆蓋點則可以統計該功能點是否被覆蓋,以及被覆蓋的次數,從而評估該組激勵對功能點的驗證分布情況。

Figure 13 Debug waveform of branch test program圖13 分支測試程序的調試波形
基于SVA的結果自動對比示例:
assert_DP_PC:assert property (@(posedge clk)
disable iff (~rst_n) if (!G_Stall)ResultPC_Mem[DP_ptr]==DP_PC);
assert_U1_Inst:assert property (@(posedge clk)
disable iff (~rst_n) if (!G_Stall)ResultU_Mem[DP_ptr]==U1_Inst);
基于SVA的功能覆蓋點統計示例:
cover_TH_Flush_U1:cover property (@(posedge clk)
disable iff (~rst_n) if (!G_Stall)U1_Valid&&TH_Flush);
cover_TH_Flush_with_GStall:assert property (@(posedge clk)
disable iff (~rst_n)TH_Flush&&G_Stall);
本文采用Verilog/SystemVerilog語言對基于參考模型的指令流控自動驗證平臺進行設計實現,進行了大量的模擬驗證并對覆蓋率信息進行統計收集。實驗從激勵有效性、覆蓋率、仿真效率和可移植性等方面進行了分析。
在對測試激勵的自動生成進行了參數配置后,通過檢測激勵運行過程中斷言被觸發的情況,判斷激勵生成是否符合參數配置。如表 3中所示,配置執行包中是否生成VLS0/VLS1指令,分別批量生成測試激勵后,對比驗證過程中斷言觸發次數,可以看到參數配置是有效的。如果將功能點全部由斷言進行描述,則可以根據斷言被觸發的次數,清晰地得到某類激勵驗證的功能點的分布情況,進而調整測試激勵參數配置,避免對同一個功能點密集覆蓋而其他功能點無覆蓋或覆蓋較少的情況。
代碼覆蓋率中,塊覆蓋率(Block Coverage)一般要求達到100%,表達式覆蓋率(Expression Coverage)一般要求達到95%以上。如表4所示,模擬覆蓋率為基于模擬的人工編寫代碼驗證的覆蓋率數據,合并覆蓋率為在增加了基于參考模型的

Table 3 Evaluation of effectiveness of parameter configuration
隨機激勵驗證后, DUT的覆蓋率數據(其中未覆蓋的項為ET測試相關)。2組覆蓋率數據表明,基于指令重排參考模型的隨機激勵驗證方法是有效且全面的。
功能覆蓋點在本文中由2部分組成:驗證前期根據功能驗證文檔,基于模擬驗證所進行的功能點驗證統計,以及驗證后期基于參考模型隨機激勵的驗證中,使用SystemVerilog進行Coverage point描述的覆蓋點統計,二者最終實現所有功能點的全覆蓋。本文驗證方法的代碼覆蓋率如表4所示。

Table 4 Evaluation of code coverage表4 代碼覆蓋率評估
在FT_xDSP中,傳統模擬驗證與參考模型隨機驗證對指令流控部件驗證進度的貢獻如圖14所示。在驗證中后期,傳統模擬驗證效率開始降低。增加參考模型隨機驗證后,受益于隨機激勵可以通過腳本快速迭代生成,以及對各種復雜隨機激勵的結果可以自動對比分析的優勢,更多處于模擬驗證盲區的錯誤得以快速暴露,加快了驗證收斂速度。

Figure 14 Contribution of simulation verification and random verification to instruction flow control verification圖14 模擬驗證與隨機驗證對指令流控驗證的貢獻
為了評估模擬驗證和參考模型隨機驗證在同等條件下的驗證效率,人為在已經成熟驗證的指令流控中插入10個不同類型的錯誤。2種驗證方法在仿真時間上的對比如圖15所示。雖然2種方法在驗證某些類型的功能點時分別出現了效率降低的情況,但是,參考模型隨機驗證在總體仿真時間上較傳統模擬驗證更有優勢,足以彌補其在參考模型搭建和受約束的隨機激勵生成等方面所花費的時間。

Figure 15 Comparison of simulation time between simulation verification and random verification圖15 模擬驗證與隨機驗證仿真時間對比
由圖14可知,減少平臺開發時間(t)可以更早發現驗證盲區,縮短驗證周期?;谥噶钪嘏诺膮⒖寄P?,抽象層次高,只需要對取指地址產生邏輯進行修改,便可集成在系統級環境中。激勵自動產生方法和參考模型的指令隊列重排方法,適用于多數指令集系統和指令流水線結構,可以通過微調移植到不同的硬件設計中,從而大大節省驗證平臺開發時間。
本文重點介紹了自主高性能GPDSP處理器FT-xDSP的指令流控系統的驗證方法,在基于人工編寫測試激勵的模擬驗證已經完成,但是仍有一些復雜功能以及驗證薄弱點難以通過人工編寫測試激勵進行代碼覆蓋的情況下,提出了一種基于參考模型的隨機驗證方法。實驗及實際驗證的結果表明,這種隨機驗證方法能夠快速生成大量可配置的定向隨機激勵,大幅度提升驗證效率,并且在不同芯片設計中具有可移植性。但是,本文中的參考模型在處理分支跳轉和中斷事件響應時,對原設計DUT的地址產生有侵入式設計,在整個芯片的設計驗證流程中要注意防范因此造成的代碼版本管理問題。另外,指令流控部件的功能覆蓋率依靠簡單SystemVerilog描述實現,且未對所有功能點進行描述,統計方法過于簡陋,在下一步的工作中將對本文提出的方法做出進一步的實驗和完善,在驗證平臺中加入covergroup進行功能點的自動收集。