def connectOuterSig(self, signal): """ Connect to port item on subunit """ if self.direction == DIRECTION.IN: if self.src is not None: raise HwtSyntaxError( "Port %s is already associated with %r" % (self.name, self.src)) self.src = signal signal.endpoints.append(self) elif self.direction == DIRECTION.OUT: if self.dst is not None: raise HwtSyntaxError( "Port %s is already associated with %r" % (self.name, self.dst)) self.dst = signal signal.drivers.append(self) else: raise NotImplementedError(self) signal.hidden = False signal.ctx.subUnits.add(self.unit)
def __init__(self, switchOn): switchOn = _intfToSig(switchOn) if not isinstance(switchOn, RtlSignalBase): raise HwtSyntaxError("Select is not signal, it is not certain" " if this an error or desire") if arr_any(discoverEventDependency(switchOn), lambda x: True): raise HwtSyntaxError("Can not switch on result of event operator") super(Switch, self).__init__(switchOn, []) switchOn.ctx.statements.add(self)
def _getIndexCascade(self): """ Find out if this signal is something indexed """ intf = self indexes = [] while True: try: # now I am result of the index xxx[xx] <= source # get index op d = intf.singleDriver() try: op = d.operator except AttributeError: break if op == AllOps.INDEX: # get signal on which is index applied indexedOn = d.operands[0] if isinstance(indexedOn, RtlSignalBase): intf = indexedOn indexes.append(d.operands[1]) else: raise HwtSyntaxError( f"can not assign to a static value {indexedOn}") except SignalDriverErr: break if not indexes: indexes = None else: indexes.reverse() return intf, indexes
def Else(self, *statements): assert self.parentStm is None if self.ifFalse is not None: raise HwtSyntaxError( "Else on this if-then-else statement was already used") self.rank += 1 self.ifFalse = [] self._register_stements(statements, self.ifFalse) return self
def connectInternSig(self, signal): """ Connect signal from internal side of of this component to this port. """ if self.direction == DIRECTION.OUT: if self.src is not None: raise HwtSyntaxError( "Port %s is already associated with signal %s" % (self.name, str(self.src))) self.src = signal self.src.endpoints.append(self) elif self.direction == DIRECTION.IN: if self.dst is not None: raise HwtSyntaxError( "Port %s is already associated with signal %s" % (self.name, str(self.dst))) self.dst = signal self.dst.drivers.append(self) else: raise NotImplementedError(self.direction)
def _discover_sensitivity(self, seen) -> None: """ Doc on parent class :meth:`HdlStatement._discover_sensitivity` """ assert self._sensitivity is None, self ctx = self._sensitivity = SensitivityCtx() casual_sensitivity = set() self.switchOn._walk_sensitivity(casual_sensitivity, seen, ctx) if ctx.contains_ev_dependency: raise HwtSyntaxError("Can not switch on event operator result", self.switchOn) ctx.extend(casual_sensitivity) for stm in self._iter_stms(): stm._discover_sensitivity(seen) ctx.extend(stm._sensitivity)
def __init__(self, cond, *statements): """ :param cond: condition in if statement :param statements: list of statements which should be active if condition is met """ cond_sig = _intfToSig(cond) if not isinstance(cond_sig, RtlSignalBase): raise HwtSyntaxError( "Condition is not signal, it is not certain" " if this is an error or desire ", cond_sig) super(If, self).__init__(cond_sig) self.rank = 1 self._inputs.append(cond_sig) cond_sig.endpoints.append(self) ev_dep = arr_any(discoverEventDependency(cond_sig), lambda x: True) self._event_dependent_from_branch = 0 if ev_dep else None self._register_stements(statements, self.ifTrue) self._get_rtl_context().statements.add(self)
def _statements_to_HdlStatementBlocks(_statements, tryToSolveCombLoops)\ -> Generator[HdlStatementBlock, None, None]: assert _statements # try to simplify statements proc_statements = [] for _stm in _statements: _stm._clean_signal_meta() stms, _ = _stm._try_reduce() proc_statements.extend(stms) if not proc_statements: return outputs = UniqList() _inputs = UniqList() sensitivity = UniqList() enclosed_for = set() _proc_statements = [] for _stm in proc_statements: seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() if _stm._outputs: # remove a statement entirely if it has no ouput # (empty if statment or something similar) # simulation only processes should not be processed by this function # and process should always drive something, unless it is useless outputs.extend(_stm._outputs) _inputs.extend(_stm._inputs) sensitivity.extend(_stm._sensitivity) enclosed_for.update(_stm._enclosed_for) _proc_statements.append(_stm) proc_statements = _proc_statements if not proc_statements: # this can happen e.g. when If does not contains any Assignment return sensitivity_recompute = False enclosure_recompute = False enclosure_values = {} for sig in outputs: # inject nop_val if needed if sig._nop_val is not NO_NOPVAL and sig not in enclosed_for: enclosure_recompute = True n = sig._nop_val enclosure_values[sig] = n if not isinstance(n, Value): _inputs.append(n) sensitivity_recompute = True if enclosure_recompute: # we have some enclosure values, try fill missing code branches with # this values do_enclose_for = [o for o in outputs if o in enclosure_values] fill_stm_list_with_enclosure(None, enclosed_for, proc_statements, do_enclose_for, enclosure_values) if enclosure_recompute or sensitivity_recompute: for _stm in proc_statements: _stm._clean_signal_meta() seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() if sensitivity_recompute: sensitivity = UniqList() for _stm in proc_statements: sensitivity.extend(_stm._sensitivity) for o in outputs: assert not o.hidden, o seen = set() inputs = UniqList() for i in _inputs: inputs.extend(i._walk_public_drivers(seen)) intersect = outputs.intersection_set(sensitivity) if intersect: # there is a combinational loop inside a single process which # can not be solved by separation of statments in process if not tryToSolveCombLoops: raise HwtSyntaxError( "Combinational loop on signal(s)", intersect) # try to solve combinational loops by separating drivers of signals # from statements for sig in intersect: proc_statements, proc_stms_select = cut_off_drivers_of( sig, proc_statements) yield from _statements_to_HdlStatementBlocks(proc_stms_select, False) if proc_statements: yield from _statements_to_HdlStatementBlocks(proc_statements, False) else: # no combinational loops, wrap current statemetns to a process instance name = name_for_process(outputs) yield HdlStatementBlock("assig_process_" + name, proc_statements, sensitivity, inputs, outputs)