from typing import Tuple, List, Dict, Union, Optional, Generator
from hwt.doc_markers import internal
from hwt.hdl.const import HConst
from hwt.hdl.constUtils import isSameHConst, areSameHConsts
from hwt.hdl.operatorUtils import replace_input_in_expr
from hwt.hdl.sensitivityCtx import SensitivityCtx
from hwt.hdl.statements.statement import HdlStatement, SignalReplaceSpecType
from hwt.hdl.statements.utils.listOfHdlStatements import ListOfHdlStatement
from hwt.mainBases import RtlSignalBase
from hwt.pyUtils.setList import SetList
from hwt.pyUtils.typingFuture import override
[docs]
class HdlAssignmentContainer(HdlStatement):
"""
Assignment container
:ivar ~.src: source
:ivar ~.dst: destination signal
:ivar ~.indexes: description of index selector on dst
(list of Index/Slice objects) (f.e. [0, 1] means dst[0][1])
:cvar __instCntr: counter used for generating instance ids
:ivar ~._instId: internally used only for intuitive sorting of statements
"""
_DEEPCOPY_SKIP = (*HdlStatement._DEEPCOPY_SKIP, 'src', 'dst', 'indexes')
_DEEPCOPY_SHALLOW_ONLY = (*HdlStatement._DEEPCOPY_SHALLOW_ONLY, "indexes")
__instCntr = 0
[docs]
def __init__(self, src: Union[RtlSignalBase, HConst], dst: RtlSignalBase,
indexes: Optional[List[Union[RtlSignalBase, HConst]]]=None,
virtual_only=False,
parentStm: Optional[HdlStatement]=None,
parentStmList: Optional[ListOfHdlStatement]=None,
sensitivity: Optional[SetList]=None,
event_dependent_from_branch:Optional[int]=None):
"""
:param dst: destination to assign to
:param src: source which is assigned from
:param indexes: description of index selector on dst
(list of Index/Slice objects) (f.e. [[0], [1]] means dst[0][1])
:param virtual_only: flag indicates that this assignments
is only virtual and should not be added into
netlist, because it is only for internal notation
"""
super(HdlAssignmentContainer, self).__init__(
parentStm,
parentStmList,
sensitivity,
event_dependent_from_branch=event_dependent_from_branch)
self._instId = HdlAssignmentContainer._nextInstId()
self.src = src
self.dst = dst
assert isinstance(dst, RtlSignalBase), dst
self.indexes = indexes
self._collect_inputs()
if not virtual_only:
for i in self._inputs:
i._rtlEndpoints.append(self)
dst._rtlDrivers.append(self)
dst._rtlCtx.statements.add(self)
self._outputs.append(dst)
@override
def __deepcopy__(self, memo: dict):
result = super(HdlAssignmentContainer, self).__deepcopy__(memo)
result.src = self.src
result.dst = self.dst
result._instId = self._nextInstId()
return result
[docs]
@internal
@override
def _cut_off_drivers_of(self, sig: RtlSignalBase):
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._cut_off_drivers_of`
"""
if self._try_cut_off_whole_stm(sig):
return self
[docs]
@internal
@override
def _discover_enclosure(self) -> None:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._discover_enclosure`
"""
assert self._enclosed_for is None
self._enclosed_for = set()
self._enclosed_for.update(self._outputs)
[docs]
@internal
@override
def _discover_sensitivity(self, seen: set) -> None:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._discover_sensitivity`
"""
assert self._sensitivity is None
ctx = self._sensitivity = SensitivityCtx()
casualSensitivity = set()
for inp in self._inputs:
if inp not in seen:
seen.add(inp)
inp._walk_sensitivity(casualSensitivity, seen, ctx)
ctx.extend(casualSensitivity)
[docs]
@internal
@override
def _fill_enclosure(self, enclosure: Dict[RtlSignalBase, HdlStatement]):
"""
The assignment does not have any uncovered code branches
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._fill_enclosure`
"""
pass
[docs]
@internal
@override
def _iter_stms(self) -> Generator[HdlStatement, None, None]:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._iter_stms`
"""
return
yield
[docs]
@internal
@override
def _iter_stms_for_output(self, output: RtlSignalBase) -> Generator[HdlStatement, None, None]:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._iter_stms_for_output`
"""
return
yield
[docs]
@internal
@override
def _on_parent_event_dependent(self):
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._on_parent_event_dependent`
"""
self._event_dependent_from_branch = 0
[docs]
@internal
@override
def _try_reduce(self) -> Tuple[ListOfHdlStatement, bool]:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._try_reduce`
"""
return ListOfHdlStatement((self,)), False
[docs]
@internal
@override
def _is_mergable(self, other: HdlStatement) -> bool:
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement._is_mergable`
"""
return isinstance(other, self.__class__)
[docs]
@override
def isSame(self, other):
"""
:see: :meth:`hwt.hdl.statements.statement.HdlStatement.isSame`
"""
if isinstance(other, self.__class__):
if isSameHConst(self.dst, other.dst)\
and isSameHConst(self.src, other.src)\
and areSameHConsts(self.indexes, other.indexes):
return True
return False
[docs]
@internal
@override
@classmethod
def _nextInstId(cls):
"""
Get next instance id
"""
i = cls.__instCntr
cls.__instCntr += 1
return i