uvm_config_db and uvm_resource_db


uvm_resource_db is base class and uvm_config_db is extended from uvm_resource_db. Using the resource_db requires that the scope (arbitrary string) for the set and get a match. For trivial environments, this isn’t difficult. However, for complex environments, including IP from different sources, it’s more difficult to manage. That, along with some other non-intuitive behaviors of the resource_db is why you should always just use the config_db.

uvm_config_db and it’s application

The UVM configuration mechanism supports sharing of configurations and parameters across different testbench components. This is enabled using a configuration database called uvm_config_db. Any testbench component can populate the configuration database with variables, parameters, object handles, etc. Other testbench components can get access to these variables, parameters, object handles from the configuration database without really knowing where it exists in the hierarchy.  

In particular, uvm_resource_db uses a “last write wins” approach. The uvm_config_db, on the other hand, looks at where things are in the hierarchy up through end_of_elaboration, so “parent wins.” Once you start start_of_simulation, the config_db becomes “the last write wins.”

The get() and set() are the primary methods used to populate or retrieve information from the uvm_config_db. Any verification component can use the set() method to populate the config_db with some configuration information and can also control which other components will have visibility to the same information. It could be set to have global visibility or visible only to one or more specific testbench components. The get() function checks for a shared configuration from the database matching the parameters. The syntax for the get() and set() methods are as follows:

uvm_config_db#(<type>)::set(uvm_component context, string inst_name, string field_name,<type> value)
uvm_config_db#(<type>)::get(uvm_component context, string inst_name, string field_name, ref value)

Context specifies the current class or component from which get/set is called. 

inst_name is the name of the instance of a component from which get/set is called.

field_name is the name of the object or parameter or variable which is set/get in config_db. 

 <type> identifies the type of the configuration information set/get in config_db. For object handles, this will have the class name while for other variables; it will be the type of that variable.  

Let’s understand the application of uvm_config_db with an example:

module test;
  logic pclk;
  logic [31:0] paddr;
  //Instantiate an APB bus master DUT
  apb_master apb_master(.pclk(pclk),*);
  //Instantiate a physical interface for APB interface
  apb_if apb_if(.pclk(pclk), *);
  initial begin
    //Pass this physical interface to test class top
    //which will further pass it down to env->agent->drv/sqr/mon
    uvm_config_db#(virtual apb_if)::set(null, “uvm_test_top”, “vif”, apb_if);
class apb_env extends uvm_env;
  apb_agent agt;
  //virtual interface for APB interface
  virtual apb_if vif;
  function void build_phase(uvm_phase phase);
    agt = apb_agent::type_id::create(“agt”, this);
    if (!uvm_config_db#(virtual apb_if)::get(this, ””, “vif”, vif))
        `uvm_fatal(“config_db_err”, “No virtual interface specified for this env instance”)
          uvm_config_db#(virtual apb_if)::set( this, “agt”, “vif”, vif);
  endfunction: build_phase
endclass : apb_env

In the above-mentioned example, interfaces will set() the virtual interface in the uvm_config_db. A test class or any other component in the UVM component hierarchy can then query the uvm_config_db using the get() method to get handles to this virtual interface and use them for accessing signals. The following shows an example of how this is done. The module test actually instantiates a DUT and physical interface for an APB bus master. It then sets the virtual interface handle to the uvm_config_db