一、概述
在驗證環境的建立過程build_phase中,除了元件的執行個體化,配置也是必不可少的。為了驗證環境的複用性,通過外部的參數配置,使得環境在建立時可以根據不同參數來選擇建立的元件類型、元件執行個體數目、元件之間的連接配接以及元件的運作模式等。在更細緻的環境調節中有更多的變量需要配置,例如for-loop的門檻值、字元串名稱、随機變量的生成比重等。比起重新編譯來調節變量,如果在仿真中可以通過變量設定來修改環境,那麼就更靈活了,而UVM的config機制正提供了這樣的便利。
UVM提供了
uvm_config_db
配置類以及幾種友善的變量設定方法來實作仿真時的環境控制,常見的
uvm_config_db
類的使用方式包括:
- 傳遞virtual interface到環境中
- 設定單一變量值,例如int、string、enum等
- 傳遞配置對象(config object)到環境
uvm_config_db #(T)::set(uvm_component cntxt, string inst_name, string field_name, T value);
uvm_config_db #(T)::get(uvm_component cntxt, string inst_name, string field_name, T value);
二、interface傳遞
interface
傳遞可以很好地解決了連接配接硬體世界和軟體世界。而在之前SV驗證子產品中,雖然SV可以通過階層化的
interface
的索引來完成了傳遞,但是這樣不利于軟體環境的封裝和複用。UVM的
uvm_comfig_db
使得接口的傳遞和擷取徹底分離開來。
在實作接口傳遞的過程中需要注意:
- 接口傳遞應該發生在
之前。保證了在進入run_test()
之前,build_phase
已經被傳遞到virtual interface
中。uvm_config_db
- 應該把
與interface
的聲明區分開來,在傳遞過程中的類型應當為virtual interface
,即實際接口的句柄。virtual interface
interface intf1;
logic enable = 0;
endinterface
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
virtual intf1 vif;
...
function void build_phase(uvm_phase phase);
if(!uvm_config_db #(virtual intf1)::get(this, "", "vif", vif)) begin //this指代目前元件comp1,“vif”指的是comp1的一個變量
`uvm_error("GETVIF", "no virtual interface is assigned")
end
`uvm_info("SETVIF", $sformatf("vif.enable is %b before set", vif.enable), UVM_LOW)
vif.enable = 1;
`uvm_info("SETVIF", $sformatf("vif.enable is %b after set", vif.enable), UVM_LOW)
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1;
...
endclass
intf1 intf();
initial begin
//第一個參數時傳遞一個句柄,第二個參數時路徑,第三個參數時c1.vif這個變量,第四個參數是那個例化的需要傳遞的intf
uvm_config_db #(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf);
run_test("test1");
end
uvm_config_db #(virtual intf1)::get(this, "", "vif", vif)
的含義如下圖所示

uvm_config_db #(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf)
的含義如下圖所示
三、變量設定
在各個test中,可以在build_phase對底層元件的變量加以配置,進而在環境例化之前完成配置,使得環境可以按照預期運作。
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
int vall = 1;
string str1 = "null";
...
function void build_phase(uvm_phase phase);
`uvm_info("SETVIF", $sformatf("vall is %d before set", vall), UVM_LOW)
`uvm_info("SETVIF", $sformatf("str1 is %s before set", str1), UVM_LOW)
uvm_config_db#(int)::get(this, "", "vall", vall);
uvm_config_db#(string)::get(this, "", "str1", str1);
`uvm_info("SETVIF", $sformatf("vall is %d after set", vall), UVM_LOW)
`uvm_info("SETVIF", $sformatf("str1 is %s after set", str1), UVM_LOW)
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1;
...
function void build_phase(uvm_phase phase);
uvm_config_db#(int)::set(this, "c1", "vall", 100);
uvm_config_db#(string)::set(this, "c1", "str1", "comp1");
c1 = comp1::type_id::create("c1", this);
endfunction
endclass
四、object傳遞
在test配置中,需要配置的參數不隻是數量多,而且可能還分屬于不同的元件。那麼如果對這麼多層次中的變量做出類似上面的變量設定,那會需要更多的代碼,容易出錯還不易于複用,甚至底層元件的變量被删除後,也無法通過
uvm_config_db::set()
得知配置是否成功。然而如果将每個元件中的變量加以整合,首先放置到一個
uvm_object
中,再對中心化的配置對象進行傳遞,将會有利于整體環境的修改。
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
config1 cfg;
...
function void build_phase(uvm_phase phase);
uvm_object tmp;
uvm_config_db#(uvm_object)::get(this, "", "cfg", tmp);
void'($cast(cfg, tmp));
`uvm_info("SETVIF", $sformatf("cfg.vall is %d after get", cfg.vall), UVM_LOW)
`uvm_info("SETVIF", $sformatf("cfg.str1 is %s after get", cfg.str1), UVM_LOW)
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1, c2;
config1 cfg1, cfg2;
...
function void build_phase(uvm_phase phase);
cfg1 = config1::type_id::create("cfg1");
cfg2 = config1::type_id::create("cfg2");
cfg1.vall = 30;
cfg1.str1 = "c1";
cfg2.vall = 50;
cfg2.str1 = "c2";
uvm_config_db#(uvm_object)::set(this, "c1", "cfg", cfg1);
uvm_config_db#(uvm_object)::set(this, "c2", "cfg", cfg2);
c1 = comp1::type_id::create("c1", this);
c2 = comp1::type_id::create("c2", this);
endfunction
endclass
五、總結
- 在使用
時,通過層次和變量名,将這些資訊放置到uvm_config_db::set()
唯一的全局變量uvm_pkg
。全局變量uvm_pkg::uvm_resources
用來儲存和釋放配置資源資訊,uvm_resources
是uvm_resources
類的全局唯一執行個體,該執行個體中有兩個uvm_resource_pool
數組用來存放配置資訊,這兩個數組中一個由層次名字是以,一個由類型索引,通過這兩個關聯數組可以存放通過層次配置的資訊。同時,底層的元件也可以通過層次或者類型來取得來自高層的配置資訊。而在使用resource
方法時,通過傳遞的參數構成索引層次,然後在uvm_config_db::get()
已有的配置資訊池中索引該配置,如果索引到傳回1,否則傳回0。uvm_resources
- 在使用
和set()
方法時,傳遞的參數類型應當上下保持一緻,對于get()
等執行個體的傳遞,如果類型不一緻,應首先通過uvm_object
完成類型轉換,再對類型轉換後的對象進行操作。$cast()
-
和set()
方法傳遞的參數可以使用通配符get()
來表示任意的層次。*
- 在
環境中如果使用module
,則傳遞的第一個參數uvm_config_db::set()
參數一般用來表示目前的層次。如果目前層次為最高層,可以設定為uvm_component cntxt
,也可以設定為null
來表示uvm_root::get()
的全局頂層執行個體。uvm_root
- 在使用配置變量時,應確定先進行
,在獲得了正确的配置值以後再使用。uvm_config_db::get()
- 應該盡量確定
方法在相關配置元件建立前調用,隻有先完成配置,相關元件在例化前才可以得到配置值繼而正确地例化。uvm_config_db::set()
- 在
方法第一個參數使用目前層次的前提下,對于同一個元件的同一個變量,如果有多個高層元件對該變量進行設定,那麼較高層元件的配置會覆寫較低層的配置,但是如果是同一層次元件對該變量進行多次配置時,後面的配置會覆寫前面的配置。uvm_config_db::set()
- 在使用
方法時,添加便于調試的語句,例如通過UVM報告資訊得知uvm_config_db::get()
方法中的配置變量是否從uvm_config_db::get()
擷取到。uvm_config_db