加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    •  
    • 樹狀結(jié)構(gòu)
    •  
    • 運行機制
    •  
    • 工廠機制
    •  
    • build_phase 的內(nèi)容
    •  
    • 本期總結(jié)
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

UVM實戰(zhàn)[三]

2020/12/01
554
閱讀需 15 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

本期將講解 UVM 環(huán)境運行以及他的樹狀結(jié)構(gòu)。

主要參考資料為:

[白皮書]: http://bbs.eetop.cn/thread-320165-1-1.html

[紅寶書]: http://rockeric.com/

上期推送中,我們講解了整體環(huán)境的構(gòu)成,以及他們之間的關(guān)系。那么當仿真開始時,整個環(huán)境又將如何建立起來呢,組件按照什么順序進行組件實例化,如何將組件之間的通訊構(gòu)建起來,以及在運行時我們需要做什么呢?

?

樹狀結(jié)構(gòu)

整體的驗證環(huán)境由許多的組件實現(xiàn),作為環(huán)境組件,UVM 提供了 uvm_component,所有下圖中的測試組件都繼承于 uvm_component,只有 uvm_component 能夠作為組件構(gòu)建起整個環(huán)境。

上圖中可以看到框圖一層套一層,實際上就是 UVM 環(huán)境的樹狀結(jié)構(gòu)的體現(xiàn)。下圖是一個典型的測試環(huán)境的樹狀結(jié)構(gòu)圖。結(jié)合上下兩圖,uvm_top 是一個全局變量,它是 uvm_root 的一個實例(而且也是唯一的一個實例 ,它的實現(xiàn)方式非常巧妙),而 uvm_root 派生自 uvm_component,所以 uvm_top 本質(zhì)上是一個 uvm_component,它是樹的根。uvm_test_top 的 parent 是 uvm_top,而 uvm_top 的 parent 則是 null。

這里我們要注意區(qū)分,uvm 平臺中的 parent 和我們在 oop 中所說的父類是不同的概念,這里指的是節(jié)點,而非類的繼承關(guān)系,上圖的箭頭就像是鉤子,從上至下一個鉤住一個。通常我們不會接觸到 uvm_root 這個類,他是一個全局變量,構(gòu)建環(huán)境我們需要構(gòu)建 uvm_test_top 及其以下的組件。

而具體每個組件的作用,可以參照上一期的推送。

?

運行機制

仿真的進程分為幾個基本階段,例化組件,連接組件,仿真運行和報告階段。但實際上 UVM 在運行時提供了更加細致的階段劃分,將不同的任務(wù)劃分到對應(yīng)的階段中。UVM 稱這種機制為 phase 機制,一共包括九個 phase。

?

仿真開始后,phase 將從上至下,依次自動運行。phase 的引入在很大程度上解決了代碼順序雜亂可能會引發(fā)的問題。它本質(zhì)上是通過把代碼順序強制固定來實現(xiàn)這個目的的,如 build_phase 的代碼一定在 connect_phase 之前執(zhí)行 ,而 connect_phase 的代碼一定在 end_of_elaboration_phase 之前執(zhí)行等等。遵循 UVM 的這種代碼順序劃分原則,可以在很大程度上減少驗證平臺開發(fā)者的工作量,讓其從一部分雜亂的工作中解脫出來。

?function phase:不消耗仿真時間,而其也可分成兩大類:

1. 繼承自 uvm_bottomup_phase, 在 UVM component 樹中,自下而上的執(zhí)行, 如 connect_phase2. 繼承自 uvm_topdown_phase, 在 UVM component 樹中,自上而下執(zhí)行, 如 build_phase

?task phase:消耗仿真時間的,也稱動態(tài)運行(run-time)phase.

在初學 UVM 進行驗證過程中,只需要關(guān)注其中幾個 phase 即可。將組件的例化在 build_phase 實現(xiàn),組件連接在 connect_phase 實現(xiàn),測試的過程在 run_phase 中實現(xiàn)。就像下面 cfg_monitor 的代碼一樣,分步驟完成環(huán)境的構(gòu)建。



  class cfg_monitor extends uvm_monitor;    local virtual cfg_intf intf;    uvm_blocking_put_port #(cfg_item) mon_bp_port;
    `uvm_component_utils(cfg_monitor)
    function new(string name="cfg_monitor", uvm_component parent);    endfunction
    function void set_interface(virtual cfg_intf intf);    endfunction
    task run_phase(uvm_phase phase);    endtask
    task mon_trans();    endtask  endclass: cfg_monitor

從前面的圖中可以看到,run_phase 和旁邊十二個小的 phase 是并行的,UVM 為仿真提供了非常細致的階段劃分,即十二個小 phase,但是只使用 run_phase 也可以完成仿真。

?

工廠機制

在講解我們在 build_phase 所需,要完成的任務(wù)前,我們需要了解 UVM 中一個非常重要的機制 - 工廠機制。這并非是 UVM 獨創(chuàng)的機制,而是在設(shè)計模式中一種常用的機制。簡而言之,就是我們在編寫每個類時,都是在繪制圖紙,當我們完成圖紙以后,將圖紙遞交到工廠。仿真運行時,我們就能通過工廠,使用圖紙的名字,創(chuàng)建出不同的類。

繪制圖紙的過程就是在編寫類的代碼,而提交圖紙這個過程,體現(xiàn)在代碼中就是通過 UVM 的宏進行注冊,告訴工廠圖紙的名字。宏 uvm_component_utils 將 cfg_agent 注冊到工廠,而在構(gòu)造函數(shù)中,可以同時指定對象的默認名字。

注意 new 方法的參數(shù)中,string 是我們在創(chuàng)建組件時所需要傳遞的內(nèi)容,一定要與句柄的名字一直,否則在后續(xù)其他步驟中會出現(xiàn)意想不到的錯誤。而第二個參數(shù) parent 就是前面所提到的樹狀結(jié)構(gòu)的鉤子,父節(jié)點。


class cfg_agent extends uvm_agent;    `uvm_component_utils(cfg_agent)
    function new(string name = "cfg_agent", uvm_component parent);        super.new(name, parent);    endfunctionendclass:cfg_agent

?

build_phase 的內(nèi)容

通過工廠機制我們可以很輕松地完成組件對象的實例化,下面就是一個示例。


class cfg_agent extends uvm_agent;    function void build_phase(uvm_phase phase);      super.build_phase(phase);      driver = cfg_driver::type_id::create("driver", this);      monitor = cfg_monitor::type_id::create("monitor", this);      sequencer = cfg_sequencer::type_id::create("sequencer", this);    endfunctionendclass:cfg_agent

使用 component_name::type_id::create()就能通過工廠實例化對象,create 是 uvm_component 的一個靜態(tài)函數(shù),會返回組件的句柄,第一個參數(shù)就是我們 new 中的 string,建議與句柄名保持一致,第二個參數(shù)通常使用 this,表示創(chuàng)建的組件是在當前的組件的子節(jié)點上,從而構(gòu)建樹狀結(jié)構(gòu)。

有了創(chuàng)建組件的方法,我們就能通過 build_phase 實現(xiàn)組件的構(gòu)建。我們知道,整個環(huán)境是一個樹狀結(jié)構(gòu),那么檢索樹狀結(jié)構(gòu)就有兩個方向,自頂向下和自底向上。我們觀察 create 的參數(shù),發(fā)現(xiàn)需要傳遞父節(jié)點的句柄,那么很顯然,build_phase 是自頂向下的。從下面的代碼就能看到,在 build_phase 中,我們需要完成與本節(jié)點相連的子節(jié)點的創(chuàng)建,這樣一層一層的勾起組件,從根到最末端,所有的 build_phase 完成以后再進入下一個 phase。


class conv_base_test extends uvm_test;    function void build_phase(uvm_phase phase);      super.build_phase(phase);      this.env = conv_env::type_id::create("env", this);    endfunctionendclass: conv_base_test
class conv_env extends uvm_env;    function void build_phase(uvm_phase phase);      super.build_phase(phase);      this.chker    = conv_checker::type_id::create("chker", this);      this.cfg_agt  = cfg_agent::type_id::create("cfg_agt", this);      this.fmi_agt  = mem_in_agent::type_id::create("fmi_agt", this);      this.wt_agt   = mem_in_agent::type_id::create("wt_agt", this);      this.bias_agt = mem_in_agent::type_id::create("bias_agt", this);      this.fmo_agt  = mem_out_agent::type_id::create("fmo_agt", this);      this.cvrg     = conv_coverage::type_id::create("cvrg", this);      this.virt_sqr = conv_virtual_sequencer::type_id::create("virt_sqr", this);    endfunction endclass: conv_env
class cfg_agent extends uvm_agent;    function void build_phase(uvm_phase phase);      super.build_phase(phase);      driver = cfg_driver::type_id::create("driver", this);      monitor = cfg_monitor::type_id::create("monitor", this);      sequencer = cfg_sequencer::type_id::create("sequencer", this);    endfunctionendclass:cfg_agent

?

本期總結(jié)

1.UVM 的組件是樹狀連接的,環(huán)境中的 parent 和 oop 的父類是不一樣的

2.UVM 的運行劃分成多個 phase,每個 phase 負責不同的任務(wù),run_phase 與旁邊的十二個 phase 是并行的。整體運行從上至下順序運行。只有 run_phase 和并行的 phase 是 task,其他都是 funtion。

3. 使用宏在工廠中注冊,然后就能夠通過 create 靜態(tài)方法實現(xiàn)組件實例化

4. 在 build_phase 中順序創(chuàng)建字節(jié)點的組件,從而構(gòu)建整個環(huán)境

相關(guān)推薦

電子產(chǎn)業(yè)圖譜