From 1feff1d7d5a8686a458709e7e47dfde0290e7530 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 7 Feb 2020 19:50:35 +0100 Subject: [PATCH] soc: integrate CSR master/interconnect/collection and IRQ collection --- litex/soc/integration/soc.py | 69 +++++++++++++++++++++++++++++-- litex/soc/integration/soc_core.py | 44 ++------------------ litex/soc/interconnect/csr_bus.py | 7 +++- 3 files changed, 74 insertions(+), 46 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 3667a6cb..c4208613 100755 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -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) ----------------------------------------------------- diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 04450381..9f2f6c6d 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -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): diff --git a/litex/soc/interconnect/csr_bus.py b/litex/soc/interconnect/csr_bus.py index 215ac666..8642edbc 100644 --- a/litex/soc/interconnect/csr_bus.py +++ b/litex/soc/interconnect/csr_bus.py @@ -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): -- 2.30.2