天天看點

UVM的config機制一、概述二、interface傳遞三、變量設定四、object傳遞五、總結

一、概述

在驗證環境的建立過程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機制一、概述二、interface傳遞三、變量設定四、object傳遞五、總結

uvm_config_db #(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf)

的含義如下圖所示

UVM的config機制一、概述二、interface傳遞三、變量設定四、object傳遞五、總結

三、變量設定

在各個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()

    方法時,通過傳遞的參數構成索引層次,然後在

    uvm_resources

    已有的配置資訊池中索引該配置,如果索引到傳回1,否則傳回0。
  • 在使用

    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_config_db::get()

    方法時,添加便于調試的語句,例如通過UVM報告資訊得知

    uvm_config_db::get()

    方法中的配置變量是否從

    uvm_config_db

    擷取到。
下一篇: 棋子翻轉