def _impl(self): HandshakedFifo._impl( self, clk_rst=( (self.dataIn_clk, self.dataIn_rst_n), (self.dataOut_clk, self.dataOut_rst_n) ) )
def _impl(self): req = self.wDatapump.req w = self.wDatapump.w ack = self.wDatapump.ack # multi frame if self.MAX_OVERLAP > 1: ackPropageteInfo = HandshakedFifo(Handshaked) ackPropageteInfo.DEPTH = self.MAX_OVERLAP else: ackPropageteInfo = HandshakedReg(Handshaked) ackPropageteInfo.DATA_WIDTH = 1 self.ackPropageteInfo = ackPropageteInfo if self.WRITE_ACK: _set = self.set else: _set = HsBuilder(self, self.set).buff().end if self.ID_WIDTH: req.id(self.ID) def propagateRequest(frame, indx): inNode = StreamNode(slaves=[req, ackPropageteInfo.dataIn]) ack = inNode.ack() isLastFrame = indx == len(self._frames) - 1 statements = [ req.addr(_set.data + frame.startBitAddr // 8), req.len(frame.getWordCnt() - 1), self.driveReqRem( req, frame.parts[-1].endOfPart - frame.startBitAddr), ackPropageteInfo.dataIn.data(SKIP if indx != 0 else PROPAGATE), inNode.sync(_set.vld), _set.rd(ack if isLastFrame else 0), ] return statements, ack & _set.vld StaticForEach(self, self._frames, propagateRequest) # connect write channel w(self.frameAssember.dataOut) # propagate ack StreamNode(masters=[ack, ackPropageteInfo.dataOut], slaves=[self.writeAck], skipWhen={ self.writeAck: ackPropageteInfo.dataOut.data._eq(PROPAGATE) }).sync() # connect fields to assembler for _, transTmpl in self._tmpl.walkFlatten(): f = transTmpl.getFieldPath() intf = self.frameAssember.dataIn._fieldsToInterfaces[f] intf(self.dataIn._fieldsToInterfaces[f]) propagateClkRstn(self)
def _declr(self): AxiInterconnectCommon._declr(self, has_r=False, has_w=True) masters_for_slave = AxiInterconnectMatrixCrossbar._masters_for_slave( self.MASTERS, len(self.SLAVES)) # fifo for master index for each slave so slave knows # which master did read and where is should send it order_m_index_for_s_data = HObjList() order_m_index_for_s_b = HObjList() for connected_masters in masters_for_slave: if len(connected_masters) > 1: f_w = HandshakedFifo(Handshaked) f_b = HandshakedFifo(Handshaked) for _f in [f_w, f_b]: _f.DEPTH = self.MAX_TRANS_OVERLAP _f.DATA_WIDTH = log2ceil(len(self.MASTERS)) else: f_w, f_b = None, None order_m_index_for_s_data.append(f_w) order_m_index_for_s_b.append(f_b) self.order_m_index_for_s_data = order_m_index_for_s_data self.order_m_index_for_s_b = order_m_index_for_s_b # fifo for slave index for each master # so master knows where it should expect the data order_s_index_for_m_data = HObjList() order_s_index_for_m_b = HObjList() for connected_slaves in self.MASTERS: if len(connected_slaves) > 1: f_w = HandshakedFifo(Handshaked) f_b = HandshakedFifo(Handshaked) for f in [f_w, f_b]: f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.SLAVES)) else: f_w, f_b = None, None order_s_index_for_m_data.append(f_w) order_s_index_for_m_b.append(f_b) self.order_s_index_for_m_data = order_s_index_for_m_data self.order_s_index_for_m_b = order_s_index_for_m_b AXI = self.intfCls with self._paramsShared(): self.addr_crossbar = AxiInterconnectMatrixAddrCrossbar(AXI.AW_CLS) with self._paramsShared(): c = self.data_crossbar = AxiInterconnectMatrixCrossbar(AXI.W_CLS) c.INPUT_CNT = len(self.MASTERS) W_OUTPUTS = [set() for _ in self.SLAVES] for m_i, accessible_slaves in enumerate(self.MASTERS): for s_i in accessible_slaves: W_OUTPUTS[s_i].add(m_i) c.OUTPUTS = W_OUTPUTS with self._paramsShared(): c = self.b_crossbar = AxiInterconnectMatrixCrossbarB(AXI.B_CLS) c.INPUT_CNT = len(self.SLAVES) c.OUTPUTS = self.MASTERS
def _declr(self): addClkRstn(self) with self._paramsShared(): self.drivers = HObjList(AxiWDatapumpIntf() for _ in range(int(self.DRIVER_CNT))) self.wDatapump = AxiWDatapumpIntf()._m() self.DRIVER_INDEX_WIDTH = log2ceil(self.DRIVER_CNT) fW = self.orderInfoFifoW = HandshakedFifo(Handshaked) fAck = self.orderInfoFifoAck = HandshakedFifo(Handshaked) for f in [fW, fAck]: f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = self.DRIVER_INDEX_WIDTH
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 _declr(self) -> None: self._normalize_config() addClkRstn(self) slavePorts = HObjList() for _ in self.MASTERS: s = Mi32() s._updateParamsFrom(self) slavePorts.append(s) self.s = slavePorts masterPorts = HObjList() for _, size in self.SLAVES: m = Mi32()._m() m.ADDR_WIDTH = log2ceil(size - 1) m.DATA_WIDTH = self.DATA_WIDTH masterPorts.append(m) self.m = masterPorts # fifo which keeps index of slave for master read transaction # so the interconnect can delivery the read data to master # which asked for it f = self.r_data_order = HandshakedFifo(Handshaked) f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.SLAVES))
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() # because we are downloading only addres of next block self.rDatapump.MAX_LEN = 1 # write interface for datapump self.wDatapump = AxiWDatapumpIntf()._m() self.wDatapump.MAX_LEN = 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.DATA_WIDTH = self.ADDR_WIDTH self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr.DATA_WIDTH = self.PTR_WIDTH f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE = True f.DATA_WIDTH = self.DATA_WIDTH f.DEPTH = self.BUFFER_CAPACITY self.ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8)
def setUp(self): SimTestCase.setUp(self) u = self.u = HandshakedFifo(Handshaked) u.DEPTH.set(self.ITEMS) u.DATA_WIDTH.set(8) u.EXPORT_SIZE.set(True) self.prepareUnit(u)
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_BYTES = self.BUFFER_CAPACITY // 2 * self.DATA_WIDTH // 8 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.DATA_WIDTH = self.ADDR_WIDTH self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr.DATA_WIDTH = self.PTR_WIDTH f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE = True f.DATA_WIDTH = self.DATA_WIDTH f.DEPTH = self.BUFFER_CAPACITY
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 _impl(self): req = self.wDatapump.req w = self.wDatapump.w ack = self.wDatapump.ack # multi frame ackPropageteInfo = HandshakedFifo(Handshaked) ackPropageteInfo.DATA_WIDTH.set(1) ackPropageteInfo.DEPTH.set(self.MAX_OVERLAP) self.ackPropageteInfo = ackPropageteInfo propagateClkRstn(self) if self.WRITE_ACK: _set = self.set else: _set = HsBuilder(self, self.set).buff().end req.id(self.ID) req.rem(0) def propagateRequests(frame, indx): ack = StreamNode(slaves=[req, ackPropageteInfo.dataIn]).ack() statements = [req.addr(_set.data + frame.startBitAddr // 8), req.len(frame.getWordCnt() - 1), StreamNode(slaves=[req, ackPropageteInfo.dataIn], ).sync(_set.vld) ] if indx != 0: prop = SKIP else: prop = PROPAGATE statements.append(ackPropageteInfo.dataIn.data(prop)) isLastFrame = indx == len(self._frames) - 1 if isLastFrame: statements.append(_set.rd(ack)) else: statements.append(_set.rd(0)) return statements, ack & _set.vld StaticForEach(self, self._frames, propagateRequests) # connect write channel w(self.frameAssember.dataOut) # propagate ack StreamNode(masters=[ack, ackPropageteInfo.dataOut], slaves=[self.writeAck], skipWhen={ self.writeAck: ackPropageteInfo.dataOut.data._eq(PROPAGATE) }).sync() # connect fields to assembler for _, transTmpl in self._tmpl.walkFlatten(): f = transTmpl.origin intf = self.frameAssember.dataIn._fieldsToInterfaces[f] intf(self.dataIn._fieldsToInterfaces[f])
def _declr(self): super()._declr() # add clk, rst, axi addr channel and req channel with self._paramsShared(): self.w = self._axiWCls()._m() self.b = Axi4_b() self.errorWrite = Signal()._m() self.driver = AxiWDatapumpIntf() with self._paramsShared(): # fifo for id propagation and frame splitting on axi.w channel wf = self.writeInfoFifo = HandshakedFifo(WFifoIntf) wf.ID_WIDTH.set(self.ID_WIDTH) wf.DEPTH.set(self.MAX_TRANS_OVERLAP) # fifo for propagation of end of frame from axi.b channel bf = self.bInfoFifo = HandshakedFifo(BFifoIntf) bf.DEPTH.set(self.MAX_TRANS_OVERLAP)
def _declr(self): super()._declr() # add clk, rst, axi addr channel and req channel with self._paramsShared(): self.r = Axi4_r() self.driver = AxiRDatapumpIntf() self.errorRead = Signal()._m() f = self.sizeRmFifo = HandshakedFifo(TransEndInfo) f.DEPTH.set(self.MAX_TRANS_OVERLAP)
def connect_r_fifo(self, avalon: AvalonMM, axi: Axi4): # buffer for read data to allow forward dispatch of the read requests # the availability of the space in fifo is checked using r_data_fifo_capacity counter f = HandshakedFifo(Handshaked) f.DEPTH = self.R_DATA_FIFO_DEPTH f.DATA_WIDTH = self.DATA_WIDTH self.r_data_fifo = f # f.dataIn.rd ignored because the request should not be dispatched in the first place f.dataIn.data(avalon.readData) f.dataIn.vld(avalon.readDataValid) sf = self.r_size_fifo wordIndexCntr = self._reg( "wordIndexCntr", HStruct( (sf.dataOut.len._dtype, "len"), (axi.r.id._dtype, "id"), (BIT, "vld") ), def_val={"vld": 0} ) r_out_node = StreamNode([f.dataOut], [axi.r]) r_out_node.sync(wordIndexCntr.vld) # load word index counter if it is invalid else decrement on data transaction newSizeAck = (~wordIndexCntr.vld | (wordIndexCntr.len._eq(0) & r_out_node.ack())) If(newSizeAck, wordIndexCntr.id(sf.dataOut.id), wordIndexCntr.len(sf.dataOut.len), wordIndexCntr.vld(sf.dataOut.vld), ).Elif(r_out_node.ack(), wordIndexCntr.len(wordIndexCntr.len - 1), wordIndexCntr.vld(wordIndexCntr.len != 0), ) sf.dataOut.rd(newSizeAck) axi.r.id(wordIndexCntr.id) axi.r.data(f.dataOut.data) axi.r.resp(RESP_OKAY) axi.r.last(wordIndexCntr.len._eq(0)) return rename_signal(self, r_out_node.ack(), "r_data_ack")
def _declr(self): addClkRstn(self) self.items = Handshaked() self.items.DATA_WIDTH = self.ITEM_WIDTH with self._paramsShared(): self.wDatapump = AxiWDatapumpIntf()._m() self.uploaded = VectSignal(16)._m() self.baseAddr = RegCntrl() self.baseAddr.DATA_WIDTH = self.ADDR_WIDTH self.buff_remain = VectSignal(16)._m() b = HandshakedFifo(Handshaked) b.DATA_WIDTH = self.ITEM_WIDTH b.EXPORT_SIZE = True b.DEPTH = self.BUFF_DEPTH self.buff = b
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 _declr(self): addClkRstn(self) with self._paramsShared(): self.s = self.intfCLs() self.m = Axi4Lite()._m() # *_req_fifo are used to aviod blocking during addr/data/confirmation waiting on axi channels r_f = self.r_req_fifo = HandshakedFifo(HandshakedIdAndLen) w_f = self.w_req_fifo = HandshakedFifo(HandshakedIdAndLen) for f in [w_f, r_f]: f.ID_WIDTH = self.ID_WIDTH f.LEN_WIDTH = self.intfCLs.LEN_WIDTH f.DEPTH = self.MAX_TRANS_OVERLAP with self._paramsShared(): self.out_reg = AxiBuff(Axi4Lite) self.in_reg = AxiBuff(self.intfCLs) self.in_reg.DATA_BUFF_DEPTH =\ self.in_reg.ADDR_BUFF_DEPTH = \ self.out_reg.DATA_BUFF_DEPTH = \ self.out_reg.ADDR_BUFF_DEPTH = 1
def _declr(self): super()._declr() # add clk, rst, axi addr channel and req channel self.errorWrite = Signal()._m() if self.ALIGNAS != 8: self.errorAlignment = Signal()._m() with self._paramsShared(): self.axi.HAS_R = False d = self.driver = AxiWDatapumpIntf() d.ID_WIDTH = 0 d.ID_WIDTH = 0 d.MAX_BYTES = self.MAX_CHUNKS * (self.CHUNK_WIDTH // 8) # fifo for id propagation and frame splitting on axi.w channel wf = self.writeInfoFifo = HandshakedFifo(WFifoIntf) wf.DEPTH = self.MAX_TRANS_OVERLAP wf.SHIFT_OPTIONS = self.getShiftOptions() # fifo for propagation of end of frame from axi.b channel bf = self.bInfoFifo = HandshakedFifo(BFifoIntf) bf.DEPTH = self.MAX_TRANS_OVERLAP
def _declr(self) -> None: addClkRstn(self) with self._paramsShared(): self.s = Axi4() self.m = AvalonMM()._m() # a tmp buffer for sizes of read transactions to generate ax.r.last f = self.r_size_fifo = HandshakedFifo(IdLenHs) f.DEPTH = self.R_DATA_FIFO_DEPTH f.LEN_WIDTH = self.s.LEN_WIDTH f.ID_WIDTH = self.ID_WIDTH if self.MAX_BURST != 2 ** (self.s.LEN_WIDTH + 1): raise NotImplementedError(self.MAX_BURST, (2 ** self.s.LEN_WIDTH + 1))
def propagate_addr(self, m_a, s_a): name_prefix = m_a._name + "_" AL_IN_W = self.ALIGN_BITS_IN AL_OUT_W = self.ALIGN_BITS_OUT ALIG_W = AL_OUT_W - AL_IN_W assert ALIG_W > 0, ALIG_W m_a = AxiSBuilder(self, m_a).buff().end align_fifo = HandshakedFifo(Handshaked) align_fifo.DATA_WIDTH = ALIG_W align_fifo.DEPTH = self.MAX_TRANS_OVERLAP setattr(self, name_prefix + "align_fifo", align_fifo) aligned_addr = Concat(m_a.addr[:AL_OUT_W], Bits(AL_OUT_W).from_py(0)) align_fifo.dataIn.data(m_a.addr[AL_OUT_W:AL_IN_W]) s_a(m_a, exclude={m_a.addr, m_a.valid, m_a.ready}) StreamNode( masters=[m_a], slaves=[s_a, align_fifo.dataIn], ).sync() s_a.addr(aligned_addr, fit=self.ADDR_WIDTH != self.OUT_ADDR_WIDTH) return align_fifo
def _declr(self): super()._declr() # add clk, rst, axi addr channel and req channel self.errorRead = Signal()._m() if self.ALIGNAS != 8: self.errorAlignment = Signal()._m() with self._paramsShared(): self.axi.HAS_W = False d = self.driver = AxiRDatapumpIntf() d.ID_WIDTH = 0 d.MAX_BYTES = self.MAX_CHUNKS * (self.CHUNK_WIDTH // 8) f = self.sizeRmFifo = HandshakedFifo(TransEndInfo) f.ID_WIDTH = 0 f.DEPTH = self.MAX_TRANS_OVERLAP f.SHIFT_OPTIONS = self.getShiftOptions()
def _declr(self): AxiInterconnectCommon._declr(self, has_r=True, has_w=False) masters_for_slave = AxiInterconnectMatrixCrossbar._masters_for_slave( self.MASTERS, len(self.SLAVES)) # fifo for master index for each slave so slave knows # which master did read and where is should send it order_m_index_for_s_data = HObjList() for connected_masters in masters_for_slave: if len(connected_masters) > 1: f = HandshakedFifo(Handshaked) f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.MASTERS)) else: f = None order_m_index_for_s_data.append(f) self.order_m_index_for_s_data = order_m_index_for_s_data # fifo for slave index for each master # so master knows where it should expect the data order_s_index_for_m_data = HObjList() for connected_slaves in self.MASTERS: if len(connected_slaves) > 1: f = HandshakedFifo(Handshaked) f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.SLAVES)) else: f = None order_s_index_for_m_data.append(f) self.order_s_index_for_m_data = order_s_index_for_m_data with self._paramsShared(): self.addr_crossbar = AxiInterconnectMatrixAddrCrossbar( self.intfCls.AR_CLS) with self._paramsShared(): c = self.data_crossbar = AxiInterconnectMatrixCrossbar( self.intfCls.R_CLS) c.INPUT_CNT = len(self.SLAVES) c.OUTPUTS = self.MASTERS
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): HandshakedFifo._declr(self) self.dataIn_discard = Signal() self.dataIn_commit = Signal()
def _impl(self): HandshakedFifo._impl(self, clks=(self.dataIn_clk, self.dataOut_clk))
def setUpClass(cls): u = cls.u = HandshakedFifo(Handshaked) u.DEPTH = cls.ITEMS u.DATA_WIDTH = 64 u.EXPORT_SIZE = True cls.compileSim(u)
def _config(self): HandshakedFifo._config(self) self.IN_FREQ = Param(int(100e6)) self.OUT_FREQ = Param(int(100e6))