[go: up one dir, main page]

0% found this document useful (0 votes)
113 views57 pages

Winning Startegies in Derivative Segmanet

The document describes the UVM factory facility which is used to create UVM objects and components. It defines classes like uvm_factory that manage object creation and registration. The factory allows creating objects by type or name and supports type and instance overrides.

Uploaded by

Bhim Gudur
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
113 views57 pages

Winning Startegies in Derivative Segmanet

The document describes the UVM factory facility which is used to create UVM objects and components. It defines classes like uvm_factory that manage object creation and registration. The factory allows creating objects by type or name and supports type and instance overrides.

Uploaded by

Bhim Gudur
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 57

//

//------------------------------------------------------------------------------

// Copyright 2007-2011 Mentor Graphics Corporation

// Copyright 2007-2011 Cadence Design Systems, Inc.

// Copyright 2010-2011 Synopsys, 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 uvm_object;

typedef class uvm_component;

typedef class uvm_object_wrapper;

typedef class uvm_factory_override;

//Instance overrides by requested type lookup


class 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. Only one instance of the factory is present in a given

// simulation (termed a singleton). 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.

//

// See <Usage> section for details on configuring and using the factory.

//

class uvm_factory;

extern `_protected function new ();

// Function: get()

// Get the factory singleton

//

extern static function uvm_factory get();

// 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.

extern function void register (uvm_object_wrapper obj);

// Group: Type & Instance Overrides

// Function: set_inst_override_by_type

extern function

void 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 contentation 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.

extern function

void set_inst_override_by_name (string original_type_name,

string override_type_name,

string full_inst_path);

// Function: set_type_override_by_type

extern function

void 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.

extern function

void set_type_override_by_name (string original_type_name,

string override_type_name,

bit replace=1);

// Group: Creation

// Function: create_object_by_type

extern function
uvm_object create_object_by_type (uvm_object_wrapper requested_type,

string parent_inst_path="",

string name="");

// Function: create_component_by_type

extern function

uvm_component create_component_by_type (uvm_object_wrapper requested_type,

string parent_inst_path="",

string name,

uvm_component parent);

// Function: create_object_by_name

extern function

uvm_object 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.

extern function

uvm_component 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 function

void 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.

extern function

void debug_create_by_name (string requested_type_name,

string parent_inst_path="",

string name="");

// Function: find_override_by_type

extern function
uvm_object_wrapper 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 }.

extern function

uvm_object_wrapper find_override_by_name (string requested_type_name,

string full_inst_path);

extern

function uvm_object_wrapper find_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.

extern function void 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);

static local uvm_factory m_inst;

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 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 registeriing 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

// 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 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 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 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 get_type_name();

endclass

//------------------------------------------------------------------------------

//

// CLASS- uvm_factory_override

//

// Internal class.

//------------------------------------------------------------------------------

class uvm_factory_override;

string full_inst_path;

string orig_type_name;

string ovrd_type_name;

bit selected;

uvm_object_wrapper orig_type;

uvm_object_wrapper ovrd_type;

function 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

//-----------------------------------------------------------------------------

// our singleton factory; it is statically initialized

//-----------------------------------------------------------------------------

const uvm_factory factory = uvm_factory::get();

//-----------------------------------------------------------------------------

// IMPLEMENTATION

//-----------------------------------------------------------------------------

// get

// ---
function uvm_factory uvm_factory::get();

if (m_inst == null) begin

m_inst = new();

end

return m_inst;

endfunction

// new

// ---

function uvm_factory::new ();

endfunction

// register

// --------

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

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_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);

return;

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_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_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_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_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_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_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_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_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_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_by_name

// ------------

function uvm_object_wrapper uvm_factory::find_by_name(string type_name);

if (m_type_names.exists(type_name))

return m_type_names[type_name];

uvm_report_warning("UnknownTypeName", {"find_by_name: Type name '",type_name,

"' not registered with the factory."}, UVM_NONE);

endfunction

// find_override_by_name

// ---------------------
function uvm_object_wrapper uvm_factory::find_override_by_name (string requested_type_name,

string full_inst_path);

uvm_object_wrapper rtype;

uvm_factory_queue_class qc;

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;

end

end

else begin

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;

end

end

else begin

return find_override_by_type(m_type_overrides[index].ovrd_type,full_inst_path);

end

end

if (m_debug_pass && override != null)

return find_override_by_type(override, full_inst_path);

// No override found

return null;

endfunction
// find_override_by_type

// ---------------------

function uvm_object_wrapper uvm_factory::find_override_by_type(uvm_object_wrapper


requested_type,

string full_inst_path);

uvm_object_wrapper override;

uvm_factory_queue_class qc = null;

if (m_inst_override_queues.exists(requested_type))

qc = m_inst_override_queues[requested_type];

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);

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;

end

end

else begin

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;

end

end

else begin

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)

if (override == requested_type)

return requested_type;

else

return find_override_by_type(override,full_inst_path);

return requested_type;

endfunction
// print

// -----

function void uvm_factory::print (int all_types=1);

string key;

uvm_factory_queue_class sorted_override_queues[string];

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

$display("\n#### Factory Configuration (*)\n");

// print instance overrides

if(!m_type_overrides.size() && !sorted_override_queues.num())


$display(" No instance or type overrides are registered with this factory");

else begin

int max1,max2,max3;

string dash = "---------------------------------------------------------------------------------------------------";

string space= " ";

// print instance overrides

if(!sorted_override_queues.num())

$display("No instance overrides are registered with this factory");

else begin

foreach(sorted_override_queues[j]) begin

uvm_factory_queue_class 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;

$display("Instance Overrides:\n");

$display(" %0s%0s %0s%0s %0s%0s","Requested Type",space.substr(1,max1-14),

"Override Path", space.substr(1,max2-13),

"Override Type", space.substr(1,max3-13));


$display(" %0s %0s %0s",dash.substr(1,max1),

dash.substr(1,max2),

dash.substr(1,max3));

foreach(sorted_override_queues[j]) begin

uvm_factory_queue_class qc = sorted_override_queues[j];

for (int i=0; i<qc.queue.size(); ++i) begin

$write(" %0s%0s",qc.queue[i].orig_type_name,

space.substr(1,max1-qc.queue[i].orig_type_name.len()));

$write(" %0s%0s", qc.queue[i].full_inst_path,

space.substr(1,max2-qc.queue[i].full_inst_path.len()));

$display(" %0s", qc.queue[i].ovrd_type_name);

end

end

end

// print type overrides

if (!m_type_overrides.size())

$display("\nNo type overrides are registered with this factory");

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;

$display("\nType Overrides:\n");

$display(" %0s%0s %0s%0s","Requested Type",space.substr(1,max1-14),

"Override Type", space.substr(1,max2-13));

$display(" %0s %0s",dash.substr(1,max1),

dash.substr(1,max2));

foreach (m_type_overrides[index])

$display(" %0s%0s %0s",

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;

$display("\nAll types registered with the factory: %0d total",m_types.num());

$display("(types without type names will not be printed)\n");

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

$display(" Type Name");


$display(" ---------");

banner=1;

end

$display(" ", m_type_names[key].get_type_name());

end

end while(m_type_names.next(key));

end

$display("(*) Types with no associated type name will be printed as <unknown>");

$display("\n####\n");

endfunction

// debug_create_by_name

// --------------------

function void uvm_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_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_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_factory::m_debug_display (string requested_type_name,

uvm_object_wrapper result,

string full_inst_path);

int max1,max2,max3;

string dash = "---------------------------------------------------------------------------------------------------";

string space= " ";

$display("\n#### Factory Override Information (*)\n");

$write("Given a request for an object of type '",requested_type_name,

"' with an instance\npath of '",full_inst_path,

"', the factory encountered\n");

if (m_override_info.size() == 0)

$display("no relevant overrides.\n");

else begin

$display("the following relevant overrides. An 'x' next to a match indicates a",

"\nmatch that was ignored.\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;

$display(" %0s%0s", "Original Type", space.substr(1,max1-13),

" %0s%0s", "Instance Path", space.substr(1,max2-13),

" %0s%0s", "Override Type", space.substr(1,max3-13));

$display(" %0s %0s %0s",dash.substr(1,max1),

dash.substr(1,max2),

dash.substr(1,max3));

foreach (m_override_info[i]) begin

$write("%s%0s%0s",

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()));

$write(" %0s%0s", m_override_info[i].full_inst_path,

space.substr(1,max2-m_override_info[i].full_inst_path.len()));

$write(" %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 == "*")

$display(" <type override>");

else

$display();

end

$display();

end
$display("Result:\n");

$display(" The factory will produce an object of type '%0s'",

result == null ? requested_type_name : result.get_type_name());

$display("\n(*) Types with no associated type name will be printed as <unknown>");

$display("\n####\n");

endfunction

You might also like