Add support for clam shell topology (#332)

Add clam shell topology support.
This commit is contained in:
Chen 2023-05-26 04:20:21 +08:00 committed by GitHub
parent d8c327b2b1
commit 83a29b190d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 12 deletions

View File

@ -229,6 +229,7 @@ class PhySettings(Settings):
write_dq_dqs_training: bool = False,
write_latency_calibration: bool = False,
read_leveling: bool = False,
is_clam_shell: bool = False,
):
if strobes is None:
strobes = databits // 8

View File

@ -17,11 +17,12 @@ from litedram.core.crossbar import LiteDRAMCrossbar
class LiteDRAMCore(Module, AutoCSR):
def __init__(self, phy, geom_settings, timing_settings, clk_freq, **kwargs):
self.submodules.dfii = DFIInjector(
addressbits = max(geom_settings.addressbits, getattr(phy, "addressbits", 0)),
bankbits = max(geom_settings.bankbits, getattr(phy, "bankbits", 0)),
nranks = phy.settings.nranks,
databits = phy.settings.dfi_databits,
nphases = phy.settings.nphases)
addressbits = max(geom_settings.addressbits, getattr(phy, "addressbits", 0)),
bankbits = max(geom_settings.bankbits, getattr(phy, "bankbits", 0)),
nranks = phy.settings.nranks,
databits = phy.settings.dfi_databits,
nphases = phy.settings.nphases,
is_clam_shell = phy.settings.is_clam_shell)
self.comb += self.dfii.master.connect(phy.dfi)
self.submodules.controller = controller = LiteDRAMController(

View File

@ -21,6 +21,9 @@ class PhaseInjector(Module, AutoCSR):
CSRField("ras", size=1, description="DFI row address strobe bus"),
CSRField("wren", size=1, description="DFI write data enable bus"),
CSRField("rden", size=1, description="DFI read data enable bus"),
# Separate cs for clam shell topology
CSRField("cs_top", size=1, description="DFI chip select bus for top half only"),
CSRField("cs_bottom", size=1, description="DFI chip select bus for bottom half only"),
], description="Control DFI signals on a single phase")
self._command_issue = CSR() # description="The command gets commited on a write to this register"
@ -33,7 +36,15 @@ class PhaseInjector(Module, AutoCSR):
self.comb += [
If(self._command_issue.re,
phase.cs_n.eq(Replicate(~self._command.fields.cs, len(phase.cs_n))),
If(self._command.fields.cs_top,
phase.cs_n.eq(2), # cs_n=0b10
).Else(
If(self._command.fields.cs_bottom,
phase.cs_n.eq(1), # cs_n=0b01
).Else(
phase.cs_n.eq(Replicate(~self._command.fields.cs, len(phase.cs_n))),
),
),
phase.we_n.eq(~self._command.fields.we),
phase.cas_n.eq(~self._command.fields.cas),
phase.ras_n.eq(~self._command.fields.ras)
@ -55,10 +66,10 @@ class PhaseInjector(Module, AutoCSR):
# DFIInjector --------------------------------------------------------------------------------------
class DFIInjector(Module, AutoCSR):
def __init__(self, addressbits, bankbits, nranks, databits, nphases=1):
def __init__(self, addressbits, bankbits, nranks, databits, nphases=1, is_clam_shell=False):
self.slave = dfi.Interface(addressbits, bankbits, nranks, databits, nphases)
self.master = dfi.Interface(addressbits, bankbits, nranks, databits, nphases)
csr_dfi = dfi.Interface(addressbits, bankbits, nranks, databits, nphases)
self.master = dfi.Interface(addressbits, bankbits, nranks*2 if is_clam_shell else nranks, databits, nphases)
csr_dfi = dfi.Interface(addressbits, bankbits, nranks*2 if is_clam_shell else nranks, databits, nphases)
self.ext_dfi = dfi.Interface(addressbits, bankbits, nranks, databits, nphases)
self.ext_dfi_sel = Signal()
@ -87,7 +98,11 @@ class DFIInjector(Module, AutoCSR):
self.ext_dfi.connect(self.master)
# Through LiteDRAM controller.
).Else(
self.slave.connect(self.master)
self.slave.connect(self.master),
# Broadcast cs_n for clam shell topology
If(is_clam_shell,
[self.master.phases[i].cs_n.eq(Replicate(self.slave.phases[i].cs_n, 2)) for i in range(nphases)],
)
)
# Software Control (through CSRs).
# --------------------------------

View File

@ -23,6 +23,14 @@ cmds = {
"CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
}
# Swap two bits in num
# https://www.techiedelight.com/swap-two-bits-given-position-integer/
def swap_bit(num, a, b):
if ((num >> a) & 1) != ((num >> b) & 1):
num = num ^ (1 << a)
num = num ^ (1 << b)
return num
def reg(fields):
# takes a list of tuples: [(bit_offset, bit_width, value), ...]
regval = 0
@ -894,6 +902,9 @@ def get_sdram_phy_c_header(phy_settings, timing_settings, geom_settings):
r.define("DFII_COMMAND_RAS", "0x08")
r.define("DFII_COMMAND_WRDATA", "0x10")
r.define("DFII_COMMAND_RDDATA", "0x20")
if phy_settings.is_clam_shell:
r.define("DFII_COMMAND_CS_TOP", "0x40")
r.define("DFII_COMMAND_CS_BOTTOM", "0x80")
r.newline()
phytype = phy_settings.phytype.upper()
@ -941,6 +952,9 @@ def get_sdram_phy_c_header(phy_settings, timing_settings, geom_settings):
if phy_settings.is_rdimm:
assert phy_settings.memtype == "DDR4"
r.define("SDRAM_PHY_DDR4_RDIMM")
if phy_settings.is_clam_shell:
assert phy_settings.memtype == "DDR4"
r.define("SDRAM_PHY_CLAM_SHELL")
# litedram doesn't support multiple ranks
supported_memory = 2 ** (geom_settings.bankbits +
@ -1010,6 +1024,33 @@ def get_sdram_phy_c_header(phy_settings, timing_settings, geom_settings):
invert_masks.append((0b10101111111000, 0b1111))
for a_inv, ba_inv in invert_masks:
# handle clam shell topology
if cmd == cmds["MODE_REGISTER"] and phy_settings.is_clam_shell:
b += f"/* {comment} for top */"
b += f"sdram_dfii_pi0_address_write({a ^ a_inv:#x});"
b += f"sdram_dfii_pi0_baddress_write({ba ^ ba_inv:d});"
b += f"command_p0({cmd}|DFII_COMMAND_CS_TOP);"
if delay:
b += f"cdelay({delay});\n"
b.newline()
# swap addr and pass to bottom
b += f"/* {comment} for bottom */"
addr = a ^ a_inv
addr = swap_bit(addr, 3, 4)
addr = swap_bit(addr, 5, 6)
addr = swap_bit(addr, 7, 8)
addr = swap_bit(addr, 11, 13)
b += f"sdram_dfii_pi0_address_write({addr:#x});"
baddr = ba ^ ba_inv
baddr = swap_bit(baddr, 0, 1)
b += f"sdram_dfii_pi0_baddress_write({baddr:d});"
b += f"command_p0({cmd}|DFII_COMMAND_CS_BOTTOM);"
if delay:
b += f"cdelay({delay});\n"
b.newline()
continue
b += f"/* {comment} */"
b += f"sdram_dfii_pi0_address_write({a ^ a_inv:#x});"
b += f"sdram_dfii_pi0_baddress_write({ba ^ ba_inv:d});"

View File

@ -32,7 +32,8 @@ class USDDRPHY(Module, AutoCSR):
cwl = None,
cmd_latency = 0,
cmd_delay = None,
is_rdimm = False):
is_rdimm = False,
is_clam_shell = False):
phytype = self.__class__.__name__
device = {"USDDRPHY": "ULTRASCALE", "USPDDRPHY": "ULTRASCALE_PLUS"}[phytype]
pads = PHYPadsCombiner(pads)
@ -97,7 +98,7 @@ class USDDRPHY(Module, AutoCSR):
memtype = memtype,
databits = databits,
dfi_databits = 2*databits,
nranks = nranks,
nranks = nranks//2 if is_clam_shell else nranks,
nphases = nphases,
rdphase = self._rdphase.storage,
wrphase = self._wrphase.storage,
@ -112,6 +113,7 @@ class USDDRPHY(Module, AutoCSR):
read_leveling = True,
delays = 512,
bitslips = 8,
is_clam_shell = is_clam_shell,
)
if is_rdimm: