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:
Florent Kermarrec 2019-10-09 10:14:14 +02:00
parent e8b90e8009
commit a4ef9b29b9
9 changed files with 60 additions and 19 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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