首先要區分一下仿真時間和運行時間:
仿真時間是使用$time函數等到的時間,而運行時間則是CPU的時間。
類繼承層次:

這里面跟phasing相關的類介紹如下:
1. uvm_phase: 基本的類,定義一個phase的行為,狀態,內容
2. uvm_domain:phasing的進度節點,代表進度的一個獨立分支
3. uvm_bottemup_phase: 實現bottem up 函數
4. uvm_topdown_phase:實現topdown 函數
5. uvm_task_phase:實現task phase
uvm中的phase,按照其是否消耗仿真時間特性,可以分成兩大類:
1. function phase不消耗仿真時間,而function phase也分成兩大類:
a. 繼承自uvm_bottemup_phase的自下而上的執行function
b. 繼承自uvm_topdown_phase的自上而下執行的function
2. 只有run_phase是task phase,消耗仿真時間的,自上而下啟動,同時在運行。
UVM中同一phase的執行順序:
phase是和uvm_componet相伴相生的一個概念,對於每一個uvm_component來說,都有全部的phase,而
驗證平台中的component是分層次的。
1. UVM使用自上而下執行build_phase,在build_phase中做component的實例化工作,如果在其他phase實例化一個uvm_component的話,系統會報錯的。如果uvm_object的實例化,則可以在任何phase完成。
2. 除了build_phase之外,所有的不耗仿真時間的phase都是自下而上執行。
3. 對於同一層次的uvm_component按照new時指定名字的字典順序執行
UVM中的動態運行run_time phase:
1.
UVM把 run_phase又分割成了 12 個小的phase,這 12 個小的 phase各自在執行
順序方面與run_phase完全相同,即自下而上的啟動,同時運行。這里有兩個問題,
第一個問題是為什么要分成小的 phase?第二個問題是這 12 個小的 phase 與
run_phase之間關系如何?

UVM把run_phase又分割成12個小的phase:
1. 為啥要分成小phase,精細化控制 reset/configure/main/shutdown是核心
一個大的chip里面有很多功能性比較獨立的模塊,這些功能性獨立意味着一個模塊A在run的時刻另一個模塊B可以不run,也可以run,B運行不運行和A運行不運行關聯度不大甚至沒有關聯,比如A是只負責處理發通路的而B只負責收通路;但是另一方面,功能性獨立並不意味着什么都獨立,舉例來說,A模塊和B模塊功能性很獨立,比如A是一個clock generation模塊,B是一個processor模塊,那在A沒有正常work的前提下B是不能正常工作的。
1. 分成小的phase是為了實現更加精細的控制,其中核心的四個phase是(reset,configure,main,shutdown),這四個phase模擬了DUT的正常的工作方式
2. 實現跳轉操作
3. 12 個小的 phase之間並不是這樣順序執行,而是每當一個小的phase 執行完成的時候要看看其它component的同名的小 phase有沒有執行完,等所有的都執行完后,才會進入下一個小的phase,也就是說有一個同步的過程。
由此我們至少可以提出兩點需求:
(1)能不能讓B的reset phase發生在A的reset phase之后,這樣等待clock都穩定了再對B做reset操作或者release reset操作?
(2)能不能讓A的main phase和B的main phase異步的運行?
上面兩點至少需要用到UVM中的的如下機制:新建一個domain、給不同的component設置不同的domain、不同的domain之間phase的同步和異步。
再如,功能更復雜的tb可能需要新建一個user-defined的phase,讓它在某一需要個時刻點運行,可以是function性質的或者task性質的。
2. 12個小phase於run_phase之間的關系?
每當一個小的phase執行完成時候,要等到所有component的同名的小phase有沒有執行完,等所有執行完了,才進入下個小phase。
UVM中的objection:
UVM中,通過objection機制來控制驗證平台的關閉。
在進入到某一phase的時候,UVM會收集此phase提出的所有的objection,並且實時監測所有的objection是否已經drop了,當發現所有的都已經drop后,那么就會關閉此phase,開始進入下一個phase。當所有的phase都執行完畢后,就會調用$finish來把整個的驗證平台關掉。

如果想執行一些耗費時間的代碼,那么至少也要在此phase下raise一次objection。
這個結論只適用於run_time的phase。對於run_phase則不適用。
phase的引入是為了解決何時結束仿真的問題
上例中,只要把pkt_num設置成要發送的transaction的數量就可以了。這種設置可以通過config的形式,讀者可以參照config機制的相關章節。
另外一種方法就如在第一章的例子中那樣,在sequence中把sequencer的objection給raise起來,當sequence完成后,再drop此objection。這種方法相對上一種方法的好處就是不必設置要發送的包的數量。不過,這種方法的限制是,此sequence必須要做為sequencer的某個phase(比如main_phase)的default_sequence,這個通常是比較容易的,一般都使用這種方法。
domain:
domain把兩塊時鍾域隔開,之后兩個時鍾域內的各個動態運行(run_time)的phase就可以不必同步。注意,這里domain只能把run_time的phase給隔離開來,對於其它的phase,其實還是同步的,即兩個domain的run_phase依然是同步的,其它的function phase也是同步的。
多domain與單domain的區別主要體現在phase和objection上