sdram: move lasmibus to core, rename crossbar to lasmixbar and move it to core, move...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 3 Mar 2015 08:49:57 +0000 (09:49 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 3 Mar 2015 08:55:25 +0000 (09:55 +0100)
19 files changed:
misoclib/mem/sdram/bus/dfi.py [deleted file]
misoclib/mem/sdram/bus/lasmibus.py [deleted file]
misoclib/mem/sdram/core/__init__.py
misoclib/mem/sdram/core/lasmibus.py [new file with mode: 0644]
misoclib/mem/sdram/core/lasmicon/__init__.py
misoclib/mem/sdram/core/lasmicon/crossbar.py [deleted file]
misoclib/mem/sdram/core/lasmixbar.py [new file with mode: 0644]
misoclib/mem/sdram/core/minicon/__init__.py
misoclib/mem/sdram/phy/dfi.py [new file with mode: 0644]
misoclib/mem/sdram/phy/dfii.py
misoclib/mem/sdram/phy/gensdrphy.py
misoclib/mem/sdram/phy/k7ddrphy.py
misoclib/mem/sdram/phy/s6ddrphy.py
misoclib/mem/sdram/test/abstract_transactions_lasmi.py
misoclib/mem/sdram/test/bankmachine_tb.py
misoclib/mem/sdram/test/lasmicon_df_tb.py
misoclib/mem/sdram/test/lasmicon_tb.py
misoclib/mem/sdram/test/lasmicon_wb.py
misoclib/soc/sdram.py

diff --git a/misoclib/mem/sdram/bus/dfi.py b/misoclib/mem/sdram/bus/dfi.py
deleted file mode 100644 (file)
index fa80f9c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.record import *
-
-def phase_cmd_description(a, ba):
-       return [
-               ("address",                     a,              DIR_M_TO_S),
-               ("bank",                        ba,             DIR_M_TO_S),
-               ("cas_n",                       1,              DIR_M_TO_S),
-               ("cs_n",                        1,              DIR_M_TO_S),
-               ("ras_n",                       1,              DIR_M_TO_S),
-               ("we_n",                        1,              DIR_M_TO_S),
-               ("cke",                         1,              DIR_M_TO_S),
-               ("odt",                         1,              DIR_M_TO_S),
-               ("reset_n",                     1,              DIR_M_TO_S)
-       ]
-
-def phase_wrdata_description(d):
-       return [
-               ("wrdata",                      d,              DIR_M_TO_S),
-               ("wrdata_en",           1,              DIR_M_TO_S),
-               ("wrdata_mask",         d//8,   DIR_M_TO_S)
-       ]
-
-def phase_rddata_description(d):
-       return [
-               ("rddata_en",           1,              DIR_M_TO_S),
-               ("rddata",                      d,              DIR_S_TO_M),
-               ("rddata_valid",        1,              DIR_S_TO_M)
-       ]
-
-def phase_description(a, ba, d):
-       r = phase_cmd_description(a, ba)
-       r += phase_wrdata_description(d)
-       r += phase_rddata_description(d)
-       return r
-
-class Interface(Record):
-       def __init__(self, a, ba, d, nphases=1):
-               layout = [("p"+str(i), phase_description(a, ba, d)) for i in range(nphases)]
-               Record.__init__(self, layout)
-               self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
-               for p in self.phases:
-                       p.cas_n.reset = 1
-                       p.cs_n.reset = 1
-                       p.ras_n.reset = 1
-                       p.we_n.reset = 1
-
-       # Returns pairs (DFI-mandated signal name, Migen signal object)
-       def get_standard_names(self, m2s=True, s2m=True):
-               r = []
-               add_suffix = len(self.phases) > 1
-               for n, phase in enumerate(self.phases):
-                       for field, size, direction in phase.layout:
-                               if (m2s and direction == DIR_M_TO_S) or (s2m and direction == DIR_S_TO_M):
-                                       if add_suffix:
-                                               if direction == DIR_M_TO_S:
-                                                       suffix = "_p" + str(n)
-                                               else:
-                                                       suffix = "_w" + str(n)
-                                       else:
-                                               suffix = ""
-                                       r.append(("dfi_" + field + suffix, getattr(phase, field)))
-               return r
-
-class Interconnect(Module):
-       def __init__(self, master, slave):
-               self.comb += master.connect(slave)
diff --git a/misoclib/mem/sdram/bus/lasmibus.py b/misoclib/mem/sdram/bus/lasmibus.py
deleted file mode 100644 (file)
index 7578d0e..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import *
-from migen.genlib import roundrobin
-from migen.genlib.record import *
-from migen.genlib.misc import optree
-
-class Interface(Record):
-       def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
-               self.aw = aw
-               self.dw = dw
-               self.nbanks = nbanks
-               self.req_queue_size = req_queue_size
-               self.read_latency = read_latency
-               self.write_latency = write_latency
-
-               bank_layout = [
-                       ("adr",                 aw,             DIR_M_TO_S),
-                       ("we",                  1,              DIR_M_TO_S),
-                       ("stb",                 1,              DIR_M_TO_S),
-                       ("req_ack",             1,              DIR_S_TO_M),
-                       ("dat_w_ack",   1,              DIR_S_TO_M),
-                       ("dat_r_ack",   1,              DIR_S_TO_M),
-                       ("lock",                1,              DIR_S_TO_M)
-               ]
-               if nbanks > 1:
-                       layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
-               else:
-                       layout = bank_layout
-               layout += [
-                       ("dat_w",       dw,     DIR_M_TO_S),
-                       ("dat_we",      dw//8,  DIR_M_TO_S),
-                       ("dat_r",       dw,     DIR_S_TO_M)
-               ]
-               Record.__init__(self, layout)
-
-class Initiator(Module):
-       def __init__(self, generator, bus):
-               self.generator = generator
-               self.bus = bus
-               self.transaction_start = 0
-               self.transaction = None
-               self.transaction_end = None
-
-       def do_simulation(self, selfp):
-               selfp.bus.dat_w = 0
-               selfp.bus.dat_we = 0
-
-               if self.transaction is not None:
-                       if selfp.bus.req_ack:
-                               selfp.bus.stb = 0
-                       if selfp.bus.dat_ack:
-                               if isinstance(self.transaction, TRead):
-                                       self.transaction_end = selfp.simulator.cycle_counter + self.bus.read_latency
-                               else:
-                                       self.transaction_end = selfp.simulator.cycle_counter + self.bus.write_latency - 1
-
-               if self.transaction is None or selfp.simulator.cycle_counter == self.transaction_end:
-                       if self.transaction is not None:
-                               self.transaction.latency = selfp.simulator.cycle_counter - self.transaction_start - 1
-                               if isinstance(self.transaction, TRead):
-                                       self.transaction.data = selfp.bus.dat_r
-                               else:
-                                       selfp.bus.dat_w = self.transaction.data
-                                       selfp.bus.dat_we = self.transaction.sel
-                       try:
-                               self.transaction = next(self.generator)
-                       except StopIteration:
-                               raise StopSimulation
-                       if self.transaction is not None:
-                               self.transaction_start = selfp.simulator.cycle_counter
-                               selfp.bus.stb = 1
-                               selfp.bus.adr = self.transaction.address
-                               if isinstance(self.transaction, TRead):
-                                       selfp.bus.we = 0
-                               else:
-                                       selfp.bus.we = 1
-
-class TargetModel:
-       def __init__(self):
-               self.last_bank = 0
-
-       def read(self, bank, address):
-               return 0
-
-       def write(self, bank, address, data, we):
-               pass
-
-       # Round-robin scheduling
-       def select_bank(self, pending_banks):
-               if not pending_banks:
-                       return -1
-               self.last_bank += 1
-               if self.last_bank > max(pending_banks):
-                       self.last_bank = 0
-               while self.last_bank not in pending_banks:
-                       self.last_bank += 1
-               return self.last_bank
-
-class _ReqFIFO(Module):
-       def __init__(self, req_queue_size, bank):
-               self.req_queue_size = req_queue_size
-               self.bank = bank
-               self.contents = []
-
-       def do_simulation(self, selfp):
-               if len(self.contents) < self.req_queue_size:
-                       if selfp.bank.stb:
-                               self.contents.append((selfp.bank.we, selfp.bank.adr))
-                       selfp.bank.req_ack = 1
-               else:
-                       selfp.bank.req_ack = 0
-               selfp.bank.lock = bool(self.contents)
-       do_simulation.passive = True
-
-class Target(Module):
-       def __init__(self, model, *ifargs, **ifkwargs):
-               self.model = model
-               self.bus = Interface(*ifargs, **ifkwargs)
-               self.req_fifos = [_ReqFIFO(self.bus.req_queue_size, getattr(self.bus, "bank"+str(nb)))
-                       for nb in range(self.bus.nbanks)]
-               self.submodules += self.req_fifos
-               self.rd_pipeline = [None]*self.bus.read_latency
-               self.wr_pipeline = [None]*(self.bus.write_latency + 1)
-
-       def do_simulation(self, selfp):
-               # determine banks with pending requests
-               pending_banks = set(nb for nb, rf in enumerate(self.req_fifos) if rf.contents)
-
-               # issue new transactions
-               selected_bank_n = self.model.select_bank(pending_banks)
-               selected_transaction = None
-               for nb in range(self.bus.nbanks):
-                       bank = getattr(selfp.bus, "bank"+str(nb))
-                       if nb == selected_bank_n:
-                               bank.dat_ack = 1
-                               selected_transaction = self.req_fifos[nb].contents.pop(0)
-                       else:
-                               bank.dat_ack = 0
-
-               rd_transaction = None
-               wr_transaction = None
-               if selected_bank_n >= 0:
-                       we, adr = selected_transaction
-                       if we:
-                               wr_transaction = selected_bank_n, adr
-                       else:
-                               rd_transaction = selected_bank_n, adr
-
-               # data pipeline
-               self.rd_pipeline.append(rd_transaction)
-               self.wr_pipeline.append(wr_transaction)
-               done_rd_transaction = self.rd_pipeline.pop(0)
-               done_wr_transaction = self.wr_pipeline.pop(0)
-               if done_rd_transaction is not None:
-                       selfp.bus.dat_r = self.model.read(done_rd_transaction[0], done_rd_transaction[1])
-               if done_wr_transaction is not None:
-                       self.model.write(done_wr_transaction[0], done_wr_transaction[1],
-                               selfp.bus.dat_w, selfp.bus.dat_we)
-       do_simulation.passive = True
index a4b526c5efd825dd8dbee3dfab1a9bcfccc5746f..f31277528a3c339c36aa04f464fda12ee951ac74 100644 (file)
@@ -4,7 +4,7 @@ from migen.bank.description import *
 
 from misoclib.mem.sdram.phy import dfii
 from misoclib.mem.sdram.core import minicon, lasmicon
-from misoclib.mem.sdram.core.lasmicon.crossbar import Crossbar
+from misoclib.mem.sdram.core import lasmixbar
 
 class SDRAMCore(Module, AutoCSR):
        def __init__(self, phy, ramcon_type, sdram_geom, sdram_timing, **kwargs):
@@ -18,7 +18,7 @@ class SDRAMCore(Module, AutoCSR):
                        self.submodules.controller = controller = lasmicon.LASMIcon(phy.settings, sdram_geom, sdram_timing, **kwargs)
                        self.comb += Record.connect(controller.dfi, self.dfii.slave)
 
-                       self.submodules.crossbar = crossbar = Crossbar([controller.lasmic], controller.nrowbits)
+                       self.submodules.crossbar = crossbar = lasmixbar.LASMIxbar([controller.lasmic], controller.nrowbits)
 
                # MINICON
                elif ramcon_type == "minicon":
diff --git a/misoclib/mem/sdram/core/lasmibus.py b/misoclib/mem/sdram/core/lasmibus.py
new file mode 100644 (file)
index 0000000..7578d0e
--- /dev/null
@@ -0,0 +1,159 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import *
+from migen.genlib import roundrobin
+from migen.genlib.record import *
+from migen.genlib.misc import optree
+
+class Interface(Record):
+       def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
+               self.aw = aw
+               self.dw = dw
+               self.nbanks = nbanks
+               self.req_queue_size = req_queue_size
+               self.read_latency = read_latency
+               self.write_latency = write_latency
+
+               bank_layout = [
+                       ("adr",                 aw,             DIR_M_TO_S),
+                       ("we",                  1,              DIR_M_TO_S),
+                       ("stb",                 1,              DIR_M_TO_S),
+                       ("req_ack",             1,              DIR_S_TO_M),
+                       ("dat_w_ack",   1,              DIR_S_TO_M),
+                       ("dat_r_ack",   1,              DIR_S_TO_M),
+                       ("lock",                1,              DIR_S_TO_M)
+               ]
+               if nbanks > 1:
+                       layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
+               else:
+                       layout = bank_layout
+               layout += [
+                       ("dat_w",       dw,     DIR_M_TO_S),
+                       ("dat_we",      dw//8,  DIR_M_TO_S),
+                       ("dat_r",       dw,     DIR_S_TO_M)
+               ]
+               Record.__init__(self, layout)
+
+class Initiator(Module):
+       def __init__(self, generator, bus):
+               self.generator = generator
+               self.bus = bus
+               self.transaction_start = 0
+               self.transaction = None
+               self.transaction_end = None
+
+       def do_simulation(self, selfp):
+               selfp.bus.dat_w = 0
+               selfp.bus.dat_we = 0
+
+               if self.transaction is not None:
+                       if selfp.bus.req_ack:
+                               selfp.bus.stb = 0
+                       if selfp.bus.dat_ack:
+                               if isinstance(self.transaction, TRead):
+                                       self.transaction_end = selfp.simulator.cycle_counter + self.bus.read_latency
+                               else:
+                                       self.transaction_end = selfp.simulator.cycle_counter + self.bus.write_latency - 1
+
+               if self.transaction is None or selfp.simulator.cycle_counter == self.transaction_end:
+                       if self.transaction is not None:
+                               self.transaction.latency = selfp.simulator.cycle_counter - self.transaction_start - 1
+                               if isinstance(self.transaction, TRead):
+                                       self.transaction.data = selfp.bus.dat_r
+                               else:
+                                       selfp.bus.dat_w = self.transaction.data
+                                       selfp.bus.dat_we = self.transaction.sel
+                       try:
+                               self.transaction = next(self.generator)
+                       except StopIteration:
+                               raise StopSimulation
+                       if self.transaction is not None:
+                               self.transaction_start = selfp.simulator.cycle_counter
+                               selfp.bus.stb = 1
+                               selfp.bus.adr = self.transaction.address
+                               if isinstance(self.transaction, TRead):
+                                       selfp.bus.we = 0
+                               else:
+                                       selfp.bus.we = 1
+
+class TargetModel:
+       def __init__(self):
+               self.last_bank = 0
+
+       def read(self, bank, address):
+               return 0
+
+       def write(self, bank, address, data, we):
+               pass
+
+       # Round-robin scheduling
+       def select_bank(self, pending_banks):
+               if not pending_banks:
+                       return -1
+               self.last_bank += 1
+               if self.last_bank > max(pending_banks):
+                       self.last_bank = 0
+               while self.last_bank not in pending_banks:
+                       self.last_bank += 1
+               return self.last_bank
+
+class _ReqFIFO(Module):
+       def __init__(self, req_queue_size, bank):
+               self.req_queue_size = req_queue_size
+               self.bank = bank
+               self.contents = []
+
+       def do_simulation(self, selfp):
+               if len(self.contents) < self.req_queue_size:
+                       if selfp.bank.stb:
+                               self.contents.append((selfp.bank.we, selfp.bank.adr))
+                       selfp.bank.req_ack = 1
+               else:
+                       selfp.bank.req_ack = 0
+               selfp.bank.lock = bool(self.contents)
+       do_simulation.passive = True
+
+class Target(Module):
+       def __init__(self, model, *ifargs, **ifkwargs):
+               self.model = model
+               self.bus = Interface(*ifargs, **ifkwargs)
+               self.req_fifos = [_ReqFIFO(self.bus.req_queue_size, getattr(self.bus, "bank"+str(nb)))
+                       for nb in range(self.bus.nbanks)]
+               self.submodules += self.req_fifos
+               self.rd_pipeline = [None]*self.bus.read_latency
+               self.wr_pipeline = [None]*(self.bus.write_latency + 1)
+
+       def do_simulation(self, selfp):
+               # determine banks with pending requests
+               pending_banks = set(nb for nb, rf in enumerate(self.req_fifos) if rf.contents)
+
+               # issue new transactions
+               selected_bank_n = self.model.select_bank(pending_banks)
+               selected_transaction = None
+               for nb in range(self.bus.nbanks):
+                       bank = getattr(selfp.bus, "bank"+str(nb))
+                       if nb == selected_bank_n:
+                               bank.dat_ack = 1
+                               selected_transaction = self.req_fifos[nb].contents.pop(0)
+                       else:
+                               bank.dat_ack = 0
+
+               rd_transaction = None
+               wr_transaction = None
+               if selected_bank_n >= 0:
+                       we, adr = selected_transaction
+                       if we:
+                               wr_transaction = selected_bank_n, adr
+                       else:
+                               rd_transaction = selected_bank_n, adr
+
+               # data pipeline
+               self.rd_pipeline.append(rd_transaction)
+               self.wr_pipeline.append(wr_transaction)
+               done_rd_transaction = self.rd_pipeline.pop(0)
+               done_wr_transaction = self.wr_pipeline.pop(0)
+               if done_rd_transaction is not None:
+                       selfp.bus.dat_r = self.model.read(done_rd_transaction[0], done_rd_transaction[1])
+               if done_wr_transaction is not None:
+                       self.model.write(done_wr_transaction[0], done_wr_transaction[1],
+                               selfp.bus.dat_w, selfp.bus.dat_we)
+       do_simulation.passive = True
index bfe3a1309d5242d767e7329d96d436add216600d..393e218b320b7ac1aa68a816fd9e4fbfcdf25e95 100644 (file)
@@ -1,6 +1,7 @@
 from migen.fhdl.std import *
 
-from misoclib.mem.sdram.bus import dfi, lasmibus
+from misoclib.mem.sdram.phy import dfi
+from misoclib.mem.sdram.core import lasmibus
 from misoclib.mem.sdram.core.lasmicon.refresher import *
 from misoclib.mem.sdram.core.lasmicon.bankmachine import *
 from misoclib.mem.sdram.core.lasmicon.multiplexer import *
diff --git a/misoclib/mem/sdram/core/lasmicon/crossbar.py b/misoclib/mem/sdram/core/lasmicon/crossbar.py
deleted file mode 100644 (file)
index e441490..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-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
diff --git a/misoclib/mem/sdram/core/lasmixbar.py b/misoclib/mem/sdram/core/lasmixbar.py
new file mode 100644 (file)
index 0000000..d4da809
--- /dev/null
@@ -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.core.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 LASMIxbar(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
index 1f7660eeb6d4e894a8cbe536a80005525fe0cc0b..19a76373ef22143ecec22319edfdfcb318615783 100644 (file)
@@ -2,7 +2,7 @@ from migen.fhdl.std import *
 from migen.bus import wishbone
 from migen.genlib.fsm import FSM, NextState
 
-from misoclib.mem.sdram.bus import dfi as dfibus
+from misoclib.mem.sdram.phy import dfi as dfibus
 
 class _AddressSlicer:
        def __init__(self, col_a, bank_a, row_a, address_align):
diff --git a/misoclib/mem/sdram/phy/dfi.py b/misoclib/mem/sdram/phy/dfi.py
new file mode 100644 (file)
index 0000000..fa80f9c
--- /dev/null
@@ -0,0 +1,67 @@
+from migen.fhdl.std import *
+from migen.genlib.record import *
+
+def phase_cmd_description(a, ba):
+       return [
+               ("address",                     a,              DIR_M_TO_S),
+               ("bank",                        ba,             DIR_M_TO_S),
+               ("cas_n",                       1,              DIR_M_TO_S),
+               ("cs_n",                        1,              DIR_M_TO_S),
+               ("ras_n",                       1,              DIR_M_TO_S),
+               ("we_n",                        1,              DIR_M_TO_S),
+               ("cke",                         1,              DIR_M_TO_S),
+               ("odt",                         1,              DIR_M_TO_S),
+               ("reset_n",                     1,              DIR_M_TO_S)
+       ]
+
+def phase_wrdata_description(d):
+       return [
+               ("wrdata",                      d,              DIR_M_TO_S),
+               ("wrdata_en",           1,              DIR_M_TO_S),
+               ("wrdata_mask",         d//8,   DIR_M_TO_S)
+       ]
+
+def phase_rddata_description(d):
+       return [
+               ("rddata_en",           1,              DIR_M_TO_S),
+               ("rddata",                      d,              DIR_S_TO_M),
+               ("rddata_valid",        1,              DIR_S_TO_M)
+       ]
+
+def phase_description(a, ba, d):
+       r = phase_cmd_description(a, ba)
+       r += phase_wrdata_description(d)
+       r += phase_rddata_description(d)
+       return r
+
+class Interface(Record):
+       def __init__(self, a, ba, d, nphases=1):
+               layout = [("p"+str(i), phase_description(a, ba, d)) for i in range(nphases)]
+               Record.__init__(self, layout)
+               self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
+               for p in self.phases:
+                       p.cas_n.reset = 1
+                       p.cs_n.reset = 1
+                       p.ras_n.reset = 1
+                       p.we_n.reset = 1
+
+       # Returns pairs (DFI-mandated signal name, Migen signal object)
+       def get_standard_names(self, m2s=True, s2m=True):
+               r = []
+               add_suffix = len(self.phases) > 1
+               for n, phase in enumerate(self.phases):
+                       for field, size, direction in phase.layout:
+                               if (m2s and direction == DIR_M_TO_S) or (s2m and direction == DIR_S_TO_M):
+                                       if add_suffix:
+                                               if direction == DIR_M_TO_S:
+                                                       suffix = "_p" + str(n)
+                                               else:
+                                                       suffix = "_w" + str(n)
+                                       else:
+                                               suffix = ""
+                                       r.append(("dfi_" + field + suffix, getattr(phase, field)))
+               return r
+
+class Interconnect(Module):
+       def __init__(self, master, slave):
+               self.comb += master.connect(slave)
index c3fa216f97bc7ff8b46ef73352a7c7de39b73fc5..abe4ce3701a98abcde1e9242e8f2db6f94b8ba91 100644 (file)
@@ -1,7 +1,7 @@
 from migen.fhdl.std import *
 from migen.bank.description import *
 
-from misoclib.mem.sdram.bus import dfi
+from misoclib.mem.sdram.phy import dfi
 
 class PhaseInjector(Module, AutoCSR):
        def __init__(self, phase):
index f7af68d404dbcb7078ef8d88214042c17098188a..befd6509cbc9f0efcbd95e3e51cfeff8ffee7f4f 100644 (file)
@@ -25,7 +25,7 @@ from migen.fhdl.std import *
 from migen.genlib.record import *
 from migen.fhdl.specials import *
 
-from misoclib.mem.sdram.bus.dfi import *
+from misoclib.mem.sdram.phy.dfi import *
 from misoclib.mem import sdram
 
 class GENSDRPHY(Module):
index 420219445f57bbe3c82c4a4ef2ae72a23b807169..8d86931da070a8d65d0d13165878798432787bfb 100644 (file)
@@ -3,7 +3,7 @@
 from migen.fhdl.std import *
 from migen.bank.description import *
 
-from misoclib.mem.sdram.bus.dfi import *
+from misoclib.mem.sdram.phy.dfi import *
 from misoclib.mem import sdram
 
 class K7DDRPHY(Module, AutoCSR):
index 1d5fe0f73c4def01e887d36b4b39ca776189c1d9..aacdf04cbea7cf8c1972f08c673bb8fea51a91a4 100644 (file)
@@ -17,7 +17,7 @@
 from migen.fhdl.std import *
 from migen.genlib.record import *
 
-from misoclib.mem.sdram.bus.dfi import *
+from misoclib.mem.sdram.phy.dfi import *
 from misoclib.mem import sdram
 
 class S6DDRPHY(Module):
index 6bfb1fdbafb0452aa5112990e4a78589e0990e4e..cdd78e707c7491fff6722be43c81b1e036512f3e 100644 (file)
@@ -2,7 +2,7 @@ from migen.fhdl.std import *
 from migen.bus.transactions import *
 from migen.sim.generic import run_simulation
 
-from misoclib.mem.sdram.bus import lasmibus
+from misoclib.mem.sdram.core import lasmibus
 
 def my_generator(n):
        bank = n % 4
index 12ae5da0a91917191bd3a24d6088f32ff4e547b0..77841e433c4339f8be32958e5289c96fbb0a241e 100644 (file)
@@ -1,7 +1,7 @@
 from migen.fhdl.std import *
 from migen.sim.generic import run_simulation
 
-from misoclib.mem.sdram.bus import lasmibus
+from misoclib.mem.sdram.code import lasmibus
 from misoclib.mem.sdram.core.lasmicon.bankmachine import *
 
 from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger
index e06722f0c124b0214e79688e98ff01dd2c525d8b..d239d49a0dfc1107845a436cc8d9675b6ed3e711 100644 (file)
@@ -1,7 +1,7 @@
 from migen.fhdl.std import *
 from migen.sim.generic import run_simulation
 
-from misoclib.mem.sdram.bus import lasmibus
+from misoclib.mem.sdram.core import lasmibus
 from misoclib.mem.sdram.core.lasmicon import *
 from misoclib.mem.sdram.frontend import dma_lasmi
 
index a102b07c58b512a64cedff6767c444102e85453a..0352c0609962471378493eb158607678d323fd60 100644 (file)
@@ -1,7 +1,7 @@
 from migen.fhdl.std import *
 from migen.sim.generic import run_simulation
 
-from misoclib.mem.sdram.bus import lasmibus
+from misoclib.mem.sdram.core import lasmibus
 from misoclib.mem.sdram.core.lasmicon import *
 
 from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
index 978655dcbb1e1ae261c72863ccbe48fd79aefe2e..dae6c6342e00c78473e6605f9f01bda548fef174 100644 (file)
@@ -3,7 +3,7 @@ from migen.bus import wishbone
 from migen.bus.transactions import *
 from migen.sim.generic import run_simulation
 
-from misoclib.mem.sdram.bus import lasmibus
+from misoclib.mem.sdram.core import lasmibus
 from misoclib.mem.sdram.core.lasmicon import *
 from misoclib.mem.sdram.frontend import wishbone2lasmi
 
index ac4024c34332bca3bb9cfdd8fa0f64eb0367eb99..4acc42975014ff4b86b5f72e031a962023fc387d 100644 (file)
@@ -2,7 +2,6 @@ from migen.fhdl.std import *
 from migen.bus import wishbone, csr
 from migen.genlib.record import *
 
-from misoclib.mem.sdram.bus import dfi, lasmibus
 from misoclib.mem.sdram.core import SDRAMCore
 from misoclib.mem.sdram.frontend import memtest, wishbone2lasmi
 from misoclib.soc import SoC, mem_decoder