Source code for hwtLib.amba.axi4_wDatapump

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from hwt.bitmask import mask
from hwt.code import connect, If
from hwt.interfaces.std import Signal, Handshaked, VectSignal, \
    HandshakeSync
from hwt.interfaces.utils import propagateClkRstn
from hwt.synthesizer.param import Param
from hwtLib.amba.axi4 import Axi4_w, Axi4_b, Axi4_addr
from hwtLib.amba.axiDatapumpIntf import AxiWDatapumpIntf
from hwtLib.amba.axi_datapump_base import Axi_datapumpBase
from hwtLib.amba.constants import RESP_OKAY
from hwtLib.handshaked.fifo import HandshakedFifo
from hwtLib.handshaked.streamNode import StreamNode


[docs]class WFifoIntf(Handshaked):
[docs] def _config(self): self.ID_WIDTH = Param(4)
[docs] def _declr(self): self.id = VectSignal(self.ID_WIDTH) HandshakeSync._declr(self)
[docs]class BFifoIntf(Handshaked):
[docs] def _config(self): pass
[docs] def _declr(self): self.isLast = Signal() HandshakeSync._declr(self)
[docs]class Axi_wDatapump(Axi_datapumpBase): """ Axi3/4 to axi write datapump, * splits request to correct request size * simplifies axi communication without lose of performance \n""" + Axi_datapumpBase.__doc__
[docs] def __init__(self, axiAddrCls=Axi4_addr, axiWCls=Axi4_w): self._axiWCls = axiWCls Axi_datapumpBase.__init__(self, axiAddrCls=axiAddrCls)
[docs] def _declr(self): super()._declr() # add clk, rst, axi addr channel and req channel with self._paramsShared(): self.w = self._axiWCls() self.b = Axi4_b() self.errorWrite = Signal() 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)
[docs] def axiAwHandler(self, wErrFlag): req = self.driver.req aw = self.a r = self._reg self.axiAddrDefaults() wInfo = self.writeInfoFifo.dataIn if self.useTransSplitting(): LEN_MAX = mask(aw.len._dtype.bit_length()) lastReqDispatched = r("lastReqDispatched", defVal=1) lenDebth = r("lenDebth", req.len._dtype) addrBackup = r("addrBackup", req.addr._dtype) req_idBackup = r("req_idBackup", req.id._dtype) _id = self._sig("id", aw.id._dtype) requiresSplit = req.len > LEN_MAX requiresDebtSplit = lenDebth > LEN_MAX If(lastReqDispatched, _id(req.id), aw.addr(req.addr), If(requiresSplit, aw.len(LEN_MAX) ).Else( connect(req.len, aw.len, fit=True), ), req_idBackup(req.id), addrBackup(req.addr + self.getBurstAddrOffset()), lenDebth(req.len - (LEN_MAX + 1)), If(wInfo.rd & aw.ready & req.vld, If(requiresSplit, lastReqDispatched(0) ).Else( lastReqDispatched(1) ) ), StreamNode(masters=[req], slaves=[aw, wInfo], extraConds={aw: ~wErrFlag}).sync(), ).Else( _id(req_idBackup), aw.addr(addrBackup), If(requiresDebtSplit, aw.len(LEN_MAX) ).Else( connect(lenDebth, aw.len, fit=True) ), StreamNode(slaves=[aw, wInfo], extraConds={aw:~wErrFlag}).sync(), req.rd(0), If(StreamNode(slaves=[wInfo, aw]).ack(), addrBackup(addrBackup + self.getBurstAddrOffset()), lenDebth(lenDebth - (LEN_MAX+1)), If(lenDebth <= LEN_MAX, lastReqDispatched(1) ) ) ) aw.id(_id) wInfo.id(_id) else: aw.id(req.id) wInfo.id(req.id) aw.addr(req.addr) connect(req.len, aw.len, fit=True) StreamNode(masters=[req], slaves=[aw, wInfo]).sync()
[docs] def axiWHandler(self, wErrFlag): w = self.w wIn = self.driver.w wInfo = self.writeInfoFifo.dataOut bInfo = self.bInfoFifo.dataIn if hasattr(w, "id"): # AXI3 has, AXI4 does not w.id(wInfo.id) w.data(wIn.data) w.strb(wIn.strb) if self.useTransSplitting(): wordCntr = self._reg("wWordCntr", self.a.len._dtype, 0) doSplit = wordCntr._eq(self.getAxiLenMax()) | wIn.last If(StreamNode([wInfo, wIn], [bInfo, w]).ack(), If(doSplit, wordCntr(0) ).Else( wordCntr(wordCntr + 1) ) ) else: doSplit = wIn.last extraConds = {wInfo: doSplit, bInfo: doSplit, w: ~wErrFlag} w.last(doSplit) bInfo.isLast(wIn.last) StreamNode(masters=[wIn, wInfo], slaves=[bInfo, w], extraConds=extraConds ).sync()
[docs] def axiBHandler(self): wErrFlag = self._reg("wErrFlag", defVal=0) b = self.b ack = self.driver.ack lastFlags = self.bInfoFifo.dataOut If(lastFlags.vld & ack.rd & b.valid & (b.resp != RESP_OKAY), wErrFlag(1) ) self.errorWrite(wErrFlag) ack.data(b.id) StreamNode(masters=[b, lastFlags], slaves=[ack], extraConds={ ack: lastFlags.isLast }).sync() return wErrFlag
[docs] def _impl(self): propagateClkRstn(self) wErrFlag = self.axiBHandler() self.axiAwHandler(wErrFlag) self.axiWHandler(wErrFlag)
if __name__ == "__main__": from hwt.synthesizer.utils import toRtl u = Axi_wDatapump() print(toRtl(u))