Exemple #1
0
    def _impl(self):
        if not self.IGNORE_DATA_LOSE:
            assert self.IN_FREQ <= self.OUT_FREQ
        in_clk_rst_n = self.dataIn_clk, self.dataIn_rst_n
        out_clk_rst_n = self.dataOut_clk, self.dataOut_rst_n
        in_vld, out_vld = (self.get_valid_signal(self.dataIn),
                           self.get_valid_signal(self.dataOut))

        b_cntrl = SignalCdcBuilder(in_vld,
                                   in_clk_rst_n,
                                   out_clk_rst_n,
                                   0,
                                   name_prefix="")
        b_cntrl.add_in_reg()
        for _ in range(3):
            b_cntrl.add_out_reg()
        out_data_en = b_cntrl.path[-2]
        out_vld(b_cntrl.path[-1])

        in_data = packIntf(self.dataIn, exclude=[in_vld])
        b_data = SignalCdcBuilder(in_data,
                                  in_clk_rst_n,
                                  out_clk_rst_n,
                                  self.DATA_RESET_VAL,
                                  name_prefix="")
        b_data.add_in_reg()
        b_data.add_out_reg(en=out_data_en)

        connectPacked(b_data.path[-1], self.dataOut, exclude=[out_vld])
Exemple #2
0
    def _connect_fifo_in(self):
        rd = self.get_ready_signal
        vld = self.get_valid_signal

        din = self.dataIn
        fIn = self.fifo.dataIn
        wr_en = ~fIn.wait
        rd(din)(wr_en)
        if fIn.DATA_WIDTH > 0:
            fIn.data(packIntf(din, exclude=[vld(din), rd(din)]))
        fIn.en(vld(din) & wr_en)
Exemple #3
0
    def _connect_fifo_in(self):
        rd = self.get_ready_signal
        vld = self.get_valid_signal

        din = self.dataIn
        fIn = self.fifo.dataIn
        wr_en = ~fIn.wait
        rd(din)(wr_en)
        fIn.discard(self.dataIn_discard)
        fIn.commit(din.valid & din.last)
        fIn.data(packIntf(din, exclude=[vld(din), rd(din)]))
        fIn.en(vld(din) & wr_en)
Exemple #4
0
    def _impl(self, clks: Optional[Tuple[Clk, Clk]]=None):
        """
        :clks: optional tuple (inClk, outClk)
        """
        rd = self.getRd
        vld = self.getVld

        # connect clock and resets
        if clks is None:
            propagateClkRstn(self)
            inClk, outClk = (None, None)
        else:
            propagateRstn(self)
            inClk, outClk = clks
            self.fifo.dataIn_clk(inClk)
            self.fifo.dataOut_clk(outClk)

        # to fifo
        fIn = self.fifo.dataIn
        din = self.dataIn
        wr_en = ~fIn.wait
        rd(din)(wr_en)
        fIn.data(packIntf(din, exclude=[vld(din), rd(din)]))
        fIn.en(vld(din) & wr_en)

        # from fifo
        fOut = self.fifo.dataOut
        dout = self.dataOut
        out_vld = self._reg("out_vld", defVal=0, clk=outClk)
        vld(dout)(out_vld)
        connectPacked(fOut.data,
                      dout,
                      exclude=[vld(dout), rd(dout)])
        fOut.en((rd(dout) | ~out_vld) & ~fOut.wait)
        If(rd(dout) | ~out_vld,
           out_vld(~fOut.wait)
        )

        if self.EXPORT_SIZE:
            sizeTmp = self._sig("sizeTmp", self.size._dtype)
            connect(self.fifo.size, sizeTmp, fit=True)

            If(out_vld,
               self.size(sizeTmp + 1)
            ).Else(
                connect(self.fifo.size, self.size, fit=True)
            )
Exemple #5
0
    def _impl(self, clks: Optional[Tuple[Clk, Clk]] = None):
        """
        :clks: optional tuple (inClk, outClk)
        """
        rd = self.getRd
        vld = self.getVld

        # connect clock and resets
        if clks is None:
            propagateClkRstn(self)
            inClk, outClk = (None, None)
        else:
            propagateRstn(self)
            inClk, outClk = clks
            self.fifo.dataIn_clk(inClk)
            self.fifo.dataOut_clk(outClk)

        # to fifo
        fIn = self.fifo.dataIn
        din = self.dataIn
        wr_en = ~fIn.wait
        rd(din)(wr_en)
        fIn.data(packIntf(din, exclude=[vld(din), rd(din)]))
        fIn.en(vld(din) & wr_en)

        # from fifo
        fOut = self.fifo.dataOut
        dout = self.dataOut
        out_vld = self._reg("out_vld", defVal=0, clk=outClk)
        vld(dout)(out_vld)
        connectPacked(fOut.data, dout, exclude=[vld(dout), rd(dout)])
        fOut.en((rd(dout) | ~out_vld) & ~fOut.wait)
        If(rd(dout) | ~out_vld, out_vld(~fOut.wait))

        if self.EXPORT_SIZE:
            sizeTmp = self._sig("sizeTmp", self.size._dtype)
            connect(self.fifo.size, sizeTmp, fit=True)

            If(out_vld, self.size(sizeTmp + 1)).Else(
                connect(self.fifo.size, self.size, fit=True))
Exemple #6
0
    def ar_dispatch(self):
        """
        Send read request on AXI and store transaction in to state array and ooo_fifo for later wake up
        """
        ooo_fifo = self.ooo_fifo
        ar = self.m.ar
        din = self.dataIn
        assert din.addr._dtype.bit_length() == self.ADDR_WIDTH - self.ADDR_OFFSET_W, (
            din.addr._dtype.bit_length(), self.ADDR_WIDTH, self.ADDR_OFFSET_W)
        dataIn_reg = HandshakedReg(din.__class__)
        dataIn_reg._updateParamsFrom(din)
        self.dataIn_reg = dataIn_reg
        StreamNode(
            [din],
            [dataIn_reg.dataIn, ooo_fifo.write_confirm]
        ).sync()
        dataIn_reg.dataIn(din, exclude=[din.rd, din.vld])

        ar_node = StreamNode(
            [dataIn_reg.dataOut, ooo_fifo.read_execute],
            [ar]
        )
        ar_node.sync()

        state_arr = self.state_array
        state_write = state_arr.port[0]
        state_write.en(ar_node.ack())
        state_write.addr(ooo_fifo.read_execute.index)

        din_data = dataIn_reg.dataOut

        state_write.din(packIntf(din_data, exclude=[din_data.rd, din_data.vld]))

        ar.id(ooo_fifo.read_execute.index)
        ar.addr(Concat(din_data.addr, Bits(self.ADDR_OFFSET_W).from_py(0)))
        self._axi_addr_defaults(ar, 1)
Exemple #7
0
    def main_pipeline(self):
        PIPELINE_CONFIG = self.PIPELINE_CONFIG
        self.pipeline = pipeline = [
            OOOOpPipelineStage(i, f"st{i:d}", self)
            for i in range(PIPELINE_CONFIG.WAIT_FOR_WRITE_ACK + 1)
        ]

        state_read = self.state_array.port[1]
        self.collision_detector(pipeline)
        HAS_TRANS_ST = self.TRANSACTION_STATE_T is not None

        for i, st in enumerate(pipeline):
            if i > 0:
                st_prev = pipeline[i - 1]

            if i < len(pipeline) - 1:
                st_next = pipeline[i + 1]

            # :note: pipeline stages described in PIPELINE_CONFIG enum
            if i == PIPELINE_CONFIG.READ_DATA_RECEIVE:
                # :note: we can not apply forward write data there because we do not know the original address yet
                r = self.m.r
                state_read.addr(r.id)
                st.addr = state_read.dout[self.MAIN_STATE_INDEX_WIDTH:]
                if HAS_TRANS_ST:
                    low = self.MAIN_STATE_INDEX_WIDTH
                    st.transaction_state = state_read.dout[:low]._reinterpret_cast(self.TRANSACTION_STATE_T)

                r.ready(st.in_ready)
                st.in_valid(r.valid)
                st.out_ready(st_next.in_ready)
                state_read.en(st.load_en)
                If(st.load_en,
                    st.id(r.id),
                    self.data_load(r, st),
                )

            elif i <= PIPELINE_CONFIG.STATE_LOAD:
                If(st.load_en,
                    st.id(st_prev.id),
                    st.addr(st_prev.addr),
                    self.propagate_trans_st(st_prev, st),
                )
                self.apply_data_write_forwarding(st, st.load_en)
                st.in_valid(st_prev.valid)
                st.out_ready(st_next.in_ready)

            elif i == PIPELINE_CONFIG.WRITE_BACK:
                If(st.load_en,
                    st.id(st_prev.id),
                    st.addr(st_prev.addr),
                    self.propagate_trans_st(st_prev, st),
                )
                self.apply_data_write_forwarding(st, st.load_en, self.main_op)
                aw = self.m.aw
                w = self.m.w

                cancel = rename_signal(self, self.write_cancel(st), "write_back_cancel")
                st.in_valid(st_prev.valid)
                st.out_ready(st_next.in_ready & ((aw.ready & w.ready) | cancel))

                StreamNode(
                    [], [aw, w],
                    extraConds={
                        aw: st.valid & st_next.in_ready & ~cancel,
                        w: st.valid & st_next.in_ready & ~cancel
                    },
                    skipWhen={
                        aw:cancel,
                        w:cancel,
                    }
                ).sync()

                self._axi_addr_defaults(aw, 1)
                aw.id(st.id)
                aw.addr(Concat(st.addr, Bits(self.ADDR_OFFSET_W).from_py(0)))

                st_data = st.data
                if not isinstance(st_data, RtlSignal):
                    st_data = packIntf(st_data)

                w.data(st_data._reinterpret_cast(w.data._dtype))
                w.strb(mask(self.DATA_WIDTH // 8))
                w.last(1)

            elif i > PIPELINE_CONFIG.WRITE_BACK and i != PIPELINE_CONFIG.WAIT_FOR_WRITE_ACK:
                if i == PIPELINE_CONFIG.WRITE_BACK + 1:
                    st.in_valid(st_prev.valid & ((aw.ready & w.ready) | cancel))
                else:
                    st.in_valid(st_prev.valid)
                st.out_ready(st_next.in_ready)

                If(st.load_en,
                   st.id(st_prev.id),
                   st.addr(st_prev.addr),
                   st.data(st_prev.data),
                   self.propagate_trans_st(st_prev, st),
                )
            elif i == PIPELINE_CONFIG.WAIT_FOR_WRITE_ACK:
                If(st.load_en,
                    st.id(st_prev.id),
                    st.addr(st_prev.addr),
                    self.propagate_trans_st(st_prev, st),
                    st.data(st_prev.data),
                )
                dout = self.dataOut
                b = self.m.b
                confirm = self.ooo_fifo.read_confirm
                cancel = self.write_cancel(st)

                # ommiting st_next.ready as there is no next
                w_ack_node = StreamNode(
                    [b],
                    [dout, confirm],
                    extraConds={
                        dout: st.valid,
                        b: st.valid & ~cancel,
                        confirm: st.valid,
                    },
                    skipWhen={
                        b: st.valid & cancel,
                    }
                )
                w_ack_node.sync()
                st.in_valid(st_prev.valid)
                st.out_ready((b.valid | cancel) & dout.rd & confirm.rd)

                dout.addr(st.addr)
                dout.data(st.data)
                if HAS_TRANS_ST:
                    dout.transaction_state(st.transaction_state)

                confirm.data(st.id)