lasmibus/Crossbar: more flexible master assignment

This commit is contained in:
Sebastien Bourdeauducq 2013-11-23 17:51:22 +01:00
parent 8efd9d11dc
commit 948d7e7332

View file

@ -41,39 +41,51 @@ def _getattr_all(l, attr):
return r return r
class Crossbar(Module): class Crossbar(Module):
def __init__(self, controllers, nmasters, cba_shift): def __init__(self, controllers, cba_shift):
ncontrollers = len(controllers) self._controllers = controllers
rca_bits = _getattr_all(controllers, "aw") self._cba_shift = cba_shift
dw = _getattr_all(controllers, "dw")
nbanks = _getattr_all(controllers, "nbanks")
req_queue_size = _getattr_all(controllers, "req_queue_size")
read_latency = _getattr_all(controllers, "read_latency")
write_latency = _getattr_all(controllers, "write_latency")
bank_bits = log2_int(nbanks, False) self._rca_bits = _getattr_all(controllers, "aw")
controller_bits = log2_int(ncontrollers, False) self._dw = _getattr_all(controllers, "dw")
self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, req_queue_size, read_latency, write_latency) self._nbanks = _getattr_all(controllers, "nbanks")
for i in range(nmasters)] self._req_queue_size = _getattr_all(controllers, "req_queue_size")
self._read_latency = _getattr_all(controllers, "read_latency")
self._write_latency = _getattr_all(controllers, "write_latency")
### self._bank_bits = log2_int(self._nbanks, False)
self._controller_bits = log2_int(len(self._controllers), False)
m_ca, m_ba, m_rca = self._split_master_addresses(controller_bits, bank_bits, rca_bits, cba_shift) self._masters = []
def get_master(self):
if self.finalized:
raise FinalizeError
lasmi_master = Interface(self._rca_bits + self._bank_bits + self._controller_bits,
self._dw, 1, self._req_queue_size, self._read_latency, self._write_latency)
self._masters.append(lasmi_master)
return lasmi_master
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(controllers): for nc, controller in enumerate(self._controllers):
if controller_bits: if self._controller_bits:
controller_selected = [ca == nc for ca in m_ca] controller_selected = [ca == nc for ca in m_ca]
else: else:
controller_selected = [1]*nmasters controller_selected = [1]*nmasters
master_req_acks = [0]*nmasters master_req_acks = [0]*nmasters
master_dat_acks = [0]*nmasters master_dat_acks = [0]*nmasters
rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(nbanks)] rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
self.submodules += rrs self.submodules += rrs
for nb, rr in enumerate(rrs): for nb, rr in enumerate(rrs):
bank = getattr(controller, "bank"+str(nb)) bank = getattr(controller, "bank"+str(nb))
# for each master, determine if another bank locks it # for each master, determine if another bank locks it
master_locked = [] master_locked = []
for nm, master in enumerate(self.masters): for nm, master in enumerate(self._masters):
locked = 0 locked = 0
for other_nb, other_rr in enumerate(rrs): for other_nb, other_rr in enumerate(rrs):
if other_nb != nb: if other_nb != nb:
@ -83,7 +95,7 @@ class Crossbar(Module):
# arbitrate # arbitrate
bank_selected = [cs & (ba == nb) & ~locked for cs, ba, locked in zip(controller_selected, m_ba, master_locked)] 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)] bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self._masters)]
self.comb += [ self.comb += [
rr.request.eq(Cat(*bank_requested)), rr.request.eq(Cat(*bank_requested)),
rr.ce.eq(~bank.stb & ~bank.lock) rr.ce.eq(~bank.stb & ~bank.lock)
@ -92,7 +104,7 @@ class Crossbar(Module):
# route requests # route requests
self.comb += [ self.comb += [
bank.adr.eq(Array(m_rca)[rr.grant]), bank.adr.eq(Array(m_rca)[rr.grant]),
bank.we.eq(Array(self.masters)[rr.grant].we), bank.we.eq(Array(self._masters)[rr.grant].we),
bank.stb.eq(Array(bank_requested)[rr.grant]) bank.stb.eq(Array(bank_requested)[rr.grant])
] ]
master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack) master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
@ -100,20 +112,20 @@ class Crossbar(Module):
master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack) master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack)
for nm, master_dat_ack in enumerate(master_dat_acks)] for nm, master_dat_ack in enumerate(master_dat_acks)]
self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self.masters, master_req_acks)] 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_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self.masters, master_dat_acks)] self.comb += [master.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self._masters, master_dat_acks)]
# route data writes # route data writes
controller_selected_wl = controller_selected controller_selected_wl = controller_selected
for i in range(write_latency): for i in range(self._write_latency):
n_controller_selected_wl = [Signal() for i in range(nmasters)] 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)] self.sync += [n.eq(o) for n, o in zip(n_controller_selected_wl, controller_selected_wl)]
controller_selected_wl = n_controller_selected_wl controller_selected_wl = n_controller_selected_wl
dat_w_maskselect = [] dat_w_maskselect = []
dat_we_maskselect = [] dat_we_maskselect = []
for master, selected in zip(self.masters, controller_selected_wl): for master, selected in zip(self._masters, controller_selected_wl):
o_dat_w = Signal(dw) o_dat_w = Signal(self._dw)
o_dat_we = Signal(dw//8) o_dat_we = Signal(self._dw//8)
self.comb += If(selected, self.comb += If(selected,
o_dat_w.eq(master.dat_w), o_dat_w.eq(master.dat_w),
o_dat_we.eq(master.dat_we) o_dat_we.eq(master.dat_we)
@ -126,31 +138,31 @@ class Crossbar(Module):
] ]
# route data reads # route data reads
if controller_bits: if self._controller_bits:
for master in self.masters: for master in self._masters:
controller_sel = Signal(controller_bits) controller_sel = Signal(self._controller_bits)
for nc, controller in enumerate(controllers): for nc, controller in enumerate(self._controllers):
for nb in range(nbanks): for nb in range(nbanks):
bank = getattr(controller, "bank"+str(nb)) bank = getattr(controller, "bank"+str(nb))
self.comb += If(bank.stb & bank.ack, controller_sel.eq(nc)) self.comb += If(bank.stb & bank.ack, controller_sel.eq(nc))
for i in range(read_latency): for i in range(self._read_latency):
n_controller_sel = Signal(controller_bits) n_controller_sel = Signal(self._controller_bits)
self.sync += n_controller_sel.eq(controller_sel) self.sync += n_controller_sel.eq(controller_sel)
controller_sel = n_controller_sel controller_sel = n_controller_sel
self.comb += master.dat_r.eq(Array(controllers)[controller_sel].dat_r) self.comb += master.dat_r.eq(Array(self._controllers)[controller_sel].dat_r)
else: else:
self.comb += [master.dat_r.eq(controllers[0].dat_r) for master in self.masters] self.comb += [master.dat_r.eq(self._controllers[0].dat_r) for master in self._masters]
def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift): def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
m_ca = [] # controller address m_ca = [] # controller address
m_ba = [] # bank address m_ba = [] # bank address
m_rca = [] # row and column address m_rca = [] # row and column address
for master in self.masters: for master in self._masters:
cba = Signal(controller_bits + bank_bits) cba = Signal(self._controller_bits + self._bank_bits)
rca = Signal(rca_bits) rca = Signal(self._rca_bits)
cba_upper = cba_shift + controller_bits + bank_bits cba_upper = cba_shift + controller_bits + bank_bits
self.comb += cba.eq(master.adr[cba_shift:cba_upper]) self.comb += cba.eq(master.adr[cba_shift:cba_upper])
if cba_shift < rca_bits: if cba_shift < self._rca_bits:
if cba_shift: if cba_shift:
self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:])) self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
else: else:
@ -158,9 +170,9 @@ class Crossbar(Module):
else: else:
self.comb += rca.eq(master.adr[:cba_shift]) self.comb += rca.eq(master.adr[:cba_shift])
if controller_bits: if self._controller_bits:
ca = Signal(controller_bits) ca = Signal(self._controller_bits)
ba = Signal(bank_bits) ba = Signal(self._bank_bits)
self.comb += Cat(ba, ca).eq(cba) self.comb += Cat(ba, ca).eq(cba)
else: else:
ca = None ca = None