The White Rabbit Link to heading
The factory is a way to dynamically construct objects(see wiki). For UVM, Factory can be used to override the objected created which allow injection
of new functionality into already existing sequences.
It requires registering the class first then using create
to get an object
- registration
class env extends uvm_env;
`uvm_component_utils(uvm_env)
- Creation
env = uvm_env::type_id::create("env",this);
Registration Link to heading
uvm_component_utils
is defined in src/macros/uvm_object_defines.svh
`define uvm_component_utils(T) \
`m_uvm_component_registry_internal(T,T) \
`m_uvm_get_type_name_func(T) \
let’s start with m_uvm_get_type_name_func
which simply defines the type_name
by stringify the T
`define m_uvm_get_type_name_func(T) \
const static string type_name = `"T`"; \
virtual function string get_type_name (); \
return type_name; \
endfunction
Then m_uvm_component_registry_internal
just adds type_id
type which is going to be called to create the object. (the protagonist)
`define m_uvm_component_registry_internal(T,S) \
typedef uvm_component_registry #(T,`"S`") type_id; \
static function type_id get_type(); \
return type_id::get(); \
endfunction \
virtual function uvm_object_wrapper get_object_type(); \
return type_id::get(); \
endfunction
Initialization Link to heading
It’s clear that the heavy stuff is done by uvm_component_registry::create
but first looking at get
in src/base/uvm_registry.svh
, get
returns me
if initialized. but me
is static and already initialized before any create is called.
local static this_type me = get();
// Function: get
//
// Returns the singleton instance of this type. Type-based factory operation
// depends on there being a single proxy instance for each registered type.
static function this_type get();
if (me == null) begin
uvm_factory f = uvm_factory::get();
me = new;
f.register(me);
end
return me;
endfunction
in get
above, the factory singleton is created as well(if not already). so in src/base/uvm_factory.svh
, get
is defined.
function uvm_factory uvm_factory::get();
if (m_inst == null) begin
m_inst = new();
end
return m_inst;
endfunction
Creation Link to heading
To create the component, in build phase the type_id::create
is called
env = uvm_env::type_id::create("env",this);
create
in src/base/uvm_registry.svh
, calls create_component_by_type
static function T create (string name="", uvm_component parent=null,
string contxt="");
uvm_object obj;
uvm_factory f = uvm_factory::get();
...
...
obj = f.create_object_by_type(get(),contxt,name);
...
...
endfunction
create_component_by_type
first calls find_override_by_type
which checks for override. if there is no override, it returns requested_type
as is.
function uvm_object uvm_factory::create_object_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
...
...
requested_type = find_override_by_type(requested_type, full_inst_path);
return requested_type.create_object(name);
endfunction
Finally create_component_by_type
calls create_component
return requested_type.create_component(name, parent);
create_component
is picked up from requested_type which is uvm_component_registry
and it calls new
to create the object
virtual function uvm_component create_component (string name,
uvm_component parent);
T obj;
obj = new(name, parent);
return obj;
endfunction