Source code for uvm.base.uvm_factory

#//
#//------------------------------------------------------------------------------
#//   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.
#//   Copyright 2019 Tuomas Poikela (tpoikela)
#//   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.
#//------------------------------------------------------------------------------

# pytype: disable=attribute-error,not-writable

from typing import List, Optional

from .sv import sv
from .uvm_queue import UVMQueue
from .uvm_pool import UVMPool
from .uvm_globals import (uvm_report_error, uvm_report_fatal, uvm_report_warning,
    uvm_is_match, uvm_report_info)
from .uvm_object_globals import UVM_NONE, UVM_MEDIUM, UVM_HIGH
from ..macros import uvm_info
from ..uvm_macros import UVM_STRING_QUEUE_STREAMING_PACK



[docs]def m_has_wildcard(nm: str) -> bool: """ Returns True if given string has wildcard * or ? """ for char in nm: if char == "*" or char == "?": return True return False
[docs]class uvm_factory_queue_class: def __init__(self): self.queue = UVMQueue()
#------------------------------------------------------------------------------ # # CLASS- UVMFactoryOverride # # Internal class. Data structure for factory overrides to store all override # related information. #------------------------------------------------------------------------------
[docs]class UVMFactoryOverride: def __init__(self, full_inst_path="", orig_type_name="", orig_type=None, ovrd_type=None): if ovrd_type is None: uvm_report_fatal("NULLWR", "Attempting to register a null override object with the factory", UVM_NONE) self.full_inst_path = full_inst_path self.orig_type_name = orig_type_name if orig_type is not None: self.orig_type_name = orig_type.get_type_name() self.orig_type = orig_type self.ovrd_type_name = ovrd_type.get_type_name() self.ovrd_type = ovrd_type self.selected = False self.used = 0
[docs]class UVMFactory: """ UVMFactory is used to create objects of type `UVMComponent` and `UVMObject` (and their derived user-defined types). Object and component types are registered with the factory using lightweight proxies to the actual objects and components being created. The `UVMObjectRegistry` and `UVMComponentRegistry` class are used to proxy `UVMObject` and `UVMComponent`. The factory provides both name-based and type-based interfaces. type-based - The type-based interface is far less prone to errors in usage. 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. The `UVMFactory` is an abstract class. The UVM uses the `UVMDefaultFactory` class as its default factory implementation. See `UVMDefaultFactory` section for details on configuring and using the factory. """ #// Group: Retrieving the factory
[docs] @classmethod def get(cls) -> 'UVMFactory': """ Function: get Static accessor for `UVMFactory` The static accessor is provided as a convenience wrapper around retrieving the factory via the `UVMCoreService.get_factory` method. .. code-block:: python # Using the uvm_coreservice_t: cs = UVMCoreService.get() f = cs.get_factory() .. code-block:: python # Not using the uvm_coreservice_t: f = UVMFactory.get() Returns: UVMFactory: Singleton instace of the factory """ from .uvm_coreservice import UVMCoreService cs = UVMCoreService.get() return cs.get_factory()
# NOTE: SV virtual functions not added from original uvm_factory, not needed in python #------------------------------------------------------------------------------ # # CLASS: uvm_default_factory # #------------------------------------------------------------------------------ # # Default implementation of the UVM factory.
[docs]class UVMDefaultFactory(UVMFactory): m_debug_pass = False def __init__(self): self.m_override_info: List[UVMFactoryOverride] = [] self.m_types = UVMPool() # [uvm_object_wrapper] -> bit self.m_lookup_strs = UVMPool() self.m_type_names = UVMPool() self.m_type_overrides: List[UVMFactoryOverride] = [] self.m_inst_override_queues = {} # [uvm_object_wrapper] -> queue self.m_inst_override_name_queues = {} # [string] -> queue self.m_wildcard_inst_overrides = UVMQueue()
[docs] def register(self, obj) -> None: """ Group: Registering Types Function: register Registers the given proxy object, `obj`, with the factory. Args: obj: """ if obj is None: uvm_report_fatal("NULLWR", "Attempting to register a null object with the factory") if obj.get_type_name() != "" and obj.get_type_name() != "<unknown>": if self.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: self.m_type_names.add(obj.get_type_name(), obj) if self.m_types.exists(obj): if obj.get_type_name() != "" and obj.get_type_name() != "<unknown>": uvm_report_warning("TPRGED", ("Object type '" + obj.get_type_name() + "' already registered with factory. "), UVM_NONE) else: self.m_types.add(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. tname = obj.get_type_name() if obj.get_type_name() in self.m_inst_override_name_queues: self.m_inst_override_queues[obj] = UVMQueue() self.m_inst_override_queues[obj] = self.m_inst_override_name_queues[tname] del self.m_inst_override_name_queues[tname] if self.m_wildcard_inst_overrides.size(): if obj not in self.m_inst_override_queues: self.m_inst_override_queues[obj] = UVMQueue() for i in range(0, self.m_wildcard_inst_overrides.size()): wc_inst_override = self.m_wildcard_inst_overrides[i] if uvm_is_match(wc_inst_override.orig_type_name, tname): self.m_inst_override_queues[obj].push_back(wc_inst_override)
[docs] def set_type_override_by_type(self, original_type, override_type, replace=True): """ set_type_override_by_type ------------------------- #def set_type_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, bit replace=1) Args: original_type: override_type: replace: """ replaced = False # check that old and new are not the same if original_type == override_type: if original_type.get_type_name() == "" or 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) # register the types if not already done so, for the benefit of string-based lookup if not self.m_types.exists(original_type): self.register(original_type) if not self.m_types.exists(override_type): self.register(override_type) # check for existing type override for index in range(len(self.m_type_overrides)): idx_orig_type = self.m_type_overrides[index].orig_type idx_type_name = self.m_type_overrides[index].orig_type_name if (idx_orig_type == original_type or (idx_type_name != "<unknown>" and idx_type_name != "" and idx_type_name == original_type.get_type_name())): msg = ("Original object type '" + original_type.get_type_name() + "' already registered to produce '" + self.m_type_overrides[index].ovrd_type_name + "'") if replace is False: msg = msg + ". Set 'replace' argument to replace the existing entry." uvm_report_info("TPREGD", msg, UVM_MEDIUM) return msg = (msg + ". Replacing with override to produce type '" + override_type.get_type_name() + "'.") uvm_report_info("TPREGR", msg, UVM_MEDIUM) replaced = True self.m_type_overrides[index].orig_type = original_type self.m_type_overrides[index].orig_type_name = original_type.get_type_name() self.m_type_overrides[index].ovrd_type = override_type self.m_type_overrides[index].ovrd_type_name = override_type.get_type_name() # make a new entry if replaced is False: # uvm_factory_override override override = UVMFactoryOverride(orig_type=original_type, orig_type_name=original_type.get_type_name(), full_inst_path="*", ovrd_type=override_type) self.m_type_overrides.append(override)
[docs] def set_type_override_by_name(self, original_type_name, override_type_name, replace=True): """ set_type_override_by_name ------------------------- Args: original_type_name: override_type_name: replace: """ replaced = False original_type = None override_type = None if self.m_type_names.exists(original_type_name): original_type = self.m_type_names.get(original_type_name) if self.m_type_names.exists(override_type_name): override_type = self.m_type_names.get(override_type_name) # check that type is registered with the factory if override_type is None: 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 # check that old and new are not the same if original_type_name == override_type_name: uvm_report_warning("TYPDUP", ("Requested and actual type name " + " arguments are identical: " + original_type_name + ". Ignoring this override."), UVM_NONE) return for index in range(0, len(self.m_type_overrides)): ovrd_type_name = self.m_type_overrides[index].ovrd_type_name if self.m_type_overrides[index].orig_type_name == original_type_name: if not replace: uvm_report_info("TPREGD", ("Original type '" + original_type_name + "' already registered to produce '" + ovrd_type_name + "'. Set 'replace' argument to replace the existing entry."), UVM_MEDIUM) return uvm_report_info("TPREGR", ("Original object type '" + original_type_name + "' already registered to produce '" + ovrd_type_name + "'. Replacing with override to produce type '" + override_type_name + "'."), UVM_MEDIUM) replaced = True self.m_type_overrides[index].ovrd_type = override_type self.m_type_overrides[index].ovrd_type_name = override_type_name if original_type is None: self.m_lookup_strs[original_type_name] = 1 if not replaced: # uvm_factory_override override override = UVMFactoryOverride(orig_type=original_type, orig_type_name=original_type_name, full_inst_path="*", ovrd_type=override_type) self.m_type_overrides.append(override) self.m_type_names.add(original_type_name, override.ovrd_type)
[docs] def check_inst_override_exists(self, original_type, override_type, full_inst_path): """ check_inst_override_exists -------------------------- #def check_inst_override_exists (uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path) Args: original_type: override_type: full_inst_path: Returns: """ override = None # uvm_factory_override qc = None # uvm_factory_queue_class if original_type in self.m_inst_override_queues: qc = self.m_inst_override_queues[original_type] else: return 0 for index in range(len(qc.queue)): override = qc.queue[index] if (override.full_inst_path == full_inst_path and override.orig_type == original_type and override.ovrd_type == override_type and override.orig_type_name == original_type.get_type_name()): 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 return 0
[docs] def set_inst_override_by_type(self, original_type, override_type, full_inst_path): """ set_inst_override_by_type ------------------------- #def set_inst_override_by_type (uvm_object_wrapper original_type, uvm_object_wrapper override_type, string full_inst_path) Args: original_type: override_type: full_inst_path: """ override = None # uvm_factory_override # register the types if not already done so if not self.m_types.exists(original_type): self.register(original_type) if not self.m_types.exists(override_type): self.register(override_type) if self.check_inst_override_exists(original_type,override_type,full_inst_path): return if original_type not in self.m_inst_override_queues: self.m_inst_override_queues[original_type] = UVMQueue() override = UVMFactoryOverride(full_inst_path=full_inst_path, orig_type=original_type, orig_type_name=original_type.get_type_name(), ovrd_type=override_type) self.m_inst_override_queues[original_type].push_back(override)
# set_inst_override_by_name # ------------------------- # TODO #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(self.m_type_names.exists(original_type_name)) # original_type = self.m_type_names[original_type_name] # # if(self.m_type_names.exists(override_type_name)) # override_type = self.m_type_names[override_type_name] # # // check that type is registered with the factory # if (override_type is None): # 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 is None) # 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): # 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: # if(m_has_wildcard(original_type_name)): # foreach(self.m_type_names[i]): # if(uvm_is_match(original_type_name,i)): # this.set_inst_override_by_name(i, override_type_name, full_inst_path) # end # end # m_wildcard_inst_overrides.push_back(override) # end # else: # if(!self.m_inst_override_name_queues.exists(original_type_name)) # self.m_inst_override_name_queues[original_type_name] = new # self.m_inst_override_name_queues[original_type_name].queue.push_back(override) # end # end # #endfunction
[docs] def create_object_by_name(self, requested_type_name, parent_inst_path="", name=""): """ create_object_by_name --------------------- Args: requested_type_name: parent_inst_path: name: Returns: """ inst_path = self._get_inst_path(parent_inst_path, name) self.m_override_info.clear() wrapper = self.find_override_by_name(requested_type_name, inst_path) # if no override exists, try to use requested_type_name directly if wrapper is None: if not self.m_type_names.exists(requested_type_name): uvm_report_warning("BDTYP", ("Cannot create an object of type '" + requested_type_name + "' because it is not registered with the factory."), UVM_NONE) return None wrapper = self.m_type_names.get(requested_type_name) return wrapper.create_object(name)
[docs] def create_object_by_type(self, requested_type, parent_inst_path="", name=""): """ create_object_by_type --------------------- Args: requested_type: parent_inst_path: name: Returns: """ if requested_type is None: uvm_report_fatal("REQ_TYPE_NONE", "Requested type object was None") full_inst_path = self._get_inst_path(parent_inst_path, name) self.m_override_info.clear() requested_type = self.find_override_by_type(requested_type, full_inst_path) if requested_type is None: uvm_report_fatal("REQ_TYPE_NONE", "Requested type object was None after override") return requested_type.create_object(name)
def _get_inst_path(self, parent_inst_path, name): inst_path = "" if parent_inst_path == "": inst_path = name elif name != "": inst_path = parent_inst_path + "." + name else: inst_path = parent_inst_path return inst_path
[docs] def create_component_by_name(self, requested_type_name, parent_inst_path, name, parent): """ create_component_by_name ------------------------ Args: requested_type_name: parent_inst_path: name: parent: Returns: """ inst_path = self._get_inst_path(parent_inst_path, name) self.m_override_info.clear() wrapper = self.find_override_by_name(requested_type_name, inst_path) # if no override exists, try to use requested_type_name directly if wrapper is None: if not self.m_type_names.exists(requested_type_name): uvm_report_warning("BDTYP", ("Cannot create a component of type '" + requested_type_name + "' because it is not registered with the factory."), UVM_NONE) return None wrapper = self.m_type_names.get(requested_type_name) return wrapper.create_component(name, parent)
[docs] def create_component_by_type(self, requested_type, parent_inst_path, name, parent): """ create_component_by_type ------------------------ Args: requested_type: parent_inst_path: name: parent: Returns: """ full_inst_path = self._get_inst_path(parent_inst_path, name) self.m_override_info.clear() requested_type = self.find_override_by_type(requested_type, full_inst_path) return requested_type.create_component(name, parent)
# find_wrapper_by_name # ------------ # TODO
[docs] def find_wrapper_by_name(self, type_name: str) -> Optional['UVMObjectWrapper']: if self.m_type_names.exists(type_name): return self.m_type_names[type_name] uvm_report_warning("UnknownTypeName", ("find_wrapper_by_name: Type name '" + type_name + "' not registered with the factory."), UVM_NONE)
[docs] def find_override_by_name( self, requested_type_name, full_inst_path) -> Optional['UVMObjectWrapper']: """ find_override_by_name --------------------- Args: requested_type_name (str): full_inst_path (str): Returns: UVMObjectWrapper """ rtype = None qc = UVMQueue() lindex = None override = None if self.m_type_names.exists(requested_type_name): rtype = self.m_type_names.get(requested_type_name) if full_inst_path != "": if rtype is None: if requested_type_name in self.m_inst_override_name_queues: qc = self.m_inst_override_name_queues[requested_type_name] else: if rtype in self.m_inst_override_queues: qc = self.m_inst_override_queues[rtype] if qc is not None: for index in range(0, qc.size()): match_ok = uvm_is_match(qc[index].orig_type_name, requested_type_name) if match_ok and uvm_is_match(qc[index].full_inst_path, full_inst_path): self.m_override_info.append(qc[index]) if UVMDefaultFactory.m_debug_pass: if override is None: override = qc[index].ovrd_type qc[index].selected = 1 lindex = qc[index] else: qc[index].used += 1 if qc[index].ovrd_type.get_type_name() == requested_type_name: return qc[index].ovrd_type else: return self.find_override_by_type(qc[index].ovrd_type,full_inst_path) ovrd_ok = rtype not in self.m_inst_override_queues and self.m_wildcard_inst_overrides.size() > 0 if rtype is not None and ovrd_ok: self.m_inst_override_queues[rtype] = UVMQueue() for i in range(0, self.m_wildcard_inst_overrides.size()): if uvm_is_match(self.m_wildcard_inst_overrides.get(i).orig_type_name, requested_type_name): self.m_inst_override_queues[rtype].push_back(self.m_wildcard_inst_overrides.get(i)) # type override - exact match for index in range(0, len(self.m_type_overrides)): if self.m_type_overrides[index].orig_type_name == requested_type_name: self.m_override_info.append(self.m_type_overrides[index]) if UVMDefaultFactory.m_debug_pass: if override is None: override = self.m_type_overrides[index].ovrd_type self.m_type_overrides[index].selected = 1 lindex = self.m_type_overrides[index] else: self.m_type_overrides[index].used += 1 return self.find_override_by_type(self.m_type_overrides[index].ovrd_type,full_inst_path) if UVMDefaultFactory.m_debug_pass and override is not None: lindex.used += 1 return self.find_override_by_type(override, full_inst_path) # No override found return None
[docs] def find_override_by_type(self, requested_type, full_inst_path): """ find_override_by_type --------------------- Args: requested_type: full_inst_path: Returns: """ override = None lindex = None qc = None if requested_type in self.m_inst_override_queues: qc = self.m_inst_override_queues[requested_type] for index in range(0, len(self.m_override_info)): if self.m_override_info[index].orig_type == requested_type: uvm_report_error("OVRDLOOP", "Recursive loop detected while finding override.", UVM_NONE) if UVMDefaultFactory.m_debug_pass is False: self.debug_create_by_type(requested_type, full_inst_path) self.m_override_info[index].used += 1 return requested_type # inst override; return first match; takes precedence over type overrides if full_inst_path != "" and qc is not None: for index in range(0, qc.size()): if self.are_args_ok(qc[index], requested_type, full_inst_path): self.m_override_info.append(qc[index]) if UVMDefaultFactory.m_debug_pass: if override is None: override = qc[index].ovrd_type qc[index].selected = 1 lindex = qc[index] else: qc[index].used += 1 if qc[index].ovrd_type == requested_type: return requested_type else: return self.find_override_by_type(qc[index].ovrd_type,full_inst_path) # type override - exact match for index in range(0, len(self.m_type_overrides)): if self.args_are_ok_again(self.m_type_overrides[index],requested_type): self.m_override_info.append(self.m_type_overrides[index]) if UVMDefaultFactory.m_debug_pass: if override is None: override = self.m_type_overrides[index].ovrd_type self.m_type_overrides[index].selected = 1 lindex = self.m_type_overrides[index] else: self.m_type_overrides[index].used += 1 if self.m_type_overrides[index].ovrd_type == requested_type: return requested_type else: return self.find_override_by_type(self.m_type_overrides[index].ovrd_type, full_inst_path) if UVMDefaultFactory.m_debug_pass and override is not None: lindex.used += 1 if override == requested_type: return requested_type else: return self.find_override_by_type(override,full_inst_path) return requested_type
#endfunction
[docs] def convert2string(self, all_types=True) -> str: """ tpoikela: Added this to access factory string repr without print() Args: all_types (bool): If True, adds all possible types Returns: str: Factory converted to string """ key = "" sorted_override_queues = {} # uvm_factory_queue_class s[string] qs = UVMQueue() tmp = "" id = 0 obj = None # uvm_object_wrapper obj # sort the override queues for key in self.m_inst_override_queues: obj = self.m_inst_override_queues[key] tmp = obj.get_type_name() if tmp == "": tmp = "__unnamed_id_" + str(id) id += 1 sorted_override_queues[tmp] = self.m_inst_override_queues[key] for key in self.m_inst_override_name_queues: sorted_override_queues[key] = self.m_inst_override_name_queues[key] qs.push_back("\n#### Factory Configuration (*)\n\n") # print instance overrides if len(self.m_type_overrides) == 0 and len(sorted_override_queues) == 0: qs.push_back(" No instance or type overrides are registered with this factory\n") else: max1 = 0 max2 = 0 max3 = 0 dash = "-" * 100 space = " " * 100 # print instance overrides if len(sorted_override_queues) == 0: qs.push_back("No instance overrides are registered with this factory\n") else: for key, qc in sorted_override_queues.items(): for i in range(len(qc.queue)): orig_type_name = qc.queue[i].orig_type_name full_inst_path = qc.queue[i].full_inst_path ovrd_type_name = qc.queue[i].ovrd_type_name if len(orig_type_name) > max1: max1 = len(orig_type_name) if len(full_inst_path) > max2: max2 = len(full_inst_path) if len(ovrd_type_name) > max3: max3 = len(ovrd_type_name) 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(sv.sformatf(" %0s%0s %0s%0s %0s%0s\n","Requested Type", space[1:max1-14], "Override Path", space[1:max2-13], "Override Type", space[1:max3-13])) qs.push_back(sv.sformatf(" %0s %0s %0s\n",dash[1:max1], dash[1:max2], dash[1:max3])) for key, qc in sorted_override_queues.items(): # qc = sorted_override_queues[j] for i in range(len(qc.queue)): qs.push_back(sv.sformatf(" %0s%0s %0s%0s",qc.queue[i].orig_type_name, space[1:max1-len(qc.queue[i].orig_type_name)], qc.queue[i].full_inst_path, space[1:max2-len(qc.queue[i].full_inst_path)])) qs.push_back(sv.sformatf(" %0s\n", qc.queue[i].ovrd_type_name)) # print type overrides if len(self.m_type_overrides) == 0: qs.push_back("\nNo type overrides are registered with this factory\n") else: # Resize for type overrides if max1 < 14: max1 = 14 if max2 < 13: max2 = 13 if max3 < 13: max3 = 13 for i in range(len(self.m_type_overrides)): if len(self.m_type_overrides[i].orig_type_name) > max1: max1 = len(self.m_type_overrides[i].orig_type_name) if len(self.m_type_overrides[i].ovrd_type_name) > max2: max2 = len(self.m_type_overrides[i].ovrd_type_name) if max1 < 14: max1 = 14 if max2 < 13: max2 = 13 qs.push_back("\nType Overrides:\n\n") qs.push_back(sv.sformatf(" %0s%0s %0s%0s\n","Requested Type", space[1:max1-14], "Override Type", space[1:max2-13])) qs.push_back(sv.sformatf(" %0s %0s\n",dash[1:max1], dash[1:max2])) for index in range(len(self.m_type_overrides)): qs.push_back(sv.sformatf(" %0s%0s %0s\n", self.m_type_overrides[index].orig_type_name, space[1:max1-len(self.m_type_overrides[index].orig_type_name)], self.m_type_overrides[index].ovrd_type_name)) # print all registered types, if all_types >= 1 if all_types >= 1 and self.m_type_names.has_first(): banner = False qs.push_back(sv.sformatf("\nAll types registered with the factory: %0d total\n",self.m_types.num())) key = self.m_type_names.first() while key is not None: # filter out uvm_ classes (if all_types<2) and non-types (lookup strings) if (not (all_types < 2 and uvm_is_match("uvm_*", self.m_type_names[key].get_type_name())) and key == self.m_type_names[key].get_type_name()): if not banner: qs.push_back(" Type Name\n") qs.push_back(" ---------\n") banner = True qs.push_back(sv.sformatf(" %s\n", self.m_type_names[key].get_type_name())) if self.m_type_names.has_next(): key = self.m_type_names.next() else: break # end while(self.m_type_names.next(key)) qs.push_back("(*) Types with no associated type name will be printed as <unknown>\n\n####\n\n") return UVM_STRING_QUEUE_STREAMING_PACK(qs)
[docs] def print_factory(self, all_types=True): """ print ----- Args: all_types: """ fact_str = self.convert2string(all_types) uvm_info("UVM/FACTORY/PRINT", fact_str, UVM_NONE)
# debug_create_by_name # -------------------- # TODO
[docs] def debug_create_by_name(self, requested_type_name, parent_inst_path="", name=""): self.m_debug_create(requested_type_name, None, parent_inst_path, name)
# debug_create_by_type # --------------------
[docs] def debug_create_by_type(self, requested_type, parent_inst_path="", name=""): self.m_debug_create("", requested_type, parent_inst_path, name)
# m_debug_create # -------------- # TODO
[docs] def m_debug_create(self, requested_type_name, requested_type, parent_inst_path, name): full_inst_path = self._get_inst_path(parent_inst_path, name) result = None self.m_override_info.clear() if requested_type is None: if (not self.m_type_names.exists(requested_type_name) and not self.m_lookup_strs.exists(requested_type_name)): uvm_report_warning("Factory Warning", {"The factory does not recognize '", requested_type_name,"' as a registered type."}, UVM_NONE) return UVMDefaultFactory.m_debug_pass = 1 result = self.find_override_by_name(requested_type_name,full_inst_path) else: UVMDefaultFactory.m_debug_pass = 1 if not self.m_types.exists(requested_type): self.register(requested_type) result = self.find_override_by_type(requested_type,full_inst_path) if requested_type_name == "": requested_type_name = requested_type.get_type_name() self.m_debug_display(requested_type_name, result, full_inst_path) UVMDefaultFactory.m_debug_pass = 0 for obj in self.m_override_info: obj.selected = 0
# m_debug_display # --------------- # TODO
[docs] def m_debug_display(self, requested_type_name, result, full_inst_path): pass max1 = 0 max2 = 0 max3 = 0 dash = 100 * "-" space = 100 * " " qs = [] qs.append("\n#### Factory Override Information (*)\n\n") qs.append(sv.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 len(self.m_override_info) == 0: qs.append("no relevant overrides.\n\n") else: qs.append("the following relevant overrides. " + "An 'x' next to a match indicates a\nmatch that was ignored.\n\n") for i in range(len(self.m_override_info)): if (len(self.m_override_info[i].orig_type_name) > max1): max1 = len(self.m_override_info[i].orig_type_name) if (len(self.m_override_info[i].full_inst_path) > max2): max2 = len(self.m_override_info[i].full_inst_path) if (len(self.m_override_info[i].ovrd_type_name) > max3): max3 = len(self.m_override_info[i].ovrd_type_name) if max1 < 13: max1 = 13 if max2 < 13: max2 = 13 if max3 < 13: max3 = 13 qs.append(sv.sformatf("Original Type%0s Instance Path%0s Override Type%0s\n", space[1:max1-12],space[1:max2-12],space[1:max3-12])) #space.substr(1,max1-13),space.substr(1,max2-13),space.substr(1,max3-13))) qs.append(sv.sformatf(" %0s %0s %0s\n", dash[1:max1], dash[1:max2], dash[1:max3])) for i in range(len(self.m_override_info)): orig_type_len = len(self.m_override_info[i].orig_type_name) full_inst_path_len = len(self.m_override_info[i].full_inst_path) ovrd_type_len = len(self.m_override_info[i].ovrd_type_name) is_sel_str = "x " if self.m_override_info[i].selected: is_sel_str = " " qs.append(sv.sformatf("%s%0s%0s", is_sel_str, self.m_override_info[i].orig_type_name, space[1:max1-orig_type_len])) qs.append(sv.sformatf(" %0s%0s", self.m_override_info[i].full_inst_path, space[1:max2-full_inst_path_len])) qs.append(sv.sformatf(" %0s%0s", self.m_override_info[i].ovrd_type_name, space[1:max3-ovrd_type_len])) if self.m_override_info[i].full_inst_path == "*": qs.append(" <type override>") else: qs.append("\n") qs.append("\n") qs.append("Result:\n\n") chosen_type_name = requested_type_name if result is not None: chosen_type_name = result.get_type_name() qs.append(sv.sformatf(" The factory will produce an object of type '%0s'\n", chosen_type_name)) qs.append("\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)
# Internal helper functions
[docs] def are_args_ok(self, qc_elem, requested_type, full_inst_path) -> bool: name_ok = (qc_elem.orig_type == requested_type or (qc_elem.orig_type_name != "<unknown>" and qc_elem.orig_type_name != "" and qc_elem.orig_type_name == requested_type.get_type_name())) return name_ok and uvm_is_match(qc_elem.full_inst_path, full_inst_path)
[docs] def args_are_ok_again(self, type_override, requested_type) -> bool: match_ok = (type_override.orig_type_name != "<unknown>" and type_override.orig_type_name != "" and requested_type is not None and type_override.orig_type_name == requested_type.get_type_name()) return type_override.orig_type == requested_type or match_ok
[docs]class UVMObjectWrapper: """ The UVMObjectWrapper provides an abstract interface for creating object and component proxies. Instances of these lightweight proxies, representing every `UVMObject`-based and `UVMComponent`-based object available in the test environment, are registered with the `UVMFactory`. When the factory is called upon to create an object or component, it finds and delegates the request to the appropriate proxy. """
[docs] def create_object(self, name=""): """ 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. Args: name (str): Returns: UVMObject|None """ return None
[docs] def create_component(self, name, parent): """ 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. Args: name (str): parent (UVMComponent): Parent of the created component. Returns: UVMComponent|None """ return None
[docs] def get_type_name(self): """ 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. Returns: str: Name of the type """ return "<unknown_type>"
# pytype: enable=attribute-error,not-writable