Passing configuration objects around

We typically store configuration information in uvm_objects that are passed around through the config_db. This practice is widely used in our testbenches and works pretty well. Here’s an example:


class config_object extends uvm_object;
  int a;
endclass

class my_monitor extends uvm_monitor;

  config_object cfg_obj;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(config_object)::get(this, "*", "cfg_obj", cfg_obj))
        `uvm_fatal("something going wrong with configdb")
  endfunction

  task run_phase(uvm_phase phase);
    if (cfg_obj.a == 0) do_something();
    else                do_somethingelse();
  endtask
endclass

class env extends uvm_env;

  config_object cfg_obj;
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // Create the configuration object
    cfg_obj = config_object::type_id::create("cfg_obj", this);

    // Passing the configuration object through configdb
    uvm_config_db#(config_object)::set(null, "*my_monitor*", "cfg_obj", cfg_obj);
  endfunction
endclass

Up to here everything is without problem (at least this is what I think), but then I thought, hey why should I get the configuration in the monitor, this is what automation is for. So I modified the my_monitor class like this:


class my_monitor extends uvm_monitor;

  config_object cfg_obj;

  `uvm_component_utils_begin(my_monitor)
    `uvm_field_object(cfg_obj, UVM_DEFAULT)
  `uvm_component_utils_end

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    // no need to call the config_db::get explicitly anymore... right?
  endfunction

  task run_phase(uvm_phase phase);
    if (cfg_obj.a == 0) do_something();
    else                do_somethingelse();
  endtask
endclass


Unfortunately this does not work [1] and I’m not able to figure out why. Through the simulator I’m able even to see the “matching resource database entries” and apparently the component my_monitor matches the scope pattern for the given config_object, but it doesn’t seem to retrieve the handle correctly, which leads to a runtime failure when I try to access a null pointer.

Any idea/suggestion/pointer would be appreciated.

Al

[1] does not work: the component which is trying to retrieve the information from the config_db is not able to for the uvm_object even though it is capable for other members (like int, enum, etc.)

In reply to abs:

the component which is trying to retrieve the information from the config_db is not able to for the uvm_object even though it is capable for other members (like int, enum, etc.)

After some searching I’ve realized I was missing two points to make it work:

  1. I need to register the config_object as a uvm_object and not the extended class
  2. I need to automate the field with a UVM_REFERENCE instead

With the above I get the following code that works just fine:



class env extends uvm_env;

  config_object cfg_obj;
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // Create the configuration object
    cfg_obj = config_object::type_id::create("cfg_obj", this);

    // Passing the configuration object through configdb
    uvm_config_db#(uvm_object)::set(null, "*my_monitor*", "cfg_obj", cfg_obj); // <-- passing a uvm_object
  endfunction
endclass

class my_monitor extends uvm_monitor;

  config_object cfg_obj;

  `uvm_component_utils_begin(my_monitor)
    `uvm_field_object(cfg_obj, UVM_REFERENCE) // <-- I'm retrieving a reference to the config_object
  `uvm_component_utils_end

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    // no need to call the config_db::get explicitly anymore... right?
  endfunction

  task run_phase(uvm_phase phase);
    if (cfg_obj.a == 0) do_something();
    else                do_somethingelse();
  endtask
endclass


I think I’ll mark this question as the solution, but if anyone out there think I’m doing this wrong I’m open to suggestions

In reply to abs:

Two comments which may help:

When calling set() from within the UVM hierarchy, you want to use the appropriate context:


uvm_config_db#(config_object)::set(this, "my_agent.my_monitor", "cfg_obj", cfg_obj);

Also, note that the second argument is the relative path to the component which you want to target for the configuration. Make sure that this is correct.

Never use the field automation macros. Always call get() within the build_phase(). The second argument should always be an empty string (“”), unless you know what you are doing:


  if(!uvm_config_db#(config_object)::get(this, "", "cfg_obj", cfg_obj))
        `uvm_fatal("something going wrong with configdb")

In reply to cgales:

In reply to abs:
[…]
Never use the field automation macros. Always call get() within the build_phase(). The second argument should always be an empty string (“”), unless you know what you are doing:


if(!uvm_config_db#(config_object)::get(this, "", "cfg_obj", cfg_obj))
`uvm_fatal("something going wrong with configdb")

Why not using the automation macros? they seem to keep the code cleaner and remove a lot of boilerplate code. After all why would I want to do the get explicitly?

As for the empty string you refer to, could you elaborate on why it should be empty and what so mysterious about it? Thanks for your feedback

In reply to abs:

The Cookbook chapter on the Configuration Database explains the different arguments to set() and get().

This Cookbook chapter on UVM Macros explains why you shouldn’t use the automation macros.

In reply to abs:

In reply to cgales:
Why not using the automation macros? they seem to keep the code cleaner and remove a lot of boilerplate code. After all why would I want to do the get explicitly?
As for the empty string you refer to, could you elaborate on why it should be empty and what so mysterious about it? Thanks for your feedback

Could you please explain how the field automation macros are used instead of the config_db set and get?

In reply to chr_sue:

Could you please explain how the field automation macros are used instead of the config_db set and get?

the config_db set will still be needed, as I already mentioned here: Your text to link here…

The automation macros will simplify getting the fields from the config_db since the apply_config_settings() call in the super.build_phase will do this for us.

Does it answer your question or did I misunderstood something?

In reply to cgales:

In reply to abs:
The Cookbook chapter on the Configuration Database explains the different arguments to set() and get().
This Cookbook chapter on UVM Macros explains why you shouldn’t use the automation macros.

Thanks for the links.

As for the recommendation in the UVM Cookbook w.r.t. field macros, let me say that the article linked is mainly focused on the ovm_field macros, with a mild coverage over the uvm ones.

Moreover IMHO it does not give a sufficient rationale as to under which circumstances the code bloat is actually a real limiting factor for simulation execution. What if my environment has a dozen of agents with maybe 5 components each? would the field macros make a difference? I can imagine if you have thousands of components maybe everything counts, but talking about performances without giving a benchmark of some sort is somehow not useful.

The advice to write your own SystemVerilog functions to overcome the code bloat might be specific to some use case, but personally I find the field macros simpler to maintain and much more robust than what a team of mildly experienced verification engineers can achieve in a project timeline.

I also would like to say that Cadence UVM courses advocates for the usage of the field macros exactly to streamline the configuration of each component, so while I believe the article has merit to raise awareness on the potential performance impact, it would be a little far fetched to recommend to avoid using field macros wholesale.

In reply to abs:

Hi abs,

This is something really interesting. I was not aware of this and I am not sure why this method is not popular. May be because we cannot check if the value has been actually set or not? e.g. if virtual interface is not passed down to the driver, is there a way to check this without using conventional method of using uvm_config_db…get() method?

In reply to mbhat:

In reply to abs:
Hi abs,
This is something really interesting. I was not aware of this and I am not sure why this method is not popular. May be because we cannot check if the value has been actually set or not? e.g. if virtual interface is not passed down to the driver, is there a way to check this without using conventional method of using uvm_config_db…get() method?

If you pass this option: +UVM_CONFIG_DB_TRACE you will have the set and get call displayed in your log and can debug more easily (see the uvm_config_db_options class and its method turn_on_tracing which is activated by the option I referred to)

In reply to abs:

In reply to cgales:
As for the recommendation in the UVM Cookbook w.r.t. field macros, let me say that the article linked is mainly focused on the ovm_field macros, with a mild coverage over the uvm ones.
Moreover IMHO it does not give a sufficient rationale as to under which circumstances the code bloat is actually a real limiting factor for simulation execution. What if my environment has a dozen of agents with maybe 5 components each? would the field macros make a difference? I can imagine if you have thousands of components maybe everything counts, but talking about performances without giving a benchmark of some sort is somehow not useful.
The advice to write your own SystemVerilog functions to overcome the code bloat might be specific to some use case, but personally I find the field macros simpler to maintain and much more robust than what a team of mildly experienced verification engineers can achieve in a project timeline.
I also would like to say that Cadence UVM courses advocates for the usage of the field macros exactly to streamline the configuration of each component, so while I believe the article has merit to raise awareness on the potential performance impact, it would be a little far fetched to recommend to avoid using field macros wholesale.

I would not say the simulation performance is a real argument against the usage of field macros. But 1 argument is you will run into trouble when having a variable with the name ‘count’. This might cause serious issues.
The 2nd argument is, you get automatically generated functions. An engineer wants to have control over thhese things. What I recommend and whatis fairly easy is the usage of a UVM Framework Generator. This generator will create the code and you can take influence on the format.

If Cadnce is recommending field macros and Mentor is not I consider this as a differentiator between 2 competitors.
And I’d like to understand what do you mean with ‘streamlining the configuration’?

In reply to chr_sue:

In reply to abs:
I would not say the simulation performance is a real argument against the usage of field macros. But 1 argument is you will run into trouble when having a variable with the name ‘count’. This might cause serious issues.

Could you elaborate on the variable name ‘count’? What’s so special about it?

The 2nd argument is, you get automatically generated functions. An engineer wants to have control over thhese things. What I recommend and whatis fairly easy is the usage of a UVM Framework Generator. This generator will create the code and you can take influence on the format.

Control in my jargon means understanding how it works and use it as deemed fit. Yet for many use cases I think the macros are providing a good entry point to approach configuration without the need to maintain two separate calls (get and set, plus take care about the context, plus take care about the spelling, etc.). If there are specific use cases I should be aware of I’m all ears, but otherwise I wouldn’t easily buy in a religious debate whether we should always use them or never use them.

As for the UVM Framework Generator (which I’d call a shameless plug in this context ;-)), I’d be happy to try it out. I haven’t found the download page on your website. I’ll try searching a bit more and if I don’t find it I’ll come back to you.

If Cadnce is recommending field macros and Mentor is not I consider this as a differentiator between 2 competitors.
And I’d like to understand what do you mean with ‘streamlining the configuration’?

Streamlining: make (an organization or system) more efficient and effective by employing faster or simpler working methods.