From 8c0e732c24f259ce2ceeea3e133a6dd98eb55013 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 2 May 2016 21:38:18 +0200 Subject: [PATCH] core: use a single structure to pass settings / simplify --- litedram/common.py | 16 ++++++------- litedram/core/bankmachine.py | 24 +++++++++----------- litedram/core/controller.py | 35 ++++++++++------------------- litedram/core/multiplexer.py | 42 ++++++++++++++++------------------- litedram/core/refresher.py | 13 ++++++----- litedram/frontend/crossbar.py | 6 ++--- 6 files changed, 59 insertions(+), 77 deletions(-) diff --git a/litedram/common.py b/litedram/common.py index fd918d1..7b423a5 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -59,16 +59,14 @@ def data_layout(dw): class InternalInterface(Record): - def __init__(self, aw, dw, nbanks, cmd_buffer_depth, read_latency, write_latency): - self.aw = aw - self.dw = dw - self.nbanks = nbanks - self.cmd_buffer_depth = cmd_buffer_depth - self.read_latency = read_latency - self.write_latency = write_latency + def __init__(self, address_align, settings): + self.aw = settings.geom.rowbits + settings.geom.colbits - address_align + self.dw = settings.phy.dfi_databits*settings.phy.nphases + self.nbanks = 2**settings.geom.bankbits + self.settings = settings - layout = [("bank"+str(i), cmd_layout(aw)) for i in range(nbanks)] - layout += data_layout(dw) + layout = [("bank"+str(i), cmd_layout(self.aw)) for i in range(self.nbanks)] + layout += data_layout(self.dw) Record.__init__(self, layout) diff --git a/litedram/core/bankmachine.py b/litedram/core/bankmachine.py index 0d9719d..8e9d046 100644 --- a/litedram/core/bankmachine.py +++ b/litedram/core/bankmachine.py @@ -28,28 +28,26 @@ class AddressSlicer: class BankMachine(Module): def __init__(self, - aw, n, + aw, address_align, - geom_settings, - timing_settings, - controller_settings): + settings): self.req = req = Record(cmd_layout(aw)) self.refresh_req = Signal() self.refresh_gnt = Signal() - a = geom_settings.addressbits - ba = geom_settings.bankbits + a = settings.geom.addressbits + ba = settings.geom.bankbits self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) # # # # Command buffer cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))] - if controller_settings.cmd_buffer_depth < 2: + if settings.cmd_buffer_depth < 2: cmd_buffer = stream.Buffer(cmd_buffer_layout) else: cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, - controller_settings.cmd_buffer_depth) + settings.cmd_buffer_depth) self.submodules += cmd_buffer self.comb += [ req.connect(cmd_buffer.sink, omit=["dat_w_ack", "dat_r_ack", "lock"]), @@ -57,11 +55,11 @@ class BankMachine(Module): req.lock.eq(cmd_buffer.source.valid), ] - slicer = AddressSlicer(geom_settings.colbits, address_align) + slicer = AddressSlicer(settings.geom.colbits, address_align) # Row tracking has_openrow = Signal() - openrow = Signal(geom_settings.rowbits) + openrow = Signal(settings.geom.rowbits) hit = Signal() self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr)) track_open = Signal() @@ -86,7 +84,7 @@ class BankMachine(Module): ] # Respect write-to-precharge specification - precharge_time = 2 + timing_settings.tWR - 1 + 1 + precharge_time = 2 + settings.timing.tWR - 1 + 1 self.submodules.precharge_timer = WaitTimer(precharge_time) self.comb += self.precharge_timer.wait.eq(~(cmd.valid & cmd.ready & @@ -153,5 +151,5 @@ class BankMachine(Module): NextState("REGULAR") ) ) - fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1) - fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD-1) + fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP-1) + fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD-1) diff --git a/litedram/core/controller.py b/litedram/core/controller.py index 8a38a5b..1cc957c 100644 --- a/litedram/core/controller.py +++ b/litedram/core/controller.py @@ -34,40 +34,29 @@ class LiteDRAMController(Module): phy_settings.dfi_databits, phy_settings.nphases) - self.lasmic = common.InternalInterface( - aw=geom_settings.rowbits + geom_settings.colbits - address_align, - dw=phy_settings.dfi_databits*phy_settings.nphases, - nbanks=2**geom_settings.bankbits, - cmd_buffer_depth=controller_settings.cmd_buffer_depth, - read_latency=phy_settings.read_latency+1, - write_latency=phy_settings.write_latency+1) - self.nrowbits = geom_settings.colbits - address_align + self.settings = settings = controller_settings + self.settings.phy = phy_settings + self.settings.geom = geom_settings + self.settings.timing = timing_settings + + self.lasmic = common.InternalInterface(address_align, settings) + self.nrowbits = settings.geom.colbits - address_align # # # - self.submodules.refresher = Refresher(geom_settings.addressbits, - geom_settings.bankbits, - timing_settings.tRP, - timing_settings.tREFI, - timing_settings.tRFC, - controller_settings.with_refresh) + self.submodules.refresher = Refresher(self.settings) bank_machines = [] for i in range(2**geom_settings.bankbits): - bank_machine = BankMachine(self.lasmic.aw, - i, + bank_machine = BankMachine(i, + self.lasmic.aw, address_align, - geom_settings, - timing_settings, - controller_settings) + settings) bank_machines.append(bank_machine) self.submodules += bank_machine self.comb += getattr(self.lasmic, "bank"+str(i)).connect(bank_machine.req) - self.submodules.multiplexer = Multiplexer(phy_settings, - geom_settings, - timing_settings, - controller_settings, + self.submodules.multiplexer = Multiplexer(settings, bank_machines, self.refresher, self.dfi, diff --git a/litedram/core/multiplexer.py b/litedram/core/multiplexer.py index cabb84c..f56cca6 100644 --- a/litedram/core/multiplexer.py +++ b/litedram/core/multiplexer.py @@ -102,31 +102,27 @@ class _Steerer(Module): class Multiplexer(Module, AutoCSR): def __init__(self, - phy_settings, - geom_settings, - timing_settings, - controller_settings, + settings, bank_machines, refresher, dfi, lasmic, with_bandwidth=False): - assert(phy_settings.nphases == len(dfi.phases)) - self.phy_settings = phy_settings + assert(settings.phy.nphases == len(dfi.phases)) # Command choosing requests = [bm.cmd for bm in bank_machines] self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests) self.submodules.choose_req = choose_req = _CommandChooser(requests) - if phy_settings.nphases == 1: + if settings.phy.nphases == 1: self.comb += [ choose_cmd.want_cmds.eq(1), choose_req.want_cmds.eq(1) ] # Command steering - nop = Record(cmd_request_layout(geom_settings.addressbits, - geom_settings.bankbits)) + nop = Record(cmd_request_layout(settings.geom.addressbits, + settings.geom.bankbits)) # nop must be 1st commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4) @@ -159,8 +155,8 @@ class Multiplexer(Module, AutoCSR): self.comb += max_time.eq(0) return en, max_time - read_time_en, max_read_time = anti_starvation(controller_settings.read_time) - write_time_en, max_write_time = anti_starvation(controller_settings.write_time) + read_time_en, max_read_time = anti_starvation(settings.read_time) + write_time_en, max_write_time = anti_starvation(settings.write_time) # Refresh self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines] @@ -178,19 +174,19 @@ class Multiplexer(Module, AutoCSR): Cat(*all_wrdata_mask).eq(~lasmic.dat_we) ] - def steerer_sel(steerer, phy_settings, r_w_n): + def steerer_sel(steerer, r_w_n): r = [] - for i in range(phy_settings.nphases): + for i in range(settings.phy.nphases): s = steerer.sel[i].eq(STEER_NOP) if r_w_n == "read": - if i == phy_settings.rdphase: + if i == settings.phy.rdphase: s = steerer.sel[i].eq(STEER_REQ) - elif i == phy_settings.rdcmdphase: + elif i == settings.phy.rdcmdphase: s = steerer.sel[i].eq(STEER_CMD) elif r_w_n == "write": - if i == phy_settings.wrphase: + if i == settings.phy.wrphase: s = steerer.sel[i].eq(STEER_REQ) - elif i == phy_settings.wrcmdphase: + elif i == settings.phy.wrcmdphase: s = steerer.sel[i].eq(STEER_CMD) else: raise ValueError @@ -204,7 +200,7 @@ class Multiplexer(Module, AutoCSR): choose_req.want_reads.eq(1), choose_cmd.cmd.ready.eq(1), choose_req.cmd.ready.eq(1), - steerer_sel(steerer, phy_settings, "read"), + steerer_sel(steerer, "read"), If(write_available, # TODO: switch only after several cycles of ~read_available? If(~read_available | max_read_time, @@ -220,7 +216,7 @@ class Multiplexer(Module, AutoCSR): choose_req.want_writes.eq(1), choose_cmd.cmd.ready.eq(1), choose_req.cmd.ready.eq(1), - steerer_sel(steerer, phy_settings, "write"), + steerer_sel(steerer, "write"), If(read_available, If(~write_available | max_write_time, NextState("WTR") @@ -238,9 +234,9 @@ class Multiplexer(Module, AutoCSR): ) ) # TODO: reduce this, actual limit is around (cl+1)/nphases - fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1) - fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1) + fsm.delayed_enter("RTW", "WRITE", settings.phy.read_latency-1) + fsm.delayed_enter("WTR", "READ", settings.timing.tWTR-1) - if controller_settings.with_bandwidth: - data_width = phy_settings.dfi_databits*phy_settings.nphases + if settings.with_bandwidth: + data_width = settings.phy.dfi_databits*settings.phy.nphases self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width) diff --git a/litedram/core/refresher.py b/litedram/core/refresher.py index db4d0fa..d4e4829 100644 --- a/litedram/core/refresher.py +++ b/litedram/core/refresher.py @@ -5,10 +5,11 @@ from litedram.core.multiplexer import * class Refresher(Module): - def __init__(self, a, ba, tRP, tREFI, tRFC, enable): + def __init__(self, settings): self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack - self.cmd = cmd = Record(cmd_request_layout(a, ba)) + self.cmd = cmd = Record(cmd_request_layout(settings.geom.addressbits, + settings.geom.bankbits)) # # # @@ -29,18 +30,18 @@ class Refresher(Module): cmd.ras.eq(1), cmd.we.eq(1) ]), - (1+tRP, [ + (1+settings.timing.tRP, [ cmd.cas.eq(1), cmd.ras.eq(1) ]), - (1+tRP+tRFC, [ + (1+settings.timing.tRP+settings.timing.tRFC, [ seq_done.eq(1) ]) ]) # Periodic refresh counter - self.submodules.timer = WaitTimer(tREFI) - self.comb += self.timer.wait.eq(enable & ~self.timer.done) + self.submodules.timer = WaitTimer(settings.timing.tREFI) + self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done) # Control FSM self.submodules.fsm = fsm = FSM() diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index 770f349..0ae6bb4 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -15,9 +15,9 @@ class LiteDRAMCrossbar(Module): self.rca_bits = controller.aw self.dw = controller.dw self.nbanks = controller.nbanks - self.cmd_buffer_depth = controller.cmd_buffer_depth - self.read_latency = controller.read_latency - self.write_latency = controller.write_latency + self.cmd_buffer_depth = controller.settings.cmd_buffer_depth + self.read_latency = controller.settings.phy.read_latency + 1 + self.write_latency = controller.settings.phy.write_latency + 1 self.bank_bits = log2_int(self.nbanks, False)