Skip to content

Commit

Permalink
more docstring work
Browse files Browse the repository at this point in the history
  • Loading branch information
raysalemi committed Jun 28, 2024
1 parent 0b7001f commit 73a8c49
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 21 deletions.
18 changes: 18 additions & 0 deletions pyuvm/s13_predefined_component_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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):
Expand All @@ -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()}")
93 changes: 72 additions & 21 deletions pyuvm/s13_uvm_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand All @@ -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()

Expand All @@ -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):
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
"""
Expand Down Expand Up @@ -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)

Expand All @@ -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:
Expand All @@ -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]
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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] == '.':
Expand All @@ -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.
Expand All @@ -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:
Expand All @@ -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
"""
Expand All @@ -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
"""
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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. "
Expand All @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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)
Expand All @@ -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.")

Expand Down

0 comments on commit 73a8c49

Please sign in to comment.