soc_core/cpu: add io_regions and deprecate shadow_base (with API retro-compat)
The shadow_base parameter has always been difficult to apprehend, replace it with io_regions (uncached regions) defined user or the CPU. The equivalent of a shadow_base parameter of 0x80000000 in the old API is: io_regions = {0x80000000: 0x80000000} # origin, length It's still possible to use shadow_base with retro-compat, but user is encouraged to update and features will be removed in the future.
This commit is contained in:
parent
e8b90e8009
commit
a4ef9b29b9
|
@ -21,6 +21,7 @@ class LM32(CPU):
|
|||
endianness = "big"
|
||||
gcc_triple = "lm32-elf"
|
||||
linker_output_format = "elf32-lm32"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def gcc_flags(self):
|
||||
|
|
|
@ -18,6 +18,7 @@ class Minerva(CPU):
|
|||
endianness = "little"
|
||||
gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed")
|
||||
linker_output_format = "elf32-littleriscv"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def gcc_flags(self):
|
||||
|
|
|
@ -21,6 +21,7 @@ class MOR1KX(CPU):
|
|||
gcc_triple = "or1k-elf"
|
||||
clang_triple = "or1k-linux"
|
||||
linker_output_format = "elf32-or1k"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def mem_map_linux(self):
|
||||
|
@ -31,7 +32,7 @@ class MOR1KX(CPU):
|
|||
"main_ram" : 0x00000000,
|
||||
"rom" : 0x10000000,
|
||||
"sram" : 0x50000000,
|
||||
"csr" : 0x60000000,
|
||||
"csr" : 0xe0000000,
|
||||
}
|
||||
|
||||
@property
|
||||
|
|
|
@ -36,6 +36,7 @@ class PicoRV32(CPU):
|
|||
endianness = "little"
|
||||
gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed")
|
||||
linker_output_format = "elf32-littleriscv"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def gcc_flags(self):
|
||||
|
|
|
@ -56,6 +56,7 @@ class RocketRV64(CPU):
|
|||
endianness = "little"
|
||||
gcc_triple = ("riscv64-unknown-elf")
|
||||
linker_output_format = "elf64-littleriscv"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def mem_map(self):
|
||||
|
|
|
@ -80,6 +80,7 @@ class VexRiscv(CPU, AutoCSR):
|
|||
endianness = "little"
|
||||
gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed")
|
||||
linker_output_format = "elf32-littleriscv"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
@property
|
||||
def mem_map_linux(self):
|
||||
|
|
|
@ -110,8 +110,7 @@ class Builder:
|
|||
write_to_file(
|
||||
os.path.join(generated_dir, "csr.h"),
|
||||
cpu_interface.get_csr_header(self.soc.csr_regions,
|
||||
self.soc.constants,
|
||||
shadow_base=self.soc.shadow_base)
|
||||
self.soc.constants)
|
||||
)
|
||||
write_to_file(
|
||||
os.path.join(generated_dir, "git.h"),
|
||||
|
|
|
@ -156,7 +156,7 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_onl
|
|||
return r
|
||||
|
||||
|
||||
def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000):
|
||||
def get_csr_header(regions, constants, with_access_functions=True):
|
||||
alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32)
|
||||
r = generated_banner("//")
|
||||
r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
|
||||
|
@ -174,8 +174,6 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b
|
|||
r += "#endif /* ! CSR_ACCESSORS_DEFINED */\n"
|
||||
for name, region in regions.items():
|
||||
origin = region.origin
|
||||
if not with_shadow_base:
|
||||
origin &= (~shadow_base)
|
||||
r += "\n/* "+name+" */\n"
|
||||
r += "#define CSR_"+name.upper()+"_BASE "+hex(origin)+"L\n"
|
||||
if not isinstance(region.obj, Memory):
|
||||
|
|
|
@ -69,16 +69,16 @@ class SoCCore(Module):
|
|||
csr_map = {}
|
||||
interrupt_map = {}
|
||||
mem_map = {
|
||||
"rom": 0x00000000, # (default shadow @0x80000000)
|
||||
"sram": 0x01000000, # (default shadow @0x81000000)
|
||||
"csr": 0x02000000, # (default shadow @0x82000000)
|
||||
"main_ram": 0x40000000, # (default shadow @0xc0000000)
|
||||
"rom": 0x00000000,
|
||||
"sram": 0x01000000,
|
||||
"main_ram": 0x40000000,
|
||||
"csr": 0x82000000,
|
||||
}
|
||||
io_regions = {}
|
||||
|
||||
def __init__(self, platform, clk_freq,
|
||||
# CPU parameters
|
||||
cpu_type="vexriscv", cpu_reset_address=0x00000000, cpu_variant=None,
|
||||
# MEM MAP parameters
|
||||
shadow_base=0x80000000,
|
||||
# ROM parameters
|
||||
integrated_rom_size=0, integrated_rom_init=[],
|
||||
# SRAM parameters
|
||||
|
@ -96,7 +96,8 @@ class SoCCore(Module):
|
|||
# Controller parameters
|
||||
with_ctrl=True,
|
||||
# Wishbone parameters
|
||||
with_wishbone=True, wishbone_timeout_cycles=1e6):
|
||||
with_wishbone=True, wishbone_timeout_cycles=1e6,
|
||||
**kwargs):
|
||||
self.platform = platform
|
||||
self.clk_freq = clk_freq
|
||||
|
||||
|
@ -104,6 +105,7 @@ class SoCCore(Module):
|
|||
self.soc_csr_map = {}
|
||||
self.soc_interrupt_map = {}
|
||||
self.soc_mem_map = self.mem_map
|
||||
self.soc_io_regions = self.io_regions
|
||||
|
||||
# SoC's Config/Constants/Regions
|
||||
self.config = {}
|
||||
|
@ -118,6 +120,8 @@ class SoCCore(Module):
|
|||
# CSR masters list
|
||||
self._csr_masters = []
|
||||
|
||||
self.add_retro_compat(kwargs)
|
||||
|
||||
# Parameters managment ---------------------------------------------------------------------
|
||||
if cpu_type == "None":
|
||||
cpu_type = None
|
||||
|
@ -128,9 +132,6 @@ class SoCCore(Module):
|
|||
self.cpu_type = cpu_type
|
||||
self.cpu_variant = cpu.check_format_cpu_variant(cpu_variant)
|
||||
|
||||
self.shadow_base = shadow_base
|
||||
self.config["SHADOW_BASE"] = shadow_base
|
||||
|
||||
self.integrated_rom_size = integrated_rom_size
|
||||
self.integrated_rom_initialized = integrated_rom_init != []
|
||||
self.integrated_sram_size = integrated_sram_size
|
||||
|
@ -174,6 +175,9 @@ class SoCCore(Module):
|
|||
# Update Memory Map (if defined by CPU)
|
||||
self.soc_mem_map.update(self.cpu.mem_map)
|
||||
|
||||
# Update IO Regions (if defined by CPU)
|
||||
self.soc_io_regions.update(self.cpu.io_regions)
|
||||
|
||||
# Set reset address
|
||||
self.cpu.set_reset_address(self.soc_mem_map["rom"] if integrated_rom_size else cpu_reset_address)
|
||||
self.config["CPU_RESET_ADDR"] = self.cpu.reset_address
|
||||
|
@ -348,7 +352,20 @@ class SoCCore(Module):
|
|||
raise FinalizeError
|
||||
self._csr_masters.append(csrm)
|
||||
|
||||
def add_memory_region(self, name, origin, length):
|
||||
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)):
|
||||
return
|
||||
msg = "{} region: 0x{:08x}-0x{:x} not located in an IO region.\n".format(
|
||||
name, origin, origin + length - 1)
|
||||
msg += "Avalaible IO regions:\n"
|
||||
for region_origin, region_length in self.soc_io_regions.items():
|
||||
msg += "- 0x{:08x}-0x{:x}\n".format(region_origin, region_origin + region_length - 1)
|
||||
raise ValueError(msg)
|
||||
|
||||
def add_memory_region(self, name, origin, length, io_region=False):
|
||||
if io_region:
|
||||
self.check_io_region(name, origin, length)
|
||||
def in_this_region(addr):
|
||||
return addr >= origin and addr < origin + length
|
||||
for n, r in self.mem_regions.items():
|
||||
|
@ -375,6 +392,7 @@ class SoCCore(Module):
|
|||
raise ValueError("CSR region conflict between {} and {}".format(n, name))
|
||||
|
||||
def add_csr_region(self, name, origin, busword, obj):
|
||||
self.check_io_region(name, origin, 0x800)
|
||||
self.check_csr_region(name, origin)
|
||||
self.csr_regions[name] = SoCCSRRegion(origin, busword, obj)
|
||||
|
||||
|
@ -433,14 +451,14 @@ class SoCCore(Module):
|
|||
# Check and add CSRs regions
|
||||
for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
|
||||
self.check_csr_range(name, 0x800*mapaddr)
|
||||
self.add_csr_region(name, (self.soc_mem_map["csr"] + 0x800*mapaddr) | self.shadow_base,
|
||||
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:
|
||||
self.check_csr_range(name, 0x800*mapaddr)
|
||||
self.add_csr_region(name + "_" + memory.name_override,
|
||||
(self.soc_mem_map["csr"] + 0x800*mapaddr) | self.shadow_base,
|
||||
(self.soc_mem_map["csr"] + 0x800*mapaddr),
|
||||
self.csr_data_width, memory)
|
||||
|
||||
# Add CSRs / Config items to constants
|
||||
|
@ -464,6 +482,26 @@ class SoCCore(Module):
|
|||
self.comb += self.cpu.interrupt[_id].eq(module.ev.irq)
|
||||
self.constants[_name.upper() + "_INTERRUPT"] = _id
|
||||
|
||||
|
||||
# API retro-compatibility layer ----------------------------------------------------------------
|
||||
# Allow user to build the design the old API for ~3 months after the API change is introduced.
|
||||
# Adds warning and artificical delay to encourage user to update.
|
||||
|
||||
def add_retro_compat(self, kwargs):
|
||||
# 2019-10-09 : deprecate shadow_base, introduce io_regions
|
||||
if "shadow_base" in kwargs.keys():
|
||||
deprecated_warning(": shadow_base replaced by IO regions.")
|
||||
self.retro_compat_shadow_base = kwargs.get("shadow_base", 0x80000000)
|
||||
self.config["SHADOW_BASE"] = self.retro_compat_shadow_base
|
||||
|
||||
def __getattr__(self, name):
|
||||
# 2019-10-09: deprecate shadow_base, introduce io_regions
|
||||
if name == "shadow_base":
|
||||
deprecated_warning(": shadow_base replaced by IO regions.")
|
||||
return self.retro_compat_shadow_base
|
||||
else:
|
||||
return Module.__getattr__(self, name)
|
||||
|
||||
# SoCCore arguments --------------------------------------------------------------------------------
|
||||
|
||||
def soc_core_args(parser):
|
||||
|
|
Loading…
Reference in New Issue