From f4770219fa87640a61328ec92a9b2ceef40efe03 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 8 Jul 2019 09:53:52 +0200 Subject: [PATCH] soc_core: add csr_alignment to allow 64-bit alignment with 64-bit CPUs --- litex/soc/integration/cpu_interface.py | 22 ++++++++++++++++------ litex/soc/integration/soc_core.py | 10 ++++++++-- litex/soc/interconnect/csr_bus.py | 11 ++++++++--- litex/soc/software/bios/sdram.c | 26 ++++++++++++++------------ 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index 35c57cbb..c1acd144 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -21,6 +21,13 @@ from litex.soc.interconnect.csr import CSRStatus from litex.build.tools import generated_banner +# FIXME: use OrderedDict for constants? +def get_constant(name, constants): + for n, v in constants: + if n == name: + return v + return None + def get_cpu_mak(cpu): # select between clang and gcc clang = os.getenv("CLANG", "") @@ -97,7 +104,7 @@ def get_mem_header(regions, flash_boot_address, shadow_base): return r -def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_access_functions): +def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions): r = "" r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"L\n" @@ -120,7 +127,7 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc if size > 1: r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+"L);\n" for byte in range(1, nwords): - r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+4*byte)+"L);\n" + r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+alignment//8*byte)+"L);\n" r += "\treturn r;\n}\n" else: r += "\treturn csr_readl("+hex(reg_base)+"L);\n}\n" @@ -133,12 +140,13 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc value_shifted = "value >> "+str(shift) else: value_shifted = "value" - r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+4*word)+"L);\n" + r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+alignment//8*word)+"L);\n" r += "}\n" return r def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000): + alignment = get_constant("CONFIG_CSR_ALIGNMENT", constants) r = generated_banner("//") r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n" if with_access_functions: @@ -161,8 +169,9 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b if not isinstance(obj, Memory): for csr in obj: nr = (csr.size + busword - 1)//busword - r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, busword, isinstance(csr, CSRStatus), with_access_functions) - origin += 4*nr + r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, busword, alignment, + isinstance(csr, CSRStatus), with_access_functions) + origin += alignment//8*nr r += "\n/* constants */\n" for name, value in constants: @@ -185,6 +194,7 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b def get_csr_csv(csr_regions=None, constants=None, memory_regions=None): + alignment = 32 if constants is None else get_constant("CONFIG_CSR_ALIGNMENT", constants) r = generated_banner("#") if csr_regions is not None: @@ -196,7 +206,7 @@ def get_csr_csv(csr_regions=None, constants=None, memory_regions=None): for csr in obj: nr = (csr.size + busword - 1)//busword r += "csr_register,{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw") - origin += 4*nr + origin += alignment//8*nr if constants is not None: for name, value in constants: diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 835acef1..00de250f 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -150,7 +150,7 @@ class SoCCore(Module): # MAIN_RAM parameters integrated_main_ram_size=0, integrated_main_ram_init=[], # CSR parameters - csr_data_width=8, csr_address_width=14, + csr_data_width=8, csr_alignment=32, csr_address_width=14, # Identifier parameters ident="", ident_version=False, # UART parameters @@ -210,7 +210,10 @@ class SoCCore(Module): self.integrated_sram_size = integrated_sram_size self.integrated_main_ram_size = integrated_main_ram_size + assert csr_data_width in [8, 32, 64] + assert csr_alignment in [32, 64] self.csr_data_width = csr_data_width + self.csr_alignment = csr_alignment self.csr_address_width = csr_address_width self.with_ctrl = with_ctrl @@ -291,6 +294,7 @@ class SoCCore(Module): bus_csr=csr_bus.Interface(csr_data_width, csr_address_width)) self.add_csr_master(self.wishbone2csr.csr) self.config["CSR_DATA_WIDTH"] = csr_data_width + self.config["CSR_ALIGNMENT"] = csr_alignment self.register_mem("csr", self.soc_mem_map["csr"], self.wishbone2csr.wishbone) # Add UART @@ -495,7 +499,9 @@ class SoCCore(Module): # Collect and create CSRs self.submodules.csrbankarray = csr_bus.CSRBankArray(self, self.get_csr_dev_address, - data_width=self.csr_data_width, address_width=self.csr_address_width) + data_width=self.csr_data_width, + address_width=self.csr_address_width, + alignment=self.csr_alignment) # Add CSRs interconnect self.submodules.csrcon = csr_bus.InterconnectShared( diff --git a/litex/soc/interconnect/csr_bus.py b/litex/soc/interconnect/csr_bus.py index 4c63a741..038cdd59 100644 --- a/litex/soc/interconnect/csr_bus.py +++ b/litex/soc/interconnect/csr_bus.py @@ -32,7 +32,8 @@ _layout = [ class Interface(Record): - def __init__(self, data_width=8, address_width=14): + def __init__(self, data_width=8, address_width=14, alignment=32): + self.alignment = alignment Record.__init__(self, set_layout_parameters(_layout, data_width=data_width, address_width=address_width)) @@ -160,19 +161,23 @@ class CSRBank(csr.GenericBank): sel = Signal() self.comb += sel.eq(self.bus.adr[9:] == address) + if bus.alignment == 64: + self.comb += If(self.bus.adr[0], sel.eq(0)) + + adr_shift = log2_int(bus.alignment//32) for i, c in enumerate(self.simple_csrs): self.comb += [ c.r.eq(self.bus.dat_w[:c.size]), c.re.eq(sel & \ self.bus.we & \ - (self.bus.adr[:self.decode_bits] == i)) + (self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)) ] brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs)) self.sync += [ self.bus.dat_r.eq(0), - If(sel, Case(self.bus.adr[:self.decode_bits], brcases)) + If(sel, Case(self.bus.adr[adr_shift:adr_shift+self.decode_bits], brcases)) ] diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index b6aa5237..5cb4929d 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -51,6 +51,8 @@ __attribute__((unused)) static void cdelay(int i) #ifdef CSR_SDRAM_BASE +#define DFII_ADDR_SHIFT CONFIG_CSR_ALIGNMENT/8 + void sdrsw(void) { sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N); @@ -103,7 +105,7 @@ void sdrrdbuf(int dq) for(p=0;p