注1:該篇文章側重於config_db機制的使用;
1. config機制成對出現
1.1 簡單示例
如在某個case(派生自uvm_test)的build_phase中可以做如下設置:
1 uvm_config_db#(int)::set(this,"env.agent.driver","pre_num_max",100);
那么在driver的build_phase中需要:
1 uvm_config_db#(int)::get(this,"","pre_num_max",pre_num_max);
1.2 示例解釋
(1) uvm_config_db中set和get都是靜態函數,可用雙冒號形式調用.
1 static function void set(uvm_component cntxt, 2 string inst_name, 3 string field_name, 4 T value); 5 static function bit get(uvm_component cntxt, 6 string inst_name, 7 string field_name, 8 inout T value);
(2) uvm_config_db::set的參數解釋:
1 initial begin 2 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.i_agt.drv","vif",input_if); 3 end 4 5 initial begin 6 uvm_config_db#(virtual my_if)::set(uvm_root::get(),"uvm_test_top.env.i_agt.drv","vif",input_if); 7 end
注1:在top module中通過config_db機制的set函數設置virtual interface時,set的第一個參數為null; 在這種情況下,UVM會自動把第一個參數替換為uvm_root::get(),即uvm_top;
(2.1) set的第一個參數用以說明是哪個component對pre_num_max進行設置,通常是一個uvm_component的指針,一般使用填寫this;
(2.2) set的第二個參數表示從調用uvm_config_db::set的地方看下去,要設置的變量所在的component的路徑; set的前兩個參數聯合起來組成路徑;
(2.3) set的第三個參數表示一個記號,用於說明這個值是傳給driver中的哪個變量的;
(2.4) set的第四個參數是要設置的值;
(3) uvm_config_db::get的參數解釋:
(3.1) get的第一個參數一般是this即可;
(3.2) get的第二個參數填寫一個空的字符串;
(3.3) get的第三個參數就是set中的第三個參數,二者必須一致;
(3.4) get的第四個參數則是要設置的變量;
1 uvm_config_db#(int)::set(this,"env.i_agt.drv","p_num",100); 2 uvm_config_db#(int)::get(this,"","p_num",pre_num);
注1:get函數中第三個參數可以與get函數中第四個參數不一樣(但是最好一樣,這種情況下,如果再滿足其他條件,可以省略get語句);
2. 省略get的config
(1) 雖然通常要求set與get成對出現,但是在某些特定情況下,get是可以省略的.
(2) 實現原理: build_phase內的super.build_phase(phase)在滿足以下特定條件的情況下,可以完成get的功能(super.build_phase中實現的自動get,uvm_component的apply_config_settings實現自動get);
特定條件1:將正常情況下需要執行get操作的類注冊到factory;
特定條件2:使用field_automation機制把要get的變量注冊;
特定條件3:set的第三個參數必須與要get的變量的名字相一致;
(3) 示例
1 class mac_driver extends uvm_driver#(mca_transaction); 2 ... 3 int pre_num; 4 int pre_num_min; 5 int pre_num_max; 6 7 `uvm_component_utils_begin(mac_driver) 8 `uvm_field_int(pre_num_min,UVM_ALL_ON) 9 `uvm_field_int(pre_num_max,UVM_ALL_ON) 10 `uvm_component_utils_end 11 12 function void build_phase(uvm_phase phase); 13 super.build(phase); 14 //uvm_config_db#(int)::get(this,"","pre_num_max",pre_num_max); 15 //uvm_config_db#(int)::get(this,"","pre_num_min",pre_num_min); 16 endfunction 17 18 endclass
3. 跨層次的多重set(build_phase的set)
注1:后面需要補充非build_phase的set相關內容,可參考公眾號-芯片學堂;
假如set多次,get一次,那么最終get到的是哪個set值呢?
(1) 首先看set的優先級(層次越高,set的優先級越高);
(2) 其次看時間先后;
比如,在uvm_test_top和env中分別有以下set語句:
1 uvm_config_db#(int)::set(this,"env.agent.driver","pre_num_max",100); 2 uvm_config_db#(int)::set(this,"agent.driver","pre_num_max",999);
uvm_test_top的層次高於env,所以uvm_test_top中的set優先級高.因為越往上,越接近用戶,方便用戶控制.
4. 同一層次的多重set(build_phase的set)
當跨層次看待問題時,高層次的set優先; 當處於同一層次時,則是時間優先.
1 uvm_config_db#(int)::set(this,"env.agent.driver","pre_num_max",100); 2 uvm_config_db#(int)::set(this,"env.agent.driver","pre_num_max",109);
driver最終get的值會是109.
5. 非直線的設置與獲取
(1) 如在scoreboard中,對driver的某些變量使用config_db機制進行設置,則稱為非直線設置;
1 //my_scoreboard.sv 2 function void my_scoreboard::build_phase(uvm_phase phase); 3 ... 4 uvm_config_db#(int)::set(this.m_parent,"i_agt.drv","pre_num",200); 5 ... 6 endfunction 7 8 //my_scoreboard.sv 9 function void my_scoreboard::build_phase(uvm_phase phase); 10 ... 11 uvm_config_db#(int)::set(uvm_root::get(),"uvm_test_top.env.i_agt.drv","pre_num",200); 12 ... 13 endfunction
(2) 存在的問題: UVM沒有明文指出同一級別的build_phase的執行順序,所以當my_driver在獲取參數值時,my_scoreboard的build_phase可能已經執行了,也可能沒有執行;所以,這種非直線的設置,存在一定風險;
6. config機制對通配符的支持
(1) 在config_db::set操作時,其第二個參數可以提供完整的路徑,也可以不提供完整的路徑;
注1:可以將config_db的set放到一個module的initial begin...end塊內,並通過bind的方式將該module在top module內例化;
注2:下圖中使用通配符的code中,i_agt是否能看到該資源?需要確認下(可以!);
1 //top_tb.sv 2 //不使用通配符 3 initial begin 4 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.i_agt.drv","vif",input_if); 5 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.i_agt.mon","vif",input_if); 6 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.o_agt.mon","vif",output_if); 7 end 8 9 //使用通配符 10 initial begin 11 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.i_agt*","vif",input_if); 12 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.o_agt*","vif",output_if); 13 end 14 15 //使用通配符 16 initial begin 17 uvm_config_db#(virtual my_if)::set(null,"*i_agt*","vif",input_if); 18 uvm_config_db#(virtual my_if)::set(null,"*o_agt*","vif",output_if); 19 end
7. config_db與變量的變化
注:以下是仿真得出的結論;
(1) 如果通過config_db進行int變量的set/get,發現一次set后, int變量接着發生了變化,這種變化無法通過config_db::get得到; 只能在每次變化后,重新set,並且重新get;
(2) 如果通過config_db進行類變量/virtual interface的set/get,發現一次set后,類變量/virtual interface的內部成員變量值發生了變化,不需要重復get,可以直接通過已經get過一次的句柄/virtual interface發現其內部成員變量的變化;
