def __repr__(self, indent=0, withAddr=None, expandStructs=False): """ :param indent: number of indentation :param withAddr: if is not None is used as a additional information about on which address this type is stored (used only by HStruct) :param expandStructs: expand HStructTypes (used by HStruct and HArray) """ if self.name: name = self.name + " " else: name = "" myIndent = getIndent(indent) childIndent = getIndent(indent + 1) header = "%sunion %s{" % (myIndent, name) buff = [ header, ] for f in self.fields.values(): if f.name is None: buff.append("%s//%r empty space" % (childIndent, f.dtype)) else: buff.append( "%s %s" % (f.dtype.__repr__(indent=indent + 1, withAddr=withAddr, expandStructs=expandStructs), f.name)) buff.append("%s}" % (myIndent)) return "\n".join(buff)
def __repr__(self, indent=0): buff = ["{"] indentOfFields = getIndent(indent + 1) for f in self._dtype.fields: if f.name is not None: val = getattr(self, f.name) try: v = val.__repr__(indent=indent + 1) except TypeError: v = repr(val) buff.append(f"{indentOfFields:s}{f.name:s}: {v:s}") buff.append(getIndent(indent) + "}") return ("\n").join(buff)
def __repr__(self, indent=0): buff = ["{"] indentOfFields = getIndent(indent + 1) for f in self._dtype.fields.values(): if f.name is not None: val = getattr(self, f.name) try: v = val.__repr__(indent=indent + 1) except TypeError: v = repr(val) buff.append("%s%s: %s" % (indentOfFields, f.name, v)) buff.append(getIndent(indent) + "}") return ("\n").join(buff)
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 IfContainer(cls, ifc: IfContainer, ctx: HwtSerializerCtx): cond = cls.condAsHdl(ifc.cond, ctx) ifTrue = ifc.ifTrue ifFalse = ifc.ifFalse if ifFalse is None: ifFalse = [] childCtx = ctx.withIndent() def serialize_statements(statements): return [cls.stmAsHdl(obj, childCtx) for obj in statements] def serialize_elif(elifCase): cond, statements = elifCase return (cls.condAsHdl(cond, ctx), serialize_statements(statements)) return ifTmpl.render( indent=getIndent(ctx.indent), indentNum=ctx.indent, cond=cond, ifTrue=serialize_statements(ifTrue), elIfs=[serialize_elif(elIf) for elIf in ifc.elIfs], ifFalse=serialize_statements(ifFalse) )
def __repr__(self, indent=0, withAddr=None, expandStructs=False): """ :param indent: number of indentation :param withAddr: if is not None is used as a additional information about on which address this type is stored (used only by HStruct) :param expandStructs: expand HStructTypes (used by HStruct and HArray) """ constr = [] if self.name is not None: constr.append('"%s"' % self.name) c = self.bit_length() constr.append("%dbits" % c) if self.force_vector: constr.append("force_vector") if self.signed: constr.append("signed") elif self.signed is False: constr.append("unsigned") if not self.strict_sign: constr.append("strict_sign=False") if not self.strict_width: constr.append("strict_width=False") return "%s<%s, %s>" % (getIndent(indent), self.__class__.__name__, ", ".join(constr))
def __repr__(self, indent=0): # [TODO] refactor too similar to StructValBase.__repr__ buff = ["{"] indentOfFields = getIndent(indent + 1) for f in self._dtype.fields.values(): if f.name is not None: val = getattr(self, f.name) try: v = val.__repr__(indent=indent + 1) except TypeError: v = repr(val) buff.append(f"{indentOfFields:s}{f.name:s}: {v:s}") buff.append(getIndent(indent) + "}") return ("\n").join(buff)
def Architecture(cls, arch, ctx): serializerVars = [] procs = [] extraTypes = set() extraTypes_serialized = [] arch.variables.sort(key=lambda x: (x.name, x._instId)) arch.componentInstances.sort(key=lambda x: x._name) childCtx = ctx.withIndent() extraProcesses = [] for v in arch.variables: _eProc = cls.Architecture_var(v, serializerVars, extraTypes, extraTypes_serialized, ctx, childCtx) extraProcesses.extend(_eProc) arch.processes.extend(extraProcesses) arch.processes.sort(key=lambda x: (x.name, maxStmId(x))) 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) componentInstances = list( map(lambda c: cls.ComponentInstance(c, childCtx), arch.componentInstances)) return cls.moduleBodyTmpl.render(indent=getIndent(ctx.indent), entityName=arch.getEntityName(), name=arch.name, variables=serializerVars, extraTypes=extraTypes_serialized, processes=procs, componentInstances=componentInstances)
def IfContainer(cls, ifc, ctx): childCtx = ctx.withIndent() def asHdl(statements): return [cls.asHdl(s, childCtx) for s in statements] cond = cls.condAsHdl(ifc.cond, True, childCtx) elIfs = [] if ifc.ifFalse is not None: ifFalse = ifc.ifFalse else: ifFalse = [] ifTrue = ifc.ifTrue if cls.VHDL_VER < VhdlVersion.v2008: ifTrue = ternaryOpsToIf(ifTrue) ifFalse = ternaryOpsToIf(ifFalse) for c, statements in ifc.elIfs: if cls.VHDL_VER < VhdlVersion.v2008: statements = ternaryOpsToIf(statements) elIfs.append((cls.condAsHdl(c, True, childCtx), asHdl(statements))) return cls.ifTmpl.render( indent=getIndent(ctx.indent), cond=cond, ifTrue=asHdl(ifTrue), elIfs=elIfs, ifFalse=asHdl(ifFalse))
def Component(cls, entity, ctx): with CurrentUnitSwap(ctx, entity.origin): return cls.componentTmpl.render( indent=getIndent(ctx.indent), ports=[cls.PortItem(pi, ctx) for pi in entity.ports], generics=[cls.GenericItem(g, ctx) for g in entity.generics], entity=entity)
def pprintInterface(intf: Union[Unit, InterfaceBase], indent: int = 0, prefix: str = "", file=sys.stdout): """ Pretty print interface """ try: s = intf._sig except AttributeError: s = None if s is None: s = "" else: s = " " + repr(s) file.write("".join( [getIndent(indent), prefix, repr(intf._getFullName()), s])) file.write("\n") if isinstance(intf, HObjList): for i, p in enumerate(intf): # interfaces have already name of this array and index in it's name pprintInterface(p, indent=indent + 1, prefix=prefix, file=file) else: for i in intf._interfaces: pprintInterface(i, indent=indent + 1, file=file)
def Dict_valAsHdl(cls, val, ctx): sep = (",\n" + getIndent(ctx.indent + 1)) def sItem(i): k, v = i return "%d: %s" % (k, cls.Value(v, ctx)) return "{%s}" % sep.join(map(sItem, val.items()))
def IfContainer(cls, ifc: IfContainer, ctx: SerializerCtx): cond = cls.condAsHdl(ifc.cond, ctx) ifTrue = ifc.ifTrue if ifc.elIfs: # replace elifs with nested if statements ifFalse = [] topIf = IfContainer(ifc.cond, ifc.ifTrue, ifFalse) topIf._inputs = ifc._inputs topIf._outputs = ifc._outputs topIf._sensitivity = ifc._sensitivity for c, stms in ifc.elIfs: _ifFalse = [] lastIf = IfContainer(c, stms, _ifFalse) lastIf._inputs = ifc._inputs lastIf._outputs = ifc._outputs lastIf._sensitivity = ifc._sensitivity ifFalse.append(lastIf) ifFalse = _ifFalse if ifc.ifFalse is None: lastIf.ifFalse = [] else: lastIf.ifFalse = ifc.ifFalse return cls.IfContainer(topIf, ctx) else: ifFalse = ifc.ifFalse if ifFalse is None: ifFalse = [] childCtx = ctx.withIndent() outputInvalidateStms = [] for o in ifc._outputs: # [TODO] look up indexes indexes = None oa = Assignment(o._dtype.from_py(None), o, indexes, virtual_only=True, parentStm=ifc, is_completly_event_dependent=ifc. _is_completly_event_dependent) outputInvalidateStms.append(cls.stmAsHdl(oa, childCtx)) return ifTmpl.render( indent=getIndent(ctx.indent), indentNum=ctx.indent, cond=cond, outputInvalidateStms=outputInvalidateStms, ifTrue=tuple( map(lambda obj: cls.stmAsHdl(obj, childCtx), ifTrue)), ifFalse=tuple( map(lambda obj: cls.stmAsHdl(obj, childCtx), ifFalse)))
def WaitStm(cls, w, ctx): indent_str = getIndent(ctx.indent) if w.isTimeWait: return "%swait for %d ns" % (indent_str, w.waitForWhat) elif w.waitForWhat is None: return "%swait" % indent_str else: raise NotImplementedError()
def _Assignment(cls, dst, typeOfDst, src, ctx): indent_str = getIndent(ctx.indent) dstStr = cls.asHdl(dst, ctx.forTarget()) if typeOfDst == SIGNAL_TYPE.REG: fmt = "%s%s = %s;" else: fmt = "%s%s.write(%s);" return fmt % (indent_str, dstStr, cls.Value(src, ctx))
def __repr__(self, indent=0, withAddr=None, expandStructs=False): return "%s<%s len:%s, align:%r\n%s>" % ( getIndent(indent), self.__class__.__name__, (self.len_min, self.len_max), self.start_offsets, self.element_t.__repr__(indent=indent+1, withAddr=withAddr, expandStructs=expandStructs), )
def Assignment(cls, a: Assignment, ctx: HwtSerializerCtx): dst = a.dst indentStr = getIndent(ctx.indent) srcStr = "%s" % cls.Value(a.src, ctx) indexes = a.indexes if indexes is None: indexes = [] return "%s%s%s(%s)" % (indentStr, dst.name, "".join( map(lambda x: "[%s]" % cls.asHdl(x, ctx), indexes)), srcStr)
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 __repr__(self, indent=0, withAddr=None, expandStructs=False): """ :param indent: number of indentation :param withAddr: if is not None is used as a additional information about on which address this type is stored (used only by HStruct) :param expandStructs: expand HStructTypes (used by HStruct and HArray) """ if self.name: name = self.name + " " else: name = "" myIndent = getIndent(indent) childIndent = getIndent(indent + 1) header = f"{myIndent:s}struct {name:s}{{" buff = [ header, ] for f in self.fields: if withAddr is not None: withAddr_B = withAddr // 8 addrTag = f" // start:0x{withAddr:x}(bit) 0x{withAddr_B:x}(byte)" else: addrTag = "" if f.name is None: buff.append( f"{childIndent:s}//{f.dtype} empty space{addrTag:s}") else: buff.append("%s %s%s" % (f.dtype.__repr__( indent=indent + 1, withAddr=withAddr, expandStructs=expandStructs), f.name, addrTag)) if withAddr is not None: withAddr += f.dtype.bit_length() buff.append(f"{myIndent:s}}}") return "\n".join(buff)
def __repr__(self, indent=0, withAddr=None, expandStructs=False): """ :param indent: number of indentation :param withAddr: if is not None is used as a additional information about on which address this type is stored (used only by HStruct) :param expandStructs: expand HStructTypes (used by HStruct and HArray) """ if self.name: name = self.name + " " else: name = "" myIndent = getIndent(indent) childIndent = getIndent(indent + 1) header = "%sstruct %s{" % (myIndent, name) buff = [ header, ] for f in self.fields: if withAddr is not None: addrTag = " // start:0x%x(bit) 0x%x(byte)" % (withAddr, withAddr // 8) else: addrTag = "" if f.name is None: buff.append("%s//%r empty space%s" % (childIndent, f.dtype, addrTag)) else: buff.append("%s %s%s" % (f.dtype.__repr__( indent=indent + 1, withAddr=withAddr, expandStructs=expandStructs), f.name, addrTag)) if withAddr is not None: withAddr += f.dtype.bit_length() buff.append("%s}" % (myIndent)) return "\n".join(buff)
def Assignment(cls, a: Assignment, ctx): dst = a.dst assert isinstance(dst, SignalItem) # dstSignalType = verilogTypeOfSig(dst) indent_str = getIndent(ctx.indent) _dst = dst if a.indexes is not None: for i in a.indexes: if isinstance(i, SliceVal): i = i.__copy__() dst = dst[i] dstStr = cls.asHdl(dst, ctx) ver_sig_t = verilogTypeOfSig(_dst) if ver_sig_t == SIGNAL_TYPE.REG: evDep = False for driver in _dst.drivers: if driver._now_is_event_dependent: evDep = True break if not evDep or _dst.virtual_only: prefix = "" symbol = "=" else: prefix = "" symbol = "<=" elif ver_sig_t == SIGNAL_TYPE.WIRE: if a.parentStm is None: prefix = "assign " else: prefix = "" symbol = "=" else: ValueError(ver_sig_t) firstPartOfStr = "%s%s%s" % (indent_str, prefix, dstStr) src_t = a.src._dtype dst_t = dst._dtype srcStr = cls.Value(a.src, ctx) if dst_t == src_t \ or (isinstance(src_t, Bits) and isinstance(dst_t, Bits) and src_t.bit_length() == dst_t.bit_length() == 1): return "%s %s %s;" % (firstPartOfStr, symbol, srcStr) else: raise SerializerException("%s %s %s is not valid assignment\n" " because types are different (%r; %r) " % (dstStr, symbol, srcStr, dst._dtype, a.src._dtype))
def SignalItem(cls, si, ctx, declaration=False): if declaration: ctx = ctx.forSignal(si) v = si.defVal if si.virtualOnly: pass elif si.drivers: pass elif si.endpoints or si.simSensProcs: if not v.vldMask: raise SerializerException( "Signal %s is constant and has undefined value" % si.name) else: raise SerializerException( "Signal %s should be declared but it is not used" % si.name) t = si._dtype dimensions = [] while isinstance(t, HArray): # collect array dimensions dimensions.append(t.size) t = t.elmType s = "%s%s %s" % (getIndent(ctx.indent), cls.HdlType(t, ctx), si.name) if dimensions: # to make a space between name and dimensoins dimensions = list( map(lambda x: "[%s-1:0]" % cls.asHdl(toHVal(x), ctx), dimensions)) dimensions.append("") s += " ".join(reversed(dimensions)) if isinstance(v, RtlSignalBase): if v._const: return s + " = %s" % cls.asHdl(v, ctx) else: # default value has to be set by reset because it is only signal return s elif isinstance(v, Value): if v.vldMask: return s + " = %s" % cls.Value(v, ctx) else: return s else: raise NotImplementedError(v) else: return cls.get_signal_name(si, ctx)
def HWProcess(cls, proc: HWProcess, ctx: HwtSerializerCtx): body = proc.statements assert body proc.name = ctx.scope.checkedName(proc.name, proc) sensitivityList = sorted( map(cls.sensitivityListItem, proc.sensitivityList)) _body = "\n".join([cls.stmAsHdl(stm, ctx) for stm in body]) return processTmpl.render(indent=getIndent(ctx.indent), name=proc.name, sensitivityList=sensitivityList, stmLines=[_body])
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)
def Entity(cls, ent, ctx): generics, ports = cls.Entity_prepare(ent, ctx) entVerilog = cls.moduleHeadTmpl.render(indent=getIndent(ctx.indent), name=ent.name, ports=ports, generics=generics) doc = ent.__doc__ if doc and id(doc) != id(Entity.__doc__): doc = cls.comment(doc) + "\n" return doc + entVerilog else: return entVerilog
def HWProcess(cls, proc, ctx): """ Serialize HWProcess instance :param scope: name scope to prevent name collisions """ body = proc.statements childCtx = ctx.withIndent() statemets = [cls.asHdl(s, childCtx) for s in body] proc.name = ctx.scope.checkedName(proc.name, proc) return cls.methodTmpl.render(indent=getIndent(ctx.indent), name=proc.name, statements=statemets)
def Entity(cls, entity: Entity, ctx): with CurrentUnitSwap(ctx, entity.origin): generics, ports = cls.Entity_prepare(entity, ctx) entVhdl = cls.entityTmpl.render(indent=getIndent(ctx.indent), name=entity.name, ports=ports, generics=generics) doc = entity.__doc__ if doc and id(doc) != id(Entity.__doc__): doc = cls.comment(doc) + "\n" return doc + entVhdl else: return entVhdl
def pprintAgents(unitOrIntf, indent=0, prefix="", file=sys.stdout): if isinstance(unitOrIntf, InterfaceBase): ag = unitOrIntf._ag elif isinstance(unitOrIntf, HObjList): for i, item in enumerate(unitOrIntf): item_prefix = "%s_%d" % (prefix, i) pprintAgents(item, indent=indent+1, prefix=item_prefix, file=file) return else: ag = None if ag is not None: file.write("%s%s%r\n" % (getIndent(indent), prefix, ag)) for i in unitOrIntf._interfaces: pprintAgents(i, indent + 1, file=file)
def Assignment(cls, a: Assignment, ctx): dst = a.dst assert isinstance(dst, SignalItem) def valAsHdl(v): return cls.Value(v, ctx) # dstSignalType = verilogTypeOfSig(dst) assert not dst.virtualOnly if a._is_completly_event_dependent: prefix = "" symbol = "<=" else: if a.parentStm is None: prefix = "assign " else: prefix = "" symbol = "=" if a.indexes is not None: for i in a.indexes: if isinstance(i, SliceVal): i = i.clone() i.val = (i.val[0], i.val[1]) dst = dst[i] indent_str = getIndent(ctx.indent) dstStr = cls.asHdl(dst, ctx) firstPartOfStr = "%s%s%s" % (indent_str, prefix, dstStr) src_t = a.src._dtype dst_t = dst._dtype if dst_t == src_t \ or (isinstance(src_t, Bits) and isinstance(dst_t, Bits) and src_t.bit_length() == dst_t.bit_length() == 1): return "%s %s %s;" % (firstPartOfStr, symbol, valAsHdl(a.src)) else: raise SerializerException("%s %s %s is not valid assignment\n" " because types are different (%r; %r) " % (dstStr, symbol, valAsHdl(a.src), dst._dtype, a.src._dtype))
def IfContainer(cls, ifc: IfContainer, ctx: SerializerCtx): """ Srialize IfContainer instance """ childCtx = ctx.withIndent() def asHdl(statements): return [cls.asHdl(s, childCtx) for s in statements] try: cond = cls.condAsHdl(ifc.cond, True, ctx) except UnsupportedEventOpErr as e: cond = None if cond is None: assert not ifc.elIfs assert not ifc.ifFalse stmBuff = [cls.asHdl(s, ctx) for s in ifc.ifTrue] return "\n".join(stmBuff) elIfs = [] ifTrue = ifc.ifTrue ifFalse = ifc.ifFalse if ifFalse is None: ifFalse = [] for c, statements in ifc.elIfs: try: elIfs.append((cls.condAsHdl(c, True, ctx), asHdl(statements))) except UnsupportedEventOpErr as e: if len(ifc.elIfs) == 1 and not ifFalse: # register expression is in valid format and this # is just register with asynchronous reset or etc... ifFalse = statements else: raise e return cls.ifTmpl.render(indent=getIndent(ctx.indent), cond=cond, ifTrue=asHdl(ifTrue), elIfs=elIfs, ifFalse=asHdl(ifFalse))