From 73a8c497b0f92c0fc9b3988e21c7a3ffd7b7278d Mon Sep 17 00:00:00 2001 From: Ray Salemi Date: Fri, 28 Jun 2024 10:20:32 -0400 Subject: [PATCH] more docstring work --- pyuvm/s13_predefined_component_classes.py | 18 +++++ pyuvm/s13_uvm_component.py | 93 ++++++++++++++++++----- 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/pyuvm/s13_predefined_component_classes.py b/pyuvm/s13_predefined_component_classes.py index 41d3901..e6a9c62 100644 --- a/pyuvm/s13_predefined_component_classes.py +++ b/pyuvm/s13_predefined_component_classes.py @@ -56,6 +56,14 @@ class uvm_agent(uvm_component): """ def build_phase(self): + """ + This ``build_phase()`` implements agent-specific behavior. + * It sets the agent's ``is_active`` property to ``UVM_ACTIVE`` + * It allows the user to override the ``is_active`` property using + the ``cdb_get()`` method. + * It logs a warning if the user sets an illegal value for + ``is_active`` and sets the value to ``UVM_ACTIVE``. + """ super().build_phase() self.is_active = uvm_active_passive_enum.UVM_ACTIVE try: @@ -108,6 +116,13 @@ def __init__(self, name, parent, write_fn): self.write_fn = write_fn def write(self, tt): + """ + Write a transaction to all the connected subscribers. + + :param tt: The transaction to write + :return: None + + """ self.write_fn(tt) def __init__(self, name, parent): @@ -117,6 +132,9 @@ def __init__(self, name, parent): self.write) def write(self, tt): + """ + Force the user to implement the write method. + """ raise error_classes.UVMFatalError( "You must override the write() method in" f"uvm_subscriber {self.get_full_name()}") diff --git a/pyuvm/s13_uvm_component.py b/pyuvm/s13_uvm_component.py index c2bf60b..0a1e392 100644 --- a/pyuvm/s13_uvm_component.py +++ b/pyuvm/s13_uvm_component.py @@ -22,6 +22,9 @@ def __init__(self, name, parent): """ 13.1.2.1---This is new() in the IEEE-UVM, but we mean the same thing with __init__() + + :param name: The name of the component. Used in the UVM hierarchy + :param parent: The parent component. If None, the parent is uvm_root """ self._children = {} @@ -38,9 +41,15 @@ def __init__(self, name, parent): uvm_component.component_dict[self.get_full_name()] = self def clear_children(self): + """ + Removes the direct children from this component. + """ self._children = {} def clear_hierarchy(self): + """ + Removes self from the UVM hierarchy + """ self._parent = None self.clear_children() @@ -63,14 +72,20 @@ def get_parent(self): """ :return: parent object - 13.1.3.1--- No "get" prefix + 13.1.3.1 """ return self._parent def raise_objection(self): + """ + Raise an objection, usually at the start of the ``run_phase()`` + """ utility_classes.ObjectionHandler().raise_objection(self) def drop_objection(self): + """ + Drop an objection, usually at the end of the ``run_phase()`` + """ utility_classes.ObjectionHandler().drop_objection(self) def objection(self): @@ -88,7 +103,8 @@ def __exit__(self, *args): def cdb_set(self, label, value, inst_path="*"): """ - Store an object in the config_db. + A convenience routing to store an object in the config_db using + this component's ``get_full_name()`` path. :param value: The object to store :param label: The label to use to retrieve it @@ -100,8 +116,9 @@ def cdb_set(self, label, value, inst_path="*"): def cdb_get(self, label, inst_path=""): """ - Retrieve an object from the config_db using this components - get_full_name() path. Can find objects stored with wildcards + A convenience routine that retrieves an object from + the config_db using this component's + ``get_full_name()`` path. Can find objects stored with wildcards :param inst_path: The path below this component :param label: The label used to store the value @@ -125,7 +142,7 @@ def parent(self, parent): def get_full_name(self): """ - :return: Name concatenated to parent name. + :return: This component's name concatenated to parent name. 13.1.3.2 """ @@ -165,7 +182,7 @@ def get_full_name(self): def get_children(self): """ 13.1.3.3 - :return: dict with children + :return: A dict containing children objects """ return list(self.children) @@ -180,7 +197,8 @@ def hierarchy(self): """ We return a generator to find the children. This is more pythonic and saves memory for large hierarchies. - :return: An ordered list of components top to bottom. + + :return: A generator that returns the children. """ yield self for child in self.children: @@ -205,7 +223,8 @@ def children(self): """ 13.1.3.4 Implements the intention of this requirement - without the approach taken in the UVM + without the approach taken in the UVM We use a + generator instead. """ for child in self._children: yield self._children[child] @@ -217,8 +236,8 @@ def get_child(self, name): """ 13.1.3.4 :param self: - :param name: child string - :return: uvm_component of that name + :param name: child's name + :return: child ``uvm_component`` of that name """ assert (isinstance(name, str)) try: @@ -230,16 +249,17 @@ def get_num_children(self): """ 13.1.3.5 :param self: - :return: Number of children in component + :return: The number of children in component + """ return len(self._children) def has_child(self, name): """ 13.1.3.6 - :param self: - :param name: Name of child object + :param name: Name of child the object :return: True if exists, False otherwise + """ assert (isinstance(name, str)) return name in self._children @@ -249,8 +269,10 @@ def lookup(self, name): 13.1.3.7 Return a component base on the path. If . then use full name from root otherwise relative + :param name: The search name :return: either the component or None + """ assert (isinstance(name, str)) if name[0] == '.': @@ -266,8 +288,8 @@ def get_depth(self): """ 13.1.3.8 Get the depth that I am from the top component. uvm_root is 0. - :param self: That's me - :return: depth + + :return: The hierarchy depth from me to the bottom. """ # Rather than getting all recursive just count # levels in the full name. @@ -282,8 +304,10 @@ def set_logging_level_hier(self, logging_level): """ Set the logging level for this component's logger and all the way down the hierarchy + :param logging_level: typically a constant from logging module :return: None + """ self.set_logging_level(logging_level) for child in self.children: @@ -292,6 +316,7 @@ def set_logging_level_hier(self, logging_level): def add_logging_handler_hier(self, handler): """ Add an additional handler all the way down the component hierarchy + :param handler: A logging.Handler object :return: None """ @@ -304,6 +329,7 @@ def add_logging_handler_hier(self, handler): def remove_logging_handler_hier(self, handler): """ Remove a handler from all loggers below this component + :param handler: logging handler :return: None """ @@ -314,11 +340,18 @@ def remove_logging_handler_hier(self, handler): child.remove_logging_handler_hier(handler) def remove_streaming_handler_hier(self): + """ + Remove this component's streaming handler and all the way down + the hierarchy + """ self.remove_streaming_handler() for child in self.children: child.remove_streaming_handler_hier() def disable_logging_hier(self): + """ + Disable logging for this component and all the way down the hierarchy + """ self.disable_logging() for child in self.children: child.disable_logging_hier() @@ -367,20 +400,20 @@ def final_phase(self): # 13.2 (rest of 13.2 is in s13_predefined_components) class uvm_test(uvm_component): """ - The base class for all tests + The base class for all tests """ class uvm_root(uvm_component, metaclass=utility_classes.UVM_ROOT_Singleton): """ - F.7. We do not use uvm_pkg to hold uvm_root. Instead it + F.7. We do not use ``uvm_pkg`` to hold ``uvm_root``. Instead it is a class variable of uvm_component. This avoids circular reference issues regarding uvm_pkg. Plus, it's cleaner. - uvm_root is still a singleton that you access through its - constructor instead of through a get() method. + ``uvm_root`` is still a singleton that you access through its + constructor instead of through a ``get()`` method. Much of the functionality in Annex F delivers functionality in SystemVerilog that is already built into Python. So we're @@ -389,6 +422,9 @@ class uvm_root(uvm_component, metaclass=utility_classes.UVM_ROOT_Singleton): @classmethod def clear_singletons(cls, keep_set={}): + """ + Clear the singletons in the system. This is used for testing + """ keepers = {uvm_factory, utility_classes.FactoryData}.union(keep_set) utility_classes.Singleton.clear_singletons(keep=keepers) @@ -416,7 +452,7 @@ async def run_test(self, test_name, :param test_name: The uvm test name or test class :param keep_singletons: If True do not clear singletons (default False) :param keep_set: Set of singleton classes to keep - if keep_singletons is False + if keep_singletons is False. Pass a list of singletons to `set()` :return: none """ factory = uvm_factory() @@ -498,9 +534,11 @@ def clear(self): def _get_context_inst_name(context, inst_name): """ Get the config_key from context and passed inst_name + :param context: uvm_component or None :param inst_name: string that can be a glob :return: string that is the key + """ assert context is None or isinstance(context, uvm_component), \ "config_db context must be None or a uvm_component. " @@ -515,6 +553,9 @@ def _get_context_inst_name(context, inst_name): return context, inst_name def trace(self, method, context, inst_name, field_name, value): + """ + Output the ConfigDB activity if tracing is on. + """ if self.is_tracing: # noinspection SpellCheckingInspection self.logger_holder.logger.info(f"CFGDB/{method} Context: {context} -- {inst_name} {field_name}={value}") # noqa: E501 @@ -524,11 +565,13 @@ def set(self, context, inst_name, field_name, value): Stores an object in the db using the context and inst_name to create a retrieval path, and the key name. + :param context: A handle to a component :param inst_name: The instance name within the component :param field_name: The key we're setting :param value: The object to be stored :return: None + """ if not set(field_name).issubset(self.legal_chars): @@ -557,14 +600,17 @@ def get(self, context, inst_name, field_name, default=default_get): The component path matches against the paths in the ConfigDB. The path cannot have wildcards, but can match against keys with wildcards. Return the value stored at key. If the key is missing, returns default - or raises UVMConfigItemNotFound. + or raises ``UVMConfigItemNotFound``. :param context: The component making the call :param inst_name: component full path with no wildcards :param field_name: the field_name being retrieved :param default: the value to return if there is no key, defaults to default_get + :raises UVMConfigItemNotFound: if the key is not found and the + default is not set :return: value found at location + """ if not set(inst_name).issubset(self.legal_chars): raise error_classes.UVMError( @@ -635,10 +681,12 @@ def get(self, context, inst_name, field_name, default=default_get): def exists(self, context, inst_name, field_name): """ Returns true if there is data in the database at this location + :param context: None or uvm_component :param inst_name: instance name string in context :param field_name: key name for location :return: True if exists + """ try: _ = self.get(context, inst_name, field_name) @@ -647,6 +695,9 @@ def exists(self, context, inst_name, field_name): return True def wait_modified(self): + """ + :raises UVMNotImplemented: This is not implemented in pyuvm + """ raise error_classes.UVMNotImplemented( "wait_modified not implemented pending requests for it.")