From 4baeeed946c1a063661ede45241f329d916bd5d1 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 15 Nov 2022 12:03:11 +0100 Subject: [PATCH] soc/cores/cpu: Add reset_address_check attribute and enable/disable methods and use it to disable CPU Reset Address check in Soc. For designs willing to put the reset address of the CPU in a region not directly handled by LiteX, self.cpu.disable_reset_address_check() can be used in the SoC to disable CPU reset address check. --- litex/soc/cores/cpu/__init__.py | 37 +++++++++++++++--------- litex/soc/integration/soc.py | 51 +++++++++++++++++---------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/litex/soc/cores/cpu/__init__.py b/litex/soc/cores/cpu/__init__.py index 3b39aa2f0..0a5c101c2 100644 --- a/litex/soc/cores/cpu/__init__.py +++ b/litex/soc/cores/cpu/__init__.py @@ -12,7 +12,7 @@ import importlib from migen import * -# CPU ---------------------------------------------------------------------------------------------- +# CPU (Generic) ------------------------------------------------------------------------------------ class CPU(Module): category = None @@ -30,27 +30,36 @@ class CPU(Module): io_regions = {} use_rom = False csr_decode = True - - def __init__(self, *args, **kwargs): - pass + reset_address_check = True def set_reset_address(self, reset_address): - pass + pass # pass must be overloaded (if required) + + def enable_reset_address_check(self): + self.reset_address_check = True + + def disable_reset_address_check(self): + self.reset_address_check = False + +# CPU None (Used for SoC without a CPU) ------------------------------------------------------------ class CPUNone(CPU): - variants = ["standard"] - data_width = 32 - endianness = "little" - reset_address = 0x00000000 - io_regions = {0x0000_0000: 0x1_0000_0000} # origin, length - periph_buses = [] - memory_buses = [] - mem_map = { + variants = ["standard"] + data_width = 32 + endianness = "little" + reset_address = 0x00000000 + reset_address_check = False + io_regions = {0x0000_0000: 0x1_0000_0000} # origin, length + periph_buses = [] + memory_buses = [] + mem_map = { "csr" : 0x0000_0000, "ethmac" : 0x0002_0000, # FIXME: Remove. "spiflash" : 0x1000_0000, # FIXME: Remove. } +# CPUs GCC Triples --------------------------------------------------------------------------------- + CPU_GCC_TRIPLE_RISCV64 = ( "riscv64-pc-linux-musl", "riscv64-unknown-elf", @@ -70,7 +79,7 @@ CPU_GCC_TRIPLE_RISCV32 = CPU_GCC_TRIPLE_RISCV64 + ( "riscv-none-elf", ) -# CPUS --------------------------------------------------------------------------------------------- +# CPUs Collection ---------------------------------------------------------------------------------- def collect_cpus(): cpus = {"None" : CPUNone} diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 53048e47e..47578b320 100755 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1074,14 +1074,13 @@ class SoC(LiteXModule, SoCCoreCompat): # Add Bus Masters/CSR/IRQs. if not isinstance(self.cpu, cpu.CPUNone): # Reset Address. - if hasattr(self.cpu, "set_reset_address"): - if reset_address is None: - reset_address = self.mem_map["rom"] - self.logger.info("CPU {} {} reset address to {}.".format( - colorer(name, color="underline"), - colorer("setting", color="cyan"), - colorer(f"0x{reset_address:08x}"))) - self.cpu.set_reset_address(reset_address) + if reset_address is None: + reset_address = self.mem_map["rom"] + self.logger.info("CPU {} {} reset address to {}.".format( + colorer(name, color="underline"), + colorer("setting", color="cyan"), + colorer(f"0x{reset_address:08x}"))) + self.cpu.set_reset_address(reset_address) # Bus Masters. self.logger.info("CPU {} {} Bus Master(s).".format( @@ -1231,22 +1230,26 @@ class SoC(LiteXModule, SoCCoreCompat): for name, constant in self.csr_bankarray.constants: self.add_constant(name + "_" + constant.name, constant.value.value) - # SoC CPU Check ---------------------------------------------------------------------------- - if not isinstance(self.cpu, cpu.CPUNone): - cpu_reset_address_valid = False - for name, container in self.bus.regions.items(): - if self.bus.check_region_is_in( - region = SoCRegion(origin=self.cpu.reset_address, size=self.bus.data_width//8), - container = container): - cpu_reset_address_valid = True - if name == "rom": - self.cpu.use_rom = True - if not cpu_reset_address_valid: - self.logger.error("CPU needs {} to be in a {} Region.".format( - colorer("reset address 0x{:08x}".format(self.cpu.reset_address)), - colorer("defined", color="red"))) - self.logger.error(self.bus) - raise SoCError() + # SoC CPU Reset Address Check -------------------------------------------------------------- + + # Check if CPU Reset Address is in a defined Region. + cpu_reset_address_valid = False + for name, container in self.bus.regions.items(): + if self.bus.check_region_is_in( + region = SoCRegion(origin=self.cpu.reset_address, size=self.bus.data_width//8), + container = container): + cpu_reset_address_valid = True + # If we have a ROM, make the CPU use it. + if name == "rom": + self.cpu.use_rom = True + + # If CPU Reset Address Check is enabled and Reset Address is invalid, raise SoCError. + if self.cpu.reset_address_check and (not cpu_reset_address_valid): + self.logger.error("CPU needs {} to be in a {} Region.".format( + colorer("reset address 0x{:08x}".format(self.cpu.reset_address)), + colorer("defined", color="red"))) + self.logger.error(self.bus) + raise SoCError() # SoC IRQ Interconnect --------------------------------------------------------------------- if hasattr(self, "cpu") and hasattr(self.cpu, "interrupt"):