Race condition setting config from testbench parameter

Hi all.

This one has me going in circles. I’ve found related info in this forum but still can get it to work.

I have a top-level testbench with a bunch of parameters used to configure the RTL DUT and can also be overridden in the command-line with -g PNAME=PVALUE (I’m using QuestaSim).

I need to use these parameters in various places in my UVM env. From another post, I found this which partially works:

top.sv


module top;
  parameter A;

  my_uvm_config  cfg_h;  // config object to store parameters

  initial begin
    start_of_simulation_ph.wait_for_state(UVM_PHASE_STARTED);  // make sure to wait until UVM objects created
    uvm_config_db # (my_uvm_config) :: get (null, "", "my_uvm_config", cfg_h);

    cfg_h.a = A;
end 

my_uvm_config.sv:


class my_uvm_config extends uvm_object;
 `uvm_object_utils(my_uvm_config)

  int unsigned a;
  // new, etc
endclass

basetest.sv:


class basetest extends uvm_test;
   my_uvm_config  cfg_h;

   function void build_phase (phase);
       cfg_h = my_uvm_config :: type_id :: create ("cfg_h", this);
       uvm_config_db # (my_uvm_config) :: set (null, "*", "my_uvm_config", cfg_h);
       cfg_h.a = 5; // default value
    endfunction

Now this seems to work ok. Where it all breaks is that I have some agents set up in the env containing basetest that also need to get access to the value ‘a’ that might have been overridden in the command-line. When I set up a similar config object for the agent and try and set it in top, it doesn’t seem to wait for the UVM_PHASE_STARTED or some kind of race and the agents just get the default value.

I tried messing with uvm_config_db::wait_modified but couldn’t get the syntax right and couldn’t find much documentation for it (or start_of_simulation_ph.wait_for_state). Any ideas? Any better ways of passing RTL parameters into UVM land?

Thanks,

David

Without seeing all the code involved, it is difficult to see the cause of your problem. A better approach would be to set() the parameter into the config_db in the initial block. That is guaranteed to execute before any get() in your test environment.

module top;
  parameter A;
  initial begin
    uvm_config_db # (int) :: get (null, "", "ParamA", A);
end 

class basetest extends uvm_test;
   my_uvm_config  cfg_h;
 
   function void build_phase (phase);
       cfg_h = my_uvm_config :: type_id :: create ("cfg_h", this);
       uvm_config_db # (my_uvm_config) :: set (null, "*", "my_uvm_config", cfg_h);
       if ( !uvm_config_db #(int) :: get (null, "", "ParamA", cfg_h.a) )
            cfg_h.a = 5; // default value
    endfunction

In reply to dave_59:

Without seeing all the code involved, it is difficult to see the cause of your problem. A better approach would be to set() the parameter into the config_db in the initial block. That is guaranteed to execute before any get() in your test environment.

Thanks - I’ll try that. I thought it would be simpler to just get the handle to the config class instead of dealing with each item - but whatever works!

In reply to drogoff:
If you have a significant number of parameters to set, then I would go back to your original attempted code. When do your agents first try to read cfg_h.a?