예제 #1
0
    def _parseTemplate(self):
        self.WORD_ADDR_STEP = self._getWordAddrStep()
        self.ADDR_STEP = self._getAddrStep()

        AW = int(self.ADDR_WIDTH)
        SUGGESTED_AW = self._suggestedAddrWidth()
        assert SUGGESTED_AW <= AW, ("Address width too small", SUGGESTED_AW,
                                    AW)
        tmpl = TransTmpl(self.STRUCT_TEMPLATE)

        self._ADDR_MIN = TransTmpl_get_min_addr(tmpl) // self.ADDR_STEP
        self._ADDR_MAX = ceil(TransTmpl_get_max_addr(tmpl) / self.ADDR_STEP)

        # resolve addresses for bram port mapped fields
        self._bramPortMapped = []

        def shouldEnterFn(trans_tmpl: TransTmpl):
            p = trans_tmpl.getFieldPath()
            intf = self.decoded._fieldsToInterfaces[p]
            if isinstance(intf,
                          (StructIntf, UnionSink, UnionSource, HObjList)):
                shouldEnter = True
                shouldUse = False
            elif isinstance(intf, BramPort_withoutClk):
                shouldEnter = False
                shouldUse = True
            else:
                shouldEnter = False
                shouldUse = False

            return shouldEnter, shouldUse

        for ((base, end), t) in tmpl.walkFlatten(shouldEnterFn=shouldEnterFn):
            self._bramPortMapped.append(((base, end), t))

        # resolve exact addresses for directly mapped field parts
        directly_mapped_fields = {}
        for p, out in self.decoded._fieldsToInterfaces.items():
            if not isinstance(out, (RegCntrl, Signal)):
                continue
            a = directly_mapped_fields
            for _p in p:
                if isinstance(_p, int) and _p != 0:
                    # we need spec only for first array item
                    break
                a = a.setdefault(_p, {})

        dmw = self._directly_mapped_words = []
        if directly_mapped_fields:
            DW = self.DATA_WIDTH
            directly_mapped_t = HdlType_select(self.STRUCT_TEMPLATE,
                                               directly_mapped_fields)
            tmpl = TransTmpl(directly_mapped_t)

            frames = list(
                FrameTmpl.framesFromTransTmpl(
                    tmpl,
                    DW,
                    maxPaddingWords=0,
                    trimPaddingWordsOnStart=True,
                    trimPaddingWordsOnEnd=True,
                ))

            for f in frames:
                f_word_offset = f.startBitAddr // DW
                for (w_i, items) in f.walkWords(showPadding=True):
                    dmw.append((w_i + f_word_offset, items))
예제 #2
0
class StructReader(AxiS_frameParser):
    """
    This unit downloads required structure fields over rDatapump
    interface from address specified by get interface

    :ivar MAX_DUMMY_WORDS: Param, specifies maximum dummy bus words between fields
        if there is more of ignored space transaction will be split to
    :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

    .. aafig::
            get (base addr)          +---------+
         +----------------    +------> field0  |
                         |    |      +---------+
            bus req   +--v---+-+
         <------------+         |    +---------+
                      | reader  +----> field1  |
         +------------>         |    +---------+
            bus data  +-------+-+
                              |      +---------+
                              +------> field2  |
                                     +---------+

    :note: names in the picture are just illustrative

    .. hwt-schematic:: _example_StructReader
    """
    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)
        self._structT = structT
        if tmpl is not None:
            assert frames is not None, "tmpl and frames can be used only together"
        else:
            assert frames is None, "tmpl and frames can be used only together"

        self._tmpl = tmpl
        self._frames = frames

    def _config(self):
        self.ID = Param(0)
        AxiRDatapumpIntf._config(self)
        self.USE_STRB.set(False)
        self.READ_ACK = Param(False)
        self.SHARED_READY = Param(False)

    def maxWordIndex(self):
        return max(map(lambda f: f.endBitAddr - 1, self._frames)) // int(self.DATA_WIDTH)

    def parseTemplate(self):
        if self._tmpl is None:
            self._tmpl = TransTmpl(self._structT)
        if self._frames is None:
            DW = int(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,
                                  self._mkFieldIntf)._m()

        g = self.get = Handshaked()  # data signal is addr of structure to download
        g._replaceParam(g.DATA_WIDTH, self.ADDR_WIDTH)
        self.parseTemplate()

        with self._paramsShared():
            # interface for communication with datapump
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(self.maxWordIndex() + 1)

        with self._paramsShared(exclude={self.ID_WIDTH}):
            self.parser = AxiS_frameParser(self._structT,
                                           tmpl=self._tmpl,
                                           frames=self._frames)
            self.parser.SYNCHRONIZE_BY_LAST.set(False)

        if self.SHARED_READY:
            self.ready = Signal()

    def _impl(self):
        propagateClkRstn(self)
        req = self.rDatapump.req

        
        req.rem(0)
        if self.READ_ACK:
            get = self.get
        else:
            get = HsBuilder(self, self.get).buff().end

        def f(frame, indx):
            s = [req.addr(get.data + frame.startBitAddr // 8),
                 req.len(frame.getWordCnt() - 1),
                 req.vld(get.vld)
                 ]
            isLastFrame = indx == len(self._frames) - 1
            if isLastFrame:
                rd = req.rd
            else:
                rd = 0
            s.append(get.rd(rd))

            ack = StreamNode(masters=[get], slaves=[self.rDatapump.req]).ack()
            return s, ack

        StaticForEach(self, self._frames, f)

        r = self.rDatapump.r
        data_sig_to_exclude = []
        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)

        connect(r, self.parser.dataIn, exclude=data_sig_to_exclude)

        for _, field in self._tmpl.walkFlatten():
            myIntf = self.dataOut._fieldsToInterfaces[field.origin]
            parserIntf = self.parser.dataOut._fieldsToInterfaces[field.origin]
            myIntf(parserIntf)
예제 #3
0
class StructReader(AxiS_frameParser):
    """
    This unit downloads required structure fields over rDatapump
    interface from address specified by get interface

    :ivar MAX_DUMMY_WORDS: Param, specifies maximum dummy bus words between fields
        if there is more of ignored space transaction will be split to
    :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

    .. aafig::
            get (base addr)          +---------+
         +----------------    +------> field0  |
                         |    |      +---------+
            bus req   +--v---+-+
         <------------+         |    +---------+
                      | reader  +----> field1  |
         +------------>         |    +---------+
            bus data  +-------+-+
                              |      +---------+
                              +------> field2  |
                                     +---------+

    :note: names in the picture are just illustrative

    .. hwt-schematic:: _example_StructReader
    """
    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)
        self._structT = structT
        if tmpl is not None:
            assert frames is not None, "tmpl and frames can be used only together"
        else:
            assert frames is None, "tmpl and frames can be used only together"

        self._tmpl = tmpl
        self._frames = frames

    def _config(self):
        self.ID = Param(0)
        AxiRDatapumpIntf._config(self)
        self.USE_STRB.set(False)
        self.READ_ACK = Param(False)
        self.SHARED_READY = Param(False)

    def maxWordIndex(self):
        return max(map(lambda f: f.endBitAddr - 1, self._frames)) // int(
            self.DATA_WIDTH)

    def parseTemplate(self):
        if self._tmpl is None:
            self._tmpl = TransTmpl(self._structT)
        if self._frames is None:
            DW = int(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, self._mkFieldIntf)._m()

        g = self.get = Handshaked(
        )  # data signal is addr of structure to download
        g._replaceParam(g.DATA_WIDTH, self.ADDR_WIDTH)
        self.parseTemplate()

        with self._paramsShared():
            # interface for communication with datapump
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(self.maxWordIndex() + 1)

        with self._paramsShared(exclude={self.ID_WIDTH}):
            self.parser = AxiS_frameParser(self._structT,
                                           tmpl=self._tmpl,
                                           frames=self._frames)
            self.parser.SYNCHRONIZE_BY_LAST.set(False)

        if self.SHARED_READY:
            self.ready = Signal()

    def _impl(self):
        propagateClkRstn(self)
        req = self.rDatapump.req

        req.rem(0)
        if self.READ_ACK:
            get = self.get
        else:
            get = HsBuilder(self, self.get).buff().end

        def f(frame, indx):
            s = [
                req.addr(get.data + frame.startBitAddr // 8),
                req.len(frame.getWordCnt() - 1),
                req.vld(get.vld)
            ]
            isLastFrame = indx == len(self._frames) - 1
            if isLastFrame:
                rd = req.rd
            else:
                rd = 0
            s.append(get.rd(rd))

            ack = StreamNode(masters=[get], slaves=[self.rDatapump.req]).ack()
            return s, ack

        StaticForEach(self, self._frames, f)

        r = self.rDatapump.r
        data_sig_to_exclude = []
        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)

        connect(r, self.parser.dataIn, exclude=data_sig_to_exclude)

        for _, field in self._tmpl.walkFlatten():
            myIntf = self.dataOut._fieldsToInterfaces[field.origin]
            parserIntf = self.parser.dataOut._fieldsToInterfaces[field.origin]
            myIntf(parserIntf)
예제 #4
0
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

    .. aafig::

            get (base addr)          +---------+
         +----------------   +------>| field0  |
                         |   |       +---------+
                         v   |
            bus req   +------+--+
         <------------+         |    +---------+
                      | reader  +--->| field1  |
         +----------->|         |    +---------+
            bus data  +-------+-+
                              |      +---------+
                              +----->| field2  |
                                     +---------+

    :note: names in the picture are just illustrative

    .. hwt-autodoc:: _example_StructReader
    """

    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)

    def maxWordIndex(self):
        return max(f.endBitAddr - 1 for f in self._frames) // self.DATA_WIDTH

    def maxBytesInTransaction(self):
        return ceil(max(
                    [f.parts[-1].endOfPart - f.startBitAddr for f in self._frames]
                    ) / 8)

    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()

    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)