Beispiel #1
0
    def _replace_child_statement(self, stm: HdlStatement,
                                 replacement: List[HdlStatement],
                                 update_io: bool) -> None:
        if update_io:
            raise NotImplementedError()
        for branch_list in (self.ifTrue, *(elif_stms
                                           for _, elif_stms in self.elIfs),
                            self.ifFalse):
            if branch_list is None:
                continue
            try:
                i = branch_list.index(stm)
            except ValueError:
                # not in list
                continue

            self.rank -= stm.rank
            branch_list[i:i + 1] = replacement
            for rstm in replacement:
                rstm._set_parent_stm(self)
            # reset IO because it was shared with this statement
            stm._destroy()
            return

        raise ValueError("Statement", stm, "not found in ", self)
Beispiel #2
0
def walk_assignments(stm: HdlStatement, dst: RtlSignal)\
        ->Generator[Assignment, None, None]:
    if isinstance(stm, Assignment):
        if dst is stm.dst:
            yield stm
    else:
        for _stm in stm._iter_stms():
            yield from walk_assignments(_stm, dst)
Beispiel #3
0
def _count_mux_inputs_for_outputs(stm: HdlStatement, cnt):
    if isinstance(stm, Assignment):
        cnt[stm.dst] += 1
    else:
        for _stm in stm._iter_stms():
            if isinstance(_stm, Assignment):
                cnt[_stm.dst] += 1
            else:
                _count_mux_inputs_for_outputs(_stm, cnt)
Beispiel #4
0
def walkInputsForSpecificOutput(output_sig: RtlSignalBase, stm: HdlStatement):
    if output_sig not in stm._outputs:
        return
    if isinstance(stm, Assignment):
        assert stm.dst is output_sig
        yield from stm._inputs
    elif isinstance(stm, IfContainer):
        yield stm.cond
        for c, _ in stm.elIfs:
            yield c
        for _stm in stm._iter_stms():
            yield from walkInputsForSpecificOutput(output_sig, _stm)
    elif isinstance(stm, SwitchContainer):
        yield stm.switchOn
        for _stm in stm._iter_stms():
            yield from walkInputsForSpecificOutput(output_sig, _stm)
    else:
        raise NotImplementedError(stm)
Beispiel #5
0
def tryToMerge(procA: HdlStatementBlock, procB: HdlStatementBlock):
    """
    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
    """
    if (checkIfIsTooSimple(procA) or checkIfIsTooSimple(procB)
            or areSetsIntersets(procA._outputs, procB._sensitivity)
            or areSetsIntersets(procB._outputs, procA._sensitivity)
            or not HdlStatement._is_mergable_statement_list(
                procA.statements, procB.statements)):
        raise IncompatibleStructure()

    procA.statements = HdlStatement._merge_statement_lists(
        procA.statements, procB.statements)

    procA._outputs.extend(procB._outputs)
    procA._inputs.extend(procB._inputs)
    procA._sensitivity.extend(procB._sensitivity)

    return procA
Beispiel #6
0
def find_independent_slice_drivers(stm: HdlStatement):
    if isinstance(stm, Assignment):
        if stm.indexes and len(stm.indexes) == 1 and isinstance(
                stm.dst._dtype, Bits):
            dst = stm.dst
            for i in stm.indexes:
                if not isConst(i):
                    return

            can_directly_replace_with_src_expr = stm.parentStm is None
            yield (dst, tuple(stm.indexes), can_directly_replace_with_src_expr,
                   stm.src if can_directly_replace_with_src_expr else None)
    else:
        for _stm in stm._iter_stms():
            yield from find_independent_slice_drivers(_stm)
Beispiel #7
0
 def _clean_signal_meta(self):
     self._sensitivity = None
     self._ifTrue_enclosed_for = None
     self._elIfs_enclosed_for = None
     self._ifFalse_enclosed_for = None
     HdlStatement._clean_signal_meta(self)
Beispiel #8
0
 def _clean_signal_meta(self):
     self._case_enclosed_for = None
     self._default_enclosed_for = None
     HdlStatement._clean_signal_meta(self)
Beispiel #9
0
def extract_part_drivers_stm(stm: HdlStatement,
                             signal_parts: Dict[RtlSignal,
                                                List[Tuple[RtlSignal,
                                                           List[HValue]]]]):
    if isinstance(stm, Assignment):
        if stm.indexes and len(stm.indexes) == 1:
            dst = stm.dst
            parts = signal_parts.get(dst, None)
            if parts is None:
                return False
            indexes = _format_indexes(stm.indexes)
            new_dsts, do_remove_stm = parts[indexes]
            if isinstance(new_dsts, list):
                assert len(new_dsts) > 1, (dst, new_dsts, stm)
                assert not do_remove_stm, (dst, new_dsts, stm)
                # the driven slice was split to multiple sub slices
                replacement = []
                dst_offset = new_dsts[0][-1][1]
                for i in new_dsts:
                    new_dst = parts[i][0]
                    new_src = stm.src
                    for _i in i:
                        high, low = _i[0] - dst_offset, _i[1] - dst_offset
                        assert high > 0 and low >= 0, dst_offset
                        assert high > low, (dst, stm, (high, low))
                        new_src = new_src[high:low]
                    a = new_dst(new_src)
                    replacement.append(a)

                # it has to hav parent statement because it needs to be nested
                # because otherwise it would not have some overlapping parts driven diferently
                # inder some condition
                stm.parentStm._replace_child_statement(stm, replacement, False)
            elif do_remove_stm:
                # remove current assignment because we are using src directly
                assert stm.parentStm is None, stm
                stm._destroy()
            else:
                # rewrite the Assignment instance to use new dst
                replacement = [
                    new_dsts(stm.src),
                ]
                stm.parentStm._replace_child_statement(stm, replacement, False)

            return True

    elif isinstance(stm, (IfContainer, SwitchContainer, HdlStatementBlock)):
        modified = False
        for _stm in stm._iter_stms():
            modified |= extract_part_drivers_stm(_stm, signal_parts)
        if modified:
            assert not stm._enclosed_for, "_enclosed_for is expected not to be initialized yet"
            outputs = stm._outputs
            inputs = stm._inputs
            stm._outputs = UniqList()
            stm._inputs = UniqList()
            stm._collect_io()
            if stm.parentStm is None:
                for o in outputs:
                    if o not in stm._outputs:
                        o.drivers.remove(stm)

                for i in inputs:
                    if i not in stm._inputs:
                        i.endpoints.remove(stm)

            return True

    else:
        raise NotImplementedError("Unknown statement ", stm)

    return False