soc: integrate CSR master/interconnect/collection and IRQ collection
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 7 Feb 2020 18:50:35 +0000 (19:50 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 7 Feb 2020 18:50:35 +0000 (19:50 +0100)
litex/soc/integration/soc.py
litex/soc/integration/soc_core.py
litex/soc/interconnect/csr_bus.py

index 3667a6cbbaa9499baafecbed4dbcf765058a88c5..c42086139fb3cba9d7434d332d15e3e466ea0c43 100755 (executable)
@@ -228,7 +228,7 @@ class SoCBusHandler(Module):
             self.logger.error(self)
             raise
         if master.data_width != self.data_width:
-            self.logger.error("{} Bus Master {} from {}-bit to {}-bit.".format(
+            self.logger.info("{} Bus Master {} from {}-bit to {}-bit.".format(
                 colorer(name),
                 colorer("converted", color="yellow"),
                 colorer(master.data_width),
@@ -237,7 +237,9 @@ class SoCBusHandler(Module):
             self.submodules += wishbone.Converter(master, new_master)
             master = new_master
         self.masters[name] = master
-        self.logger.info("{} {} as Bus Master.".format(colorer(name, color="underline"), colorer("added", color="green")))
+        self.logger.info("{} {} as Bus Master.".format(
+            colorer(name,    color="underline"),
+            colorer("added", color="green")))
         # FIXME: handle IO regions
 
     def add_slave(self, name=None, slave=None, region=None):
@@ -404,6 +406,7 @@ class SoCCSRHandler(SoCLocHandler):
         self.address_width = address_width
         self.alignment     = alignment
         self.paging        = paging
+        self.masters       = {}
         self.logger.info("{}-bit CSR Bus, {}KiB Address Space, {}B Paging (Up to {} Locations).\n".format(
             colorer(self.data_width),
             colorer(2**self.address_width/2**10),
@@ -415,7 +418,38 @@ class SoCCSRHandler(SoCLocHandler):
         for name, n in reserved_csrs.items():
             self.add(name, n)
 
-        self.logger.info(colorer("CSR Bus Handler created.", color="cyan"))
+        self.logger.info(colorer("CSR Handler created.", color="cyan"))
+
+    # 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(self)
+            raise
+        print(master)
+        if master.data_width != self.data_width:
+            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")))
+            raise
+        self.masters[name] = master
+        self.logger.info("{} {} as CSR Master.".format(
+            colorer(name,    color="underline"),
+            colorer("added", color="green")))
+        # FIXME: handle IO regions
+
+    # Address map ----------------------------------------------------------------------------------
+    def address_map(self, name, memory):
+        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")))
+            raise
+        return self.locs[name]
 
     # Str ------------------------------------------------------------------------------------------
     def __str__(self):
@@ -615,6 +649,7 @@ class SoC(Module):
             data_width    = self.csr.data_width))
         csr_size = 2**(self.csr.address_width + 2)
         self.bus.add_slave("csr", self.csr_bridge.wishbone, SoCRegion(origin=origin, size=csr_size))
+        self.csr.add_master(name="bridge", master=self.csr_bridge.csr)
 
     # SoC finalization -----------------------------------------------------------------------------
     def do_finalize(self):
@@ -635,6 +670,34 @@ class SoC(Module):
                 slaves         = bus_slaves,
                 register       = True,
                 timeout_cycles = self.bus.timeout)
+        if hasattr(self, "ctrl") and self.bus.timeout is not None:
+            self.comb += self.ctrl.bus_error.eq(self.bus_interconnect.timeout.error)
+
+        # 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
+        )
+        if len(self.csr.masters):
+            self.submodules.csr_interconnect = csr_bus.InterconnectShared(
+                masters = list(self.csr.masters.values()),
+                slaves  = self.csr_bankarray.get_buses())
+
+        # SoC IRQ Interconnect ---------------------------------------------------------------------
+        if hasattr(self, "cpu"):
+            if hasattr(self.cpu, "interrupt"):
+                for name, loc in sorted(self.irq.locs.items()):
+                    if name in self.cpu.interrupts.keys():
+                        continue
+                    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.comb += self.cpu.interrupt[loc].eq(module.ev.irq)
+                    self.add_constant(name + "_INTERRUPT", loc)
 
 # Test (FIXME: move to litex/text and improve) -----------------------------------------------------
 
index 044503810697942cac43e937cc0dd9b460bf94cf..9f2f6c6d7a0cb4750efa9943ec09a9e88f1d48d8 100644 (file)
@@ -102,9 +102,6 @@ class SoCCore(SoC):
         self.config      = {}
         self.csr_regions = {}
 
-        # CSR masters list
-        self._csr_masters = []
-
         # Parameters managment ---------------------------------------------------------------------
         if cpu_type == "None":
             cpu_type = None
@@ -234,7 +231,6 @@ class SoCCore(SoC):
         self.add_config("CSR_ALIGNMENT", csr_alignment)
         if with_wishbone:
             self.add_csr_bridge(self.soc_mem_map["csr"])
-            self.add_csr_master(self.csr_bridge.csr) # FIXME
 
     # Methods --------------------------------------------------------------------------------------
 
@@ -258,12 +254,6 @@ class SoCCore(SoC):
                 break
         self.bus.add_slave(name=wb_name, slave=interface)
 
-    def add_csr_master(self, csrm):
-        # CSR masters are not arbitrated, use this with precaution.
-        if self.finalized:
-            raise FinalizeError
-        self._csr_masters.append(csrm)
-
     def check_io_region(self, name, origin, length):
         for region_origin, region_length in self.soc_io_regions.items():
             if (origin >= region_origin) & ((origin + length) < (region_origin + region_length)):
@@ -326,30 +316,13 @@ class SoCCore(SoC):
 
         SoC.do_finalize(self)
 
-        # Add the Wishbone Masters/Slaves interconnect
-        if hasattr(self, "ctrl") and (self.wishbone_timeout_cycles is not None):
-            self.comb += self.ctrl.bus_error.eq(self.bus_interconnect.timeout.error)
-
-        # 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,
-            alignment     = self.csr_alignment
-        )
-
-        # Add CSRs interconnect
-        if len(self._csr_masters) != 0:
-            self.submodules.csrcon = csr_bus.InterconnectShared(
-                self._csr_masters, self.csrbankarray.get_buses())
-
         # Check and add CSRs regions
-        for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
+        for name, csrs, mapaddr, rmap in self.csr_bankarray.banks:
             self.add_csr_region(name, (self.soc_mem_map["csr"] + 0x800*mapaddr),
                 self.csr_data_width, csrs)
 
         # Check and add Memory regions
-        for name, memory, mapaddr, mmap in self.csrbankarray.srams:
+        for name, memory, mapaddr, mmap in self.csr_bankarray.srams:
             self.add_csr_region(name + "_" + memory.name_override,
                 (self.soc_mem_map["csr"] + 0x800*mapaddr),
                 self.csr_data_width, memory)
@@ -358,22 +331,11 @@ class SoCCore(SoC):
         self.csr_regions = {k: v for k, v in sorted(self.csr_regions.items(), key=lambda item: item[1].origin)}
 
         # Add CSRs / Config items to constants
-        for name, constant in self.csrbankarray.constants:
+        for name, constant in self.csr_bankarray.constants:
             self.add_constant(name.upper() + "_" + constant.name.upper(), constant.value.value)
         for name, value in self.config.items():
             self.add_config(name, value)
 
-        # Connect interrupts
-        if hasattr(self.cpu, "interrupt"):
-            for _name, _id in sorted(self.irq.locs.items()):
-                if _name in self.cpu.interrupts.keys():
-                    continue
-                if hasattr(self, _name):
-                    module = getattr(self, _name)
-                    assert hasattr(module, 'ev'), "Submodule %s does not have EventManager (xx.ev) module" % _name
-                    self.comb += self.cpu.interrupt[_id].eq(module.ev.irq)
-                self.constants[_name.upper() + "_INTERRUPT"] = _id
-
 # SoCCore arguments --------------------------------------------------------------------------------
 
 def soc_core_args(parser):
index 215ac66641fb07c048cec9cbab20ae380c5d4988..8642edbc4475fa9a931dbdbe671d16edb9608d2e 100644 (file)
@@ -33,9 +33,12 @@ _layout = [
 
 class Interface(Record):
     def __init__(self, data_width=8, address_width=14, alignment=32):
-        self.alignment = alignment
+        self.data_width    = data_width
+        self.address_width = address_width
+        self.alignment     = alignment
         Record.__init__(self, set_layout_parameters(_layout,
-            data_width=data_width, address_width=address_width))
+            data_width    = data_width,
+            address_width = address_width))
 
     @classmethod
     def like(self, other):