From e82531cdf8748e49d45e9baf433198edbc6f9c8d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 27 Feb 2015 16:54:22 +0100 Subject: [PATCH] move dfi/lasmibus/wishbone2lasmi to MiSoC sdram --- examples/sim/abstract_transactions_lasmi.py | 38 --- migen/bus/dfi.py | 67 ----- migen/bus/lasmibus.py | 309 -------------------- migen/bus/wishbone2lasmi.py | 171 ----------- 4 files changed, 585 deletions(-) delete mode 100644 examples/sim/abstract_transactions_lasmi.py delete mode 100644 migen/bus/dfi.py delete mode 100644 migen/bus/lasmibus.py delete mode 100644 migen/bus/wishbone2lasmi.py diff --git a/examples/sim/abstract_transactions_lasmi.py b/examples/sim/abstract_transactions_lasmi.py deleted file mode 100644 index 80f5c0b50..000000000 --- a/examples/sim/abstract_transactions_lasmi.py +++ /dev/null @@ -1,38 +0,0 @@ -from migen.fhdl.std import * -from migen.bus.transactions import * -from migen.bus import lasmibus -from migen.sim.generic import run_simulation - -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/migen/bus/dfi.py b/migen/bus/dfi.py deleted file mode 100644 index fa80f9c82..000000000 --- a/migen/bus/dfi.py +++ /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/migen/bus/lasmibus.py b/migen/bus/lasmibus.py deleted file mode 100644 index f1d3e29a9..000000000 --- a/migen/bus/lasmibus.py +++ /dev/null @@ -1,309 +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_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/migen/bus/wishbone2lasmi.py b/migen/bus/wishbone2lasmi.py deleted file mode 100644 index a2110caf2..000000000 --- a/migen/bus/wishbone2lasmi.py +++ /dev/null @@ -1,171 +0,0 @@ -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") - ) - )