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])), ]
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))
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 ]
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)
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 ]
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)