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:
parent
703bd16a96
commit
4baeeed946
|
@ -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}
|
||||
|
|
|
@ -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"):
|
||||
|
|
Loading…
Reference in New Issue