示例#1
0
        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
示例#2
0
文件: base.py 项目: mfkiwl/hwtLib
    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)