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=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 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 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