@internal<EOL><INDENT>def _cut_off_drivers_of(self, sig: RtlSignalBase):<DEDENT>

if len(self._outputs) == <NUM_LIT:1> and sig in self._outputs:<EOL><INDENT>self.parentStm = None<EOL>return self<EOL><DEDENT>child_keep_mask = []<EOL>newIfTrue = []<EOL>all_cut_off = True<EOL>all_cut_off &= self._cut_off_drivers_of_list(<EOL>sig, self.ifTrue, child_keep_mask, newIfTrue)<EOL>self.ifTrue = list(compress(self.ifTrue, child_keep_mask))<EOL>newElifs = []<EOL>anyElifHit = False<EOL>for cond, stms in self.elIfs:<EOL><INDENT>newCase = []<EOL>child_keep_mask.clear()<EOL>all_cut_off &= self._cut_off_drivers_of_list(<EOL>sig, stms, child_keep_mask, newCase)<EOL>_stms = list(compress(stms, child_keep_mask))<EOL>stms.clear()<EOL>stms.extend(_stms)<EOL>if newCase:<EOL><INDENT>anyElifHit = True<EOL><DEDENT>newElifs.append((cond, newCase))<EOL><DEDENT>newIfFalse = None<EOL>if self.ifFalse:<EOL><INDENT>newIfFalse = []<EOL>child_keep_mask.clear()<EOL>all_cut_off &= self._cut_off_drivers_of_list(<EOL>sig, self.ifFalse, child_keep_mask, newIfFalse)<EOL>self.ifFalse = list(compress(self.ifFalse, child_keep_mask))<EOL><DEDENT>assert not all_cut_off, "<STR_LIT>"<EOL>if newIfTrue or newIfFalse or anyElifHit or newIfFalse:<EOL><INDENT>cond_sig = self.cond<EOL>n = self.__class__(cond_sig, newIfTrue)<EOL>for c, stms in newElifs:<EOL><INDENT>assert len(c) == <NUM_LIT:1><EOL>c_sig = c[<NUM_LIT:0>]<EOL>n.Elif(c_sig, stms)<EOL><DEDENT>if newIfFalse is not None:<EOL><INDENT>n.Else(newIfFalse)<EOL><DEDENT>if self.parentStm is None:<EOL><INDENT>ctx = n._get_rtl_context()<EOL>ctx.statements.add(n)<EOL><DEDENT>self._inputs.clear()<EOL>self._inputs.append(cond_sig)<EOL>for c, _ in self.elIfs:<EOL><INDENT>self._inputs.extend(c)<EOL><DEDENT>self._inputs.append(cond_sig)<EOL>self._outputs.clear()<EOL>out_add = self._outputs.append<EOL>in_add = self._inputs.append<EOL>for stm in self._iter_stms():<EOL><INDENT>for inp in stm._inputs:<EOL><INDENT>in_add(inp)<EOL><DEDENT>for outp in stm._outputs:<EOL><INDENT>out_add(outp)<EOL><DEDENT><DEDENT>if self._sensitivity is not None or self._enclosed_for is not None:<EOL><INDENT>raise NotImplementedError(<EOL>"<STR_LIT>")<EOL><DEDENT>return n<EOL><DEDENT>

Doc on parent class :meth:`HdlStatement._cut_off_drivers_of`


outputs = self._outputs<EOL>self._ifTrue_enclosed_for = self._discover_enclosure_for_statements(<EOL>self.ifTrue, outputs)<EOL>elif_encls = self._elIfs_enclosed_for = []<EOL>for _, stms in self.elIfs:<EOL><INDENT>e = self._discover_enclosure_for_statements(<EOL>stms, outputs)<EOL>elif_encls.append(e)<EOL><DEDENT>self._ifFalse_enclosed_for = self._discover_enclosure_for_statements(<EOL>self.ifFalse, outputs)<EOL>assert self._enclosed_for is None<EOL>encl = self._enclosed_for = set()<EOL>for s in self._ifTrue_enclosed_for:<EOL><INDENT>enclosed = True<EOL>for elif_e in elif_encls:<EOL><INDENT>if s not in elif_e:<EOL><INDENT>enclosed = False<EOL>break<EOL><DEDENT><DEDENT>if enclosed and s in self._ifFalse_enclosed_for:<EOL><INDENT>encl.add(s)<EOL><DEDENT><DEDENT>

Doc on parent class :meth:`HdlStatement._discover_enclosure`


@internal<EOL><INDENT>def _discover_sensitivity(self, seen: set) -> None:<DEDENT>

assert self._sensitivity is None, self<EOL>ctx = self._sensitivity = SensitivityCtx()<EOL>self._discover_sensitivity_sig(self.cond, seen, ctx)<EOL>if ctx.contains_ev_dependency:<EOL><INDENT>return<EOL><DEDENT>for stm in self.ifTrue:<EOL><INDENT>stm._discover_sensitivity(seen)<EOL>ctx.extend(stm._sensitivity)<EOL><DEDENT>for cond, stms in self.elIfs:<EOL><INDENT>if ctx.contains_ev_dependency:<EOL><INDENT>break<EOL><DEDENT>self._discover_sensitivity_sig(cond, seen, ctx)<EOL>if ctx.contains_ev_dependency:<EOL><INDENT>break<EOL><DEDENT>for stm in stms:<EOL><INDENT>if ctx.contains_ev_dependency:<EOL><INDENT>break<EOL><DEDENT>stm._discover_sensitivity(seen)<EOL>ctx.extend(stm._sensitivity)<EOL><DEDENT><DEDENT>if not ctx.contains_ev_dependency and self.ifFalse:<EOL><INDENT>for stm in self.ifFalse:<EOL><INDENT>stm._discover_sensitivity(seen)<EOL>ctx.extend(stm._sensitivity)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>assert not self.ifFalse, "<STR_LIT>"<EOL><DEDENT>

Doc on parent class :meth:`HdlStatement._discover_sensitivity`


yield from self.ifTrue<EOL>for _, stms in self.elIfs:<EOL><INDENT>yield from stms<EOL><DEDENT>if self.ifFalse is not None:<EOL><INDENT>yield from self.ifFalse<EOL><DEDENT>

Doc on parent class :meth:`HdlStatement._iter_stms`


@internal<EOL><INDENT>def _try_reduce(self) -> Tuple[bool, List[HdlStatement]]:<DEDENT>

<EOL>io_change = False<EOL>self.ifTrue, rank_decrease, _io_change = self._try_reduce_list(<EOL>self.ifTrue)<EOL>self.rank -= rank_decrease<EOL>io_change |= _io_change<EOL>new_elifs = []<EOL>for cond, statements in self.elIfs:<EOL><INDENT>_statements, rank_decrease, _io_change = self._try_reduce_list(<EOL>statements)<EOL>self.rank -= rank_decrease<EOL>io_change |= _io_change<EOL>new_elifs.append((cond, _statements))<EOL><DEDENT>if self.ifFalse is not None:<EOL><INDENT>self.ifFalse, rank_decrease, _io_update_required = self._try_reduce_list(<EOL>self.ifFalse)<EOL>self.rank -= rank_decrease<EOL>io_change |= _io_change<EOL><DEDENT>reduce_self = not self.condHasEffect(<EOL>self.ifTrue, self.ifFalse, self.elIfs)<EOL>if reduce_self:<EOL><INDENT>res = self.ifTrue<EOL><DEDENT>else:<EOL><INDENT>res = [self, ]<EOL><DEDENT>self._on_reduce(reduce_self, io_change, res)<EOL>if self.ifFalse is not None and len(self.ifFalse) == <NUM_LIT:1>:<EOL><INDENT>child = self.ifFalse[<NUM_LIT:0>]<EOL>if isinstance(child, IfContainer):<EOL><INDENT>self._merge_nested_if_from_else(child)<EOL><DEDENT><DEDENT>return res, io_change<EOL>

Doc on parent class :meth:`HdlStatement._try_reduce`


@internal<EOL><INDENT>def _merge_nested_if_from_else(self, ifStm: "<STR_LIT>"):<DEDENT>

self.elIfs.append((ifStm.cond, ifStm.ifTrue))<EOL>self.elIfs.extend(ifStm.elIfs)<EOL>self.ifFalse = ifStm.ifFalse<EOL>

Merge nested IfContarner form else branch to this IfContainer
as elif and else branches


@internal<EOL><INDENT>def _merge_with_other_stm(self, other: "<STR_LIT>") -> None:<DEDENT>

merge = self._merge_statement_lists<EOL>self.ifTrue = merge(self.ifTrue, other.ifTrue)<EOL>new_elifs = []<EOL>for ((c, elifA), (_, elifB)) in zip(self.elIfs, other.elIfs):<EOL><INDENT>new_elifs.append((c,  merge(elifA, elifB)))<EOL><DEDENT>self.elIfs = new_elifs<EOL>self.ifFalse = merge(self.ifFalse, other.ifFalse)<EOL>other.ifTrue = []<EOL>other.elIfs = []<EOL>other.ifFalse = None<EOL>self._on_merge(other)<EOL>

:attention: statements has to be mergable (to check use _is_mergable method)


def isSame(self, other: HdlStatement) -> bool:

if self is other:<EOL><INDENT>return True<EOL><DEDENT>if self.rank != other.rank:<EOL><INDENT>return False<EOL><DEDENT>if isinstance(other, IfContainer):<EOL><INDENT>if self.cond is other.cond:<EOL><INDENT>if len(self.ifTrue) == len(other.ifTrue)and len(self.ifFalse) == len(other.ifFalse)and len(self.elIfs) == len(other.elIfs):<EOL><INDENT>if not isSameStatementList(self.ifTrue,<EOL>other.ifTrue)or not isSameStatementList(self.ifFalse,<EOL>other.ifFalse):<EOL><INDENT>return False<EOL><DEDENT>for (ac, astms), (bc, bstms) in zip(self.elIfs,<EOL>other.elIfs):<EOL><INDENT>if not (ac == bc) ornot isSameStatementList(astms, bstms):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL><DEDENT><DEDENT><DEDENT>return False<EOL>

:return: True if other has same meaning as this statement


def __init__(self, src, dst, indexes=None, virtualOnly=False,<EOL>parentStm=None,<EOL>sensitivity=None,<EOL>is_completly_event_dependent=False):

super(Assignment, self).__init__(<EOL>parentStm,<EOL>sensitivity,<EOL>is_completly_event_dependent)<EOL>self.src = src<EOL>isReal = not virtualOnly<EOL>if not isinstance(src, Value):<EOL><INDENT>self._inputs.append(src)<EOL>if isReal:<EOL><INDENT>src.endpoints.append(self)<EOL><DEDENT><DEDENT>self.dst = dst<EOL>if not isinstance(dst, Value):<EOL><INDENT>self._outputs.append(dst)<EOL>if isReal:<EOL><INDENT>dst.drivers.append(self)<EOL><DEDENT><DEDENT>self.indexes = indexes<EOL>if indexes:<EOL><INDENT>for i in indexes:<EOL><INDENT>if not isinstance(i, Value):<EOL><INDENT>self._inputs.append(i)<EOL>if isReal:<EOL><INDENT>i.endpoints.append(self)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>self._instId = Assignment._nextInstId()<EOL>if not virtualOnly:<EOL><INDENT>dst.ctx.statements.add(self)<EOL><DEDENT>

: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 virtualOnly: flag indicates that this assignments
    is only virtual and should not be added into
    netlist, because it is only for internal notation


if self.dst is sig:<EOL><INDENT>self.parentStm = None<EOL>return self<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

Cut off statements which are driver of specified signal


@internal<EOL><INDENT>def _fill_enclosure(self, enclosure: Dict[RtlSignalBase, HdlStatement]):<DEDENT>

pass<EOL>


return<EOL>yield<EOL>

Iterate all statements in this statement


if not self._is_completly_event_dependent:<EOL><INDENT>self._is_completly_event_dependent = True<EOL><DEDENT>

After parrent statement become event dependent


i = cls.__instCntr<EOL>cls.__instCntr += <NUM_LIT:1><EOL>return i<EOL>


self.dst._val = self.src.staticEval()<EOL>


def __call__(self, prop: Union[str, int]):

self.nextProp = prop<EOL>return self<EOL>

Prepare to enter child property or item in sequence

:prop: str if entering a property, int if entering an item of sequence


prop = self.nextProp<EOL>self.nextProp = None<EOL>a = self.actual<EOL>if isinstance(prop, int):<EOL><INDENT>child = a[prop]<EOL><DEDENT>else:<EOL><INDENT>child = getattr(a, prop)<EOL><DEDENT>self.parents.append(a)<EOL>self.onParentNames.append(prop)<EOL>self.actual = child<EOL>return self<EOL>

Enter child property or item in sequence


def __exit__(self, exc_type, exc_val, exc_tb):

self.actual = self.parents.pop()<EOL>self.onParentNames.pop()<EOL>


@internal<EOL><INDENT>def _loadFromArray(self, dtype: HdlType, bitAddr: int) -> int:<DEDENT>

self.itemCnt = evalParam(dtype.size).val<EOL>self.children = TransTmpl(<EOL>dtype.elmType, <NUM_LIT:0>, parent=self, origin=self.origin)<EOL>return bitAddr + self.itemCnt * self.children.bitAddrEnd<EOL>

Parse HArray type to this transaction template instance

:return: address of it's end


@internal<EOL><INDENT>def _loadFromBits(self, dtype: HdlType, bitAddr: int):<DEDENT>

return bitAddr + dtype.bit_length()<EOL>

Parse Bits type to this transaction template instance

:return: address of it's end


@internal<EOL><INDENT>def _loadFromHStruct(self, dtype: HdlType, bitAddr: int):<DEDENT>

for f in dtype.fields:<EOL><INDENT>t = f.dtype<EOL>origin = f<EOL>isPadding = f.name is None<EOL>if isPadding:<EOL><INDENT>width = t.bit_length()<EOL>bitAddr += width<EOL><DEDENT>else:<EOL><INDENT>fi = TransTmpl(t, bitAddr, parent=self, origin=origin)<EOL>self.children.append(fi)<EOL>bitAddr = fi.bitAddrEnd<EOL><DEDENT><DEDENT>return bitAddr<EOL>

Parse HStruct type to this transaction template instance

:return: address of it's end


@internal<EOL><INDENT>def _loadFromUnion(self, dtype: HdlType, bitAddr: int) -> int:<DEDENT>

for field in dtype.fields.values():<EOL><INDENT>ch = TransTmpl(field.dtype, <NUM_LIT:0>, parent=self, origin=field)<EOL>self.children.append(ch)<EOL><DEDENT>return bitAddr + dtype.bit_length()<EOL>

Parse HUnion type to this transaction template instance

:return: address of it's end


@internal<EOL><INDENT>def _loadFromHStream(self, dtype: HStream, bitAddr: int) -> int:<DEDENT>

ch = TransTmpl(dtype.elmType, <NUM_LIT:0>, parent=self, origin=self.origin)<EOL>self.children.append(ch)<EOL>return bitAddr + dtype.elmType.bit_length()<EOL>


def _loadFromHType(self, dtype: HdlType, bitAddr: int) -> None:

self.bitAddr = bitAddr<EOL>childrenAreChoice = False<EOL>if isinstance(dtype, Bits):<EOL><INDENT>ld = self._loadFromBits<EOL><DEDENT>elif isinstance(dtype, HStruct):<EOL><INDENT>ld = self._loadFromHStruct<EOL><DEDENT>elif isinstance(dtype, HArray):<EOL><INDENT>ld = self._loadFromArray<EOL><DEDENT>elif isinstance(dtype, HStream):<EOL><INDENT>ld = self._loadFromHStream<EOL><DEDENT>elif isinstance(dtype, HUnion):<EOL><INDENT>ld = self._loadFromUnion<EOL>childrenAreChoice = True<EOL><DEDENT>else:<EOL><INDENT>raise TypeError("<STR_LIT>", dtype)<EOL><DEDENT>self.bitAddrEnd = ld(dtype, bitAddr)<EOL>self.childrenAreChoice = childrenAreChoice<EOL>

Parse any HDL type to this transaction template instance


if not isinstance(self.dtype, HArray):<EOL><INDENT>raise TypeError()<EOL><DEDENT>return (self.bitAddrEnd - self.bitAddr) // self.itemCnt<EOL>

Only for transactions derived from HArray

:return: width of item in original array


return self.bitAddrEnd - self.bitAddr<EOL>

:return: number of bits in this transaction


def walkFlatten(self, offset: int=<NUM_LIT:0>,<EOL>shouldEnterFn=_default_shouldEnterFn,<EOL>otherObjItCtx: ObjIteratorCtx =_DummyIteratorCtx()<EOL>) -> Generator[<EOL>Union[Tuple[Tuple[int, int], '<STR_LIT>'], '<STR_LIT>'],<EOL>None, None]:

t = self.dtype<EOL>base = self.bitAddr + offset<EOL>end = self.bitAddrEnd + offset<EOL>shouldEnter, shouldYield = shouldEnterFn(self)<EOL>if shouldYield:<EOL><INDENT>yield ((base, end), self)<EOL><DEDENT>if shouldEnter:<EOL><INDENT>if isinstance(t, Bits):<EOL><INDENT>pass<EOL><DEDENT>elif isinstance(t, HStruct):<EOL><INDENT>for ch in self.children:<EOL><INDENT>with otherObjItCtx(ch.origin.name):<EOL><INDENT>yield from ch.walkFlatten(<EOL>offset,<EOL>shouldEnterFn,<EOL>otherObjItCtx)<EOL><DEDENT><DEDENT><DEDENT>elif isinstance(t, HArray):<EOL><INDENT>itemSize = (self.bitAddrEnd - self.bitAddr) // self.itemCnt<EOL>for i in range(self.itemCnt):<EOL><INDENT>with otherObjItCtx(i):<EOL><INDENT>yield from self.children.walkFlatten(<EOL>base + i * itemSize,<EOL>shouldEnterFn,<EOL>otherObjItCtx)<EOL><DEDENT><DEDENT><DEDENT>elif isinstance(t, HUnion):<EOL><INDENT>yield OneOfTransaction(self, offset, shouldEnterFn,<EOL>self.children)<EOL><DEDENT>elif isinstance(t, HStream):<EOL><INDENT>assert len(self.children) == <NUM_LIT:1><EOL>yield StreamTransaction(self, offset, shouldEnterFn,<EOL>self.children[<NUM_LIT:0>])<EOL><DEDENT>else:<EOL><INDENT>raise TypeError(t)<EOL><DEDENT><DEDENT>

Walk fields in instance of TransTmpl

:param offset: optional offset for all children in this TransTmpl
:param shouldEnterFn: function (transTmpl) which returns True
    when field should be split on it's children
:param shouldEnterFn: function(transTmpl) which should return
    (shouldEnter, shouldUse) where shouldEnter is flag that means
    iterator should look inside of this actual object
    and shouldUse flag means that this field should be used
    (=generator should yield it)
:return: generator of tuples ((startBitAddress, endBitAddress),
    TransTmpl instance)


def walkFlattenChilds(self) -> Generator[<EOL>Union[Tuple[Tuple[int, int], TransTmpl], '<STR_LIT>'],<EOL>None, None]:

for p in self.possibleTransactions:<EOL><INDENT>yield p.walkFlatten(offset=self.offset,<EOL>shouldEnterFn=self.shouldEnterFn)<EOL><DEDENT>

:return: generator of generators of tuples
    ((startBitAddress, endBitAddress), TransTmpl instance)
    for each possiblility in this transaction


return self.child.walkFlatten(*args, **kwargs)<EOL>

:note: doc in :meth:`.TransTmpl.walkFlatten`


@internal<EOL><INDENT>def _discover_sensitivity(self, seen) -> None:<DEDENT>

assert self._sensitivity is None, self<EOL>ctx = self._sensitivity = SensitivityCtx()<EOL>casual_sensitivity = set()<EOL>self.switchOn._walk_sensitivity(casual_sensitivity, seen, ctx)<EOL>if ctx.contains_ev_dependency:<EOL><INDENT>raise HwtSyntaxError(<EOL>"<STR_LIT>", self.switchOn)<EOL><DEDENT>ctx.extend(casual_sensitivity)<EOL>for stm in self._iter_stms():<EOL><INDENT>stm._discover_sensitivity(seen)<EOL>ctx.extend(stm._sensitivity)<EOL><DEDENT>

Doc on parent class :meth:`HdlStatement._discover_sensitivity`


@internal<EOL><INDENT>def _fill_enclosure(self, enclosure: Dict[RtlSignalBase, HdlStatement]) -> None:<DEDENT>

select = []<EOL>outputs = self._outputs<EOL>for e in enclosure.keys():<EOL><INDENT>if e in outputs:<EOL><INDENT>select.append(e)<EOL><DEDENT><DEDENT>for (_, stms), e in zip(self.cases, self._case_enclosed_for):<EOL><INDENT>fill_stm_list_with_enclosure(self, e, stms, select, enclosure)<EOL>e.update(select)<EOL><DEDENT>t = self.switchOn._dtype<EOL>default_required = len(self.cases) < t.domain_size()<EOL>if self.default is not None or default_required:<EOL><INDENT>self.default = fill_stm_list_with_enclosure(<EOL>self, self._default_enclosed_for, self.default, select, enclosure)<EOL>self._default_enclosed_for.update(select)<EOL><DEDENT>self._enclosed_for.update(select)<EOL>

:attention: enclosure has to be discoverd first use _discover_enclosure()  method


for _, stms in self.cases:<EOL><INDENT>yield from stms<EOL><DEDENT>if self.default is not None:<EOL><INDENT>yield from self.default<EOL><DEDENT>

Doc on parent class :meth:`HdlStatement._iter_stms`


@internal<EOL><INDENT>def _is_mergable(self, other) -> bool:<DEDENT>

if not isinstance(other, SwitchContainer):<EOL><INDENT>return False<EOL><DEDENT>if not (self.switchOn is other.switchOn and<EOL>len(self.cases) == len(other.cases) and<EOL>self._is_mergable_statement_list(self.default, other.default)):<EOL><INDENT>return False<EOL><DEDENT>for (vA, caseA), (vB, caseB) in zip(self.cases, other.cases):<EOL><INDENT>if vA != vB or not self._is_mergable_statement_list(caseA, caseB):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL>

:return: True if other can be merged into this statement else False


@internal<EOL><INDENT>def _merge_with_other_stm(self, other: "<STR_LIT>") -> None:<DEDENT>

merge = self._merge_statement_lists<EOL>newCases = []<EOL>for (c, caseA), (_, caseB) in zip(self.cases, other.cases):<EOL><INDENT>newCases.append((c, merge(caseA, caseB)))<EOL><DEDENT>self.cases = newCases<EOL>if self.default is not None:<EOL><INDENT>self.default = merge(self.default, other.default)<EOL><DEDENT>self._on_merge(other)<EOL>


@internal<EOL><INDENT>def _try_reduce(self) -> Tuple[List["<STR_LIT>"], bool]:<DEDENT>

io_change = False<EOL>new_cases = []<EOL>for val, statements in self.cases:<EOL><INDENT>_statements, rank_decrease, _io_change = self._try_reduce_list(<EOL>statements)<EOL>io_change |= _io_change<EOL>self.rank -= rank_decrease<EOL>new_cases.append((val, _statements))<EOL><DEDENT>self.cases = new_cases<EOL>if self.default is not None:<EOL><INDENT>self.default, rank_decrease, _io_change = self._try_reduce_list(<EOL>self.default)<EOL>self.rank -= rank_decrease<EOL>io_change |= _io_change<EOL><DEDENT>reduce_self = not self._condHasEffect()<EOL>if reduce_self:<EOL><INDENT>if self.cases:<EOL><INDENT>res = self.cases[<NUM_LIT:0>][<NUM_LIT:1>]<EOL><DEDENT>elif self.default is not None:<EOL><INDENT>res = self.default<EOL><DEDENT>else:<EOL><INDENT>res = []<EOL><DEDENT><DEDENT>else:<EOL><INDENT>res = [self, ]<EOL><DEDENT>self._on_reduce(reduce_self, io_change, res)<EOL>if not self.default:<EOL><INDENT>t = self.switchOn._dtype<EOL>if isinstance(t, HEnum):<EOL><INDENT>dom_size = t.domain_size()<EOL>val_cnt = len(t._allValues)<EOL>if len(self.cases) == val_cnt and val_cnt < dom_size:<EOL><INDENT>_, stms = self.cases.pop()<EOL>self.default = stms<EOL><DEDENT><DEDENT><DEDENT>return res, io_change<EOL>

Doc on parent class :meth:`HdlStatement._try_reduce`


@internal<EOL><INDENT>def _condHasEffect(self) -> bool:<DEDENT>

if not self.cases:<EOL><INDENT>return False<EOL><DEDENT>type_domain_covered = bool(self.default) or len(<EOL>self.cases) == self.switchOn._dtype.domain_size()<EOL>stmCnt = len(self.cases[<NUM_LIT:0>])<EOL>if type_domain_covered and reduce(<EOL>and_,<EOL>[len(stm) == stmCnt<EOL>for _, stm in self.cases],<EOL>True) and (self.default is None<EOL>or len(self.default) == stmCnt):<EOL><INDENT>stms = list(self._iter_stms())<EOL>if statementsAreSame(stms):<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return True<EOL>

:return: True if statements in branches has different effect


def isSame(self, other: HdlStatement) -> bool:

if self is other:<EOL><INDENT>return True<EOL><DEDENT>if self.rank != other.rank:<EOL><INDENT>return False<EOL><DEDENT>if isinstance(other, SwitchContainer)and isSameHVal(self.switchOn, other.switchOn)and len(self.cases) == len(other.cases)and isSameStatementList(self.default, other.default):<EOL><INDENT>for (ac, astm), (bc, bstm) in zip(self.cases, other.cases):<EOL><INDENT>if not isSameHVal(ac, bc)or not isSameStatementList(astm, bstm):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL><DEDENT>return False<EOL>

Doc on parent class :meth:`HdlStatement.isSame`


return self.endOfPart - self.startOfPart<EOL>


def getBusWordBitRange(self) -> Tuple[int, int]:

offset = self.startOfPart % self.parent.wordWidth<EOL>return (offset + self.bit_length(), offset)<EOL>

:return: bit range which contains data of this part on bus data signal


def getFieldBitRange(self) -> Tuple[int, int]:

offset = self.inFieldOffset<EOL>return (self.bit_length() + offset, offset)<EOL>

:return: bit range which contains data of this part on interface
    of field


return self.tmpl.bitAddrEnd == self.endOfPart<EOL>

:return: True if this part is last in parts derived from original field
    else False


def __init__(self, origin, wordWidth, startBitAddr, endBitAddr,<EOL>transParts):

self.origin = origin<EOL>self.wordWidth = wordWidth<EOL>assert startBitAddr <= endBitAddr<EOL>self.startBitAddr = startBitAddr<EOL>self.endBitAddr = endBitAddr<EOL>self.parts = transParts<EOL>self._fieldToTPart = None<EOL>for p in self.parts:<EOL><INDENT>p.parent = self<EOL>assert p.startOfPart >= startBitAddr, (p, startBitAddr)<EOL>assert p.endOfPart <= endBitAddr, (p, endBitAddr)<EOL><DEDENT>

:param origin: instance of HType (usually HStruct)
    from which this FrameTmpl was generated from
:param wordWidth: width of word on interface
    where this template should be used
:param startBitAddr: bit offset where this frame starts
:param endBitAddr: bit offset where this frame ends
    (bit index of first bit behind this frame)
:param transParts: instances of TransPart which are parts of this frame


@staticmethod<EOL><INDENT>def framesFromTransTmpl(transaction: '<STR_LIT>',<EOL>wordWidth: int,<EOL>maxFrameLen: Union[int, float]=inf,<EOL>maxPaddingWords: Union[int, float]=inf,<EOL>trimPaddingWordsOnStart: bool=False,<EOL>trimPaddingWordsOnEnd: bool=False) -> Generator[<EOL>'<STR_LIT>', None, None]:<DEDENT>

isFirstInFrame = True<EOL>partsPending = False<EOL>startOfThisFrame = <NUM_LIT:0><EOL>assert maxFrameLen > <NUM_LIT:0><EOL>assert maxPaddingWords >= <NUM_LIT:0><EOL>if maxPaddingWords < inf:<EOL><INDENT>assert trimPaddingWordsOnStart or trimPaddingWordsOnEnd,"<STR_LIT>"<EOL><DEDENT>it = TransTmplWordIterator(wordWidth)<EOL>lastWordI = <NUM_LIT:0><EOL>endOfThisFrame = maxFrameLen<EOL>parts = []<EOL>for wordI, word in it.groupByWordIndex(transaction, <NUM_LIT:0>):<EOL><INDENT>if wordI * wordWidth >= endOfThisFrame:<EOL><INDENT>paddingWords = wordI - lastWordI<EOL>if trimPaddingWordsOnEnd and paddingWords > maxPaddingWords:<EOL><INDENT>_endOfThisFrame = (lastWordI + <NUM_LIT:1>) * wordWidth<EOL><DEDENT>else:<EOL><INDENT>_endOfThisFrame = wordI * wordWidth<EOL><DEDENT>yield FrameTmpl(transaction,<EOL>wordWidth,<EOL>startOfThisFrame,<EOL>_endOfThisFrame,<EOL>parts)<EOL>parts = []<EOL>isFirstInFrame = True<EOL>partsPending = False<EOL>startOfThisFrame = _endOfThisFrame<EOL>endOfThisFrame = startOfThisFrame + maxFrameLen<EOL>lastWordI = wordI<EOL><DEDENT>if (not isFirstInFrame<EOL>and trimPaddingWordsOnEnd<EOL>and wordI - lastWordI > <NUM_LIT:1>):<EOL><INDENT>_endOfThisFrame = (lastWordI + <NUM_LIT:1>) * wordWidth<EOL>yield FrameTmpl(transaction,<EOL>wordWidth,<EOL>startOfThisFrame,<EOL>_endOfThisFrame,<EOL>parts)<EOL>parts = []<EOL>isFirstInFrame = True<EOL>partsPending = False<EOL>startOfThisFrame = _endOfThisFrame<EOL>endOfThisFrame = startOfThisFrame + maxFrameLen<EOL>lastWordI = wordI - <NUM_LIT:1><EOL><DEDENT>if isFirstInFrame:<EOL><INDENT>partsPending = True<EOL>isFirstInFrame = False<EOL>paddingWords = wordI - lastWordI<EOL>if trimPaddingWordsOnStart and paddingWords > maxPaddingWords:<EOL><INDENT>startOfThisFrame += paddingWords * wordWidth<EOL><DEDENT>endOfThisFrame = startOfThisFrame + maxFrameLen<EOL><DEDENT>parts.extend(word)<EOL>lastWordI = wordI<EOL><DEDENT>endOfThisFrame = transaction.bitAddrEnd<EOL>withPadding = not (trimPaddingWordsOnEnd or trimPaddingWordsOnStart)<EOL>if partsPending or (withPadding<EOL>and endOfThisFrame != startOfThisFrame):<EOL><INDENT>endOfLastWord = (lastWordI + <NUM_LIT:1>) * wordWidth<EOL>if endOfThisFrame < endOfLastWord:<EOL><INDENT>endOfThisFrame = endOfLastWord<EOL><DEDENT>else:<EOL><INDENT>paddingWords = it.fullWordCnt(endOfLastWord, endOfThisFrame)<EOL>if trimPaddingWordsOnEnd and paddingWords > maxPaddingWords:<EOL><INDENT>endOfThisFrame -= paddingWords * wordWidth<EOL><DEDENT><DEDENT>endOfThisFrame = min(startOfThisFrame +<EOL>maxFrameLen, endOfThisFrame)<EOL>yield FrameTmpl(transaction,<EOL>wordWidth,<EOL>startOfThisFrame,<EOL>endOfThisFrame,<EOL>parts)<EOL>parts = []<EOL>startOfThisFrame = endOfThisFrame<EOL><DEDENT>while withPadding and startOfThisFrame < transaction.bitAddrEnd:<EOL><INDENT>endOfThisFrame = min(startOfThisFrame +<EOL>maxFrameLen, transaction.bitAddrEnd)<EOL>yield FrameTmpl(transaction,<EOL>wordWidth,<EOL>startOfThisFrame,<EOL>endOfThisFrame,<EOL>[])<EOL>startOfThisFrame = endOfThisFrame<EOL><DEDENT>

Convert transaction template into FrameTmpls

:param transaction: transaction template used which are FrameTmpls
    created from
:param wordWidth: width of data signal in target interface
    where frames will be used
:param maxFrameLen: maximum length of frame in bits,
    if exceeded another frame will be created
:param maxPaddingWords: maximum of continual padding words in frame,
    if exceed frame is split and words are cut of
:attention: if maxPaddingWords<inf trimPaddingWordsOnEnd
    or trimPaddingWordsOnStart has to be True
    to decide where padding should be trimmed
:param trimPaddingWordsOnStart: trim padding from start of frame
    at word granularity
:param trimPaddingWordsOnEnd: trim padding from end of frame
    at word granularity


@internal<EOL><INDENT>def _wordIndx(self, addr: int):<DEDENT>

return floor(addr / self.wordWidth)<EOL>

convert bit address to index of word where this address is


return ceil((self.endBitAddr - self.startBitAddr) / self.wordWidth)<EOL>


def walkWords(self, showPadding: bool=False):

wIndex = <NUM_LIT:0><EOL>lastEnd = self.startBitAddr<EOL>parts = []<EOL>for p in self.parts:<EOL><INDENT>end = p.startOfPart<EOL>if showPadding and end != lastEnd:<EOL><INDENT>while end != lastEnd:<EOL><INDENT>assert end >= lastEnd, (end, lastEnd)<EOL>endOfWord = ceil(<EOL>(lastEnd + <NUM_LIT:1>) / self.wordWidth) * self.wordWidth<EOL>endOfPadding = min(endOfWord, end)<EOL>_p = TransPart(self, None, lastEnd, endOfPadding, <NUM_LIT:0>)<EOL>parts.append(_p)<EOL>if endOfPadding >= endOfWord:<EOL><INDENT>yield (wIndex, parts)<EOL>wIndex += <NUM_LIT:1><EOL>parts = []<EOL><DEDENT>lastEnd = endOfPadding<EOL><DEDENT><DEDENT>if self._wordIndx(lastEnd) != self._wordIndx(p.startOfPart):<EOL><INDENT>yield (wIndex, parts)<EOL>wIndex += <NUM_LIT:1><EOL>parts = []<EOL>lastEnd = p.endOfPart<EOL><DEDENT>parts.append(p)<EOL>lastEnd = p.endOfPart<EOL>if lastEnd % self.wordWidth == <NUM_LIT:0>:<EOL><INDENT>yield (wIndex, parts)<EOL>wIndex += <NUM_LIT:1><EOL>parts = []<EOL><DEDENT><DEDENT>if showPadding and (parts<EOL>or lastEnd != self.endBitAddr<EOL>or lastEnd % self.wordWidth != <NUM_LIT:0>):<EOL><INDENT>end = ceil(self.endBitAddr / self.wordWidth) * self.wordWidth<EOL>while end != lastEnd:<EOL><INDENT>assert end >= lastEnd, (end, lastEnd)<EOL>endOfWord = ((lastEnd // self.wordWidth) + <NUM_LIT:1>) * self.wordWidth<EOL>endOfPadding = min(endOfWord, end)<EOL>_p = TransPart(self, None, lastEnd, endOfPadding, <NUM_LIT:0>)<EOL>_p.parent = self<EOL>parts.append(_p)<EOL>if endOfPadding >= endOfWord:<EOL><INDENT>yield (wIndex, parts)<EOL>wIndex += <NUM_LIT:1><EOL>parts = []<EOL><DEDENT>lastEnd = endOfPadding<EOL><DEDENT>if parts:<EOL><INDENT>yield (wIndex, parts)<EOL><DEDENT><DEDENT>

Walk enumerated words in this frame

:attention: not all indexes has to be present, only words
    with items will be generated when not showPadding
:param showPadding: padding TransParts are also present
:return: generator of tuples (wordIndex, list of TransParts
    in this word)


@staticmethod<EOL><INDENT>def fieldToDataDict(dtype, data, res):<DEDENT>

<EOL>for f in dtype.fields:<EOL><INDENT>try:<EOL><INDENT>fVal = data[f.name]<EOL><DEDENT>except KeyError:<EOL><INDENT>fVal = None<EOL><DEDENT>if isinstance(f.dtype, Bits):<EOL><INDENT>if fVal is not None:<EOL><INDENT>assert isinstance(fVal, int)<EOL>res[f] = fVal<EOL><DEDENT><DEDENT>elif isinstance(f.dtype, HStruct):<EOL><INDENT>if fVal:<EOL><INDENT>FrameTmpl.fieldToDataDict(f.dtype, fVal, res)<EOL><DEDENT><DEDENT>elif isinstance(f.dtype, HArray):<EOL><INDENT>if fVal:<EOL><INDENT>res[f] = fVal<EOL><DEDENT><DEDENT><DEDENT>return res<EOL>

Construct dictionary {StructField:value} for faster lookup of values
for fields


typeOfWord = simBitsT(self.wordWidth, None)<EOL>fieldToVal = self._fieldToTPart<EOL>if fieldToVal is None:<EOL><INDENT>fieldToVal = self._fieldToTPart = self.fieldToDataDict(<EOL>self.origin.dtype,<EOL>data,<EOL>{})<EOL><DEDENT>for _, transParts in self.walkWords(showPadding=True):<EOL><INDENT>actualVldMask = <NUM_LIT:0><EOL>actualVal = <NUM_LIT:0><EOL>for tPart in transParts:<EOL><INDENT>high, low = tPart.getBusWordBitRange()<EOL>fhigh, flow = tPart.getFieldBitRange()<EOL>if not tPart.isPadding:<EOL><INDENT>val = fieldToVal.get(tPart.tmpl.origin, None)<EOL><DEDENT>else:<EOL><INDENT>val = None<EOL><DEDENT>if val is None:<EOL><INDENT>newBits = <NUM_LIT:0><EOL>vld = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>newBits = selectBitRange(val, flow, fhigh - flow)<EOL>vld = mask(high - low) << low<EOL><DEDENT>actualVal = setBitRange(actualVal, low, high - low, newBits)<EOL>actualVldMask = setBitRange(actualVal, low, high - low, vld)<EOL><DEDENT>yield typeOfWord.getValueCls()(actualVal, typeOfWord,<EOL>actualVldMask, -<NUM_LIT:1>)<EOL><DEDENT>

Pack data into list of BitsVal of specified dataWidth

:param data: dict of values for struct fields {fieldName: value}

:return: list of BitsVal which are representing values of words


actual = []<EOL>_iterators = []<EOL>for i, it in enumerate(iterators):<EOL><INDENT>try:<EOL><INDENT>a = next(it)<EOL>_iterators.append((i, it))<EOL>actual.append(a)<EOL><DEDENT>except StopIteration:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>while True:<EOL><INDENT>if not _iterators:<EOL><INDENT>return<EOL><DEDENT>elif len(_iterators) == <NUM_LIT:1>:<EOL><INDENT>originIndex, it = _iterators[<NUM_LIT:0>]<EOL>yield originIndex, actual[<NUM_LIT:0>]<EOL>for item in it:<EOL><INDENT>yield originIndex, item<EOL><DEDENT>return<EOL><DEDENT>minimum = None<EOL>minimumIndex = None<EOL>secondMin = None<EOL>for i, val in enumerate(actual):<EOL><INDENT>skipSecMinCheck = False<EOL>if minimum is None:<EOL><INDENT>minimum = val<EOL>minimumIndex = i<EOL><DEDENT>elif cmpFn(val, minimum):<EOL><INDENT>secondMin = minimum<EOL>minimum = val<EOL>minimumIndex = i<EOL>skipSecMinCheck = True<EOL><DEDENT>elif not skipSecMinCheck and (<EOL>secondMin is None or cmpFn(val, secondMin)):<EOL><INDENT>secondMin = val<EOL><DEDENT><DEDENT>actualI, actualIt = _iterators[minimumIndex]<EOL>while not cmpFn(secondMin, minimum):<EOL><INDENT>yield (actualI, minimum)<EOL>try:<EOL><INDENT>minimum = next(actualIt)<EOL><DEDENT>except StopIteration:<EOL><INDENT>minimum = None<EOL>break<EOL><DEDENT><DEDENT>if minimum is None:<EOL><INDENT>del _iterators[minimumIndex]<EOL>del actual[minimumIndex]<EOL><DEDENT>else:<EOL><INDENT>actual[minimumIndex] = minimum<EOL><DEDENT><DEDENT>

Sort items from iterators(generators) by alwas selecting item
with lowest value (min first)

:return: generator of tuples (origin index, item) where origin index
    is index of iterator in "iterators" from where item commes from


def groupIntoChoices(splitsOnWord, wordWidth: int, origin: OneOfTransaction):

def cmpWordIndex(a, b):<EOL><INDENT>return a.startOfPart // wordWidth < b.startOfPart // wordWidth<EOL><DEDENT>actual = None<EOL>itCnt = len(splitsOnWord)<EOL>for i, item in iterSort(splitsOnWord, cmpWordIndex):<EOL><INDENT>_actualW = item.startOfPart // wordWidth<EOL>if actual is None:<EOL><INDENT>actual = ChoicesOfFrameParts(item.startOfPart, origin)<EOL>actual.extend(<EOL>ChoiceOfFrameParts(actual,<EOL>origin.possibleTransactions[_i])<EOL>for _i in range(itCnt))<EOL>actualW = _actualW<EOL><DEDENT>elif _actualW > actualW:<EOL><INDENT>actual.resolveEnd()<EOL>yield actual<EOL>actual = ChoicesOfFrameParts(item.startOfPart, origin)<EOL>actual.extend(<EOL>ChoiceOfFrameParts(actual,<EOL>origin.possibleTransactions[_i])<EOL>for _i in range(itCnt))<EOL>actualW = _actualW<EOL><DEDENT>actual[i].append(item)<EOL><DEDENT>if actual is not None:<EOL><INDENT>actual.setIsLast(True)<EOL>actual.resolveEnd()<EOL>yield actual<EOL><DEDENT>

:param splitsOnWord: list of lists of parts (fields splited on word
    boundaries)
:return: generators of ChoicesOfFrameParts for each word
    which are not crossing word boundaries


return self._isLast<EOL>


def fullWordCnt(self, start: int, end: int):

assert end >= start, (start, end)<EOL>gap = max(<NUM_LIT:0>, (end - start) - (start % self.wordWidth))<EOL>return gap // self.wordWidth<EOL>

Count of complete words between two addresses


def groupByWordIndex(self, transaction: '<STR_LIT>', offset: int):

actualW = None<EOL>partsInWord = []<EOL>wordWidth = self.wordWidth<EOL>for item in self.splitOnWords(transaction, offset):<EOL><INDENT>_actualW = item.startOfPart // wordWidth<EOL>if actualW is None:<EOL><INDENT>actualW = _actualW<EOL>partsInWord.append(item)<EOL><DEDENT>elif _actualW > actualW:<EOL><INDENT>yield (actualW, partsInWord)<EOL>actualW = _actualW<EOL>partsInWord = [item, ]<EOL><DEDENT>else:<EOL><INDENT>partsInWord.append(item)<EOL><DEDENT><DEDENT>if partsInWord:<EOL><INDENT>yield (actualW, partsInWord)<EOL><DEDENT>

Group transaction parts splited on words to words

:param transaction: TransTmpl instance which parts
    should be grupped into words
:return: generator of tuples (wordIndex, list of transaction parts
    in this word)


@internal<EOL><INDENT>def splitOnWords(self, transaction, addrOffset=<NUM_LIT:0>):<DEDENT>

wordWidth = self.wordWidth<EOL>end = addrOffset<EOL>for tmp in transaction.walkFlatten(offset=addrOffset):<EOL><INDENT>if isinstance(tmp, OneOfTransaction):<EOL><INDENT>split = [self.splitOnWords(ch, end)<EOL>for ch in tmp.possibleTransactions]<EOL>yield from groupIntoChoices(split, wordWidth, tmp)<EOL>end = addrOffset + tmp.possibleTransactions[<NUM_LIT:0>].bitAddrEnd<EOL><DEDENT>elif isinstance(tmp, StreamTransaction):<EOL><INDENT>ch_len = tmp.child.bit_length()<EOL>if end % self.wordWidth != <NUM_LIT:0> or ch_len != self.wordWidth:  <EOL><INDENT>raise NotImplementedError(tmp)<EOL><DEDENT>else:<EOL><INDENT>s = StreamOfFramePars(end, tmp)<EOL>s.extend(self.splitOnWords(tmp.child, end))<EOL>s.setIsLast(True)<EOL>s.resolveEnd()<EOL>yield s<EOL>end = addrOffset + tmp.child.bitAddrEnd<EOL><DEDENT><DEDENT>else:<EOL><INDENT>(base, end), tmpl = tmp<EOL>startOfPart = base<EOL>while startOfPart != end:<EOL><INDENT>wordIndex = startOfPart // wordWidth<EOL>endOfWord = (wordIndex + <NUM_LIT:1>) * wordWidth<EOL>endOfPart = min(endOfWord, end)<EOL>inFieldOffset = startOfPart - base<EOL>yield TransPart(self, tmpl, startOfPart, endOfPart,<EOL>inFieldOffset)<EOL>startOfPart = endOfPart<EOL><DEDENT><DEDENT><DEDENT>

:return: generator of TransPart instance


return isinstance(item, Value) or item._const<EOL>


for o in self.operands:<EOL><INDENT>if isinstance(o, RtlSignalBase):<EOL><INDENT>if o in outputs:<EOL><INDENT>o.drivers.append(self)<EOL><DEDENT>else:<EOL><INDENT>o.endpoints.append(self)<EOL><DEDENT><DEDENT>elif isinstance(o, Value):<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>" % (o))<EOL><DEDENT><DEDENT>

Register potential signals to drivers/endpoints


for o in self.operands:<EOL><INDENT>o.staticEval()<EOL><DEDENT>self.result._val = self.evalFn()<EOL>

Recursively statistically evaluate result of this operator


return self.operator.eval(self, simulator=simulator)<EOL>


@internal<EOL><INDENT>@staticmethod<EOL>def withRes(opDef, operands, resT, outputs=[]):<DEDENT>

op = Operator(opDef, operands)<EOL>out = RtlSignal(getCtxFromOps(operands), None, resT)<EOL>out._const = arr_all(op.operands, isConst)<EOL>out.drivers.append(op)<EOL>out.origin = op<EOL>op.result = out<EOL>op.registerSignals(outputs)<EOL>if out._const:<EOL><INDENT>out.staticEval()<EOL><DEDENT>return out<EOL>

Create operator with result signal

:ivar resT: data type of result signal
:ivar outputs: iterable of singnals which are outputs
    from this operator


if op == AllOps.RISING_EDGE:<EOL><INDENT>return SENSITIVITY.RISING<EOL><DEDENT>elif op == AllOps.FALLING_EDGE:<EOL><INDENT>return SENSITIVITY.FALLING<EOL><DEDENT>else:<EOL><INDENT>raise TypeError()<EOL><DEDENT>


def eval(self, operator, simulator=None):

def getVal(v):<EOL><INDENT>while not isinstance(v, Value):<EOL><INDENT>v = v._val<EOL><DEDENT>return v<EOL><DEDENT>operands = list(map(getVal, operator.operands))<EOL>if isEventDependentOp(operator.operator):<EOL><INDENT>operands.append(simulator.now)<EOL><DEDENT>elif operator.operator == AllOps.IntToBits:<EOL><INDENT>operands.append(operator.result._dtype)<EOL><DEDENT>return self._evalFn(*operands)<EOL>

Load all operands and process them by self._evalFn


if self.direction == DIRECTION.IN:<EOL><INDENT>if self.src is not None:<EOL><INDENT>raise HwtSyntaxError(<EOL>"<STR_LIT>"<EOL>% (self.name, self.src))<EOL><DEDENT>self.src = signal<EOL>signal.endpoints.append(self)<EOL><DEDENT>elif self.direction == DIRECTION.OUT:<EOL><INDENT>if self.dst is not None:<EOL><INDENT>raise HwtSyntaxError(<EOL>"<STR_LIT>"<EOL>% (self.name, self.dst))<EOL><DEDENT>self.dst = signal<EOL>signal.drivers.append(self)<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError(self)<EOL><DEDENT>signal.hidden = False<EOL>signal.ctx.subUnits.add(self.unit)<EOL>


if self.direction == DIRECTION.OUT:<EOL><INDENT>if self.src is not None:<EOL><INDENT>raise HwtSyntaxError(<EOL>"<STR_LIT>"<EOL>% (self.name, str(self.src)))<EOL><DEDENT>self.src = signal<EOL><DEDENT>elif self.direction == DIRECTION.IN:<EOL><INDENT>if self.dst is not None:<EOL><INDENT>raise HwtSyntaxError(<EOL>"<STR_LIT>"<EOL>% (self.name, str(self.dst)))<EOL><DEDENT>self.dst = signal<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError(self.direction)<EOL><DEDENT>

Connect internal signal to port item,
this connection is used by simulator and only output port items
will be connected


d = self.direction<EOL>if d == DIRECTION.OUT:<EOL><INDENT>self.src.endpoints.append(self)<EOL><DEDENT>elif d == DIRECTION.IN or d == DIRECTION.INOUT:<EOL><INDENT>self.dst.drivers.append(self)<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError(d)<EOL><DEDENT>

connet signal from internal side of of this component to this port


d = self.direction<EOL>if d == DIRECTION.IN:<EOL><INDENT>return self.dst<EOL><DEDENT>elif d == DIRECTION.OUT:<EOL><INDENT>return self.src<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError(d)<EOL><DEDENT>

return signal inside unit which has this port


s = set()<EOL>for i in iterable:<EOL><INDENT>r = fn(i)<EOL>if r not in s:<EOL><INDENT>s.add(r)<EOL>yield i<EOL><DEDENT><DEDENT>


found = False<EOL>ret = None<EOL>for i in iterable:<EOL><INDENT>if fn(i):<EOL><INDENT>if found:<EOL><INDENT>raise DuplicitValueExc(i)<EOL><DEDENT>found = True<EOL>ret = i<EOL><DEDENT><DEDENT>if not found:<EOL><INDENT>raise NoValueExc()<EOL><DEDENT>return ret<EOL>

Get value from iterable where fn(item) and check
if there is not fn(other item)

:raise DuplicitValueExc: when there are multiple items satisfying fn()
:raise NoValueExc: when no value satisfying fn(item) found


for item in iterable:<EOL><INDENT>if fn(item):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return False<EOL>

:return: True if fn(item) for any item else False


for item in iterable:<EOL><INDENT>if not fn(item):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL>

:return: True if fn(item) for all items in interable or iterable
    is empty else False


assert howMay >= <NUM_LIT:0><EOL>if not howMay:<EOL><INDENT>return<EOL><DEDENT>last = howMay - <NUM_LIT:1><EOL>for i, item in enumerate(iterrable):<EOL><INDENT>yield item<EOL>if i == last:<EOL><INDENT>return<EOL><DEDENT><DEDENT>

:return: generator of first n items from iterrable


for i in iterable:<EOL><INDENT>if fn(i):<EOL><INDENT>yield i<EOL><DEDENT><DEDENT>

:return: generator of items from iterable where fn(item)


<EOL>iterable = iter(iterable)<EOL>prev = next(iterable)<EOL>for item in iterable:<EOL><INDENT>yield False, prev<EOL>prev = item<EOL><DEDENT>yield True, prev<EOL>

:return: generator of tuples (isLastFlag, item)


d = {}<EOL>for item in collection:<EOL><INDENT>k = fn(item)<EOL>try:<EOL><INDENT>arr = d[k]<EOL><DEDENT>except KeyError:<EOL><INDENT>arr = []<EOL>d[k] = arr<EOL><DEDENT>arr.append(item)<EOL><DEDENT>yield from d.items()<EOL>

same like itertools.groupby

:note: This function does not needs initial sorting like itertools.groupby

:attention: Order of pairs is not deterministic.


if level >= <NUM_LIT:0> and isinstance(iterables, (list, tuple, GeneratorType,<EOL>map, zip)):<EOL><INDENT>level -= <NUM_LIT:1><EOL>for i in iterables:<EOL><INDENT>yield from flatten(i, level=level)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>yield iterables<EOL><DEDENT>

Flatten nested lists, tuples, generators and maps

:param level: maximum depth of flattening


def grouper(n, iterable, padvalue=None):

return zip_longest(*[iter(iterable)] * n, fillvalue=padvalue)<EOL>


return any(x in setA for x in setB)<EOL>

Check if intersection of sets is not empty


def find_files(directory, pattern, recursive=True):

if not os.path.isdir(directory):<EOL><INDENT>if os.path.exists(directory):<EOL><INDENT>raise IOError(directory + '<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>raise IOError(directory + "<STR_LIT>")<EOL><DEDENT><DEDENT>if recursive:<EOL><INDENT>for root, _, files in os.walk(directory):<EOL><INDENT>for basename in files:<EOL><INDENT>if fnmatch.fnmatch(basename, pattern):<EOL><INDENT>filename = os.path.join(root, basename)<EOL>yield filename<EOL><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>root = directory<EOL>for basename in os.listdir(root):<EOL><INDENT>if fnmatch.fnmatch(basename, pattern):<EOL><INDENT>filename = os.path.join(root, basename)<EOL>if os.path.isfile(filename):<EOL><INDENT>yield filename<EOL><DEDENT><DEDENT><DEDENT><DEDENT>


while isinstance(p, Param):<EOL><INDENT>p = p.get()<EOL><DEDENT>if isinstance(p, RtlSignalBase):<EOL><INDENT>return p.staticEval()<EOL><DEDENT>return toHVal(p)<EOL>


if isinstance(p, Param):<EOL><INDENT>p = p.get()<EOL><DEDENT>return p<EOL>

get param value or value
getParam gets only item which is specified as param value,
but evalParam also evaluates it if it is not value


assert not self.__isReadOnly,("<STR_LIT>"<EOL>"<STR_LIT>" % self.name)<EOL>assert self.replacedWith is None,("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>val = toHVal(val)<EOL>self.defVal = val<EOL>self._val = val.staticEval()<EOL>self._dtype = self._val._dtype<EOL>


def fitTo_t(what: Union[RtlSignal, Value], where_t: HdlType,<EOL>extend: bool=True, shrink: bool=True):

whatWidth = what._dtype.bit_length()<EOL>toWidth = where_t.bit_length()<EOL>if toWidth == whatWidth:<EOL><INDENT>return what<EOL><DEDENT>elif toWidth < whatWidth:<EOL><INDENT>if not shrink:<EOL><INDENT>raise BitWidthErr()<EOL><DEDENT>return what[toWidth:]<EOL><DEDENT>else:<EOL><INDENT>if not extend:<EOL><INDENT>raise BitWidthErr()<EOL><DEDENT>w = toWidth - whatWidth<EOL>if what._dtype.signed:<EOL><INDENT>msb = what[whatWidth - <NUM_LIT:1>]<EOL>ext = reduce(lambda a, b: a._concat(b), [msb for _ in range(w)])<EOL><DEDENT>else:<EOL><INDENT>ext = vec(<NUM_LIT:0>, w)<EOL><DEDENT>return ext._concat(what)<EOL><DEDENT>

Slice signal "what" to fit in "where"
or
arithmetically (for signed by MSB / unsigned, vector with 0) extend
"what" to same width as "where"

little-endian impl.


def iterBits(sigOrVal: Union[RtlSignal, Value], bitsInOne: int=<NUM_LIT:1>,<EOL>skipPadding: bool=True, fillup: bool=False):

bw = BitWalker(sigOrVal, skipPadding, fillup)<EOL>for _ in range(ceil(sigOrVal._dtype.bit_length() / bitsInOne)):<EOL><INDENT>yield bw.get(bitsInOne)<EOL><DEDENT>bw.assertIsOnEnd()<EOL>

Iterate over bits in vector

:param sigOrVal: signal or value to iterate over
:param bitsInOne: number of bits in one part
:param skipPadding: if true padding is skipped in dense types


def __init__(self, sigOrVal: Union[RtlSignal, Value],<EOL>skipPadding: bool=True,<EOL>fillup: bool=False):

self.it = walkFlattenFields(sigOrVal, skipPadding=skipPadding)<EOL>self.fillup = fillup<EOL>self.actuallyHave = <NUM_LIT:0><EOL>self.actual = None<EOL>self.actualOffset = <NUM_LIT:0><EOL>

:param skipPadding: if true padding is skipped in dense types


@internal<EOL><INDENT>def _get(self, numberOfBits: int, doCollect: bool):<DEDENT>

if not isinstance(numberOfBits, int):<EOL><INDENT>numberOfBits = int(numberOfBits)<EOL><DEDENT>while self.actuallyHave < numberOfBits:<EOL><INDENT>try:<EOL><INDENT>f = next(self.it)<EOL><DEDENT>except StopIteration:<EOL><INDENT>if self.fillup and self.actual is not None:<EOL><INDENT>break<EOL><DEDENT>else:<EOL><INDENT>raise NotEnoughtBitsErr()<EOL><DEDENT><DEDENT>thisFieldLen = f._dtype.bit_length()<EOL>if self.actual is None:<EOL><INDENT>if not doCollect and thisFieldLen <= numberOfBits:<EOL><INDENT>numberOfBits -= thisFieldLen<EOL><DEDENT>else:<EOL><INDENT>self.actual = f<EOL>self.actuallyHave = thisFieldLen<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if not doCollect and self.actuallyHave < numberOfBits:<EOL><INDENT>self.actuallyHave = thisFieldLen<EOL>self.actual = f<EOL><DEDENT>else:<EOL><INDENT>self.actuallyHave += thisFieldLen<EOL>self.actual = f._concat(self.actual)<EOL><DEDENT><DEDENT><DEDENT>actual = self.actual<EOL>actualOffset = self.actualOffset<EOL>if self.actuallyHave < numberOfBits:<EOL><INDENT>assert self.fillup<EOL>if doCollect:<EOL><INDENT>t = self.actual._dtype<EOL>fillupW = numberOfBits - self.actuallyHave<EOL>padding_t = Bits(fillupW, signed=t.signed, negated=t.negated)<EOL>padding = padding_t.fromPy(None)<EOL>actual = padding._concat(actual)<EOL><DEDENT>self.actuallyHave = <NUM_LIT:0><EOL><DEDENT>self.actuallyHave -= numberOfBits<EOL>self.actualOffset += numberOfBits<EOL>if self.actuallyHave == <NUM_LIT:0>:<EOL><INDENT>self.actual = None<EOL>self.actualOffset = <NUM_LIT:0><EOL><DEDENT>if doCollect:<EOL><INDENT>if numberOfBits == <NUM_LIT:1>:<EOL><INDENT>return actual[actualOffset]<EOL><DEDENT>else:<EOL><INDENT>return actual[(actualOffset + numberOfBits):actualOffset]<EOL><DEDENT><DEDENT>

:param numberOfBits: number of bits to get from actual possition
:param doCollect: if False output is not collected just iterator moves
    in structure


def get(self, numberOfBits: int) -> Union[RtlSignal, Value]:

return self._get(numberOfBits, True)<EOL>

:param numberOfBits: number of bits to get from actual possition
:return: chunk of bits of specified size (instance of Value or RtlSignal)


def skip(self, numberOfBits: int) -> None:

self._get(numberOfBits, False)<EOL>

Move this iterator without care about item

:param numberOfBits: number of bits to get from actual possition


try:<EOL><INDENT>next(self.it)<EOL><DEDENT>except StopIteration:<EOL><INDENT>return<EOL><DEDENT>raise AssertionError("<STR_LIT>")<EOL>

Assert there is nothing left in this iterator


w = signalOrVal._dtype.bit_length()<EOL>i = w<EOL>items = []<EOL>while i > <NUM_LIT:0>:<EOL><INDENT>lower = max(i - <NUM_LIT:8>, <NUM_LIT:0>)<EOL>items.append(signalOrVal[i:lower])<EOL>i -= <NUM_LIT:8><EOL><DEDENT>return Concat(*items)<EOL>

Reverse byteorder (littleendian/bigendian) of signal or value


@internal<EOL><INDENT>def _toRtl(self, targetPlatform: DummyPlatform):<DEDENT>

assert not self._wasSynthetised()<EOL>self._targetPlatform = targetPlatform<EOL>if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self._name = self._getDefaultName()<EOL><DEDENT>for proc in targetPlatform.beforeToRtl:<EOL><INDENT>proc(self)<EOL><DEDENT>self._ctx.params = self._buildParams()<EOL>self._externInterf = []<EOL>for u in self._units:<EOL><INDENT>yield from u._toRtl(targetPlatform)<EOL><DEDENT>for u in self._units:<EOL><INDENT>subUnitName = u._name<EOL>u._signalsForMyEntity(self._ctx, "<STR_LIT>" + subUnitName)<EOL><DEDENT>for i in self._interfaces:<EOL><INDENT>signals = i._signalsForInterface(self._ctx)<EOL>if i._isExtern:<EOL><INDENT>self._externInterf.extend(signals)<EOL><DEDENT><DEDENT>for proc in targetPlatform.beforeToRtlImpl:<EOL><INDENT>proc(self)<EOL><DEDENT>self._loadMyImplementations()<EOL>yield from self._lazyLoaded<EOL>if not self._externInterf:<EOL><INDENT>raise IntfLvlConfErr(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>% self._name)<EOL><DEDENT>for proc in targetPlatform.afterToRtlImpl:<EOL><INDENT>proc(self)<EOL><DEDENT>yield from self._synthetiseContext(self._externInterf)<EOL>self._checkArchCompInstances()<EOL>for proc in targetPlatform.afterToRtl:<EOL><INDENT>proc(self)<EOL><DEDENT>

synthesize all subunits, make connections between them,
build entity and component for this unit


if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self._interfaces = []<EOL><DEDENT>if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self._private_interfaces = []<EOL><DEDENT>if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self._units = []<EOL><DEDENT>self._setAttrListener = self._declrCollector<EOL>self._declr()<EOL>self._setAttrListener = None<EOL>for i in self._interfaces:<EOL><INDENT>self._loadInterface(i, True)<EOL><DEDENT>for u in self._units:<EOL><INDENT>u._loadDeclarations()<EOL><DEDENT>for p in self._params:<EOL><INDENT>p.setReadOnly()<EOL><DEDENT>

Load all declarations from _decl() method, recursively
for all interfaces/units.


@internal<EOL><INDENT>def _registerIntfInImpl(self, iName, intf):<DEDENT>

self._registerInterface(iName, intf, isPrivate=True)<EOL>self._loadInterface(intf, False)<EOL>intf._signalsForInterface(self._ctx)<EOL>

Register interface in implementation phase


def _updateParamsFrom(self, otherObj, updater=_default_param_updater, exclude=None, prefix="<STR_LIT>"):

PropDeclrCollector._updateParamsFrom(self, otherObj, updater, exclude, prefix)<EOL>

:note: doc in :func:`~hwt.synthesizer.interfaceLevel.propDeclCollector._updateParamsFrom`


def __init__(self, ctx, name, dtype, defVal=None, nopVal=None,<EOL>useNopVal=False, virtualOnly=False):

if name is None:<EOL><INDENT>name = "<STR_LIT>"<EOL>self.hasGenericName = True<EOL><DEDENT>else:<EOL><INDENT>self.hasGenericName = False<EOL><DEDENT>assert isinstance(dtype, HdlType)<EOL>super(RtlSignal, self).__init__(name, dtype, defVal, virtualOnly=virtualOnly)<EOL>self.ctx = ctx<EOL>if ctx:<EOL><INDENT>ctx.signals.add(self)<EOL><DEDENT>self.endpoints = UniqList()<EOL>self.drivers = UniqList()<EOL>self._usedOps = {}<EOL>self.hidden = True<EOL>self._instId = RtlSignal._nextInstId()<EOL>self._nopVal = nopVal<EOL>self._useNopVal = useNopVal<EOL>self._const = False<EOL>

:param ctx: context - RtlNetlist which is this signal part of
:param name: name hint for this signal, if is None name
    is chosen automatically
:param defVal: value which is used for reset and as default value
    in hdl
:param useNopVal: use nopVal or ignore it
:param nopVal: value which is used to fill up statements when no other
    value is assigned


i = cls.__instCntr<EOL>cls.__instCntr += <NUM_LIT:1><EOL>return i<EOL>


<EOL>drv_cnt = len(self.drivers)<EOL>if not drv_cnt:<EOL><INDENT>raise NoDriverErr(self)<EOL><DEDENT>elif drv_cnt != <NUM_LIT:1>:<EOL><INDENT>raise MultipleDriversErr(self)<EOL><DEDENT>return self.drivers[<NUM_LIT:0>]<EOL>

Returns a first driver if signal has only one driver.


@internal<EOL>def name_for_process_and_mark_outputs(statements: List[HdlStatement])-> str:

out_names = []<EOL>for stm in statements:<EOL><INDENT>for sig in stm._outputs:<EOL><INDENT>if not sig.hasGenericName:<EOL><INDENT>out_names.append(sig.name)<EOL><DEDENT><DEDENT><DEDENT>if out_names:<EOL><INDENT>return min(out_names)<EOL><DEDENT>else:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>

Resolve name for process and mark outputs of statemens as not hidden


separated = []<EOL>stm_filter = []<EOL>for stm in statements:<EOL><INDENT>stm._clean_signal_meta()<EOL>d = stm._cut_off_drivers_of(dstSignal)<EOL>if d is not None:<EOL><INDENT>separated.append(d)<EOL><DEDENT>f = d is not stm<EOL>stm_filter.append(f)<EOL><DEDENT>return list(compress(statements, stm_filter)), separated<EOL>


@internal<EOL>def statements_to_HWProcesses(statements: List[HdlStatement])-> Generator[HWProcess, None, None]:

<EOL>statements = copy(statements)<EOL>processes = []<EOL>while statements:<EOL><INDENT>stm = statements.pop()<EOL>proc_statements = [stm, ]<EOL>ps = _statements_to_HWProcesses(proc_statements, True)<EOL>processes.extend(ps)<EOL><DEDENT>yield from reduceProcesses(processes)<EOL>

Pack statements into HWProcess instances,
* for each out signal resolve it's drivers and collect them
* split statements if there is and combinational loop
* merge statements if it is possible
* resolve sensitivitilists
* wrap into HWProcess instance
* for every IO of process generate name if signal has not any


@internal<EOL>def markVisibilityOfSignals(ctx, ctxName, signals, interfaceSignals):

for sig in signals:<EOL><INDENT>driver_cnt = len(sig.drivers)<EOL>has_comb_driver = False<EOL>if driver_cnt > <NUM_LIT:1>:<EOL><INDENT>sig.hidden = False<EOL>for d in sig.drivers:<EOL><INDENT>if not isinstance(d, Operator):<EOL><INDENT>sig.hidden = False<EOL><DEDENT>is_comb_driver = False<EOL>if isinstance(d, PortItem):<EOL><INDENT>is_comb_driver = True<EOL><DEDENT>elif not d._now_is_event_dependent:<EOL><INDENT>for a in walk_assignments(d, sig):<EOL><INDENT>if not a.indexesand not a._is_completly_event_dependent:<EOL><INDENT>is_comb_driver = True<EOL>break<EOL><DEDENT><DEDENT><DEDENT>if has_comb_driver and is_comb_driver:<EOL><INDENT>raise MultipleDriversErr(<EOL>"<STR_LIT>" %<EOL>(ctx.getDebugScopeName(), sig))<EOL><DEDENT>has_comb_driver |= is_comb_driver<EOL><DEDENT><DEDENT>elif driver_cnt == <NUM_LIT:1>:<EOL><INDENT>if not isinstance(sig.drivers[<NUM_LIT:0>], Operator):<EOL><INDENT>sig.hidden = False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>sig.hidden = False<EOL>if sig not in interfaceSignals:<EOL><INDENT>if not sig.defVal._isFullVld():<EOL><INDENT>raise NoDriverErr(<EOL>sig, "<STR_LIT>", ctxName)<EOL><DEDENT>sig._const = True<EOL><DEDENT><DEDENT><DEDENT>

* check if all signals are driven by something
* mark signals with hidden = False if they are connecting statements
  or if they are external interface


def sig(self, name, dtype=BIT, clk=None, syncRst=None, defVal=None):

if isinstance(defVal, RtlSignal):<EOL><INDENT>assert defVal._const,"<STR_LIT>"<EOL>_defVal = defVal._auto_cast(dtype)<EOL><DEDENT>elif isinstance(defVal, Value):<EOL><INDENT>_defVal = defVal._auto_cast(dtype)<EOL><DEDENT>elif isinstance(defVal, InterfaceBase):<EOL><INDENT>_defVal = defVal._sig<EOL><DEDENT>else:<EOL><INDENT>_defVal = dtype.fromPy(defVal)<EOL><DEDENT>if clk is not None:<EOL><INDENT>s = RtlSyncSignal(self, name, dtype, _defVal)<EOL>if syncRst is not None and defVal is None:<EOL><INDENT>raise SigLvlConfErr(<EOL>"<STR_LIT>", name)<EOL><DEDENT>if syncRst is not None:<EOL><INDENT>r = If(syncRst._isOn(),<EOL>RtlSignal.__call__(s, _defVal)<EOL>).Else(<EOL>RtlSignal.__call__(s, s.next)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>r = [RtlSignal.__call__(s, s.next)]<EOL><DEDENT>If(clk._onRisingEdge(),<EOL>r<EOL>)<EOL><DEDENT>else:<EOL><INDENT>if syncRst:<EOL><INDENT>raise SigLvlConfErr(<EOL>"<STR_LIT>" % name)<EOL><DEDENT>s = RtlSignal(self, name, dtype, defVal=_defVal)<EOL><DEDENT>self.signals.add(s)<EOL>return s<EOL>

Create new signal in this context

:param clk: clk signal, if specified signal is synthesized
    as SyncSignal
:param syncRst: synchronous reset signal


def synthesize(self, name, interfaces, targetPlatform):

ent = Entity(name)<EOL>ent._name = name + "<STR_LIT>"  <EOL>for _, v in self.params.items():<EOL><INDENT>ent.generics.append(v)<EOL><DEDENT>if isinstance(interfaces, set):<EOL><INDENT>intfSet = interfaces<EOL><DEDENT>else:<EOL><INDENT>intfSet = set(interfaces)<EOL><DEDENT>for s in interfaces:<EOL><INDENT>pi = portItemfromSignal(s, ent)<EOL>pi.registerInternSig(s)<EOL>ent.ports.append(pi)<EOL>s.hidden = False<EOL><DEDENT>removeUnconnectedSignals(self)<EOL>markVisibilityOfSignals(self, name, self.signals, intfSet)<EOL>for proc in targetPlatform.beforeHdlArchGeneration:<EOL><INDENT>proc(self)<EOL><DEDENT>arch = Architecture(ent)<EOL>for p in statements_to_HWProcesses(self.statements):<EOL><INDENT>arch.processes.append(p)<EOL><DEDENT>for s in self.signals:<EOL><INDENT>if s not in intfSet and not s.hidden:<EOL><INDENT>arch.variables.append(s)<EOL><DEDENT><DEDENT>for u in self.subUnits:<EOL><INDENT>arch.componentInstances.append(u)<EOL><DEDENT>for su in distinctBy(self.subUnits, lambda x: x.name):<EOL><INDENT>arch.components.append(su)<EOL><DEDENT>self.synthesised = True<EOL>return [ent, arch]<EOL>

Build Entity and Architecture instance out of netlist representation


def __init__(self, ctx, name, var_type, defVal=None):

super().__init__(ctx, name, var_type, defVal)<EOL>self.next = RtlSignal(ctx, name + "<STR_LIT>", var_type,<EOL>nopVal=self, useNopVal=True)<EOL>

:param ctx: context in which is sig. created (instance of RtlNetlist)
:param name: suggested name
:param var_type: type of signal
:param defVal: default value for signal
    (used as def. val in hdl and for reset)


if isinstance(source, InterfaceBase):<EOL><INDENT>source = source._sig<EOL><DEDENT>if source is None:<EOL><INDENT>source = self._dtype.fromPy(None)<EOL><DEDENT>else:<EOL><INDENT>source = toHVal(source)<EOL>source = source._auto_cast(self._dtype)<EOL><DEDENT>a = Assignment(source, self.next)<EOL>return [a]<EOL>

assign to signal which is next value of this register

:return: list of assignments


try:<EOL><INDENT>drivers = sig.drivers<EOL><DEDENT>except AttributeError:<EOL><INDENT>return<EOL><DEDENT>if len(drivers) == <NUM_LIT:1>:<EOL><INDENT>d = drivers[<NUM_LIT:0>]<EOL>if isinstance(d, Operator):<EOL><INDENT>if isEventDependentOp(d.operator):<EOL><INDENT>yield (d.operator, d.operands[<NUM_LIT:0>])<EOL><DEDENT>else:<EOL><INDENT>for op in d.operands:<EOL><INDENT>yield from discoverEventDependency(op)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

:return: generator of tuples (event operator, signal)


return signal._dtype.getValueCls()<EOL>


@internal<EOL><INDENT>def naryOp(self, operator, opCreateDelegate, *otherOps) -> RtlSignalBase:<DEDENT>

k = (operator, *otherOps)<EOL>used = self._usedOps<EOL>try:<EOL><INDENT>return used[k]<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT>o = opCreateDelegate(self, *otherOps)<EOL>try:<EOL><INDENT>op_instanciated = (o.origin.operator == operator<EOL>and o.origin.operands[<NUM_LIT:0>] is self)<EOL><DEDENT>except AttributeError:<EOL><INDENT>op_instanciated = False<EOL><DEDENT>if op_instanciated:<EOL><INDENT>k_real = (operator, *o.origin.operands[<NUM_LIT:1>:])<EOL>real_o = used.get(k_real, None)<EOL>if real_o is not None:<EOL><INDENT>ctx = self.ctx<EOL>if ctx is not None:<EOL><INDENT>ctx.signals.remove(o)<EOL><DEDENT>op = o.origin<EOL>o.origin = None<EOL>o.drivers.clear()<EOL>for inp in op.operands:<EOL><INDENT>if isinstance(inp, RtlSignalBase):<EOL><INDENT>inp.endpoints.remove(op)<EOL><DEDENT><DEDENT>o = real_o<EOL><DEDENT>else:<EOL><INDENT>used[k_real] = o<EOL><DEDENT><DEDENT>used[k] = o<EOL>return o<EOL>

Try lookup operator with this parameters in _usedOps
if not found create new one and soter it in _usedOps

:param operator: instance of OpDefinition
:param opCreateDelegate: function (*ops) to create operator
:param otherOps: other operands (ops = self + otherOps)

:return: RtlSignal which is result of newly created operator


return self.naryOp(AllOps.EQ, tv(self)._eq, other)<EOL>

__eq__ is not overloaded because it will destroy hashability of object


try:<EOL><INDENT>d = self.singleDriver()<EOL>try:<EOL><INDENT>op = d.operator<EOL><DEDENT>except AttributeError:<EOL><INDENT>return<EOL><DEDENT>if op == AllOps.INDEX:<EOL><INDENT>indexedOn = d.operands[<NUM_LIT:0>]<EOL>if isinstance(indexedOn, RtlSignalBase):<EOL><INDENT>return indexedOn, [d.operands[<NUM_LIT:1>]]<EOL><DEDENT>else:<EOL><INDENT>raise Exception(<EOL>"<STR_LIT>" % indexedOn)<EOL><DEDENT><DEDENT><DEDENT>except (MultipleDriversErr, NoDriverErr):<EOL><INDENT>pass<EOL><DEDENT>

Find out if this signal is something indexed


def __call__(self, source) -> Assignment:

if isinstance(source, InterfaceBase):<EOL><INDENT>assert source._isAccessible<EOL>source = source._sig<EOL><DEDENT>if source is None:<EOL><INDENT>source = self._dtype.fromPy(None)<EOL><DEDENT>else:<EOL><INDENT>source = toHVal(source, suggestedType=self._dtype)<EOL>err = False<EOL>try:<EOL><INDENT>source = source._auto_cast(self._dtype)<EOL><DEDENT>except TypeConversionErr:<EOL><INDENT>err = True<EOL><DEDENT>if err:<EOL><INDENT>raise TypeConversionErr(<EOL>("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>% (source, source._dtype, self, self._dtype))<EOL><DEDENT><DEDENT>tmp = self._getIndexCascade()<EOL>if tmp:<EOL><INDENT>mainSig, indexCascade = tmp<EOL>self = mainSig<EOL><DEDENT>else:<EOL><INDENT>indexCascade = None<EOL><DEDENT>return Assignment(source, self, indexCascade)<EOL>

Create assignment to this signal

:attention: it is not call of function it is operator of assignment
:return: list of assignments


toDelete = set()<EOL>toSearch = netlist.signals<EOL>while toSearch:<EOL><INDENT>_toSearch = set()<EOL>for sig in toSearch:<EOL><INDENT>if not sig.endpoints:<EOL><INDENT>try:<EOL><INDENT>if sig._interface is not None:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>for e in sig.drivers:<EOL><INDENT>if isinstance(e, Operator):<EOL><INDENT>inputs = e.operands<EOL>if e.result is sig:<EOL><INDENT>e.result = None<EOL><DEDENT><DEDENT>else:<EOL><INDENT>inputs = e._inputs<EOL>netlist.statements.discard(e)<EOL><DEDENT>for op in inputs:<EOL><INDENT>if not isinstance(op, Value):<EOL><INDENT>try:<EOL><INDENT>op.endpoints.remove(e)<EOL><DEDENT>except KeyError:<EOL><INDENT>continue<EOL><DEDENT>_toSearch.add(op)<EOL><DEDENT><DEDENT><DEDENT>toDelete.add(sig)<EOL><DEDENT><DEDENT>if toDelete:<EOL><INDENT>for sig in toDelete:<EOL><INDENT>if sig.ctx == netlist:<EOL><INDENT>netlist.signals.remove(sig)<EOL><DEDENT>_toSearch.discard(sig)<EOL><DEDENT>toDelete = set()<EOL><DEDENT>toSearch = _toSearch<EOL><DEDENT>

If signal is not driving anything remove it


try:<EOL><INDENT>a, = proc.statements<EOL>if isinstance(a, Assignment):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT>return False<EOL>

check if process is just unconditional assignments
       and it is useless to merge them


@internal<EOL>def tryToMerge(procA: HWProcess, procB: HWProcess):

if (checkIfIsTooSimple(procA) or<EOL>checkIfIsTooSimple(procB) or<EOL>areSetsIntersets(procA.outputs, procB.sensitivityList) or<EOL>areSetsIntersets(procB.outputs, procA.sensitivityList) or<EOL>not HdlStatement._is_mergable_statement_list(procA.statements, procB.statements)):<EOL><INDENT>raise IncompatibleStructure()<EOL><DEDENT>procA.statements = HdlStatement._merge_statement_lists(<EOL>procA.statements, procB.statements)<EOL>procA.outputs.extend(procB.outputs)<EOL>procA.inputs.extend(procB.inputs)<EOL>procA.sensitivityList.extend(procB.sensitivityList)<EOL>return procA<EOL>

Try merge procB into procA

:raise IncompatibleStructure: if merge is not possible
:attention: procA is now result if merge has succeed
:return: procA which is now result of merge


<EOL>processes.sort(key=lambda x: (x.name, maxStmId(x)), reverse=True)<EOL>for _, procs in groupedby(processes, lambda p: p.rank):<EOL><INDENT>for iA, pA in enumerate(procs):<EOL><INDENT>if pA is None:<EOL><INDENT>continue<EOL><DEDENT>for iB, pB in enumerate(islice(procs, iA + <NUM_LIT:1>, None)):<EOL><INDENT>if pB is None:<EOL><INDENT>continue<EOL><DEDENT>try:<EOL><INDENT>pA = tryToMerge(pA, pB)<EOL><DEDENT>except IncompatibleStructure:<EOL><INDENT>continue<EOL><DEDENT>procs[iA + <NUM_LIT:1> + iB] = None<EOL><DEDENT><DEDENT>for p in procs:<EOL><INDENT>if p is not None:<EOL><INDENT>yield p<EOL><DEDENT><DEDENT><DEDENT>

Try to merge processes as much is possible

:param processes: list of processes instances


@internal<EOL>def nameAvailabilityCheck(obj, propName, prop):

if getattr(obj, propName, None) is not None:<EOL><INDENT>raise IntfLvlConfErr("<STR_LIT>" % <EOL>(obj, propName, repr(getattr(obj, propName)), prop))<EOL><DEDENT>


pass<EOL>

Configure object parameters

* setup all parameters on this object,
  use Param class instances to allow use of parameter inheritance
* called in __init__ of class


pass<EOL>

declarations

* do all declarations of externally accessible objects there (Interfaces)
* _declr method is called after _config
* if this object is Unit all interfaces are threaten as externally accessible interfaces
  if this object is Interface all subinterfaces are loaded


pass<EOL>

implementations

* implement functionality of design there
* called after _declr


@internal<EOL><INDENT>def __setattr__(self, attr, value) -> None:<DEDENT>

try:<EOL><INDENT>saListerner = self._setAttrListener<EOL><DEDENT>except AttributeError:<EOL><INDENT>super().__setattr__(attr, value)<EOL>return<EOL><DEDENT>if saListerner:<EOL><INDENT>saListerner(attr, value)<EOL><DEDENT>super().__setattr__(attr, value)<EOL>


@internal<EOL><INDENT>def _registerParameter(self, pName, parameter) -> None:<DEDENT>

nameAvailabilityCheck(self, pName, parameter)<EOL>try:<EOL><INDENT>hasName = parameter._name is not None<EOL><DEDENT>except AttributeError:<EOL><INDENT>hasName = False<EOL><DEDENT>if not hasName:<EOL><INDENT>parameter._name = pName<EOL><DEDENT>parameter._registerScope(pName, self)<EOL>if parameter.hasGenericName:<EOL><INDENT>parameter.name = pName<EOL><DEDENT>if parameter._parent is None:<EOL><INDENT>parameter._parent = self<EOL><DEDENT>self._params.append(parameter)<EOL>

Register Param object on interface level object


def _paramsShared(self, exclude=None, prefix="<STR_LIT>") -> MakeParamsShared:

return MakeParamsShared(self, exclude=exclude, prefix=prefix)<EOL>

Auto-propagate params by name to child components and interfaces
Usage:

.. code-block:: python

    with self._paramsShared():
        # your interfaces and unit which should share all params with "self" there

:param exclude: params which should not be shared
:param prefix: prefix which should be added to name of child parameters
    before parameter name matching


def _make_association(self, clk=None, rst=None) -> None:

if clk is not None:<EOL><INDENT>assert self._associatedClk is None<EOL>self._associatedClk = clk<EOL><DEDENT>if rst is not None:<EOL><INDENT>assert self._associatedRst is None<EOL>self._associatedRst = rst<EOL><DEDENT>

Associate this object with specified clk/rst


def _associated(self, clk=None, rst=None) -> MakeClkRstAssociations:

return MakeClkRstAssociations(self, clk, rst)<EOL>

associate newly added interfaces to "self" with selected clk, rst
(if interface is not associated agents try to find clk/rst by _getAssociatedClk/_getAssociatedRst
which will search for any clk/rst on parent recursively)
Usage:

.. code-block:: python

    with self._associated(clk=self.myClk, rst=self.myRst):
        self.myAxi = AxiStrem()
        # this interface is associated with myClk and myRst
        # simulation agents and component builders will use them

:param exclude: params which should not be shared


def _updateParamsFrom(self, otherObj:"<STR_LIT>", updater, exclude:set, prefix:str) -> None:

excluded = set()<EOL>if exclude is not None:<EOL><INDENT>exclude = set(exclude)<EOL><DEDENT>for myP in self._params:<EOL><INDENT>pPName = prefix + myP._scopes[self][<NUM_LIT:1>]<EOL>try:<EOL><INDENT>otherP = getattr(otherObj, pPName)<EOL>if not isinstance(otherP, Param):<EOL><INDENT>continue<EOL><DEDENT><DEDENT>except AttributeError:<EOL><INDENT>continue<EOL><DEDENT>if exclude and otherP in exclude:<EOL><INDENT>excluded.add(otherP)<EOL>continue<EOL><DEDENT>updater(self, myP, otherP)<EOL><DEDENT>if exclude is not None:<EOL><INDENT>assert excluded == exclude<EOL><DEDENT>

Update all parameters which are defined on self from otherObj

:param otherObj: other object which Param instances should be updated
:param updater: updater function(self, myParameter, onOtherParameterName, otherParameter)
:param exclude: iterable of parameter on otherObj object which should be excluded
:param prefix: prefix which should be added to name of paramters of this object before matching
    parameter name on parent


@internal<EOL><INDENT>def _registerUnit(self, uName, unit):<DEDENT>

nameAvailabilityCheck(self, uName, unit)<EOL>assert unit._parent is None<EOL>unit._parent = self<EOL>unit._name = uName<EOL>self._units.append(unit)<EOL>

Register unit object on interface level object


@internal<EOL><INDENT>def _registerInterface(self, iName, intf, isPrivate=False):<DEDENT>

nameAvailabilityCheck(self, iName, intf)<EOL>assert intf._parent is None<EOL>intf._parent = self<EOL>intf._name = iName<EOL>intf._ctx = self._ctx<EOL>if isPrivate:<EOL><INDENT>self._private_interfaces.append(intf)<EOL>intf._isExtern = False<EOL><DEDENT>else:<EOL><INDENT>self._interfaces.append(intf)<EOL>intf._isExtern = True<EOL><DEDENT>

Register interface object on interface level object


@internal<EOL><INDENT>def _registerArray(self, name, items):<DEDENT>

items._parent = self<EOL>items._name = name<EOL>for i, item in enumerate(items):<EOL><INDENT>setattr(self, "<STR_LIT>" % (name, i), item)<EOL><DEDENT>

Register array of items on interface level object


@internal<EOL><INDENT>def _registerUnitInImpl(self, uName, u):<DEDENT>

self._registerUnit(uName, u)<EOL>u._loadDeclarations()<EOL>self._lazyLoaded.extend(u._toRtl(self._targetPlatform))<EOL>u._signalsForMyEntity(self._ctx, "<STR_LIT>" + uName)<EOL>

:attention: unit has to be parametrized before it is registered
    (some components can change interface by parametrization)


@internal<EOL><INDENT>def _registerIntfInImpl(self, iName, i):<DEDENT>

raise NotImplementedError()<EOL>

Register interface in implementation phase


a = self._associatedRst<EOL>if a is not None:<EOL><INDENT>return a<EOL><DEDENT>p = self._parent<EOL>assert p is not None<EOL>if isinstance(p, UnitBase):<EOL><INDENT>return getRst(p)<EOL><DEDENT>else:<EOL><INDENT>return p._getAssociatedRst()<EOL><DEDENT>

If interface has associated rst(_n) return it otherwise
try to find rst(_n) on parent recursively


a = self._associatedClk<EOL>if a is not None:<EOL><INDENT>return a<EOL><DEDENT>p = self._parent<EOL>assert p is not None<EOL>if isinstance(p, UnitBase):<EOL><INDENT>return getClk(p)<EOL><DEDENT>else:<EOL><INDENT>return p._getAssociatedClk()<EOL><DEDENT>

If interface has associated clk return it otherwise
try to find clk on parent recursively


intf = self.__class__()<EOL>intf._updateParamsFrom(self)<EOL>return intf<EOL>

Create new instance of interface of same type and configuration


self._isExtern = isExtern<EOL>for prop in self._interfaces:<EOL><INDENT>prop._setAsExtern(isExtern)<EOL><DEDENT>


self._direction = INTF_DIRECTION.opposite(self._direction)<EOL>for intf in self._interfaces:<EOL><INDENT>intf._reverseDirection()<EOL><DEDENT>

Reverse direction of this interface in implementation stage


for si in intf._interfaces:<EOL><INDENT>yield from walkParams(si, discovered)<EOL><DEDENT>for p in intf._params:<EOL><INDENT>if p not in discovered:<EOL><INDENT>discovered.add(p)<EOL>yield p<EOL><DEDENT><DEDENT>

walk parameter instances on this interface


def connectPacked(srcPacked, dstInterface, exclude=None):

offset = <NUM_LIT:0><EOL>connections = []<EOL>for i in reversed(list(walkPhysInterfaces(dstInterface))):<EOL><INDENT>if exclude is not None and i in exclude:<EOL><INDENT>continue<EOL><DEDENT>sig = i._sig<EOL>t = sig._dtype<EOL>if t == BIT:<EOL><INDENT>s = srcPacked[offset]<EOL>offset += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>w = t.bit_length()<EOL>s = srcPacked[(w + offset): offset]<EOL>offset += w<EOL><DEDENT>connections.append(sig(s))<EOL><DEDENT>return connections<EOL>

Connect 1D vector signal to this structuralized interface

:param packedSrc: vector which should be connected
:param dstInterface: structuralized interface where should
    packedSrc be connected to
:param exclude: sub interfaces of self which should be excluded


_shouldEnter, _shouldYield = shouldEnterIntfFn(interface)<EOL>if _shouldYield:<EOL><INDENT>yield interface<EOL><DEDENT>if shouldEnterIntfFn:<EOL><INDENT>for intf in interface._interfaces:<EOL><INDENT>yield from walkFlatten(intf, shouldEnterIntfFn)<EOL><DEDENT><DEDENT>

:param shouldEnterIntfFn: function (actual interface)
    returns tuple (shouldEnter, shouldYield)


def packIntf(intf, masterDirEqTo=DIRECTION.OUT, exclude=None):

if not intf._interfaces:<EOL><INDENT>if intf._masterDir == masterDirEqTo:<EOL><INDENT>return intf._sig<EOL><DEDENT>return None<EOL><DEDENT>res = None<EOL>for i in intf._interfaces:<EOL><INDENT>if exclude is not None and i in exclude:<EOL><INDENT>continue<EOL><DEDENT>if i._interfaces:<EOL><INDENT>if i._masterDir == DIRECTION.IN:<EOL><INDENT>d = DIRECTION.opposite(masterDirEqTo)<EOL><DEDENT>else:<EOL><INDENT>d = masterDirEqTo<EOL><DEDENT>s = i._pack(d, exclude=exclude)<EOL><DEDENT>else:<EOL><INDENT>if i._masterDir == masterDirEqTo:<EOL><INDENT>s = i._sig<EOL><DEDENT>else:<EOL><INDENT>s = None<EOL><DEDENT><DEDENT>if s is not None:<EOL><INDENT>if res is None:<EOL><INDENT>res = s<EOL><DEDENT>else:<EOL><INDENT>res = res._concat(s)<EOL><DEDENT><DEDENT><DEDENT>return res<EOL>

Concatenate all signals to one big signal, recursively

:param masterDirEqTo: only signals with this direction are packed
:param exclude: sequence of signals/interfaces to exclude


def _reg(self, name, dtype=BIT, defVal=None, clk=None, rst=None):

if clk is None:<EOL><INDENT>clk = getClk(self)<EOL><DEDENT>if defVal is None:<EOL><INDENT>rst = None<EOL><DEDENT>else:<EOL><INDENT>rst = getRst(self)._sig<EOL><DEDENT>if isinstance(dtype, HStruct):<EOL><INDENT>if defVal is not None:<EOL><INDENT>raise NotImplementedError()<EOL><DEDENT>container = dtype.fromPy(None)<EOL>for f in dtype.fields:<EOL><INDENT>if f.name is not None:<EOL><INDENT>r = self._reg("<STR_LIT>" % (name, f.name), f.dtype)<EOL>setattr(container, f.name, r)<EOL><DEDENT><DEDENT>return container<EOL><DEDENT>return self._ctx.sig(name,<EOL>dtype=dtype,<EOL>clk=clk._sig,<EOL>syncRst=rst,<EOL>defVal=defVal)<EOL>

Create register in this unit

:param defVal: default value of this register,
    if this value is specified reset of this component is used
    (unit has to have single interface of class Rst or Rst_n)
:param clk: optional clok signal specification
:param rst: optional reset signal specification
:note: rst/rst_n resolution is done from signal type,
    if it is negated type it is rst_n
:note: if clk or rst is not specifid default signal
    from parent unit will be used


def _sig(self, name, dtype=BIT, defVal=None):

if isinstance(dtype, HStruct):<EOL><INDENT>if defVal is not None:<EOL><INDENT>raise NotImplementedError()<EOL><DEDENT>container = dtype.fromPy(None)<EOL>for f in dtype.fields:<EOL><INDENT>if f.name is not None:<EOL><INDENT>r = self._sig("<STR_LIT>" % (name, f.name), f.dtype)<EOL>setattr(container, f.name, r)<EOL><DEDENT><DEDENT>return container<EOL><DEDENT>return self._ctx.sig(name, dtype=dtype, defVal=defVal)<EOL>


for pi in self._entity.ports:<EOL><INDENT>pi.connectInternSig()<EOL><DEDENT>for i in chain(self._interfaces, self._private_interfaces):<EOL><INDENT>i._clean()<EOL><DEDENT>

Disconnect internal signals so unit can be reused by parent unit


def toRtl(unitOrCls: Unit, name: str=None,<EOL>serializer: GenericSerializer=VhdlSerializer,<EOL>targetPlatform=DummyPlatform(), saveTo: str=None):

if not isinstance(unitOrCls, Unit):<EOL><INDENT>u = unitOrCls()<EOL><DEDENT>else:<EOL><INDENT>u = unitOrCls<EOL><DEDENT>u._loadDeclarations()<EOL>if name is not None:<EOL><INDENT>assert isinstance(name, str)<EOL>u._name = name<EOL><DEDENT>globScope = serializer.getBaseNameScope()<EOL>mouduleScopes = {}<EOL>serializedClasses = {}<EOL>serializedConfiguredUnits = {}<EOL>doSerialize = True<EOL>createFiles = saveTo is not None<EOL>if createFiles:<EOL><INDENT>os.makedirs(saveTo, exist_ok=True)<EOL>files = UniqList()<EOL><DEDENT>else:<EOL><INDENT>codeBuff = []<EOL><DEDENT>for obj in u._toRtl(targetPlatform):<EOL><INDENT>doSerialize = serializer.serializationDecision(<EOL>obj,<EOL>serializedClasses,<EOL>serializedConfiguredUnits)<EOL>if doSerialize:<EOL><INDENT>if isinstance(obj, Entity):<EOL><INDENT>s = globScope.fork(<NUM_LIT:1>)<EOL>s.setLevel(<NUM_LIT:2>)<EOL>ctx = serializer.getBaseContext()<EOL>ctx.scope = s<EOL>mouduleScopes[obj] = ctx<EOL>ctx.currentUnit = obj.origin<EOL>sc = serializer.Entity(obj, ctx)<EOL>if createFiles:<EOL><INDENT>fName = obj.name + serializer.fileExtension<EOL>fileMode = '<STR_LIT:w>'<EOL><DEDENT><DEDENT>elif isinstance(obj, Architecture):<EOL><INDENT>try:<EOL><INDENT>ctx = mouduleScopes[obj.entity]<EOL><DEDENT>except KeyError:<EOL><INDENT>raise SerializerException(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>% (obj.getEntityName()))<EOL><DEDENT>sc = serializer.Architecture(obj, ctx)<EOL>if createFiles:<EOL><INDENT>fName = obj.getEntityName() + serializer.fileExtension<EOL>fileMode = '<STR_LIT:a>'<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if hasattr(obj, "<STR_LIT>"):<EOL><INDENT>for fn in obj._hdlSources:<EOL><INDENT>if isinstance(fn, str):<EOL><INDENT>shutil.copy2(fn, saveTo)<EOL>files.append(fn)<EOL>continue<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>sc = serializer.asHdl(obj)<EOL><DEDENT><DEDENT>if sc:<EOL><INDENT>if createFiles:<EOL><INDENT>fp = os.path.join(saveTo, fName)<EOL>files.append(fp)<EOL>with open(fp, fileMode) as f:<EOL><INDENT>if fileMode == '<STR_LIT:a>':<EOL><INDENT>f.write("<STR_LIT:\n>")<EOL><DEDENT>f.write(<EOL>serializer.formatter(sc)<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>codeBuff.append(sc)<EOL><DEDENT><DEDENT><DEDENT>elif not createFiles:<EOL><INDENT>try:<EOL><INDENT>name = '<STR_LIT>' % obj.name<EOL><DEDENT>except AttributeError:<EOL><INDENT>name = "<STR_LIT>"<EOL><DEDENT>codeBuff.append(serializer.comment(<EOL>"<STR_LIT>" % (<EOL>obj.__class__.__name__, name)))<EOL><DEDENT><DEDENT>if createFiles:<EOL><INDENT>return files<EOL><DEDENT>else:<EOL><INDENT>return serializer.formatter(<EOL>"<STR_LIT:\n>".join(codeBuff)<EOL>)<EOL><DEDENT>

Convert unit to RTL using specified serializer

:param unitOrCls: unit instance or class, which should be converted
:param name: name override of top unit (if is None name is derived
    form class name)
:param serializer: serializer which should be used for to RTL conversion
:param targetPlatform: metainformatins about target platform, distributed
    on every unit under _targetPlatform attribute
    before Unit._impl() is called
:param saveTo: directory where files should be stored
    If None RTL is returned as string.
:raturn: if saveTo returns RTL string else returns list of file names
    which were created


self._setAttrListener = None<EOL>self._associatedClk = None<EOL>self._associatedRst = None<EOL>self._parent = None<EOL>super().__init__()<EOL>self._masterDir = masterDir<EOL>self._direction = INTF_DIRECTION.UNKNOWN<EOL>self._ctx = None<EOL>if loadConfig:<EOL><INDENT>self._loadConfig()<EOL><DEDENT>self._isExtern = False<EOL>self._isAccessible = True<EOL>self._ag = None<EOL>

This constructor is called when constructing new interface,
it is usually done manually while creating Unit or
automatically while extracting interfaces from UnitWithSoure

:param masterDir: direction which this interface should have for master
:param multiplyedBy: this can be instance of integer or Param,
    this mean the interface is array of the interfaces
    where multiplyedBy is the size
:param loadConfig: do load config in __init__


assert not hasattr(self, "<STR_LIT>") or not self._interfaces,"<STR_LIT>"<EOL>self._direction = DIRECTION.asIntfDirection(DIRECTION.opposite(self._masterDir))<EOL>return self<EOL>

Note that this interface will be master

:return: self


return self._connectTo(other)<EOL>

:attention: it is not call of function it is operator of assignment


if not hasattr(self, "<STR_LIT>"):<EOL><INDENT>self._interfaces = []<EOL><DEDENT>self._setAttrListener = self._declrCollector<EOL>self._declr()<EOL>self._setAttrListener = None<EOL>for i in self._interfaces:<EOL><INDENT>i._isExtern = self._isExtern<EOL>i._loadDeclarations()<EOL><DEDENT>for p in self._params:<EOL><INDENT>p.setReadOnly()<EOL><DEDENT>if self._isExtern:<EOL><INDENT>if self._direction == INTF_DIRECTION.UNKNOWN:<EOL><INDENT>self._direction = INTF_DIRECTION.MASTER<EOL><DEDENT>self._setDirectionsLikeIn(self._direction)<EOL><DEDENT>

load declaratoins from _declr method
This function is called first for parent and then for children


@internal<EOL><INDENT>def _clean(self, rmConnetions=True, lockNonExternal=True):<DEDENT>

if self._interfaces:<EOL><INDENT>for i in self._interfaces:<EOL><INDENT>i._clean(rmConnetions=rmConnetions,<EOL>lockNonExternal=lockNonExternal)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self._sigInside = self._sig<EOL>del self._sig<EOL><DEDENT>if lockNonExternal and not self._isExtern:<EOL><INDENT>self._isAccessible = False<EOL><DEDENT>

Remove all signals from this interface (used after unit is synthesized
and its parent is connecting its interface to this unit)


@internal<EOL><INDENT>def _signalsForInterface(self, context, prefix='<STR_LIT>', typeTransform=None):<DEDENT>

sigs = []<EOL>if self._interfaces:<EOL><INDENT>for intf in self._interfaces:<EOL><INDENT>sigs.extend(<EOL>intf._signalsForInterface(context, prefix,<EOL>typeTransform=typeTransform))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if hasattr(self, '<STR_LIT>'):<EOL><INDENT>sigs = [self._sig]<EOL><DEDENT>else:<EOL><INDENT>t = self._dtype<EOL>if typeTransform is not None:<EOL><INDENT>t = typeTransform(t)<EOL><DEDENT>s = context.sig(prefix + self._getPhysicalName(), t)<EOL>s._interface = self<EOL>self._sig = s<EOL>if hasattr(self, '<STR_LIT>'):<EOL><INDENT>self._boundedEntityPort.connectSig(self._sig)<EOL><DEDENT>sigs = [s]<EOL><DEDENT><DEDENT>return sigs<EOL>

generate _sig for each interface which has no subinterface
if already has _sig return it instead

:param context: instance of RtlNetlist where signals should be created
:param prefix: name prefix for created signals
:param typeTransform: optional function (type) returns modified type
    for signal


if hasattr(self, "<STR_LIT>"):<EOL><INDENT>return self._boundedEntityPort.name<EOL><DEDENT>else:<EOL><INDENT>return self._getFullName().replace('<STR_LIT:.>', self._NAME_SEPARATOR)<EOL><DEDENT>


return HObjList._getFullName(self)<EOL>


i = self._params.index(p)<EOL>pName = p._scopes[self][<NUM_LIT:1>]<EOL>assert i > -<NUM_LIT:1><EOL>self._params[i] = newP<EOL>del p._scopes[self]  <EOL>newP._registerScope(pName, self)<EOL>object.__setattr__(self, pName, newP)<EOL>

Replace parameter on this interface (in configuration stage)

:ivar pName: actual name of param on me
:ivar newP: new Param instance by which should be old replaced


def _updateParamsFrom(self, otherObj, updater=_default_param_updater,<EOL>exclude=None, prefix="<STR_LIT>"):

PropDeclrCollector._updateParamsFrom(self, otherObj, updater, exclude, prefix)<EOL>

:note: doc in :func:`~hwt.synthesizer.interfaceLevel.propDeclCollector._updateParamsFrom`


try:<EOL><INDENT>interfaces = self._interfaces<EOL><DEDENT>except AttributeError:<EOL><INDENT>interfaces = None<EOL><DEDENT>if interfaces is None:<EOL><INDENT>_intf = self._clone()<EOL>_intf._loadDeclarations()<EOL>interfaces = _intf._interfaces<EOL><DEDENT>if interfaces:<EOL><INDENT>w = <NUM_LIT:0><EOL>for i in interfaces:<EOL><INDENT>w += i._bit_length()<EOL><DEDENT>return w<EOL><DEDENT>else:<EOL><INDENT>return self._dtype.bit_length()<EOL><DEDENT>

Sum of all width of interfaces in this interface


def _connectTo(self, master, exclude=None, fit=False):

return list(self._connectToIter(master, exclude, fit))<EOL>

connect to another interface interface (on rtl level)
works like self <= master in VHDL


name = "<STR_LIT>"<EOL>tmp = self<EOL>while isinstance(tmp, (InterfaceBase, HObjList)):<EOL><INDENT>if hasattr(tmp, "<STR_LIT>"):<EOL><INDENT>n = tmp._name<EOL><DEDENT>else:<EOL><INDENT>n = '<STR_LIT>'<EOL><DEDENT>if name == '<STR_LIT>':<EOL><INDENT>name = n<EOL><DEDENT>else:<EOL><INDENT>name = n + '<STR_LIT:.>' + name<EOL><DEDENT>if hasattr(tmp, "<STR_LIT>"):<EOL><INDENT>tmp = tmp._parent<EOL><DEDENT>else:<EOL><INDENT>tmp = None<EOL><DEDENT><DEDENT>return name<EOL>


def _make_association(self, *args, **kwargs):

for o in self:<EOL><INDENT>o._make_association(*args, **kwargs)<EOL><DEDENT>

Delegate _make_association on items

:note: doc in :func:`~hwt.synthesizer.interfaceLevel.propDeclCollector._make_association`


def _updateParamsFrom(self, *args, **kwargs):

for o in self:<EOL><INDENT>o._updateParamsFrom(*args, **kwargs)<EOL><DEDENT>


isNegated = False<EOL>try:<EOL><INDENT>drivers = c.drivers<EOL><DEDENT>except AttributeError:<EOL><INDENT>return (c, isNegated)<EOL><DEDENT>if len(drivers) == <NUM_LIT:1>:<EOL><INDENT>d = list(c.drivers)[<NUM_LIT:0>]<EOL>if isinstance(d, Operator) and d.operator == AllOps.NOT:<EOL><INDENT>c = d.operands[<NUM_LIT:0>]<EOL>isNegated = True<EOL><DEDENT><DEDENT>return (c, isNegated)<EOL>

if is negated return original cond and negated flag


def op(*operands, key=None) -> RtlSignalBase:<EOL><INDENT>"""<STR_LIT>"""<EOL>assert operands, operands<EOL>top = None<EOL>if key is not None:<EOL><INDENT>operands = map(key, operands)<EOL><DEDENT>for s in operands:<EOL><INDENT>if top is None:<EOL><INDENT>top = s<EOL><DEDENT>else:<EOL><INDENT>top = fn(top, s)<EOL><DEDENT><DEDENT>return top<EOL><DEDENT>return op<EOL>

Function to create variadic operator function

:param fn: function to perform binary operation


return self._sig._isOn()<EOL>


return self._sig._eq(other)<EOL>

Equality operator "==" is not used because it would damage python
ecosystem


return self._sig.__ne__(other)<EOL>


return self._sig.__gt__(other)<EOL>


return self._sig.__lt__(other)<EOL>


return self._sig.__ge__(other)<EOL>


return self._sig.__le__(other)<EOL>


return self._sig.__invert__()<EOL>

~ operator - logical negation for one bit signals and hBool
           bitwise inversion for wider signals


return self._sig.__and__(other)<EOL>

& operator - logical 'and' for one bit signals and hBool
bitwise and for wider signals


return self._sig.__xor__(other)<EOL>

^ operator - logical '!=' for one bit signals and hBool
bitwise and for wider signals


return self._sig.__or__(other)<EOL>

| operator - logical 'or' for one bit signals and hBool
bitwise and for wider signals


return self._sig._reversed()<EOL>


return self._sig._concat(*others)<EOL>


return self._sig.__getitem__(key)<EOL>


assert self._isAccessible<EOL>return self._sig(source)<EOL>

connect this signal to driver

:attention: it is not call of function it is operator of assignment
:return: list of assignments


structFields = []<EOL>for m in interfaceMap:<EOL><INDENT>f = HTypeFromIntfMapItem(m)<EOL>structFields.append(f)<EOL><DEDENT>return HStruct(*structFields)<EOL>

Generate flattened register map for HStruct

:param interfaceMap: sequence of
    tuple (type, name) or (will create standard struct field member)
    interface or (will create a struct field from interface)
    instance of hdl type (is used as padding)
    tuple (list of interface, name)
:param DATA_WIDTH: width of word
:param terminalNodes: None or set whre are placed StructField instances
    which are derived directly from interface
:return: generator of tuple (type, name, BusFieldInfo)


Process for injecting of this callback loop into simulator


self.requests.append((READ, addr))<EOL>


self.requests.append((WRITE, addr, data))<EOL>


if self.notReset(sim) and self._enabled:<EOL><INDENT>self.wrRd(sim.write, <NUM_LIT:1>)<EOL>yield sim.waitOnCombUpdate()<EOL>d = self.doRead(sim)<EOL>self.data.append(d)<EOL><DEDENT>else:<EOL><INDENT>self.wrRd(sim.write, <NUM_LIT:0>)<EOL><DEDENT>


return sim.read(self.intf.data)<EOL>


sim.write(data, self.intf.data)<EOL>


r = sim.read<EOL>if self.actualData is NOP and self.data:<EOL><INDENT>self.actualData = self.data.popleft()<EOL><DEDENT>do = self.actualData is not NOP<EOL>if do:<EOL><INDENT>self.doWrite(sim, self.actualData)<EOL><DEDENT>else:<EOL><INDENT>self.doWrite(sim, None)<EOL><DEDENT>en = self.notReset(sim) and self._enabled<EOL>if not (en and do):<EOL><INDENT>return<EOL><DEDENT>yield sim.waitOnCombUpdate()<EOL>rd = self.isRd(r)<EOL>if en:<EOL><INDENT>assert rd.vldMask, (<EOL>("<STR_LIT>"<EOL>"<STR_LIT>") %<EOL>(sim.now, self.intf))<EOL><DEDENT>if rd.val:<EOL><INDENT>if self._debugOutput is not None:<EOL><INDENT>self._debugOutput.write("<STR_LIT>" % (<EOL>self.intf._getFullName(),<EOL>sim.now, self.actualData))<EOL><DEDENT>if self.data:<EOL><INDENT>self.actualData = self.data.popleft()<EOL><DEDENT>else:<EOL><INDENT>self.actualData = NOP<EOL><DEDENT><DEDENT>


return self.intf.rd._sigInside<EOL>


return readFn(self._rd)<EOL>


return self.intf.vld._sigInside<EOL>


return readFn(self._vld)<EOL>

get value of "valid" signal, override f.e. when you
need to use signal with reversed polarity


r = sim.read<EOL>if self.notReset(sim):<EOL><INDENT>if self._lastRd is not <NUM_LIT:1>:<EOL><INDENT>self.wrRd(sim.write, <NUM_LIT:1>)<EOL>self._lastRd = <NUM_LIT:1><EOL>try:<EOL><INDENT>onMonitorReady = self.onMonitorReady<EOL><DEDENT>except AttributeError:<EOL><INDENT>onMonitorReady = None<EOL><DEDENT>if onMonitorReady is not None:<EOL><INDENT>onMonitorReady(sim)<EOL><DEDENT><DEDENT>yield sim.waitOnCombUpdate()<EOL>vld = self.isVld(r)<EOL>assert vld.vldMask, (sim.now, self.intf,<EOL>"<STR_LIT>")<EOL>if vld.val:<EOL><INDENT>d = self.doRead(sim)<EOL>if self._debugOutput is not None:<EOL><INDENT>self._debugOutput.write(<EOL>"<STR_LIT>" % (<EOL>self.intf._getFullName(),<EOL>sim.now, d))<EOL><DEDENT>self.data.append(d)<EOL>if self._afterRead is not None:<EOL><INDENT>self._afterRead(sim)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if self._lastRd is not <NUM_LIT:0>:<EOL><INDENT>self.wrRd(sim.write, <NUM_LIT:0>)<EOL>self._lastRd = <NUM_LIT:0><EOL><DEDENT><DEDENT>


r = sim.read<EOL>if self.actualData is NOP and self.data:<EOL><INDENT>self.actualData = self.data.popleft()<EOL><DEDENT>doSend = self.actualData is not NOP<EOL>if self.actualData is not self._lastWritten:<EOL><INDENT>if doSend:<EOL><INDENT>self.doWrite(sim, self.actualData)<EOL><DEDENT>else:<EOL><INDENT>self.doWrite(sim, None)<EOL><DEDENT>self._lastWritten = self.actualData<EOL><DEDENT>en = self.notReset(sim)<EOL>vld = int(en and doSend)<EOL>if self._lastVld is not vld:<EOL><INDENT>self.wrVld(sim.write, vld)<EOL>self._lastVld = vld<EOL><DEDENT>if not self._enabled:<EOL><INDENT>sim.add_process(self.checkIfRdWillBeValid(sim))<EOL>return<EOL><DEDENT>yield sim.waitOnCombUpdate()<EOL>rd = self.isRd(r)<EOL>assert rd.vldMask, (sim.now, self.intf,<EOL>"<STR_LIT>")<EOL>if not vld:<EOL><INDENT>return<EOL><DEDENT>if rd.val:<EOL><INDENT>if self._debugOutput is not None:<EOL><INDENT>self._debugOutput.write("<STR_LIT>" % (<EOL>self.intf._getFullName(),<EOL>sim.now,<EOL>self.actualData))<EOL><DEDENT>a = self.actualData<EOL>if self.data:<EOL><INDENT>self.actualData = self.data.popleft()<EOL><DEDENT>else:<EOL><INDENT>self.actualData = NOP<EOL><DEDENT>onDriverWriteAck = getattr(self, "<STR_LIT>", None)<EOL>if onDriverWriteAck is not None:<EOL><INDENT>onDriverWriteAck(sim)<EOL><DEDENT>onDone = getattr(a, "<STR_LIT>", None)<EOL>if onDone is not None:<EOL><INDENT>onDone(sim)<EOL><DEDENT><DEDENT>

Push data to interface

set vld high and wait on rd in high then pass new data


def pullDownAfter(sig, initDelay=<NUM_LIT:6> * Time.ns):

def _pullDownAfter(s):<EOL><INDENT>s.write(True, sig)<EOL>yield s.wait(initDelay)<EOL>s.write(False, sig)<EOL><DEDENT>return _pullDownAfter<EOL>

:return: simulation driver which keeps signal value high for initDelay
    then it sets value to 0


def pullUpAfter(sig, initDelay=<NUM_LIT:6> * Time.ns):

def _pullDownAfter(s):<EOL><INDENT>s.write(False, sig)<EOL>yield s.wait(initDelay)<EOL>s.write(True, sig)<EOL><DEDENT>return _pullDownAfter<EOL>

:return: Simulation driver which keeps signal value low for initDelay then
    it sets value to 1


obj.clk = Clk()<EOL>obj.rst_n = Rst_n()<EOL>

Construct clk, rst_n signal on object (usually Unit/Interface instance)


obj.clk = Clk()<EOL>obj.rst = Rst()<EOL>

Construct clk, rst signal on object (usually Unit/Interface instance)


try:<EOL><INDENT>dst = getattr(unit, intfName)<EOL><DEDENT>except AttributeError:<EOL><INDENT>return<EOL><DEDENT>if not dst._sig.drivers:<EOL><INDENT>connect(src, dst)<EOL><DEDENT>

Try connect src to interface of specified name on unit.
Ignore if interface is not present or if it already has driver.


clk = obj.clk<EOL>for u in obj._units:<EOL><INDENT>_tryConnect(clk, u, '<STR_LIT>')<EOL><DEDENT>

Propagate "clk" clock signal to all subcomponents


clk = obj.clk<EOL>rst_n = obj.rst_n<EOL>for u in obj._units:<EOL><INDENT>_tryConnect(clk, u, '<STR_LIT>')<EOL>_tryConnect(rst_n, u, '<STR_LIT>')<EOL>_tryConnect(~rst_n, u, '<STR_LIT>')<EOL><DEDENT>

Propagate "clk" clock and negative reset "rst_n" signal
to all subcomponents


clk = obj.clk<EOL>rst = obj.rst<EOL>for u in obj._units:<EOL><INDENT>_tryConnect(clk, u, '<STR_LIT>')<EOL>_tryConnect(~rst, u, '<STR_LIT>')<EOL>_tryConnect(rst, u, '<STR_LIT>')<EOL><DEDENT>

Propagate "clk" clock and reset "rst" signal to all subcomponents


rst_n = obj.rst_n<EOL>for u in obj._units:<EOL><INDENT>_tryConnect(rst_n, u, '<STR_LIT>')<EOL>_tryConnect(~rst_n, u, '<STR_LIT>')<EOL><DEDENT>

Propagate negative reset "rst_n" signal
to all subcomponents


rst = obj.rst<EOL>for u in obj._units:<EOL><INDENT>_tryConnect(~rst, u, '<STR_LIT>')<EOL>_tryConnect(rst, u, '<STR_LIT>')<EOL><DEDENT>

Propagate reset "rst" signal
to all subcomponents


return Signal(masterDir,<EOL>Bits(width, signed, forceVector=True),<EOL>loadConfig)<EOL>

Create basic :class:`.Signal` interface where type is vector


return <NUM_LIT:1><EOL>

:return: size of one word in unit of address


return int(self.DATA_WIDTH)<EOL>

:return: how many bits is one unit of address (f.e. 8 bits for
    char * pointer, 36 for 36 bit bram)


cls._serializeDecision = staticmethod(_serializeExclude_eval)<EOL>return cls<EOL>

Never serialize HDL objects from this class


cls._serializeDecision = staticmethod(_serializeOnce_eval)<EOL>return cls<EOL>

Serialize HDL objects only once per class


cls._serializeDecision = staticmethod(_serializeParamsUniq_eval)<EOL>return cls<EOL>

Decide to serialize only when parameters are unique


@internal<EOL>def _serializeExclude_eval(parentUnit, obj, isDeclaration, priv):

if isDeclaration:<EOL><INDENT>prepareEntity(obj, parentUnit.__class__.__name__, priv)<EOL><DEDENT>if priv is None:<EOL><INDENT>priv = parentUnit<EOL><DEDENT>return False, priv<EOL>

Always decide not to serialize obj

:param priv: private data for this function first unit of this class
:return: tuple (do serialize this object, next priv)


@internal<EOL>def _serializeOnce_eval(parentUnit, obj, isDeclaration, priv):

clsName = parentUnit.__class__.__name__<EOL>if isDeclaration:<EOL><INDENT>obj.name = clsName<EOL><DEDENT>if priv is None:<EOL><INDENT>priv = parentUnit<EOL><DEDENT>elif isDeclaration:<EOL><INDENT>prepareEntity(obj, clsName, parentUnit)<EOL><DEDENT>serialize = priv is parentUnit<EOL>return serialize, priv<EOL>

Decide to serialize only first obj of it's class

:param priv: private data for this function
    (first object with class == obj.__class__)

:return: tuple (do serialize this object, next priv)
    where priv is private data for this function
    (first object with class == obj.__class__)


@internal<EOL>def _serializeParamsUniq_eval(parentUnit, obj, isDeclaration, priv):

params = paramsToValTuple(parentUnit)<EOL>if priv is None:<EOL><INDENT>priv = {}<EOL><DEDENT>if isDeclaration:<EOL><INDENT>try:<EOL><INDENT>prevUnit = priv[params]<EOL><DEDENT>except KeyError:<EOL><INDENT>priv[params] = parentUnit<EOL>return True, priv<EOL><DEDENT>prepareEntity(obj, prevUnit._entity.name, prevUnit)<EOL>return False, priv<EOL><DEDENT>return priv[params] is parentUnit, priv<EOL>

Decide to serialize only objs with uniq parameters and class

:param priv: private data for this function
    ({frozen_params: obj})

:return: tuple (do serialize this object, next priv)


return ValueWidthRequirementScope(self, val)<EOL>

Create scope where width is required on values or not

.. code-block:: python

    with ctx.valWidthReq(True):
       #...


@classmethod<EOL><INDENT>def asHdl(cls, obj, ctx: HwtSerializerCtx):<DEDENT>

if isinstance(obj, RtlSignalBase):<EOL><INDENT>return cls.SignalItem(obj, ctx)<EOL><DEDENT>elif isinstance(obj, Value):<EOL><INDENT>return cls.Value(obj, ctx)<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>serFn = obj.asHwt<EOL><DEDENT>except AttributeError:<EOL><INDENT>serFn = None<EOL><DEDENT>if serFn is not None:<EOL><INDENT>return serFn(cls, ctx)<EOL><DEDENT>try:<EOL><INDENT>serFn = getattr(cls, obj.__class__.__name__)<EOL><DEDENT>except AttributeError:<EOL><INDENT>serFn = None<EOL><DEDENT>if serFn is not None:<EOL><INDENT>return serFn(obj, ctx)<EOL><DEDENT>raise SerializerException("<STR_LIT>" % (obj))<EOL><DEDENT>

Convert object to HDL string

:param obj: object to serialize
:param ctx: HwtSerializerCtx instance


@classmethod<EOL><INDENT>def Entity(cls, ent: Entity, ctx: HwtSerializerCtx):<DEDENT>

cls.Entity_prepare(ent, ctx, serialize=False)<EOL>ent.name = ctx.scope.checkedName(ent.name, ent, isGlobal=True)<EOL>ports = list(<EOL>map(lambda p: (p.name, cls.HdlType(p._dtype, ctx)),<EOL>ent.ports))<EOL>return unitHeadTmpl.render(<EOL>name=ent.name,<EOL>ports=ports,<EOL>)<EOL>

Entity is just forward declaration of Architecture, it is not used
in most HDL languages as there is no recursion in hierarchy