cpu_interface: add json csr map export, simplify csv csr map export using json
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 15 Aug 2019 07:26:25 +0000 (09:26 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 15 Aug 2019 07:27:33 +0000 (09:27 +0200)
litex/soc/integration/builder.py
litex/soc/integration/cpu_interface.py

index 81c66b7db14afc6f1feeb9c14954e67a3ce20e6e..28fc145aab562de310c6d3a6b96db42a0d990d49 100644 (file)
@@ -1,5 +1,5 @@
 # This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
-# This file is Copyright (c) 2015-2018 Florent Kermarrec <florent@enjoy-digital.fr>
+# This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
 # This file is Copyright (c) 2019 Mateusz Holenko <mholenko@antmicro.com>
 # This file is Copyright (c) 2018 Peter Gielda <pgielda@antmicro.com>
 # This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
@@ -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):
index 067e1d47c8245fe726c77366d0bb5434cb5a169e..7eaeb5154b25d3a86d34eee04e832cef67b13656 100644 (file)
@@ -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)
-    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)
+    d = {
+        "csr_bases":     {},
+        "csr_registers": {},
+        "constants":     {},
+        "memories":      {},
+    }
 
-        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
+    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
 
-    if constants is not None:
-        for name, value in constants:
-            r += "constant,{},{},,\n".format(name.lower(), value)
+    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
+        }
 
-    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)
+    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():