sdram/lasmicon: create a separate file for the crossbar and remove it from lasmibus

This commit is contained in:
Florent Kermarrec 2015-03-02 09:18:32 +01:00
parent 7300879b7f
commit c0b38e4905
3 changed files with 178 additions and 171 deletions

View file

@ -33,176 +33,6 @@ class Interface(Record):
]
Record.__init__(self, layout)
def _getattr_all(l, attr):
it = iter(l)
r = getattr(next(it), attr)
for e in it:
if getattr(e, attr) != r:
raise ValueError
return r
class Crossbar(Module):
def __init__(self, controllers, cba_shift):
self._controllers = controllers
self._cba_shift = cba_shift
self._rca_bits = _getattr_all(controllers, "aw")
self._dw = _getattr_all(controllers, "dw")
self._nbanks = _getattr_all(controllers, "nbanks")
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)
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(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(optree("|", dat_w_maskselect)),
controller.dat_we.eq(optree("|", 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 _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
m_ca = [] # controller address
m_ba = [] # bank address
m_rca = [] # row and column address
for master in self._masters:
cba = Signal(self._controller_bits + self._bank_bits)
rca = Signal(self._rca_bits)
cba_upper = cba_shift + controller_bits + bank_bits
self.comb += cba.eq(master.adr[cba_shift:cba_upper])
if cba_shift < self._rca_bits:
if cba_shift:
self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
else:
self.comb += rca.eq(master.adr[cba_upper:])
else:
self.comb += rca.eq(master.adr[:cba_shift])
if self._controller_bits:
ca = Signal(self._controller_bits)
ba = Signal(self._bank_bits)
self.comb += Cat(ba, ca).eq(cba)
else:
ca = None
ba = cba
m_ca.append(ca)
m_ba.append(ba)
m_rca.append(rca)
return m_ca, m_ba, m_rca
class Initiator(Module):
def __init__(self, generator, bus):
self.generator = generator

View file

@ -0,0 +1,176 @@
from migen.fhdl.std import *
from migen.genlib import roundrobin
from migen.genlib.record import *
from migen.genlib.misc import optree
from misoclib.mem.sdram.bus.lasmibus import Interface
def _getattr_all(l, attr):
it = iter(l)
r = getattr(next(it), attr)
for e in it:
if getattr(e, attr) != r:
raise ValueError
return r
class Crossbar(Module):
def __init__(self, controllers, cba_shift):
self._controllers = controllers
self._cba_shift = cba_shift
self._rca_bits = _getattr_all(controllers, "aw")
self._dw = _getattr_all(controllers, "dw")
self._nbanks = _getattr_all(controllers, "nbanks")
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)
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(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(optree("|", dat_w_maskselect)),
controller.dat_we.eq(optree("|", 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 _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
m_ca = [] # controller address
m_ba = [] # bank address
m_rca = [] # row and column address
for master in self._masters:
cba = Signal(self._controller_bits + self._bank_bits)
rca = Signal(self._rca_bits)
cba_upper = cba_shift + controller_bits + bank_bits
self.comb += cba.eq(master.adr[cba_shift:cba_upper])
if cba_shift < self._rca_bits:
if cba_shift:
self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
else:
self.comb += rca.eq(master.adr[cba_upper:])
else:
self.comb += rca.eq(master.adr[:cba_shift])
if self._controller_bits:
ca = Signal(self._controller_bits)
ba = Signal(self._bank_bits)
self.comb += Cat(ba, ca).eq(cba)
else:
ca = None
ba = cba
m_ca.append(ca)
m_ba.append(ba)
m_rca.append(rca)
return m_ca, m_ba, m_rca

View file

@ -4,6 +4,7 @@ from migen.bus import wishbone, csr
from misoclib.mem.sdram.bus import dfi, lasmibus
from misoclib.mem.sdram.phy import dfii
from misoclib.mem.sdram import minicon, lasmicon
from misoclib.mem.sdram.lasmicon import crossbar
from misoclib.mem.sdram.frontend import memtest, wishbone2lasmi
from misoclib.soc import SoC, mem_decoder
@ -47,7 +48,7 @@ class SDRAMSoC(SoC):
self.submodules.lasmicon = lasmicon.LASMIcon(phy_settings, sdram_geom, sdram_timing)
self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave)
self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], self.lasmicon.nrowbits)
self.submodules.lasmixbar = crossbar.Crossbar([self.lasmicon.lasmic], self.lasmicon.nrowbits)
if self.with_memtest:
self.submodules.memtest_w = memtest.MemtestWriter(self.lasmixbar.get_master())