def connected_reg(name, input_=None, inputEn=None, fit=False): if input_ is not None: assert inputEn is not None port = getattr(ep, name) reg = self._reg(name, port.din._dtype) e = If(port.dout.vld, connect(port.dout.data, reg, fit=fit)) if input_ is not None: e.Elif(inputEn, connect(input_, reg, fit=fit)) port.din(reg) return reg
def addrHandler(self, req: AddrSizeHs, axiA: Union[Axi3_addr, Axi3Lite_addr, Axi4_addr, Axi4Lite_addr], transInfo: HandshakeSync, errFlag: RtlSignal): """ Propagate read/write requests from req to axi address channel and store extra info using transInfo interface. """ r, s = self._reg, self._sig self.axiAddrDefaults(axiA) if self.ID_WIDTH: axiA.id(self.ID_VAL) alignmentError = self.hasAlignmentError(req.addr) HAS_LEN = self._axiCls.LEN_WIDTH > 0 if self.useTransSplitting(): # if axi len is smaller we have to use transaction splitting # that means we need to split requests from driver.req to multiple axi requests transPartPending = r("transPartPending", def_val=0) addrTmp = r("addrTmp", req.addr._dtype) dispatchNode = StreamNode([ req, ], [axiA, transInfo], skipWhen={req: transPartPending.next}, extraConds={ req: ~transPartPending.next, axiA: req.vld & ~alignmentError, transInfo: req.vld & ~alignmentError }) dispatchNode.sync(~errFlag) ack = s("ar_ack") ack(dispatchNode.ack() & ~errFlag) LEN_MAX = max(mask(self._axiCls.LEN_WIDTH), 0) reqLen = s("reqLen", self.getLen_t()) reqLenRemaining = r("reqLenRemaining", reqLen._dtype) If(reqLen > LEN_MAX, *([axiA.len(LEN_MAX)] if HAS_LEN else []), self.storeTransInfo(transInfo, 0)).Else( # connect only lower bits of len *([axiA.len(reqLen, fit=True)] if HAS_LEN else []), self.storeTransInfo(transInfo, 1)) # dispatchNode not used because of combinational loop If( StreamNode([ req, ], [axiA, transInfo]).ack() & ~errFlag, If(reqLen > LEN_MAX, reqLenRemaining(reqLen - (LEN_MAX + 1)), transPartPending(1)).Else(transPartPending(0))) reqLenSwitch = If( ~req.vld, reqLen(None), ) if not self.isAlwaysAligned(): crossesWordBoundary = self.isCrossingWordBoundary( req.addr, req.rem) reqLenSwitch.Elif( ~self.addrIsAligned(req.addr) & crossesWordBoundary, reqLen(fitTo(req.len, reqLen, shrink=False) + 1), ) reqLenSwitch.Else(reqLen(fitTo(req.len, reqLen, shrink=False)), ) ADDR_STEP = self.getBurstAddrOffset() If( transPartPending, axiA.addr(self.addrAlign(addrTmp)), If(ack, addrTmp(addrTmp + ADDR_STEP)), reqLen(reqLenRemaining), ).Else( axiA.addr(self.addrAlign(req.addr)), addrTmp(req.addr + ADDR_STEP), reqLenSwitch, ) else: # if axi len is wider we can directly translate requests to axi axiA.addr(self.addrAlign(req.addr)) if req.MAX_LEN > 0: lenDrive = axiA.len(fitTo(req.len, axiA.len, shrink=False)) if not self.isAlwaysAligned(): crossesWordBoundary = self.isCrossingWordBoundary( req.addr, req.rem) If( ~self.addrIsAligned(req.addr) & crossesWordBoundary, axiA.len(fitTo(req.len, axiA.len) + 1), ).Else(lenDrive, ) else: if HAS_LEN: axiA.len(0) self.storeTransInfo(transInfo, 1) StreamNode(masters=[req], slaves=[axiA, transInfo], extraConds={ axiA: ~alignmentError, transInfo: ~alignmentError, }).sync(~errFlag)