The White Rabbit Link to heading

Configuration database is used to pass around configuration parameters through centralized database. one of the famous patterns is storing the virtual interface.

uvm_config_db#(virtual v_if)::set(null,"*","v_if",intf);

Then any component(driver/monitor) can get the virtual interface

uvm_config_db#(virtual v_if)::get(null,"*","v_if",vintf);

::set Link to heading

Starting with ::set, it is defined in src/base/uvm_config_db.svh as static method of class uvm_class_db

class uvm_config_db#(type T=int) extends uvm_resource_db#(T);

...
...
  static function void set(uvm_component cntxt,
                           string inst_name,
                           string field_name,
                           T value);

set uses cntxt to build the inst_name then add resource m_rsc if it doesn’t exist

    uvm_pool#(string,uvm_resource#(T)) pool;


    if(cntxt == null) 
      cntxt = top;
    if(inst_name == "") 
      inst_name = cntxt.get_full_name();
    else if(cntxt.get_full_name() != "") 
      inst_name = {cntxt.get_full_name(), ".", inst_name};

    if(!m_rsc.exists(cntxt)) begin
      m_rsc[cntxt] = new;
    end
    pool = m_rsc[cntxt];

m_rsc is defined as assoc array of pools

  static uvm_pool#(string,uvm_resource#(T)) m_rsc[uvm_component];

Assuming the field wasn’t already in the pool for that context, a new resource is created and added to the pool

       r = new(field_name, inst_name);
       pool.add(lookup, r);

and in uvm_pool.svh, add just adds the item (in this case resource to local protected assoc array)

  virtual function void add (KEY key, T item);
    pool[key] = item;
  endfunction

at this point, the value and cntxt are passed to resource.

  r.write(value, cntxt);

and write, define in uvm_resource.svh, just stores the value in local variable val

    val = t;

at this point, we have the resource r ready to be in uvm_resource_pool. Note that uvm_resource_pool will be used by ::get in the next section.

    if(exists) begin
      uvm_resource_pool rp = uvm_resource_pool::get();
      rp.set_priority_name(r, uvm_resource_types::PRI_HIGH);
    end
    else begin
      //Doesn't exist yet, so put it in resource db at the head.
      r.set_override();
    end

set_override is defined in uvm_resource.svh,

  function void set_override(uvm_resource_types::override_t override = 2'b11);
    uvm_resource_pool rp = uvm_resource_pool::get();
    rp.set(this, override);
  endfunction

uvm_resource_pool has the set method called with resource. Note the resource has the value and context at this point. rq is created for that resource, and added to rtab assoc array

        rq = new();
        ....
      if(override & uvm_resource_types::NAME_OVERRIDE)
        rq.push_front(rsrc);
      else
        rq.push_back(rsrc);

      rtab[name] = rq;

::get Link to heading

it is also defined in src/base/uvm_config_db.svh as static method of class uvm_class_db. have similar logic to set

starting with creating the inst_name

   if(cntxt == null) 
      cntxt = uvm_root::get();
    if(inst_name == "") 
      inst_name = cntxt.get_full_name();
    else if(cntxt.get_full_name() != "") 
      inst_name = {cntxt.get_full_name(), ".", inst_name};

then the instance name is looked up in uvm_resource_pool

    uvm_resource_pool rp = uvm_resource_pool::get();
    uvm_resource_types::rsrc_q_t rq;
    ...
    rq = rp.lookup_regex_names(inst_name, field_name, uvm_resource#(T)::get_type());
    r = uvm_resource#(T)::get_highest_precedence(rq);
    ...
        value = r.read(cntxt);

lookup_regex_names looks up the name and returns the uvm_resource_pool. it iterates over rq in rtab and returns it.

  function uvm_resource_types::rsrc_q_t lookup_regex_names(string scope,
                                                           string name,
                                                           uvm_resource_base type_handle = null);

...
...
      foreach (rtab[re]) begin
      rq = rtab[re];
      for(i = 0; i < rq.size(); i++) begin
        r = rq.get(i);
        if(uvm_re_match(uvm_glob_to_re(re),name) == 0)
          // does the type and scope match?
          if(((type_handle == null) || (r.get_type_handle() == type_handle)) &&
             r.match_scope(scope))
            result_q.push_back(r);
      end
    end
    return result_q;

get_highest_precedence given uvm_resource_types::rsrc_q_t, will get the first element in the queue that was push_front in last stage in ::set

  function uvm_resource_base get_highest_precedence(ref uvm_resource_types::rsrc_q_t q);
...
...
    // get the first resources in the queue
    rsrc = q.get(0);