How do get value of string in an initial block the value of which is set in a build_phase

module mymod();

   string mystr;

   initial begin
      if (!(uvm_config_db#(string)::get(this, "*", "my_string", mystr)))
        `uvm_fatal("FATAL", "Could not get value for my_string")
   end
endmodule

module mymod1();
   `include "tests.sv"
   `include "myobjs.sv"
   initial begin
      run_test();
   end
endmodule

File:tests.sv
class c1 extends uvm_object;
   string mystr1="VALUE1";

   function new()
      super.new();
   endfunction
   virtual function void build_phase(uvm_phase phase)
      super.build_phase(phase);
      uvm_config_db#(string)::set(null, "*", "my_string", mystr1);
   endfunction
endclass

File:myobjs.sv
class mytest extends uvm_test;
   c1 obj_c1;
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      obj_c1=c1::type_id::create("obj_c1", this);
   endfunction
endclass

Compile order is mymod1 followed by mymod

But the code hits uvm_fatal in mymod. I get that the order of execution of “initail” block is not controllable.
But is there a way I can get the value “my_string” in mymod module or there’s no way

The idea is to control the blocks that get compiled without having to use 'ifdef
It’s easier to control(compilation)the blocks in an agent. Based on the agent if it’s active we use uvm_active_passive_enum and check if “is_active” we have all 3 blocks seqr, driver and monitor, if not we drop the seqr & driver.
But I’m trying to control the blocks that get compiled at the top(top most module), but controlling what gets compiled from a test and without having to use ifdef

Hope there’s a way.

Thanks in advance

In reply to bramani@uvm:

modules are static entity so your string has to be defined either through preprocess (ifdef macro) or parameter. If you have a requirement for some module to be compiled, then you can use
typedef enum {A=0 , B}string_e
parameter string_e STRING = A
generate if ( STRING == A ) … generate

In reply to bramani@uvm:
Please use code tags making your code easier to read. I have added them for you.

It would also help to make your code as complete and runnable as possible. There were many errors in your code even before I could get to your issue.

Your issue is that when you call run_test(), the component phases like build_phase() do not actually start executing until after at least one #0 delay. So you can’t call uvm_config_db::get() at time 0 unless you wait until the NBA region starts executing, or you can use uvm_config_db#(string)::wait_modified until the ::set happens (be careful of a hang if it never gets set).

import uvm_pkg::*;
`include "uvm_macros.svh"
module mymod;
 
   string mystr;
 
   initial begin
     uvm_wait_for_nba_region;
    // uvm_config_db#(string)::wait_modified(null, "*", "my_string");
     if (!(uvm_config_db#(string)::get(null, "*", "my_string", mystr))) // can't use 'this'
        `uvm_fatal("FATAL", "Could not get value for my_string")
       else  $display("Value for my_string is: ",mystr);
   end
endmodule
 
module mymod1;
  class c1 extends uvm_component; // not uvm_object
    `uvm_component_utils(c1) // missing
   string mystr1="VALUE1";
 
    function new(string name, uvm_component parent); //missing
      super.new(name,parent);
   endfunction
    virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      uvm_config_db#(string)::set(null, "*", "my_string", mystr1);
   endfunction
endclass
 
class mytest extends uvm_test;
  `uvm_component_utils(mytest) // missing
 function new(string name, uvm_component parent); // missing
      super.new(name,parent);
 endfunction
   c1 obj_c1;
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      obj_c1=c1::type_id::create("obj_c1", this);
   endfunction
endclass
 
   initial begin
     run_test("mytest"); // missing "mytest"
   end
endmodule

Thanks Dave, exactly what I was looking for and it worked :-)