コード例 #1
0
ファイル: matrixW.py プロジェクト: mfkiwl/hwtLib
    def _impl(self):
        propagateClkRstn(self)
        addr_crossbar = self.addr_crossbar
        data_crossbar = self.data_crossbar
        b_crossbar = self.b_crossbar

        master_addr_channels = HObjList([m.aw for m in self.s])
        slave_addr_channels = HObjList([s.aw for s in self.m])
        addr_crossbar.s(master_addr_channels)
        slave_addr_channels(addr_crossbar.m)

        master_w_channels = HObjList([m.w for m in self.s])
        data_crossbar.dataIn(master_w_channels)
        slave_w_channels = HObjList([s.w for s in self.m])
        slave_w_channels(data_crossbar.dataOut)

        master_b_channels = HObjList([m.b for m in self.s])
        master_b_channels(b_crossbar.dataOut)
        slave_b_channels = HObjList([s.b for s in self.m])
        b_crossbar.dataIn(slave_b_channels)

        for addr_crossbar_s_index_out, f_w, f_b in zip(
                addr_crossbar.order_s_index_for_m_data_out,
                self.order_s_index_for_m_data, self.order_s_index_for_m_b):
            if f_w is None:
                assert f_b is None
                continue
            HsBuilder(self, addr_crossbar_s_index_out)\
                .split_copy_to(f_w.dataIn, f_b.dataIn)

        for f_w, f_b, data_dout_for_din, b_din_for_dout in zip(
                self.order_s_index_for_m_data, self.order_s_index_for_m_b,
                data_crossbar.order_dout_index_for_din_in,
                b_crossbar.order_din_index_for_dout_in):
            if f_w is None:
                assert f_b is None
                continue
            data_dout_for_din(f_w.dataOut)
            b_din_for_dout(f_b.dataOut)

        for addr_crossbar_m_index_out, f_w, f_b in zip(
                addr_crossbar.order_m_index_for_s_data_out,
                self.order_m_index_for_s_data, self.order_m_index_for_s_b):
            if f_w is None:
                assert f_b is None
                assert addr_crossbar_m_index_out is None
                continue
            HsBuilder(self, addr_crossbar_m_index_out)\
                .split_copy_to(f_w.dataIn, f_b.dataIn)

        for f_w, f_b, data_din_for_dout, b_dout_for_din in zip(
                self.order_m_index_for_s_data, self.order_m_index_for_s_b,
                data_crossbar.order_din_index_for_dout_in,
                b_crossbar.order_dout_index_for_din_in):
            if f_w is None:
                assert f_b is None
                assert data_din_for_dout is None
                continue
            data_din_for_dout(f_w.dataOut)
            b_dout_for_din(f_b.dataOut)
コード例 #2
0
    def _impl(self):
        # instanciate builder
        b = HsBuilder(self, self.a)

        # HsBuilder is derived from AbstractStreamBuilder and implements
        # it can:
        # * instantiate and connect:
        #    * fifos, registers, delays
        #    * frame builders, frame parsers
        #    * data width resizers
        #    * various stream join/split components
        #    * clock domain crossing

        # for most of stream interfaces like AvalonST, LocalLink ...
        # there is builder with same program interface

        # instanciate handshaked register (default buff items=1)
        # and connect it to end (which is self.a)
        b.buff()

        # instantiate fifo with 16 items and connect it to output of register
        # from previous step
        b.buff(items=16)

        # instantiate register with latency=2 and delay=1 and connect it
        # to output of fifo from previous step
        b.buff(latency=2, delay=1)

        # b.end is now output of register from previous step,
        # connect it to uptput
        self.b(b.end)
コード例 #3
0
    def _impl(self):
        dma = AxiVirtualDma(self.axi_m, alignas=self.ALIGNAS)
        rxGet, rxR = dma.read(frameHeader)
        txSet, txW, wAck = dma.write(frameHeader)
        dma.build()

        # send address to an engine which reads and writes the packet header
        HsBuilder(self, self.packetAddr)\
            .split_copy_to(rxGet, txSet)

        # ignore write ack
        wAck.rd(1)

        def withFifo(interface):
            return HsBuilder(self, interface)\
                      .buff(items=4)\
                      .end

        # swap dst/src in IP and Ethernet MAC, use fifo to compensate for
        # a diferent arrival times of the data
        txW.eth.dst(withFifo(rxR.eth.src))
        txW.eth.src(withFifo(rxR.eth.dst))

        txW.ipv4.dst(withFifo(rxR.ipv4.src))
        txW.ipv4.src(withFifo(rxR.ipv4.dst))

        propagateClkRstn(self)
コード例 #4
0
ファイル: addr_data_hs_to_Axi.py プロジェクト: mfkiwl/hwtLib
    def connect_r(self, s_r: RamHsR, axi: Axi4, r_cntr: RtlSignal,
                  CNTR_MAX: int, in_axi_t: Union[HStruct, HUnion]):
        self.addr_defaults(axi.ar)

        # rm id from r channel as it is not currently supported in frame parser
        r_tmp = AxiStream()
        r_tmp.USE_STRB = False
        r_tmp.DATA_WIDTH = axi.r.DATA_WIDTH
        self.r_tmp = r_tmp
        r_tmp(axi.r, exclude=(
            axi.r.id,
            axi.r.resp,
        ))
        r_data = AxiSBuilder(self, r_tmp)\
            .parse(in_axi_t).data

        if self.data_words_in_axi_word <= 1:
            self.connect_addr(s_r.addr.data, axi.ar.addr)

            s_r.data.data(r_data.data[s_r.DATA_WIDTH:])

            ar_sn = StreamNode([s_r.addr], [axi.ar])
            r_sn = StreamNode([r_data], [s_r.data])

        else:
            addr, sub_addr = self.split_subaddr(s_r.addr.data)
            self.connect_addr(addr, axi.ar.addr)

            sel = HsBuilder(self, r_data._select, master_to_slave=False)\
                .buff(self.MAX_TRANS_OVERLAP).end
            sel.data(sub_addr)

            data_items = [
                getattr(r_data, f"data{i:d}").data
                for i in range(self.data_words_in_axi_word)
            ]
            r_data_selected = HsBuilder.join_prioritized(self, data_items).end
            s_r.data.data(r_data_selected.data)

            ar_sn = StreamNode([s_r.addr], [axi.ar, sel])
            r_sn = StreamNode([r_data_selected], [s_r.data])

        ar_sn.sync(r_cntr != CNTR_MAX)
        r_sn.sync()
        r_en = r_sn.ack()
        If(axi.ar.ready & axi.ar.valid,
           If(~r_en, r_cntr(r_cntr + 1))).Elif(r_en, r_cntr(r_cntr - 1))
コード例 #5
0
ファイル: structWriter.py プロジェクト: jesseclin/hwtLib
    def _impl(self):
        req = self.wDatapump.req
        w = self.wDatapump.w
        ack = self.wDatapump.ack

        # multi frame
        ackPropageteInfo = HandshakedFifo(Handshaked)
        ackPropageteInfo.DATA_WIDTH.set(1)
        ackPropageteInfo.DEPTH.set(self.MAX_OVERLAP)
        self.ackPropageteInfo = ackPropageteInfo
        propagateClkRstn(self)

        if self.WRITE_ACK:
            _set = self.set
        else:
            _set = HsBuilder(self, self.set).buff().end

        req.id(self.ID)
        req.rem(0)

        def propagateRequests(frame, indx):
            ack = StreamNode(slaves=[req, ackPropageteInfo.dataIn]).ack()
            statements = [req.addr(_set.data + frame.startBitAddr // 8),
                          req.len(frame.getWordCnt() - 1),
                          StreamNode(slaves=[req, ackPropageteInfo.dataIn],
                                     ).sync(_set.vld)
                          ]
            if indx != 0:
                prop = SKIP
            else:
                prop = PROPAGATE

            statements.append(ackPropageteInfo.dataIn.data(prop))

            isLastFrame = indx == len(self._frames) - 1
            if isLastFrame:
                statements.append(_set.rd(ack))
            else:
                statements.append(_set.rd(0))

            return statements, ack & _set.vld

        StaticForEach(self, self._frames, propagateRequests)

        # connect write channel
        w(self.frameAssember.dataOut)

        # propagate ack
        StreamNode(masters=[ack, ackPropageteInfo.dataOut],
                   slaves=[self.writeAck],
                   skipWhen={
                             self.writeAck: ackPropageteInfo.dataOut.data._eq(PROPAGATE)
                            }).sync()

        # connect fields to assembler
        for _, transTmpl in self._tmpl.walkFlatten():
            f = transTmpl.origin
            intf = self.frameAssember.dataIn._fieldsToInterfaces[f]
            intf(self.dataIn._fieldsToInterfaces[f])
コード例 #6
0
ファイル: structWriter.py プロジェクト: mfkiwl/hwtLib
    def _impl(self):
        req = self.wDatapump.req
        w = self.wDatapump.w
        ack = self.wDatapump.ack

        # multi frame
        if self.MAX_OVERLAP > 1:
            ackPropageteInfo = HandshakedFifo(Handshaked)
            ackPropageteInfo.DEPTH = self.MAX_OVERLAP
        else:
            ackPropageteInfo = HandshakedReg(Handshaked)
        ackPropageteInfo.DATA_WIDTH = 1
        self.ackPropageteInfo = ackPropageteInfo

        if self.WRITE_ACK:
            _set = self.set
        else:
            _set = HsBuilder(self, self.set).buff().end

        if self.ID_WIDTH:
            req.id(self.ID)

        def propagateRequest(frame, indx):
            inNode = StreamNode(slaves=[req, ackPropageteInfo.dataIn])
            ack = inNode.ack()
            isLastFrame = indx == len(self._frames) - 1
            statements = [
                req.addr(_set.data + frame.startBitAddr // 8),
                req.len(frame.getWordCnt() - 1),
                self.driveReqRem(
                    req, frame.parts[-1].endOfPart - frame.startBitAddr),
                ackPropageteInfo.dataIn.data(SKIP if indx != 0 else PROPAGATE),
                inNode.sync(_set.vld),
                _set.rd(ack if isLastFrame else 0),
            ]

            return statements, ack & _set.vld

        StaticForEach(self, self._frames, propagateRequest)

        # connect write channel
        w(self.frameAssember.dataOut)

        # propagate ack
        StreamNode(masters=[ack, ackPropageteInfo.dataOut],
                   slaves=[self.writeAck],
                   skipWhen={
                       self.writeAck:
                       ackPropageteInfo.dataOut.data._eq(PROPAGATE)
                   }).sync()

        # connect fields to assembler
        for _, transTmpl in self._tmpl.walkFlatten():
            f = transTmpl.getFieldPath()
            intf = self.frameAssember.dataIn._fieldsToInterfaces[f]
            intf(self.dataIn._fieldsToInterfaces[f])

        propagateClkRstn(self)
コード例 #7
0
    def _impl(self):
        # instanciate builder
        b = HsBuilder(self, self.a)

        # HsBuilder is derived from AbstractStreamBuilder and implements
        # it can:
        # * instantiate and connect:
        #    * fifos, registers, delays
        #    * frame builders, frame parsers
        #    * data width resizers
        #    * various stream join/split components
        #    * clock domain crossing

        # for most of stream interfaces like AvalonST, LocalLink ...
        # there is builder with same program interface

        # instanciate handshaked register (default buff items=1)
        # and connect it to end (which is self.a)
        b.buff()

        # instantiate fifo with 16 items and connect it to output of register
        # from previous step
        b.buff(items=16)

        # instantiate register with latency=2 and delay=1 and connect it
        # to output of fifo from previous step
        b.buff(latency=2, delay=1)

        # b.end is now output of register from previous step,
        # connect it to uptput
        self.b(b.end)
コード例 #8
0
    def _impl(self):
        """
        Read operation:

        * Use index to lookup in tag memory
        * if tag matches return cacheline else dispatch read request
          (the transaction is dispatched with original id, uppon data receive the transaction
          is passed to master without any synchronisation with the cache )

        Write operation:

        * Use index to lookup in tag memory
        * If tag matches and the cacheline is not beeing replaced update the data in data array.
        * If tag is not found in corresponding set select a victim and read it from data array, flush it
          and write back cacheline to array and update tag
        """
        # transaction type usind in data array memory access pipeline

        data_array_r, data_array_w = self.data_array.port
        ar_tagRes, aw_tagRes = self.tag_array.lookupRes
        with self._paramsShared():
            data_arr_read = self.data_arr_read = Axi4_r()
            data_arr_read_req = IndexWayHs()
            data_arr_read_req.INDEX_WIDTH = self.INDEX_W
            self.data_arr_read_req = data_arr_read_req

        self.connect_tag_lookup()

        # addd a register with backup register for poential overflow
        # we need this as we need to check if we can store data in advance.
        # this is because we need a higher priority for flushing
        # in order to avoid deadlock.
        _data_arr_read = AxiSBuilder(self, data_arr_read)\
            .buff(1, latency=(1, 2))\
            .end
        _data_arr_read_req = HsBuilder(self, data_arr_read_req)\
            .buff(1, latency=(1, 2))\
            .end

        self.read_handler(self.lru_array.incr[0], ar_tagRes, data_arr_read_req,
                          _data_arr_read)

        self.data_array_io(
            self.lru_array.incr[1],
            aw_tagRes,
            self.lru_array.victim_req,
            self.lru_array.victim_data,
            _data_arr_read_req,
            data_arr_read,
            data_array_r,
            data_array_w,
            self.tag_array.update[0],
        )

        propagateClkRstn(self)
コード例 #9
0
    def reqHandler(self, dpReq, orderFifoIn):
        # join with roundrobin on requests form drivers and selected index is stored into orderFifo

        # because it is just proxy
        driversReq = list(map(lambda d: d.req, self.drivers))
        b = HsBuilder.join_fair(self, driversReq, exportSelected=True)
        req = b.end
        reqJoin = b.lastComp

        StreamNode(masters=[req], slaves=[dpReq, orderFifoIn]).sync()
        connect(req, dpReq, exclude=[dpReq.vld, dpReq.rd])
        orderFifoIn.data(oneHotToBin(self, reqJoin.selectedOneHot.data))
コード例 #10
0
    def _impl(self):
        self.tables_tmp = HObjList([
            HashTableIntf()._updateParamsFrom(t.io) for t in self.table_cores
        ])

        for t_io, t in zip(self.tables_tmp, self.table_cores):
            t.io(t_io, exclude={t.io.lookupRes})
            t_io.lookupRes(
                HsBuilder(self, t.io.lookupRes).buff(latency=(1, 2)).end)

        self.tables = list(self.tables_tmp)
        CuckooHashTable._impl(self)
コード例 #11
0
ファイル: driver.py プロジェクト: mfkiwl/hwtLib
    def _impl(self):
        """
        * read on 'en' faling edge, write on 'en' rising edge
        * 'en' max frequency = LCD_FREQ / 10
        * rs has to be set at least 1 clk (LCD_FREQ) before rising edge of 'en'
        """
        LCD_DW = self.LCD_DATA_WIDTH
        assert LCD_DW in (4, 8), LCD_DW
        cmd_timer_rst = self._sig("cmd_timer_rst")
        HALF_LCD_PERIOD = ceil(self.FREQ / (self.LCD_FREQ * 2))
        LCD_CLK_PER = 2 * HALF_LCD_PERIOD
        lcd_clk_en, = ClkBuilder(self, self.clk).timers([
            ("lcd_clk_en", LCD_CLK_PER),
        ])
        delay_cmd_half_done, delay_cmd_done, delay_cmd_long_done =\
            ClkBuilder(self, self.clk)\
            .timers([
                # used to signalize that the 'en' should be asserted low
                ("delay_cmd_half_done", Hd44780Intf.DELAY_CMD // 2),
                # used to signalize that the processing of command is completed
                ("delay_cmd_done", Hd44780Intf.DELAY_CMD),
                # used to signalize that the long command (return home, etc.) is completed
                ("delay_cmd_long_done", Hd44780Intf.DELAY_RETURN_HOME)
            ],
                enableSig=lcd_clk_en,
                rstSig=cmd_timer_rst
            )
        data_in_tmp = Hd44780CmdIntf()
        data_in_tmp.DATA_WIDTH = self.LCD_DATA_WIDTH
        self.data_in_tmp = data_in_tmp

        self._io_core(data_in_tmp, cmd_timer_rst,
                      lcd_clk_en, delay_cmd_half_done,
                      delay_cmd_done, delay_cmd_long_done)
        INIT_SEQUENCE = [
            Hd44780Intf.CMD_FUNCTION_SET(
                Hd44780Intf.DATA_LEN_8b if LCD_DW == 8 else Hd44780Intf.DATA_LEN_4b,
                self.LCD_ROWS - 1,
                Hd44780Intf.FONT_5x8),
            Hd44780Intf.CMD_DISPLAY_CONTROL(1, 0, 0),
            Hd44780Intf.CMD_ENTRY_MODE_SET(1, 1),
        ]
        init_seq = Hd44780CmdIntfBurst()
        init_seq.DATA_WIDTH = self.LCD_DATA_WIDTH
        init_seq.DATA = tuple(
            (Hd44780Intf.RS_CONTROL, Hd44780Intf.RW_WRITE, 0, d)
            for d in INIT_SEQUENCE
        )
        self.init_seq = init_seq
        propagateClkRstn(self)
        data_in = self._translate_data_in(self.dataIn)
        data_in_tmp(HsBuilder.join_prioritized(self, [init_seq.dataOut, data_in]).end)
コード例 #12
0
ファイル: axiInterconnectbase.py プロジェクト: Nic30/hwtLib
    def reqHandler(self, dpReq, orderFifoIn):
        # join with roundrobin on requests form drivers and selected index is stored into orderFifo

        # because it is just proxy
        driversReq = list(map(lambda d: d.req, self.drivers))
        b = HsBuilder.join_fair(self, driversReq, exportSelected=True)
        req = b.end
        reqJoin = b.lastComp

        StreamNode(masters=[req],
                   slaves=[dpReq, orderFifoIn]).sync()
        connect(req, dpReq, exclude=[dpReq.vld, dpReq.rd])
        orderFifoIn.data(oneHotToBin(self, reqJoin.selectedOneHot.data))
コード例 #13
0
    def _impl(self):
        m = self._Mi32_addr_to_Mi32AddrHs(self.s, "addr_tmp")
        m = HsBuilder(self, m).buff(items=self.ADDR_BUFF_DEPTH).end
        self._connect_Mi32AddrHs_to_Mi32(m, self.m)

        data_t = HStruct(
            (self.m.drd._dtype, "drd"),  # read data
            (BIT, "drdy"),  # read data valid
        )
        m = (self.m.drd, self.m.drdy)

        for i in range(self.DATA_BUFF_DEPTH):
            reg = self._reg(f"read_data_reg{i:d}", data_t, def_val={"drdy": 0})
            reg.drd(m[0])
            reg.drdy(m[1])
            m = (reg.drd, reg.drdy)

        self.s.drd(m[0])
        self.s.drdy(m[1])
コード例 #14
0
ファイル: structReader.py プロジェクト: jesseclin/hwtLib
    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)
コード例 #15
0
ファイル: structReader.py プロジェクト: mfkiwl/hwtLib
    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)
コード例 #16
0
ファイル: field_connector.py プロジェクト: mfkiwl/hwtLib
    def connectChoicesOfFrameParts(self, hsNondes: ListOfOutNodeInfos,
                                   part: ChoicesOfFrameParts,
                                   en: Union[RtlSignal, bool],
                                   exclusiveEn: Optional[RtlSignal],
                                   wordIndex: Optional[RtlSignal],
                                   currentWordIndex: int):
        tToIntf = self.dataOut._fieldsToInterfaces
        parentIntf = tToIntf[part.origin.parent.getFieldPath()]
        try:
            sel = self._tmpRegsForSelect[parentIntf]
        except KeyError:
            sel = HsBuilder(self.parent, parentIntf._select).buff().end
            self._tmpRegsForSelect[parentIntf] = sel
        unionGroup = ExclusieveListOfHsNodes(sel)

        # for unions
        for choice in part:
            # connect data signals of choices and collect info about
            # streams
            intfOfChoice = tToIntf[choice.tmpl.getFieldPath()]
            selIndex, isSelected, isSelectValid = self.choiceIsSelected(
                intfOfChoice)
            _exclusiveEn = isSelectValid & isSelected & exclusiveEn

            unionMemberPart = ListOfOutNodeInfos()
            for p in choice:
                self.connectPart(unionMemberPart, p, en, _exclusiveEn,
                                 wordIndex, currentWordIndex)
            unionGroup.append(selIndex, unionMemberPart)
        hsNondes.append(unionGroup)

        if wordIndex is not None:
            en = en & wordIndex._eq(currentWordIndex)
        if part.isLastPart():
            # synchronization of reading from _select register for unions
            selNode = InNodeInfo(sel, en)
        else:
            selNode = InNodeReadOnlyInfo(sel, en)
        hsNondes.append(selNode)
コード例 #17
0
ファイル: ethAddrUpdater.py プロジェクト: jesseclin/hwtLib
    def _impl(self):
        propagateClkRstn(self)
        connectDp(self, self.rxPacketLoader, self.rxDataPump, self.axi_m)
        connectDp(self, self.txPacketUpdater, self.txDataPump, self.axi_m)

        self.txPacketUpdater.writeAck.rd(1)

        rxR = self.rxPacketLoader.dataOut
        txW = self.txPacketUpdater.dataIn

        def withFifo(interface):
            return HsBuilder(self, interface)\
                      .buff(items=4)\
                      .end

        txW.eth.dst(withFifo(rxR.eth.src))
        txW.eth.src(withFifo(rxR.eth.dst))

        txW.ipv4.dst(withFifo(rxR.ipv4.src))
        txW.ipv4.src(withFifo(rxR.ipv4.dst))

        HsBuilder(self,
                  self.packetAddr).split_copy_to(self.rxPacketLoader.get,
                                                 self.txPacketUpdater.set)
コード例 #18
0
ファイル: hsBuilderSplit.py プロジェクト: mfkiwl/hwtLib
    def _impl(self):
        # Builder is class which simplifies building of datapaths
        # and keeps components which are used  which this interface together
        a = HsBuilder(self, self.a, name="builderFromA")
        # .end = last interface in datapath
        # .lastComp = last component in datapath
        # ... take a look at AbstractStreamBuilder

        # register
        a.buff(items=1, latency=1, delay=0)

        # fifo
        a.buff(items=4, latency=1, delay=0)

        # reg + fifo
        a.buff(items=5, latency=2, delay=0)

        # reg wit delay (breaks combinational loop of ready signal)
        a.buff(items=1, latency=2, delay=1)

        # create 3 identhical streams and connect them to a_0-3
        # there is also only split_copy which only create split component
        # but left output unconnected
        a.split_copy_to(self.a_0, self.a_1, self.a_2)

        # round robin like split, data is send only to one of output ports
        # and there is cycling flag which selects priority for each output
        # to assert uniform load
        b = HsBuilder(self, self.b)\
            .split_fair_to(self.b_0, self.b_1, self.b_2,
                           exportSelected=True)

        self.b_selected(b.lastComp.selectedOneHot)

        # send data output interface which is ready and has higher priority
        # (=lowest index)
        HsBuilder(self, self.c).split_prioritized_to(self.c_0, self.c_1)

        # explicitly select output
        HsBuilder(self, self.d)\
            .split_select_to([1, 2, 1, 0],
                             self.d_0, self.d_1, self.d_2)

        # explicitly select output
        HsBuilder(self, self.e)\
            .split_select_to(self.e_select,
                             self.e_0, self.e_1, self.e_2)
コード例 #19
0
ファイル: ethAddrUpdater.py プロジェクト: jesseclin/hwtLib
 def withFifo(interface):
     return HsBuilder(self, interface)\
               .buff(items=4)\
               .end
コード例 #20
0
    def connectPart(self,
                    hsNondes: list,
                    part: Union[TransPart, ChoicesOfFrameParts],
                    en: Union[RtlSignal, bool],
                    exclusiveEn: Optional[RtlSignal]=hBit(1)):
        """
        Create datamux for one word in main fsm
        and colect metainformations for handshake logic

        :param hsNondes: list of nodes of handshaked logic
        """
        busVld = self.dataIn.valid
        tToIntf = self.dataOut._fieldsToInterfaces

        if isinstance(part, ChoicesOfFrameParts):
            parentIntf = tToIntf[part.origin.parent.origin]
            try:
                sel = self._tmpRegsForSelect[parentIntf]
            except KeyError:
                sel = HsBuilder(self, parentIntf._select).buff().end
                self._tmpRegsForSelect[parentIntf] = sel
            unionGroup = ExclusieveListOfHsNodes(sel)

            # for unions
            for choice in part:
                # connect data signals of choices and collect info about
                # streams
                intfOfChoice = tToIntf[choice.tmpl.origin]
                selIndex, isSelected, isSelectValid = self.choiceIsSelected(
                    intfOfChoice)
                _exclusiveEn = isSelectValid & isSelected & exclusiveEn

                unionMemberPart = ListOfOutNodeInfos()
                for p in choice:
                    self.connectPart(unionMemberPart, p, en, _exclusiveEn)
                unionGroup.append(selIndex, unionMemberPart)

            hsNondes.append(unionGroup)

            if part.isLastPart():
                # synchronization of reading from _select register for unions
                selNode = InNodeInfo(sel, en)
            else:
                selNode = InNodeReadOnlyInfo(sel, en)
            hsNondes.append(selNode)
            return

        if part.isPadding:
            return

        fPartSig = self.getInDataSignal(part)
        fieldInfo = part.tmpl.origin

        try:
            signalsOfParts = self._signalsOfParts[part.tmpl]
        except KeyError:
            signalsOfParts = []
            self._signalsOfParts[part.tmpl] = signalsOfParts

        if part.isLastPart():
            # connect all parts in this group to output stream
            signalsOfParts.append(fPartSig)
            intf = self.dataOut._fieldsToInterfaces[fieldInfo]
            intf.data(self.byteOrderCare(
                Concat(
                    *reversed(signalsOfParts)
                ))
            )
            on = OutNodeInfo(self, intf, en, exclusiveEn)
            hsNondes.append(on)
        else:
            dataVld = busVld & en & exclusiveEn
            # part is in some word as last part, we have to store its value to register
            # until the last part arrive
            fPartReg = self._reg("%s_part_%d" % (fieldInfo.name,
                                                 len(signalsOfParts)),
                                 fPartSig._dtype)
            If(dataVld,
               fPartReg(fPartSig)
               )
            signalsOfParts.append(fPartReg)
コード例 #21
0
    def speculative_read_handler(self):
        """
        Connect the speculative_read port to internal storages of the :class:`AxiWriteAggregator`

        We need to handle several cases:

        1. the data is currently in tmp register
        2. the data was in tmp register and now is in data memory
        3. the data is in data memory
        4. the data was in data memory and now it is deallocated
        5. the data was not found anywhere


        Handling of speculative read has following stages:

        1. search input register and main address CAM for data
        2. optionaly load the data from ram
        3. send data to speculative_read_data and set resp to error if was not found
           it may also happen that the data was flushed in the mean time

        .. figure:: ./_static/AxiStoreQueueWritePropagating_speculativeRead.png

        :note: speculative read never block the write channel and thus data may be invalid if the speculative read data is stalled.
            This should be handled in master of speculative read port (Other component which is using this component).
        """
        sra = self.speculative_read_addr

        # CLOCK_PERIOD 0
        ooo_fifo = self.ooo_fifo
        ooo_fifo.read_lookup.data(sra.addr[:self.CACHE_LINE_OFFSET_BITS])

        w_in_reg = self.w_in_reg.dataOut
        w_in_reg_tmp = HObjList(
            HandshakedReg(AxiWriteAggregatorWriteTmpIntf) for _ in range(2))
        for r in w_in_reg_tmp:
            r._updateParamsFrom(w_in_reg)
            r.ID_WIDTH = self.ID_WIDTH

        self.w_in_reg_tmp = w_in_reg_tmp

        w_i = w_in_reg_tmp[0].dataIn
        w_i.orig_request_addr(sra.addr[:self.CACHE_LINE_OFFSET_BITS])
        w_i.orig_request_addr_eq(w_in_reg.addr._eq(w_i.orig_request_addr))
        w_i.orig_request_id(sra.id)
        w_i.orig_request_valid(sra.vld)
        w_i.addr(w_in_reg.addr)
        w_i.data(w_in_reg.data)
        w_i.valid(w_in_reg.vld)

        StreamNode(
            [sra],
            [ooo_fifo.read_lookup, w_i],
            skipWhen={
                sra: ~sra.vld
            },  # flush the pipeline if no request
        ).sync()

        # CLK_PERIOD 1
        read_lookup_res = HsBuilder(self, ooo_fifo.read_lookup_res).buff(1).end
        StreamNode([read_lookup_res, w_in_reg_tmp[0].dataOut],
                   [w_in_reg_tmp[1].dataIn]).sync()
        w_in_reg_tmp[1].dataIn(
            w_in_reg_tmp[0].dataOut,
            exclude=[w_in_reg_tmp[1].dataIn.vld, w_in_reg_tmp[1].dataIn.rd])

        in_ram_flag = rename_signal(self,
                                    read_lookup_res.data & ooo_fifo.item_valid,
                                    "in_ram_flag")
        found_in_ram_flag = self._reg("found_in_ram_flag", def_val=0)
        If(read_lookup_res.vld & read_lookup_res.rd,
           found_in_ram_flag(in_ram_flag != 0))

        ram_r = self.data_ram.port[2]
        ram_r.en.vld(found_in_ram_flag.next)
        ram_r.addr(oneHotToBin(self, in_ram_flag, "in_ram_index"))

        # CLK_PERIOD 2
        srd = self.speculative_read_data
        w_in_reg_tmp_o = w_in_reg_tmp[1].dataOut
        StreamNode(
            [w_in_reg_tmp_o],
            [srd],
            # filter out pipeline flushes
            extraConds={
                srd: w_in_reg_tmp_o.orig_request_valid
            },
            skipWhen={
                srd: ~w_in_reg_tmp_o.orig_request_valid
            },
        ).sync()

        # read from in_tmp req has to be postponed so we can potentially load the data from ram first
        found_in_actual_w_in_reg = rename_signal(
            self,
            w_in_reg.vld & w_in_reg.addr._eq(w_in_reg_tmp_o.orig_request_addr),
            "spec_read_found_in_actual_w_in_reg")
        w_in_reg_tmp_1_o = w_in_reg_tmp[0].dataOut
        found_in_w_in_reg_1 = rename_signal(
            self, w_in_reg_tmp_1_o.vld & w_in_reg_tmp_1_o.valid
            & w_in_reg_tmp_1_o.addr._eq(w_in_reg_tmp_o.orig_request_addr),
            "spec_read_found_in_w_in_reg_1")
        found_in_write_tmp_reg_2 = rename_signal(
            self, w_in_reg_tmp_o.vld & w_in_reg_tmp_o.valid
            & w_in_reg_tmp_o.orig_request_addr_eq,
            "spec_read_found_in_write_tmp_reg_2")

        srd.id(w_in_reg_tmp_o.orig_request_id)
        If(
            found_in_actual_w_in_reg,
            # found in tmp register just now
            srd.data(w_in_reg.data),
            srd.resp(RESP_OKAY),
            srd.last(1),
        ).Elif(
            found_in_w_in_reg_1,
            # found in tmp register in clock cycle -2
            srd.data(w_in_reg_tmp_1_o.data),
            srd.resp(RESP_OKAY),
            srd.last(1),
        ).Elif(
            found_in_write_tmp_reg_2,
            # found in tmp register in clock cycle -2
            srd.data(w_in_reg_tmp_o.data),
            srd.resp(RESP_OKAY),
            srd.last(1),
        ).Elif(
            found_in_ram_flag,
            # found in write data memory
            srd.data(ram_r.dout),
            srd.resp(RESP_OKAY),
            srd.last(1),
        ).Else(
            # not found anywhere
            srd.data(None),
            srd.resp(RESP_EXOKAY),
            srd.last(1),
        )
コード例 #22
0
ファイル: _deparser.py プロジェクト: mfkiwl/hwtLib
    def connectPartsOfWord(self, wordData_out: RtlSignal,
                           tPart: Union[TransPart,
                                        ChoicesOfFrameParts],
                           inPorts_out: List[Union[Handshaked,
                                                   StreamNode]],
                           lastInPorts_out: List[Union[Handshaked,
                                                       StreamNode]])\
            ->Tuple[Optional[RtlSignal], Optional[RtlSignal]]:
        """
        Connect transactions parts to signal for word of output stream

        :param wordData_out: signal for word of output stream
        :param tPart: instance of TransPart or ChoicesOfFrameParts to connect
        :param inPorts_out: input interfaces to this transaction part
        :param lastInPorts_out: input interfaces for last parts of transactions
        :return: tuple (strb, keep) if strb/keep driven by input stream, else (None, None)
        """

        tToIntf = self.dataIn._fieldsToInterfaces

        if isinstance(tPart, ChoicesOfFrameParts):
            # connect parts of union to output signal
            high, low = tPart.getBusWordBitRange()
            parentIntf = tToIntf[tPart.origin.parent.getFieldPath()]

            if parentIntf not in self._tmpRegsForSelect.keys():
                sel = HsBuilder(self, parentIntf._select).buff().end
                self._tmpRegsForSelect[parentIntf] = sel

            inPortGroups = ExclusiveStreamGroups()
            lastInPortsGroups = ExclusiveStreamGroups()
            w = tPart.bit_length()

            # tuples (cond, part of data mux for dataOut)
            unionChoices = []
            sk_stashes = []
            # for all choices in union
            for choice in tPart:
                tmp = self._sig("union_tmp_", Bits(w))
                intfOfChoice = tToIntf[choice.tmpl.getFieldPath()]
                _, _isSelected, isSelectValid = \
                    AxiS_frameParserFieldConnector.choiceIsSelected(self, intfOfChoice)
                unionChoices.append((_isSelected, wordData_out[high:low](tmp)))

                isSelected = _isSelected & isSelectValid

                # build meta for handshake logic sync
                inPortsNode = StreamNode()
                inPortGroups.append((isSelected, inPortsNode))

                lastPortsNode = StreamNode()
                lastInPortsGroups.append((isSelected, lastPortsNode))

                sk_stash = StrbKeepStash()
                # walk all parts in union choice
                start = tPart.startOfPart
                for choicePart in choice:
                    if start != choicePart.startOfPart:
                        # add padding because there is a hole in data
                        _w = choicePart.startOfPart - start
                        assert _w > 0, _w
                        sk_stash.push((_w, 0), (_w, 0))

                    _strb, _keep = self.connectPartsOfWord(
                        tmp, choicePart, inPortsNode.masters,
                        lastPortsNode.masters)
                    sk_stash.push(_strb, _keep)
                    start = choicePart.endOfPart

                if start != tPart.endOfPart:
                    # add padding because there is a hole after
                    _w = tPart.endOfPart - start
                    assert _w > 0, _w
                    sk_stash.push((_w, 0), (_w, 0))

                # store isSelected sig and strb/keep value for later strb/keep resolving
                sk_stashes.append((isSelected, sk_stash))

            # generate data out mux
            SwitchLogic(unionChoices, default=wordData_out(None))

            inPorts_out.append(inPortGroups)
            lastInPorts_out.append(lastInPortsGroups)
            # resolve strb/keep from strb/keep and isSelected of union members
            if w % 8 != 0:
                raise NotImplementedError(w)
            strb, keep = reduce_conditional_StrbKeepStashes(sk_stashes)
        else:
            # connect parts of fields to output signal
            high, low = tPart.getBusWordBitRange()
            if tPart.isPadding:
                wordData_out[high:low](None)
            else:
                intf = tToIntf[tPart.tmpl.getFieldPath()]
                fhigh, flow = tPart.getFieldBitRange()
                wordData_out[high:low](self.byteOrderCare(
                    intf.data)[fhigh:flow])
                inPorts_out.append(intf)

                if tPart.isLastPart():
                    lastInPorts_out.append(intf)

            w = tPart.bit_length()
            strb = int(not tPart.isPadding)
            keep = int(not tPart.canBeRemoved)
        return ((w, strb), (w, keep))
コード例 #23
0
ファイル: frameForge.py プロジェクト: jesseclin/hwtLib
    def connectPartsOfWord(self, wordData_out: RtlSignal,
                           tPart: Union[TransPart, ChoicesOfFrameParts,
                                        StreamOfFramePars],
                           inPorts_out: List[Union[Handshaked, StreamNode]],
                           lastInPorts_out: List[Union[Handshaked,
                                                       StreamNode]]):
        """
        Connect transactions parts to signal for word of output stream

        :param wordData_out: signal for word of output stream
        :param tPart: instance of TransPart or ChoicesOfFrameParts to connect
        :param inPorts_out: input interfaces to this transaction part
        :param lastInPorts_out: input interfaces for last parts of transactions
        """

        tToIntf = self.dataIn._fieldsToInterfaces

        if isinstance(tPart, ChoicesOfFrameParts):
            # connnect parts of union to output signal
            w = tPart.bit_length()
            high, low = tPart.getBusWordBitRange()
            parentIntf = tToIntf[tPart.origin.parent.origin]

            if parentIntf not in self._tmpRegsForSelect.keys():
                sel = HsBuilder(self, parentIntf._select).buff().end
                self._tmpRegsForSelect[parentIntf] = sel

            inPortGroups = ExclusiveStreamGroups()
            lastInPortsGroups = ExclusiveStreamGroups()

            # tuples (cond, part of data mux for dataOut)
            unionChoices = []

            # for all union choices
            for choice in tPart:
                tmp = self._sig("union_tmp_", Bits(w))
                intfOfChoice = tToIntf[choice.tmpl.origin]
                _, isSelected, isSelectValid = AxiS_frameParser.choiceIsSelected(
                    self, intfOfChoice)
                unionChoices.append((isSelected, wordData_out[high:low](tmp)))

                isSelected = isSelected & isSelectValid

                inPortsNode = StreamNode()
                lastPortsNode = StreamNode()

                inPortGroups.append((isSelected, inPortsNode))
                lastInPortsGroups.append((isSelected, lastPortsNode))

                # walk all parts in union choice
                for _tPart in choice:
                    self.connectPartsOfWord(tmp, _tPart, inPortsNode.masters,
                                            lastPortsNode.masters)

            # generate data out mux
            SwitchLogic(unionChoices, default=wordData_out(None))

            inPorts_out.append(inPortGroups)
            lastInPorts_out.append(lastInPortsGroups)
        elif isinstance(tPart, StreamOfFramePars):
            if len(tPart) != 1:
                raise NotImplementedError(
                    "Structuralized streams not implemented yiet")

            p = tPart[0]
            intf = tToIntf[p.tmpl.origin]

            if int(intf.DATA_WIDTH) != wordData_out._dtype.bit_length():
                raise NotImplementedError(
                    "Dynamic resizing of streams not implemented yiet")

            if len(self._frames) > 1:
                raise NotImplementedError(
                    "Dynamic splitting on frames not implemented yet")
            wordData_out(self.byteOrderCare(intf.data))
            inPorts_out.append(intf)

            if tPart.isLastPart():
                lastInPorts_out.append(intf)

            return intf.strb

        else:
            # connect parts of fields to output signal
            high, low = tPart.getBusWordBitRange()
            if tPart.isPadding:
                wordData_out[high:low](None)
            else:
                intf = tToIntf[tPart.tmpl.origin]
                fhigh, flow = tPart.getFieldBitRange()
                wordData_out[high:low](self.byteOrderCare(
                    intf.data)[fhigh:flow])
                inPorts_out.append(intf)

                if tPart.isLastPart():
                    lastInPorts_out.append(intf)
コード例 #24
0
ファイル: hsBuilderSplit.py プロジェクト: Nic30/hwtLib
    def _impl(self):
        # Builder is class which simplifies building of datapaths
        # and keeps components which are used  which this interface together
        a = HsBuilder(self, self.a, name="builderFromA")
        # .end = last interface in datapath
        # .lastComp = last component in datapath
        # ... take a look at AbstractStreamBuilder

        # register
        a.buff(items=1, latency=1, delay=0)

        # fifo
        a.buff(items=4, latency=1, delay=0)

        # reg + fifo
        a.buff(items=5, latency=2, delay=0)

        # reg wit delay (breaks combinational loop of ready signal)
        a.buff(items=1, latency=2, delay=1)

        # create 3 identhical streams and connect them to a_0-3
        # there is also only split_copy which only create split component
        # but left output unconnected
        a.split_copy_to(self.a_0, self.a_1, self.a_2)

        # round robin like split, data is send only to one of output ports
        # and there is cycling flag which selects priority for each output
        # to assert uniform load
        b = HsBuilder(self, self.b)\
            .split_fair_to(self.b_0, self.b_1, self.b_2,
                           exportSelected=True)

        self.b_selected(b.lastComp.selectedOneHot)

        # send data output interface which is ready and has higher priority
        # (=lowest index)
        HsBuilder(self, self.c).split_prioritized_to(self.c_0, self.c_1)

        # explicitly select output
        HsBuilder(self, self.d)\
            .split_select_to([1, 2, 1, 0],
                             self.d_0, self.d_1, self.d_2)

        # explicitly select output
        HsBuilder(self, self.e)\
            .split_select_to(self.e_select,
                             self.e_0, self.e_1, self.e_2)