mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
sdram/lasmicon: create a separate file for the crossbar and remove it from lasmibus
This commit is contained in:
parent
7300879b7f
commit
c0b38e4905
3 changed files with 178 additions and 171 deletions
|
@ -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
|
||||
|
|
176
misoclib/mem/sdram/lasmicon/crossbar.py
Normal file
176
misoclib/mem/sdram/lasmicon/crossbar.py
Normal 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
|
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue