From: Florent Kermarrec Date: Sun, 29 Sep 2019 15:23:01 +0000 (+0200) Subject: soc/integration: rename cpu_interface to export (with retro-compat), re-arrange a... X-Git-Tag: 24jan2021_ls180~961 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=334ae336bfb98c388d28bc0c03609bdebcf46197;p=litex.git soc/integration: rename cpu_interface to export (with retro-compat), re-arrange a bit, add separators --- diff --git a/litex/soc/integration/__init__.py b/litex/soc/integration/__init__.py index 8a97adbd..1c9d9b4b 100644 --- a/litex/soc/integration/__init__.py +++ b/litex/soc/integration/__init__.py @@ -1,2 +1,6 @@ + from litex.soc.integration.soc_core import SoCCore from litex.soc.integration.soc_sdram import SoCSDRAM + +# FIXME: retro-compat 2019-09-29 +from litex.soc.integration import export as cpu_interface diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py deleted file mode 100644 index 0134fc9f..00000000 --- a/litex/soc/integration/cpu_interface.py +++ /dev/null @@ -1,266 +0,0 @@ -# This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq -# This file is Copyright (c) 2014-2019 Florent Kermarrec -# This file is Copyright (c) 2018 Dolu1990 -# This file is Copyright (c) 2019 Gabriel L. Somlo -# This file is Copyright (c) 2018 Jean-François Nguyen -# This file is Copyright (c) 2019 Mateusz Holenko -# This file is Copyright (c) 2013 Robert Jordens -# This file is Copyright (c) 2018 Sean Cross -# This file is Copyright (c) 2018 Sergiusz Bazanski -# This file is Copyright (c) 2018-2016 Tim 'mithro' Ansell -# This file is Copyright (c) 2015 whitequark -# This file is Copyright (c) 2018 William D. Jones -# License: BSD - -import os -import json -from shutil import which -from sysconfig import get_platform - -from migen import * - -from litex.soc.interconnect.csr import CSRStatus - -from litex.build.tools import generated_banner - -# FIXME: use OrderedDict for constants? -def get_constant(name, constants): - for n, v in constants: - if n == name: - return v - return None - -def get_cpu_mak(cpu, compile_software): - # select between clang and gcc - clang = os.getenv("CLANG", "") - if clang != "": - clang = bool(int(clang)) - else: - clang = None - if not hasattr(cpu, "clang_triple"): - if clang: - raise ValueError(cpu.name + "not supported with clang.") - else: - clang = False - else: - # Default to gcc unless told otherwise - if clang is None: - clang = False - assert isinstance(clang, bool) - if clang: - triple = cpu.clang_triple - flags = cpu.clang_flags - else: - triple = cpu.gcc_triple - flags = cpu.gcc_flags - - # select triple when more than one - def select_triple(triple): - r = None - if not isinstance(triple, tuple): - triple = (triple,) - p = get_platform() - for i in range(len(triple)): - t = triple[i] - # use native toolchain if host and target platforms are the same - if t == 'riscv64-unknown-elf' and p == 'linux-riscv64': - r = '--native--' - break - if which(t+"-gcc"): - r = t - break - if r is None: - if not compile_software: - return "--not-found--" - msg = "Unable to find any of the cross compilation toolchains:\n" - for i in range(len(triple)): - msg += "- " + triple[i] + "\n" - raise OSError(msg) - return r - - # return informations - return [ - ("TRIPLE", select_triple(triple)), - ("CPU", cpu.name), - ("CPUFLAGS", flags), - ("CPUENDIANNESS", cpu.endianness), - ("CLANG", str(int(clang))) - ] - - -def get_linker_output_format(cpu): - return "OUTPUT_FORMAT(\"" + cpu.linker_output_format + "\")\n" - - -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) - r += "}\n" - return r - - -def get_mem_header(regions, flash_boot_address, shadow_base): - r = generated_banner("//") - r += "#ifndef __GENERATED_MEM_H\n#define __GENERATED_MEM_H\n\n" - for name, base, size in regions: - 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) - r += "#endif\n" - return r - - -def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions): - r = "" - - r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"L\n" - r += "#define CSR_"+reg_name.upper()+"_SIZE "+str(nwords)+"\n" - - size = nwords*busword - if size > 64: - return r - elif size > 32: - ctype = "unsigned long long int" - elif size > 16: - ctype = "unsigned int" - elif size > 8: - ctype = "unsigned short int" - else: - ctype = "unsigned char" - - if with_access_functions: - r += "static inline "+ctype+" "+reg_name+"_read(void) {\n" - if size > 1: - r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+"L);\n" - for byte in range(1, nwords): - r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+alignment//8*byte)+"L);\n" - r += "\treturn r;\n}\n" - else: - r += "\treturn csr_readl("+hex(reg_base)+"L);\n}\n" - - if not read_only: - r += "static inline void "+reg_name+"_write("+ctype+" value) {\n" - for word in range(nwords): - shift = (nwords-word-1)*busword - if shift: - value_shifted = "value >> "+str(shift) - else: - value_shifted = "value" - r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+alignment//8*word)+"L);\n" - r += "}\n" - return 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) - r = generated_banner("//") - r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n" - if with_access_functions: - r += "#include \n" - r += "#ifdef CSR_ACCESSORS_DEFINED\n" - r += "extern void csr_writeb(uint8_t value, unsigned long addr);\n" - r += "extern uint8_t csr_readb(unsigned long addr);\n" - r += "extern void csr_writew(uint16_t value, unsigned long addr);\n" - r += "extern uint16_t csr_readw(unsigned long addr);\n" - r += "extern void csr_writel(uint32_t value, unsigned long addr);\n" - r += "extern uint32_t csr_readl(unsigned long addr);\n" - r += "#else /* ! CSR_ACCESSORS_DEFINED */\n" - r += "#include \n" - r += "#endif /* ! CSR_ACCESSORS_DEFINED */\n" - for name, origin, busword, obj in regions: - 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, - isinstance(csr, CSRStatus), with_access_functions) - origin += alignment//8*nr - if hasattr(csr, "fields"): - for field in csr.fields.fields: - r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_OFFSET "+str(field.offset)+"\n" - 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: - if value is None: - r += "#define "+name+"\n" - continue - if isinstance(value, str): - value = "\"" + value + "\"" - ctype = "const char *" - else: - value = str(value) - ctype = "int" - r += "#define "+name+" "+value+"\n" - if with_access_functions: - r += "static inline "+ctype+" "+name.lower()+"_read(void) {\n" - r += "\treturn "+value+";\n}\n" - - r += "\n#endif\n" - return r - -def get_csr_json(csr_regions=[], constants=[], memory_regions=[]): - alignment = 32 if constants is None else get_constant("CONFIG_CSR_ALIGNMENT", constants) - - d = { - "csr_bases": {}, - "csr_registers": {}, - "constants": {}, - "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 - d["csr_registers"][name + "_" + csr.name] = { - "addr": origin, - "size": size, - "type": "ro" if isinstance(csr, CSRStatus) else "rw" - } - origin += alignment//8*size - - for name, value in constants: - d["constants"][name.lower()] = value.lower() if isinstance(value, str) else value - - for name, origin, length in memory_regions: - d["memories"][name.lower()] = { - "base": origin, - "size": length - } - - return json.dumps(d, indent=4) - -def get_csr_csv(csr_regions=[], constants=[], memory_regions=[]): - d = json.loads(get_csr_json(csr_regions, constants, memory_regions)) - r = generated_banner("#") - for name, value in d["csr_bases"].items(): - r += "csr_base,{},0x{:08x},,\n".format(name, value) - for name in d["csr_registers"].keys(): - r += "csr_register,{},0x{:08x},{},{}\n".format(name, - d["csr_registers"][name]["addr"], - d["csr_registers"][name]["size"], - d["csr_registers"][name]["type"]) - for name, value in d["constants"].items(): - r += "constant,{},{},,\n".format(name, value) - for name in d["memories"].keys(): - r += "memory_region,{},0x{:08x},{:d},\n".format(name, - d["memories"][name]["base"], - d["memories"][name]["size"]) - return r - -def get_git_header(): - from litex.build.tools import get_migen_git_revision, get_litex_git_revision - r = generated_banner("//") - r += "#ifndef __GENERATED_GIT_H\n#define __GENERATED_GIT_H\n\n" - r += "#define MIGEN_GIT_SHA1 \"{}\"\n".format(get_migen_git_revision()) - r += "#define LITEX_GIT_SHA1 \"{}\"\n".format(get_litex_git_revision()) - r += "#endif\n" - return r diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py new file mode 100644 index 00000000..74c1ea24 --- /dev/null +++ b/litex/soc/integration/export.py @@ -0,0 +1,278 @@ +# This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq +# This file is Copyright (c) 2014-2019 Florent Kermarrec +# This file is Copyright (c) 2018 Dolu1990 +# This file is Copyright (c) 2019 Gabriel L. Somlo +# This file is Copyright (c) 2018 Jean-François Nguyen +# This file is Copyright (c) 2019 Mateusz Holenko +# This file is Copyright (c) 2013 Robert Jordens +# This file is Copyright (c) 2018 Sean Cross +# This file is Copyright (c) 2018 Sergiusz Bazanski +# This file is Copyright (c) 2018-2016 Tim 'mithro' Ansell +# This file is Copyright (c) 2015 whitequark +# This file is Copyright (c) 2018 William D. Jones +# License: BSD + +import os +import json +from shutil import which +from sysconfig import get_platform + +from migen import * + +from litex.soc.interconnect.csr import CSRStatus + +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): + # select between clang and gcc + clang = os.getenv("CLANG", "") + if clang != "": + clang = bool(int(clang)) + else: + clang = None + if not hasattr(cpu, "clang_triple"): + if clang: + raise ValueError(cpu.name + "not supported with clang.") + else: + clang = False + else: + # Default to gcc unless told otherwise + if clang is None: + clang = False + assert isinstance(clang, bool) + if clang: + triple = cpu.clang_triple + flags = cpu.clang_flags + else: + triple = cpu.gcc_triple + flags = cpu.gcc_flags + + # select triple when more than one + def select_triple(triple): + r = None + if not isinstance(triple, tuple): + triple = (triple,) + p = get_platform() + for i in range(len(triple)): + t = triple[i] + # use native toolchain if host and target platforms are the same + if t == 'riscv64-unknown-elf' and p == 'linux-riscv64': + r = '--native--' + break + if which(t+"-gcc"): + r = t + break + if r is None: + if not compile_software: + return "--not-found--" + msg = "Unable to find any of the cross compilation toolchains:\n" + for i in range(len(triple)): + msg += "- " + triple[i] + "\n" + raise OSError(msg) + return r + + # return informations + return [ + ("TRIPLE", select_triple(triple)), + ("CPU", cpu.name), + ("CPUFLAGS", flags), + ("CPUENDIANNESS", cpu.endianness), + ("CLANG", str(int(clang))) + ] + + +def get_linker_output_format(cpu): + return "OUTPUT_FORMAT(\"" + cpu.linker_output_format + "\")\n" + + +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) + r += "}\n" + return r + + +# C Export ----------------------------------------------------------------------------------------- + +def get_git_header(): + from litex.build.tools import get_migen_git_revision, get_litex_git_revision + r = generated_banner("//") + r += "#ifndef __GENERATED_GIT_H\n#define __GENERATED_GIT_H\n\n" + r += "#define MIGEN_GIT_SHA1 \"{}\"\n".format(get_migen_git_revision()) + r += "#define LITEX_GIT_SHA1 \"{}\"\n".format(get_litex_git_revision()) + r += "#endif\n" + return r + +def get_mem_header(regions, flash_boot_address, shadow_base): + r = generated_banner("//") + r += "#ifndef __GENERATED_MEM_H\n#define __GENERATED_MEM_H\n\n" + for name, base, size in regions: + 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) + r += "#endif\n" + return r + + +def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions): + r = "" + + r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"L\n" + r += "#define CSR_"+reg_name.upper()+"_SIZE "+str(nwords)+"\n" + + size = nwords*busword + if size > 64: + return r + elif size > 32: + ctype = "unsigned long long int" + elif size > 16: + ctype = "unsigned int" + elif size > 8: + ctype = "unsigned short int" + else: + ctype = "unsigned char" + + if with_access_functions: + r += "static inline "+ctype+" "+reg_name+"_read(void) {\n" + if size > 1: + r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+"L);\n" + for byte in range(1, nwords): + r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+alignment//8*byte)+"L);\n" + r += "\treturn r;\n}\n" + else: + r += "\treturn csr_readl("+hex(reg_base)+"L);\n}\n" + + if not read_only: + r += "static inline void "+reg_name+"_write("+ctype+" value) {\n" + for word in range(nwords): + shift = (nwords-word-1)*busword + if shift: + value_shifted = "value >> "+str(shift) + else: + value_shifted = "value" + r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+alignment//8*word)+"L);\n" + r += "}\n" + return 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) + r = generated_banner("//") + r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n" + if with_access_functions: + r += "#include \n" + r += "#ifdef CSR_ACCESSORS_DEFINED\n" + r += "extern void csr_writeb(uint8_t value, unsigned long addr);\n" + r += "extern uint8_t csr_readb(unsigned long addr);\n" + r += "extern void csr_writew(uint16_t value, unsigned long addr);\n" + r += "extern uint16_t csr_readw(unsigned long addr);\n" + r += "extern void csr_writel(uint32_t value, unsigned long addr);\n" + r += "extern uint32_t csr_readl(unsigned long addr);\n" + r += "#else /* ! CSR_ACCESSORS_DEFINED */\n" + r += "#include \n" + r += "#endif /* ! CSR_ACCESSORS_DEFINED */\n" + for name, origin, busword, obj in regions: + 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, + isinstance(csr, CSRStatus), with_access_functions) + origin += alignment//8*nr + if hasattr(csr, "fields"): + for field in csr.fields.fields: + r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_OFFSET "+str(field.offset)+"\n" + 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: + if value is None: + r += "#define "+name+"\n" + continue + if isinstance(value, str): + value = "\"" + value + "\"" + ctype = "const char *" + else: + value = str(value) + ctype = "int" + r += "#define "+name+" "+value+"\n" + if with_access_functions: + r += "static inline "+ctype+" "+name.lower()+"_read(void) {\n" + r += "\treturn "+value+";\n}\n" + + r += "\n#endif\n" + return r + +# JSON Export -------------------------------------------------------------------------------------- + +def get_csr_json(csr_regions=[], constants=[], memory_regions=[]): + alignment = 32 if constants is None else get_constant("CONFIG_CSR_ALIGNMENT", constants) + + d = { + "csr_bases": {}, + "csr_registers": {}, + "constants": {}, + "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 + d["csr_registers"][name + "_" + csr.name] = { + "addr": origin, + "size": size, + "type": "ro" if isinstance(csr, CSRStatus) else "rw" + } + origin += alignment//8*size + + for name, value in constants: + d["constants"][name.lower()] = value.lower() if isinstance(value, str) else value + + for name, origin, length in memory_regions: + d["memories"][name.lower()] = { + "base": origin, + "size": 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)) + r = generated_banner("#") + for name, value in d["csr_bases"].items(): + r += "csr_base,{},0x{:08x},,\n".format(name, value) + for name in d["csr_registers"].keys(): + r += "csr_register,{},0x{:08x},{},{}\n".format(name, + d["csr_registers"][name]["addr"], + d["csr_registers"][name]["size"], + d["csr_registers"][name]["type"]) + for name, value in d["constants"].items(): + r += "constant,{},{},,\n".format(name, value) + for name in d["memories"].keys(): + r += "memory_region,{},0x{:08x},{:d},\n".format(name, + d["memories"][name]["base"], + d["memories"][name]["size"]) + return r