From 2899928aba932d5fa93902d9a2ef6a169f1c76b7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 15 Aug 2019 09:26:25 +0200 Subject: [PATCH] cpu_interface: add json csr map export, simplify csv csr map export using json --- litex/soc/integration/builder.py | 27 ++++++---- litex/soc/integration/cpu_interface.py | 70 ++++++++++++++++++-------- 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index 81c66b7db..28fc145aa 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -1,5 +1,5 @@ # This file is Copyright (c) 2015 Sebastien Bourdeauducq -# This file is Copyright (c) 2015-2018 Florent Kermarrec +# This file is Copyright (c) 2015-2019 Florent Kermarrec # This file is Copyright (c) 2019 Mateusz Holenko # This file is Copyright (c) 2018 Peter Gielda # This file is Copyright (c) 2018 Sergiusz Bazanski @@ -41,7 +41,7 @@ class Builder: def __init__(self, soc, output_dir=None, compile_software=True, compile_gateware=True, gateware_toolchain_path=None, - csr_csv=None): + csr_json=None, csr_csv=None): self.soc = soc if output_dir is None: output_dir = "soc_{}_{}".format( @@ -54,6 +54,7 @@ class Builder: self.compile_gateware = compile_gateware self.gateware_toolchain_path = gateware_toolchain_path self.csr_csv = csr_csv + self.csr_json = csr_json self.software_packages = [] for name in soc_software_packages: @@ -128,7 +129,7 @@ class Builder: self.soc.sdram.controller.settings.phy, self.soc.sdram.controller.settings.timing)) - def _generate_csr_csv(self): + 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() @@ -141,11 +142,15 @@ class Builder: if flash_boot_address: constants.append(('flash_boot_address', flash_boot_address)) - csr_dir = os.path.dirname(os.path.realpath(self.csr_csv)) - os.makedirs(csr_dir, exist_ok=True) - write_to_file( - self.csr_csv, - cpu_interface.get_csr_csv(csr_regions, constants, memory_regions)) + 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)) + + 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)) def _prepare_software(self): for name, src_dir in self.software_packages: @@ -180,8 +185,7 @@ class Builder: if not self.soc.integrated_rom_initialized: self._initialize_rom() - if self.csr_csv is not None: - self._generate_csr_csv() + self._generate_csr_map(self.csr_json, self.csr_csv) if self.gateware_toolchain_path is not None: toolchain_path = self.gateware_toolchain_path @@ -209,6 +213,9 @@ def builder_args(parser): parser.add_argument("--csr-csv", default=None, help="store CSR map in CSV format into the " "specified file") + parser.add_argument("--csr-json", default=None, + help="store CSR map in JSON format into the " + "specified file") def builder_argdict(args): diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index 067e1d47c..7eaeb5154 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -13,6 +13,7 @@ # License: BSD import os +import json from shutil import which from migen import * @@ -192,30 +193,55 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b r += "\n#endif\n" return r - -def get_csr_csv(csr_regions=None, constants=None, memory_regions=None): +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("#") - - if csr_regions is not None: - for name, origin, busword, obj in csr_regions: - r += "csr_base,{},0x{:08x},,\n".format(name, origin) - - for name, origin, busword, obj in csr_regions: - if not isinstance(obj, Memory): - for csr in obj: - nr = (csr.size + busword - 1)//busword - r += "csr_register,{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw") - origin += alignment//8*nr - - if constants is not None: - for name, value in constants: - r += "constant,{},{},,\n".format(name.lower(), value) - - if memory_regions is not None: - for name, origin, length in memory_regions: - r += "memory_region,{},0x{:08x},{:d},\n".format(name.lower(), origin, length) - + 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():