01、前言
芯片驗證是為了發(fā)現(xiàn)芯片中的錯誤而執(zhí)行的過程,它是一個破壞性的過程。有效激勵灌入待測模塊后,需要判斷出不符合功能描述的行為。檢查器(Checker)就是用于查看待測模塊是否按照功能描述文檔做出期望的行為,識別出所有的設計缺陷。
不同被檢查邏輯的層次,所需要的檢查方法不一致,本文主要側重于模塊級驗證的檢查器設計。該層次需要檢查的范圍有:
待測模塊的所有輸入輸出信號;
待測模塊的內(nèi)部設計細節(jié);
待測模塊在芯片系統(tǒng)級的應用角色;
所需要的功能描述文檔至少有:
項目產(chǎn)品文檔:描述本模塊的實際應用場景。
項目需求文檔:將產(chǎn)品文檔轉(zhuǎn)換為技術人員可讀懂的技術文檔。
待測模塊設計文檔:將需求文檔轉(zhuǎn)換為實際RTL規(guī)范。
有些模塊還需要其它手冊,比如Arm和RISC-V的CPU還會有架構參考手冊。
對待測模塊行為的檢查,可以采用不同的檢查方法,主要有:
監(jiān)視器(monitor):可以用于信號級別的數(shù)值、時序和協(xié)議檢查;
參考模型+比較器(Checker):檢查包層級的信息;
斷言:主要依靠它檢查模塊的邏輯細節(jié)和時序信息;
定向測試:用于簡單場景的檢查,一般自帶檢查器;
形式驗證:用數(shù)學方式來證明功能是否正確;
根據(jù)情況不同,以上這些方法可以采用其中的一種或多種,一般很少只使用一種的。待測模塊使用什么樣的檢查方法以及檢查哪些內(nèi)容,也是芯片驗證的一大難點。和激勵設計分析類似(如何寫出更牛更系統(tǒng)的驗證激勵),本文也是從完備性、可拓展性和可控性三方面展開闡述如何系統(tǒng)地思考和構建驗證檢查器。
02、完備性
檢查器的完備性是最基本要求,可以從接口類型、內(nèi)部結構、結束檢查(End of check)和檢查器審查這四方面去思考。
2.1 接口類型
接口類型檢查主要是檢查輸入輸出信號是否符合文檔描述的行為,也就是與待測模塊連接的上下游模塊的互動信號行為。可以從單一接口類型和多個接口交互兩方向去分析。
2.1.1 單一接口類型
單一接口類型分析由信號檢查和協(xié)議檢查組成。
信號檢查:主要檢查每根信號的行為,包括信號值正確性和數(shù)據(jù)完整性。
協(xié)議檢查:主要檢查多根信號之間的行為,包括時序檢查、握手檢查,hazard檢查,order檢查,outstanding能力檢查和包傳輸流程檢查等。
信號值檢查、時序檢查和握手檢查通??梢杂脭嘌詸z查;outstanding能力檢查和包傳輸流程檢查通常可以用監(jiān)控器檢查。數(shù)據(jù)完整性、hazard檢查和order檢查等復雜建模需求的通常需要使用檢查器檢查。
2.1.2 多個接口交互
多個接口交互由數(shù)據(jù)完整性、保序和同步交互組成。
數(shù)據(jù)完整性:檢查信息傳輸沒有丟失。
保序:檢查有先后關系的傳輸包是否正確傳輸。
同步交互:檢查傳輸包是否有同步或者約定先后出現(xiàn)等關系。
多個接口交互的檢查通常需要檢查器檢查。
2.2 內(nèi)部結構
內(nèi)部結構檢查需要沿著數(shù)據(jù)流(data flow)方向分析,看看有哪些必須檢查的轉(zhuǎn)換(transformation)和決策(decision)。主要有:
內(nèi)部功能點:order、hazard、forward、sleep、replay邏輯、register讀寫等。
資源占用:FIFO、Buffer、Interface、流水線等。
資源仲裁:優(yōu)先級、死鎖等。
數(shù)據(jù)完整性:數(shù)據(jù)拆分、數(shù)據(jù)合并、數(shù)據(jù)保序等。
功能配置:待測模塊行為是否符合當前寄存器和參數(shù)配置等。
異常檢查:復位值、內(nèi)部觸發(fā)fault、外部返回錯誤響應、中斷等。
異常事件是否合理;
異常處理是否正確;
異常處理完,待測模塊是否能恢復;
內(nèi)部結構的檢查經(jīng)常需要用到RTL內(nèi)部的輔助信號,最好是在非常有必要或可以大大節(jié)省檢查器建模工作量的情況下,才使用這些輔助信號。而且檢查器用輔助信號之前,必須檢查輔助信號行為的合理性。
2.3 結束檢查
結束檢查主要用于在驗證用例結束時,檢查RTL和TB的狀態(tài),比如RTL是否處于非busy狀態(tài)、FIFO是否為空、請求是否全部處理完畢等。只要有預期某個功能在用例結束時必須處于某種狀態(tài),都可以放到結束檢查里。主要有:
TB/DUT狀態(tài)檢查:Counter、FIFO、Buffer、Queue、Busy等。
仿真日志檢查:可以通過腳本自動提取。
波形檢查:通過腳本解析波形內(nèi)容來檢查。
2.4 檢查器審查
審查(Review)環(huán)節(jié)對完善檢查器起著至關重要的作用,可以提高檢查器質(zhì)量,并減少漏檢查特性的概率,對個人成長也有很大幫助。
建議以下這些審查方式都要按順序進行:
個人審查:由自己進行,對照歷史錯誤清單進行,舉一反三,避免犯類似錯誤。
同組審查:由組內(nèi)更有經(jīng)驗的人進行,對檢查完備性、檢查器設計結構、假設、采用的RTL輔助信號、代碼實現(xiàn)進行檢查。
跨組審查:由待測模塊的設計人員進行,對檢查器完備性、設計顧慮、易錯特性、局限性和各種檢查器假設進行檢查。
03、可拓展性
可擴展性也包括可復用性。為了處理驗證周期縮短、待測RTL規(guī)格頻繁變動等各種情況,我們需要在設計檢查器時提前構思如何讓檢查器更容易擴展?;诖?,我們可以從模塊化和解耦性方面去思考。
3.1 模塊化
模塊化需要對待測模塊的每個功能點檢查都分別集中于一處,而不是將一個功能點的檢查分散到檢查器各個地方,且多個功能點檢查互相穿插耦合,這樣后期如果某個功能點改動會影響檢查器的很多代碼,而且容易改漏。
把常見的功能封裝成公共庫,這樣在多個地方都可以直接使用,如果功能需要改動,只需要改動一處代碼即可。
不要把所有檢查器內(nèi)容都放到一個class類里解決,這樣會造成這個類代碼巨多,而且難以維護??梢园褭z查器根據(jù)待測模塊特性切割成多個小的建模單位,由這些小的建模單位共同組成整體檢查器,這樣結構更清晰,而且待測模塊特性的改動,只會影響其中一些建模單位,不需要整體檢查器都修改。
3.2 解耦性
解耦性要求檢查器代碼盡量減少依賴于環(huán)境其它組件的代碼,不管是變量類型、方法還是類,最好使用自身定義的,方便修改、移植和重用。
比如monitor送過來的類內(nèi)容要轉(zhuǎn)換為檢查器自己內(nèi)部定義的類內(nèi)容,檢查器就可以減少依賴于monitor中類的改動。
04、可控性
檢查器的可控性在這里主要是指是否方便控制檢查器的功能檢查范圍和消息打印內(nèi)容。
4.1 功能檢查控制
最常見的就是控制檢查器是否開啟,比如在調(diào)試激勵的時候,通常會先把檢查器關閉掉,避免造成不必要的干擾。
如果需要的話,功能檢查控制可以做到更細粒度的控制,按照待測模塊的規(guī)格、接口或某個功能來控制,這樣就方便根據(jù)實際情況,選擇打開或關閉哪些檢查。
4.2 消息等級控制
檢查器中會打印一些消息,跟蹤檢查器的內(nèi)部情況,方便出錯時調(diào)試。有效的打印消息越多,仿真速度越慢,但對調(diào)試來說更友好些。因此,需要控制好不同消息的打印等級,不要每個周期都打印大量信息。默認情況下,只打印一些關鍵信息。只有需要更多調(diào)試消息時,才調(diào)低等級,打印更多的消息。
05、總結
綜上所述,檢查器設計可以按照“完備性->可拓展性->可控性”方向去分析。在完備性中,可以按照“接口類型->內(nèi)部結構->結束檢查->檢查器審查”方向去分析。在可拓展性中,可以按照“模塊化->解耦性”方向去分析。在可控性中,可以按照“功能檢查控制->消息等級控制”方向去分析。
另外很重要的一點是:要經(jīng)常對驗證結果進行復盤分析,并完善檢查器。
總得思維導圖如下: