self.software_packages.append((name, src_dir))
def _generate_includes(self):
- cpu_type = self.soc.cpu_type
- memory_regions = self.soc.get_memory_regions()
- flash_boot_address = getattr(self.soc, "flash_boot_address", None)
- shadow_base = getattr(self.soc, "shadow_base", None)
- csr_regions = self.soc.get_csr_regions()
- constants = self.soc.get_constants()
-
- buildinc_dir = os.path.join(self.output_dir, "software", "include")
+ buildinc_dir = os.path.join(self.output_dir, "software", "include")
generated_dir = os.path.join(buildinc_dir, "generated")
os.makedirs(generated_dir, exist_ok=True)
- if cpu_type is not None:
+ if self.soc.cpu_type is not None:
variables_contents = []
def define(k, v):
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
"COPY_TO_MAIN_RAM" : "0",
"EXECUTE_IN_PLACE" : "0"
}
- if "main_ram" in (m[0] for m in memory_regions):
+ if "main_ram" in self.soc.mem_regions.keys():
exec_profiles["COPY_TO_MAIN_RAM"] = "1"
else:
exec_profiles["EXECUTE_IN_PLACE"] = "1"
cpu_interface.get_linker_output_format(self.soc.cpu))
write_to_file(
os.path.join(generated_dir, "regions.ld"),
- cpu_interface.get_linker_regions(memory_regions))
+ cpu_interface.get_linker_regions(self.soc.mem_regions))
write_to_file(
os.path.join(generated_dir, "mem.h"),
- cpu_interface.get_mem_header(memory_regions, flash_boot_address, shadow_base))
+ cpu_interface.get_mem_header(self.soc.mem_regions))
write_to_file(
os.path.join(generated_dir, "csr.h"),
- cpu_interface.get_csr_header(csr_regions, constants))
+ cpu_interface.get_csr_header(self.soc.csr_regions, self.soc.constants))
write_to_file(
os.path.join(generated_dir, "git.h"),
cpu_interface.get_git_header()
self.soc.sdram.controller.settings.timing))
def _generate_csr_map(self, csr_json=None, csr_csv=None):
- memory_regions = self.soc.get_memory_regions()
- csr_regions = self.soc.get_csr_regions()
- constants = self.soc.get_constants()
-
- shadow_base = getattr(self.soc, "shadow_base", None)
- if shadow_base:
- constants.append(('shadow_base', shadow_base))
-
- flash_boot_address = getattr(self.soc, "flash_boot_address", None)
- if flash_boot_address:
- constants.append(('flash_boot_address', flash_boot_address))
-
if csr_json is not None:
csr_dir = os.path.dirname(os.path.realpath(csr_json))
os.makedirs(csr_dir, exist_ok=True)
- write_to_file(csr_json, cpu_interface.get_csr_json(csr_regions, constants, memory_regions))
+ write_to_file(csr_json, cpu_interface.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if csr_csv is not None:
csr_dir = os.path.dirname(os.path.realpath(csr_csv))
os.makedirs(csr_dir, exist_ok=True)
- write_to_file(csr_csv, cpu_interface.get_csr_csv(csr_regions, constants, memory_regions))
+ write_to_file(csr_csv, cpu_interface.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
def _prepare_software(self):
for name, src_dir in self.software_packages:
from migen import *
+# Helpers ----------------------------------------------------------------------------------------
+
def mem_decoder(address, size=0x10000000):
address &= ~0x80000000
size = 2**log2_int(size, False)
data[int(base, 16)//4 + i] = struct.unpack(">I", w)[0]
i += 1
return data
+
+# SoC primitives -----------------------------------------------------------------------------------
+
+def SoCConstant(value):
+ return value
+
+class SoCMemRegion:
+ def __init__(self, origin, length):
+ self.origin = origin
+ self.length = length
+
+class SoCCSRRegion:
+ def __init__(self, origin, busword, obj):
+ self.origin = origin
+ self.busword = busword
+ self.obj = obj
from litex.build.tools import generated_banner
-# Helpers ----------------------------------------------------------------------------------------
-
-# FIXME: use OrderedDict for constants?
-def get_constant(name, constants):
- for n, v in constants:
- if n == name:
- return v
- return None
-
# CPU files ----------------------------------------------------------------------------------------
def get_cpu_mak(cpu, compile_software):
def get_linker_regions(regions):
r = "MEMORY {\n"
- for name, origin, length in regions:
- r += "\t{} : ORIGIN = 0x{:08x}, LENGTH = 0x{:08x}\n".format(name, origin, length)
+ for name, region in regions.items():
+ r += "\t{} : ORIGIN = 0x{:08x}, LENGTH = 0x{:08x}\n".format(name, region.origin, region.length)
r += "}\n"
return r
r += "#endif\n"
return r
-def get_mem_header(regions, flash_boot_address, shadow_base):
+def get_mem_header(regions):
r = generated_banner("//")
r += "#ifndef __GENERATED_MEM_H\n#define __GENERATED_MEM_H\n\n"
- for name, base, size in regions:
+ for name, region in regions.items():
r += "#define {name}_BASE 0x{base:08x}L\n#define {name}_SIZE 0x{size:08x}\n\n".format(
- name=name.upper(), base=base, size=size)
- if flash_boot_address is not None:
- r += "#define FLASH_BOOT_ADDRESS 0x{:08x}L\n\n".format(flash_boot_address)
- if shadow_base is not None:
- r += "#define SHADOW_BASE 0x{:08x}L\n\n".format(shadow_base)
+ name=name.upper(), base=region.origin, size=region.length)
r += "#endif\n"
return r
-
def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions):
r = ""
def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000):
- alignment = get_constant("CONFIG_CSR_ALIGNMENT", constants)
+ alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32)
r = generated_banner("//")
r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
if with_access_functions:
r += "#else /* ! CSR_ACCESSORS_DEFINED */\n"
r += "#include <hw/common.h>\n"
r += "#endif /* ! CSR_ACCESSORS_DEFINED */\n"
- for name, origin, busword, obj in regions:
+ 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(obj, Memory):
- for csr in obj:
- nr = (csr.size + busword - 1)//busword
- r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, busword, alignment,
+ if not isinstance(region.obj, Memory):
+ for csr in region.obj:
+ nr = (csr.size + region.busword - 1)//region.busword
+ r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, region.busword, alignment,
isinstance(csr, CSRStatus), with_access_functions)
origin += alignment//8*nr
if hasattr(csr, "fields"):
r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_SIZE "+str(field.size)+"\n"
r += "\n/* constants */\n"
- for name, value in constants:
+ for name, value in constants.items():
if value is None:
r += "#define "+name+"\n"
continue
# JSON Export --------------------------------------------------------------------------------------
-def get_csr_json(csr_regions=[], constants=[], memory_regions=[]):
- alignment = 32 if constants is None else get_constant("CONFIG_CSR_ALIGNMENT", constants)
+def get_csr_json(csr_regions={}, constants={}, mem_regions={}):
+ alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32)
d = {
"csr_bases": {},
"memories": {},
}
- for name, origin, busword, obj in csr_regions:
- d["csr_bases"][name] = origin
- if not isinstance(obj, Memory):
- for csr in obj:
- size = (csr.size + busword - 1)//busword
+ for name, region in csr_regions.items():
+ d["csr_bases"][name] = region.origin
+ region_origin = region.origin
+ if not isinstance(region.obj, Memory):
+ for csr in region.obj:
+ size = (csr.size + region.busword - 1)//region.busword
d["csr_registers"][name + "_" + csr.name] = {
- "addr": origin,
+ "addr": region_origin,
"size": size,
"type": "ro" if isinstance(csr, CSRStatus) else "rw"
}
- origin += alignment//8*size
+ region_origin += alignment//8*size
- for name, value in constants:
+ for name, value in constants.items():
d["constants"][name.lower()] = value.lower() if isinstance(value, str) else value
- for name, origin, length in memory_regions:
+ for name, region in mem_regions.items():
d["memories"][name.lower()] = {
- "base": origin,
- "size": length
+ "base": region.origin,
+ "size": region.length
}
return json.dumps(d, indent=4)
# CSV Export --------------------------------------------------------------------------------------
-def get_csr_csv(csr_regions=[], constants=[], memory_regions=[]):
- d = json.loads(get_csr_json(csr_regions, constants, memory_regions))
+def get_csr_csv(csr_regions={}, constants={}, mem_regions={}):
+ d = json.loads(get_csr_json(csr_regions, constants, mem_regions))
r = generated_banner("#")
for name, value in d["csr_bases"].items():
r += "csr_base,{},0x{:08x},,\n".format(name, value)
self.platform = platform
self.clk_freq = clk_freq
- # config dictionary (store all SoC's parameters to be exported to software)
- self.config = dict()
-
- # SoC's register/interrupt/memory mappings (default or user defined + dynamically allocateds)
+ # SoC's CSR/Mem/Interrupt mapping (default or user defined + dynamically allocateds)
self.soc_csr_map = {}
self.soc_interrupt_map = {}
self.soc_mem_map = self.mem_map
- # Regions / Constants lists
- self._memory_regions = [] # (name, origin, length)
- self._csr_regions = [] # (name, origin, busword, csr_list/Memory)
- self._constants = [] # (name, value)
+ # SoC's Config/Constants/Regions
+ self.config = {}
+ self.constants = {}
+ self.mem_regions = {}
+ self.csr_regions = {}
# Wishbone masters/slaves lists
self._wb_masters = []
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 != []
def add_memory_region(self, name, origin, length):
def in_this_region(addr):
return addr >= origin and addr < origin + length
- for n, o, l in self._memory_regions:
- l = 2**log2_int(l, False)
- if n == name or in_this_region(o) or in_this_region(o+l-1):
+ for n, r in self.mem_regions.items():
+ r.length = 2**log2_int(r.length, False)
+ if n == name or in_this_region(r.origin) or in_this_region(r.origin + r.length - 1):
raise ValueError("Memory region conflict between {} and {}".format(n, name))
-
- self._memory_regions.append((name, origin, length))
+ self.mem_regions[name] = SoCMemRegion(origin, length)
def register_mem(self, name, address, interface, size=0x10000000):
self.add_wb_slave(address, interface, size)
self.add_wb_slave(self.soc_mem_map["rom"], interface, rom_size)
self.add_memory_region("rom", self.cpu.reset_address, rom_size)
- def get_memory_regions(self):
- return self._memory_regions
-
def check_csr_range(self, name, addr):
if addr >= 1<<(self.csr_address_width+2):
raise ValueError("{} CSR out of range, increase csr_address_width".format(name))
def check_csr_region(self, name, origin):
- for n, o, l, obj in self._csr_regions:
- if n == name or o == origin:
+ for n, r in self.csr_regions.items():
+ if n == name or r.origin == origin:
raise ValueError("CSR region conflict between {} and {}".format(n, name))
def add_csr_region(self, name, origin, busword, obj):
self.check_csr_region(name, origin)
- self._csr_regions.append((name, origin, busword, obj))
-
- def get_csr_regions(self):
- return self._csr_regions
+ self.csr_regions[name] = SoCCSRRegion(origin, busword, obj)
def add_constant(self, name, value=None):
- self._constants.append((name, value))
-
- def get_constants(self):
- r = []
- for _name, _id in sorted(self.soc_interrupt_map.items()):
- r.append((_name.upper() + "_INTERRUPT", _id))
- r += self._constants
- return r
+ if name in self.constants.keys():
+ raise ValueError("Constant {} already declared.".format(name))
+ self.constants[name] = SoCConstant(value)
def get_csr_dev_address(self, name, memory):
if memory is not None:
def do_finalize(self):
# Verify CPU has required memories
- registered_mems = {regions[0] for regions in self._memory_regions}
if self.cpu_type is not None:
- for mem in "rom", "sram":
- if mem not in registered_mems:
- raise FinalizeError("CPU needs \"{}\" to be registered with SoC.register_mem()".format(mem))
+ for name in "rom", "sram":
+ if name not in self.mem_regions.keys():
+ raise FinalizeError("CPU needs \"{}\" to be registered with SoC.register_mem()".format(name))
# Add the Wishbone Masters/Slaves interconnect
if len(self._wb_masters):
# Add CSRs / Config items to constants
for name, constant in self.csrbankarray.constants:
- self._constants.append(((name + "_" + constant.name).upper(), constant.value.value))
+ self.add_constant(name + "_" + constant.name, constant.value.value)
for name, value in sorted(self.config.items(), key=itemgetter(0)):
- self._constants.append(("CONFIG_" + name.upper(), value))
+ self.add_constant("CONFIG_" + name.upper(), value)
if isinstance(value, str):
- self._constants.append(("CONFIG_" + name.upper() + "_" + value, 1))
+ self.add_constant("CONFIG_" + name.upper() + "_" + value)
# Connect interrupts
if hasattr(self, "cpu"):
module = getattr(self, _name)
assert hasattr(module, 'ev'), "Submodule %s does not have EventManager (xx.ev) module" % _name
self.comb += self.cpu.interrupt[_id].eq(module.ev.irq)
-
+ self.constants[_name.upper() + "_INTERRUPT"] = _id
# SoCCore arguments --------------------------------------------------------------------------------