Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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)
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)
Esempio n. 8
0
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)