Build_phase() doesn't start

I have created a component with it’s ’ parent ’ argument as null

( i.e It comes a child of uvm_root i.e a Top - Level Component )


 
  `include "uvm_pkg.sv"
  `include "uvm_macros.svh" 
  
   import  uvm_pkg::*;
  
  class  base_comp extends  uvm_component ;

     //  Factory  Registration  N  Std.  3  line  Component  Constructor 

      function  void  build_phase ( uvm_phase phase ) ;
       
          `uvm_info( get_name , $sformatf(" In  build_phase()  of  base_comp")  , UVM_NONE ) 

      endfunction
      
  endclass
 
  class  my_env extends  uvm_env ;

     //  Factory  Registration  N  Std.  3  line  Component  Constructor 
      
      base_comp  base_h ;

      function  void  build_phase ( uvm_phase phase ) ;
       
        base_h  =  base_comp  :: type_id :: create( "base_h" , null ) ;  // ' null '  parent  !!

      endfunction
      
  endclass


  class  user_test extends  uvm_test ;

     //  Factory  Registration  N  Std.  3  line  Component  Constructor 
      
      my_env   my_env_h ;

      function  void  build_phase ( uvm_phase phase ) ;

          my_env_h  =  my_env :: type_id :: create("my_env_h",this) ; 

      endfunction        

 endclass

module  top_tb ;

    initial  run_test("user_test") ;

endmodule



I Observe Output as ::
UVM_INFO @ 0: reporter [RNTST] Running test user_test…

NOTE :: There is No display from the build_phase() of base_comp !!

If I Print Topology in connect_phase() of user_test , I Observe that base_comp has been created

However when I change the syntax to create ::


  base_h  =  base_comp  :: type_id :: create( "zase_h" , null ) ;  //  Changed  the  name  argument 
 

Now I Observe Output as ::

UVM_INFO @ 0: reporter [RNTST] Running test user_test…
UVM_INFO @ 0: zase_h [zase_h] In build_phase() of base_comp

[Q] So why doesn’t build_phase() start in the Original Code ?

In reply to MICRO_91:

Your problem is here:
function void build_phase ( uvm_phase phase ) ;

    base_h  =  base_comp  :: type_id :: create( "base_h" , null ) ;  // ' null '  parent  !!

  endfunction

The 2nd argument is pointing to the parent. And the parent is the env.
Replace ‘null’ with ‘this’ and it will work.

In reply to chr_sue:

Like I mentioned I have purposely used ’ null ’ as parent argument .

Also when I change the name argument ( parent argument remains null )
I do Observe display from build_phase() of base_comp .

In reply to MICRO_91:

I was investigating your problem in some more detail.
Replacing the argument ‘this’ with ‘null’ should result in a bad reference fatal error.
Could you provide your example on EDAPlayground, please.

In reply to chr_sue:

EDAPlayground

Components created in a module before calling run_test() are created with ’ parent ’ argument as null .

So using null as argument isn’t illegal .

In reply to MICRO_91:

When you call run_test(), UVM creates a single instance of your test as uvm_test_top. The UVM scheduler only knows of this one top-level instance and calls all of the phases on this top-level module and child components.

If you create() another component outside of this hierarchy, UVM can’t just restart these phases on an new top-level.

Why are you trying to create a component outside of the uvm_test_top hierarchy? Is there a problem you are trying to solve?

In reply to cgales:

I was curious to try a code with parent component as null so that it becomes a child of uvm_root .

I understand that typically there is only one top-level instance i.e uvm_test_top .

However components created with parent argument as null before calling run_test ,
are a top level component too i.e There are 2 top-level instances

uvm_test_top and the the component created before run_test .

Your suggestion on “UVM can’t just restart these phases on an new top-level” is a start .

Given that build_phase operates depth-first the instance_name decides the exact order of calling build_phase .

Changing the instance_name to “zase_h” ensures that build_phase() does execute .

My understanding for now is that Lexicographical ordering impacts the Output .
As “z” occurs after “u” , build_phase() executes
whereas as “b” occurs before “u” , the scheduler has moved past “u” by then , so it doesn’t execute .

To have a deeper understanding I might need to debug the source code

EDIT : A similar issue has been discussed here

In reply to MICRO_91:

You are correct. The uvm_root maintains a list of children. “uvm_test_top” is one of these that is created by run_test(). You can also create other top level instances at the testbench, or as you are doing, in the build_phase(). However, the list of children in uvm_root is iterated over by name, so if you create an instance that is named alphabetically before the current instance, the build_phase() won’t be called.

Additionally, the follow on phases will be called on all of the top level instances, so in your case where you create a component that is alphabetically before ‘uvm_test_top’, the connect_phase() will be called even though the build_phase() wasn’t.