Issues while connecting port in class hierarchy to a module having imp

Hi all ,


class trans ;
   rand int addr;
endclass

class leaf1 extends uvm_component;
 `uvm_component_utils(leaf1)
  uvm_blocking_put_port #(trans) out; // Initialized in build_phase with name arg. as "out" .
  // Std 3 line constructor 
  // In build_phase 
   out = new("out" , this ) ; 
   uvm_config_db#(uvm_blocking_put_port #(trans))::set( uvm_root::get() ,"*","ENV",out) ; // [A] 
virtual task run_phase(uvm_phase phase);
   trans t;
     phase.raise_objection(this, "prolonging run_phase");
     t = new;
     t.randomize();
 
       out.put(t);
        #5 ;
	phase.drop_objection(this, "prolonging run_phase");
  
  endtask
endclass

class env extends uvm_env ;

  `uvm_component_utils(env)
  
   leaf1  leaf1_h ;
 
 function new(string name, uvm_component parent=null);
   super.new(name,parent);
   leaf1_h = new("leaf1_h",this);
  endfunction

endclass

module top ;

class my_class extends uvm_component ;
   `uvm_component_utils(my_class)
     uvm_blocking_put_imp #( trans, my_class ) imp ; 
     
    // Std . 3 Line Constructor 
      task put ( input trans t ) ;
       `uvm_info(get_name,$sformatf("Received %0p",t),UVM_NONE)
      endtask 
    
     function void build_phase ( uvm_phase phase ) ;
      uvm_blocking_put_port #(trans) put ;

       imp = new("imp",this) ;

     if (  uvm_config_db#( uvm_blocking_put_port #(trans) )::get(this,"","ENV",put) )  // [B] 
      begin  
	put.connect( imp ) ; 
      end
    else
       begin
         `uvm_error("CONFIG_DB_GET","GET Failed")  // Fails but why ??
       end

     endfunction

     function void connect_phase ( uvm_phase phase ) ;
          put.connect(imp)
     endfunction

my_class class_h ; 

initial begin
   class_h = new("class_h" , null ) ; // Would also be a top-level component at same level of hierarchy as run_test argument component !!
   run_test("env");
 end

In the Output I see error as its unable to get inside myclass . I have a few questions

[A] Since myclass is also a top-level component , I have purposely set the cntxt argument as instance of uvm_root ( I could write null too ) .

[B] So why am I unable to get it in myclass ?

In reply to MICRO_91:

First, you need to use “create” method to create these components.
Second, your my_class is not a part of env hierarchy. When you call run_test(“env”), uvm will traverse all components which are children of env component and execute their phases in order from build to final.
Since my_class is not a child of env component, I think there is no way all phases of my_class can be called.

You should create a test component where env, my_class are children, then you call run_test(“test”).

In reply to cuonghle:

I appreciate your reply but I respectfully disagree with phasing in my_class .

The above code is a small example of what I am trying to do .
There is already a post here to achieve phasing in static entity like modules .

Although its opposite to what is normally implemented in code , its still possible ( Achieving phasing in modules )

In reply to MICRO_91:

You should be careful with your words.
As a UVM Coach and Trainer I see what people are doing with the UVM. Of course you can do what you like. But in most cases you are limiting the power of the UVM. When learning the wrong things you will do them also in your projects resulting bad examples.
At least you should follow the approach using the test/environment/agent appraoch.
A simple example of bad UVM code is using $display. Doing so you did not understand the power and the benefit of the UVM reporting mechanism.

In reply to chr_sue:

I mean no disrespect to anybody here , nor do I mean to offend anyone .

I have posted a sample code to express my query and hence I don’t use the general practice of using create() above .
There are far more components in my actual environment ( VIP ) than what I have mentioned above . I just meant to post a small code trying to achieve my goal .

Also as per the link about the phasing mechanism in module , others too have faced similar challenges .

In reply to MICRO_91:

Hi,

After checking, I agree with you about the phasing approach.
About your problem, the my_class component is not a part of “env” component hierarchy, then the order execution of leaf1’s build_phase and my_class’s build_phase cannot be identified. In your case, the my_class’s build_phase was executed before leaf1’s build_phase, that’s why you could not get what you want in build_phase of my_class component.

If you move the uvm_config_db#(…)::get(…) statement of my_class component to other phases which are executed after build_phase (such as connect_phase, etc.), you will be able to get your port.
Example:


class my_class extends uvm_component ;
  ...
  function void connect_phase(uvm_phase phase);
    uvm_blocking_put_port #(trans) put ;
    if(uvm_config_db#( uvm_blocking_put_port #(trans) )::get(this,"","ENV",put) )  // [B] 
    begin  
      put.connect( imp ) ; 
    end
    else
    begin
      `uvm_error("CONFIG_DB_GET","GET Failed")  // Fails but why ??
    end
  endfunction
endclass

I hope this will help.

In reply to cuonghle:

Thanks , it works .