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)
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
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)
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)
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)
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