SystemVerilog 中的 universal verfication methodology (UVM) 是什麼(二)
前一篇文章中說明了用 trace 來統一驗證 Verilog 的方式,但是 trace 可能會很大或是不好產生。本文將會探討還有哪些潛在的問題,以及 UVM 對這些問題的對策。
Debug module 中間的連線
這邊我用大學時數位電路實驗的助教曾經教過一句話,作為本文的楔子。「如果你的 Verilog 不會動,那就要檢查每個小 module 有什麼錯,如果都沒錯的話,那就是 module 中間的連線有錯,要去檢查中間的連線。」當年覺得這句話很 trivial,因為當年的我不知道有正規的方法來實踐這樣的檢查,但是幾年後的我發現 UVM 就是想要實踐統一的檢查手段。
上一篇文章中提到當 module 的輸入輸出格式統一時,如何用一份 code 就能驗證所有的 module。可以先把 module 輸入輸出之 trace 記錄下來,接著幫 trace 配上一個統一的 testbench 來測試。
現在的問題來了,第一個情形下當 SubModuleA
跟 SubModuleB
放在 TopModule
下一起運作時,只比對頭尾,發現結果是錯的,要怎麼抓出中間的錯呢?(什麼,你說兩個 module 都照 spec 寫,也各自驗證過了,怎麼還會有問題呢?我才想問你怎麼會有這種美好的幻想,覺得兩個獨立能動的東西黏起來就一定會動?)
一個可行的解法,就是把本來 SubModuleA
的 output trace 塞到 SubmoduleB
,得到的 output trace 也拿來比對,這樣就能在三個檢查點抓出錯誤。為此,UVM 中通常會把比對的功能單獨拆出來,這個單獨的功能一般叫做 monitor。其功能就是一直觀察這些連線上面的 protocol 有沒有發生錯誤,並跟目標檔案比對是否結果正確。
如果對 design pattern 熟悉的人,就會發現這跟的觀察者模式是同一個東西。
減少 trace 的使用
在上面的作法中,monitor 的功能相當單純,也很能輕鬆用 monitor 在各個 module 的接線中插入檢查點。此外,monitor 的功能也跟 generic master/slave 區分的相當乾淨,這樣的作法有良好的維護性跟擴展性。
但是,一個 productive 的電路中,檢查點的數量非常驚人,每產生一個新的測資就要幫所有的檢查點重新生成一次 trace。一來檔案大,二來產生的檔案變多了,把大量的 trace 加入 source code 中,會嚴重增加跨版本維護的難度。
正好 monitor 就是 design pattern 中的觀察者,觀察者通常都會配上 callback 使用。經過 callback 的機制,就能減少 trace 的使用。
在這張圖中:
- (上)Monitor1 看到一次
5'b01001
的傳輸,就會觸發 callback,把[1,0,0,1,0]
放入 Monitor2 的 answer list 備用。 - (下)Verilog module 計算完畢之後,把資料丟出來。Monitor2 也會觸發自己的 callback,這個 callback 作兩件事情。
- 檢查第一個輸出是不是跟 answer list 的第一個值一樣(應該要是
1
),檢查正確。 - 因為拿到一個
1
了,所以把[1,1]
放入 Monitor3 answer list 備用。
- 檢查第一個輸出是不是跟 answer list 的第一個值一樣(應該要是
(在許多 UVM 的文件中,會把 answer list 叫做記分板 (scoreboard)。)
如此一來,所有的資料都在驗證的同時動態產生,就不須要維護 trace file 了,加上現在開發電路的同時都會用上 SystemC 等工具來建立模型,幾乎不需要為了動態產生資料額外開發。另外,跟一般的觀察者模型一樣,我們也可依照需求加入其他的 callback,像是把值印出來、寫出檔案作為其他用途,提供了巨大的彈性。