Uvm_config_db set from module, get from testcase?

I’m setting a uvm_config_db value from the top level module using

uvm_pkg::uvm_config_db#()::set(uvm_root::get(), “*”, “”, );

Then in the testcase I do the following:

if (!(uvm_pkg::uvm_config_db#()::get(uvm_root::get(), “*”, “<classname”, ) begin
`uvm_fatal(…)
end

The above line fails, however if I do the get within the top level module, it passes, so the name is correct. The path has to be correct since it’s the same. But it seems like the hierarchical path used in the get isn’t the same as the one in the set, or at least that’s what it seems to be at the moment.

As a side note, I’d really to pass a parameterized class using this method, but it fails just the same. The above is a simplified version of the parameterized class attempt.

So, my question is whether I can set a variable in the config_db from a module and read it later in a testcase. And then to ask whether I can do that with a parameterized class.

Thanks.
James.

In reply to jwatt_f:

In your top-level module, you should set the value with:


uvm_config_db#(data_type)::set(null, "uvm_test_top", "DATA_NAME", data_handle);

In your testcase, you should get the value with:


if (!uvm_config_db#(data_type)::get(this, "", "DATA_NAME", data_handle))
  `uvm_error(get_full_name(), "Unable to get DATA_NAME");

For a parameterized class, create a typedef of the class with the required parameter and use the typedef as ‘data_type’.

In reply to jwatt_f:

A quick addition to the answer above .


uvm_config_db#(data_type)::set(null, "uvm_test_top", "DATA_NAME", data_handle); 

This will work in 99% of the cases where either ::

(1) String Argument is provided to run_test in top_tb and No run-time argument of +UVM_TESTNAME=user_test

(2) Run-time argument of +UVM_TESTNAME=user_test is provided

However if the component / test ( where the config_db::get is being fetched ) is explicitly created before call to run_test


   initial  begin
     
     //  No  "uvm_test_top"  as  2nd  argument  !!

     uvm_config_db#(data_type)::set(null, "user_comp_h" , "DATA_NAME", data_handle);

     user_comp_h =  user_comp :: type_id :: create("user_comp_h" , null); 
    
     //  Could  even  set  after  creating  user_comp  as  Phasing  would  start  after  call  to  run_test()
    //  uvm_config_db#(data_type)::set(null, "user_comp_h", "DATA_NAME", data_handle);

     run_test() ;

   end

  //   Assume  run - time  argument  of  +UVM_TESTNAME=user_test  is  provided


Now if the config::get is required in user_comp ::


  //  In  user_comp's  build_phase() ::
  
  if (!uvm_config_db#(data_type)::get(this, "", "DATA_NAME", data_handle))
  `uvm_error(get_full_name(), "Unable to get DATA_NAME");
  
 

In reply to cgales:

Thanks. I tried this and it still won’t find the class. I have typedefs for the parameterized classes, but I’m not using them right now, only the bare class.

I’ve also changed “uvm_test_top” to the actual name of the module where the set occurs. Also tried uvm_test_top - no joy.

In reply to ABD_91:

Unfortunately it’s still not seeing the name in uvm_config_db. Are there any ways to view the uvm_config_db in a log file? Visualizer isn’t helping me with this part.

In reply to jwatt_f:

The second argument to set() is not the module where the set() is being called. It is the ‘target’ instance name of where get() will be called.

In your top-level module, you should always target ‘uvm_test_top’. This is the name of the top-level class created by the run_test() call. In your test class, you should get() every item set in the top-level and place it in the required agent’s configuration object, and then pass the agent’s configuration object in the config_db, targeting the correct agent’s hierarchy.

The UVM Cookbook explains how to use the config_db correctly.

In reply to cgales:

In reply to jwatt_f:
The second argument to set() is not the module where the set() is being called. It is the ‘target’ instance name of where get() will be called.
In your top-level module, you should always target ‘uvm_test_top’. This is the name of the top-level class created by the run_test() call. In your test class, you should get() every item set in the top-level and place it in the required agent’s configuration object, and then pass the agent’s configuration object in the config_db, targeting the correct agent’s hierarchy.
The UVM Cookbook explains how to use the config_db correctly.

Thanks for the info!

The ::get is called in the testcase, the ::set in the top level module. I don’t have a config object, just the testcase and the instance of the class created at the top level.

I’ve reviewed the cookbook and it doesn’t describe what happens at the top (infers it).

So, in the module I’ve tried the following:
uvm_pkg::uvm_config_db#[[class typedef])::set(null, “[test_instance_name]”, “[name]”, [local_instance_value);
uvm_pkg::uvm_config_db#([class typedef])::set(uvm_root::get(), “[test_instance_name]”, “[name]”, [local_instance_value]);
uvm_pkg::uvm_config_db#([class typedef])::set(uvm_root::get(), “[instance_name_inside_test]”, “[name]”, [local_instance_value]);
uvm_pkg::uvm_config_db#([class typedef])::set(null, “uvm_test_top.*”, [instance_name_inside_test]", “[name]”, [local_instance_value]);

In the testcase:
uvm_pkg::uvm_config_db#([class typedef])::get(this, “”, “[testcase_instance_name]”, tc_local_var);
uvm_pkg::uvm_config_db#([class typedef])::get(this, “”, “[local_instance_name]”, tc_local_var);

None of the above works, still can’t find the handle.

In reply to jwatt_f:

You seem to be confused regarding the third argument. The third argument to both set() and get() is a string used to identify the object. This argument needs to be identical in the set() and get() functions.

I’m not sure why you are trying to use “[testcase_instance_name]” or “[local_instance_name]”. If you use “[name]” in the set(), you need to use “[name]” in the get().

In reply to cgales:

A typo on my part while transcribing late at night, sorry. In the get, the [name] is the same in both the module and the testcase.

I created another call to set and get using a completely different name, “_FRED”. Also, I found another function, exists(), and am using that to check as well. The call is

uvm_pkg::uvm_config_db#([my_type])::exists(this, “*”, “_FRED”, 1);

In the module I set _FRED and it shows up in visualizer (1 write, 0 reads):

The set is:
uvm_pkg::uvm_config_db#([my_type])::set(null, “uvm_test_top”, “_FRED”, [local_var]);

And the get is:

uvm_pkg::uvm_config_db#([[my_type])::get(this, “*”, “_FRED”, fred);

Exists() claims _FRED doesn’t exist.

The second argument to set is the instance name, is a hierarchical string, and is used to limit availability of the variable to certain instances. The first argument is the context and is prepended to the instance name string. Or at least that’s what I understand from various docs. So if the context is null, the 2nd argument has to start at the top. If the first arg is something like uvm_root::get(), the second arg can start there, or be “"? If I don’t care to limit availability, I should be able to use null as the first argument and "” as the instance?

In reply to jwatt_f:

You can’t just add “*”. The set() and get() calls have specific parameter requirements. You are not following what I wrote in the first response.

Here is an example you can use as reference:


import uvm_pkg::*;
`include "uvm_macros.svh"

class config_object#(int CFG_VAL=10) extends uvm_object;
  typedef config_object#(.CFG_VAL(42)) config_object_t;

  `uvm_object_param_utils(config_object_t);
  
  int my_config_int = CFG_VAL;
  
  function new(string name="config_object");
    super.new(name);
  endfunction
endclass

class my_test extends uvm_test;
  typedef config_object#(.CFG_VAL(42)) config_object_t;
  
  `uvm_component_utils(my_test);
  
  config_object_t cfg_obj_m;
  
  function new(string name="my_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if (!uvm_config_db#(config_object_t)::get(this, "", "CFG_OBJ", cfg_obj_m)) begin
      `uvm_fatal(get_full_name(), "Unable to get CFG_OBJ");
    end
    
    `uvm_info(get_full_name(), $sformatf("Config object my_config_int is %0d", cfg_obj_m.my_config_int), UVM_MEDIUM);

  endfunction
endclass

module testbench();
  typedef config_object#(.CFG_VAL(42)) config_object_t;

  config_object_t cfg_obj;
  
  initial begin
    cfg_obj = config_object_t::type_id::create("cfg_obj");
    uvm_config_db#(config_object_t)::set(null, "uvm_test_top", "CFG_OBJ", cfg_obj);
    run_test("my_test");
  end
endmodule