Exemplo n.º 1
0
    def HWProcess_operators(cls, sig: RtlSignal, ctx: ResourceContext, synchronous):
        seen = ctx.seen
        for d in sig.drivers:
            if (not isinstance(d, Operator)
                    or d in seen):
                continue

            skip_op = d.operator in IGNORED_OPERATORS
            if not skip_op:
                if d.operator == AllOps.EQ:
                    o1 = d.operands[1]
                    if (isinstance(o1, Value)
                            and o1._dtype.bit_length() == 1
                            and o1.val):
                        # to bool conversion
                        skip_op = True
                elif d.operator == AllOps.INDEX:
                    o1 = d.operands[1]
                    skip_op = True
                    if isConst(o1):
                        # constant signal silice
                        pass
                    else:
                        o0 = d.operands[0]
                        if isinstance(o0._dtype, HArray):
                            ctx.registerRAM_read_port(o0, o1, synchronous)
                        else:
                            ctx.registerMUX(d, sig, 2)
                elif d.operator == AllOps.TERNARY:
                    o1 = d.operands[1]
                    o2 = d.operands[2]
                    if (isConst(o1)
                            and bool(o1)
                            and isConst(o2)
                            and not bool(o2)):
                        # to bit conversion
                        skip_op = True
                    else:
                        raise NotImplementedError("Ternary as mux")

            if not skip_op:
                ctx.registerOperator(d)

            for op in d.operands:
                if (not isinstance(op, RtlSignal)
                        or not op.hidden
                        or op in seen):
                    continue
                cls.HWProcess_operators(op, ctx, synchronous)
Exemplo n.º 2
0
def addStmAsLNode(root: LNode, stm: HdlStatement,
                  stmPorts: Dict[LNode, Signal2stmPortCtx],
                  netCtx: NetCtxs) -> LNode:
    toL = root._node2lnode
    isOnlyAssig = isinstance(stm, HdlAssignmentContainer)
    if isOnlyAssig and not stm.indexes and isConst(stm.src):
        # is only constant
        n = ValueAsLNode(root, stm.src)
        ctx, _ = netCtx.getDefault(stm.dst)
        ctx.addDriver(n.east[0])

    elif isOnlyAssig:
        # inline operators in assignment to parent node
        n = toL[stm] = VirtualLNode(root, stm)

    else:
        # render content of statement into container node
        bodyText = toStr(stm)
        n = root.addNode(
            originObj=stm,
            cls="Process",
            bodyText=bodyText)

        stmPorts[n] = Signal2stmPortCtx(n)

    return n
Exemplo n.º 3
0
    def addInputPort(self,
                     node,
                     name,
                     i: Union[HValue, RtlSignalBase],
                     side=PortSide.WEST):
        """
        Add and connect input port on subnode

        :param node: node where to add input port
        :param name: name of newly added port
        :param i: input value
        :param side: side where input port should be added
        """
        root = self.node
        port = node.addPort(name, PortType.INPUT, side)
        netCtxs = self.netCtxs

        if isinstance(i, LPort):
            root.addEdge(i, port)
        elif isConst(i):
            i = i.staticEval()
            c, wasThereBefore = self.netCtxs.getDefault(i)
            if not wasThereBefore:
                v = ValueAsLNode(root, i).east[0]
                c.addDriver(v)
            c.addEndpoint(port)
        elif i.hidden:
            # later connect driver of this signal to output port
            ctx, wasThereBefore = netCtxs.getDefault(i)
            if not wasThereBefore:
                self.lazyLoadNet(i)
            ctx.addEndpoint(port)
        else:
            portCtx = self.portCtx
            rootCtx, _ = self.rootNetCtxs.getDefault(i)

            if self.isVirtual:
                # later connect signal in root to input port or input port of
                # wrap node
                rootCtx.addEndpoint(port)
            else:
                # spot input port on this wrap node if required
                isNewlySpotted = (i, PortType.INPUT) not in portCtx.data
                src = portCtx.register(i, PortType.INPUT)
                # connect input port on wrap node with specified output port
                ctx, _ = netCtxs.getDefault(i)
                ctx.addDriver(src)
                ctx.addEndpoint(port)

                if isNewlySpotted:
                    # get input port from parent view
                    _port = portCtx.getOutside(i, PortType.INPUT)
                    rootCtx.addEndpoint(_port)
Exemplo n.º 4
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)
Exemplo n.º 5
0
def extractSplits(root: LNode):
    """
    convert group of indexed assignments witch are splitting signal to Split node

    a = sig[0]
    b = sig[1]
    to
    a, b = sig

    :param toL: dictionary {hdl object: layout object}
    """
    toL = root._node2lnode
    signals = sorted(root.originObj._ctx.signals, key=RtlSignal_sort_key)

    # search from "sig" side (look at doc string)
    for s in signals:
        if len(s.drivers) == 1 and len(s.endpoints) > 1:
            sliceParts = []
            for ep in s.endpoints:
                if isinstance(ep, HdlAssignmentContainer
                              ) and not ep.indexes and ep.src.hidden:
                    op = ep.src.origin
                else:
                    op = ep

                if isinstance(op, Operator)\
                        and op.operator == AllOps.INDEX\
                        and op.operands[0] is s:
                    index = op.operands[1]
                    if isConst(index):
                        sliceRange = index.staticEval().to_py()
                        if isinstance(sliceRange, int):
                            sliceRange = slice(sliceRange + 1, sliceRange)

                        if ep not in toL:
                            continue
                        sliceParts.append((sliceRange, ep, toL[ep]))

            for _root, _sliceParts in groupby(sliceParts,
                                              lambda x: x[2].parent):
                # the slices may be spoted in some sub node, in that case we need to extract it only in this sub node
                _sliceParts = list(_sliceParts)
                if _sliceParts:
                    extractSplitsAsSingleNode(_root, _sliceParts, toL)
Exemplo n.º 6
0
    def createAssignment(self, assig: HdlAssignmentContainer,
                         connectOut: bool):
        pctx = self.portCtx
        src = assig.src
        inputs = [
            src,
        ]
        isBitToVectorConv = False
        if assig.indexes:
            # if len(assig.indexes) > 1:
            #    raise NotImplementedError()
            i = assig.indexes[0]
            if len(assig.indexes) == 1\
                    and isConst(i)\
                    and assig.dst._dtype.bit_length() == src._dtype.bit_length() == 1:
                # bit to vector conversion
                isBitToVectorConv = True
            else:
                inputs.extend(assig.indexes)

        for s in inputs:
            if (not isConst(s) and s.hidden and s not in self.netCtxs):
                self.lazyLoadNet(s)

        if not isBitToVectorConv and assig.indexes:
            if len(assig.indexes) == 1 and not isConst(assig.indexes[0]):
                # assignments to separate bites are extracted
                # by indexedAssignmentsToConcatenation as concatenation
                # this has to be kind of MUX
                controls = [
                    assig.indexes[0],
                ]
                return self.createMux(assig.dst,
                                      inputs,
                                      controls,
                                      connectOut,
                                      latched=False)
            else:
                for i in assig.indexes:
                    assert isConst(i), (
                        i,
                        "It is expected that this is staticaly indexed connection to items of array"
                    )
                body_text = "".join(
                    [self._format_const_index(i) for i in assig.indexes])
                n = self.node.addNode(ITEM_SET,
                                      cls="Operator",
                                      bodyText=body_text)
                self.addInputPort(n, "", assig.src)
                oPort = self.addOutputPort(n,
                                           "",
                                           assig.dst if connectOut else None,
                                           origObj=assig.dst)
                return n, oPort

        elif connectOut:
            dst = assig.dst
            rootNetCtxs = self.rootNetCtxs
            if pctx is None:
                # connect to original dst signal directly
                ctx, _ = rootNetCtxs.getDefault(dst)
                ctx.addDriver(src)
                assert rootNetCtxs[dst] is rootNetCtxs[src]
                return None, dst
            else:
                # connect src to dst port on this wrap
                dstPort = pctx.getInside(dst, PortType.OUTPUT)
                raise NotImplementedError()
                # connect original signal from port on this wrap

                odstPort = pctx.getOutside(dst)
                ctx, _ = rootNetCtxs.getDefault(dst)
                ctx.addDriver(odstPort)
                return None, dstPort
        else:
            return None, assig.src