Add SVD export capability to Builder (csr_svd parameter) and targets (--csr-svd argument) and fix svd regression.

This allows generating SVD export files during the build as we are already doing for .csv or .json.

Use with Builder:
builder = Builder(soc, csr_svd="csr.svd")

Use with target:
./arty.py --csr-svd=csr.svd
This commit is contained in:
Florent Kermarrec 2020-03-06 08:36:52 +01:00
parent e124aed9a2
commit e2dab06386
3 changed files with 43 additions and 37 deletions

View File

@ -32,7 +32,7 @@ def generate_svd(soc, buildpath, filename=None, name="soc", **kwargs):
filename = name + ".svd" filename = name + ".svd"
kwargs["name"] = name kwargs["name"] = name
with open(buildpath + "/" + filename, "w", encoding="utf-8") as svd: with open(buildpath + "/" + filename, "w", encoding="utf-8") as svd:
svd.write(export.get_svd(soc, **kwargs)) svd.write(export.get_csr_svd(soc, **kwargs))
def generate_docs(soc, base_dir, def generate_docs(soc, base_dir,

View File

@ -14,7 +14,7 @@ import struct
import shutil import shutil
from litex.build.tools import write_to_file from litex.build.tools import write_to_file
from litex.soc.integration import cpu_interface, soc_core from litex.soc.integration import export, soc_core
__all__ = ["soc_software_packages", "soc_directory", __all__ = ["soc_software_packages", "soc_directory",
"Builder", "builder_args", "builder_argdict"] "Builder", "builder_args", "builder_argdict"]
@ -45,7 +45,8 @@ class Builder:
compile_software = True, compile_software = True,
compile_gateware = True, compile_gateware = True,
csr_json = None, csr_json = None,
csr_csv = None): csr_csv = None,
csr_svd = None):
self.soc = soc self.soc = soc
# From Python doc: makedirs() will become confused if the path # From Python doc: makedirs() will become confused if the path
@ -58,8 +59,9 @@ class Builder:
self.compile_software = compile_software self.compile_software = compile_software
self.compile_gateware = compile_gateware self.compile_gateware = compile_gateware
self.csr_csv = csr_csv self.csr_csv = csr_csv
self.csr_json = csr_json self.csr_json = csr_json
self.csr_svd = csr_svd
self.software_packages = [] self.software_packages = []
for name in soc_software_packages: for name in soc_software_packages:
@ -79,7 +81,7 @@ class Builder:
def define(k, v): def define(k, v):
variables_contents.append("{}={}\n".format(k, _makefile_escape(v))) variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
for k, v in cpu_interface.get_cpu_mak(self.soc.cpu, self.compile_software): for k, v in export.get_cpu_mak(self.soc.cpu, self.compile_software):
define(k, v) define(k, v)
# Distinguish between LiteX and MiSoC. # Distinguish between LiteX and MiSoC.
define("LITEX", "1") define("LITEX", "1")
@ -106,25 +108,25 @@ class Builder:
"".join(variables_contents)) "".join(variables_contents))
write_to_file( write_to_file(
os.path.join(self.generated_dir, "output_format.ld"), os.path.join(self.generated_dir, "output_format.ld"),
cpu_interface.get_linker_output_format(self.soc.cpu)) export.get_linker_output_format(self.soc.cpu))
write_to_file( write_to_file(
os.path.join(self.generated_dir, "regions.ld"), os.path.join(self.generated_dir, "regions.ld"),
cpu_interface.get_linker_regions(self.soc.mem_regions)) export.get_linker_regions(self.soc.mem_regions))
write_to_file( write_to_file(
os.path.join(self.generated_dir, "mem.h"), os.path.join(self.generated_dir, "mem.h"),
cpu_interface.get_mem_header(self.soc.mem_regions)) export.get_mem_header(self.soc.mem_regions))
write_to_file( write_to_file(
os.path.join(self.generated_dir, "soc.h"), os.path.join(self.generated_dir, "soc.h"),
cpu_interface.get_soc_header(self.soc.constants)) export.get_soc_header(self.soc.constants))
write_to_file( write_to_file(
os.path.join(self.generated_dir, "csr.h"), os.path.join(self.generated_dir, "csr.h"),
cpu_interface.get_csr_header(self.soc.csr_regions, export.get_csr_header(self.soc.csr_regions,
self.soc.constants) self.soc.constants)
) )
write_to_file( write_to_file(
os.path.join(self.generated_dir, "git.h"), os.path.join(self.generated_dir, "git.h"),
cpu_interface.get_git_header() export.get_git_header()
) )
if hasattr(self.soc, "sdram"): if hasattr(self.soc, "sdram"):
@ -134,16 +136,21 @@ class Builder:
self.soc.sdram.controller.settings.phy, self.soc.sdram.controller.settings.phy,
self.soc.sdram.controller.settings.timing)) self.soc.sdram.controller.settings.timing))
def _generate_csr_map(self, csr_json=None, csr_csv=None): def _generate_csr_map(self):
if csr_json is not None: if self.csr_json is not None:
csr_dir = os.path.dirname(os.path.realpath(csr_json)) csr_dir = os.path.dirname(os.path.realpath(self.csr_json))
os.makedirs(csr_dir, exist_ok=True) os.makedirs(csr_dir, exist_ok=True)
write_to_file(csr_json, cpu_interface.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions)) write_to_file(self.csr_json, export.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if csr_csv is not None: if self.csr_csv is not None:
csr_dir = os.path.dirname(os.path.realpath(csr_csv)) csr_dir = os.path.dirname(os.path.realpath(self.csr_csv))
os.makedirs(csr_dir, exist_ok=True) os.makedirs(csr_dir, exist_ok=True)
write_to_file(csr_csv, cpu_interface.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions)) write_to_file(self.csr_csv, export.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
if self.csr_svd is not None:
svd_dir = os.path.dirname(os.path.realpath(self.csr_svd))
os.makedirs(svd_dir, exist_ok=True)
write_to_file(self.csr_svd, export.get_csr_svd(self.soc))
def _prepare_software(self): def _prepare_software(self):
for name, src_dir in self.software_packages: for name, src_dir in self.software_packages:
@ -180,7 +187,7 @@ class Builder:
if not self.soc.integrated_rom_initialized: if not self.soc.integrated_rom_initialized:
self._initialize_rom() self._initialize_rom()
self._generate_csr_map(self.csr_json, self.csr_csv) self._generate_csr_map()
if "run" not in kwargs: if "run" not in kwargs:
kwargs["run"] = self.compile_gateware kwargs["run"] = self.compile_gateware
@ -214,17 +221,21 @@ def builder_args(parser):
parser.add_argument("--csr-json", default=None, parser.add_argument("--csr-json", default=None,
help="store CSR map in JSON format into the " help="store CSR map in JSON format into the "
"specified file") "specified file")
parser.add_argument("--csr-svd", default=None,
help="store CSR map in SVD format into the "
"specified file")
def builder_argdict(args): def builder_argdict(args):
return { return {
"output_dir": args.output_dir, "output_dir": args.output_dir,
"gateware_dir": args.gateware_dir, "gateware_dir": args.gateware_dir,
"software_dir": args.software_dir, "software_dir": args.software_dir,
"include_dir": args.include_dir, "include_dir": args.include_dir,
"generated_dir": args.generated_dir, "generated_dir": args.generated_dir,
"compile_software": not args.no_compile_software, "compile_software": not args.no_compile_software,
"compile_gateware": not args.no_compile_gateware, "compile_gateware": not args.no_compile_gateware,
"csr_csv": args.csr_csv, "csr_csv": args.csr_csv,
"csr_json": args.csr_json, "csr_json": args.csr_json,
"csr_svd": args.csr_svd,
} }

View File

@ -281,7 +281,7 @@ def get_csr_csv(csr_regions={}, constants={}, mem_regions={}):
# SVD Export -------------------------------------------------------------------------------------- # SVD Export --------------------------------------------------------------------------------------
def get_svd(soc, vendor="litex", name="soc", description=None): def get_csr_svd(soc, vendor="litex", name="soc", description=None):
def sub_csr_bit_range(busword, csr, offset): def sub_csr_bit_range(busword, csr, offset):
nwords = (csr.size + busword - 1)//busword nwords = (csr.size + busword - 1)//busword
i = nwords - offset - 1 i = nwords - offset - 1
@ -337,17 +337,12 @@ def get_svd(soc, vendor="litex", name="soc", description=None):
interrupts[csr] = irq interrupts[csr] = irq
documented_regions = [] documented_regions = []
for name, region in soc.csr.regions.items():
raw_regions = []
if hasattr(soc, "get_csr_regions"):
raw_regions = soc.get_csr_regions()
else:
for region_name, region in soc.csr_regions.items():
raw_regions.append((region_name, region.origin,
region.busword, region.obj))
for csr_region in raw_regions:
documented_regions.append(DocumentedCSRRegion( documented_regions.append(DocumentedCSRRegion(
csr_region, csr_data_width=soc.csr_data_width)) name = name,
region = region,
csr_data_width = soc.csr.data_width)
)
svd = [] svd = []
svd.append('<?xml version="1.0" encoding="utf-8"?>') svd.append('<?xml version="1.0" encoding="utf-8"?>')