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):
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)

View File

@ -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)

View File

@ -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,

View File

@ -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)

View File

@ -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()

View File

@ -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)