Esempio n. 1
0
def reduceProcesses(processes):
    """
    Try to merge processes as much is possible

    :param processes: list of processes instances
    """
    # sort to make order of merging same deterministic
    processes.sort(key=lambda x: (x.name, maxStmId(x)), reverse=True)
    # now try to reduce processes with nearly same structure of statements into one
    # to minimize number of processes
    for _, procs in groupedby(processes, lambda p: p.rank):
        for iA, pA in enumerate(procs):
            if pA is None:
                continue
            for iB, pB in enumerate(islice(procs, iA + 1, None)):
                if pB is None:
                    continue

                try:
                    pA = tryToMerge(pA, pB)
                except IncompatibleStructure:
                    continue
                procs[iA + 1 + iB] = None
                # procs[iA] = pA

        for p in procs:
            if p is not None:
                yield p
Esempio n. 2
0
    def Architecture(cls, arch: Architecture, ctx):
        with CurrentUnitSwap(ctx, arch.entity.origin):
            variables = []
            procs = []
            extraTypes = set()
            extraTypes_serialized = []
            arch.variables.sort(key=lambda x: (x.name, x._instId))
            arch.processes.sort(key=lambda x: (x.name, maxStmId(x)))
            arch.components.sort(key=lambda x: x.name)
            arch.componentInstances.sort(key=lambda x: x._name)

            childCtx = ctx.withIndent()

            for v in arch.variables:
                t = v._dtype
                # if type requires extra definition
                if isinstance(t, (HEnum, HArray)) and t not in extraTypes:
                    extraTypes.add(v._dtype)
                    extraTypes_serialized.append(
                        cls.HdlType(t, childCtx, declaration=True))

                v.name = ctx.scope.checkedName(v.name, v)
                serializedVar = cls.SignalItem(v, childCtx, declaration=True)
                variables.append(serializedVar)

            for p in arch.processes:
                procs.append(cls.HWProcess(p, childCtx))

            # architecture names can be same for different entities
            # arch.name = scope.checkedName(arch.name, arch, isGlobal=True)

            uniqComponents = list(
                map(lambda x: x[1][0],
                    groupedby(arch.components, lambda c: c.name)))
            uniqComponents.sort(key=lambda c: c.name)
            components = list(
                map(lambda c: cls.Component(c, childCtx), uniqComponents))

            componentInstances = list(
                map(lambda c: cls.ComponentInstance(c, childCtx),
                    arch.componentInstances))

            return cls.architectureTmpl.render(
                indent=getIndent(ctx.indent),
                entityName=arch.getEntityName(),
                name=arch.name,
                variables=variables,
                extraTypes=extraTypes_serialized,
                processes=procs,
                components=components,
                componentInstances=componentInstances)
Esempio n. 3
0
    def Architecture(cls, arch, scope):
        variables = []
        procs = []
        extraTypes = set()
        extraTypes_serialized = []
        arch.variables.sort(key=lambda x: x.name)
        arch.processes.sort(key=lambda x: (x.name, maxStmId(x)))
        arch.components.sort(key=lambda x: x.name)
        arch.componentInstances.sort(key=lambda x: x._name)

        def createTmpVarFn(suggestedName, dtype):
            raise NotImplementedError()

        for v in arch.variables:
            t = v._dtype
            # if type requires extra definition
            if isinstance(t, (Enum, Array)) and t not in extraTypes:
                extraTypes.add(v._dtype)
                extraTypes_serialized.append(
                    cls.HdlType(t, createTmpVarFn, scope, declaration=True))

            v.name = scope.checkedName(v.name, v)
            serializedVar = cls.SignalItem(v, createTmpVarFn, declaration=True)
            variables.append(serializedVar)

        for p in arch.processes:
            procs.append(cls.HWProcess(p, scope))

        # architecture names can be same for different entities
        # arch.name = scope.checkedName(arch.name, arch, isGlobal=True)

        uniqComponents = list(
            map(lambda x: x[1][0], groupedby(arch.components,
                                             lambda c: c.name)))
        uniqComponents.sort(key=lambda c: c.name)
        components = list(
            map(lambda c: cls.Component(c, createTmpVarFn), uniqComponents))

        componentInstances = list(
            map(lambda c: cls.ComponentInstance(c, createTmpVarFn, scope),
                arch.componentInstances))

        return architectureTmpl.render({
            "entityName": arch.getEntityName(),
            "name": arch.name,
            "variables": variables,
            "extraTypes": extraTypes_serialized,
            "processes": procs,
            "components": components,
            "componentInstances": componentInstances
        })
Esempio n. 4
0
    def buildProcessesOutOfAssignments(self):
        """
        Render conditional assignments to statements and wrap them with process statement
        """
        assigments = where(self.startsOfDataPaths,
                           lambda x: isinstance(x, Assignment))
        for sig, dps in groupedby(assigments, lambda x: x.dst):
            dps = list(dps)
            name = ""
            if not sig.hasGenericName:
                name = sig.name
            sig.hidden = False

            haveNotIndexes = True
            for dp in dps:
                haveNotIndexes = haveNotIndexes and not dp.indexes

            # render sequential statements in process
            # (conversion from netlist to statements)
            hasCombDriver = False
            for stm in renderIfTree(dps):

                p = HWProcess("assig_process_" + name)
                if sig._useNopVal and not isEnclosed(stm):
                    n = sig._nopVal
                    p.statements.append(Assignment(n, sig))
                    if isinstance(n, RtlSignal):
                        p.sensitivityList.add(n)

                p.statements.append(stm)

                sensitivity = discoverSensitivity(stm)
                p.sensitivityList.update(sensitivity)

                isEventDependent = False
                for s in p.sensitivityList:
                    if isinstance(s, Operator):
                        # event operator
                        s.ops[0].hidden = False
                        isEventDependent = True
                    else:
                        s.hidden = False

                if hasCombDriver and not isEventDependent and haveNotIndexes:
                    raise MultipleDriversExc(
                        "%s: Signal %s has multiple combinational drivers" %
                        (self.getDebugScopeName(), name))
                hasCombDriver = hasCombDriver or not isEventDependent

                yield p
Esempio n. 5
0
    def _merge_statements(statements: List["HdlStatement"])\
            -> Tuple[List["HdlStatement"], int]:
        """
        Merge statements in list to remove duplicated if-then-else trees

        :return: tuple (list of merged statements, rank decrease due merging)
        :note: rank decrease is sum of ranks of reduced statements
        :attention: statement list has to me mergable
        """
        order = {}
        for i, stm in enumerate(statements):
            order[stm] = i

        new_statements = []
        rank_decrease = 0

        for rank, stms in groupedby(statements, lambda s: s.rank):
            if rank == 0:
                new_statements.extend(stms)
            else:
                if len(stms) == 1:
                    new_statements.extend(stms)
                    continue

                # try to merge statements if they are same condition tree
                for iA, stmA in enumerate(stms):
                    if stmA is None:
                        continue

                    for iB, stmB in enumerate(islice(stms, iA + 1, None)):
                        if stmB is None:
                            continue

                        if stmA._is_mergable(stmB):
                            rank_decrease += stmB.rank
                            stmA._merge_with_other_stm(stmB)
                            stms[iA + 1 + iB] = None
                            new_statements.append(stmA)
                        else:
                            new_statements.append(stmA)
                            new_statements.append(stmB)

        new_statements.sort(key=lambda stm: order[stm])
        return new_statements, rank_decrease
Esempio n. 6
0
    def as_hdl_HdlModuleDef(self, o: HdlModuleDef):
        """
        Translate hwt types and expressions to HDL AST and add explicit components
        """
        _o = super(ToHdlAstVhdl2008, self).as_hdl_HdlModuleDef(o)
        component_insts = []
        for c in _o.objs:
            component_insts.extend(self._find_HdlCompInst(c))

        # select comonent instances whith an unique module_name
        components = [
            x[1][0]
            for x in groupedby(component_insts, lambda c: c.module_name)
        ]
        components.sort(key=lambda c: c.module_name)
        components = [self.as_hdl_HldComponent(c) for c in components]
        if components:
            _o.objs = components + _o.objs

        res = HdlContext()
        res.objs.extend(self.DEFAULT_IMPORTS)
        res.objs.append(_o)
        return res
Esempio n. 7
0
    def readPart(self, awAddr, w_hs):
        ADDR_STEP = self._getAddrStep()
        DW = int(self.DATA_WIDTH)
        # build read data output mux
        r = self.bus.r
        ar = self.bus.ar
        rSt_t = HEnum('rSt_t', ['rdIdle', 'bramRd', 'rdData'])
        isBramAddr = self._sig("isBramAddr")

        rSt = FsmBuilder(self, rSt_t, stateRegName='rSt')\
        .Trans(rSt_t.rdIdle,
            (ar.valid & ~isBramAddr & ~w_hs, rSt_t.rdData),
            (ar.valid & isBramAddr & ~w_hs, rSt_t.bramRd)
        ).Trans(rSt_t.bramRd,
            (~w_hs, rSt_t.rdData)
        ).Trans(rSt_t.rdData,
            (r.ready, rSt_t.rdIdle)
        ).stateReg

        arRd = rSt._eq(rSt_t.rdIdle)
        ar.ready(arRd & ~w_hs)

        # save ar addr
        arAddr = self._reg('arAddr', ar.addr._dtype)
        If(ar.valid & arRd, arAddr(ar.addr))

        isInAddrRange = self.isInMyAddrRange(arAddr)
        r.valid(rSt._eq(rSt_t.rdData))
        If(isInAddrRange, r.resp(RESP_OKAY)).Else(r.resp(RESP_SLVERR))
        if self._bramPortMapped:
            rdataReg = self._reg("rdataReg", r.data._dtype)
            _isInBramFlags = []
            # list of tuples (cond, rdataReg assignment)
            rregCases = []
            # index of bram from where we reads from
            bramRdIndx = self._reg("bramRdIndx",
                                   Bits(log2ceil(len(self._bramPortMapped))))
            bramRdIndxSwitch = Switch(bramRdIndx)
            for bramIndex, t in enumerate(self._bramPortMapped):
                port = self.getPort(t)

                # map addr for bram ports
                dstAddrStep = port.dout._dtype.bit_length()
                (_isMyArAddr,
                 arAddrConnect) = self.propagateAddr(ar.addr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                (_,
                 ar2AddrConnect) = self.propagateAddr(arAddr, ADDR_STEP,
                                                      port.addr, dstAddrStep,
                                                      t)
                (_isMyAwAddr,
                 awAddrConnect) = self.propagateAddr(awAddr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                prioritizeWrite = _isMyAwAddr & w_hs

                If(prioritizeWrite,
                   awAddrConnect).Elif(rSt._eq(rSt_t.rdIdle),
                                       arAddrConnect).Else(ar2AddrConnect)
                _isInBramFlags.append(_isMyArAddr)

                port.en((_isMyArAddr & ar.valid) | prioritizeWrite)
                port.we(prioritizeWrite)

                rregCases.append((_isMyArAddr, bramRdIndx(bramIndex)))
                bramRdIndxSwitch.Case(bramIndex, rdataReg(port.dout))

            bramRdIndxSwitch.Default(rdataReg(rdataReg))
            If(arRd, SwitchLogic(rregCases))
            isBramAddr(Or(*_isInBramFlags))

        else:
            rdataReg = None
            isBramAddr(0)

        directlyMappedWors = []
        for w, items in sorted(groupedby(
                self._directlyMapped, lambda t: t.bitAddr // DW *
            (DW // ADDR_STEP)),
                               key=lambda x: x[0]):
            lastBit = 0
            res = []
            items.sort(key=lambda t: t.bitAddr)
            for t in items:
                b = t.bitAddr % DW
                if b > lastBit:
                    # add padding
                    pad_w = b - lastBit
                    pad = Bits(pad_w).fromPy(None)
                    res.append(pad)
                    lastBit += pad_w
                din = self.getPort(t).din
                res.append(din)
                lastBit += din._dtype.bit_length()

            if lastBit != DW:
                # add at end padding
                pad = Bits(DW - lastBit).fromPy(None)
                res.append(pad)

            directlyMappedWors.append((w, Concat(*reversed(res))))

        Switch(arAddr).addCases([
            (w[0], r.data(w[1])) for w in directlyMappedWors
        ]).Default(r.data(rdataReg))
Esempio n. 8
0
    def readPart(self, awAddr, w_hs):
        ADDR_STEP = self._getAddrStep()
        DW = int(self.DATA_WIDTH)
        # build read data output mux
        r = self.bus.r
        ar = self.bus.ar
        rSt_t = HEnum('rSt_t', ['rdIdle', 'bramRd', 'rdData'])
        isBramAddr = self._sig("isBramAddr")

        rSt = FsmBuilder(self, rSt_t, stateRegName='rSt')\
        .Trans(rSt_t.rdIdle,
            (ar.valid & ~isBramAddr & ~w_hs, rSt_t.rdData),
            (ar.valid & isBramAddr & ~w_hs, rSt_t.bramRd)
        ).Trans(rSt_t.bramRd,
            (~w_hs, rSt_t.rdData)
        ).Trans(rSt_t.rdData,
            (r.ready, rSt_t.rdIdle)
        ).stateReg

        arRd = rSt._eq(rSt_t.rdIdle)
        ar.ready(arRd & ~w_hs)

        # save ar addr
        arAddr = self._reg('arAddr', ar.addr._dtype)
        If(ar.valid & arRd,
            arAddr(ar.addr)
        )

        isInAddrRange = self.isInMyAddrRange(arAddr)
        r.valid(rSt._eq(rSt_t.rdData))
        If(isInAddrRange,
            r.resp(RESP_OKAY)
        ).Else(
            r.resp(RESP_SLVERR)
        )
        if self._bramPortMapped:
            rdataReg = self._reg("rdataReg", r.data._dtype)
            _isInBramFlags = []
            # list of tuples (cond, rdataReg assignment)
            rregCases = []
            # index of bram from where we reads from
            bramRdIndx = self._reg("bramRdIndx", Bits(
                log2ceil(len(self._bramPortMapped))))
            bramRdIndxSwitch = Switch(bramRdIndx)
            for bramIndex, t in enumerate(self._bramPortMapped):
                port = self.getPort(t)

                # map addr for bram ports
                dstAddrStep = port.dout._dtype.bit_length()
                (_isMyArAddr, arAddrConnect) = self.propagateAddr(
                    ar.addr, ADDR_STEP, port.addr, dstAddrStep, t)
                (_, ar2AddrConnect) = self.propagateAddr(
                    arAddr, ADDR_STEP, port.addr, dstAddrStep, t)
                (_isMyAwAddr, awAddrConnect) = self.propagateAddr(
                    awAddr, ADDR_STEP, port.addr, dstAddrStep, t)
                prioritizeWrite = _isMyAwAddr & w_hs

                If(prioritizeWrite,
                    awAddrConnect
                ).Elif(rSt._eq(rSt_t.rdIdle),
                    arAddrConnect
                ).Else(
                    ar2AddrConnect
                )
                _isInBramFlags.append(_isMyArAddr)

                port.en((_isMyArAddr & ar.valid) | prioritizeWrite)
                port.we(prioritizeWrite)

                rregCases.append((_isMyArAddr, bramRdIndx(bramIndex)))
                bramRdIndxSwitch.Case(bramIndex, rdataReg(port.dout))

            bramRdIndxSwitch.Default(rdataReg(rdataReg))
            If(arRd,
               SwitchLogic(rregCases)
            )
            isBramAddr(Or(*_isInBramFlags))

        else:
            rdataReg = None
            isBramAddr(0)

        directlyMappedWors = []
        for w, items in sorted(groupedby(self._directlyMapped,
                                         lambda t: t.bitAddr // DW * (DW // ADDR_STEP)),
                               key=lambda x: x[0]):
            lastBit = 0
            res = []
            items.sort(key=lambda t: t.bitAddr)
            for t in items:
                b = t.bitAddr % DW
                if b > lastBit:
                    # add padding
                    pad_w = b - lastBit
                    pad = Bits(pad_w).fromPy(None)
                    res.append(pad)
                    lastBit += pad_w
                din = self.getPort(t).din
                res.append(din)
                lastBit += din._dtype.bit_length()

            if lastBit != DW:
                # add at end padding
                pad = Bits(DW - lastBit).fromPy(None)
                res.append(pad)

            directlyMappedWors.append((w, Concat(*reversed(res))))

        Switch(arAddr).addCases(
            [(w[0], r.data(w[1]))
             for w in directlyMappedWors]
        ).Default(
            r.data(rdataReg)
        )