core: use a single structure to pass settings / simplify

This commit is contained in:
Florent Kermarrec 2016-05-02 21:38:18 +02:00
parent 7ce42d5324
commit 8c0e732c24
6 changed files with 59 additions and 77 deletions

View File

@ -59,16 +59,14 @@ def data_layout(dw):
class InternalInterface(Record): class InternalInterface(Record):
def __init__(self, aw, dw, nbanks, cmd_buffer_depth, read_latency, write_latency): def __init__(self, address_align, settings):
self.aw = aw self.aw = settings.geom.rowbits + settings.geom.colbits - address_align
self.dw = dw self.dw = settings.phy.dfi_databits*settings.phy.nphases
self.nbanks = nbanks self.nbanks = 2**settings.geom.bankbits
self.cmd_buffer_depth = cmd_buffer_depth self.settings = settings
self.read_latency = read_latency
self.write_latency = write_latency
layout = [("bank"+str(i), cmd_layout(aw)) for i in range(nbanks)] layout = [("bank"+str(i), cmd_layout(self.aw)) for i in range(self.nbanks)]
layout += data_layout(dw) layout += data_layout(self.dw)
Record.__init__(self, layout) Record.__init__(self, layout)

View File

@ -28,28 +28,26 @@ class AddressSlicer:
class BankMachine(Module): class BankMachine(Module):
def __init__(self, def __init__(self,
aw,
n, n,
aw,
address_align, address_align,
geom_settings, settings):
timing_settings,
controller_settings):
self.req = req = Record(cmd_layout(aw)) self.req = req = Record(cmd_layout(aw))
self.refresh_req = Signal() self.refresh_req = Signal()
self.refresh_gnt = Signal() self.refresh_gnt = Signal()
a = geom_settings.addressbits a = settings.geom.addressbits
ba = geom_settings.bankbits ba = settings.geom.bankbits
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))
# # # # # #
# Command buffer # Command buffer
cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))] 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) cmd_buffer = stream.Buffer(cmd_buffer_layout)
else: else:
cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, cmd_buffer = stream.SyncFIFO(cmd_buffer_layout,
controller_settings.cmd_buffer_depth) settings.cmd_buffer_depth)
self.submodules += cmd_buffer self.submodules += cmd_buffer
self.comb += [ self.comb += [
req.connect(cmd_buffer.sink, omit=["dat_w_ack", "dat_r_ack", "lock"]), 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), req.lock.eq(cmd_buffer.source.valid),
] ]
slicer = AddressSlicer(geom_settings.colbits, address_align) slicer = AddressSlicer(settings.geom.colbits, address_align)
# Row tracking # Row tracking
has_openrow = Signal() has_openrow = Signal()
openrow = Signal(geom_settings.rowbits) openrow = Signal(settings.geom.rowbits)
hit = Signal() hit = Signal()
self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr)) self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr))
track_open = Signal() track_open = Signal()
@ -86,7 +84,7 @@ class BankMachine(Module):
] ]
# Respect write-to-precharge specification # 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.submodules.precharge_timer = WaitTimer(precharge_time)
self.comb += self.precharge_timer.wait.eq(~(cmd.valid & self.comb += self.precharge_timer.wait.eq(~(cmd.valid &
cmd.ready & cmd.ready &
@ -153,5 +151,5 @@ class BankMachine(Module):
NextState("REGULAR") NextState("REGULAR")
) )
) )
fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1) fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP-1)
fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD-1) fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD-1)

View File

@ -34,40 +34,29 @@ class LiteDRAMController(Module):
phy_settings.dfi_databits, phy_settings.dfi_databits,
phy_settings.nphases) phy_settings.nphases)
self.lasmic = common.InternalInterface( self.settings = settings = controller_settings
aw=geom_settings.rowbits + geom_settings.colbits - address_align, self.settings.phy = phy_settings
dw=phy_settings.dfi_databits*phy_settings.nphases, self.settings.geom = geom_settings
nbanks=2**geom_settings.bankbits, self.settings.timing = timing_settings
cmd_buffer_depth=controller_settings.cmd_buffer_depth,
read_latency=phy_settings.read_latency+1, self.lasmic = common.InternalInterface(address_align, settings)
write_latency=phy_settings.write_latency+1) self.nrowbits = settings.geom.colbits - address_align
self.nrowbits = geom_settings.colbits - address_align
# # # # # #
self.submodules.refresher = Refresher(geom_settings.addressbits, self.submodules.refresher = Refresher(self.settings)
geom_settings.bankbits,
timing_settings.tRP,
timing_settings.tREFI,
timing_settings.tRFC,
controller_settings.with_refresh)
bank_machines = [] bank_machines = []
for i in range(2**geom_settings.bankbits): for i in range(2**geom_settings.bankbits):
bank_machine = BankMachine(self.lasmic.aw, bank_machine = BankMachine(i,
i, self.lasmic.aw,
address_align, address_align,
geom_settings, settings)
timing_settings,
controller_settings)
bank_machines.append(bank_machine) bank_machines.append(bank_machine)
self.submodules += bank_machine self.submodules += bank_machine
self.comb += getattr(self.lasmic, "bank"+str(i)).connect(bank_machine.req) self.comb += getattr(self.lasmic, "bank"+str(i)).connect(bank_machine.req)
self.submodules.multiplexer = Multiplexer(phy_settings, self.submodules.multiplexer = Multiplexer(settings,
geom_settings,
timing_settings,
controller_settings,
bank_machines, bank_machines,
self.refresher, self.refresher,
self.dfi, self.dfi,

View File

@ -102,31 +102,27 @@ class _Steerer(Module):
class Multiplexer(Module, AutoCSR): class Multiplexer(Module, AutoCSR):
def __init__(self, def __init__(self,
phy_settings, settings,
geom_settings,
timing_settings,
controller_settings,
bank_machines, bank_machines,
refresher, refresher,
dfi, dfi,
lasmic, lasmic,
with_bandwidth=False): with_bandwidth=False):
assert(phy_settings.nphases == len(dfi.phases)) assert(settings.phy.nphases == len(dfi.phases))
self.phy_settings = phy_settings
# Command choosing # Command choosing
requests = [bm.cmd for bm in bank_machines] requests = [bm.cmd for bm in bank_machines]
self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests) self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests)
self.submodules.choose_req = choose_req = _CommandChooser(requests) self.submodules.choose_req = choose_req = _CommandChooser(requests)
if phy_settings.nphases == 1: if settings.phy.nphases == 1:
self.comb += [ self.comb += [
choose_cmd.want_cmds.eq(1), choose_cmd.want_cmds.eq(1),
choose_req.want_cmds.eq(1) choose_req.want_cmds.eq(1)
] ]
# Command steering # Command steering
nop = Record(cmd_request_layout(geom_settings.addressbits, nop = Record(cmd_request_layout(settings.geom.addressbits,
geom_settings.bankbits)) settings.geom.bankbits))
# nop must be 1st # nop must be 1st
commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd]
(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4) (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
@ -159,8 +155,8 @@ class Multiplexer(Module, AutoCSR):
self.comb += max_time.eq(0) self.comb += max_time.eq(0)
return en, max_time return en, max_time
read_time_en, max_read_time = anti_starvation(controller_settings.read_time) read_time_en, max_read_time = anti_starvation(settings.read_time)
write_time_en, max_write_time = anti_starvation(controller_settings.write_time) write_time_en, max_write_time = anti_starvation(settings.write_time)
# Refresh # Refresh
self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines] 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) 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 = [] r = []
for i in range(phy_settings.nphases): for i in range(settings.phy.nphases):
s = steerer.sel[i].eq(STEER_NOP) s = steerer.sel[i].eq(STEER_NOP)
if r_w_n == "read": if r_w_n == "read":
if i == phy_settings.rdphase: if i == settings.phy.rdphase:
s = steerer.sel[i].eq(STEER_REQ) s = steerer.sel[i].eq(STEER_REQ)
elif i == phy_settings.rdcmdphase: elif i == settings.phy.rdcmdphase:
s = steerer.sel[i].eq(STEER_CMD) s = steerer.sel[i].eq(STEER_CMD)
elif r_w_n == "write": elif r_w_n == "write":
if i == phy_settings.wrphase: if i == settings.phy.wrphase:
s = steerer.sel[i].eq(STEER_REQ) s = steerer.sel[i].eq(STEER_REQ)
elif i == phy_settings.wrcmdphase: elif i == settings.phy.wrcmdphase:
s = steerer.sel[i].eq(STEER_CMD) s = steerer.sel[i].eq(STEER_CMD)
else: else:
raise ValueError raise ValueError
@ -204,7 +200,7 @@ class Multiplexer(Module, AutoCSR):
choose_req.want_reads.eq(1), choose_req.want_reads.eq(1),
choose_cmd.cmd.ready.eq(1), choose_cmd.cmd.ready.eq(1),
choose_req.cmd.ready.eq(1), choose_req.cmd.ready.eq(1),
steerer_sel(steerer, phy_settings, "read"), steerer_sel(steerer, "read"),
If(write_available, If(write_available,
# TODO: switch only after several cycles of ~read_available? # TODO: switch only after several cycles of ~read_available?
If(~read_available | max_read_time, If(~read_available | max_read_time,
@ -220,7 +216,7 @@ class Multiplexer(Module, AutoCSR):
choose_req.want_writes.eq(1), choose_req.want_writes.eq(1),
choose_cmd.cmd.ready.eq(1), choose_cmd.cmd.ready.eq(1),
choose_req.cmd.ready.eq(1), choose_req.cmd.ready.eq(1),
steerer_sel(steerer, phy_settings, "write"), steerer_sel(steerer, "write"),
If(read_available, If(read_available,
If(~write_available | max_write_time, If(~write_available | max_write_time,
NextState("WTR") NextState("WTR")
@ -238,9 +234,9 @@ class Multiplexer(Module, AutoCSR):
) )
) )
# TODO: reduce this, actual limit is around (cl+1)/nphases # TODO: reduce this, actual limit is around (cl+1)/nphases
fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1) fsm.delayed_enter("RTW", "WRITE", settings.phy.read_latency-1)
fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1) fsm.delayed_enter("WTR", "READ", settings.timing.tWTR-1)
if controller_settings.with_bandwidth: if settings.with_bandwidth:
data_width = phy_settings.dfi_databits*phy_settings.nphases data_width = settings.phy.dfi_databits*settings.phy.nphases
self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width) self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width)

View File

@ -5,10 +5,11 @@ from litedram.core.multiplexer import *
class Refresher(Module): class Refresher(Module):
def __init__(self, a, ba, tRP, tREFI, tRFC, enable): def __init__(self, settings):
self.req = Signal() self.req = Signal()
self.ack = Signal() # 1st command 1 cycle after assertion of ack 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.ras.eq(1),
cmd.we.eq(1) cmd.we.eq(1)
]), ]),
(1+tRP, [ (1+settings.timing.tRP, [
cmd.cas.eq(1), cmd.cas.eq(1),
cmd.ras.eq(1) cmd.ras.eq(1)
]), ]),
(1+tRP+tRFC, [ (1+settings.timing.tRP+settings.timing.tRFC, [
seq_done.eq(1) seq_done.eq(1)
]) ])
]) ])
# Periodic refresh counter # Periodic refresh counter
self.submodules.timer = WaitTimer(tREFI) self.submodules.timer = WaitTimer(settings.timing.tREFI)
self.comb += self.timer.wait.eq(enable & ~self.timer.done) self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done)
# Control FSM # Control FSM
self.submodules.fsm = fsm = FSM() self.submodules.fsm = fsm = FSM()

View File

@ -15,9 +15,9 @@ class LiteDRAMCrossbar(Module):
self.rca_bits = controller.aw self.rca_bits = controller.aw
self.dw = controller.dw self.dw = controller.dw
self.nbanks = controller.nbanks self.nbanks = controller.nbanks
self.cmd_buffer_depth = controller.cmd_buffer_depth self.cmd_buffer_depth = controller.settings.cmd_buffer_depth
self.read_latency = controller.read_latency self.read_latency = controller.settings.phy.read_latency + 1
self.write_latency = controller.write_latency self.write_latency = controller.settings.phy.write_latency + 1
self.bank_bits = log2_int(self.nbanks, False) self.bank_bits = log2_int(self.nbanks, False)