def translate_addr_signal(self, mem_map, sig_in, sig_out): cases = [] AW = sig_in._dtype.bit_length() for (offset_in, size, offset_out) in mem_map: in_is_aligned = offset_in % size == 0 and isPow2(size) out_is_aligned = offset_out % size == 0 and isPow2(size) if in_is_aligned: L = (size - 1).bit_length() en_sig = sig_in[:L]._eq(offset_in >> L) _sig_in = sig_in[L:] if out_is_aligned: addr_drive = Concat( Bits(AW - L).from_py(offset_out), _sig_in) else: addr_drive = Concat(Bits(AW - L).from_py(0), _sig_in) + offset_out else: en_sig = inRange(sig_in, offset_in, offset_in + size) if offset_in == offset_out: addr_drive = sig_in elif offset_in < offset_out: addr_drive = sig_in + (offset_out - offset_in) else: # offset_in > offset_out: addr_drive = sig_in - (offset_in - offset_out) cases.append((en_sig, sig_out(addr_drive))) SwitchLogic(cases, default=sig_out(sig_in))
def _declr(self): addClkRstn(self) assert self.ALIGNAS % 8 == 0 and self.ALIGNAS > 0 and self.ALIGNAS <= self.DATA_WIDTH assert isPow2(self.ALIGNAS), self.ALIGNAS if self.MAX_CHUNKS != 1: assert self.CHUNK_WIDTH % 8 == 0, self.CHUNK_WIDTH assert isPow2(self.CHUNK_WIDTH) assert self.MAX_CHUNKS > 0, self.MAX_CHUNKS with self._paramsShared(): # address channel to axi self.axi = self._axiCls()._m()
def __init__(self, src_addr_step: int = 8, dst_addr_step: int = 8): self.src_addr_step = src_addr_step self.dst_addr_step = dst_addr_step assert isPow2(src_addr_step), src_addr_step assert isPow2(dst_addr_step), dst_addr_step if src_addr_step == dst_addr_step: align_bits = 0 elif src_addr_step < dst_addr_step: align_bits = log2ceil((dst_addr_step // src_addr_step) - 1) else: align_bits = log2ceil((src_addr_step // dst_addr_step) - 1) self.align_bits = align_bits
def _declr(self): assert isPow2(self.DEPTH - 1), ( "DEPTH has to be 2**n + 1" " because fifo has have DEPTH 2**n" " and 1 item is stored on output reg", self.DEPTH) self.dataIn_clk = Clk() self.dataOut_clk = Clk() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn_rst_n = Rst_n() with self._associated(rst=self.dataIn_rst_n): self.dataIn = self.intfCls() with self._associated(clk=self.dataOut_clk): self.dataOut_rst_n = Rst_n() with self._associated(rst=self.dataOut_rst_n): self.dataOut = self.intfCls()._m() f = self.fifo = FifoAsync() f.IN_FREQ = self.IN_FREQ f.OUT_FREQ = self.OUT_FREQ DW = self.dataIn._bit_length() - 2 # 2 for control (valid, ready) f.DATA_WIDTH = DW # because the output register is used as another item storage f.DEPTH = self.DEPTH - 1 f.EXPORT_SIZE = self.EXPORT_SIZE f.EXPORT_SPACE = self.EXPORT_SPACE SIZE_W = log2ceil(self.DEPTH + 1 + 1) if self.EXPORT_SIZE: self.size = VectSignal(SIZE_W, signed=False) if self.EXPORT_SPACE: self.space = VectSignal(SIZE_W, signed=False)
def _declr(self): assert int( self.DEPTH ) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2( self.DEPTH), f"DEPTH has to be power of 2, is {self.DEPTH:d}" # pow 2 because of gray conter counters if self.EXPORT_SIZE or self.EXPORT_SPACE: raise NotImplementedError() self.dataIn_clk = Clk() self.dataIn_clk.FREQ = self.IN_FREQ self.dataOut_clk = Clk() self.dataOut_clk.FREQ = self.OUT_FREQ with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn_rst_n = Rst_n() with self._associated(rst=self.dataIn_rst_n): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut_rst_n = Rst_n() with self._associated(rst=self.dataOut_rst_n): self.dataOut = FifoReader()._m() self.AW = log2ceil(self.DEPTH)
def _setup_clk_rst_n(self): self.clk.FREQ = self.M_FREQ self.rst_n._make_association(clk=self.clk) self.s._make_association(clk=self.clk, rst=self.rst_n) self.m_clk = Clk() self.m_clk.FREQ = self.S_FREQ self.m_rst_n = Rst_n() self.m_rst_n._make_association(clk=self.m_clk) self.m._make_association(clk=self.m_clk, rst=self.m_rst_n) assert self.ADDR_BUFF_DEPTH == 1 or isPow2(self.ADDR_BUFF_DEPTH - 1), ( self.ADDR_BUFF_DEPTH, "size 2**n + 1 for output reg") assert self.DATA_BUFF_DEPTH == 1 or isPow2(self.DATA_BUFF_DEPTH - 1), ( self.DATA_BUFF_DEPTH, "size 2**n + 1 for output reg")
def _declr(self): assert isPow2(self.WINDOW_SIZE), self.WINDOW_SIZE assert self.M_ADDR_WIDTH > self.ADDR_WIDTH, (self.M_ADDR_WIDTH, self.ADDR_WIDTH) assert (2**self.M_ADDR_WIDTH) >= self.WINDOW_SIZE, ( "has to be large enough in order to address whole window", self.M_ADDR_WIDTH, self.WINDOW_SIZE) addClkRstn(self) with self._paramsShared(exclude=({"ADDR_WIDTH"}, {})): self.m = Mi32()._m() self.m.ADDR_WIDTH = self.M_ADDR_WIDTH self.s = Mi32() self.s.ADDR_WIDTH = self.ADDR_WIDTH
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( f"{timer.name:s}timerTick{timer.maxVal:d}") timer.cntrRegister = parentUnit._reg( f"{timer.name:s}timerCntr{timer.maxVal:d}", 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.dataIn = AxiStream() self.dataOut = AxiStream()._m() db = self.dataBuff = AxiSFifo() # to place fifo in bram db.DEPTH = (self.MAX_LEN + 1) * 2 self.sizes = Handshaked()._m() self.sizes.DATA_WIDTH = (log2ceil(self.MAX_LEN) + 1 + self.getAlignBitsCnt()) sb = self.sizesBuff = HandshakedFifo(Handshaked) sb.DEPTH = self.SIZES_BUFF_DEPTH sb.DATA_WIDTH = self.sizes.DATA_WIDTH 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 resolveSharing(timers): # filter out timers with maxVal == 1 because they are only clock timers = sorted((t for t in timers if t.maxVal != 1), key=lambda t: t.maxVal, reverse=True) for i, t in enumerate(timers): if isPow2(t.maxVal): # this timer will be driven from bit of some larger # counter if there is suitable for possibleParent in timers[:i]: if possibleParent.maxVal % t.maxVal == 0: if possibleParent.parent is not None: continue t.parent = possibleParent break else: # this timer will have its own timer which will be enabled by # some other timer if there is suitable for possibleParent in timers[(i + 1):]: if t.maxVal % possibleParent.maxVal == 0: if possibleParent.parent is t: continue t.parent = possibleParent break
def _declr(self): assert isPow2(self.DATA_WIDTH), self.DATA_WIDTH self.data_in = VectSignal(self.DATA_WIDTH) self.data_out = VectSignal(log2ceil(self.DATA_WIDTH + 1))._m()
def _create_frame_build_logic(self): self.byteOrderCare = get_byte_order_modifier(self.dataOut) STRB_ALL = mask(int(self.DATA_WIDTH // 8)) words = list(self.chainFrameWords()) dout = self.dataOut maxWordIndex = words[-1][0] multipleWords = maxWordIndex > 0 if multipleWords: # multiple word frame wordCntr_inversed = self._reg("wordCntr_inversed", Bits(log2ceil(maxWordIndex + 1), False), def_val=maxWordIndex) wcntrSw = Switch(wordCntr_inversed) # inversed indexes of ends of frames endsOfFrames = [] extra_strbs = [] extra_keeps = [] for i, transParts, isLast in words: inversedIndx = maxWordIndex - i # input ports for value of this output word inPorts = [] # input ports which value should be consumed on this word lastInPorts = [] if multipleWords: wordData = self._sig(f"word{i:d}", dout.data._dtype) else: wordData = self.dataOut.data sk_stash = StrbKeepStash() for tPart in transParts: strb, keep = self.connectPartsOfWord(wordData, tPart, inPorts, lastInPorts) sk_stash.push(strb, keep) sk_stash.pop(inversedIndx, extra_strbs, extra_keeps, STRB_ALL) if multipleWords: en = wordCntr_inversed._eq(inversedIndx) else: en = True en = self.dataOut.ready & en ack = self.handshakeLogicForWord(inPorts, lastInPorts, en) inStreamLast = True for p in inPorts: if isinstance(p, AxiStream): inStreamLast = p.last & inStreamLast if multipleWords: # word cntr next logic if i == maxWordIndex: nextWordIndex = maxWordIndex else: nextWordIndex = wordCntr_inversed - 1 _ack = dout.ready & ack & inStreamLast a = [ If(_ack, wordCntr_inversed(nextWordIndex)), ] else: a = [] a.append(dout.valid(ack)) # frame with multiple words (using wordCntr_inversed) if multipleWords: # data out logic a.append(dout.data(wordData)) wcntrSw.Case(inversedIndx, a) # is last word in frame if isLast: endsOfFrames.append((inversedIndx, inStreamLast)) # to prevent latches if not multipleWords: pass elif not isPow2(maxWordIndex + 1): default = [ wordCntr_inversed(maxWordIndex), ] default.append(dout.valid(0)) default.append(dout.data(None)) wcntrSw.Default(default) if multipleWords: last = False last_last = last for indexOrTuple in endsOfFrames: i, en = indexOrTuple last_last = wordCntr_inversed._eq(i) & en last = (last_last) | last selectRegLoad = last_last & dout.ready & ack else: last = endsOfFrames[0][1] selectRegLoad = dout.ready & ack for r in self._tmpRegsForSelect.values(): r.rd(selectRegLoad) dout.last(last) if multipleWords: if self.USE_STRB: strb = dout.strb Switch(wordCntr_inversed).add_cases([ (i, strb(v)) for i, v in extra_strbs ]).Default(strb(STRB_ALL)) if self.USE_KEEP: keep = dout.keep Switch(wordCntr_inversed).add_cases([ (i, keep(v)) for i, v in extra_keeps ]).Default(keep(STRB_ALL)) else: if extra_strbs: m = extra_strbs[0][1] else: m = STRB_ALL if self.USE_STRB: dout.strb(m) if extra_keeps: m = extra_keeps[0][1] else: m = STRB_ALL if self.USE_KEEP: dout.keep(m)
def __init__(self, lru_reg: RtlSignal): assert isPow2(lru_reg._dtype.bit_length() - 1) or lru_reg._dtype.bit_length( ) == 1, lru_reg._dtype.bit_length() self.lru_regs = lru_reg