soc_core: add csr_alignment to allow 64-bit alignment with 64-bit CPUs
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 8 Jul 2019 07:53:52 +0000 (09:53 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 8 Jul 2019 08:20:51 +0000 (10:20 +0200)
litex/soc/integration/cpu_interface.py
litex/soc/integration/soc_core.py
litex/soc/interconnect/csr_bus.py
litex/soc/software/bios/sdram.c

index 35c57cbb9e145b0370a1ecfbba7bc50017b9c1f3..c1acd144128183184d2e1f298466aa04f0d93b63 100644 (file)
@@ -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:
index 835acef18ec888bbce66a781dc0ccc4da075bdff..00de250fa6c58eee9cbcc3fec42aaa3e15943e43 100644 (file)
@@ -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(
index 4c63a741c5b8e080e48a236508ff9e9124058c67..038cdd596ef82b5fec71195f972b68d36fb977da 100644 (file)
@@ -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))
         ]
 
 
index b6aa52373a76489053885348d710164829508352..5cb4929d124206a23dc5df5f38f17eaa3e7e4a82 100644 (file)
@@ -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<DFII_NPHASES;p++)
                for(i=first_byte;i<DFII_PIX_DATA_SIZE;i+=step)
-                       printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i));
+                       printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i));
        printf("\n");
 }
 
@@ -167,7 +169,7 @@ void sdrrderr(char *count)
                cdelay(15);
                for(p=0;p<DFII_NPHASES;p++)
                        for(i=0;i<DFII_PIX_DATA_SIZE;i++)
-                               prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
+                               prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i);
 
                for(j=0;j<_count;j++) {
                        command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
@@ -176,7 +178,7 @@ void sdrrderr(char *count)
                                for(i=0;i<DFII_PIX_DATA_SIZE;i++) {
                                        unsigned char new_data;
 
-                                       new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
+                                       new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i);
                                        errs[p*DFII_PIX_DATA_SIZE+i] |= prev_data[p*DFII_PIX_DATA_SIZE+i] ^ new_data;
                                        prev_data[p*DFII_PIX_DATA_SIZE+i] = new_data;
                                }
@@ -211,7 +213,7 @@ void sdrwr(char *startaddr)
 
        for(p=0;p<DFII_NPHASES;p++)
                for(i=0;i<DFII_PIX_DATA_SIZE;i++)
-                       MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = 0x10*p + i;
+                       MMPTR(sdram_dfii_pix_wrdata_addr[p]+DFII_ADDR_SHIFT*i) = 0x10*p + i;
 
        sdram_dfii_piwr_address_write(addr);
        sdram_dfii_piwr_baddress_write(0);
@@ -309,7 +311,7 @@ int write_level(void)
        cdelay(100);
        for(i=0;i<NBMODULES;i++) {
                printf("m%d: |", i);
-               dq_address = sdram_dfii_pix_rddata_addr[0]+4*(NBMODULES-1-i);
+               dq_address = sdram_dfii_pix_rddata_addr[0]+DFII_ADDR_SHIFT*(NBMODULES-1-i);
 
                /* rst delay */
                write_delay_rst(i);
@@ -458,7 +460,7 @@ static int read_level_scan(int module, int bitslip)
        /* Write test pattern */
        for(p=0;p<DFII_NPHASES;p++)
                for(i=0;i<DFII_PIX_DATA_SIZE;i++)
-                       MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = prs[DFII_PIX_DATA_SIZE*p+i];
+                       MMPTR(sdram_dfii_pix_wrdata_addr[p]+DFII_ADDR_SHIFT*i) = prs[DFII_PIX_DATA_SIZE*p+i];
        sdram_dfii_piwr_address_write(0);
        sdram_dfii_piwr_baddress_write(0);
        command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
@@ -483,9 +485,9 @@ static int read_level_scan(int module, int bitslip)
                cdelay(15);
                working = 1;
                for(p=0;p<DFII_NPHASES;p++) {
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
                                working = 0;
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
                                working = 0;
                }
 #ifdef ECP5DDRPHY
@@ -554,9 +556,9 @@ static void read_level(int module)
                cdelay(15);
                working = 1;
                for(p=0;p<DFII_NPHASES;p++) {
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
                                working = 0;
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
                                working = 0;
                }
 #ifdef ECP5DDRPHY
@@ -592,9 +594,9 @@ static void read_level(int module)
                cdelay(15);
                working = 1;
                for(p=0;p<DFII_NPHASES;p++) {
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
                                working = 0;
-                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
+                       if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
                                working = 0;
                }
 #ifdef ECP5DDRPHY