soc: add linker regions management
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 11 Feb 2020 14:28:02 +0000 (15:28 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 11 Feb 2020 14:28:02 +0000 (15:28 +0100)
litex/soc/integration/soc.py
litex/soc/integration/soc_core.py

index 1c3534ee9e27822839126db92bd7e70226e90e9d..79dbc3be60770843f7bde7227dafedda67480286 100755 (executable)
@@ -26,7 +26,6 @@ from litedram.frontend.wishbone import LiteDRAMWishbone2Native
 # TODO:
 # - replace raise with exit on logging error.
 # - add configurable CSR paging.
-# - manage SoCLinkerRegion
 # - cleanup SoCCSRRegion
 
 logging.basicConfig(level=logging.INFO)
@@ -55,12 +54,13 @@ def SoCConstant(value):
 # SoCRegion ----------------------------------------------------------------------------------------
 
 class SoCRegion:
-    def __init__(self, origin=None, size=None, mode="rw", cached=True):
+    def __init__(self, origin=None, size=None, mode="rw", cached=True, linker=False):
         self.logger    = logging.getLogger("SoCRegion")
         self.origin    = origin
         self.size      = size
         self.mode      = mode
         self.cached    = cached
+        self.linker    = linker
 
     def decoder(self, bus):
         origin = self.origin
@@ -81,13 +81,12 @@ class SoCRegion:
         if self.size is not None:
             r += "Size: {}, ".format(colorer("0x{:08x}".format(self.size)))
         r += "Mode: {}, ".format(colorer(self.mode.upper()))
-        r += "Cached: {}".format(colorer(self.cached))
+        r += "Cached: {} ".format(colorer(self.cached))
+        r += "Linker: {}".format(colorer(self.linker))
         return r
 
 class SoCIORegion(SoCRegion): pass
 
-class SoCLinkerRegion(SoCRegion): pass
-
 # SoCCSRRegion -------------------------------------------------------------------------------------
 
 class SoCCSRRegion:
@@ -137,7 +136,6 @@ class SoCBusHandler(Module):
         self.slaves        = {}
         self.regions       = {}
         self.io_regions    = {}
-        self.ld_regions    = {}
         self.timeout       = timeout
         self.logger.info("{}-bit {} Bus, {}GiB Address Space.".format(
             colorer(data_width), colorer(standard), colorer(2**address_width/2**30)))
@@ -154,12 +152,12 @@ class SoCBusHandler(Module):
     # Add/Allog/Check Regions ----------------------------------------------------------------------
     def add_region(self, name, region):
         allocated = False
+        if name in self.regions.keys() or name in self.io_regions.keys():
+            self.logger.error("{} already declared as Region:".format(colorer(name, color="red")))
+            self.logger.error(self)
+            raise
         # Check if SoCIORegion
         if isinstance(region, SoCIORegion):
-            if name in self.masters.keys():
-                self.logger.error("{} already declared as IO Region:".format(colorer(name, color="red")))
-                self.logger.error(self)
-                raise
             self.io_regions[name] = region
             overlap = self.check_regions_overlap(self.io_regions)
             if overlap is not None:
@@ -173,25 +171,6 @@ class SoCBusHandler(Module):
                 colorer(name,    color="underline"),
                 colorer("added", color="green"),
                 str(region)))
-        # Check if SoCLinkerRegion
-        elif isinstance(region, SoCLinkerRegion):
-            if name in self.masters.keys():
-                self.logger.error("{} already declared as Linker Region:".format(colorer(name, color="red")))
-                self.logger.error(self)
-                raise
-            self.ld_regions[name] = region
-            overlap = self.check_regions_overlap(self.ld_regions)
-            if overlap is not None:
-                self.logger.error("Linker 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]]))
-                raise
-            self.logger.info("{} Region {} {}.".format(
-                colorer(name,    color="underline"),
-                colorer("added", color="green"),
-                str(region)))
         # Check if SoCRegion
         elif isinstance(region, SoCRegion):
             # If no origin specified, allocate region.
@@ -257,15 +236,16 @@ class SoCBusHandler(Module):
         self.logger.error("Not enough Address Space to allocate Region")
         raise
 
-    def check_regions_overlap(self, regions):
+    def check_regions_overlap(self, regions, check_linker=False):
         i = 0
         while i < len(regions):
             n0 =  list(regions.keys())[i]
             r0 = regions[n0]
             for n1 in list(regions.keys())[i+1:]:
                 r1 = regions[n1]
-                if isinstance(r0, SoCLinkerRegion) or isinstance(r1, SoCLinkerRegion):
-                    continue
+                if r0.linker or r1.linker:
+                    if not check_linker:
+                        continue
                 if r0.origin >= (r1.origin + r1.size):
                     continue
                 if r1.origin >= (r0.origin + r0.size):
@@ -351,10 +331,6 @@ class SoCBusHandler(Module):
         io_regions = {k: v for k, v in sorted(self.io_regions.items(), key=lambda item: item[1].origin)}
         for name, region in io_regions.items():
            r += colorer(name, color="underline") + " "*(20-len(name)) + ": " + str(region) + "\n"
-        r += "Linker Regions: ({})\n".format(len(self.ld_regions.keys())) if len(self.ld_regions.keys()) else ""
-        ld_regions = {k: v for k, v in sorted(self.ld_regions.items(), key=lambda item: item[1].origin)}
-        for name, region in ld_regions.items():
-           r += colorer(name, color="underline") + " "*(20-len(name)) + ": " + str(region) + "\n"
         r += "Bus Regions: ({})\n".format(len(self.regions.keys())) if len(self.regions.keys()) else ""
         regions = {k: v for k, v in sorted(self.regions.items(), key=lambda item: item[1].origin)}
         for name, region in regions.items():
@@ -448,7 +424,7 @@ class SoCCSRHandler(SoCLocHandler):
         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"))
+                colorer(", ".join(str(x) for x in self.supported_data_width), color="green")))
             raise
 
         # Check Address Width
@@ -819,7 +795,7 @@ class SoC(Module):
         # SoC CPU Check ----------------------------------------------------------------------------
         if not isinstance(self.cpu, cpu.CPUNone):
             for name in ["rom", "sram"]:
-                if name not in list(self.bus.regions.keys()) + list(self.bus.ld_regions.keys()):
+                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(self.bus)
index 16c58bfb5b858fe313a9f7e60478dfc61a39bab3..a42ca2224d13f354278d50b07fcddd520aeaeaa9 100644 (file)
@@ -202,7 +202,9 @@ class SoCCore(LiteXSoC):
         self.bus.add_slave(name=wb_name, slave=interface)
 
     def add_memory_region(self, name, origin, length, type="cached"):
-        self.bus.add_region(name, SoCRegion(origin=origin, size=length, cached="cached" in type))
+        self.bus.add_region(name, SoCRegion(origin=origin, size=length,
+            cached="cached" in type,
+            linker="linker" in type))
 
     def register_mem(self, name, address, interface, size=0x10000000):
         self.bus.add_slave(name, interface, SoCRegion(origin=address, size=size))