integration/soc: -x on soc.py
[litex.git] / litex / soc / integration / soc.py
old mode 100755 (executable)
new mode 100644 (file)
index 79dbc3b..df1e1e1
@@ -22,10 +22,10 @@ from litex.soc.interconnect import axi
 
 from litedram.core import LiteDRAMCore
 from litedram.frontend.wishbone import LiteDRAMWishbone2Native
+from litedram.frontend.axi import LiteDRAMAXI2Native
 
 # TODO:
 # - replace raise with exit on logging error.
-# - add configurable CSR paging.
 # - cleanup SoCCSRRegion
 
 logging.basicConfig(level=logging.INFO)
@@ -109,23 +109,26 @@ class SoCBusHandler(Module):
 
         # Check Standard
         if standard not in self.supported_standard:
-            self.logger.error("Unsupported Standard: {} supporteds: {:s}".format(
-                colorer(standard, color="red"),
-                colorer(", ".join(self.supported_standard), color="green")))
+            self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
+                colorer("Bus standard", color="red"),
+                colorer(standard),
+                colorer(", ".join(self.supported_standard))))
             raise
 
         # Check Data Width
         if data_width not in self.supported_data_width:
-            self.logger.error("Unsupported Data_Width: {} supporteds: {:s}".format(
-                colorer(data_width, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_data_width), color="green")))
+            self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
+                colorer("Data Width", color="red"),
+                colorer(data_width),
+                colorer(", ".join(str(x) for x in self.supported_data_width))))
             raise
 
         # Check Address Width
         if address_width not in self.supported_address_width:
-            self.logger.error("Unsupported Address Width: {} supporteds: {:s}".format(
-                colorer(data_width, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_address_width), color="green")))
+            self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
+                colorer("Address Width", color="red"),
+                colorer(data_width),
+                colorer(", ".join(str(x) for x in self.supported_address_width))))
             raise
 
         # Create Bus
@@ -161,13 +164,14 @@ class SoCBusHandler(Module):
             self.io_regions[name] = region
             overlap = self.check_regions_overlap(self.io_regions)
             if overlap is not None:
-                self.logger.error("IO Region overlap between {} and {}:".format(
-                    colorer(overlap[0], color="red"),
-                    colorer(overlap[1], color="red")))
-                self.logger.error(str(self.regions[overlap[0]]))
-                self.logger.error(str(self.regions[overlap[1]]))
+                self.logger.error("IO Region {} between {} and {}:".format(
+                    colorer("overlap", color="red"),
+                    colorer(overlap[0]),
+                    colorer(overlap[1])))
+                self.logger.error(str(self.io_regions[overlap[0]]))
+                self.logger.error(str(self.io_regions[overlap[1]]))
                 raise
-            self.logger.info("{} Region {} {}.".format(
+            self.logger.info("{} Region {} at {}.".format(
                 colorer(name,    color="underline"),
                 colorer("added", color="green"),
                 str(region)))
@@ -182,27 +186,28 @@ class SoCBusHandler(Module):
             else:
                 if not region.cached:
                     if not self.check_region_is_io(region):
-                        self.logger.error("{} Region {}: {}".format(
-                            colorer(name, color="red"),
-                            colorer("not cached but not in IO region", color="red"),
+                        self.logger.error("{} Region {}: {}.".format(
+                            colorer(name),
+                            colorer("not in IO region", color="red"),
                             str(region)))
                         self.logger.error(self)
                         raise
                 self.regions[name] = region
                 overlap = self.check_regions_overlap(self.regions)
                 if overlap is not None:
-                    self.logger.error("Region overlap between {} and {}:".format(
-                        colorer(overlap[0], color="red"),
-                        colorer(overlap[1], color="red")))
+                    self.logger.error("Region {} between {} and {}:".format(
+                        colorer("overlap", color="red"),
+                        colorer(overlap[0]),
+                        colorer(overlap[1])))
                     self.logger.error(str(self.regions[overlap[0]]))
                     self.logger.error(str(self.regions[overlap[1]]))
                     raise
-            self.logger.info("{} Region {} {}.".format(
+            self.logger.info("{} Region {} at {}.".format(
                 colorer(name, color="underline"),
                 colorer("allocated" if allocated else "added", color="cyan" if allocated else "green"),
                 str(region)))
         else:
-            self.logger.error("{} is not a supported Region".format(colorer(name, color="red")))
+            self.logger.error("{} is not a supported Region.".format(colorer(name, color="red")))
             raise
 
     def alloc_region(self, name, size, cached=True):
@@ -233,7 +238,7 @@ class SoCBusHandler(Module):
                     # If no overlap, the Candidate is selected
                     return candidate
 
-        self.logger.error("Not enough Address Space to allocate Region")
+        self.logger.error("Not enough Address Space to allocate Region.")
         raise
 
     def check_regions_overlap(self, regions, check_linker=False):
@@ -287,7 +292,9 @@ class SoCBusHandler(Module):
         if name is None:
             name = "master{:d}".format(len(self.masters))
         if name in self.masters.keys():
-            self.logger.error("{} already declared as Bus Master:".format(colorer(name, color="red")))
+            self.logger.error("{} {} as Bus Master:".format(
+                colorer(name),
+                colorer("already declared", color="red")))
             self.logger.error(self)
             raise
         master = self.add_adapter(name, master)
@@ -300,21 +307,26 @@ class SoCBusHandler(Module):
         no_name   = name is None
         no_region = region is None
         if no_name and no_region:
-            self.logger.error("Please specify at least {} or {} of Bus Slave".format(
-                colorer("name",   color="red"),
-                colorer("region", color="red")))
+            self.logger.error("Please {} {} or/and {} of Bus Slave.".format(
+                colorer("specify", color="red"),
+                colorer("name"),
+                colorer("region")))
             raise
         if no_name:
             name = "slave{:d}".format(len(self.slaves))
         if no_region:
             region = self.regions.get(name, None)
             if region is None:
-                self.logger.error("Unable to find Region {}".format(colorer(name, color="red")))
+                self.logger.error("{} Region {}.".format(
+                    colorer(name),
+                    colorer("not found", color="red")))
                 raise
         else:
              self.add_region(name, region)
         if name in self.slaves.keys():
-            self.logger.error("{} already declared as Bus Slave:".format(colorer(name, color="red")))
+            self.logger.error("{} {} as Bus Slave:".format(
+                colorer(name),
+                colorer("already declared", color="red")))
             self.logger.error(self)
             raise
         slave = self.add_adapter(name, slave)
@@ -358,11 +370,13 @@ class SoCLocHandler(Module):
         allocated = False
         if not (use_loc_if_exists and name in self.locs.keys()):
             if name in self.locs.keys():
-                self.logger.error("{} {} name already used.".format(colorer(name, "red"), self.name))
+                self.logger.error("{} {} name {}.".format(
+                    colorer(name), self.name, colorer("already used", color="red")))
                 self.logger.error(self)
                 raise
             if n in self.locs.values():
-                self.logger.error("{} {} Location already used.".format(colorer(n, "red"), self.name))
+                self.logger.error("{} {} Location {}.".format(
+                    colorer(n), self.name, colorer("already used", color="red")))
                 self.logger.error(self)
                 raise
             if n is None:
@@ -370,15 +384,17 @@ class SoCLocHandler(Module):
                 n = self.alloc(name)
             else:
                 if n < 0:
-                    self.logger.error("{} {} Location should be positive.".format(
-                        colorer(n, color="red"),
-                        self.name))
+                    self.logger.error("{} {} Location should be {}.".format(
+                        colorer(n),
+                        self.name,
+                        colorer("positive", color="red")))
                     raise
                 if n > self.n_locs:
-                    self.logger.error("{} {} Location too high (Up to {}).".format(
-                        colorer(n, color="red"),
+                    self.logger.error("{} {} Location {} than maximum: {}.".format(
+                        colorer(n),
                         self.name,
-                        colorer(self.n_csrs, color="green")))
+                        colorer("higher", color="red"),
+                        colorer(self.n_locs)))
                     raise
             self.locs[name] = n
         else:
@@ -402,55 +418,63 @@ class SoCLocHandler(Module):
     def __str__(self):
         r = "{} Locations: ({})\n".format(self.name, len(self.locs.keys())) if len(self.locs.keys()) else ""
         locs = {k: v for k, v in sorted(self.locs.items(), key=lambda item: item[1])}
+        length = 0
         for name in locs.keys():
-           r += "- {}{}: {}\n".format(colorer(name, color="underline"), " "*(20-len(name)), colorer(self.locs[name]))
+            if len(name) > length: length = len(name)
+        for name in locs.keys():
+           r += "- {}{}: {}\n".format(colorer(name, color="underline"), " "*(length + 1 - len(name)), colorer(self.locs[name]))
         return r
 
 # SoCCSRHandler ------------------------------------------------------------------------------------
 
 class SoCCSRHandler(SoCLocHandler):
     supported_data_width    = [8, 32]
-    supported_address_width = [14, 15]
+    supported_address_width = [14+i for i in range(4)]
     supported_alignment     = [32, 64]
-    supported_paging        = [0x800]
+    supported_paging        = [0x800*2**i for i in range(4)]
 
     # Creation -------------------------------------------------------------------------------------
     def __init__(self, data_width=32, address_width=14, alignment=32, paging=0x800, reserved_csrs={}):
-        SoCLocHandler.__init__(self, "CSR", n_locs=4*2**address_width//paging) # FIXME
+        SoCLocHandler.__init__(self, "CSR", n_locs=alignment//8*(2**address_width)//paging)
         self.logger = logging.getLogger("SoCCSRHandler")
         self.logger.info("Creating CSR Handler...")
 
         # Check Data Width
         if data_width not in self.supported_data_width:
-            self.logger.error("Unsupported data_width: {} supporteds: {:s}".format(
-                colorer(data_width, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_data_width), color="green")))
+            self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
+                colorer("Data Width", color="red"),
+                colorer(data_width),
+                colorer(", ".join(str(x) for x in self.supported_data_width))))
             raise
 
         # Check Address Width
         if address_width not in self.supported_address_width:
-            self.logger.error("Unsupported address_width: {} supporteds: {:s}".format(
-                colorer(address_width, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_address_width), color="green")))
+            self.logger.error("Unsupported {} {} supporteds: {:s}".format(
+                colorer("Address Width", color="red"),
+                colorer(address_width),
+                colorer(", ".join(str(x) for x in self.supported_address_width))))
             raise
 
         # Check Alignment
         if alignment not in self.supported_alignment:
-            self.logger.error("Unsupported alignment: {} supporteds: {:s}".format(
-                colorer(alignment, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_alignment), color="green")))
+            self.logger.error("Unsupported {}: {} supporteds: {:s}".format(
+                colorer("Alignment", color="red"),
+                colorer(alignment),
+                colorer(", ".join(str(x) for x in self.supported_alignment))))
             raise
         if data_width > alignment:
-            self.logger.error("Alignment ({}) should be >= data_width ({})".format(
-                colorer(alignment,  color="red"),
-                colorer(data_width, color="red")))
+            self.logger.error("Alignment ({}) {} Data Width ({})".format(
+                colorer(alignment),
+                colorer("should be >=", color="red"),
+                colorer(data_width)))
             raise
 
         # Check Paging
         if paging not in self.supported_paging:
-            self.logger.error("Unsupported paging: {} supporteds: {:s}".format(
-                colorer(paging, color="red"),
-                colorer(", ".join(str(x) for x in self.supported_paging), color="green")))
+            self.logger.error("Unsupported {} 0x{}, supporteds: {:s}".format(
+                colorer("Paging", color="red"),
+                colorer("{:x}".format(paging)),
+                colorer(", ".join("0x{:x}".format(x) for x in self.supported_paging))))
             raise
 
         # Create CSR Handler
@@ -460,8 +484,9 @@ class SoCCSRHandler(SoCLocHandler):
         self.paging        = paging
         self.masters       = {}
         self.regions       = {}
-        self.logger.info("{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).".format(
+        self.logger.info("{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging (Up to {} Locations).".format(
             colorer(self.data_width),
+            colorer(self.alignment),
             colorer(2**self.address_width/2**10),
             colorer(self.paging),
             colorer(self.n_locs)))
@@ -473,20 +498,37 @@ class SoCCSRHandler(SoCLocHandler):
 
         self.logger.info("CSR Handler {}.".format(colorer("created", color="green")))
 
+    # Update CSR Alignment ----------------------------------------------------------------------------
+    def update_alignment(self, alignment):
+        # Check Alignment
+        if alignment not in self.supported_alignment:
+            self.logger.error("Unsupported {}: {} supporteds: {:s}".format(
+                colorer("Alignment", color="red"),
+                colorer(alignment),
+                colorer(", ".join(str(x) for x in self.supported_alignment))))
+            raise
+        self.logger.info("Alignment {} from {}-bit to {}-bit.".format(
+            colorer("updated", color="cyan"),
+            colorer(self.alignment),
+            colorer(alignment)))
+        self.alignment = alignment
+
     # Add Master -----------------------------------------------------------------------------------
     def add_master(self, name=None, master=None):
         if name is None:
             name = "master{:d}".format(len(self.masters))
         if name in self.masters.keys():
-            self.logger.error("{} already declared as CSR Master:".format(colorer(name, color="red")))
+            self.logger.error("{} {} as CSR Master:".format(
+                colorer(name),
+                colorer("already declared", color="red")))
             self.logger.error(self)
             raise
         if master.data_width != self.data_width:
-            self.logger.error("{} Master/Handler data_width {} ({} vs {}).".format(
+            self.logger.error("{} Master/Handler Data Width {} ({} vs {}).".format(
                 colorer(name),
-                colorer("missmatch"),
-                colorer(master.data_width, color="red"),
-                colorer(self.data_width,   color="red")))
+                colorer("missmatch", color="red"),
+                colorer(master.data_width),
+                colorer(self.data_width)))
             raise
         self.masters[name] = master
         self.logger.info("{} {} as CSR Master.".format(
@@ -503,14 +545,18 @@ class SoCCSRHandler(SoCLocHandler):
         if memory is not None:
             name = name + "_" + memory.name_override
         if self.locs.get(name, None) is None:
-            self.logger.error("Undefined {} CSR.".format(colorer(name, color="red")))
+            self.logger.error("CSR {} {}.".format(
+                colorer(name),
+                colorer("not found", color="red")))
+            self.logger.error(self)
             raise
         return self.locs[name]
 
     # Str ------------------------------------------------------------------------------------------
     def __str__(self):
-        r = "{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
+        r = "{}-bit CSR Bus, {}-bit Aligned, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
             colorer(self.data_width),
+            colorer(self.alignment),
             colorer(2**self.address_width/2**10),
             colorer(self.paging),
             colorer(self.n_locs))
@@ -581,6 +627,7 @@ class SoCController(Module, AutoCSR):
 # SoC ----------------------------------------------------------------------------------------------
 
 class SoC(Module):
+    mem_map = {}
     def __init__(self, platform, sys_clk_freq,
 
         bus_standard         = "wishbone",
@@ -653,13 +700,17 @@ class SoC(Module):
     # SoC Helpers ----------------------------------------------------------------------------------
     def check_if_exists(self, name):
         if hasattr(self, name):
-            self.logger.error("{} SubModule already declared.".format(colorer(name, "red")))
+            self.logger.error("{} SubModule already {}.".format(
+                colorer(name),
+                colorer("declared", color="red")))
             raise
 
     def add_constant(self, name, value=None):
         name = name.upper()
         if name in self.constants.keys():
-            self.logger.error("{} Constant already declared.".format(colorer(name, "red")))
+            self.logger.error("{} Constant already {}.".format(
+                colorer(name),
+                colorer("declared", color="red")))
             raise
         self.constants[name] = SoCConstant(value)
 
@@ -704,9 +755,10 @@ class SoC(Module):
 
     def add_cpu(self, name="vexriscv", variant="standard", reset_address=None):
         if name not in cpu.CPUS.keys():
-            self.logger.error("{} CPU not supported, supporteds: {}".format(
-                colorer(name, color="red"),
-                colorer(", ".join(cpu.CPUS.keys()), color="green")))
+            self.logger.error("{} CPU {}, supporteds: {}".format(
+                colorer(name),
+                colorer("not supported", color="red"),
+                colorer(", ".join(cpu.CPUS.keys()))))
             raise
         # Add CPU
         self.submodules.cpu = cpu.CPUS[name](self.platform, variant)
@@ -714,6 +766,7 @@ class SoC(Module):
         for n, (origin, size) in enumerate(self.cpu.io_regions.items()):
             self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
         self.mem_map.update(self.cpu.mem_map) # FIXME
+        self.csr.update_alignment(self.cpu.data_width)
         # Add Bus Masters/CSR/IRQs
         if not isinstance(self.cpu, cpu.CPUNone):
             if reset_address is None:
@@ -721,7 +774,7 @@ class SoC(Module):
             self.cpu.set_reset_address(reset_address)
             for n, cpu_bus in enumerate(self.cpu.buses):
                 self.bus.add_master(name="cpu_bus{}".format(n), master=cpu_bus)
-            self.add_csr("cpu", use_loc_if_exists=True)
+            self.csr.add("cpu", use_loc_if_exists=True)
             for name, loc in self.cpu.interrupts.items():
                 self.irq.add(name, loc)
             if hasattr(self, "ctrl"):
@@ -761,11 +814,12 @@ class SoC(Module):
 
         # SoC CSR Interconnect ---------------------------------------------------------------------
         self.submodules.csr_bankarray = csr_bus.CSRBankArray(self,
-            address_map   = self.csr.address_map,
-            data_width    = self.csr.data_width,
-            address_width = self.csr.address_width,
-            alignment     = self.csr.alignment
-        )
+            address_map        = self.csr.address_map,
+            data_width         = self.csr.data_width,
+            address_width      = self.csr.address_width,
+            alignment          = self.csr.alignment,
+            paging             = self.csr.paging,
+            soc_bus_data_width = self.bus.data_width)
         if len(self.csr.masters):
             self.submodules.csr_interconnect = csr_bus.InterconnectShared(
                 masters = list(self.csr.masters.values()),
@@ -781,9 +835,9 @@ class SoC(Module):
         # Add Memory regions
         for name, memory, mapaddr, mmap in self.csr_bankarray.srams:
             self.csr.add_region(name + "_" + memory.name_override, SoCCSRRegion(
-                origin   = (self.bus.regions["csr"].origin + self.csr.paging*mapaddr),
-                busworkd = self.csr.data_width,
-                obj      = memory))
+                origin  = (self.bus.regions["csr"].origin + self.csr.paging*mapaddr),
+                busword = self.csr.data_width,
+                obj     = memory))
 
         # Sort CSR regions by origin
         self.csr.regions = {k: v for k, v in sorted(self.csr.regions.items(), key=lambda item: item[1].origin)}
@@ -796,8 +850,9 @@ class SoC(Module):
         if not isinstance(self.cpu, cpu.CPUNone):
             for name in ["rom", "sram"]:
                 if name not in self.bus.regions.keys():
-                    self.logger.error("CPU needs {} Region to be defined as Bus or Linker Region.".format(
-                        colorer(name, color="red")))
+                    self.logger.error("CPU needs {} Region to be {} as Bus or Linker Region.".format(
+                        colorer(name),
+                        colorer("defined", color="red")))
                     self.logger.error(self.bus)
                     raise
 
@@ -810,8 +865,10 @@ class SoC(Module):
                     if hasattr(self, name):
                         module = getattr(self, name)
                         if not hasattr(module, "ev"):
-                            self.logger.error("No EventManager found on {} SubModule".format(
-                                colorer(name, color="red")))
+                            self.logger.error("EventManager {} in {} SubModule.".format(
+                                colorer("not found", color="red"),
+                                colorer(name)))
+                            raise
                         self.comb += self.cpu.interrupt[loc].eq(module.ev.irq)
                     self.add_constant(name + "_INTERRUPT", loc)
 
@@ -827,7 +884,7 @@ class LiteXSoC(SoC):
         self.check_if_exists(name)
         if with_build_time:
             identifier += " " + build_time()
-        setattr(self.submodules, name, Identifier(ident))
+        setattr(self.submodules, name, Identifier(identifier))
         self.csr.add(name + "_mem", use_loc_if_exists=True)
 
     # Add UART -------------------------------------------------------------------------------------
@@ -842,7 +899,7 @@ class LiteXSoC(SoC):
                 pads     = self.platform.request("serial"),
                 clk_freq = self.sys_clk_freq,
                 baudrate = baudrate)
-            self.bus.master(name="uart_bridge", master=self.uart.wishbone)
+            self.bus.add_master(name="uart_bridge", master=self.uart.wishbone)
         elif name == "crossover":
             self.submodules.uart = uart.UARTCrossover()
         else:
@@ -924,7 +981,7 @@ class LiteXSoC(SoC):
         elif self.with_wishbone:
             # Wishbone Slave SDRAM interface -------------------------------------------------------
             wb_sdram = wishbone.Interface()
-            self.bus.add_slave("main_ram", wb_sdram, SoCRegion(origin=origin, size=sdram_size))
+            self.bus.add_slave("main_ram", wb_sdram)
 
             # L2 Cache -----------------------------------------------------------------------------
             if l2_cache_size != 0:
@@ -947,4 +1004,5 @@ class LiteXSoC(SoC):
             self.add_config("L2_SIZE", l2_cache_size)
 
             # Wishbone Slave <--> LiteDRAM bridge --------------------------------------------------
-            self.submodules.wishbone_bridge = LiteDRAMWishbone2Native(litedram_wb, port)
+            self.submodules.wishbone_bridge = LiteDRAMWishbone2Native(litedram_wb, port,
+                base_address = self.bus.regions["main_ram"].origin)