[CU]config_db机制2-uvm_resource_pool/uvm_resource/uvm_resource_db/uvm_config_db常用函数
注1:该篇文章主要涉及config_db机制的一些函数;
1.资源的写入
1.1. uvm_resource_pool
1.1.1. uvm_resource_pool.get
1 class uvm_resource_pool; 2 3 static local uvm_resource_pool rp = get(); 4 5 uvm_resource_types::rsrc_q_t rtab [string]; 6 uvm_resource_types::rsrc_q_t ttab [uvm_resource_base]; 7 8 get_t get_record [$]; // history of gets 9 10 local function new(); 11 endfunction 12 13 14 // Function: get 15 // 16 // Returns the singleton handle to the resource pool 17 18 static function uvm_resource_pool get(); 19 if(rp == null) 20 rp = new(); 21 return rp; 22 endfunction 23 24 ... 25 endclass
1.1.2. uvm_resource_pool.set
set函数主要实现两点功能:
(1) 把输入参数rsrc插入到rtab的某条记录的队列中,记录的索引是字符串,即资源的名字; 此外,还会根据输入的override参数,决定把rsrc插入到队列的最前面还是最后面;
(2) 把输入参数rsrc插入到ttab的某条记录的队列中,并且也会根据override信息决定把rsrc放在队列的前面还是后面;
1 class uvm_resource_pool; 2 3 static local uvm_resource_pool rp = get(); 4 5 uvm_resource_types::rsrc_q_t rtab [string]; 6 uvm_resource_types::rsrc_q_t ttab [uvm_resource_base]; 7 ... 8 9 // Function: set 10 // 11 // Add a new resource to the resource pool. The resource is inserted 12 // into both the name map and type map so it can be located by 13 // either. 14 // 15 // An object creates a resources and ~sets~ it into the resource pool. 16 // Later, other objects that want to access the resource must ~get~ it 17 // from the pool 18 // 19 // Overrides can be specified using this interface. Either a name 20 // override, a type override or both can be specified. If an 21 // override is specified then the resource is entered at the front of 22 // the queue instead of at the back. It is not recommended that users 23 // specify the override parameter directly, rather they use the 24 // <set_override>, <set_name_override>, or <set_type_override> 25 // functions. 26 // 27 function void set (uvm_resource_base rsrc, 28 uvm_resource_types::override_t override = 0); 29 30 uvm_resource_types::rsrc_q_t rq; 31 string name; 32 uvm_resource_base type_handle; 33 34 // If resource handle is ~null~ then there is nothing to do. 35 if(rsrc == null) 36 return; 37 38 // insert into the name map. Resources with empty names are 39 // anonymous resources and are not entered into the name map 40 name = rsrc.get_name(); //get_name is the function of uvm_object; 41 if(name != "") begin 42 if(rtab.exists(name)) 43 rq = rtab[name]; 44 else 45 rq = new(); 46 47 // Insert the resource into the queue associated with its name. 48 // If we are doing a name override then insert it in the front of 49 // the queue, otherwise insert it in the back. 50 if(override & uvm_resource_types::NAME_OVERRIDE) 51 rq.push_front(rsrc); 52 else 53 rq.push_back(rsrc); 54 55 rtab[name] = rq; 56 end 57 58 // insert into the type map 59 type_handle = rsrc.get_type_handle(); 60 if(ttab.exists(type_handle)) 61 rq = ttab[type_handle]; 62 else 63 rq = new(); 64 65 // insert the resource into the queue associated with its type. If 66 // we are doing a type override then insert it in the front of the 67 // queue, otherwise insert it in the back of the queue. 68 if(override & uvm_resource_types::TYPE_OVERRIDE) 69 rq.push_front(rsrc); 70 else 71 rq.push_back(rsrc); 72 ttab[type_handle] = rq; 73 74 endfunction 75 ... 76 endclass
1.2.uvm_resource
1.2.1.uvm_resource#(T).new
(1) new函数主要实现: (a) 设置scope信息; (b) 设置precedence信息;
1 virtual class uvm_resource_base extends uvm_object; 2 3 protected string scope; 4 protected bit modified; 5 protected bit read_only; 6 7 uvm_resource_types::access_t access[string]; 8 9 // variable: precedence 10 // 11 // This variable is used to associate a precedence that a resource 12 // has with respect to other resources which match the same scope 13 // and name. Resources are set to the <default_precedence> initially, 14 // and may be set to a higher or lower precedence as desired. 15 16 int unsigned precedence; 17 18 // variable: default_precedence 19 // 20 // The default precedence for an resource that has been created. 21 // When two resources have the same precedence, the first resource 22 // found has precedence. 23 // 24 25 static int unsigned default_precedence = 1000; 26 27 // Function: new 28 // 29 // constructor for uvm_resource_base. The constructor takes two 30 // arguments, the name of the resource and a regular expression which 31 // represents the set of scopes over which this resource is visible. 32 33 function new(string name = "", string s = "*"); 34 super.new(name); 35 set_scope(s); 36 modified = 0; 37 read_only = 0; 38 precedence = default_precedence; 39 endfunction 40 ... 41 endclass
1 class uvm_resource #(type T=int) extends uvm_resource_base; 2 3 typedef uvm_resource#(T) this_type; 4 5 // singleton handle that represents the type of this resource 6 static this_type my_type = get_type(); 7 8 // Can't be rand since things like rand strings are not legal. 9 protected T val; 10 11 ... 12 function new(string name="", scope=""); 13 super.new(name, scope); 14 15 `ifndef UVM_NO_DEPRECATED 16 begin 17 for(int i=0;i<name.len();i++) begin 18 if(name.getc(i) inside {".","/","[","*","{"}) begin 19 `uvm_warning("UVM/RSRC/NOREGEX", $sformatf("a resource with meta characters in the field name has been created \"%s\"",name)) 20 break; 21 end 22 end 23 end 24 25 `endif 26 endfunction 27 ... 28 endclass
1.2.2.uvm_resource#(T).write
1 //---------------------------------------------------------------------- 2 // Class: uvm_resource #(T) 3 // 4 // Parameterized resource. Provides essential access methods to read 5 // from and write to the resource database. 6 //---------------------------------------------------------------------- 7 8 class uvm_resource #(type T=int) extends uvm_resource_base; 9 10 typedef uvm_resource#(T) this_type; 11 12 // singleton handle that represents the type of this resource 13 static this_type my_type = get_type(); 14 15 // Can't be rand since things like rand strings are not legal. 16 protected T val; 17 ... 18 // Function: write 19 // Modify the object stored in this resource container. If the 20 // resource is read-only then issue an error message and return 21 // without modifying the object in the container. If the resource is 22 // not read-only and an ~accessor~ object has been supplied then also 23 // update the accessor record. Lastly, replace the object value in 24 // the container with the value supplied as the argument, ~t~, and 25 // release any processes blocked on 26 // <uvm_resource_base::wait_modified>. If the value to be written is 27 // the same as the value already present in the resource then the 28 // write is not done. That also means that the accessor record is not 29 // updated and the modified bit is not set. 30 31 function void write(T t, uvm_object accessor = null); 32 33 if(is_read_only()) begin 34 uvm_report_error("resource", $sformatf("resource %s is read only -- cannot modify", get_name())); 35 return; 36 end 37 38 // Set the modified bit and record the transaction only if the value 39 // has actually changed. 40 if(val == t) 41 return; 42 43 record_write_access(accessor); 44 45 // set the value and set the dirty bit 46 val = t; 47 modified = 1; 48 endfunction 49 ... 50 endclass
1.2.3.uvm_resource#(T).set
1 class uvm_resource #(type T=int) extends uvm_resource_base; 2 3 typedef uvm_resource#(T) this_type; 4 5 // singleton handle that represents the type of this resource 6 static this_type my_type = get_type(); 7 8 // Can't be rand since things like rand strings are not legal. 9 protected T val; 10 ... 11 // Function: set 12 // 13 // Simply put this resource into the global resource pool 14 15 function void set(); 16 uvm_resource_pool rp = uvm_resource_pool::get(); //uvm_resource_pool::get(); 17 rp.set(this); //uvm_resource_pool::set(); 18 endfunction 19 ... 20 endclass
1.2.4.uvm_resource#(T).set_override
(1)调用uvm_resource_pool.set函数,并传入override参数;
1 // Function: set_override 2 // 3 // Put a resource into the global resource pool as an override. This 4 // means it gets put at the head of the list and is searched before 5 // other existing resources that occupy the same position in the name 6 // map or the type map. The default is to override both the name and 7 // type maps. However, using the ~override~ argument you can specify 8 // that either the name map or type map is overridden. 9 10 function void set_override(uvm_resource_types::override_t override = 2'b11); 11 uvm_resource_pool rp = uvm_resource_pool::get(); 12 rp.set(this, override); 13 endfunction
1.3. uvm_resource_db
1.3.1.uvm_resource_db::set
1 static function void set(input string scope, input string name, 2 T val, input uvm_object accessor = null); 3 4 rsrc_t rsrc = new(name, scope); //uvm_resource#(T).new(); 5 rsrc.write(val, accessor); //uvm_resource#(T).write(); 6 rsrc.set(); //uvm_resource#(T).set(); 7 8 if(uvm_resource_db_options::is_tracing()) 9 m_show_msg("RSRCDB/SET", "Resource","set", scope, name, accessor, rsrc); 10 endfunction
1 uvm_resource_db#(type)::set("scope", "name", value, accessor); 2 //path=scope+name, default value of accessor is null; 3 uvm_resource_db#(int)::set("test", "loop_cnt", 10, this); 4 5 uvm_resource_db#(type)::read_by_name("scope", "name", var, accessor); //accessor is not necessary; 6 uvm_resource_db#(type)::read_type("scope", var, accessor);
1.3.2.uvm_resource_db::set_default
(1) 往resource_pool内添加resource. 写入的resource采用的是默认值.
1 static function rsrc_t set_default(string scope, string name); 2 3 rsrc_t r; 4 5 r = new(name, scope); //uvm_resource#(T).new(); 6 r.set(); //uvm_resource#(T).set(); 7 return r; 8 endfunction
(2) uvm_resource_db::set()与uvm_resource_db::set_default()的对比: set_default函数与set函数几乎一样,只是没有调用uvm_resource#(T)的write函数. 因此,如果name参数不为空,uvm_resource_pool的rtab和ttab相应的队列中将各自插入一条记录,否则将只会在ttab的相应队列中插入一条记录.插入的这条记录的val值是默认的值,而没有经过设置,亦即default值.
1.3.3.uvm_resource_db::set_anonymous
(1)这个函数与set函数相似,唯一区别是实例化rsrc时,输入的名字为空,所以只会向uvm_resource_pool的ttab中插入一条记录,不会向rtab中插入记录.
1 static function void set_anonymous(input string scope, 2 T val, input uvm_object accessor = null); 3 4 rsrc_t rsrc = new("", scope); //uvm_resource#(T).new(); 5 rsrc.write(val, accessor); //uvm_resource#(T).write(); 6 rsrc.set(); //uvm_resource#(T).set(); 7 8 if(uvm_resource_db_options::is_tracing()) 9 m_show_msg("RSRCDB/SETANON","Resource", "set", scope, "", accessor, rsrc); 10 endfunction
1.3.4. uvm_resource_db::set_override()
(1)该函数与uvm_resource_db::set函数比较像,唯一区别是uvm_resource_db::set_override内部调用的是uvm_resource的set_override函数,而不是rsrc的set函数;
1 //class uvm_resource_db 2 static function void set_override(input string scope, input string name, 3 T val, uvm_object accessor = null); 4 rsrc_t rsrc = new(name, scope); 5 rsrc.write(val, accessor); 6 rsrc.set_override(); 7 8 if(uvm_resource_db_options::is_tracing()) 9 m_show_msg("RSRCDB/SETOVRD", "Resource","set", scope, name, accessor, rsrc); 10 endfunction
1 //class uvm_resource; 2 function void set_override(uvm_resource_types::override_t override = 2'b11); 3 uvm_resource_pool rp = uvm_resource_pool::get(); 4 rp.set(this, override); 5 endfunction
(2) uvm_resource#(T)的set_override函数的override参数默认值为2’b11,所以会同时进行NAME_OVERRIDE和TYPE_OVERRIDE.
(3) 如果uvm_resource_db::set_override的name参数不为空,那么uvm_resource_pool的rtab和ttab相应的队列中将各自插入一条记录,否则将会只在ttab的相应队列中插入一条记录.插入的这条记录放在相应队列的最前端.
1.3.5. uvm_resource_db::set_override_type
1 static function void set_override_type(input string scope, input string name, 2 T val, uvm_object accessor = null); 3 rsrc_t rsrc = new(name, scope); 4 rsrc.write(val, accessor); 5 rsrc.set_override(uvm_resource_types::TYPE_OVERRIDE); 6 7 if(uvm_resource_db_options::is_tracing()) 8 m_show_msg("RSRCDB/SETOVRDTYP","Resource", "set", scope, name, accessor, rsrc); 9 endfunction
(1) uvm_resource_db::set_override_type与uvm_resource_db::set_override类似,只是内部调用的是uvm_resource#(T)的set_override函数时,传入了TYPE_OVERRIDE参数,从而uvm_resource#(T)的set_override在调用uvm_resource_pool的set函数时,会传入TYPE_OVERRIDE参数.
(2) 函数的执行结果: 如果name参数不为空,那么uvm_resource_pool的rtab和ttab相应的队列中将各自插入一条记录,否则只会在ttab的相应队列中插入一条记录.ttab中插入的这条记录放在相应队列的最前端,而rtab中插入的这条记录(如果插入了)是放在相应队列的最后端.
1.3.6. uvm_resource_db::set_override_name
1 static function void set_override_name(input string scope, input string name, 2 T val, uvm_object accessor = null); 3 rsrc_t rsrc = new(name, scope); 4 rsrc.write(val, accessor); 5 rsrc.set_override(uvm_resource_types::NAME_OVERRIDE); 6 7 if(uvm_resource_db_options::is_tracing()) 8 m_show_msg("RSRCDB/SETOVRDNAM","Resource", "set", scope, name, accessor, rsrc); 9 endfunction
(1) uvm_resource_db::set_override_name与uvm_resource_db::set_override_type函数类似,只是在调用uvm_resource#(T)的set_override函数时,传入了NAME_OVERRIDE参数,从而uvm_resource#(T)的set_override在调用uvm_resource_pool的set函数时会传入NAME_OVERRIDE参数.
(2) 函数的执行结果: 如果name参数不为空,那么uvm_resource_pool的rtab和ttab相应的队列中将各自插入一条记录,否则将只会在ttab的相应队列中插入一条记录.ttab中插入的这条记录是放在相应队列的最后端,而rtab中插入的这条记录(假如插入了)是放在相应队列的最前端.
1.3.7. uvm_resource_db::write_by_name()
1 static function bit write_by_name(input string scope, input string name, 2 input T val, input uvm_object accessor = null); 3 4 rsrc_t rsrc = get_by_name(scope, name); 5 6 if(uvm_resource_db_options::is_tracing()) 7 m_show_msg("RSRCDB/WR","Resource", "written", scope, name, accessor, rsrc); 8 9 if(rsrc == null) 10 return 0; 11 12 rsrc.write(val, accessor); 13 14 return 1; 15 16 endfunction
(1) write_by_name函数并不会在rtab和ttab的相应队列中新插入记录,而是会更新记录. 这里的更新不止更新rtab中相应队列中的相应记录,同时也会更新ttab中相应队列的相应记录.
1.3.8. uvm_resource_db::write_by_type
1 static function bit write_by_type(input string scope, 2 input T val, input uvm_object accessor = null); 3 4 rsrc_t rsrc = get_by_type(scope); 5 6 if(uvm_resource_db_options::is_tracing()) 7 m_show_msg("RSRCDB/WRTYP", "Resource","written", scope, "", accessor, rsrc); 8 9 if(rsrc == null) 10 return 0; 11 12 rsrc.write(val, accessor); 13 14 return 1; 15 endfunction
(1) uvm_resource_db的write_by_type函数与write_by_name函数几乎一样,区别在于前者是根据输入的参数scope查找,后者是根据输入的scope和name查找.
(2) uvm_resource_db::write_by_type和uvm_resource_db::write_by_name都只更新rtab和ttab中相应队列中的记录,而不会向相应队列中插入一条新的记录.
1.3.9.uvm_resource_db::read_by_name && uvm_resource_db::read_by_type
(1)这两个函数比较类似,先通过get_by_type或者get_by_name得到要读取的资源的指针,之后调用uvm_resource#(T)的read函数;
1.4. uvm_config_db
(1) uvm_config_db从uvm_resource_db派生而来,对uvm_resource_db的一些功能进行了扩展,主要体现在对资源的写入和读取上.
(2) 在资源的写入操作上,它重载了uvm_resource_db的set函数;
(3) 在资源的读取操作上, 它新建了一个称为get的函数.
1.4.1. uvm_config_db::set(void函数)
1 static function void set(uvm_component cntxt, 2 string inst_name, 3 string field_name, 4 T value);
(1)使用格式: uvm_config_db#(data type)::set(uvm_component context, string instance_name, string field_name, T value);
(2)使用示例: uvm_config_db#(int)::set(this,"env.agent.sqr","count",10);
1.4.2. uvm_config_db::get(返回值为bit类型函数,返回值常用于判断是否成功get)
1 static function bit get(uvm_component cntxt, 2 string inst_name, 3 string field_name, 4 inout T value); 5 //TBD: add file/line 6 int unsigned p; 7 uvm_resource#(T) r, rt; 8 uvm_resource_pool rp = uvm_resource_pool::get(); 9 uvm_resource_types::rsrc_q_t rq; 10 uvm_coreservice_t cs = uvm_coreservice_t::get(); 11 12 if(cntxt == null) 13 cntxt = cs.get_root(); 14 if(inst_name == "") 15 inst_name = cntxt.get_full_name(); 16 else if(cntxt.get_full_name() != "") 17 inst_name = {cntxt.get_full_name(), ".", inst_name}; 18 19 rq = rp.lookup_regex_names(inst_name, field_name, uvm_resource#(T)::get_type()); 20 r = uvm_resource#(T)::get_highest_precedence(rq); 21 22 if(uvm_config_db_options::is_tracing()) 23 m_show_msg("CFGDB/GET", "Configuration","read", inst_name, field_name, cntxt, r); 24 25 if(r == null) 26 return 0; 27 28 value = r.read(cntxt); 29 30 return 1; 31 endfunction
(1)使用格式:uvm_config_db#(type)::get(uvm_component context, string instance_name, string field_name, inout T variable);
(2)uvm_config_db#(int)::get(this,"",count,count);
1.4.3. uvm_config_db::wait_modified
1 // Function: wait_modified
2 //
3 // Wait for a configuration setting to be set for ~field_name~
4 // in ~cntxt~ and ~inst_name~. The task blocks until a new configuration
5 // setting is applied that effects the specified field.
6
7 static task wait_modified(uvm_component cntxt, string inst_name,
8 string field_name);
1.4.4. uvm_config_db::exists