Exemple #1
0
    def __init__(self, masters, target):
        self.submodules.rr_write = roundrobin.RoundRobin(
            len(masters), roundrobin.SP_CE)
        self.submodules.rr_read = roundrobin.RoundRobin(
            len(masters), roundrobin.SP_CE)

        def get_sig(interface, channel, name):
            return getattr(getattr(interface, channel), name)

        # Mux master->slave signals
        for channel, name, direction in target.layout_flat():
            rr = self.rr_write if channel in ["aw", "w", "b"] else self.rr_read
            if direction == DIR_M_TO_S:
                choices = Array(get_sig(m, channel, name) for m in masters)
                self.comb += get_sig(target, channel,
                                     name).eq(choices[rr.grant])

        # Connect slave->master signals
        for channel, name, direction in target.layout_flat():
            rr = self.rr_write if channel in ["aw", "w", "b"] else self.rr_read
            if direction == DIR_S_TO_M:
                source = get_sig(target, channel, name)
                for i, m in enumerate(masters):
                    dest = get_sig(m, channel, name)
                    if name == "ready":
                        self.comb += dest.eq(source & (rr.grant == i))
                    else:
                        self.comb += dest.eq(source)

        # Allow to change rr.grant only after all requests from a master have been responded to.
        self.submodules.wr_lock = wr_lock = _AXILiteRequestCounter(
            request=target.aw.valid & target.aw.ready,
            response=target.b.valid & target.b.ready)
        self.submodules.rd_lock = rd_lock = _AXILiteRequestCounter(
            request=target.ar.valid & target.ar.ready,
            response=target.r.valid & target.r.ready)

        # Switch to next request only if there are no responses pending.
        self.comb += [
            self.rr_write.ce.eq(
                ~(target.aw.valid | target.w.valid | target.b.valid)
                & wr_lock.ready),
            self.rr_read.ce.eq(~(target.ar.valid | target.r.valid)
                               & rd_lock.ready),
        ]

        # Connect bus requests to round-robin selectors.
        self.comb += [
            self.rr_write.request.eq(
                Cat(*[m.aw.valid | m.w.valid | m.b.valid for m in masters])),
            self.rr_read.request.eq(
                Cat(*[m.ar.valid | m.r.valid for m in masters])),
        ]
Exemple #2
0
    def __init__(self, masters, target):
        self.submodules.rr = roundrobin.RoundRobin(len(masters))

        # mux master->slave signals
        for name, size, direction in _layout:
            if direction == DIR_M_TO_S:
                choices = Array(getattr(m, name) for m in masters)
                self.comb += getattr(target, name).eq(choices[self.rr.grant])

        # connect slave->master signals
        for name, size, direction in _layout:
            if direction == DIR_S_TO_M:
                source = getattr(target, name)
                for i, m in enumerate(masters):
                    dest = getattr(m, name)
                    if name == "ack" or name == "err":
                        self.comb += dest.eq(source & (self.rr.grant == i))
                    else:
                        self.comb += dest.eq(source)

        # connect bus requests to round-robin selector
        reqs = [m.cyc for m in masters]
        self.comb += self.rr.request.eq(Cat(*reqs))
Exemple #3
0
    def __init__(self, masters, slaves, npending=8, register=False):
        r_transactionFIFO = partial(
            stream.SyncFIFO,
            set_layout_parameters(_transaction_layout, n=len(slaves)),
            npending)
        w_transactionFIFO = partial(
            stream.SyncFIFO,
            set_layout_parameters(_transaction_layout, n=len(masters)),
            npending)
        self.r_transaction = [r_transactionFIFO() for _ in masters]
        self.w_transaction = [w_transactionFIFO() for _ in slaves]

        ###

        self.submodules += self.r_transaction
        self.submodules += self.w_transaction
        target = Interface()
        self.submodules.ar_rr = roundrobin.RoundRobin(len(masters))
        self.submodules.aw_rr = roundrobin.RoundRobin(len(masters))
        self.submodules.ar_dec = AddressDecoder(target.ar,
                                                [(fn, slave.ar)
                                                 for (fn, slave) in slaves],
                                                register)
        self.submodules.aw_dec = AddressDecoder(target.aw,
                                                [(fn, slave.aw)
                                                 for (fn, slave) in slaves],
                                                register)

        # mux master->slave signals
        for name in [
                name for name, _, direction in target.ar.layout
                if direction == DIR_M_TO_S
        ]:
            choices = Array(getattr(m.ar, name) for m in masters)
            self.comb += getattr(target.ar, name).eq(choices[self.ar_rr.grant])
        for name in [
                name for name, _, direction in target.aw.layout
                if direction == DIR_M_TO_S
        ]:
            choices = Array(getattr(m.aw, name) for m in masters)
            self.comb += getattr(target.aw, name).eq(choices[self.aw_rr.grant])

        # connect slave->master signal
        self.comb += [
            master.ar.ready.eq(target.ar.ready &
                               # FIFO writable?
                               fifo.sink.ack & (self.ar_rr.grant == i))
            for i, (master,
                    fifo) in enumerate(zip(masters, self.r_transaction))
        ]
        w_transaction_ack = Signal()
        self.comb += w_transaction_ack.eq(
            reduce(
                operator.or_,
                Cat(*[fifo.sink.ack for fifo in self.w_transaction])
                & self.aw_dec.slave_sel_r))
        self.comb += [
            master.aw.ready.eq(target.aw.ready &
                               # FIFO writable?
                               w_transaction_ack & (self.aw_rr.grant == i))
            for i, master in enumerate(masters)
        ]

        # connect bus requests to round-robin selector
        ar_reqs = [master.ar.valid & ~master.ar.ready for master in masters]
        aw_reqs = [master.aw.valid & ~master.aw.ready for master in masters]
        self.comb += [
            self.ar_rr.request.eq(Cat(*ar_reqs)),
            self.aw_rr.request.eq(Cat(*aw_reqs)),
        ]

        # connect transaction sinks
        aw_acked = Signal()
        self.comb += [
            Cat(*[fifo.sink.stb for fifo in self.r_transaction]).eq(
                Cat(*[
                    ar.valid & ar.ready
                    for ar in [master.ar for master in masters]
                ])),
            aw_acked.eq(target.aw.valid & target.aw.ready),
            Cat(*[fifo.sink.stb for fifo in self.w_transaction]).eq(
                Replicate(aw_acked, len(slaves)) & self.aw_dec.slave_sel_r)
        ]
        self.comb += [
            fifo.sink.sel.eq(self.ar_dec.slave_sel_r)
            for fifo in self.r_transaction
        ]
        self.submodules.decoder = coding.Decoder(len(masters))
        self.comb += self.decoder.i.eq(self.aw_rr.grant)
        self.comb += [
            fifo.sink.sel.eq(self.decoder.o) for fifo in self.w_transaction
        ]
Exemple #4
0
    def do_finalize(self):
        controller = self.controller
        nmasters = len(self.masters)

        # Address mapping --------------------------------------------------------------------------
        cba_shifts = {
            "ROW_BANK_COL":
            controller.settings.geom.colbits - controller.address_align
        }
        cba_shift = cba_shifts[controller.settings.address_mapping]
        m_ba = [
            m.get_bank_address(self.bank_bits, cba_shift) for m in self.masters
        ]
        m_rca = [
            m.get_row_column_address(self.bank_bits, self.rca_bits, cba_shift)
            for m in self.masters
        ]

        master_readys = [0] * nmasters
        master_wdata_readys = [0] * nmasters
        master_rdata_valids = [0] * nmasters

        arbiters = [
            roundrobin.RoundRobin(nmasters, roundrobin.SP_CE)
            for n in range(self.nbanks)
        ]
        self.submodules += arbiters

        for nb, arbiter in enumerate(arbiters):
            bank = getattr(controller, "bank" + str(nb))

            # For each master, determine if another bank locks it ----------------------------------
            master_locked = []
            for nm, master in enumerate(self.masters):
                locked = Signal()
                for other_nb, other_arbiter in enumerate(arbiters):
                    if other_nb != nb:
                        other_bank = getattr(controller,
                                             "bank" + str(other_nb))
                        locked = locked | (other_bank.lock &
                                           (other_arbiter.grant == nm))
                master_locked.append(locked)

            # Arbitrate ----------------------------------------------------------------------------
            bank_selected = [(ba == nb) & ~locked
                             for ba, locked in zip(m_ba, master_locked)]
            bank_requested = [
                bs & master.cmd.valid
                for bs, master in zip(bank_selected, self.masters)
            ]
            self.comb += [
                arbiter.request.eq(Cat(*bank_requested)),
                arbiter.ce.eq(~bank.valid & ~bank.lock)
            ]

            # Route requests -----------------------------------------------------------------------
            self.comb += [
                bank.addr.eq(Array(m_rca)[arbiter.grant]),
                bank.we.eq(Array(self.masters)[arbiter.grant].cmd.we),
                bank.valid.eq(Array(bank_requested)[arbiter.grant])
            ]
            master_readys = [
                master_ready |
                ((arbiter.grant == nm) & bank_selected[nm] & bank.ready)
                for nm, master_ready in enumerate(master_readys)
            ]
            master_wdata_readys = [
                master_wdata_ready | ((arbiter.grant == nm) & bank.wdata_ready)
                for nm, master_wdata_ready in enumerate(master_wdata_readys)
            ]
            master_rdata_valids = [
                master_rdata_valid | ((arbiter.grant == nm) & bank.rdata_valid)
                for nm, master_rdata_valid in enumerate(master_rdata_valids)
            ]

        # Delay write/read signals based on their latency
        for nm, master_wdata_ready in enumerate(master_wdata_readys):
            for i in range(self.write_latency):
                new_master_wdata_ready = Signal()
                self.sync += new_master_wdata_ready.eq(master_wdata_ready)
                master_wdata_ready = new_master_wdata_ready
            master_wdata_readys[nm] = master_wdata_ready

        for nm, master_rdata_valid in enumerate(master_rdata_valids):
            for i in range(self.read_latency):
                new_master_rdata_valid = Signal()
                self.sync += new_master_rdata_valid.eq(master_rdata_valid)
                master_rdata_valid = new_master_rdata_valid
            master_rdata_valids[nm] = master_rdata_valid

        for master, master_ready in zip(self.masters, master_readys):
            self.comb += master.cmd.ready.eq(master_ready)
        for master, master_wdata_ready in zip(self.masters,
                                              master_wdata_readys):
            self.comb += master.wdata.ready.eq(master_wdata_ready)
        for master, master_rdata_valid in zip(self.masters,
                                              master_rdata_valids):
            self.comb += master.rdata.valid.eq(master_rdata_valid)

        # Route data writes ------------------------------------------------------------------------
        wdata_cases = {}
        for nm, master in enumerate(self.masters):
            wdata_cases[2**nm] = [
                controller.wdata.eq(master.wdata.data),
                controller.wdata_we.eq(master.wdata.we)
            ]
        wdata_cases["default"] = [
            controller.wdata.eq(0),
            controller.wdata_we.eq(0)
        ]
        self.comb += Case(Cat(*master_wdata_readys), wdata_cases)

        # Route data reads -------------------------------------------------------------------------
        for master in self.masters:
            self.comb += master.rdata.data.eq(controller.rdata)
Exemple #5
0
    def do_finalize(self):
        nmasters = len(self._masters)

        m_ca, m_ba, m_rca = self._split_master_addresses(
            self._controller_bits, self._bank_bits, self._rca_bits,
            self._cba_shift)

        for nc, controller in enumerate(self._controllers):
            if self._controller_bits:
                controller_selected = [ca == nc for ca in m_ca]
            else:
                controller_selected = [1] * nmasters
            master_req_acks = [0] * nmasters
            master_dat_w_acks = [0] * nmasters
            master_dat_r_acks = [0] * nmasters

            rrs = [
                roundrobin.RoundRobin(nmasters, roundrobin.SP_CE)
                for n in range(self._nbanks)
            ]
            self.submodules += rrs
            for nb, rr in enumerate(rrs):
                bank = getattr(controller, "bank" + str(nb))

                # for each master, determine if another bank locks it
                master_locked = []
                for nm, master in enumerate(self._masters):
                    locked = 0
                    for other_nb, other_rr in enumerate(rrs):
                        if other_nb != nb:
                            other_bank = getattr(controller,
                                                 "bank" + str(other_nb))
                            locked = locked | (other_bank.lock &
                                               (other_rr.grant == nm))
                    master_locked.append(locked)

                # arbitrate
                bank_selected = [
                    cs & (ba == nb) & ~locked for cs, ba, locked in zip(
                        controller_selected, m_ba, master_locked)
                ]
                bank_requested = [
                    bs & master.stb
                    for bs, master in zip(bank_selected, self._masters)
                ]
                self.comb += [
                    rr.request.eq(Cat(*bank_requested)),
                    rr.ce.eq(~bank.stb & ~bank.lock)
                ]

                # route requests
                self.comb += [
                    bank.adr.eq(Array(m_rca)[rr.grant]),
                    bank.we.eq(Array(self._masters)[rr.grant].we),
                    bank.stb.eq(Array(bank_requested)[rr.grant])
                ]
                master_req_acks = [
                    master_req_ack |
                    ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
                    for nm, master_req_ack in enumerate(master_req_acks)
                ]
                master_dat_w_acks = [
                    master_dat_w_ack | ((rr.grant == nm) & bank.dat_w_ack)
                    for nm, master_dat_w_ack in enumerate(master_dat_w_acks)
                ]
                master_dat_r_acks = [
                    master_dat_r_ack | ((rr.grant == nm) & bank.dat_r_ack)
                    for nm, master_dat_r_ack in enumerate(master_dat_r_acks)
                ]

            for nm, master_dat_w_ack in enumerate(master_dat_w_acks):
                for i in range(self._write_latency):
                    new_master_dat_w_ack = Signal()
                    self.sync += new_master_dat_w_ack.eq(master_dat_w_ack)
                    master_dat_w_ack = new_master_dat_w_ack
                master_dat_w_acks[nm] = master_dat_w_ack

            for nm, master_dat_r_ack in enumerate(master_dat_r_acks):
                for i in range(self._read_latency):
                    new_master_dat_r_ack = Signal()
                    self.sync += new_master_dat_r_ack.eq(master_dat_r_ack)
                    master_dat_r_ack = new_master_dat_r_ack
                master_dat_r_acks[nm] = master_dat_r_ack

            self.comb += [
                master.req_ack.eq(master_req_ack) for master, master_req_ack in
                zip(self._masters, master_req_acks)
            ]
            self.comb += [
                master.dat_w_ack.eq(master_dat_w_ack) for master,
                master_dat_w_ack in zip(self._masters, master_dat_w_acks)
            ]
            self.comb += [
                master.dat_r_ack.eq(master_dat_r_ack) for master,
                master_dat_r_ack in zip(self._masters, master_dat_r_acks)
            ]

            # route data writes
            controller_selected_wl = controller_selected
            for i in range(self._write_latency):
                n_controller_selected_wl = [Signal() for i in range(nmasters)]
                self.sync += [
                    n.eq(o) for n, o in zip(n_controller_selected_wl,
                                            controller_selected_wl)
                ]
                controller_selected_wl = n_controller_selected_wl
            dat_w_maskselect = []
            dat_we_maskselect = []
            for master, selected in zip(self._masters, controller_selected_wl):
                o_dat_w = Signal(self._dw)
                o_dat_we = Signal(self._dw // 8)
                self.comb += If(selected, o_dat_w.eq(master.dat_w),
                                o_dat_we.eq(master.dat_we))
                dat_w_maskselect.append(o_dat_w)
                dat_we_maskselect.append(o_dat_we)
            self.comb += [
                controller.dat_w.eq(reduce(or_, dat_w_maskselect)),
                controller.dat_we.eq(reduce(or_, dat_we_maskselect))
            ]

        # route data reads
        if self._controller_bits:
            for master in self._masters:
                controller_sel = Signal(self._controller_bits)
                for nc, controller in enumerate(self._controllers):
                    for nb in range(nbanks):
                        bank = getattr(controller, "bank" + str(nb))
                        self.comb += If(bank.stb & bank.ack,
                                        controller_sel.eq(nc))
                for i in range(self._read_latency):
                    n_controller_sel = Signal(self._controller_bits)
                    self.sync += n_controller_sel.eq(controller_sel)
                    controller_sel = n_controller_sel
                self.comb += master.dat_r.eq(
                    Array(self._controllers)[controller_sel].dat_r)
        else:
            self.comb += [
                master.dat_r.eq(self._controllers[0].dat_r)
                for master in self._masters
            ]
Exemple #6
0
    def do_finalize(self):
        nmasters = len(self.masters)

        m_ba, m_rca = self.split_master_addresses(self.bank_bits,
                                                  self.rca_bits,
                                                  self.cba_shift)

        controller = self.controller
        master_readys = [0] * nmasters
        master_wdata_readys = [0] * nmasters
        master_rdata_valids = [0] * nmasters

        arbiters = [
            roundrobin.RoundRobin(nmasters, roundrobin.SP_CE)
            for n in range(self.nbanks)
        ]
        self.submodules += arbiters

        rbank = Signal(max=self.nbanks)
        wbank = Signal(max=self.nbanks)
        for nb, arbiter in enumerate(arbiters):
            bank = getattr(controller, "bank" + str(nb))

            # for each master, determine if another bank locks it
            master_locked = []
            for nm, master in enumerate(self.masters):
                locked = Signal()
                if not self.controller.settings.with_reordering:
                    for other_nb, other_arbiter in enumerate(arbiters):
                        if other_nb != nb:
                            other_bank = getattr(controller,
                                                 "bank" + str(other_nb))
                            locked = locked | (other_bank.lock &
                                               (other_arbiter.grant == nm))
                master_locked.append(locked)

            # arbitrate
            bank_selected = [(ba == nb) & ~locked
                             for ba, locked in zip(m_ba, master_locked)]
            bank_requested = [
                bs & master.cmd.valid
                for bs, master in zip(bank_selected, self.masters)
            ]
            self.comb += [
                arbiter.request.eq(Cat(*bank_requested)),
                arbiter.ce.eq(~bank.valid & ~bank.lock)
            ]

            # Get rdata source bank
            self.sync += If((arbiter.grant == nm) & bank.rdata_valid,
                            rbank.eq(nb))

            # Get wdata source bank
            self.sync += \
                If((arbiter.grant == nm) & bank.wdata_ready,
                    wbank.eq(nb)
                )

            # route requests
            self.comb += [
                bank.addr.eq(Array(m_rca)[arbiter.grant]),
                bank.we.eq(Array(self.masters)[arbiter.grant].cmd.we),
                bank.valid.eq(Array(bank_requested)[arbiter.grant])
            ]
            master_readys = [
                master_ready |
                ((arbiter.grant == nm) & bank_selected[nm] & bank.ready)
                for nm, master_ready in enumerate(master_readys)
            ]
            master_wdata_readys = [
                master_wdata_ready | ((arbiter.grant == nm) & bank.wdata_ready)
                for nm, master_wdata_ready in enumerate(master_wdata_readys)
            ]
            master_rdata_valids = [
                master_rdata_valid | ((arbiter.grant == nm) & bank.rdata_valid)
                for nm, master_rdata_valid in enumerate(master_rdata_valids)
            ]

        for nm, master_wdata_ready in enumerate(master_wdata_readys):
            for i in range(self.write_latency):
                new_master_wdata_ready = Signal()
                self.sync += new_master_wdata_ready.eq(master_wdata_ready)
                master_wdata_ready = new_master_wdata_ready
            master_wdata_readys[nm] = master_wdata_ready

        for nm, master_rdata_valid in enumerate(master_rdata_valids):
            for i in range(self.read_latency):
                new_master_rdata_valid = Signal()
                self.sync += new_master_rdata_valid.eq(master_rdata_valid)
                master_rdata_valid = new_master_rdata_valid
            master_rdata_valids[nm] = master_rdata_valid

        # Delay bank output to match rvalid
        for i in range(self.read_latency - 1):
            new_master_rbank = Signal(max=self.nbanks)
            self.sync += new_master_rbank.eq(rbank)
            rbank = new_master_rbank
        # Delay wbank output to match wready
        for i in range(self.write_latency - 1):
            new_master_wbank = Signal(max=self.nbanks)
            self.sync += new_master_wbank.eq(wbank)
            wbank = new_master_wbank

        for master, master_ready in zip(self.masters, master_readys):
            self.comb += master.cmd.ready.eq(master_ready)
        for master, master_wdata_ready in zip(self.masters,
                                              master_wdata_readys):
            self.comb += master.wdata.ready.eq(master_wdata_ready)
        for master, master_rdata_valid in zip(self.masters,
                                              master_rdata_valids):
            self.comb += master.rdata.valid.eq(master_rdata_valid)

        # route data writes
        wdata_cases = {}
        for nm, master in enumerate(self.masters):
            wdata_cases[2**nm] = [
                controller.wdata.eq(master.wdata.data),
                controller.wdata_we.eq(master.wdata.we)
            ]
        wdata_cases["default"] = [
            controller.wdata.eq(0),
            controller.wdata_we.eq(0)
        ]
        self.comb += Case(Cat(*master_wdata_readys), wdata_cases)

        # route data reads
        for master in self.masters:
            self.comb += master.rdata.data.eq(self.controller.rdata)
            if hasattr(master.rdata, "bank"):
                self.comb += master.rdata.bank.eq(rbank)
                self.comb += master.wdata.bank.eq(wbank)