From e07e124118f1a5ce18a471fd70312a54ce8c0354 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 27 Feb 2015 16:55:27 +0100 Subject: [PATCH] sdram: import dfi, lasmibus, wishbone2lasmi from Migen in sdram/bus dir We will maybe move things, but at least it's in MiSoC now --- misoclib/gensoc/__init__.py | 4 +- misoclib/sdram/bus/dfi.py | 67 ++++ misoclib/sdram/bus/lasmibus.py | 309 ++++++++++++++++++ misoclib/sdram/bus/wishbone2lasmi.py | 171 ++++++++++ misoclib/sdram/dfii/__init__.py | 3 +- misoclib/sdram/lasmicon/__init__.py | 2 +- .../test/abstract_transactions_lasmi.py | 39 +++ misoclib/sdram/lasmicon/test/bankmachine.py | 2 +- misoclib/sdram/lasmicon/test/lasmicon.py | 2 +- misoclib/sdram/lasmicon/test/lasmicon_df.py | 2 +- misoclib/sdram/lasmicon/test/lasmicon_wb.py | 3 +- misoclib/sdram/minicon/__init__.py | 3 +- misoclib/sdram/phy/gensdrphy.py | 2 +- misoclib/sdram/phy/k7ddrphy.py | 2 +- misoclib/sdram/phy/s6ddrphy.py | 2 +- 15 files changed, 601 insertions(+), 12 deletions(-) create mode 100644 misoclib/sdram/bus/dfi.py create mode 100644 misoclib/sdram/bus/lasmibus.py create mode 100644 misoclib/sdram/bus/wishbone2lasmi.py create mode 100644 misoclib/sdram/lasmicon/test/abstract_transactions_lasmi.py diff --git a/misoclib/gensoc/__init__.py b/misoclib/gensoc/__init__.py index 4f18f455..28911bd1 100644 --- a/misoclib/gensoc/__init__.py +++ b/misoclib/gensoc/__init__.py @@ -4,11 +4,11 @@ from math import ceil from migen.fhdl.std import * from migen.bank import csrgen -from migen.bus import wishbone, csr, lasmibus, dfi -from migen.bus import wishbone2lasmi, wishbone2csr +from migen.bus import wishbone, csr, wishbone2csr from misoclib import uart, identifier, timer from misoclib.cpu import CPU, lm32, mor1kx +from misoclib.sdram.bus import dfi, lasmibus, wishbone2lasmi from misoclib.sdram import lasmicon from misoclib.sdram import dfii from misoclib.sdram import memtest diff --git a/misoclib/sdram/bus/dfi.py b/misoclib/sdram/bus/dfi.py new file mode 100644 index 00000000..fa80f9c8 --- /dev/null +++ b/misoclib/sdram/bus/dfi.py @@ -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) diff --git a/misoclib/sdram/bus/lasmibus.py b/misoclib/sdram/bus/lasmibus.py new file mode 100644 index 00000000..f1d3e29a --- /dev/null +++ b/misoclib/sdram/bus/lasmibus.py @@ -0,0 +1,309 @@ +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_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) + +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_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_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack) + 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.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self._masters, master_dat_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 + 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 diff --git a/misoclib/sdram/bus/wishbone2lasmi.py b/misoclib/sdram/bus/wishbone2lasmi.py new file mode 100644 index 00000000..a2110caf --- /dev/null +++ b/misoclib/sdram/bus/wishbone2lasmi.py @@ -0,0 +1,171 @@ +from migen.fhdl.std import * +from migen.bus import wishbone +from migen.bank.description import * +from migen.genlib.fsm import FSM, NextState +from migen.genlib.misc import split, displacer, chooser +from migen.genlib.record import Record, layout_len + +# cachesize (in 32-bit words) is the size of the data store, must be a power of 2 +class WB2LASMI(Module, AutoCSR): + def __init__(self, cachesize, lasmim): + self._cachesize = CSRStatus(8, reset=log2_int(cachesize)) + self.wishbone = wishbone.Interface() + + ### + + data_width = flen(self.wishbone.dat_r) + if lasmim.dw > data_width and (lasmim.dw % data_width) != 0: + raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width)) + if lasmim.dw < data_width and (data_width % lasmim.dw) != 0: + raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw)) + + # Split address: + # TAG | LINE NUMBER | LINE OFFSET + offsetbits = log2_int(max(lasmim.dw//data_width, 1)) + addressbits = lasmim.aw + offsetbits + linebits = log2_int(cachesize) - offsetbits + tagbits = addressbits - linebits + wordbits = log2_int(max(data_width//lasmim.dw, 1)) + adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) + word = Signal(wordbits) if wordbits else None + + # Data memory + data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits) + data_port = data_mem.get_port(write_capable=True, we_granularity=8) + self.specials += data_mem, data_port + + write_from_lasmi = Signal() + write_to_lasmi = Signal() + if adr_offset is None: + adr_offset_r = None + else: + adr_offset_r = Signal(offsetbits) + self.sync += adr_offset_r.eq(adr_offset) + + self.comb += [ + data_port.adr.eq(adr_line), + If(write_from_lasmi, + displacer(lasmim.dat_r, word, data_port.dat_w), + displacer(Replicate(1, lasmim.dw//8), word, data_port.we) + ).Else( + data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))), + If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, + displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) + ) + ), + If(write_to_lasmi, + chooser(data_port.dat_r, word, lasmim.dat_w), + lasmim.dat_we.eq(2**(lasmim.dw//8)-1) + ), + chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) + ] + + + # Tag memory + tag_layout = [("tag", tagbits), ("dirty", 1)] + tag_mem = Memory(layout_len(tag_layout), 2**linebits) + tag_port = tag_mem.get_port(write_capable=True) + self.specials += tag_mem, tag_port + tag_do = Record(tag_layout) + tag_di = Record(tag_layout) + self.comb += [ + tag_do.raw_bits().eq(tag_port.dat_r), + tag_port.dat_w.eq(tag_di.raw_bits()) + ] + + self.comb += [ + tag_port.adr.eq(adr_line), + tag_di.tag.eq(adr_tag) + ] + if word is not None: + self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag)) + else: + self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag)) + + # Lasmim word computation, word_clr and word_inc will be simplified + # at synthesis when wordbits=0 + word_clr = Signal() + word_inc = Signal() + if word is not None: + self.sync += \ + If(word_clr, + word.eq(0), + ).Elif(word_inc, + word.eq(word+1) + ) + + def word_is_last(word): + if word is not None: + return word == 2**wordbits-1 + else: + return 1 + + # Control FSM + assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1) + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1) + fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1) + + fsm.act("IDLE", + If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")) + ) + fsm.act("TEST_HIT", + word_clr.eq(1), + If(tag_do.tag == adr_tag, + self.wishbone.ack.eq(1), + If(self.wishbone.we, + tag_di.dirty.eq(1), + tag_port.we.eq(1) + ), + NextState("IDLE") + ).Else( + If(tag_do.dirty, + NextState("EVICT_REQUEST") + ).Else( + NextState("REFILL_WRTAG") + ) + ) + ) + + fsm.act("EVICT_REQUEST", + lasmim.stb.eq(1), + lasmim.we.eq(1), + If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK")) + ) + fsm.act("EVICT_WAIT_DATA_ACK", + If(lasmim.dat_ack, NextState("EVICT_DATAD")) + ) + fsm.act("EVICT_DATA", + write_to_lasmi.eq(1), + word_inc.eq(1), + If(word_is_last(word), + NextState("REFILL_WRTAG"), + ).Else( + NextState("EVICT_REQUEST") + ) + ) + + fsm.act("REFILL_WRTAG", + # Write the tag first to set the LASMI address + tag_port.we.eq(1), + word_clr.eq(1), + NextState("REFILL_REQUEST") + ) + fsm.act("REFILL_REQUEST", + lasmim.stb.eq(1), + If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK")) + ) + fsm.act("REFILL_WAIT_DATA_ACK", + If(lasmim.dat_ack, NextState("REFILL_DATAD")) + ) + fsm.act("REFILL_DATA", + write_from_lasmi.eq(1), + word_inc.eq(1), + If(word_is_last(word), + NextState("TEST_HIT"), + ).Else( + NextState("REFILL_REQUEST") + ) + ) diff --git a/misoclib/sdram/dfii/__init__.py b/misoclib/sdram/dfii/__init__.py index ba53d376..e34414a1 100644 --- a/misoclib/sdram/dfii/__init__.py +++ b/misoclib/sdram/dfii/__init__.py @@ -1,7 +1,8 @@ from migen.fhdl.std import * -from migen.bus import dfi from migen.bank.description import * +from misoclib.sdram.bus import dfi + class PhaseInjector(Module, AutoCSR): def __init__(self, phase): self._command = CSRStorage(6) # cs, we, cas, ras, wren, rden diff --git a/misoclib/sdram/lasmicon/__init__.py b/misoclib/sdram/lasmicon/__init__.py index 1136bcfe..9db64134 100644 --- a/misoclib/sdram/lasmicon/__init__.py +++ b/misoclib/sdram/lasmicon/__init__.py @@ -1,6 +1,6 @@ from migen.fhdl.std import * -from migen.bus import dfi, lasmibus +from misoclib.sdram.bus import dfi, lasmibus from misoclib.sdram.lasmicon.refresher import * from misoclib.sdram.lasmicon.bankmachine import * from misoclib.sdram.lasmicon.multiplexer import * diff --git a/misoclib/sdram/lasmicon/test/abstract_transactions_lasmi.py b/misoclib/sdram/lasmicon/test/abstract_transactions_lasmi.py new file mode 100644 index 00000000..d41c894e --- /dev/null +++ b/misoclib/sdram/lasmicon/test/abstract_transactions_lasmi.py @@ -0,0 +1,39 @@ +from migen.fhdl.std import * +from migen.bus.transactions import * +from migen.sim.generic import run_simulation + +from misoclib.sdram.bus import lasmibus + +def my_generator(n): + bank = n % 4 + for x in range(4): + t = TWrite(4*bank+x, 0x1000*bank + 0x100*x) + yield t + print("{0}: Wrote in {1} cycle(s)".format(n, t.latency)) + + for x in range(4): + t = TRead(4*bank+x) + yield t + print("{0}: Read {1:x} in {2} cycle(s)".format(n, t.data, t.latency)) + assert(t.data == 0x1000*bank + 0x100*x) + +class MyModel(lasmibus.TargetModel): + def read(self, bank, address): + r = 0x1000*bank + 0x100*address + #print("read from bank {0} address {1} -> {2:x}".format(bank, address, r)) + return r + + def write(self, bank, address, data, we): + print("write to bank {0} address {1:x} data {2:x}".format(bank, address, data)) + assert(data == 0x1000*bank + 0x100*address) + +class TB(Module): + def __init__(self): + self.submodules.controller = lasmibus.Target(MyModel(), aw=4, dw=32, nbanks=4, req_queue_size=4, + read_latency=4, write_latency=1) + self.submodules.xbar = lasmibus.Crossbar([self.controller.bus], 2) + self.initiators = [lasmibus.Initiator(my_generator(n), self.xbar.get_master()) for n in range(4)] + self.submodules += self.initiators + +if __name__ == "__main__": + run_simulation(TB()) diff --git a/misoclib/sdram/lasmicon/test/bankmachine.py b/misoclib/sdram/lasmicon/test/bankmachine.py index a6719cf5..336c9017 100644 --- a/misoclib/sdram/lasmicon/test/bankmachine.py +++ b/misoclib/sdram/lasmicon/test/bankmachine.py @@ -1,7 +1,7 @@ from migen.fhdl.std import * -from migen.bus.lasmibus import * from migen.sim.generic import run_simulation +from misoclib.sdram.bus import lasmibus from misoclib.sdram.lasmicon.bankmachine import * from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger diff --git a/misoclib/sdram/lasmicon/test/lasmicon.py b/misoclib/sdram/lasmicon/test/lasmicon.py index e4cd0458..c83f1ba7 100644 --- a/misoclib/sdram/lasmicon/test/lasmicon.py +++ b/misoclib/sdram/lasmicon/test/lasmicon.py @@ -1,7 +1,7 @@ from migen.fhdl.std import * -from migen.bus.lasmibus import * from migen.sim.generic import run_simulation +from misoclib.sdram.bus import lasmibus from misoclib.sdram.lasmicon import * from common import sdram_phy, sdram_geom, sdram_timing, DFILogger diff --git a/misoclib/sdram/lasmicon/test/lasmicon_df.py b/misoclib/sdram/lasmicon/test/lasmicon_df.py index d2a4add1..53fb7ec4 100644 --- a/misoclib/sdram/lasmicon/test/lasmicon_df.py +++ b/misoclib/sdram/lasmicon/test/lasmicon_df.py @@ -1,8 +1,8 @@ from migen.fhdl.std import * -from migen.bus import lasmibus from migen.actorlib import dma_lasmi from migen.sim.generic import run_simulation +from misoclib.sdram.bus import lasmibus from misoclib.sdram.lasmicon import * from common import sdram_phy, sdram_geom, sdram_timing, DFILogger diff --git a/misoclib/sdram/lasmicon/test/lasmicon_wb.py b/misoclib/sdram/lasmicon/test/lasmicon_wb.py index 35d18d9b..cbaa218e 100644 --- a/misoclib/sdram/lasmicon/test/lasmicon_wb.py +++ b/misoclib/sdram/lasmicon/test/lasmicon_wb.py @@ -1,8 +1,9 @@ from migen.fhdl.std import * -from migen.bus import wishbone, wishbone2lasmi, lasmibus +from migen.bus import wishbone from migen.bus.transactions import * from migen.sim.generic import run_simulation +from misoclib.sdram.bus import lasmibus, wishbone2lasmi from misoclib.sdram.lasmicon import * from common import sdram_phy, sdram_geom, sdram_timing, DFILogger diff --git a/misoclib/sdram/minicon/__init__.py b/misoclib/sdram/minicon/__init__.py index f7baa2c2..71cbb611 100755 --- a/misoclib/sdram/minicon/__init__.py +++ b/misoclib/sdram/minicon/__init__.py @@ -1,8 +1,9 @@ from migen.fhdl.std import * from migen.bus import wishbone -from migen.bus import dfi as dfibus from migen.genlib.fsm import FSM, NextState +from misoclib.sdram.bus import dfi as dfibus + class _AddressSlicer: def __init__(self, col_a, bank_a, row_a, address_align): self.col_a = col_a diff --git a/misoclib/sdram/phy/gensdrphy.py b/misoclib/sdram/phy/gensdrphy.py index 9abd1d00..132dda9e 100644 --- a/misoclib/sdram/phy/gensdrphy.py +++ b/misoclib/sdram/phy/gensdrphy.py @@ -22,10 +22,10 @@ # from migen.fhdl.std import * -from migen.bus.dfi import * from migen.genlib.record import * from migen.fhdl.specials import * +from misoclib.sdram.bus.dfi import * from misoclib import sdram class GENSDRPHY(Module): diff --git a/misoclib/sdram/phy/k7ddrphy.py b/misoclib/sdram/phy/k7ddrphy.py index 436d0204..498532bb 100644 --- a/misoclib/sdram/phy/k7ddrphy.py +++ b/misoclib/sdram/phy/k7ddrphy.py @@ -1,9 +1,9 @@ # tCK=5ns CL=7 CWL=6 from migen.fhdl.std import * -from migen.bus.dfi import * from migen.bank.description import * +from misoclib.sdram.bus.dfi import * from misoclib import sdram class K7DDRPHY(Module, AutoCSR): diff --git a/misoclib/sdram/phy/s6ddrphy.py b/misoclib/sdram/phy/s6ddrphy.py index 0dd38372..2479c22b 100644 --- a/misoclib/sdram/phy/s6ddrphy.py +++ b/misoclib/sdram/phy/s6ddrphy.py @@ -15,9 +15,9 @@ # from migen.fhdl.std import * -from migen.bus.dfi import * from migen.genlib.record import * +from misoclib.sdram.bus.dfi import * from misoclib import sdram class S6DDRPHY(Module): -- 2.30.2