I am trying to understand output of following code ::
`include "uvm_macros.svh"
`include "uvm_pkg.sv"
import uvm_pkg::* ;
class user_seq_item extends uvm_sequence_item ;
localparam string TYPE_NAME = "user_seq_item" ;
`uvm_object_utils(user_seq_item)
// Std 3 line Constructor
endclass
class my_driver #( type T = user_seq_item ) extends uvm_driver #( T ) ;
typedef uvm_component_registry #( my_driver#( T ) , $sformatf("my_driver#(%0s)" , T::TYPE_NAME ) ) type_id ;
// Std 3 line Constructor
task main_phase( uvm_phase phase ) ;
`uvm_info(get_name() , $sformatf(" Within driver of Tname : %0s " , type_id::type_name ) , UVM_NONE ) // 'Tname' of uvm_component_registry !!
`uvm_info(get_name() , $sformatf(" Received request is of type_name : %0s " , req.get_type_name() ) , UVM_NONE )
endtask
endclass
class ext_driver #( type T = user_seq_item ) extends my_driver #( T ) ;
typedef uvm_component_registry #( ext_driver#( T ) , $sformatf("ext_driver#(%0s)" , T::TYPE_NAME ) ) type_id ;
// Std 3 line Constructor
// main_phase() Inherited !!
endclass
class env extends uvm_env ;
`uvm_component_utils( env )
// Std 3 line Constructor
my_driver #( user_seq_item ) drvr_h ;
function void build_phase ( uvm_phase phase ) ;
drvr_h = my_driver #( user_seq_item ) :: type_id :: create( "drvr_h" , this ) ;
endfunction
endclass
class my_test extends uvm_test ;
`uvm_component_utils( my_test )
// Std 3 line Constructor
env env_h ;
function void build_phase ( uvm_phase phase ) ;
my_driver #( user_seq_item ) ::type_id :: set_type_override( ext_driver #( user_seq_item ) :: get_type() ) ;
env_h = env :: type_id :: create( "env_h" , this ) ;
endfunction
endclass
module TOP ;
initial
run_test("my_test") ;
endmodule
The Output I observe ::
UVM_INFO @ 0: reporter [RNTST] Running test my_test…
UVM_ERROR @ 0: reporter [NOTYPID] get_type not implemented in derived class.
UVM_FATAL @ 0: reporter [NULLWR] Attempting to register a null object with the factory
The UVM_ERROR occurs since implementation of static function get_type() isn’t provided .
Hence get_type() function in uvm_object gets called which throws the error .
[Q1] Why do I Observe the Fatal Error ?
[Q2] I simply need to run the main_phase() in driver .
So is it alright if I raise and drop objection in main_phase() of driver ?
[Q3] Any suggestions for an alternative way to provide the actual to ‘Tname’
during specialization of uvm_component_registry ?
In reply to MICRO_91:
(A1): Because your driver is parameterized twice you need an individual get_type function, returning the type of the 1st parameter.
(A2) Instead of running main_phase you should run run_phase. You can implement there the objection mechanism. But it is not he best place. The recommeded implementation is in the test.
(A3) why do you need a 2nd parameter in your driver implementation. What you are doing with it?
See the solution below:
`include "uvm_macros.svh"
`include "uvm_pkg.sv"
import uvm_pkg::* ;
class user_seq_item extends uvm_sequence_item ;
localparam string TYPE_NAME = "user_seq_item" ;
`uvm_object_utils(user_seq_item)
// Std 3 line Constructor
function new(string name = "user_seq_item");
super.new(name);
endfunction : new
endclass
class my_driver #( type T = user_seq_item ) extends uvm_driver #( T ) ;
typedef uvm_component_registry #( my_driver#( T ) , $sformatf("my_driver#(%0s)" , T::TYPE_NAME ) ) type_id ;
// Std 3 line Constructor
function new(string name = "my_driver", uvm_component parent = null);
super.new(name, parent);
endfunction : new
task run_phase( uvm_phase phase ) ;
`uvm_info(get_name() , $sformatf(" Within driver of Tname : %0s " , type_id::type_name ) , UVM_NONE ) // 'Tname' of uvm_component_registry !!
`uvm_info(get_name() , $sformatf(" Received request is of type_name : %0p " , req.get_type() ) , UVM_NONE )
endtask
endclass
class ext_driver #( type T = user_seq_item ) extends my_driver #( T ) ;
typedef uvm_component_registry #( ext_driver#( T ) , $sformatf("ext_driver#(%0s)" , T::TYPE_NAME ) ) type_id ;
// Std 3 line Constructor
// main_phase() Inherited !!
function new(string name = "ext_driver", uvm_component parent = null);
super.new(name, parent);
endfunction : new
static function type_id get_type();
return type_id::get();
endfunction
endclass
class env extends uvm_env ;
`uvm_component_utils( env )
function new(string name = "env", uvm_component parent = null);
super.new(name, parent);
endfunction : new
my_driver #( user_seq_item ) drvr_h ;
function void build_phase ( uvm_phase phase ) ;
drvr_h = my_driver #( user_seq_item ) :: type_id :: create( "drvr_h" , this ) ;
endfunction
endclass
class my_test extends uvm_test ;
`uvm_component_utils( my_test )
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction : new
env env_h ;
function void build_phase ( uvm_phase phase ) ;
my_driver #( user_seq_item ) ::type_id :: set_type_override( ext_driver #( user_seq_item ) :: get_type() ) ;
env_h = env :: type_id :: create( "env_h" , this ) ;
endfunction
endclass
module TOP ;
initial
run_test("my_test") ;
endmodule
In reply to chr_sue:
I finally got the exact reason ::
[1] The Fatal error is from factory::register() function .
function void uvm_factory::register (uvm_object_wrapper obj);
if (obj == null) begin
uvm_report_fatal ("NULLWR", "Attempting to register a null object with the factory", UVM_NONE);
end
.......................
endfunction
[2] Since get_type() isn’t implemented in derived class , get_type() in class
uvm_object gets called which throws UVM_ERROR and returns null .
static function uvm_object_wrapper uvm_object::get_type();
uvm_report_error("NOTYPID", "get_type not implemented in derived class.", UVM_NONE);
return null;
endfunction
[3] Via source code ::
function void uvm_factory::set_type_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
bit replace=1);
// original type points to singleton instance
// ( local static this_type me within uvm_component_registry ) via
// my_driver #( user_seq_item )
// override_type points to null via uvm_object::get_type()
.................
// register the types if not already done so, for the benefit of string-based lookup
// Condition is False since my_driver #( user_seq_item )
// already registered at TIME:0 in Type Based Factory
if (!m_types.exists(original_type))
register(original_type);
// Condition is True since 'null' isn't registered in Type Base Factory
if (!m_types.exists(override_type))
register(override_type); // Cause of error
..............
Regarding [A3] , I observe Issues with Simulators during explicit specialization of
uvm_component_registry .
Eg ::
localparam string TYPE_NAME = $sformatf("my_driver#(%0s)" , T::TYPE_NAME ) ; // Issue !!
typedef uvm_component_registry #( my_driver#( T ) , TYPE_NAME ) type_id ;
This doesn’t work across some Simulators ( Possibly Simulator Issue )
The code in original question works across all Simulators I tried .
Hence I was wondering if any alternate approach is possible for specialization of
uvm_component_registry .