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.
This commit is contained in:
Florent Kermarrec 2022-11-15 12:03:11 +01:00
parent 703bd16a96
commit 4baeeed946
2 changed files with 50 additions and 38 deletions

View File

@ -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}

View File

@ -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"):