core: use a single structure to pass settings / simplify
This commit is contained in:
parent
7ce42d5324
commit
8c0e732c24
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue