Welcome ! This website will help YOU (recent graduates/professionals) learn verification languages like SystemVerilog and UVM. Register for free and access more content !

The UVM configuration database accessed by the class uvm_config_db is a great way to pass different objects between multiple testbench components. Read more on Using config database for a quick review. There are two primary functions used to put and retrieve items from the database which are set() and get() respectively.

Syntax

 
static function void set (  uvm_component   cntxt,
                            string          inst_name,
                            string          field_name,
                            T               value);
 
static function bit get (   uvm_component  cntxt,
                            string         inst_name,
                            string         field_name,
                      inout T              value);
 

Rules

  • Create or update a config setting for field_name in inst_name from cntxt
  • The setting is made at cntxt with the full scope being {cntxt, ".", inst_name}
  • If cntxt is null, then inst_name provides the complete scope information of the setting
  • field_name is the target field
  • Both inst_name and field_name may be glob style or regular expression style expressions
  • Settings from hierarchically higher levels have higher precedence
  • Settings from the same level of hierarchy have a last setting wins semantic

How to debug expressions

The best way to understand how the combination of cntxt, inst_name and field_name works is by enabling the commandline debug +UVM_CONFIG_DB_TRACE switch for UVM that dumps information on all the set() and get() calls within a simulation.

$> irun <all_other_options> +UVM_CONFIG_DB_TRACE

Test and Env

To understand how config_db evaluates expressions, we'll set up a small testbench structure with an empty environment as shown below. An expression is set from the test class and retrieved in the environment's build_phase

Case 1

We set cntxt to null and inst_name to uvm_test_top to indicate that all components in the test can access the item. To keep things simple, we'll put a string item tagged as Friend.

 
class base_env extends uvm_env;
  ...
  string name;
 
  virtual function void build_phase (uvm_phase phase);
    super.build_name ();
 
    // Retrieve the string that was set in config_db from the test class
    if (uvm_config_db #(string) :: get (null, "uvm_test_top", "Friend", name))
      `uvm_info ("ENV", $sformatf ("Found %s", name), UVM_MEDIUM)
 
  endfunction
endclass
 
class base_test extends uvm_test;
  ...
  base_env   m_env;
 
  virtual function void build_phase (uvm_phase phase);
    ...
 
    // Set this string into config_db
    uvm_config_db #(string) :: set (null, "uvm_test_top", "Friend", "Joey");
  endfunction
endclass
 

It is quite clear that the first argument cntxt cannot be anything other than a uvm_component object. From the following simulation log, we can see that when +UVM_CONFIG_DB_TRACE is passed as a command-line switch, simulation will dump all function calls to set and get into the log. However, the lines of our interest are higlighted in color, the yellow one representing a set call and the green representing a successful get call. The concatenation of cntxt, inst_name and field_name match for both set and get calls and hence the database successfully finds and returns the string tagged as "Friend".

Simulation Log
ncsim> run
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(392) @ 0: reporter [UVM/RELNOTES] 
----------------------------------------------------------------
UVM-1.2
(C) 2007-2014 Mentor Graphics Corporation
(C) 2007-2014 Cadence Design Systems, Inc.
(C) 2006-2014 Synopsys, Inc.
(C) 2011-2013 Cypress Semiconductor Corp.
(C) 2013-2014 NVIDIA Corporation
----------------------------------------------------------------
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.recording_detail' (type logic signed[4095:0]) read by uvm_test_top.base_env = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.recording_detail' (type int) read by uvm_test_top.base_env = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.Friend' (type string) set by  = (string) "Joey"
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.m_agent0.recording_detail' (type logic signed[4095:0]) read by uvm_test_top.base_env.m_agent0 = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.m_agent0.recording_detail' (type int) read by uvm_test_top.base_env.m_agent0 = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.m_agent1.recording_detail' (type logic signed[4095:0]) read by uvm_test_top.base_env.m_agent1 = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.base_env.m_agent1.recording_detail' (type int) read by uvm_test_top.base_env.m_agent1 = null (failed lookup)
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.Friend' (type string) read by  = (string) "Joey"
UVM_INFO testbench.sv(36) @ 0: uvm_test_top.base_env [ENV] Found Joey
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
Case 2

Here, we'll make a slight modification to the set method, rest of the code being the same. The first argument cntxt gets this pointer, while inst_name is empty and still we get the same path "uvm_test_top.Friend" after concatenation.

 
  uvm_config_db #(string) :: set (this, "", "Friend", "Joey");
 
  // Same get method
  if (uvm_config_db #(string) :: get (null, "uvm_test_top", "Friend", name))
      `uvm_info ("ENV", $sformatf ("Found %s", name), UVM_MEDIUM)
 
Simulation Log
...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.Friend' (type string) set by uvm_test_top = (string) "Joey"
...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.Friend' (type string) read by  = (string) "Joey"

Test, Env, and two Agents

Now we'll expand the environment to have a couple of agents to make things more interesting.

config_db example
 
class base_agent extends uvm_agent;
  ...
 
  virtual function void build_phase (uvm_phase phase);
    if (uvm_config_db #(string) :: get (null, "uvm_test_top", "Friend1", name))
      `uvm_info ("AGENT", $sformatf ("[%s] found %s", this.get_name(), name), UVM_MEDIUM)
  endfunction
endclass
 
class base_env extends uvm_env;
  ...
  base_agent   m_agent0;
  base_agent   m_agent1;
  ...
endclass
 

If we run the code again with the new agents in place, you'll find that both agents also found the string tagged as "Friend1".

Simulation Log
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.Friend1' (type string) set by uvm_test_top = (string) "Joey"
...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.Friend1' (type string) read by  = (string) "Joey"
UVM_INFO testbench.sv(44) @ 0: uvm_test_top.base_env [ENV] Found Joey
...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.Friend1' (type string) read by  = (string) "Joey"
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.base_env.m_agent0 [AGENT] [m_agent0] Found Joey
...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.Friend1' (type string) read by  = (string) "Joey"
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.base_env.m_agent1 [AGENT] [m_agent1] Found Joey

Recommended Practice

The setting in config_db is visible by only those elements that can evaluate to the same expression as the set call. If we keep a global scope such as uvm_test_name, then all components will be able to retrieve that setting. However, this poses a potential problem of collision of field_name within the same scope, as well as retrieval of settings via unintended get calls. Hence, the recommended practice is to make the setting available to only those components that really require the setting to function. In a similar way, during get calls, components should look for settings that are available to them.

The expression that is set in config_db is "uvm_test_top.Friend" based on the set function call. config_db results show the expression evaluated by the get method call. If both of these expressions match or satisfies the glob properties, it is considered to be a match. In the case below, all the three get method calls failed simply because the expression each of the component tried to get is different from the expression that is set.

uvm_config_db #(string) :: set (this, "m_env.m_agent*", "Friend", "Joey");    // Set in test, available to agents
uvm_config_db #(string) :: get (this, "", "Friend", name);                   // Get in env
uvm_config_db #(string) :: get (this, "", "Friend", name);                   // Get in agent

cntxt = uvm_test_top, inst_name = m_env.m_agent*, tag = Friend
Expression set : "uvm_test_top.m_env.m_agent1*.Friend"

CONFIG_DB_TRACE results:
[CFGDB/SET] Configuration 'uvm_test_top.m_env.m_agent*.Friend' (type string) set by uvm_test_top = (string) "Joey"
[CFGDB/GET] Configuration 'uvm_test_top.m_env.Friend' (type string) read by uvm_test_top.m_env = null (failed lookup)
[CFGDB/GET] Configuration 'uvm_test_top.m_env.m_agent0.Friend' (type string) read by uvm_test_top.m_env.m_agent0 = (string) "Joey"
[CFGDB/GET] Configuration 'uvm_test_top.m_env.m_agent1.Friend' (type string) read by uvm_test_top.m_env.m_agent1 = (string) "Joey"

In the above case, the setting was made available only to the agents and hence environment was not able to retrieve it at its level. To make the setting available to the environment, we'll make another set call just for the environment. If you put a * like m_env*, then the setting will be made available to all the components in the environment.

uvm_config_db #(string) :: set (this, "m_env.m_agent*", "Friend", "Joey");    // Set in test, available to agents
uvm_config_db #(string) :: set (this, "m_env",          "Friend", "Joey");    // Set in test, available to env
uvm_config_db #(string) :: get (this, "", "Friend", name);                    // Get in env
uvm_config_db #(string) :: get (this, "", "Friend", name);                    // Get in agent

cntxt = uvm_test_top, inst_name = m_env.m_agent*, tag = Friend
Expression set : "uvm_test_top.m_env.m_agent1*.Friend"
cntxt = uvm_test_top, inst_name = m_env, tag = "Friend"
Expression set : "uvm_test_top.m_env.Friend"

CONFIG_DB_TRACE results:
[CFGDB/SET] Configuration 'uvm_test_top.m_env.Friend' (type string) set by uvm_test_top = (string) "Joey"
[CFGDB/SET] Configuration 'uvm_test_top.m_env.m_agent*.Friend' (type string) set by uvm_test_top = (string) "Joey"
[CFGDB/GET] Configuration 'uvm_test_top.m_env.Friend' (type string) read by uvm_test_top.m_env = (string) "Joey"
[CFGDB/GET] Configuration 'uvm_test_top.m_env.m_agent0.Friend' (type string) read by uvm_test_top.m_env.m_agent0 = (string) "Joey"
[CFGDB/GET] Configuration 'uvm_test_top.m_env.m_agent1.Friend' (type string) read by uvm_test_top.m_env.m_agent1 = (string) "Joey"

Was this article helpful ?

We use cookies to personalize content and ads, to provide social media features and to analyze our traffic. You consent to our cookies if you continue to use our website. To find out more about the cookies we use and how to delete them, see our privacy policy.

  I accept cookies from this site.
Agree
EU Cookie Directive plugin by www.channeldigital.co.uk