Source code for hwt.synthesizer.componentPath

from copy import deepcopy

from hwt.synthesizer.interface import Interface
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal
from hwt.synthesizer.unit import Unit


[docs]def to_tuple_of_names(objs): res = [] for o in objs: if isinstance(o, RtlSignal): name = o.name elif hasattr(o, "_name"): name = o._name else: name = repr(o) res.append(name) return tuple(res)
[docs]class ComponentPath(tuple): def __new__ (cls, *objs): return super(ComponentPath, cls).__new__(cls, objs) def __truediv__(self, other): if isinstance(other, ComponentPath): return ComponentPath(*self, *other) else: return ComponentPath(*self, other)
[docs] def resolve(self) -> "ComponentPath": """ Make the path absolute The ComponentPath is in absolute format only if: * The first member is a top component or path is empty * All members except the last are :class:`hwt.synthesizer.unit.Unit` instances (last can be RtlSignal/Interface) * Each successor member is instantiated in predecessor except for :class:`hwt.synthesizer.unit.Unit` instance with shared component * If member is a :class:`hwt.synthesizer.unit.Unit` instance with shared component the successor must be an interface of this instance or an object from shared component """ it = iter(reversed(self)) try: obj = next(it) except StopIteration: # empty path return self path = [] while obj is not None: _handle = next(it, None) if isinstance(_handle, Unit) and _handle._shared_component_with is not None: handle, _, _ = _handle._shared_component_with else: handle = _handle if obj is not handle: if isinstance(obj, RtlSignal): # to not modify path if it is already in absolute format if not path or path[-1] is not obj: path.append(obj) obj = obj.ctx.parent while isinstance(obj, Interface): if not path: path.append(obj) if obj is handle: break obj = obj._parent while obj is not handle: assert isinstance(obj, Unit), obj # to not modify path if it is already in absolute format if not path or path[-1] is not obj: path.append(obj) obj = obj._parent obj = _handle return ComponentPath(*reversed(path))
[docs] def is_absolute(self): """ :return: True if path starts with a top component else False """ u = self[0] return isinstance(u, Unit) and u._parent is None
[docs] def update_prefix(self, old_path_prefix: "ComponentPath", new_path_prefix: "ComponentPath"): """ Update prefix of the path tuple """ assert len(self) >= len(old_path_prefix), (self, old_path_prefix) for p, op in zip(self, old_path_prefix): assert p is op, (self, old_path_prefix) return ComponentPath(*new_path_prefix, *self[len(old_path_prefix):])
def __getitem__(self, key): if isinstance(key, slice): return self.__class__(*tuple.__getitem__(self, key)) else: return tuple.__getitem__(self, key) def __repr__(self): return f"<{self.__class__.__name__:s} {str(self):s}>" def __str__(self): return "/".join(to_tuple_of_names(self)) def __copy__(self): return self.__class__(*self) def __deepcopy__(self, memo): res = self.__class__(*(deepcopy(x, memo) for x in self)) memo[self] = res return res