Source code for hwtLib.structManipulators.structReader

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

from math import ceil

from hwt.code import StaticForEach
from hwt.hdl.frameTmpl import FrameTmpl
from hwt.hdl.transTmpl import TransTmpl
from hwt.hdl.types.struct import HStruct
from hwt.interfaces.std import Handshaked, Signal
from hwt.interfaces.structIntf import StructIntf
from hwt.interfaces.utils import propagateClkRstn, addClkRstn
from hwt.synthesizer.param import Param
from hwt.synthesizer.unit import Unit
from hwtLib.abstract.template_configured import TemplateConfigured
from hwtLib.amba.axis_comp.frame_parser import AxiS_frameParser
from hwtLib.amba.datapump.intf import AxiRDatapumpIntf, AddrSizeHs
from hwtLib.handshaked.builder import HsBuilder
from hwtLib.handshaked.streamNode import StreamNode


[docs]class StructReader(AxiS_frameParser): """ This unit downloads required structure fields over rDatapump interface from address specified by get interface :ivar ~.ID: Param, id for transactions on bus :ivar ~.READ_ACK: Param, if true ready on "get" will be set only when component is in idle (if false "get" is regular handshaked interface) :ivar ~.SHARED_READY: Param, if this is true field interfaces will be of type VldSynced and single ready signal will be used for all else every interface will be instance of Handshaked and it will have it's own ready(rd) signal :attention: interfaces of field will not send data in same time .. figure:: ./_static/StructReader.png :note: names in the picture are just illustrative .. hwt-autodoc:: _example_StructReader """
[docs] def __init__(self, structT, tmpl=None, frames=None): """ :param structT: instance of HStruct which specifies data format to download :param tmpl: instance of TransTmpl for this structT :param frames: list of FrameTmpl instances for this tmpl :note: if tmpl and frames are None they are resolved from structT parseTemplate :note: this unit can parse sequence of frames, if they are specified by "frames" :attention: interfaces for each field in struct will be dynamically created :attention: structT can not contain fields with variable size like HStream """ Unit.__init__(self) assert isinstance(structT, HStruct) TemplateConfigured.__init__(self, structT, tmpl=tmpl, frames=frames)
def _config(self): self.ID = Param(0) AxiRDatapumpIntf._config(self) self.USE_STRB = False self.READ_ACK = Param(False) self.SHARED_READY = Param(False)
[docs] def maxWordIndex(self): return max(f.endBitAddr - 1 for f in self._frames) // self.DATA_WIDTH
[docs] def maxBytesInTransaction(self): return ceil(max( [f.parts[-1].endOfPart - f.startBitAddr for f in self._frames] ) / 8)
[docs] def parseTemplate(self): if self._tmpl is None: self._tmpl = TransTmpl(self._structT) if self._frames is None: DW = self.DATA_WIDTH frames = FrameTmpl.framesFromTransTmpl( self._tmpl, DW, trimPaddingWordsOnStart=True, trimPaddingWordsOnEnd=True) self._frames = list(frames)
def _declr(self): addClkRstn(self) self.dataOut = StructIntf(self._structT, tuple(), self._mkFieldIntf)._m() g = self.get = Handshaked() # data signal is addr of structure to download g.DATA_WIDTH = self.ADDR_WIDTH self.parseTemplate() with self._paramsShared(): # interface for communication with datapump self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_BYTES = self.maxBytesInTransaction() with self._paramsShared(exclude=({"ID_WIDTH"}, set())): self.parser = AxiS_frameParser(self._structT, tmpl=self._tmpl, frames=self._frames) self.parser.SYNCHRONIZE_BY_LAST = False if self.SHARED_READY: self.ready = Signal()
[docs] def driveReqRem(self, req: AddrSizeHs, MAX_BITS: int): return req.rem(ceil((MAX_BITS % self.DATA_WIDTH) / 8))
def _impl(self): propagateClkRstn(self) req = self.rDatapump.req if self.READ_ACK: get = self.get else: get = HsBuilder(self, self.get).buff().end def propagateRequest(frame, indx): isLastFrame = indx == len(self._frames) - 1 s = [ req.addr(get.data + frame.startBitAddr // 8), req.len(frame.getWordCnt() - 1), self.driveReqRem(req, frame.parts[-1].endOfPart - frame.startBitAddr), req.vld(get.vld), get.rd(req.rd if isLastFrame else 0) ] ack = StreamNode(masters=[get], slaves=[self.rDatapump.req]).ack() return s, ack StaticForEach(self, self._frames, propagateRequest) r = self.rDatapump.r data_sig_to_exclude = [] if self.ID_WIDTH: req.id(self.ID) if hasattr(r, "id"): data_sig_to_exclude.append(r.id) if hasattr(r, "strb"): data_sig_to_exclude.append(r.strb) self.parser.dataIn(r, exclude=data_sig_to_exclude) for _, field in self._tmpl.walkFlatten(): p = field.getFieldPath() myIntf = self.dataOut._fieldsToInterfaces[p] parserIntf = self.parser.dataOut._fieldsToInterfaces[p] myIntf(parserIntf)
[docs]def _example_StructReader(): from hwtLib.types.ctypes import uint16_t, uint32_t, uint64_t s = HStruct( (uint64_t, "item0"), # tuples (type, name) where type has to be instance of Bits type (uint64_t, None), # name = None means this field will be ignored (uint64_t, "item1"), (uint64_t, None), (uint16_t, "item2"), (uint16_t, "item3"), (uint32_t, "item4"), (uint32_t, None), (uint64_t, "item5"), # this word is split on two bus words (uint32_t, None), (uint64_t, None), (uint64_t, None), (uint64_t, None), (uint64_t, "item6"), (uint64_t, "item7"), ) u = StructReader(s) return u
if __name__ == "__main__": from hwt.synthesizer.utils import to_rtl_str u = _example_StructReader() print(to_rtl_str(u))