//
//------------------------------------------------------------------------------
// Copyright 2007-2011 Mentor Graphics Corporation
// Copyright 2007-2011 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// Copyright 2013 NVIDIA Corporation
// Copyright 2013 Verilab, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//------------------------------------------------------------------------------
typedef class [docs]uvm_object;
typedef class [docs]uvm_component;
typedef class [docs]uvm_object_wrapper;
typedef class [docs]uvm_factory_override;
//Instance overrides by requested type lookup
class [docs]uvm_factory_queue_class;
uvm_factory_override queue[$];
endclass
//------------------------------------------------------------------------------
// Title: UVM Factory
//
// This page covers the classes that define the UVM factory facility.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// CLASS: uvm_factory
//
//------------------------------------------------------------------------------
//
// As the name implies, uvm_factory is used to manufacture (create) UVM objects
// and components. Object and component types are registered
// with the factory using lightweight proxies to the actual objects and
// components being created. The <uvm_object_registry #(T,Tname)> and
// <uvm_component_registry #(T,Tname)> class are used to proxy <uvm_objects>
// and <uvm_components>.
//
// The factory provides both name-based and type-based interfaces.
//
// type-based - The type-based interface is far less prone to errors in usage.
// When errors do occur, they are caught at compile-time.
//
// name-based - The name-based interface is dominated
// by string arguments that can be misspelled and provided in the wrong order.
// Errors in name-based requests might only be caught at the time of the call,
// if at all. Further, the name-based interface is not portable across
// simulators when used with parameterized classes.
//
//
// The ~uvm_factory~ is an abstract class which declares many of its methods
// as ~pure virtual~. The UVM uses the <uvm_default_factory> class
// as its default factory implementation.
//
// See <uvm_default_factory::Usage> section for details on configuring and using the factory.
//
virtual class [docs]uvm_factory;
// Group: Retrieving the factory
// Function: get
// Static accessor for <uvm_factory>
//
// The static accessor is provided as a convenience wrapper
// around retrieving the factory via the <uvm_coreservice_t::get_factory>
// method.
//
// | // Using the uvm_coreservice_t:
// | uvm_coreservice_t cs;
// | uvm_factory f;
// | cs = uvm_coreservice_t::get();
// | f = cs.get_factory();
//
// | // Not using the uvm_coreservice_t:
// | uvm_factory f;
// | f = uvm_factory::get();
//
static function uvm_factory [docs]get();
uvm_coreservice_t s;
s = uvm_coreservice_t::get();
return s.get_factory();
endfunction
// Group: Registering Types
// Function: register
//
// Registers the given proxy object, ~obj~, with the factory. The proxy object
// is a lightweight substitute for the component or object it represents. When
// the factory needs to create an object of a given type, it calls the proxy's
// create_object or create_component method to do so.
//
// When doing name-based operations, the factory calls the proxy's
// ~get_type_name~ method to match against the ~requested_type_name~ argument in
// subsequent calls to <create_component_by_name> and <create_object_by_name>.
// If the proxy object's ~get_type_name~ method returns the empty string,
// name-based lookup is effectively disabled.
pure virtual function void [docs]register (uvm_object_wrapper obj);
// Group: Type & Instance Overrides
// Function: set_inst_override_by_type
pure virtual function
void [docs]set_inst_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
string full_inst_path);
// Function: set_inst_override_by_name
//
// Configures the factory to create an object of the override's type whenever
// a request is made to create an object of the original type using a context
// that matches ~full_inst_path~. The original type is typically a super class
// of the override type.
//
// When overriding by type, the ~original_type~ and ~override_type~ are
// handles to the types' proxy objects. Preregistration is not required.
//
// When overriding by name, the ~original_type_name~ typically refers to a
// preregistered type in the factory. It may, however, be any arbitrary
// string. Future calls to any of the ~create_*~ methods with the same string
// and matching instance path will produce the type represented by
// ~override_type_name~, which must be preregistered with the factory.
//
// The ~full_inst_path~ is matched against the concatenation of
// {~parent_inst_path~, ".", ~name~} provided in future create requests. The
// ~full_inst_path~ may include wildcards (* and ?) such that a single
// instance override can be applied in multiple contexts. A ~full_inst_path~
// of "*" is effectively a type override, as it will match all contexts.
//
// When the factory processes instance overrides, the instance queue is
// processed in order of override registrations, and the first override
// match prevails. Thus, more specific overrides should be registered
// first, followed by more general overrides.
pure virtual function
void [docs]set_inst_override_by_name (string original_type_name,
string override_type_name,
string full_inst_path);
// Function: set_type_override_by_type
pure virtual function
void [docs]set_type_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
bit replace=1);
// Function: set_type_override_by_name
//
// Configures the factory to create an object of the override's type whenever
// a request is made to create an object of the original type, provided no
// instance override applies. The original type is typically a super class of
// the override type.
//
// When overriding by type, the ~original_type~ and ~override_type~ are
// handles to the types' proxy objects. Preregistration is not required.
//
// When overriding by name, the ~original_type_name~ typically refers to a
// preregistered type in the factory. It may, however, be any arbitrary
// string. Future calls to any of the ~create_*~ methods with the same string
// and matching instance path will produce the type represented by
// ~override_type_name~, which must be preregistered with the factory.
//
// When ~replace~ is 1, a previous override on ~original_type_name~ is
// replaced, otherwise a previous override, if any, remains intact.
pure virtual function
void [docs]set_type_override_by_name (string original_type_name,
string override_type_name,
bit replace=1);
// Group: Creation
// Function: create_object_by_type
pure virtual function
uvm_object [docs]create_object_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
// Function: create_component_by_type
pure virtual function
uvm_component [docs]create_component_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name,
uvm_component parent);
// Function: create_object_by_name
pure virtual function
uvm_object [docs]create_object_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
// Function: create_component_by_name
//
// Creates and returns a component or object of the requested type, which may
// be specified by type or by name. A requested component must be derived
// from the <uvm_component> base class, and a requested object must be derived
// from the <uvm_object> base class.
//
// When requesting by type, the ~requested_type~ is a handle to the type's
// proxy object. Preregistration is not required.
//
// When requesting by name, the ~request_type_name~ is a string representing
// the requested type, which must have been registered with the factory with
// that name prior to the request. If the factory does not recognize the
// ~requested_type_name~, an error is produced and a ~null~ handle returned.
//
// If the optional ~parent_inst_path~ is provided, then the concatenation,
// {~parent_inst_path~, ".",~name~}, forms an instance path (context) that
// is used to search for an instance override. The ~parent_inst_path~ is
// typically obtained by calling the <uvm_component::get_full_name> on the
// parent.
//
// If no instance override is found, the factory then searches for a type
// override.
//
// Once the final override is found, an instance of that component or object
// is returned in place of the requested type. New components will have the
// given ~name~ and ~parent~. New objects will have the given ~name~, if
// provided.
//
// Override searches are recursively applied, with instance overrides taking
// precedence over type overrides. If ~foo~ overrides ~bar~, and ~xyz~
// overrides ~foo~, then a request for ~bar~ will produce ~xyz~. Recursive
// loops will result in an error, in which case the type returned will be
// that which formed the loop. Using the previous example, if ~bar~
// overrides ~xyz~, then ~bar~ is returned after the error is issued.
pure virtual function
uvm_component [docs]create_component_by_name (string requested_type_name,
string parent_inst_path="",
string name,
uvm_component parent);
// Group: Debug
// Function: debug_create_by_type
pure virtual function
void [docs]debug_create_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
// Function: debug_create_by_name
//
// These methods perform the same search algorithm as the ~create_*~ methods,
// but they do not create new objects. Instead, they provide detailed
// information about what type of object it would return, listing each
// override that was applied to arrive at the result. Interpretation of the
// arguments are exactly as with the ~create_*~ methods.
pure virtual function
void [docs]debug_create_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
// Function: find_override_by_type
pure virtual function
uvm_object_wrapper [docs]find_override_by_type (uvm_object_wrapper requested_type,
string full_inst_path);
// Function: find_override_by_name
//
// These methods return the proxy to the object that would be created given
// the arguments. The ~full_inst_path~ is typically derived from the parent's
// instance path and the leaf name of the object to be created, i.e.
// { parent.get_full_name(), ".", name }.
pure virtual function
uvm_object_wrapper [docs]find_override_by_name (string requested_type_name,
string full_inst_path);
// Function: find_wrapper_by_name
//
// This method returns the <uvm_object_wrapper> associated with a given
// ~type_name~.
pure virtual
function uvm_object_wrapper [docs]find_wrapper_by_name (string type_name);
// Function: print
//
// Prints the state of the uvm_factory, including registered types, instance
// overrides, and type overrides.
//
// When ~all_types~ is 0, only type and instance overrides are displayed. When
// ~all_types~ is 1 (default), all registered user-defined types are printed as
// well, provided they have names associated with them. When ~all_types~ is 2,
// the UVM types (prefixed with uvm_) are included in the list of registered
// types.
pure virtual function void [docs]print (int all_types=1);
endclass
//------------------------------------------------------------------------------
//
// CLASS: uvm_default_factory
//
//------------------------------------------------------------------------------
//
// Default implementation of the UVM factory.
class [docs]uvm_default_factory extends uvm_factory;
// Group: Registering Types
// Function: register
//
// Registers the given proxy object, ~obj~, with the factory.
extern virtual function void [docs]register (uvm_object_wrapper obj);
// Group: Type & Instance Overrides
// Function: set_inst_override_by_type
extern virtual function
void [docs]set_inst_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
string full_inst_path);
// Function: set_inst_override_by_name
//
// Configures the factory to create an object of the override's type whenever
// a request is made to create an object of the original type using a context
// that matches ~full_inst_path~.
extern virtual function
void [docs]set_inst_override_by_name (string original_type_name,
string override_type_name,
string full_inst_path);
// Function: set_type_override_by_type
extern virtual function
void [docs]set_type_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
bit replace=1);
// Function: set_type_override_by_name
//
// Configures the factory to create an object of the override's type whenever
// a request is made to create an object of the original type, provided no
// instance override applies.
extern virtual function
void [docs]set_type_override_by_name (string original_type_name,
string override_type_name,
bit replace=1);
// Group: Creation
// Function: create_object_by_type
extern virtual function
uvm_object [docs]create_object_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
// Function: create_component_by_type
extern virtual function
uvm_component [docs]create_component_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name,
uvm_component parent);
// Function: create_object_by_name
extern virtual function
uvm_object [docs]create_object_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
// Function: create_component_by_name
//
// Creates and returns a component or object of the requested type, which may
// be specified by type or by name.
extern virtual function
uvm_component [docs]create_component_by_name (string requested_type_name,
string parent_inst_path="",
string name,
uvm_component parent);
// Group: Debug
// Function: debug_create_by_type
extern virtual function
void [docs]debug_create_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
// Function: debug_create_by_name
//
// These methods perform the same search algorithm as the ~create_*~ methods,
// but they do not create new objects.
extern virtual function
void [docs]debug_create_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
// Function: find_override_by_type
extern virtual function
uvm_object_wrapper [docs]find_override_by_type (uvm_object_wrapper requested_type,
string full_inst_path);
// Function: find_override_by_name
//
// These methods return the proxy to the object that would be created given
// the arguments.
extern virtual function
uvm_object_wrapper [docs]find_override_by_name (string requested_type_name,
string full_inst_path);
extern virtual
function uvm_object_wrapper [docs]find_wrapper_by_name (string type_name);
// Function: print
//
// Prints the state of the uvm_factory, including registered types, instance
// overrides, and type overrides.
//
extern virtual function void [docs]print (int all_types=1);
//----------------------------------------------------------------------------
// PRIVATE MEMBERS
extern protected
function void m_debug_create (string requested_type_name,
uvm_object_wrapper requested_type,
string parent_inst_path,
string name);
extern protected
function void m_debug_display(string requested_type_name,
uvm_object_wrapper result,
string full_inst_path);
protected bit m_types[uvm_object_wrapper];
protected bit m_lookup_strs[string];
protected uvm_object_wrapper m_type_names[string];
protected uvm_factory_override m_type_overrides[$];
protected uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper];
protected uvm_factory_queue_class m_inst_override_name_queues[string];
protected uvm_factory_override m_wildcard_inst_overrides[$];
local uvm_factory_override m_override_info[$];
local static bit m_debug_pass;
extern function bit m_has_wildcard(string nm);
extern function bit [docs]check_inst_override_exists
(uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
string full_inst_path);
endclass
//------------------------------------------------------------------------------
//
// Group: Usage
//
// Using the factory involves three basic operations
//
// 1 - Registering objects and components types with the factory
// 2 - Designing components to use the factory to create objects or components
// 3 - Configuring the factory with type and instance overrides, both within and
// outside components
//
// We'll briefly cover each of these steps here. More reference information can
// be found at <Utility Macros>, <uvm_component_registry #(T,Tname)>,
// <uvm_object_registry #(T,Tname)>, <uvm_component>.
//
// 1 -- Registering objects and component types with the factory:
//
// When defining <uvm_object> and <uvm_component>-based classes, simply invoke
// the appropriate macro. Use of macros are required to ensure portability
// across different vendors' simulators.
//
// Objects that are not parameterized are declared as
//
//| class packet extends uvm_object;
//| `uvm_object_utils(packet)
//| endclass
//|
//| class packetD extends packet;
//| `uvm_object_utils(packetD)
//| endclass
//
// Objects that are parameterized are declared as
//
//| class packet #(type T=int, int WIDTH=32) extends uvm_object;
//| `uvm_object_param_utils(packet #(T,WIDTH))
//| endclass
//
// Components that are not parameterized are declared as
//
//| class comp extends uvm_component;
//| `uvm_component_utils(comp)
//| endclass
//
// Components that are parameterized are declared as
//
//| class comp #(type T=int, int WIDTH=32) extends uvm_component;
//| `uvm_component_param_utils(comp #(T,WIDTH))
//| endclass
//
// The `uvm_*_utils macros for simple, non-parameterized classes will register
// the type with the factory and define the get_type, get_type_name, and create
// virtual methods inherited from <uvm_object>. It will also define a static
// type_name variable in the class, which will allow you to determine the type
// without having to allocate an instance.
//
// The `uvm_*_param_utils macros for parameterized classes differ from
// `uvm_*_utils classes in the following ways:
//
// - The ~get_type_name~ method and static type_name variable are not defined. You
// will need to implement these manually.
//
// - A type name is not associated with the type when registering with the
// factory, so the factory's *_by_name operations will not work with
// parameterized classes.
//
// - The factory's <print>, <debug_create_by_type>, and <debug_create_by_name>
// methods, which depend on type names to convey information, will list
// parameterized types as '<unknown>'.
//
// It is worth noting that environments that exclusively use the type-based
// factory methods (*_by_type) do not require type registration. The factory's
// type-based methods will register the types involved "on the fly," when first
// used. However, registering with the `uvm_*_utils macros enables name-based
// factory usage and implements some useful utility functions.
//
//
// 2 -- Designing components that defer creation to the factory:
//
// Having registered your objects and components with the factory, you can now
// make requests for new objects and components via the factory. Using the factory
// instead of allocating them directly (via new) allows different objects to be
// substituted for the original without modifying the requesting class. The
// following code defines a driver class that is parameterized.
//
//| class driverB #(type T=uvm_object) extends uvm_driver;
//|
//| // parameterized classes must use the _param_utils version
//| `uvm_component_param_utils(driverB #(T))
//|
//| // our packet type; this can be overridden via the factory
//| T pkt;
//|
//| // standard component constructor
//| function new(string name, uvm_component parent=null);
//| super.new(name,parent);
//| endfunction
//|
//| // get_type_name not implemented by macro for parameterized classes
//| const static string type_name = {"driverB #(",T::type_name,")"};
//| virtual function string get_type_name();
//| return type_name;
//| endfunction
//|
//| // using the factory allows pkt overrides from outside the class
//| virtual function void build_phase(uvm_phase phase);
//| pkt = packet::type_id::create("pkt",this);
//| endfunction
//|
//| // print the packet so we can confirm its type when printing
//| virtual function void do_print(uvm_printer printer);
//| printer.print_object("pkt",pkt);
//| endfunction
//|
//| endclass
//
// For purposes of illustrating type and instance overrides, we define two
// subtypes of the ~driverB~ class. The subtypes are also parameterized, so
// we must again provide an implementation for <uvm_object::get_type_name>,
// which we recommend writing in terms of a static string constant.
//
//| class driverD1 #(type T=uvm_object) extends driverB #(T);
//|
//| `uvm_component_param_utils(driverD1 #(T))
//|
//| function new(string name, uvm_component parent=null);
//| super.new(name,parent);
//| endfunction
//|
//| const static string type_name = {"driverD1 #(",T::type_name,")"};
//| virtual function string get_type_name();
//| ...return type_name;
//| endfunction
//|
//| endclass
//|
//| class driverD2 #(type T=uvm_object) extends driverB #(T);
//|
//| `uvm_component_param_utils(driverD2 #(T))
//|
//| function new(string name, uvm_component parent=null);
//| super.new(name,parent);
//| endfunction
//|
//| const static string type_name = {"driverD2 #(",T::type_name,")"};
//| virtual function string get_type_name();
//| return type_name;
//| endfunction
//|
//| endclass
//|
//| // typedef some specializations for convenience
//| typedef driverB #(packet) B_driver; // the base driver
//| typedef driverD1 #(packet) D1_driver; // a derived driver
//| typedef driverD2 #(packet) D2_driver; // another derived driver
//
// Next, we'll define a agent component, which requires a utils macro for
// non-parameterized types. Before creating the drivers using the factory, we
// override ~driver0~'s packet type to be ~packetD~.
//
//| class agent extends uvm_agent;
//|
//| `uvm_component_utils(agent)
//| ...
//| B_driver driver0;
//| B_driver driver1;
//|
//| function new(string name, uvm_component parent=null);
//| super.new(name,parent);
//| endfunction
//|
//| virtual function void build_phase(uvm_phase phase);
//|
//| // override the packet type for driver0 and below
//| packet::type_id::set_inst_override(packetD::get_type(),"driver0.*");
//|
//| // create using the factory; actual driver types may be different
//| driver0 = B_driver::type_id::create("driver0",this);
//| driver1 = B_driver::type_id::create("driver1",this);
//|
//| endfunction
//|
//| endclass
//
// Finally we define an environment class, also not parameterized. Its ~build_phase~
// method shows three methods for setting an instance override on a grandchild
// component with relative path name, ~agent1.driver1~, all equivalent.
//
//| class env extends uvm_env;
//|
//| `uvm_component_utils(env)
//|
//| agent agent0;
//| agent agent1;
//|
//| function new(string name, uvm_component parent=null);
//| super.new(name,parent);
//| endfunction
//|
//| virtual function void build_phase(uvm_phase phase);
//|
//| // three methods to set an instance override for agent1.driver1
//| // - via component convenience method...
//| set_inst_override_by_type("agent1.driver1",
//| B_driver::get_type(),
//| D2_driver::get_type());
//|
//| // - via the component's proxy (same approach as create)...
//| B_driver::type_id::set_inst_override(D2_driver::get_type(),
//| "agent1.driver1",this);
//|
//| // - via a direct call to a factory method...
//| factory.set_inst_override_by_type(B_driver::get_type(),
//| D2_driver::get_type(),
//| {get_full_name(),".agent1.driver1"});
//|
//| // create agents using the factory; actual agent types may be different
//| agent0 = agent::type_id::create("agent0",this);
//| agent1 = agent::type_id::create("agent1",this);
//|
//| endfunction
//|
//| // at end_of_elaboration, print topology and factory state to verify
//| virtual function void end_of_elaboration_phase(uvm_phase phase);
//| uvm_top.print_topology();
//| endfunction
//|
//| virtual task run_phase(uvm_phase phase);
//| #100 global_stop_request();
//| endfunction
//|
//| endclass
//
//
// 3 -- Configuring the factory with type and instance overrides:
//
// In the previous step, we demonstrated setting instance overrides and creating
// components using the factory within component classes. Here, we will
// demonstrate setting overrides from outside components, as when initializing
// the environment prior to running the test.
//
//| module top;
//|
//| env env0;
//|
//| initial begin
//|
//| // Being registered first, the following overrides take precedence
//| // over any overrides made within env0's construction & build.
//|
//| // Replace all base drivers with derived drivers...
//| B_driver::type_id::set_type_override(D_driver::get_type());
//|
//| // ...except for agent0.driver0, whose type remains a base driver.
//| // (Both methods below have the equivalent result.)
//|
//| // - via the component's proxy (preferred)
//| B_driver::type_id::set_inst_override(B_driver::get_type(),
//| "env0.agent0.driver0");
//|
//| // - via a direct call to a factory method
//| factory.set_inst_override_by_type(B_driver::get_type(),
//| B_driver::get_type(),
//| {get_full_name(),"env0.agent0.driver0"});
//|
//| // now, create the environment; our factory configuration will
//| // govern what topology gets created
//| env0 = new("env0");
//|
//| // run the test (will execute build phase)
//| run_test();
//|
//| end
//|
//| endmodule
//
// When the above example is run, the resulting topology (displayed via a call to
// <uvm_root::print_topology> in env's <uvm_component::end_of_elaboration_phase> method)
// is similar to the following:
//
//| # UVM_INFO @ 0 [RNTST] Running test ...
//| # UVM_INFO @ 0 [UVMTOP] UVM testbench topology:
//| # ----------------------------------------------------------------------
//| # Name Type Size Value
//| # ----------------------------------------------------------------------
//| # env0 env - env0@2
//| # agent0 agent - agent0@4
//| # driver0 driverB #(packet) - driver0@8
//| # pkt packet - pkt@21
//| # driver1 driverD #(packet) - driver1@14
//| # pkt packet - pkt@23
//| # agent1 agent - agent1@6
//| # driver0 driverD #(packet) - driver0@24
//| # pkt packet - pkt@37
//| # driver1 driverD2 #(packet) - driver1@30
//| # pkt packet - pkt@39
//| # ----------------------------------------------------------------------
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// CLASS: uvm_object_wrapper
//
// The uvm_object_wrapper provides an abstract interface for creating object and
// component proxies. Instances of these lightweight proxies, representing every
// <uvm_object>-based and <uvm_component>-based object available in the test
// environment, are registered with the <uvm_factory>. When the factory is
// called upon to create an object or component, it finds and delegates the
// request to the appropriate proxy.
//
//------------------------------------------------------------------------------
virtual class [docs]uvm_object_wrapper;
// Function: create_object
//
// Creates a new object with the optional ~name~.
// An object proxy (e.g., <uvm_object_registry #(T,Tname)>) implements this
// method to create an object of a specific type, T.
virtual function uvm_object [docs]create_object (string name="");
return null;
endfunction
// Function: create_component
//
// Creates a new component, passing to its constructor the given ~name~ and
// ~parent~. A component proxy (e.g. <uvm_component_registry #(T,Tname)>)
// implements this method to create a component of a specific type, T.
virtual function uvm_component [docs]create_component (string name,
uvm_component parent);
return null;
endfunction
// Function: get_type_name
//
// Derived classes implement this method to return the type name of the object
// created by <create_component> or <create_object>. The factory uses this
// name when matching against the requested type in name-based lookups.
pure virtual function string [docs]get_type_name();
endclass
//------------------------------------------------------------------------------
//
// CLASS- uvm_factory_override
//
// Internal class.
//------------------------------------------------------------------------------
class [docs]uvm_factory_override;
string full_inst_path;
string orig_type_name;
string ovrd_type_name;
bit selected;
int unsigned used;
uvm_object_wrapper orig_type;
uvm_object_wrapper ovrd_type;
function [docs]new (string full_inst_path="",
string orig_type_name="",
uvm_object_wrapper orig_type=null,
uvm_object_wrapper ovrd_type);
if (ovrd_type == null) begin
uvm_report_fatal ("NULLWR", "Attempting to register a null override object with the factory", UVM_NONE);
end
this.full_inst_path= full_inst_path;
this.orig_type_name = orig_type == null ? orig_type_name : orig_type.get_type_name();
this.orig_type = orig_type;
this.ovrd_type_name = ovrd_type.get_type_name();
this.ovrd_type = ovrd_type;
endfunction
endclass
//-----------------------------------------------------------------------------
// IMPLEMENTATION
//-----------------------------------------------------------------------------
// register
// --------
function void uvm_default_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
if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>") begin
if (m_type_names.exists(obj.get_type_name()))
uvm_report_warning("TPRGED", {"Type name '",obj.get_type_name(),
"' already registered with factory. No string-based lookup ",
"support for multiple types with the same type name."}, UVM_NONE);
else
m_type_names[obj.get_type_name()] = obj;
end
if (m_types.exists(obj)) begin
if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>")
uvm_report_warning("TPRGED", {"Object type '",obj.get_type_name(),
"' already registered with factory. "}, UVM_NONE);
end
else begin
m_types[obj] = 1;
// If a named override happens before the type is registered, need to copy
// the override queue.
// Note:Registration occurs via static initialization, which occurs ahead of
// procedural (e.g. initial) blocks. There should not be any preexisting overrides.
if(m_inst_override_name_queues.exists(obj.get_type_name())) begin
m_inst_override_queues[obj] = new;
m_inst_override_queues[obj].queue = m_inst_override_name_queues[obj.get_type_name()].queue;
m_inst_override_name_queues.delete(obj.get_type_name());
end
if(m_wildcard_inst_overrides.size()) begin
if(! m_inst_override_queues.exists(obj))
m_inst_override_queues[obj] = new;
foreach (m_wildcard_inst_overrides[i]) begin
if(uvm_is_match( m_wildcard_inst_overrides[i].orig_type_name, obj.get_type_name()))
m_inst_override_queues[obj].queue.push_back(m_wildcard_inst_overrides[i]);
end
end
end
endfunction
// set_type_override_by_type
// -------------------------
function void uvm_default_factory::set_type_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
bit replace=1);
bit replaced;
// check that old and new are not the same
if (original_type == override_type) begin
if (original_type.get_type_name() == "" || original_type.get_type_name() == "<unknown>")
uvm_report_warning("TYPDUP", {"Original and override type ",
"arguments are identical"}, UVM_NONE);
else
uvm_report_warning("TYPDUP", {"Original and override type ",
"arguments are identical: ",
original_type.get_type_name()}, UVM_NONE);
end
// register the types if not already done so, for the benefit of string-based lookup
if (!m_types.exists(original_type))
register(original_type);
if (!m_types.exists(override_type))
register(override_type);
// check for existing type override
foreach (m_type_overrides[index]) begin
if (m_type_overrides[index].orig_type == original_type ||
(m_type_overrides[index].orig_type_name != "<unknown>" &&
m_type_overrides[index].orig_type_name != "" &&
m_type_overrides[index].orig_type_name == original_type.get_type_name())) begin
string msg;
msg = {"Original object type '",original_type.get_type_name(),
"' already registered to produce '",
m_type_overrides[index].ovrd_type_name,"'"};
if (!replace) begin
msg = {msg, ". Set 'replace' argument to replace the existing entry."};
uvm_report_info("TPREGD", msg, UVM_MEDIUM);
return;
end
msg = {msg, ". Replacing with override to produce type '",
override_type.get_type_name(),"'."};
uvm_report_info("TPREGR", msg, UVM_MEDIUM);
replaced = 1;
m_type_overrides[index].orig_type = original_type;
m_type_overrides[index].orig_type_name = original_type.get_type_name();
m_type_overrides[index].ovrd_type = override_type;
m_type_overrides[index].ovrd_type_name = override_type.get_type_name();
end
end
// make a new entry
if (!replaced) begin
uvm_factory_override override;
override = new(.orig_type(original_type),
.orig_type_name(original_type.get_type_name()),
.full_inst_path("*"),
.ovrd_type(override_type));
m_type_overrides.push_back(override);
end
endfunction
// set_type_override_by_name
// -------------------------
function void uvm_default_factory::set_type_override_by_name (string original_type_name,
string override_type_name,
bit replace=1);
bit replaced;
uvm_object_wrapper original_type;
uvm_object_wrapper override_type;
if(m_type_names.exists(original_type_name))
original_type = m_type_names[original_type_name];
if(m_type_names.exists(override_type_name))
override_type = m_type_names[override_type_name];
// check that type is registered with the factory
if (override_type == null) begin
uvm_report_error("TYPNTF", {"Cannot register override for original type '",
original_type_name,"' because the override type '",
override_type_name, "' is not registered with the factory."}, UVM_NONE);
return;
end
// check that old and new are not the same
if (original_type_name == override_type_name) begin
uvm_report_warning("TYPDUP", {"Requested and actual type name ",
" arguments are identical: ",original_type_name,". Ignoring this override."}, UVM_NONE);
return;
end
foreach (m_type_overrides[index]) begin
if (m_type_overrides[index].orig_type_name == original_type_name) begin
if (!replace) begin
uvm_report_info("TPREGD", {"Original type '",original_type_name,
"' already registered to produce '",m_type_overrides[index].ovrd_type_name,
"'. Set 'replace' argument to replace the existing entry."}, UVM_MEDIUM);
return;
end
uvm_report_info("TPREGR", {"Original object type '",original_type_name,
"' already registered to produce '",m_type_overrides[index].ovrd_type_name,
"'. Replacing with override to produce type '",override_type_name,"'."}, UVM_MEDIUM);
replaced = 1;
m_type_overrides[index].ovrd_type = override_type;
m_type_overrides[index].ovrd_type_name = override_type_name;
end
end
if (original_type == null)
m_lookup_strs[original_type_name] = 1;
if (!replaced) begin
uvm_factory_override override;
override = new(.orig_type(original_type),
.orig_type_name(original_type_name),
.full_inst_path("*"),
.ovrd_type(override_type));
m_type_overrides.push_back(override);
// m_type_names[original_type_name] = override.ovrd_type;
end
endfunction
// check_inst_override_exists
// --------------------------
function bit uvm_default_factory::check_inst_override_exists (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
string full_inst_path);
uvm_factory_override override;
uvm_factory_queue_class qc;
if (m_inst_override_queues.exists(original_type))
qc = m_inst_override_queues[original_type];
else
return 0;
for (int index=0; index<qc.queue.size(); ++index) begin
override = qc.queue[index];
if (override.full_inst_path == full_inst_path &&
override.orig_type == original_type &&
override.ovrd_type == override_type &&
override.orig_type_name == original_type.get_type_name()) begin
uvm_report_info("DUPOVRD",{"Instance override for '",
original_type.get_type_name(),"' already exists: override type '",
override_type.get_type_name(),"' with full_inst_path '",
full_inst_path,"'"},UVM_HIGH);
return 1;
end
end
return 0;
endfunction
// set_inst_override_by_type
// -------------------------
function void uvm_default_factory::set_inst_override_by_type (uvm_object_wrapper original_type,
uvm_object_wrapper override_type,
string full_inst_path);
uvm_factory_override override;
// register the types if not already done so
if (!m_types.exists(original_type))
register(original_type);
if (!m_types.exists(override_type))
register(override_type);
if (check_inst_override_exists(original_type,override_type,full_inst_path))
return;
if(!m_inst_override_queues.exists(original_type))
m_inst_override_queues[original_type] = new;
override = new(.full_inst_path(full_inst_path),
.orig_type(original_type),
.orig_type_name(original_type.get_type_name()),
.ovrd_type(override_type));
m_inst_override_queues[original_type].queue.push_back(override);
endfunction
// set_inst_override_by_name
// -------------------------
function void uvm_default_factory::set_inst_override_by_name (string original_type_name,
string override_type_name,
string full_inst_path);
uvm_factory_override override;
uvm_object_wrapper original_type;
uvm_object_wrapper override_type;
if(m_type_names.exists(original_type_name))
original_type = m_type_names[original_type_name];
if(m_type_names.exists(override_type_name))
override_type = m_type_names[override_type_name];
// check that type is registered with the factory
if (override_type == null) begin
uvm_report_error("TYPNTF", {"Cannot register instance override with type name '",
original_type_name,"' and instance path '",full_inst_path,"' because the type it's supposed ",
"to produce, '",override_type_name,"', is not registered with the factory."}, UVM_NONE);
return;
end
if (original_type == null)
m_lookup_strs[original_type_name] = 1;
override = new(.full_inst_path(full_inst_path),
.orig_type(original_type),
.orig_type_name(original_type_name),
.ovrd_type(override_type));
if(original_type != null) begin
if (check_inst_override_exists(original_type,override_type,full_inst_path))
return;
if(!m_inst_override_queues.exists(original_type))
m_inst_override_queues[original_type] = new;
m_inst_override_queues[original_type].queue.push_back(override);
end
else begin
if(m_has_wildcard(original_type_name)) begin
foreach(m_type_names[i]) begin
if(uvm_is_match(original_type_name,i)) begin
this.set_inst_override_by_name(i, override_type_name, full_inst_path);
end
end
m_wildcard_inst_overrides.push_back(override);
end
else begin
if(!m_inst_override_name_queues.exists(original_type_name))
m_inst_override_name_queues[original_type_name] = new;
m_inst_override_name_queues[original_type_name].queue.push_back(override);
end
end
endfunction
function bit uvm_default_factory::m_has_wildcard(string nm);
foreach (nm[i])
if(nm[i] == "*" || nm[i] == "?") return 1;
return 0;
endfunction
// create_object_by_name
// ---------------------
function uvm_object uvm_default_factory::create_object_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
uvm_object_wrapper wrapper;
string inst_path;
if (parent_inst_path == "")
inst_path = name;
else if (name != "")
inst_path = {parent_inst_path,".",name};
else
inst_path = parent_inst_path;
m_override_info.delete();
wrapper = find_override_by_name(requested_type_name, inst_path);
// if no override exists, try to use requested_type_name directly
if (wrapper==null) begin
if(!m_type_names.exists(requested_type_name)) begin
uvm_report_warning("BDTYP",{"Cannot create an object of type '",
requested_type_name,"' because it is not registered with the factory."}, UVM_NONE);
return null;
end
wrapper = m_type_names[requested_type_name];
end
return wrapper.create_object(name);
endfunction
// create_object_by_type
// ---------------------
function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
string full_inst_path;
if (parent_inst_path == "")
full_inst_path = name;
else if (name != "")
full_inst_path = {parent_inst_path,".",name};
else
full_inst_path = parent_inst_path;
m_override_info.delete();
requested_type = find_override_by_type(requested_type, full_inst_path);
return requested_type.create_object(name);
endfunction
// create_component_by_name
// ------------------------
function uvm_component uvm_default_factory::create_component_by_name (string requested_type_name,
string parent_inst_path="",
string name,
uvm_component parent);
uvm_object_wrapper wrapper;
string inst_path;
if (parent_inst_path == "")
inst_path = name;
else if (name != "")
inst_path = {parent_inst_path,".",name};
else
inst_path = parent_inst_path;
m_override_info.delete();
wrapper = find_override_by_name(requested_type_name, inst_path);
// if no override exists, try to use requested_type_name directly
if (wrapper == null) begin
if(!m_type_names.exists(requested_type_name)) begin
uvm_report_warning("BDTYP",{"Cannot create a component of type '",
requested_type_name,"' because it is not registered with the factory."}, UVM_NONE);
return null;
end
wrapper = m_type_names[requested_type_name];
end
return wrapper.create_component(name, parent);
endfunction
// create_component_by_type
// ------------------------
function uvm_component uvm_default_factory::create_component_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name,
uvm_component parent);
string full_inst_path;
if (parent_inst_path == "")
full_inst_path = name;
else if (name != "")
full_inst_path = {parent_inst_path,".",name};
else
full_inst_path = parent_inst_path;
m_override_info.delete();
requested_type = find_override_by_type(requested_type, full_inst_path);
return requested_type.create_component(name, parent);
endfunction
// find_wrapper_by_name
// ------------
function uvm_object_wrapper uvm_default_factory::find_wrapper_by_name(string type_name);
if (m_type_names.exists(type_name))
return m_type_names[type_name];
uvm_report_warning("UnknownTypeName", {"find_wrapper_by_name: Type name '",type_name,
"' not registered with the factory."}, UVM_NONE);
endfunction
// find_override_by_name
// ---------------------
function uvm_object_wrapper uvm_default_factory::find_override_by_name (string requested_type_name,
string full_inst_path);
uvm_object_wrapper rtype;
uvm_factory_queue_class qc;
uvm_factory_override lindex;
uvm_object_wrapper override;
if (m_type_names.exists(requested_type_name))
rtype = m_type_names[requested_type_name];
/***
if(rtype == null) begin
if(requested_type_name != "") begin
uvm_report_warning("TYPNTF", {"Requested type name ",
requested_type_name, " is not registered with the factory. The instance override to ",
full_inst_path, " is ignored"}, UVM_NONE);
end
m_lookup_strs[requested_type_name] = 1;
return null;
end
***/
if (full_inst_path != "") begin
if(rtype == null) begin
if(m_inst_override_name_queues.exists(requested_type_name))
qc = m_inst_override_name_queues[requested_type_name];
end
else begin
if(m_inst_override_queues.exists(rtype))
qc = m_inst_override_queues[rtype];
end
if(qc != null)
for(int index = 0; index<qc.queue.size(); ++index) begin
if (uvm_is_match(qc.queue[index].orig_type_name, requested_type_name) &&
uvm_is_match(qc.queue[index].full_inst_path, full_inst_path)) begin
m_override_info.push_back(qc.queue[index]);
if (m_debug_pass) begin
if (override == null) begin
override = qc.queue[index].ovrd_type;
qc.queue[index].selected = 1;
lindex=qc.queue[index];
end
end
else begin
qc.queue[index].used++;
if (qc.queue[index].ovrd_type.get_type_name() == requested_type_name)
return qc.queue[index].ovrd_type;
else
return find_override_by_type(qc.queue[index].ovrd_type,full_inst_path);
end
end
end
end
if(rtype != null && !m_inst_override_queues.exists(rtype) && m_wildcard_inst_overrides.size()) begin
m_inst_override_queues[rtype] = new;
foreach (m_wildcard_inst_overrides[i]) begin
if(uvm_is_match(m_wildcard_inst_overrides[i].orig_type_name, requested_type_name))
m_inst_override_queues[rtype].queue.push_back(m_wildcard_inst_overrides[i]);
end
end
// type override - exact match
foreach (m_type_overrides[index])
if (m_type_overrides[index].orig_type_name == requested_type_name) begin
m_override_info.push_back(m_type_overrides[index]);
if (m_debug_pass) begin
if (override == null) begin
override = m_type_overrides[index].ovrd_type;
m_type_overrides[index].selected = 1;
lindex=m_type_overrides[index];
end
end
else begin
m_type_overrides[index].used++;
return find_override_by_type(m_type_overrides[index].ovrd_type,full_inst_path);
end
end
if (m_debug_pass && override != null) begin
lindex.used++;
return find_override_by_type(override, full_inst_path);
end
// No override found
return null;
endfunction
// find_override_by_type
// ---------------------
function uvm_object_wrapper uvm_default_factory::find_override_by_type(uvm_object_wrapper requested_type,
string full_inst_path);
uvm_object_wrapper override;
uvm_factory_override lindex;
uvm_factory_queue_class qc;
qc = m_inst_override_queues.exists(requested_type) ?
m_inst_override_queues[requested_type] : null;
foreach (m_override_info[index]) begin
if ( //index != m_override_info.size()-1 &&
m_override_info[index].orig_type == requested_type) begin
uvm_report_error("OVRDLOOP", "Recursive loop detected while finding override.", UVM_NONE);
if (!m_debug_pass)
debug_create_by_type (requested_type, full_inst_path);
m_override_info[index].used++;
return requested_type;
end
end
// inst override; return first match; takes precedence over type overrides
if (full_inst_path != "" && qc != null)
for (int index = 0; index < qc.queue.size(); ++index) begin
if ((qc.queue[index].orig_type == requested_type ||
(qc.queue[index].orig_type_name != "<unknown>" &&
qc.queue[index].orig_type_name != "" &&
qc.queue[index].orig_type_name == requested_type.get_type_name())) &&
uvm_is_match(qc.queue[index].full_inst_path, full_inst_path)) begin
m_override_info.push_back(qc.queue[index]);
if (m_debug_pass) begin
if (override == null) begin
override = qc.queue[index].ovrd_type;
qc.queue[index].selected = 1;
lindex=qc.queue[index];
end
end
else begin
qc.queue[index].used++;
if (qc.queue[index].ovrd_type == requested_type)
return requested_type;
else
return find_override_by_type(qc.queue[index].ovrd_type,full_inst_path);
end
end
end
// type override - exact match
foreach (m_type_overrides[index]) begin
if (m_type_overrides[index].orig_type == requested_type ||
(m_type_overrides[index].orig_type_name != "<unknown>" &&
m_type_overrides[index].orig_type_name != "" &&
requested_type != null &&
m_type_overrides[index].orig_type_name == requested_type.get_type_name())) begin
m_override_info.push_back(m_type_overrides[index]);
if (m_debug_pass) begin
if (override == null) begin
override = m_type_overrides[index].ovrd_type;
m_type_overrides[index].selected = 1;
lindex=m_type_overrides[index];
end
end
else begin
m_type_overrides[index].used++;
if (m_type_overrides[index].ovrd_type == requested_type)
return requested_type;
else
return find_override_by_type(m_type_overrides[index].ovrd_type,full_inst_path);
end
end
end
// type override with wildcard match
//foreach (m_type_overrides[index])
// if (uvm_is_match(index,requested_type.get_type_name())) begin
// m_override_info.push_back(m_inst_overrides[index]);
// return find_override_by_type(m_type_overrides[index],full_inst_path);
// end
if (m_debug_pass && override != null) begin
lindex.used++;
if (override == requested_type) begin
return requested_type;
end
else
return find_override_by_type(override,full_inst_path);
end
return requested_type;
endfunction
// print
// -----
function void uvm_default_factory::print (int all_types=1);
string key;
uvm_factory_queue_class sorted_override_queues[string];
string qs[$];
string tmp;
int id;
uvm_object_wrapper obj;
//sort the override queues
foreach (m_inst_override_queues[i]) begin
obj = i;
tmp = obj.get_type_name();
if(tmp == "") $swrite(tmp, "__unnamed_id_%0d", id++);
sorted_override_queues[tmp] = m_inst_override_queues[i];
end
foreach (m_inst_override_name_queues[i]) begin
sorted_override_queues[i] = m_inst_override_name_queues[i];
end
qs.push_back("\n#### Factory Configuration (*)\n\n");
// print instance overrides
if(!m_type_overrides.size() && !sorted_override_queues.num())
qs.push_back(" No instance or type overrides are registered with this factory\n");
else begin
int max1,max2,max3;
string dash = "---------------------------------------------------------------------------------------------------";
string space= " ";
// print instance overrides
if(!sorted_override_queues.num())
qs.push_back("No instance overrides are registered with this factory\n");
else begin
foreach(sorted_override_queues[j]) begin
uvm_factory_queue_class qc;
qc = sorted_override_queues[j];
for (int i=0; i<qc.queue.size(); ++i) begin
if (qc.queue[i].orig_type_name.len() > max1)
max1=qc.queue[i].orig_type_name.len();
if (qc.queue[i].full_inst_path.len() > max2)
max2=qc.queue[i].full_inst_path.len();
if (qc.queue[i].ovrd_type_name.len() > max3)
max3=qc.queue[i].ovrd_type_name.len();
end
end
if (max1 < 14) max1 = 14;
if (max2 < 13) max2 = 13;
if (max3 < 13) max3 = 13;
qs.push_back("Instance Overrides:\n\n");
qs.push_back($sformatf(" %0s%0s %0s%0s %0s%0s\n","Requested Type",space.substr(1,max1-14),
"Override Path", space.substr(1,max2-13),
"Override Type", space.substr(1,max3-13)));
qs.push_back($sformatf(" %0s %0s %0s\n",dash.substr(1,max1),
dash.substr(1,max2),
dash.substr(1,max3)));
foreach(sorted_override_queues[j]) begin
uvm_factory_queue_class qc;
qc = sorted_override_queues[j];
for (int i=0; i<qc.queue.size(); ++i) begin
qs.push_back($sformatf(" %0s%0s %0s%0s",qc.queue[i].orig_type_name,
space.substr(1,max1-qc.queue[i].orig_type_name.len()),
qc.queue[i].full_inst_path,
space.substr(1,max2-qc.queue[i].full_inst_path.len())));
qs.push_back($sformatf(" %0s\n", qc.queue[i].ovrd_type_name));
end
end
end
// print type overrides
if (!m_type_overrides.size())
qs.push_back("\nNo type overrides are registered with this factory\n");
else begin
// Resize for type overrides
if (max1 < 14) max1 = 14;
if (max2 < 13) max2 = 13;
if (max3 < 13) max3 = 13;
foreach (m_type_overrides[i]) begin
if (m_type_overrides[i].orig_type_name.len() > max1)
max1=m_type_overrides[i].orig_type_name.len();
if (m_type_overrides[i].ovrd_type_name.len() > max2)
max2=m_type_overrides[i].ovrd_type_name.len();
end
if (max1 < 14) max1 = 14;
if (max2 < 13) max2 = 13;
qs.push_back("\nType Overrides:\n\n");
qs.push_back($sformatf(" %0s%0s %0s%0s\n","Requested Type",space.substr(1,max1-14),
"Override Type", space.substr(1,max2-13)));
qs.push_back($sformatf(" %0s %0s\n",dash.substr(1,max1),
dash.substr(1,max2)));
foreach (m_type_overrides[index])
qs.push_back($sformatf(" %0s%0s %0s\n",
m_type_overrides[index].orig_type_name,
space.substr(1,max1-m_type_overrides[index].orig_type_name.len()),
m_type_overrides[index].ovrd_type_name));
end
end
// print all registered types, if all_types >= 1
if (all_types >= 1 && m_type_names.first(key)) begin
bit banner;
qs.push_back($sformatf("\nAll types registered with the factory: %0d total\n",m_types.num()));
do begin
// filter out uvm_ classes (if all_types<2) and non-types (lookup strings)
if (!(all_types < 2 && uvm_is_match("uvm_*",
m_type_names[key].get_type_name())) &&
key == m_type_names[key].get_type_name()) begin
if (!banner) begin
qs.push_back(" Type Name\n");
qs.push_back(" ---------\n");
banner=1;
end
qs.push_back($sformatf(" %s\n", m_type_names[key].get_type_name()));
end
end while(m_type_names.next(key));
end
qs.push_back("(*) Types with no associated type name will be printed as <unknown>\n\n####\n\n");
`uvm_info("UVM/FACTORY/PRINT",`UVM_STRING_QUEUE_STREAMING_PACK(qs),UVM_NONE)
endfunction
// debug_create_by_name
// --------------------
function void uvm_default_factory::debug_create_by_name (string requested_type_name,
string parent_inst_path="",
string name="");
m_debug_create(requested_type_name, null, parent_inst_path, name);
endfunction
// debug_create_by_type
// --------------------
function void uvm_default_factory::debug_create_by_type (uvm_object_wrapper requested_type,
string parent_inst_path="",
string name="");
m_debug_create("", requested_type, parent_inst_path, name);
endfunction
// m_debug_create
// --------------
function void uvm_default_factory::m_debug_create (string requested_type_name,
uvm_object_wrapper requested_type,
string parent_inst_path,
string name);
string full_inst_path;
uvm_object_wrapper result;
if (parent_inst_path == "")
full_inst_path = name;
else if (name != "")
full_inst_path = {parent_inst_path,".",name};
else
full_inst_path = parent_inst_path;
m_override_info.delete();
if (requested_type == null) begin
if (!m_type_names.exists(requested_type_name) &&
!m_lookup_strs.exists(requested_type_name)) begin
uvm_report_warning("Factory Warning", {"The factory does not recognize '",
requested_type_name,"' as a registered type."}, UVM_NONE);
return;
end
m_debug_pass = 1;
result = find_override_by_name(requested_type_name,full_inst_path);
end
else begin
m_debug_pass = 1;
if (!m_types.exists(requested_type))
register(requested_type);
result = find_override_by_type(requested_type,full_inst_path);
if (requested_type_name == "")
requested_type_name = requested_type.get_type_name();
end
m_debug_display(requested_type_name, result, full_inst_path);
m_debug_pass = 0;
foreach (m_override_info[index])
m_override_info[index].selected = 0;
endfunction
// m_debug_display
// ---------------
function void uvm_default_factory::m_debug_display (string requested_type_name,
uvm_object_wrapper result,
string full_inst_path);
int max1,max2,max3;
string dash = "---------------------------------------------------------------------------------------------------";
string space= " ";
string qs[$];
qs.push_back("\n#### Factory Override Information (*)\n\n");
qs.push_back(
$sformatf("Given a request for an object of type '%s' with an instance\npath of '%s' the factory encountered\n\n",
requested_type_name,full_inst_path));
if (m_override_info.size() == 0)
qs.push_back("no relevant overrides.\n\n");
else begin
qs.push_back("the following relevant overrides. An 'x' next to a match indicates a\nmatch that was ignored.\n\n");
foreach (m_override_info[i]) begin
if (m_override_info[i].orig_type_name.len() > max1)
max1=m_override_info[i].orig_type_name.len();
if (m_override_info[i].full_inst_path.len() > max2)
max2=m_override_info[i].full_inst_path.len();
if (m_override_info[i].ovrd_type_name.len() > max3)
max3=m_override_info[i].ovrd_type_name.len();
end
if (max1 < 13) max1 = 13;
if (max2 < 13) max2 = 13;
if (max3 < 13) max3 = 13;
qs.push_back($sformatf("Original Type%0s Instance Path%0s Override Type%0s\n",
space.substr(1,max1-13),space.substr(1,max2-13),space.substr(1,max3-13)));
qs.push_back($sformatf(" %0s %0s %0s\n",dash.substr(1,max1),
dash.substr(1,max2),
dash.substr(1,max3)));
foreach (m_override_info[i]) begin
qs.push_back($sformatf("%s%0s%0s\n",
m_override_info[i].selected ? " " : "x ",
m_override_info[i].orig_type_name,
space.substr(1,max1-m_override_info[i].orig_type_name.len())));
qs.push_back($sformatf(" %0s%0s", m_override_info[i].full_inst_path,
space.substr(1,max2-m_override_info[i].full_inst_path.len())));
qs.push_back($sformatf(" %0s%0s", m_override_info[i].ovrd_type_name,
space.substr(1,max3-m_override_info[i].ovrd_type_name.len())));
if (m_override_info[i].full_inst_path == "*")
qs.push_back(" <type override>");
else
qs.push_back("\n");
end
qs.push_back("\n");
end
qs.push_back("Result:\n\n");
qs.push_back($sformatf(" The factory will produce an object of type '%0s'\n",
result == null ? requested_type_name : result.get_type_name()));
qs.push_back("\n(*) Types with no associated type name will be printed as <unknown>\n\n####\n\n");
`uvm_info("UVM/FACTORY/DUMP",`UVM_STRING_QUEUE_STREAMING_PACK(qs),UVM_NONE)
endfunction