def HWProcess(cls, proc, ctx): """ Serialize HWProcess objects """ body = proc.statements extraVars = [] extraVarsSerialized = [] hasToBeVhdlProcess = extraVars or\ arr_any(body, lambda x: isinstance(x, (IfContainer, SwitchContainer, WhileContainer, WaitStm)) or (isinstance(x, Assignment) and x.indexes)) anyIsEventDependnt = arr_any( proc.sensitivityList, lambda s: isinstance(s, Operator)) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx, anyIsEventDependnt), proc.sensitivityList)) if hasToBeVhdlProcess: childCtx = ctx.withIndent() else: childCtx = ctx def createTmpVarFn(suggestedName, dtype): # [TODO] it is better to use RtlSignal s = SignalItem(None, dtype, virtualOnly=True) s.name = childCtx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] if hasToBeVhdlProcess: proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.defVal, s, virtualOnly=True) extraVarsInit.append(cls.Assignment(a, childCtx)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeVhdlProcess=hasToBeVhdlProcess, extraVars=extraVarsSerialized, sensitivityList=" or ".join(sensitivityList), statements=extraVarsInit + statemets )
def HWProcess(cls, proc: HWProcess, ctx): """ Serialize HWProcess objects """ body = proc.statements extraVars = [] extraVarsSerialized = [] anyIsEventDependnt = arr_any( proc.sensitivityList, lambda s: isinstance(s, Operator)) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx, anyIsEventDependnt), proc.sensitivityList)) hasToBeProcess = arr_any( proc.outputs, lambda x: verilogTypeOfSig(x) == SIGNAL_TYPE.REG ) if hasToBeProcess: childCtx = ctx.withIndent() else: childCtx = ctx def createTmpVarFn(suggestedName, dtype): s = RtlSignal(None, None, dtype, virtual_only=True) s.name = childCtx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] if hasToBeProcess: proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.def_val, s, virtual_only=True) extraVarsInit.append(cls.Assignment(a, childCtx)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeProcess=hasToBeProcess, extraVars=extraVarsSerialized, sensitivityList=" or ".join(sensitivityList), statements=extraVarsInit + statemets )
def systemCTypeOfSig(s): """ Check if is register or wire """ if isinstance(s, HdlIdDef): s = s.origin if isinstance(s, HdlPortItem): if s.direction == DIRECTION.IN or s.direction == DIRECTION.INOUT: return SIGNAL_TYPE.PORT_WIRE t = systemCTypeOfSig(s.getInternSig()) if t == SIGNAL_TYPE.WIRE: return SIGNAL_TYPE.PORT_WIRE elif t == SIGNAL_TYPE.REG: return SIGNAL_TYPE.PORT_REG else: raise ValueError(t) elif isinstance(s, Param): return SIGNAL_TYPE.PORT_REG elif s._const or\ arr_any(s.drivers, lambda d: isinstance(d, HdlStatement) and d._event_dependent_from_branch is not None): return SIGNAL_TYPE.REG else: return SIGNAL_TYPE.WIRE
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)
def systemCTypeOfSig(signalItem): """ Check if is register or wire """ if signalItem._const or\ arr_any(signalItem.drivers, lambda d: isinstance(d, HdlStatement) and d._now_is_event_dependent): return SIGNAL_TYPE.REG else: return SIGNAL_TYPE.WIRE
def _connectMyElems(self): if self._arrayElemCache: for indx, e in enumerate(self._arrayElemCache): elemHasConnections = arr_any( walkPhysInterfaces(e), lambda x: bool(x._sig.endpoints) or bool(x._sig.drivers)) if elemHasConnections: e._resolveDirections() if e._direction == INTF_DIRECTION.MASTER: e._connectTo(self, masterIndex=indx) else: self._connectTo(e, slaveIndex=indx)
def Elif(self, cond, *statements): cond = _intfToSig(cond) self.nowIsEventDependent = self.nowIsEventDependent or\ arr_any(discoverEventDependency(cond), lambda x: True) thisCond = AndReducedContainer() thisCond.add(cond) for c in reversed(self.elifConds): thisCond.add(~c) thisCond.add(~self.cond) self._appendStatements(thisCond, statements) self.elifConds.append(cond) return self
def verilogTypeOfSig(signalItem): """ Check if is register or wire """ driver_cnt = len(signalItem.drivers) if signalItem._const or driver_cnt > 1 or\ arr_any(signalItem.drivers, _isEventDependentDriver): return SIGNAL_TYPE.REG else: if driver_cnt == 1: d = signalItem.drivers[0] if not isinstance(d, (Assignment, PortItem)): return SIGNAL_TYPE.REG return SIGNAL_TYPE.WIRE
def HWProcess(cls, proc: HWProcess, ctx: SerializerCtx): body = proc.statements assert body proc.name = ctx.scope.checkedName(proc.name, proc) sensitivityList = sorted( map(cls.sensitivityListItem, proc.sensitivityList)) childCtx = ctx.withIndent(2) _body = "\n".join([cls.stmAsHdl(stm, childCtx) for stm in body]) return processTmpl.render(hasConditions=arr_any( body, lambda stm: not isinstance(stm, Assignment)), name=proc.name, sensitivityList=sensitivityList, stmLines=[_body])
def Elif(self, cond, *statements): assert self.parentStm is None self.rank += 1 cond_sig = _intfToSig(cond) self._now_is_event_dependent = arr_any( discoverEventDependency(cond_sig), lambda x: True) self._inputs.append(cond_sig) cond_sig.endpoints.append(self) case = [] self.elIfs.append((cond_sig, case)) self._register_stements(statements, case) return self
def as_hdl_HdlStatementBlock(self, proc: HdlStatementBlock) -> iHdlStatement: """ Serialize HdlStatementBlock objects as process if top statement """ if isinstance(proc, ALL_STATEMENT_CLASSES): return proc assert proc.parentStm is None, proc body = proc.statements hasToBeVhdlProcess = self.has_to_be_process(proc) with WithNameScope(self, self.name_scope.level_push(proc.name)): tmpVars = self.TMP_VAR_CONSTRUCTOR(self, self.name_scope) with TmpVarsSwap(self, tmpVars): statements = [self.as_hdl(s) for s in body] hasToBeVhdlProcess |= bool(tmpVars.extraVarsHdl) if hasToBeVhdlProcess: tmpVars.sort_hdl_declarations_first() statements = tmpVars.extraVarsHdl + statements if self.can_pop_process_wrap(statements, hasToBeVhdlProcess): return statements[0] else: p = HdlStmProcess() p.labels.append(proc.name) if not statements: pass # no body elif len(statements) == 1: # body made of just a singe statement p.body = statements[0] else: p.body = HdlStmBlock() assert isinstance(statements, list) p.body.body = statements anyIsEventDependnt = arr_any( proc._sensitivity, lambda s: isinstance(s, Operator)) p.sensitivity = sorted([ self.sensitivityListItem(s, anyIsEventDependnt) for s in proc._sensitivity ]) return p
def HWProcess(cls, proc, scope): """ Serialize HWProcess objects as VHDL :param scope: name scope to prevent name collisions """ body = proc.statements extraVars = [] extraVarsSerialized = [] def createTmpVarFn(suggestedName, dtype): # [TODO] it is better to use RtlSignal s = SignalItem(None, dtype, virtualOnly=True) s.name = scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, createTmpVarFn, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, None), proc.sensitivityList)) statemets = [cls.asHdl(s, createTmpVarFn) for s in body] hasToBeVhdlProcess = extraVars or arr_any( body, lambda x: isinstance(x, (IfContainer, SwitchContainer, WhileContainer, WaitStm))) if hasToBeVhdlProcess: proc.name = scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.defaultVal, s, virtualOnly=True) extraVarsInit.append(cls.Assignment(a, createTmpVarFn)) return processTmpl.render({ "name": proc.name, "hasToBeVhdlProcess": hasToBeVhdlProcess, "extraVars": extraVarsSerialized, "sensitivityList": ", ".join(sensitivityList), "statements": extraVarsInit + statemets })
def renderContent(self): """ Walk from outputs to inputs for each public signal register port of wrap node if required lazy load all operator and statement nodes for signals """ stm = self.stm portCtx = self.portCtx # for each inputs and outputs render expression trees # walk statements and render muxs and memories for o in stm._outputs: if not self.isVirtual: portCtx.register(o, PortType.OUTPUT) canHaveRamPorts = isinstance(stm, IfContainer) and arr_any( chain(stm._inputs, stm._outputs), lambda s: isinstance(s._dtype, HArray)) # render RAM ports consumedOutputs = set() if canHaveRamPorts: for pType, memSig, addrSig, enSig, io in detectRamPorts( stm, stm.cond): if pType == RAM_READ: self.createRamReadNode(memSig, enSig, addrSig, io, True) consumedOutputs.add(io) elif pType == RAM_WRITE: self.createRamWriteNode(memSig, enSig, addrSig, io, None, True) consumedOutputs.add(memSig) else: raise TypeError() for o in stm._outputs: if o not in consumedOutputs: self.renderForSignal(stm, o, True) if not self.isVirtual: self.netCtxs.applyConnections(self.node)
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 IntfLvlConfErr("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)
def walkFieldsAndIntf(self, transTmpl, structIntf): intfIt = ObjIteratorCtx(structIntf) fieldTrans = transTmpl.walkFlatten( shouldEnterFn=self._shouldEnterForTransTmpl, otherObjItCtx=intfIt) hasAnyInterface = False for ((base, end), transTmpl) in fieldTrans: intf = intfIt.actual isPartOfSomeArray = arr_any(intfIt.onParentNames, lambda x: isinstance(x, int)) if isPartOfSomeArray: _tTmpl = copy(transTmpl) _tTmpl.bitAddr = base _tTmpl.bitAddrEnd = end _tTmpl.origin = PartialField(transTmpl.origin) transTmpl = _tTmpl self.decoded._fieldsToInterfaces[transTmpl.origin] = intf yield transTmpl, intf hasAnyInterface = True assert hasAnyInterface
def walkFieldsAndIntf(self, transTmpl, structIntf): intfIt = ObjIteratorCtx(structIntf) fieldTrans = transTmpl.walkFlatten( shouldEnterFn=self._shouldEnterForTransTmpl, otherObjItCtx=intfIt) hasAnyInterface = False for ((base, end), transTmpl) in fieldTrans: intf = intfIt.actual isPartOfSomeArray = arr_any(intfIt.onParentNames, lambda x: isinstance(x, int)) if isPartOfSomeArray: _tTmpl = copy(transTmpl) _tTmpl.bitAddr = base _tTmpl.bitAddrEnd = end _tTmpl.origin = PartialField(transTmpl.origin) transTmpl = _tTmpl self.decoded._fieldsToInterfaces[transTmpl.origin] = intf yield transTmpl, intf hasAnyInterface = True assert hasAnyInterface
def xml(self): # Vivado 2015.2 bug - order of all elements is NOT optional for prefix, uri in ns.items(): etree.register_namespace(prefix, uri) c = mkSpiElm("component") appendStrElements(c, self, self._strValues[:-1]) if arr_any(self.busInterfaces, lambda intf: hasattr(intf, "_bi")): bi = appendSpiElem(c, "busInterfaces") for intf in self.busInterfaces: # for all interfaces which have bus interface class if hasattr(intf, "_bi"): bi.append(intf._bi.asElem()) c.append(self.model.asElem()) self._xmlFileSets(c) appendStrElements(c, self, [self._strValues[-1]]) self._xmlParameters(c) c.append( self.vendorExtensions.asElem(self.name + "_v" + self.version, revision=str(int(time())))) return c
def as_hdl_HdlStatementBlock(self, proc: HdlStatementBlock) -> iHdlStatement: """ Serialize HdlStatementBlock objects as process if top statement """ if isinstance(proc, HdlStmProcess): return proc assert proc.parentStm is None, proc body = proc.statements extraVars = [] extraVarsHdl = [] hasToBeVhdlProcess = self.has_to_be_process(proc) def createTmpVarInCurrentBlock(suggestedName, dtype, const=False, def_val=None): # create a new tmp variable in current process s = RtlSignal(None, None, dtype, virtual_only=True) s.name = self.name_scope.checked_name(suggestedName, s) s.hidden = False s._const = const if def_val is not None: s.def_val = def_val s._set_def_val() as_hdl = self.as_hdl_SignalItem(s, declaration=True) extraVars.append(s) extraVarsHdl.append(as_hdl) return s with WithNameScope(self, self.name_scope.level_push(proc.name)): with CreateTmpVarFnSwap(self, createTmpVarInCurrentBlock): statements = [self.as_hdl(s) for s in body] # create a initializer for tmp variables # :note: we need to do this here because now it is sure that # the drivers of tmp variable will not be modified extraVarsInit = self.as_hdl_extraVarsInit(extraVars) hasToBeVhdlProcess |= bool(extraVars) if hasToBeVhdlProcess: statements = extraVarsHdl + extraVarsInit + statements if self.can_pop_process_wrap(statements, hasToBeVhdlProcess): return statements[0] else: p = HdlStmProcess() p.labels.append(proc.name) if not statements: pass # no body elif len(statements) == 1: # body made of just a singe statement p.body = statements[0] else: p.body = HdlStmBlock() assert isinstance(statements, list) p.body.body = statements anyIsEventDependnt = arr_any( proc._sensitivity, lambda s: isinstance(s, Operator)) p.sensitivity = sorted([ self.sensitivityListItem(s, anyIsEventDependnt) for s in proc._sensitivity ]) return p
def typeIsParametrized(dtype): c = dtype.constrain if c is None: return False else: return arr_any(list(walkSignalsInExpr(c)), lambda x: True)
def HWProcess(cls, proc, ctx): """ Serialize HWProcess objects as VHDL :param scope: name scope to prevent name collisions """ body = proc.statements extraVars = [] extraVarsSerialized = [] hasToBeVhdlProcess = arr_any(body, lambda x: isinstance(x, (IfContainer, SwitchContainer, WhileContainer, WaitStm))) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx), proc.sensitivityList)) if hasToBeVhdlProcess: childCtx = ctx.withIndent() else: childCtx = copy(ctx) def createTmpVarFn(suggestedName, dtype): s = RtlSignal(None, None, dtype, virtualOnly=True) s.name = ctx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: if isinstance(s.defVal, RtlSignalBase) or s.defVal.vldMask: a = Assignment(s.defVal, s, virtualOnly=True) extraVarsInit.append(cls.Assignment(a, childCtx)) else: assert s.drivers, s for d in s.drivers: extraVarsInit.append(cls.asHdl(d, childCtx)) _hasToBeVhdlProcess = hasToBeVhdlProcess hasToBeVhdlProcess = extraVars or hasToBeVhdlProcess if hasToBeVhdlProcess and not _hasToBeVhdlProcess: # add indent because we did not added it before because we did not # know t oneIndent = getIndent(1) statemets = list(map(lambda x: oneIndent + x, statemets)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeVhdlProcess=hasToBeVhdlProcess, extraVars=extraVarsSerialized, sensitivityList=", ".join(sensitivityList), statements=extraVarsInit + statemets )