Delegating implementation to extended Component

In the following code ::


`include "uvm_pkg.sv"
`include "uvm_macros.svh" 

import uvm_pkg::*;
`define COMP_NEW function new ( string name , uvm_component parent ) ; \
                  super.new(name,parent);\
                 endfunction

class trans ; 
   rand bit [2:0] addr ;
endclass

class Producer extends uvm_component ;

 `uvm_component_utils(Producer)
 
 uvm_blocking_put_port #(trans) put_port ;

 `COMP_NEW

  function void build_phase ( uvm_phase phase ) ;
     put_port = new("put_port",this);
  endfunction
  
  task main_phase ( uvm_phase phase ) ;
    trans txn ;
     
	 phase.raise_objection(this);

	 txn = new();
   
       txn.randomize();
       put_port.put(txn);

	 phase.drop_objection(this);

  endtask

endclass

typedef class Consumer ;

class Consumer_ext extends Consumer ;

 `uvm_component_utils(Consumer_ext) 

 `COMP_NEW

  function void build_phase ( uvm_phase phase ) ;    
  endfunction
  
  task put ( trans t ) ; 
   $display(" %0s Received %0p",get_name(),t);
  endtask

endclass

class Consumer extends uvm_component ;

 `uvm_component_utils(Consumer)

  uvm_blocking_put_imp #(trans,Consumer )  put_imp ;
  Consumer_ext                             ext ; 
 `COMP_NEW

  function void build_phase ( uvm_phase phase ) ;
   put_imp = new("put_imp",ext); // Delegates put() implementatn to extended component [Q]Should be 2nd why ?  
   ext     = new("ext",this);
  endfunction
  
  virtual task put ( trans t ); 
    $display(" Received %0p",t);
  endtask  

endclass
class env extends uvm_component ;

 `uvm_component_utils(env) 
 `COMP_NEW
  
  Consumer  cons ;
  Producer  prod ;

  function void build_phase ( uvm_phase phase ) ;
     cons   = new("cons",this);
     prod   = new("prod",this);
  endfunction

 function void connect_phase ( uvm_phase phase ) ;
      prod.put_port.connect(cons.put_imp) ;
 endfunction

endclass 



[Q] The above code doesn’t work ( ext needs to be instantiated before put_imp ) .
I was under the impression that since at run-time the methods would be called , by which all components would be created so the order shouldn’t be important .

**Why is it that the order actually matters ?**

In reply to ABD_91:

put_imp = new(“put_imp”,ext); // Delegates put() implementatn to extended component [Q]Should be 2nd why ?
ext = new(“ext”,this);

Here when the put_imp object is created, the ext is pointing to a null (as ext is not actually created), so in put_imp object the Consumer class object points to null.
As you have created the ext is created after the put_imp, the put_imp object will not get updated.
if you reverse this order ,then ext is actually pointing to the actual Consumer_ext object.

Try this example: create_order - EDA Playground
you will see the change.

In reply to Venkateshwara Rao:

Thanks Venkatesh . I didn’t notice that it was actually run-time error than compile time error .

The reason for run-time error being the same as you mentioned .

In reply to ABD_91:

This seems like a very unusual use of inheritance. Normally when you extend a class, you construct it instead of its base through the use of a factory override. You don’t construct both objects and instantiate the extended inside the base. This defaeats the purpose of extension since the base has to be aware of the extended class.

In reply to dave_59:

Yes , its an impractical code I would agree ( wouldn’t use it in actual projects ) .
Was simply trying apart from ‘this’ what else could be passed as 2nd argument while instantiating implementation port-types .