def asQuartusTcl(self, buff, version, component, entity, allInterfaces, thisIf): self.quartus_tcl_add_interface(buff, thisIf) name = getSignalName(thisIf) #self.quartus_prop("associatedClock", clock) self.quartus_prop(buff, name, "synchronousEdges", "DEASSERT") self.quartus_add_interface_port(buff, getSignalName(thisIf), thisIf, "reset") clk = thisIf._getAssociatedClk() if clk is not None: self.quartus_prop(buff, name, "associatedClock", clk._sigInside.name, escapeStr=False)
def _implReadyChainBreak(self, in_vld: RtlSignal, in_rd: RtlSignal, in_data: List[RtlSignal], out_vld: RtlSignal, out_rd: RtlSignal, prefix: str): """ Two sets of registers 0. is prioritized 1. is used as a backup The in_rd is not combinationally connected to out_rd The out_vld is not combinationally connected to in_vld """ occupied = [ self._reg(f"{prefix}occupied_{i:d}", def_val=0) for i in range(2) ] reader_prio = self._reg(f"{prefix}reader_prio", def_val=0) consume_0 = (reader_prio._eq(0) & occupied[0]) | ~occupied[1] consume_1 = (reader_prio._eq(1) & occupied[1]) | ~occupied[0] outData = [] for iin in in_data: r0 = self._reg(prefix + 'reg0_' + getSignalName(iin), iin._dtype) If(in_vld & ~occupied[0], r0(iin)) r1 = self._reg(prefix + 'reg1_' + getSignalName(iin), iin._dtype) If(in_vld & ~occupied[1], r1(iin)) o = self._sig(prefix + 'out_tmp_' + getSignalName(iin), iin._dtype) If(consume_0 & occupied[0], o(r0)).Elif(consume_1 & occupied[1], o(r1)).Else(o(None)) outData.append(o) If( in_vld & (~occupied[0] | ~occupied[1]), If( occupied[0], reader_prio(0), ).Elif( occupied[1], reader_prio(1), )) oc0_set = in_vld & ~occupied[0] oc0_clr = out_rd & occupied[0] & consume_0 oc1_set = in_vld & occupied[0] & ~occupied[1] oc1_clr = out_rd & occupied[1] & consume_1 occupied[0]((occupied[0] | oc0_set) & ~oc0_clr) occupied[1]((occupied[1] | oc1_set) & ~oc1_clr) in_rd(~occupied[0] | ~occupied[1]) out_vld(occupied[0] | occupied[1]) return outData
def vcdRegisterInterfaces(self, obj: Union[Interface, Unit], parent: Optional[VcdVarWritingScope]): """ Register signals from interfaces for Interface or Unit instances """ if hasattr(obj, "_interfaces") and obj._interfaces: name = obj._name parent_ = self.vcdWriter if parent is None else parent subScope = parent_.varScope(name) self._obj2scope[obj] = subScope with subScope: # register all subinterfaces for chIntf in obj._interfaces: self.vcdRegisterInterfaces(chIntf, subScope) if isinstance(obj, (Unit, SimModel)): # register interfaces from all subunits for u in obj._units: self.vcdRegisterInterfaces(u, subScope) return subScope else: t = obj._dtype if isinstance(t, self.supported_type_classes): tName, width, formatter = vcdTypeInfoForHType(t) try: parent.addVar(obj, getSignalName(obj), tName, width, formatter) except VarAlreadyRegistered: pass
def edgeDetector(self, sig, rise=False, fall=False, last=None, initVal=0): """ :param sig: signal to detect edges on :param rise: if True signal for rise detecting will be returned :param fall: if True signal for fall detecting will be returned :param last: last value for sig (use e.g. when you have register and it's next signal (sig=reg.next, last=reg)) if last is None last register will be automatically generated :param initVal: if last is None initVal will be used as its initialization value :return: signals which is high on on rising/falling edge or both (specified by rise, fall parameter) """ namePrefix = getSignalName(sig) assert rise or fall if last is None: last = self.parent._reg(namePrefix + "_edgeDetect_last", def_val=initVal) last(sig) if rise: riseSig = self.parent._sig(namePrefix + "_rising") riseSig(sig & ~last) if fall: fallSig = self.parent._sig(namePrefix + "_falling") fallSig(~sig & last) if rise and not fall: return riseSig elif not rise and fall: return fallSig else: return (riseSig, fallSig)
def _walkStructIntfAndIntfMap_unpack(structIntf: Union[HObjList, StructIntf, UnionSink, UnionSource], intfMap): """ Try to unpack intfMap and apply the selection on structIntf :return: Optional tuple Interface, intfMap """ # items are Interface/RtlSignal or (type/interface/None or list of items, name) if isPaddingInIntfMap(intfMap): return elif isinstance(intfMap, tuple): item, name = intfMap else: item = intfMap assert isinstance(item, (InterfaceBase, RtlSignalBase)), item name = getSignalName(item) if isinstance(item, HdlType): # this part of structIntf was generated from type descriptin # and we are re searching only for those parts which were generated # from Interface/RtlSignal return return getattr(structIntf, name), item
def timerDynamic(self, periodSig, enableSig=None, rstSig=None) -> RtlSignal: """ Same as timer, just period is signal which can be configured dynamically """ if isinstance(periodSig, (tuple, list)): periodSig, name = periodSig else: periodSig, name = periodSig, getSignalName(periodSig) parentUnit = self.parent timer = DynamicTimerInfo(periodSig, name) maxVal = timer.maxVal - 1 assert maxVal._dtype.bit_length() > 0 r = parentUnit._reg(timer.name + "_delayCntr", periodSig._dtype, def_val=0) timer.cntrRegister = r tick = DynamicTimerInfo._instantiateTimerTickLogic( timer, periodSig, enableSig, rstSig) timer.tick = parentUnit._sig(timer.name + "_delayTick") timer.tick(tick) return timer.tick
def timerDynamic(self, periodSig, enableSig=None, rstSig=None) -> RtlSignal: """ Same as timer, just period is signal which can be configured dynamically """ if isinstance(periodSig, (tuple, list)): periodSig, name = periodSig else: periodSig, name = periodSig, getSignalName(periodSig) parentUnit = self.parent timer = DynamicTimerInfo(periodSig, name) maxVal = timer.maxVal - 1 assert maxVal._dtype.bit_length() > 0 r = parentUnit._reg(timer.name + "_delayCntr", periodSig._dtype, defVal=0 ) timer.cntrRegister = r tick = DynamicTimerInfo._instantiateTimerTickLogic(timer, periodSig, enableSig, rstSig) timer.tick = parentUnit._sig(timer.name + "_delayTick") timer.tick(tick) return timer.tick
def edgeDetector(self, sig, rise=False, fall=False, last=None, initVal=0): """ :param sig: signal to detect edges on :param rise: if True signal for rise detecting will be returned :param fall: if True signal for fall detecting will be returned :param last: last value for sig (use f.e. when you have register and it's next signal (sig=reg.next, last=reg)) if last is None last register will be automatically generated :param initVal: if last is None initVal will be used as its initialization value :return: signals which is high on on rising/falling edge or both (specified by rise, fall parameter) """ namePrefix = getSignalName(sig) assert rise or fall if last is None: last = self.parent._reg(namePrefix + "_edgeDetect_last", defVal=initVal) last(sig) if rise: riseSig = self.parent._sig(namePrefix + "_rising") riseSig(sig & ~last) if fall: fallSig = self.parent._sig(namePrefix + "_falling") fallSig(~sig & last) if rise and not fall: return riseSig elif not rise and fall: return fallSig else: return (riseSig, fallSig)
def __init__(self, sig, in_clk_rst: Tuple[RtlSignal, RtlSignal], out_clk_rst: Tuple[RtlSignal, RtlSignal], reg_init_val, name_prefix: Optional[str] = None): """ :param sig: data in signal :param in_clk_rst: tuple source clk signal, rst signal :param out_clk_rst: tuple destination clk signal, rst signal :note: rst/rst_n is automatically resolved from reset type :param reg_init_val: register reset value """ self.path = [ sig, ] if name_prefix is None: name_prefix = getSignalName(sig) + "_" self.name_prefix = name_prefix self.IN_CLK_RST = in_clk_rst self.OUT_CLK_RST = out_clk_rst self.REG_INIT_VAL = reg_init_val self.META_PERIOD_NS =\ 1e9 / max(in_clk_rst[0].FREQ, in_clk_rst[0].FREQ) * 0.5 self.in_reg_cnt = 0 self.out_reg_cnt = 0
def vcdRegisterRemainingSignals(self, unit: Union[Interface, Unit]): unitScope = self._obj2scope[unit] for s in unit._ctx.signals: if s not in self.vcdWriter._idScope: t = s._dtype if isinstance(t, self.supported_type_classes): tName, width, formatter = vcdTypeInfoForHType(t) unitScope.addVar(s, getSignalName(s), tName, width, formatter) for u in unit._units: self.vcdRegisterRemainingSignals(u)
def __init__(self, parent, srcInterface, name=None): """ :param parent: unit in which will be all units created by this builder instantiated :param name: prefix for all instantiated units :param srcInterface: input clock """ self.parent = parent self.end = srcInterface if name is None: name = "gen_" + getSignalName(srcInterface) self.name = name self.compId = 0
def asQuartusTcl(self, buff: List[str], version: str, component: Component, packager: IpPackager, thisIf: Interface): IntfIpMeta.asQuartusTcl(self, buff, version, component, packager, thisIf) name = getSignalName(thisIf) if thisIf._direction == INTF_DIRECTION.MASTER: self.quartus_prop(buff, name, "readIssuingCapability", 1) self.quartus_prop(buff, name, "writeIssuingCapability", 1) self.quartus_prop(buff, name, "combinedIssuingCapability", 1) else: self.quartus_prop(buff, name, "readAcceptanceCapability", 1) self.quartus_prop(buff, name, "writeAcceptanceCapability", 1) self.quartus_prop(buff, name, "combinedAcceptanceCapability", 1) self.quartus_prop(buff, name, "readDataReorderingDepth", 1) self.quartus_prop(buff, name, "bridgesToMaster", "")
def _HTypeFromIntfMap(intf): name = getSignalName(intf) if isinstance(intf, (RtlSignalBase, Signal)): dtype = intf._dtype elif isinstance(intf, VldSynced): dtype = intf.data._dtype elif isinstance(intf, RegCntrl): dtype = intf.din._dtype elif isinstance(intf, BramPort_withoutClk): dtype = Bits(int(intf.DATA_WIDTH))[2**int(intf.ADDR_WIDTH)] else: dtype, name = intf assert isinstance(dtype, HdlType) assert isinstance(name, str) return (dtype, name)
def __init__(self, parent, srcInterface, name=None, master_to_slave=True): """ :param parent: unit in which will be all units created by this builder instantiated :param name: prefix for all instantiated units :param srcInterface: start of data-path :param master_to_slave: if True the circuit is build in natural direction (master to slave, input to output) othervise it is build in reverse direction """ self.parent = parent self.lastComp = None self.end = srcInterface if name is None: name = "gen_" + getSignalName(srcInterface) self.name = name self.master_to_slave = master_to_slave self.compId = 0
def postpone_val(self, sig_in, clock_enables: List[RtlSignal], name_prefix=None): """ Generate a register pipeline which can be used to dealy a value, the length of pipeline is derived from number of clock_enable signals """ if isinstance(sig_in, (int, HValue)): return sig_in if name_prefix is None: name_prefix = getSignalName(sig_in) out = sig_in for st_i, ce in enumerate(clock_enables): r = self._reg(f"{name_prefix:s}_{st_i:d}", dtype=out._dtype) If(ce, r(out) ) out = r return out
def _implLatencyAndDelay(self, inVld: RtlSignal, inRd: RtlSignal, inData: List[RtlSignal], outVld: RtlSignal, outRd: RtlSignal, prefix: str): """ Create a register pipe """ wordLoaded = self._reg(prefix + "wordLoaded", def_val=0) If(wordLoaded, wordLoaded(~outRd)).Else(wordLoaded(inVld)) outData = [] for iin in inData: r = self._reg('reg_' + getSignalName(iin), iin._dtype) If(~wordLoaded, r(iin)) outData.append(r) inRd(~wordLoaded) outVld(wordLoaded) return outData
def _impl_latency(self, inVld, inRd, inData, outVld, outRd, prefix): """ Create a normal handshaked register """ isOccupied = self._reg(prefix + "isOccupied", def_val=0) regs_we = self._sig(prefix + 'reg_we') outData = [] for iin in inData: r = self._reg(prefix + 'reg_' + getSignalName(iin), iin._dtype) If(regs_we, r(iin)) outData.append(r) If(isOccupied, inRd(outRd), regs_we(inVld & outRd), If(outRd & ~inVld, isOccupied(0))).Else(inRd(1), regs_we(inVld), isOccupied(inVld)) outVld(isOccupied) return outData
def oversample(self, sig, sampleCount, sampleTick, rstSig=None) -> Tuple[RtlSignal, RtlSignal]: """ [TODO] last sample is not sampled correctly :param sig: signal to oversample :param sampleCount: count of samples to do :param sampleTick: signal to enable next sample taking :param rstSig: rstSig signal to reset internal counter, if is None it is not used :return: typle (oversampled signal, oversample valid signal) """ if sig._dtype != BIT: raise NotImplementedError() n = getSignalName(sig) sCnt = int(sampleCount) sampleDoneTick = self.timer((n + "_oversampleDoneTick", sampleCount), enableSig=sampleTick, rstSig=rstSig) oversampleCntr = self.parent._reg(f"{n:s}_oversample{sCnt:d}_cntr", Bits( log2ceil(sampleCount) + 1, False), def_val=0) if rstSig is None: rstSig = sampleDoneTick else: rstSig = rstSig | sampleDoneTick If(sampleDoneTick, oversampleCntr(0)).Elif(sampleTick & sig, oversampleCntr(oversampleCntr + 1)) oversampled = self.parent._sig(f"{n:s}_oversampled{sCnt:d}") oversampled(oversampleCntr > (sampleCount // 2 - 1)) return oversampled, sampleDoneTick
def quartus_tcl_add_interface(self, buff, thisIntf): """ Create interface in Quartus TCL :return: add_interface command string """ if thisIntf._direction == INTF_DIRECTION.MASTER: dir_ = "start" else: dir_ = "end" name = getSignalName(thisIntf) buff.extend( ["add_interface %s %s %s" % (name, self.get_quartus_name(), dir_)]) self.quartus_prop(buff, name, "ENABLED", True) self.quartus_prop(buff, name, "EXPORT_OF", "") self.quartus_prop(buff, name, "PORT_NAME_MAP", "") self.quartus_prop(buff, name, "CMSIS_SVD_VARIABLES", "") self.quartus_prop(buff, name, "SVD_ADDRESS_GROUP", "")
def _implLatencyAndDelay(self, inVld, inRd, inData, outVld, outRd, prefix): wordLoaded = self._reg(prefix + "wordLoaded", defVal=0) If(wordLoaded, wordLoaded(~outRd) ).Else( wordLoaded(inVld) ) outData = [] for iin in inData: r = self._reg('reg_' + getSignalName(iin), iin._dtype) If(~wordLoaded, r(iin) ) outData.append(r) inRd(~wordLoaded) outVld(wordLoaded) return outData
def oversample(self, sig, sampleCount, sampleTick, rstSig=None) -> Tuple[RtlSignal, RtlSignal]: """ [TODO] last sample is not sampled correctly :param sig: signal to oversample :param sampleCount: count of samples to do :param sampleTick: signal to enable next sample taking :param rstSig: rstSig signal to reset internal counter, if is None it is not used :return: typle (oversampled signal, oversample valid signal) """ if sig._dtype != BIT: raise NotImplementedError() n = getSignalName(sig) sCnt = int(sampleCount) sampleDoneTick = self.timer((n + "_oversampleDoneTick", sampleCount), enableSig=sampleTick, rstSig=rstSig) oversampleCntr = self.parent._reg(n + "_oversample%d_cntr" % (sCnt), Bits(log2ceil(sampleCount) + 1, False), defVal=0) if rstSig is None: rstSig = sampleDoneTick else: rstSig = rstSig | sampleDoneTick If(sampleDoneTick, oversampleCntr(0) ).Elif(sampleTick & sig, oversampleCntr(oversampleCntr + 1) ) oversampled = self.parent._sig(n + "_oversampled%d" % (sCnt)) oversampled(oversampleCntr > (sampleCount // 2 - 1)) return oversampled, sampleDoneTick
def asQuartusTcl(self, buff: List[str], version: str, component, entity: Entity, allInterfaces: List[Interface], thisIf: Interface): """ Add interface to Quartus tcl :param buff: line buffer for output :param version: Quartus version :param intfName: name of top interface :param component: component object from ipcore generator :param entity: Entity instance of top unit :param allInterfaces: list of all interfaces of top unit :param thisIf: interface to add into Quartus TCL """ name = getSignalName(thisIf) self.quartus_tcl_add_interface(buff, thisIf) clk = thisIf._getAssociatedClk() if clk is not None: self.quartus_prop(buff, name, "associatedClock", clk._sigInside.name, escapeStr=False) rst = thisIf._getAssociatedRst() if rst is not None: self.quartus_prop(buff, name, "associatedReset", rst._sigInside.name, escapeStr=False) m = self.get_quartus_map() if m: intfMapOrName = m else: intfMapOrName = thisIf.name self._asQuartusTcl(buff, version, name, component, entity, allInterfaces, thisIf, intfMapOrName)
def _walkStructIntfAndIntfMap_unpack(structIntf, intfMap): """ Try to unpack intfMap and apply the selection on structIntf :return: Optional tuple Interface, intfMap """ # items are Interface/RtlSignal or (type/interface/None or list of items, name) if isPaddingInIntfMap(intfMap): return elif isinstance(intfMap, tuple): item, name = intfMap else: item = intfMap assert isinstance(item, (InterfaceBase, RtlSignalBase)), item name = getSignalName(item) if isinstance(item, HdlType): # this part of structIntf was generated from type descriptin # and we are re searching only for those parts which were generated # from Interface/RtlSignal return return getattr(structIntf, name), item
def getInterfaceLogicalName(self, intf: Interface): """ :see: doc of method on parent class """ return getSignalName(intf)
def _impl(self): propagateClkRstn(self) for intf in self._interfaces: if intf not in [self.clk, self.rst_n]: intf.vld(getattr(self.core, getSignalName(intf)))
def asQuartusTcl(self, buff, version, component, entity, allInterfaces, thisIf): self.quartus_tcl_add_interface(buff, thisIf) name = getSignalName(thisIf) self.quartus_prop(buff, name, "clockRate", 0) self.quartus_add_interface_port(buff, getSignalName(thisIf), thisIf, "clk")