UVM驗證平臺介紹
先拋開UVM,回想一下我們在平時寫完程序后,是不是肯定需要灌一個激勵給DUT,然后再從DUT獲取結果,并跟一個參考模塊進行對比,檢查結果是否正確。就像下面這個圖:
在UVM中,引入了sequence機制,這個機制的最大作用就是將test case和testbench分離開來。對一個項目而言,testbench是相對穩定的框架,而針對各個module要有不同的測試內容,所以具體的test case 的差異非常大。在UVM中, test和sequence類總是成對出現,實現了testbench和具體的test case的結合。test類中可以針對具體的測試內容對testbench做一些差異化配置,在sequence類中則是實現test case的具體細節。
因此,在UVM中,使用sequence來產生transaction,再由sequencer傳給driver,再作為激勵傳給DUT。也就是說driver只負責驅動transaction,而不負責產生transaction。
同時UVM中將sequencer、driver和監測激勵的monitor封裝到一個in_agent中,將監測DUT輸出的monitor封裝到out_agent中,以提高代碼的可重用性,模型如下:
我們再對上面這些模塊做一些更詳細的解釋,暫時看不懂沒關系,先有個概念就行,后面的東西學的多了,這些概念自然也就懂了。
driver:向sequencer申請sequence_item(數據包transaction),并將包里的信息按照總線協議規定驅動到DUT的端口上;
sequencer:負責發送數據,組織管理sequence,driver申請數據時,它就把sequence生成的sequence_item發給driver;(需要注意sequence和sequencer的區別)
scoreboard:比較reference model和monitor分別發送來的數據,根據比較結果判斷DUT是否正確工作;
monitor:從DUT接收數據,并將其轉成transaction級別的sequence_item,發送給scoreboard,供其比較;
reference model:模仿DUT,完成與DUT相同的功能,為scoreboard提供判斷標準;
agent:將sequencer、driver和monitor封裝在一起(UVM_ACTIVE/UVM_PASSIVE、兩種模式),agent模塊的使用提高了代碼的可重用性;
env:將平臺上的component組件封裝在一起,并配置各個組件間的通信端口,實現一個環境多個用例。運行不同用例時,在其中實例化env即可;
sequence:(不屬于驗證平臺的任一部分)產生激勵內容(transaction)。通過sequence中的body任務創建(隨機化)事務,并發送給sequencer。
UVM中的類
component與object是UVM中兩大最基本的概念,也是初學者最容易混淆的兩個概念。uvm_object是UVM中最基本的類,讀者能想到的幾乎所有的類都繼承自uvm_object,包括uvm_component。
uvm_component有兩大特性是uvm_object所沒有的:
通過在new的時候指定parent參數來形成一種樹形的組織結構
phase的自動執行特點
從圖中可以看出,從uvm_object派生出了兩個分支,所有的UVM樹的結點都是由uvm_component組成的,只有基于 uvm_component派生的類才可能成為UVM樹的結點;最左邊分支的類或者直接派生自uvm_object的類,是不可能以結點的形式出 現在UVM樹上的。
UVM通過uvm_component來實現樹形結構。所有的UVM樹的結點本質上都是一個uvm_component。每個uvm_component都有 一個特點:它們在new的時候,需要指定一個類型為uvm_component、名字是parent的變量:
function new(string name, uvm_component parent);
構成環境的組件都從uvm_component類繼承而來,這是因為它們都從uvm_component類繼承了phase機制,都會經歷各個phase階段,關于phase的內容,我們后面介紹。
uvm_driver
所有的driver都要派生自uvm_driver。driver的功能主要就是向sequencer索要sequence_item(transaction),并且將 sequence_item里的信息驅動到DUT的端口上,這相當于完成了從transaction級別到DUT能夠接受的端口級別信息的轉換。
uvm_monitor
所有的monitor都要派生自uvm_monitor。monitor做的事情與driver相反,driver向DUT的pin上發送數據,而 monitor則是從DUT的pin上接收數據,并且把接收到的數據轉換成transaction級別的sequence_item,再把轉換后的數據發送給 scoreboard,供其比較。與uvm_component相比,uvm_monitor幾乎沒有做任何擴充。
uvm_sequencer
所有的sequencer都要派生自uvm_sequencer。sequencer的功能就是組織管理sequence,當driver要求數據時, 它就把sequence生成的sequence_item轉發給driver。
uvm_scoreboard
一般的scoreboard都要派生自uvm_scoreboard。scoreboard的功能就是比較reference model和monitor分別發送 來的數據,根據比較結果判斷DUT是否正確工作。
reference model
UVM中并沒有針對reference model定義一個類。所以通常來說,reference model都是直接派生自 uvm_component。reference model的作用就是模仿DUT,完成與DUT相同的功能。DUT是用Verilog寫成的時序電路,而reference model則可以直接使用SystemVerilog高級語言的特性,同時還可以通過DPI等接口調用其他語言來完成與DUT相同的功能。
uvm_agent
所有的agent要派生自uvm_agent。與前面幾個比起來,uvm_agent的作用并不是那么明顯。它只是把driver和 monitor封裝在一起,根據參數值來決定是只實例化monitor還是要同時實例化driver和monitor。agent的使用主要是從可重用性的角 度來考慮的。如果在做驗證平臺時不考慮可重用性,那么agent其實是可有可無的。
uvm_env
所有的env(environment的縮寫)要派生自uvm_env。env將驗證平臺上用到的固定不變的component都封裝在一 起。這樣,當要運行不同的測試用例時,只要在測試用例中實例化此env即可。
uvm_test
所有的測試用例要派生自uvm_test或其派生類,不同的測試用例之間差異很大,所以從uvm_test派生出來的類各不 相同。任何一個派生出的測試用例中,都要實例化env,只有這樣,當測試用例在運行的時候,才能把數據正常地發給DUT,并正常地接收DUT的數據。
?
UVM的樹形結構
上一節我們講了UVM中的類,也可以看到UVM中各個類的繼承關系。了解了這些,再來看UVM中的樹形結構。UVM中的sequencer、driver、monitor、agent、model、 scoreboard、env等都是樹的一個結點。為什么要用樹的形式來組織呢?因為作為一個驗證平臺,樹形結構是一種非常合適的管理方式。
UVM的完整樹結構如下圖所示:
uvm_top是一個全局變量,它是uvm_root的一個實例,而且也是唯一的一個實例 ,它的實現方式非常巧妙。而uvm_root 派生自uvm_component,所以uvm_top本質上是一個uvm_component,它是樹的根。uvm_test_top的parent是uvm_top,而uvm_top的 parent則是null。
uvm_top提供一系列的方法來控制仿真,例如phase機制、objection防止仿真退出機制等。
層次結構相關的函數
UVM提供了一系列的接口函數用于訪問UVM樹中的結點。這其中最主要的是以下幾個:
get_parent 用于得到當前實例的parent,其函數原型為:
externvirtualfunctionuvm_componentget_parent();
get_child函數,與get_parent不同的是,get_child需要一個string類型的參數name,表示此child實例在實例化時指定的名字。因為一個component只有一個parent,所以get_parent不需要指定參數;而可能有多個child,所以必須指定name參數。
externfunctionuvm_componentget_child(stringname);
get_children函數,為了得到所有的child
externfunctionvoidget_children(refuvm_componentchildren[$]); uvm_componentarray[$]; my_comp.get_children(array); foreach(array[i]) do_something(array[i]);
get_num_children函數,用于返回當前component所擁有的child的數量
externfunctionintget_num_children();
除了一次性得到所有的child外,還可以使用get_first_child和get_next_child的組合依次得到所有的child
externfunctionintget_first_child(refstringname); externfunctionintget_next_child(refstringname); stringname; uvm_componentchild; if(comp.get_first_child(name)) dobegin child=comp.get_child(name); child.print(); endwhile(comp.get_next_child(name));
審核編輯:劉清
-
UVM
+關注
關注
0文章
182瀏覽量
19227 -
DUT
+關注
關注
0文章
189瀏覽量
12490
原文標題:UVM手把手教程系列(一)UVM基礎
文章出處:【微信號:傅里葉的貓,微信公眾號:傅里葉的貓】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論