def _declr(self): addClkRstn(self) # addr of start of array self.base = VectSignal(self.ADDR_WIDTH) # input index of item to get self.index = Handshaked() self.index.DATA_WIDTH.set(log2ceil(self.ITEMS)) # output item from array self.item = Handshaked()._m() self.item.DATA_WIDTH.set(self.ITEM_WIDTH) self.ITEMS_IN_DATA_WORD = int(self.DATA_WIDTH) // int(self.ITEM_WIDTH) with self._paramsShared(): # interface for communication with datapump self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) if self.ITEMS_IN_DATA_WORD > 1: assert isPow2(self.ITEMS_IN_DATA_WORD) f = self.itemSubIndexFifo = HandshakedFifo(Handshaked) f.DATA_WIDTH.set(log2ceil(self.ITEMS_IN_DATA_WORD)) f.DEPTH.set(self.MAX_TRANS_OVERLAP)
def _impl(self): propagateClkRstn(self) cntr = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN)), defVal=0) en = self._reg("enable", defVal=0) _len = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN)), defVal=0) self.conv.bus(self.cntrl) cEn = self.conv.decoded.enable If(cEn.dout.vld, connect(cEn.dout.data, en, fit=True)) connect(en, cEn.din, fit=True) cLen = self.conv.decoded.len If(cLen.dout.vld, connect(cLen.dout.data, _len, fit=True)) connect(_len, cLen.din, fit=True) out = self.axis_out connect(cntr, out.data, fit=True) if self.USE_STRB: out.strb(mask(self.axis_out.strb._dtype.bit_length())) out.last(cntr._eq(0)) out.valid(en) If(cLen.dout.vld, connect(cLen.dout.data, cntr, fit=True)).Else( If(out.ready & en, If(cntr._eq(0), cntr(_len)).Else(cntr(cntr - 1))))
def _declr(self): self.id = VectSignal(self.ID_WIDTH) self.addr = VectSignal(self.ADDR_WIDTH) # len is number of words -1 self.len = VectSignal(log2ceil(self.MAX_LEN)) # rem is number of bits in last word which is valid - 1 self.rem = VectSignal(log2ceil(self.DATA_WIDTH // 8)) HandshakeSync._declr(self)
def _impl(self): propagateClkRstn(self) dIn = AxiSBuilder(self, self.dataIn).buff().end sb = self.sizesBuff db = self.dataBuff wordCntr = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN) + 1), defVal=0) overflow = wordCntr._eq(self.MAX_LEN) last = dIn.last | overflow If( StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn]).ack(), If(last, wordCntr(0)).Else(wordCntr(wordCntr + 1))) length = self._sig("length", wordCntr._dtype) BYTE_CNT = dIn.data._dtype.bit_length() // 8 if dIn.USE_STRB: # compress strb mask as binary number rem = self._sig("rem", Bits(log2ceil(BYTE_CNT))) SwitchLogic(cases=[(dIn.strb[i], rem(0 if i == BYTE_CNT - 1 else i + 1)) for i in reversed(range(BYTE_CNT))], default=[ rem(0), ]) if self.EXPORT_ALIGNMENT_ERROR: errorAlignment = self._reg("errorAlignment_reg", defVal=0) self.errorAlignment(errorAlignment) If(dIn.valid & (dIn.strb != mask(BYTE_CNT)) & ~dIn.last, errorAlignment(1)) If(last & (dIn.strb != mask(BYTE_CNT)), length(wordCntr)).Else(length(wordCntr + 1)) else: length(wordCntr + 1) rem = vec(0, log2ceil(BYTE_CNT)) sb.dataIn.data(Concat(length, rem)) connect(dIn, db.dataIn, exclude=[dIn.valid, dIn.ready, dIn.last]) db.dataIn.last(last) StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn], extraConds={ sb.dataIn: last }).sync() self.sizes(sb.dataOut) connect(db.dataOut, self.dataOut)
def _declr(self): assert int( self.DEPTH) > 0, "Fifo is disabled in this case, do not use it entirely" addClkRstn(self) with self._paramsShared(): self.dataIn = FifoWriter() self.dataOut = FifoReader()._m() if self.EXPORT_SIZE: self.size = VectSignal(log2ceil(self.DEPTH + 1), signed=False)._m() if self.EXPORT_SPACE: self.space = VectSignal(log2ceil(self.DEPTH + 1), signed=False)._m()
def _declr(self): assert int( self.DEPTH ) > 0, "Fifo is disabled in this case, do not use it entirely" addClkRstn(self) with self._paramsShared(): self.dataIn = FifoWriter() self.dataOut = FifoReader()._m() if self.EXPORT_SIZE: self.size = VectSignal(log2ceil(self.DEPTH + 1), signed=False)._m() if self.EXPORT_SPACE: self.space = VectSignal(log2ceil(self.DEPTH + 1), signed=False)._m()
def _declr(self): addClkRstn(self) with self._paramsShared(): # read interface for datapump # interface which sending requests to download addr of next block self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set( 1) # because we are downloading only addres of next block # write interface for datapump self.wDatapump = AxiWDatapumpIntf()._m() self.wDatapump.MAX_LEN.set(self.BUFFER_CAPACITY // 2) assert self.BUFFER_CAPACITY <= self.ITEMS_IN_BLOCK # interface for items which should be written into list self.dataIn = Handshaked() # interface to control internal register a = self.baseAddr = RegCntrl() a._replaceParam(a.DATA_WIDTH, self.ADDR_WIDTH) self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr._replaceParam(ptr.DATA_WIDTH, self.PTR_WIDTH) f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE.set(True) f.DATA_WIDTH.set(self.DATA_WIDTH) f.DEPTH.set(self.BUFFER_CAPACITY) self.ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8).val
def timeoutHandler(self, rst, incr): timeoutCntr = self._reg("timeoutCntr", Bits(log2ceil(self.TIMEOUT) + 1, signed=False), defVal=self.TIMEOUT) If(rst, timeoutCntr(self.TIMEOUT)).Elif((timeoutCntr != 0) & incr, timeoutCntr(timeoutCntr - 1)) return timeoutCntr._eq(0)
def _declr(self): addClkRstn(self) with self._paramsShared(): # interface which sending requests to download data # and interface which is collecting all data and only data with specified id are processed self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(self.BUFFER_CAPACITY // 2 - 1) self.dataOut = Handshaked()._m() # (how much of items remains in block) self.inBlockRemain = VectSignal(log2ceil(self.ITEMS_IN_BLOCK + 1))._m() # interface to control internal register a = self.baseAddr = RegCntrl() a._replaceParam(a.DATA_WIDTH, self.ADDR_WIDTH) self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr._replaceParam(ptr.DATA_WIDTH, self.PTR_WIDTH) f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE.set(True) f.DATA_WIDTH.set(self.DATA_WIDTH) f.DEPTH.set(self.BUFFER_CAPACITY)
def _declr(self): assert int( self.DEPTH ) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2(self.DEPTH), "FifoAsync DEPTH has to be power of 2" # pow 2 because of gray conter counters if int(self.EXPORT_SIZE) or int(self.EXPORT_SPACE): raise NotImplementedError() self.dataIn_clk = Clk() self.dataOut_clk = Clk() self.rst_n = Rst_n() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut = FifoReader()._m() self.pWr = GrayCntr() self.pRd = GrayCntr() self.addrW = log2ceil(self.DEPTH) for cntr in [self.pWr, self.pRd]: cntr.DATA_WIDTH.set(self.addrW)
def _mkFieldInterface(self, structIntf, field): t = field.dtype if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): if self.shouldEnterFn(field): if isinstance(t.elmType, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.elmType.bit_length() else: p = HObjList([StructIntf( t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size))]) return p else: p = BramPort_withoutClk() dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(int(t.size) - 1)) else: raise NotImplementedError(t) p.DATA_WIDTH.set(dw) return p
def _declr(self): addClkRstn(self) with self._paramsShared(): # read interface for datapump # interface which sending requests to download addr of next block self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) # because we are downloading only addres of next block # write interface for datapump self.wDatapump = AxiWDatapumpIntf()._m() self.wDatapump.MAX_LEN.set(self.BUFFER_CAPACITY // 2) assert self.BUFFER_CAPACITY <= self.ITEMS_IN_BLOCK # interface for items which should be written into list self.dataIn = Handshaked() # interface to control internal register a = self.baseAddr = RegCntrl() a._replaceParam(a.DATA_WIDTH, self.ADDR_WIDTH) self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr._replaceParam(ptr.DATA_WIDTH, self.PTR_WIDTH) f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE.set(True) f.DATA_WIDTH.set(self.DATA_WIDTH) f.DEPTH.set(self.BUFFER_CAPACITY) self.ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8).val
def _instantiateTimer(parentUnit, timer, enableSig=None, rstSig=None): """ :param enableSig: enable signal for all counters :param rstSig: reset signal for all counters """ if timer.parent is None: maxVal = timer.maxVal - 1 # use original to propagate parameter origMaxVal = timer.maxValOriginal - 1 assert maxVal >= 0 if maxVal == 0: if enableSig is None: tick = 1 else: tick = enableSig else: timer.cntrRegister = parentUnit._reg( timer.name + "timerCntr%d" % timer.maxVal, Bits(log2ceil(maxVal + 1)), maxVal) tick = TimerInfo._instantiateTimerTickLogic( parentUnit, timer, origMaxVal, enableSig, rstSig) timer.tick = parentUnit._sig(timer.name + "timerTick%d" % timer.maxVal) timer.tick(tick) else: TimerInfo._instantiateTimerWithParent(parentUnit, timer, timer.parent, enableSig, rstSig)
def getOptimalAddrSize(self): assert self._slaves last = self._slaves[-1] maxAddr = last[0] + last[1] maxAddr -= int(self.DATA_WIDTH) // 8 assert maxAddr >= 0 return int(log2ceil(maxAddr))
def _downscale(self, factor): inputRegs_cntr = self._reg("inputRegs_cntr", Bits(log2ceil(factor + 1), False), defVal=0) # instantiate HandshakedReg, handshaked builder is not used to avoid dependencies inReg = HandshakedReg(self.intfCls) inReg._updateParamsFrom(self.dataIn) self.inReg = inReg inReg.clk(self.clk) inReg.rst_n(self.rst_n) inReg.dataIn(self.dataIn) dataIn = inReg.dataOut dataOut = self.dataOut # create output mux for din, dout in zip(self.getData(dataIn), self.getData(dataOut)): widthOfPart = din._dtype.bit_length() // factor inParts = iterBits(din, bitsInOne=widthOfPart) Switch(inputRegs_cntr).addCases( [(i, dout(inPart)) for i, inPart in enumerate(inParts)] ) self.getVld(dataOut)(self.getVld(dataIn)) self.getRd(dataIn)(inputRegs_cntr._eq(factor - 1) & self.getRd(dataOut)) If(self.getVld(dataIn) & self.getRd(dataOut), If(inputRegs_cntr._eq(factor - 1), inputRegs_cntr(0) ).Else( inputRegs_cntr(inputRegs_cntr + 1) ) )
def _declr(self): assert int(self.DEPTH) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2(self.DEPTH), "FifoAsync DEPTH has to be power of 2" # pow 2 because of gray conter counters if int(self.EXPORT_SIZE) or int(self.EXPORT_SPACE): raise NotImplementedError() self.dataIn_clk = Clk() self.dataOut_clk = Clk() self.rst_n = Rst_n() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut = FifoReader()._m() self.pWr = GrayCntr() self.pRd = GrayCntr() self.addrW = log2ceil(self.DEPTH) for cntr in [self.pWr, self.pRd]: cntr.DATA_WIDTH.set(self.addrW)
def _mkFieldInterface(self, structIntf, field): t = field.dtype if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): if self.shouldEnterFn(field): if isinstance(t.elmType, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.elmType.bit_length() else: p = HObjList([ StructIntf(t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size)) ]) return p else: p = BramPort_withoutClk() dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(int(t.size) - 1)) else: raise NotImplementedError(t) p.DATA_WIDTH.set(dw) return p
def _declr(self): self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE).val self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil( self.LVL1_PAGE_TABLE_ITEMS).val self.LVL2_PAGE_TABLE_INDX_WIDTH = int(self.ADDR_WIDTH - self.LVL1_PAGE_TABLE_INDX_WIDTH - self.PAGE_OFFSET_WIDTH) self.LVL2_PAGE_TABLE_ITEMS = 2**int(self.LVL2_PAGE_TABLE_INDX_WIDTH) assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS # public interfaces addClkRstn(self) with self._paramsShared(): self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) i = self.virtIn = Handshaked() i._replaceParam(i.DATA_WIDTH, self.VIRT_ADDR_WIDTH) i = self.physOut = Handshaked()._m() i._replaceParam(i.DATA_WIDTH, self.ADDR_WIDTH) self.segfault = Signal()._m() self.lvl1Table = BramPort_withoutClk() # internal components self.lvl1Storage = RamSingleClock() self.lvl1Storage.PORT_CNT.set(1) self.lvl1Converter = RamAsHs() for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]: u.DATA_WIDTH.set(self.ADDR_WIDTH) u.ADDR_WIDTH.set(self.LVL1_PAGE_TABLE_INDX_WIDTH) with self._paramsShared(): self.lvl2get = ArrayItemGetter() self.lvl2get.ITEM_WIDTH.set(self.ADDR_WIDTH) self.lvl2get.ITEMS.set(self.LVL2_PAGE_TABLE_ITEMS) self.lvl2indxFifo = HandshakedFifo(Handshaked) self.lvl2indxFifo.DEPTH.set(self.MAX_OVERLAP // 2) self.lvl2indxFifo.DATA_WIDTH.set(self.LVL2_PAGE_TABLE_INDX_WIDTH) self.pageOffsetFifo = HandshakedFifo(Handshaked) self.pageOffsetFifo.DEPTH.set(self.MAX_OVERLAP) self.pageOffsetFifo.DATA_WIDTH.set(self.PAGE_OFFSET_WIDTH)
def timeoutHandler(self, rst, incr): timeoutCntr = self._reg("timeoutCntr", Bits(log2ceil(self.TIMEOUT) + 1, signed=False), defVal=self.TIMEOUT) If(rst, timeoutCntr(self.TIMEOUT) ).Elif((timeoutCntr != 0) & incr, timeoutCntr(timeoutCntr - 1) ) return timeoutCntr._eq(0)
def _declr(self): addClkRstn(self) with self._paramsShared(): self.match = Handshaked() self.write = AddrDataBitMaskHs() self.write.ADDR_WIDTH.set(log2ceil(self.ITEMS - 1)) o = self.out = VldSynced()._m() o._replaceParam(o.DATA_WIDTH, self.ITEMS)
def _instantiateTimerWithParent(parentUnit, timer, parent, enableSig, rstSig): p = parent if not hasattr(p, "tick"): TimerInfo._instantiateTimer(parentUnit, p, enableSig, rstSig) assert hasattr(p, "tick") if p.maxVal == timer.maxVal: timer.cntrRegister = p.cntrRegister timer.tick = p.tick elif p.maxVal < timer.maxVal: maxVal = (timer.maxVal // p.maxVal) - 1 assert maxVal >= 0 timer.tick = parentUnit._sig( timer.name + "timerTick%d" % timer.maxVal) timer.cntrRegister = parentUnit._reg( timer.name + "timerCntr%d" % timer.maxVal, Bits(log2ceil(maxVal + 1)), maxVal ) en = p.tick if enableSig is not None: en = en & enableSig tick = TimerInfo._instantiateTimerTickLogic( parentUnit, timer, (timer.maxValOriginal // p.maxValOriginal) - 1, en, rstSig) timer.tick(tick & p.tick) else: # take specific bit from wider counter assert isPow2(timer.maxVal), timer.maxVal bitIndx = log2ceil(timer.maxVal) timer.cntrRegister = p.cntrRegister timer.tick = p.cntrRegister[bitIndx:]._eq(0) if enableSig is not None: timer.tick = timer.tick & enableSig
def _impl(self): self._parseTemplate() bus = self.bus def connectRegIntfAlways(regIntf, _addr): return ( c(bus.din, regIntf.dout.data) + c(bus.we & bus.en & bus.addr._eq(_addr), regIntf.dout.vld) ) ADDR_STEP = self._getAddrStep() if self._directlyMapped: readReg = self._reg("readReg", dtype=bus.dout._dtype) # tuples (condition, assign statements) readRegInputs = [] for t in self._directlyMapped: port = self.getPort(t) _addr = t.bitAddr // ADDR_STEP connectRegIntfAlways(port, _addr) readRegInputs.append((bus.addr._eq(_addr), readReg(port.din) )) SwitchLogic(readRegInputs) else: readReg = None if self._bramPortMapped: BRAMS_CNT = len(self._bramPortMapped) bramIndxCases = [] readBramIndx = self._reg("readBramIndx", Bits( log2ceil(BRAMS_CNT + 1), False)) outputSwitch = Switch(readBramIndx) for i, t in enumerate(self._bramPortMapped): # if we can use prefix instead of addr comparing do it _addr = t.bitAddr // ADDR_STEP _addrEnd = t.bitAddrEnd // ADDR_STEP port = self.getPort(t) _addrVld, _ = self.propagateAddr(bus.addr, ADDR_STEP, port.addr, port.dout._dtype.bit_length(), t) port.we(bus.we & _addrVld & bus.en) port.en(bus.en & _addrVld & bus.en) port.din(bus.din) bramIndxCases.append((_addrVld, readBramIndx(i))) outputSwitch.Case(i, bus.dout(port.dout)) outputSwitch.Default(bus.dout(readReg)) SwitchLogic(bramIndxCases, default=readBramIndx(BRAMS_CNT)) else: bus.dout(readReg)
def downscale(self, IN_DW, OUT_DW): if IN_DW % OUT_DW != 0: raise NotImplementedError() dOut = self.getDataWidthDependent(self.dataOut) # instantiate AxiSReg, AxiSBuilder is not used to avoid dependencies inReg = AxiSReg(self.intfCls) inReg._updateParamsFrom(self.dataIn) self.inReg = inReg inReg.clk(self.clk) inReg.rst_n(self.rst_n) inReg.dataIn(self.dataIn) dataIn = inReg.dataOut dIn = self.getDataWidthDependent(dataIn) ITEMS = IN_DW // OUT_DW itemCntr = self._reg("itemCntr", Bits(log2ceil(ITEMS + 1)), defVal=0) hs = StreamNode([dataIn], [self.dataOut]).ack() isLastItem = itemCntr._eq(ITEMS - 1) strbLastOverride = self.nextAreNotValidLogic(dataIn.strb, itemCntr, ITEMS, OUT_DW) if strbLastOverride is not True: isLastItem = isLastItem | strbLastOverride # connected item selected by itemCntr to output for inp, outp in zip(dIn, dOut): w = outp._dtype.bit_length() Switch(itemCntr)\ .addCases([ (wordIndx, outp(inp[((wordIndx + 1) * w):(w * wordIndx)])) for wordIndx in range(ITEMS) ])\ .Default( outp(None) ) # connect others signals directly for inp, outp in zip(self.getData(dataIn), self.getData(self.dataOut)): if inp not in dIn and inp is not dataIn.last: outp(inp) self.dataOut.last(dataIn.last & isLastItem) self.getRd(dataIn)(self.getRd(self.dataOut) & isLastItem & dataIn.valid) self.getVld(self.dataOut)(self.getVld(dataIn)) If(hs, If(isLastItem, itemCntr(0) ).Else( itemCntr(itemCntr + 1) ) )
def _declr(self): addClkRstn(self) self.cntrl = HandshakeSync() self.COUNTER_WIDTH = log2ceil(self.ITERATIONS) self.index = VectSignal(self.COUNTER_WIDTH)._m() self.body = HandshakeSync()._m() self.bodyBreak = Signal()
def _declr(self): self.data = VectSignal(self.DATA_WIDTH) self.rem = VectSignal(log2ceil(self.DATA_WIDTH // 8)) self.src_rdy_n = s() self.dst_rdy_n = s(masterDir=DIRECTION.IN) self.sof_n = s() self.eof_n = s() self.eop_n = s() self.sop_n = s()
def _declr(self): self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE).val self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil(self.LVL1_PAGE_TABLE_ITEMS).val self.LVL2_PAGE_TABLE_INDX_WIDTH = int(self.ADDR_WIDTH - self.LVL1_PAGE_TABLE_INDX_WIDTH - self.PAGE_OFFSET_WIDTH) self.LVL2_PAGE_TABLE_ITEMS = 2 ** int(self.LVL2_PAGE_TABLE_INDX_WIDTH) assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS # public interfaces addClkRstn(self) with self._paramsShared(): self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_LEN.set(1) i = self.virtIn = Handshaked() i._replaceParam(i.DATA_WIDTH, self.VIRT_ADDR_WIDTH) i = self.physOut = Handshaked()._m() i._replaceParam(i.DATA_WIDTH, self.ADDR_WIDTH) self.segfault = Signal()._m() self.lvl1Table = BramPort_withoutClk() # internal components self.lvl1Storage = RamSingleClock() self.lvl1Storage.PORT_CNT.set(1) self.lvl1Converter = RamAsHs() for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]: u.DATA_WIDTH.set(self.ADDR_WIDTH) u.ADDR_WIDTH.set(self.LVL1_PAGE_TABLE_INDX_WIDTH) with self._paramsShared(): self.lvl2get = ArrayItemGetter() self.lvl2get.ITEM_WIDTH.set(self.ADDR_WIDTH) self.lvl2get.ITEMS.set(self.LVL2_PAGE_TABLE_ITEMS) self.lvl2indxFifo = HandshakedFifo(Handshaked) self.lvl2indxFifo.DEPTH.set(self.MAX_OVERLAP // 2) self.lvl2indxFifo.DATA_WIDTH.set(self.LVL2_PAGE_TABLE_INDX_WIDTH) self.pageOffsetFifo = HandshakedFifo(Handshaked) self.pageOffsetFifo.DEPTH.set(self.MAX_OVERLAP) self.pageOffsetFifo.DATA_WIDTH.set(self.PAGE_OFFSET_WIDTH)
def _mkFieldInterface(self, structIntf, field): """ Instantiate field interface for fields in structure template of this endpoint :return: interface for specified field """ t = field.dtype DW = int(self.DATA_WIDTH) shouldEnter, shouldUse = self.shouldEnterFn(field) if shouldUse: if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): p = BramPort_withoutClk() assert isinstance(t.elmType, Bits), t.elmType dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(t.size - 1)) else: raise NotImplementedError(t) elif shouldEnter: if isinstance(t, HArray): if isinstance(t.elmType, Bits): p = HObjList( RegCntrl() for _ in range(int(t.size)) ) dw = t.elmType.bit_length() else: return HObjList( StructIntf(t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size)) ) elif isinstance(t, HStruct): return StructIntf(t, instantiateFieldFn=self._mkFieldInterface) else: raise TypeError(t) if isinstance(p, HObjList): _p = p else: _p = [p] if dw == DW: # use param instead of value to improve readability DW = self.DATA_WIDTH if isinstance(DW, Param): for i in _p: i._replaceParam(i.DATA_WIDTH, DW) else: for i in _p: i.DATA_WIDTH.set(dw) return p
def cleanUpAddrIterator(self, en): lastAddr = self.TABLE_SIZE - 1 addr = self._reg("cleanupAddr", Bits(log2ceil(lastAddr), signed=False), defVal=0) If(en, addr(addr + 1) ) return addr, addr._eq(lastAddr)
def _impl(self): propagateClkRstn(self) ITEM_WIDTH = int(self.ITEM_WIDTH) DATA_WIDTH = int(self.DATA_WIDTH) ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD ITEM_SIZE_IN_WORDS = 1 if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH: raise NotImplementedError(ITEM_WIDTH) req = self.rDatapump.req req.id(self.ID) req.len(ITEM_SIZE_IN_WORDS - 1) req.rem(0) if ITEMS_IN_DATA_WORD == 1: addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8))) req.addr(self.base + fitTo(addr, req.addr)) StreamNode(masters=[self.index], slaves=[req]).sync() self.item.data(self.rDatapump.r.data) StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync() else: r = self.rDatapump.r.data f = self.itemSubIndexFifo subIndexBits = f.dataIn.data._dtype.bit_length() itemAlignBits = log2ceil(ITEM_WIDTH // 8) addr = Concat(self.index.data[:subIndexBits], vec(0, itemAlignBits + subIndexBits)) req.addr(self.base + fitTo(addr, req.addr)) f.dataIn.data(self.index.data[subIndexBits:]) StreamNode(masters=[self.index], slaves=[req, f.dataIn]).sync() Switch(f.dataOut.data).addCases([ (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)): (ITEM_WIDTH * i)])) for i in range(ITEMS_IN_DATA_WORD) ]) StreamNode(masters=[self.rDatapump.r, f.dataOut], slaves=[self.item]).sync()
def _impl(self): propagateClkRstn(self) ITEM_WIDTH = int(self.ITEM_WIDTH) DATA_WIDTH = int(self.DATA_WIDTH) ITEMS_IN_DATA_WORD = self.ITEMS_IN_DATA_WORD ITEM_SIZE_IN_WORDS = 1 if ITEM_WIDTH % 8 != 0 or ITEM_SIZE_IN_WORDS * DATA_WIDTH != ITEMS_IN_DATA_WORD * ITEM_WIDTH: raise NotImplementedError(ITEM_WIDTH) req = self.rDatapump.req req.id(self.ID) req.len(ITEM_SIZE_IN_WORDS - 1) req.rem(0) if ITEMS_IN_DATA_WORD == 1: addr = Concat(self.index.data, vec(0, log2ceil(ITEM_WIDTH // 8))) req.addr(self.base + fitTo(addr, req.addr)) StreamNode(masters=[self.index], slaves=[req]).sync() self.item.data(self.rDatapump.r.data) StreamNode(masters=[self.rDatapump.r], slaves=[self.item]).sync() else: r = self.rDatapump.r.data f = self.itemSubIndexFifo subIndexBits = f.dataIn.data._dtype.bit_length() itemAlignBits = log2ceil(ITEM_WIDTH // 8) addr = Concat(self.index.data[:subIndexBits], vec(0, itemAlignBits + subIndexBits)) req.addr(self.base + fitTo(addr, req.addr)) f.dataIn.data(self.index.data[subIndexBits:]) StreamNode(masters=[self.index], slaves=[req, f.dataIn]).sync() Switch(f.dataOut.data).addCases([ (ITEMS_IN_DATA_WORD - i - 1, self.item.data(r[(ITEM_WIDTH * (i + 1)):(ITEM_WIDTH * i)])) for i in range(ITEMS_IN_DATA_WORD) ]) StreamNode(masters=[self.rDatapump.r, f.dataOut], slaves=[self.item]).sync()
def _instantiateTimerWithParent(parentUnit, timer, parent, enableSig, rstSig): p = parent if not hasattr(p, "tick"): TimerInfo._instantiateTimer(parentUnit, p, enableSig, rstSig) assert hasattr(p, "tick") if p.maxVal == timer.maxVal: timer.cntrRegister = p.cntrRegister timer.tick = p.tick elif p.maxVal < timer.maxVal: maxVal = (timer.maxVal // p.maxVal) - 1 assert maxVal >= 0 timer.tick = parentUnit._sig(timer.name + "timerTick%d" % timer.maxVal) timer.cntrRegister = parentUnit._reg( timer.name + "timerCntr%d" % timer.maxVal, Bits(log2ceil(maxVal + 1)), maxVal) en = p.tick if enableSig is not None: en = en & enableSig tick = TimerInfo._instantiateTimerTickLogic( parentUnit, timer, (timer.maxValOriginal // p.maxValOriginal) - 1, en, rstSig) timer.tick(tick & p.tick) else: # take specific bit from wider counter assert isPow2(timer.maxVal), timer.maxVal bitIndx = log2ceil(timer.maxVal) timer.cntrRegister = p.cntrRegister timer.tick = p.cntrRegister[bitIndx:]._eq(0) if enableSig is not None: timer.tick = timer.tick & enableSig
def _declr(self): addClkRstn(self) with self._paramsShared(): self.drivers = HObjList(AxiRDatapumpIntf() for _ in range(int(self.DRIVER_CNT))) self.rDatapump = AxiRDatapumpIntf()._m() self.DRIVER_INDEX_WIDTH = log2ceil(self.DRIVER_CNT).val f = self.orderInfoFifo = HandshakedFifo(Handshaked) f.DEPTH.set(self.MAX_TRANS_OVERLAP) f.DATA_WIDTH.set(self.DRIVER_INDEX_WIDTH)
def _mkFieldInterface(self, structIntf, field): """ Instantiate field interface for fields in structure template of this endpoint :return: interface for specified field """ t = field.dtype DW = int(self.DATA_WIDTH) shouldEnter, shouldUse = self.shouldEnterFn(field) if shouldUse: if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): p = BramPort_withoutClk() assert isinstance(t.elmType, Bits), t.elmType dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(t.size - 1)) else: raise NotImplementedError(t) elif shouldEnter: if isinstance(t, HArray): if isinstance(t.elmType, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.elmType.bit_length() else: return HObjList( StructIntf(t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size))) elif isinstance(t, HStruct): return StructIntf(t, instantiateFieldFn=self._mkFieldInterface) else: raise TypeError(t) if isinstance(p, HObjList): _p = p else: _p = [p] if dw == DW: # use param instead of value to improve readability DW = self.DATA_WIDTH if isinstance(DW, Param): for i in _p: i._replaceParam(i.DATA_WIDTH, DW) else: for i in _p: i.DATA_WIDTH.set(dw) return p
def _declr(self): addClkRstn(self) with self._paramsShared(): self.drivers = HObjList( AxiRDatapumpIntf() for _ in range(int(self.DRIVER_CNT)) ) self.rDatapump = AxiRDatapumpIntf()._m() self.DRIVER_INDEX_WIDTH = log2ceil(self.DRIVER_CNT).val f = self.orderInfoFifo = HandshakedFifo(Handshaked) f.DEPTH.set(self.MAX_TRANS_OVERLAP) f.DATA_WIDTH.set(self.DRIVER_INDEX_WIDTH)
def _impl(self): r = self.dataIn self.parseTemplate() words = list(self.chainFrameWords()) assert not (self.SYNCHRONIZE_BY_LAST and len(self._frames) > 1) maxWordIndex = words[-1][0] hasMultipleWords = maxWordIndex > 0 if hasMultipleWords: wordIndex = self._reg("wordIndex", Bits( log2ceil(maxWordIndex + 1)), 0) else: wordIndex = None busVld = r.valid if self.IS_BIGENDIAN: byteOrderCare = reverseByteOrder else: def byteOrderCare(sig): return sig self.byteOrderCare = byteOrderCare self._tmpRegsForSelect = {} self._signalsOfParts = {} allOutNodes = WordFactory(wordIndex) self.connectParts(allOutNodes, words, wordIndex) if self.SHARED_READY: busReady = self.dataOut_ready r.ready(busReady) else: busReady = self._sig("busReady") busReady(allOutNodes.ack()) allOutNodes.sync(busVld) r.ready(busReady) if hasMultipleWords: if self.SYNCHRONIZE_BY_LAST: last = r.last else: last = wordIndex._eq(maxWordIndex) If(busVld & busReady, If(last, wordIndex(0) ).Else( wordIndex(wordIndex + 1) ) )
def _impl(self): propagateClkRstn(self) cntr = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN)), defVal=0) en = self._reg("enable", defVal=0) _len = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN)), defVal=0) self.conv.bus(self.cntrl) cEn = self.conv.decoded.enable If(cEn.dout.vld, connect(cEn.dout.data, en, fit=True) ) connect(en, cEn.din, fit=True) cLen = self.conv.decoded.len If(cLen.dout.vld, connect(cLen.dout.data, _len, fit=True) ) connect(_len, cLen.din, fit=True) out = self.axis_out connect(cntr, out.data, fit=True) if self.USE_STRB: out.strb(mask(self.axis_out.strb._dtype.bit_length())) out.last(cntr._eq(0)) out.valid(en) If(cLen.dout.vld, connect(cLen.dout.data, cntr, fit=True) ).Else( If(out.ready & en, If(cntr._eq(0), cntr(_len) ).Else( cntr(cntr - 1) ) ) )
def _declr(self): addClkRstn(self) assert int(self.KEY_WIDTH) > 0 assert int(self.DATA_WIDTH) >= 0 assert int(self.ITEMS_CNT) > 1 self.HASH_WITH = log2ceil(self.ITEMS_CNT).val assert self.HASH_WITH < int(self.KEY_WIDTH), ( "It makes no sense to use hash table when you can use key directly as index", self.HASH_WITH, self.KEY_WIDTH) with self._paramsShared(): self.insert = InsertIntf() self.insert.HASH_WIDTH.set(self.HASH_WITH) self.lookup = LookupKeyIntf() self.lookupRes = LookupResultIntf()._m() self.lookupRes.HASH_WIDTH.set(self.HASH_WITH) t = self.table = RamSingleClock() t.PORT_CNT.set(1) t.ADDR_WIDTH.set(log2ceil(self.ITEMS_CNT)) t.DATA_WIDTH.set(self.KEY_WIDTH + self.DATA_WIDTH + 1) # +1 for vldFlag tc = self.tableConnector = RamAsHs() tc.ADDR_WIDTH.set(t.ADDR_WIDTH.get()) tc.DATA_WIDTH.set(t.DATA_WIDTH.get()) hashWidth = max(int(self.KEY_WIDTH), int(self.HASH_WITH)) h = self.hash = CrcComb() h.DATA_WIDTH.set(hashWidth) h.setConfig(self.POLYNOME) h.POLY_WIDTH.set(hashWidth)
def _declr(self): addClkRstn(self) with self._paramsShared(): self.dataIn = self.intfCls() self.dataOut = self.intfCls()._m() f = self.fifo = Fifo() DW = self.dataIn._bit_length() - 2 # 2 for control (valid, ready) f.DATA_WIDTH.set(DW) f.DEPTH.set(self.DEPTH - 1) # because there is an extra register f.EXPORT_SIZE.set(self.EXPORT_SIZE) if self.EXPORT_SIZE: self.size = VectSignal( log2ceil(self.DEPTH + 1 + 1), signed=False)._m()
def _declr(self): addClkRstn(self) with self._paramsShared(): self.dataIn = self.intfCls() self.dataOut = self.intfCls()._m() f = self.fifo = Fifo() DW = self.dataIn._bit_length() - 2 # 2 for control (valid, ready) f.DATA_WIDTH.set(DW) f.DEPTH.set(self.DEPTH - 1) # because there is an extra register f.EXPORT_SIZE.set(self.EXPORT_SIZE) if self.EXPORT_SIZE: self.size = VectSignal(log2ceil(self.DEPTH + 1 + 1), signed=False)._m()
def oneHotToBin(parent, signals, resName="oneHotToBin"): if isinstance(signals, (RtlSignal, Signal)): signals = [signals[i] for i in range(signals._dtype.bit_length())] else: signals = list(signals) res = parent._sig(resName, Bits(log2ceil(len(signals)))) leadingZeroTop = None for i, s in enumerate(reversed(signals)): connections = res(len(signals) - i - 1) if leadingZeroTop is None: leadingZeroTop = connections else: leadingZeroTop = If(s, connections).Else(leadingZeroTop) return res
def _upscale(self, factor): inputRegs_cntr = self._reg("inputRegs_cntr", Bits(log2ceil(factor + 1), False), defVal=0) for din, dout in zip(self.getData(self.dataIn), self.getData(self.dataOut)): inputRegs = [self._reg("inReg%d_%s" % (i, din._name), din._dtype) for i in range(factor - 1)] # last word will be passed directly for i, r in enumerate(inputRegs): If(inputRegs_cntr._eq(i) & self.getVld(self.dataIn), r(din) ) dout(Concat(din, *reversed(inputRegs))) self._upscaleDataPassLogic(inputRegs_cntr, factor)
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 _impl(self) -> None: if len(self._masters) > 1: raise NotImplementedError() m_offset, _ = self._masters[0] if m_offset != 0: raise NotImplementedError() m = self.s[0] err = hBit(0) rdack = hBit(0) wrack = hBit(0) AW = int(self.ADDR_WIDTH) wdata = [] for i, (s, (s_offset, s_size, _)) in enumerate(zip(self.m, self._slaves)): connect(m.bus2ip_addr, s.bus2ip_addr, fit=True) s.bus2ip_be(m.bus2ip_be) s.bus2ip_rnw(m.bus2ip_rnw) s.bus2ip_data(m.bus2ip_data) bitsOfSubAddr = int(log2ceil(s_size - 1)) prefix = selectBitRange( s_offset, bitsOfSubAddr, AW - bitsOfSubAddr) cs = self._sig("m_cs_%d" % i) cs(m.bus2ip_addr[AW:bitsOfSubAddr]._eq(prefix)) s.bus2ip_cs(m.bus2ip_cs & cs) err = err | (cs & s.ip2bus_error) rdack = rdack | (cs & s.ip2bus_rdack) wrack = wrack | (cs & s.ip2bus_wrack) wdata.append((cs, s.ip2bus_data)) m.ip2bus_error(err) m.ip2bus_rdack(rdack) m.ip2bus_wrack(wrack) SwitchLogic( [(sel, m.ip2bus_data(data)) for sel, data in wdata], default=m.ip2bus_data(None) )
def oneHotToBin(parent, signals, resName="oneHotToBin"): if isinstance(signals, (RtlSignal, Signal)): signals = [signals[i] for i in range(signals._dtype.bit_length())] else: signals = list(signals) res = parent._sig(resName, Bits(log2ceil(len(signals)))) leadingZeroTop = None for i, s in enumerate(reversed(signals)): connections = res(len(signals) - i - 1) if leadingZeroTop is None: leadingZeroTop = connections else: leadingZeroTop = If(s, connections ).Else( leadingZeroTop ) return res
def _impl(self) -> None: if len(self._masters) > 1: raise NotImplementedError() m_offset, _ = self._masters[0] if m_offset != 0: raise NotImplementedError() m = self.s[0] err = hBit(0) rdack = hBit(0) wrack = hBit(0) AW = int(self.ADDR_WIDTH) wdata = [] for i, (s, (s_offset, s_size, _)) in enumerate(zip(self.m, self._slaves)): connect(m.bus2ip_addr, s.bus2ip_addr, fit=True) s.bus2ip_be(m.bus2ip_be) s.bus2ip_rnw(m.bus2ip_rnw) s.bus2ip_data(m.bus2ip_data) bitsOfSubAddr = int(log2ceil(s_size - 1)) prefix = selectBitRange(s_offset, bitsOfSubAddr, AW - bitsOfSubAddr) cs = self._sig("m_cs_%d" % i) cs(m.bus2ip_addr[AW:bitsOfSubAddr]._eq(prefix)) s.bus2ip_cs(m.bus2ip_cs & cs) err = err | (cs & s.ip2bus_error) rdack = rdack | (cs & s.ip2bus_rdack) wrack = wrack | (cs & s.ip2bus_wrack) wdata.append((cs, s.ip2bus_data)) m.ip2bus_error(err) m.ip2bus_rdack(rdack) m.ip2bus_wrack(wrack) SwitchLogic([(sel, m.ip2bus_data(data)) for sel, data in wdata], default=m.ip2bus_data(None))
def _declr(self): addClkRstn(self) with self._paramsShared(): self.dataIn = AxiStream() self.dataOut = AxiStream()._m() db = self.dataBuff = AxiSFifo() # to place fifo in bram db.DEPTH.set((self.MAX_LEN + 1) * 2) self.sizes = Handshaked()._m() self.sizes.DATA_WIDTH.set( log2ceil(self.MAX_LEN) + 1 + self.getAlignBitsCnt()) sb = self.sizesBuff = HandshakedFifo(Handshaked) sb.DEPTH.set(self.SIZES_BUFF_DEPTH) sb.DATA_WIDTH.set(self.sizes.DATA_WIDTH.get()) if self.EXPORT_ALIGNMENT_ERROR: assert self.USE_STRB, "Error can not happend when there is no validity mask for alignment" self.errorAlignment = Signal()._m() assert isPow2(self.DATA_WIDTH)
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 _declr(self): addClkRstn(self) with self._paramsShared(): self.dataIn = AxiStream() self.dataOut = AxiStream()._m() db = self.dataBuff = AxiSFifo() # to place fifo in bram db.DEPTH.set((self.MAX_LEN + 1) * 2) self.sizes = Handshaked()._m() self.sizes.DATA_WIDTH.set(log2ceil(self.MAX_LEN) + 1 + self.getAlignBitsCnt()) sb = self.sizesBuff = HandshakedFifo(Handshaked) sb.DEPTH.set(self.SIZES_BUFF_DEPTH) sb.DATA_WIDTH.set(self.sizes.DATA_WIDTH.get()) if self.EXPORT_ALIGNMENT_ERROR: assert self.USE_STRB, "Error can not happend when there is no validity mask for alignment" self.errorAlignment = Signal()._m() assert isPow2(self.DATA_WIDTH)
def _declr(self) -> None: addClkRstn(self) slavePorts = HObjList() for _, features in self._masters: if features is not ACCESS_RW: raise NotImplementedError(features) m = Ipif() m._updateParamsFrom(self) slavePorts.append(m) self.s = slavePorts masterPorts = HObjList() for _, size, features in self._slaves: if features is not ACCESS_RW: raise NotImplementedError(features) s = Ipif()._m() s.ADDR_WIDTH.set(log2ceil(size - 1)) s._replaceParam(s.DATA_WIDTH, self.DATA_WIDTH) masterPorts.append(s) self.m = masterPorts
def _instantiateTimer(parentUnit, timer, enableSig=None, rstSig=None): """ :param enableSig: enable signal for all counters :param rstSig: reset signal for all counters """ if timer.parent is None: maxVal = timer.maxVal - 1 # use original to propagate parameter origMaxVal = timer.maxValOriginal - 1 assert maxVal >= 0 if maxVal == 0: if enableSig is None: tick = 1 else: tick = enableSig else: timer.cntrRegister = parentUnit._reg( timer.name + "timerCntr%d" % timer.maxVal, Bits(log2ceil(maxVal + 1)), maxVal ) tick = TimerInfo._instantiateTimerTickLogic(parentUnit, timer, origMaxVal, enableSig, rstSig) timer.tick = parentUnit._sig( timer.name + "timerTick%d" % timer.maxVal ) timer.tick(tick) else: TimerInfo._instantiateTimerWithParent( parentUnit, timer, timer.parent, enableSig, rstSig)