soc/integration/builder: Cleanup and add comments.
This commit is contained in:
parent
cba4642444
commit
21273ffe87
|
@ -22,67 +22,91 @@ from litex.build.tools import write_to_file
|
|||
from litex.soc.integration import export, soc_core
|
||||
from litex.soc.cores import cpu
|
||||
|
||||
__all__ = [
|
||||
"soc_software_packages",
|
||||
"soc_directory",
|
||||
"Builder",
|
||||
"builder_args",
|
||||
"builder_argdict"
|
||||
]
|
||||
|
||||
|
||||
soc_software_packages = [
|
||||
"libcompiler_rt",
|
||||
"libbase",
|
||||
"liblitedram",
|
||||
"libliteeth",
|
||||
"liblitespi",
|
||||
"libfatfs",
|
||||
"liblitesdcard",
|
||||
"liblitesata",
|
||||
"bios"
|
||||
]
|
||||
|
||||
|
||||
soc_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
# Helpers ------------------------------------------------------------------------------------------
|
||||
|
||||
def _makefile_escape(s):
|
||||
return s.replace("\\", "\\\\")
|
||||
|
||||
def _create_dir(d):
|
||||
os.makedirs(os.path.realpath(d), exist_ok=True)
|
||||
|
||||
# Software Packages --------------------------------------------------------------------------------
|
||||
|
||||
soc_software_packages = [
|
||||
# Compiler-RT.
|
||||
"libcompiler_rt",
|
||||
|
||||
# LiteX cores.
|
||||
"libbase",
|
||||
|
||||
# LiteX Ecosystem cores.
|
||||
"libfatfs",
|
||||
"liblitespi",
|
||||
"liblitedram",
|
||||
"libliteeth",
|
||||
"liblitesdcard",
|
||||
"liblitesata",
|
||||
|
||||
# BIOS.
|
||||
"bios"
|
||||
]
|
||||
|
||||
# Builder ------------------------------------------------------------------------------------------
|
||||
|
||||
soc_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
compiler_rt_directory = get_data_mod("software", "compiler_rt").data_location
|
||||
|
||||
class Builder:
|
||||
def __init__(self, soc,
|
||||
# Directories.
|
||||
output_dir = None,
|
||||
gateware_dir = None,
|
||||
software_dir = None,
|
||||
include_dir = None,
|
||||
generated_dir = None,
|
||||
|
||||
# Compile Options.
|
||||
compile_software = True,
|
||||
compile_gateware = True,
|
||||
|
||||
# Exports.
|
||||
csr_json = None,
|
||||
csr_csv = None,
|
||||
csr_svd = None,
|
||||
memory_x = None,
|
||||
|
||||
# BIOS Options.
|
||||
bios_options = [],
|
||||
|
||||
# Documentation.
|
||||
generate_doc = False):
|
||||
|
||||
self.soc = soc
|
||||
|
||||
# From Python doc: makedirs() will become confused if the path elements to create include '..'
|
||||
# Directories.
|
||||
self.output_dir = os.path.abspath(output_dir or os.path.join("build", soc.platform.name))
|
||||
self.gateware_dir = os.path.abspath(gateware_dir or os.path.join(self.output_dir, "gateware"))
|
||||
self.software_dir = os.path.abspath(software_dir or os.path.join(self.output_dir, "software"))
|
||||
self.include_dir = os.path.abspath(include_dir or os.path.join(self.software_dir, "include"))
|
||||
self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated"))
|
||||
|
||||
# Compile Options.
|
||||
self.compile_software = compile_software
|
||||
self.compile_gateware = compile_gateware
|
||||
|
||||
# Exports.
|
||||
self.csr_csv = csr_csv
|
||||
self.csr_json = csr_json
|
||||
self.csr_svd = csr_svd
|
||||
self.memory_x = memory_x
|
||||
|
||||
# BIOS Options.
|
||||
self.bios_options = bios_options
|
||||
|
||||
# Documentation
|
||||
self.generate_doc = generate_doc
|
||||
|
||||
# List software packages.
|
||||
self.software_packages = []
|
||||
for name in soc_software_packages:
|
||||
self.add_software_package(name)
|
||||
|
@ -93,130 +117,164 @@ class Builder:
|
|||
self.software_packages.append((name, src_dir))
|
||||
|
||||
def _generate_includes(self):
|
||||
os.makedirs(self.include_dir, exist_ok=True)
|
||||
os.makedirs(self.generated_dir, exist_ok=True)
|
||||
# Generate Include/Generated directories.
|
||||
_create_dir(self.include_dir)
|
||||
_create_dir(self.generated_dir)
|
||||
|
||||
if self.soc.cpu_type not in [None, "zynq7000"]:
|
||||
# Generate BIOS files when the SoC uses it.
|
||||
with_bios = self.soc.cpu_type not in [None, "zynq7000"]
|
||||
if with_bios:
|
||||
|
||||
# Generate Variables to variables.mak.
|
||||
variables_contents = []
|
||||
def define(k, v):
|
||||
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
|
||||
variables_contents.append("{}={}".format(k, _makefile_escape(v)))
|
||||
|
||||
# Define the CPU variables.
|
||||
for k, v in export.get_cpu_mak(self.soc.cpu, self.compile_software):
|
||||
define(k, v)
|
||||
define(
|
||||
"COMPILER_RT_DIRECTORY",
|
||||
get_data_mod("software", "compiler_rt").data_location)
|
||||
|
||||
# Define the SoC/Compiler-RT/Software/Include directories.
|
||||
define("SOC_DIRECTORY", soc_directory)
|
||||
variables_contents.append("export BUILDINC_DIRECTORY\n")
|
||||
define("COMPILER_RT_DIRECTORY", compiler_rt_directory)
|
||||
variables_contents.append("export BUILDINC_DIRECTORY")
|
||||
define("BUILDINC_DIRECTORY", self.include_dir)
|
||||
for name, src_dir in self.software_packages:
|
||||
define(name.upper() + "_DIRECTORY", src_dir)
|
||||
|
||||
# Define the BIOS Options.
|
||||
for bios_option in self.bios_options:
|
||||
assert bios_option in ["TERM_NO_HIST", "TERM_MINI", "TERM_NO_COMPLETE"]
|
||||
define(bios_option, "1")
|
||||
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "variables.mak"),
|
||||
"".join(variables_contents))
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "output_format.ld"),
|
||||
export.get_linker_output_format(self.soc.cpu))
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "regions.ld"),
|
||||
export.get_linker_regions(self.soc.mem_regions))
|
||||
# Write to variables.mak.
|
||||
write_to_file(os.path.join(self.generated_dir, "variables.mak"), "\n".join(variables_contents))
|
||||
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "mem.h"),
|
||||
export.get_mem_header(self.soc.mem_regions))
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "soc.h"),
|
||||
export.get_soc_header(self.soc.constants))
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "csr.h"),
|
||||
export.get_csr_header(
|
||||
# Generate Output Format to output_format.ld.
|
||||
output_format_contents = export.get_linker_output_format(self.soc.cpu)
|
||||
write_to_file(os.path.join(self.generated_dir, "output_format.ld"), output_format_contents)
|
||||
|
||||
# Generate Memory Regions to regions.ld.
|
||||
regions_contents = export.get_linker_regions(self.soc.mem_regions)
|
||||
write_to_file(os.path.join(self.generated_dir, "regions.ld"), regions_contents)
|
||||
|
||||
# Generate Memory Regions to mem.h.
|
||||
mem_contents = export.get_mem_header(self.soc.mem_regions)
|
||||
write_to_file(os.path.join(self.generated_dir, "mem.h"), mem_contents)
|
||||
|
||||
# Generate Memory Regions to memory.x if specified.
|
||||
if self.memory_x is not None:
|
||||
memory_x_contents = export.get_memory_x(self.soc)
|
||||
write_to_file(os.path.realpath(self.memory_x), memory_x_contents)
|
||||
|
||||
# Generate SoC Config/Constants to soc.h.
|
||||
soc_contents = export.get_soc_header(self.soc.constants)
|
||||
write_to_file(os.path.join(self.generated_dir, "soc.h"), soc_contents)
|
||||
|
||||
# Generate CSR registers definitions/access functions to csr.h.
|
||||
csr_contents = export.get_csr_header(
|
||||
regions = self.soc.csr_regions,
|
||||
constants = self.soc.constants,
|
||||
csr_base = self.soc.mem_regions['csr'].origin
|
||||
)
|
||||
)
|
||||
write_to_file(
|
||||
os.path.join(self.generated_dir, "git.h"),
|
||||
export.get_git_header()
|
||||
)
|
||||
csr_base = self.soc.mem_regions['csr'].origin)
|
||||
write_to_file(os.path.join(self.generated_dir, "csr.h"), csr_contents)
|
||||
|
||||
# Generate Git SHA1 of tools to git.h
|
||||
git_contents = export.get_git_header()
|
||||
write_to_file(os.path.join(self.generated_dir, "git.h"), git_contents)
|
||||
|
||||
# Generate LiteDRAM C header to sdram_phy.h when the SoC use it.
|
||||
if hasattr(self.soc, "sdram"):
|
||||
from litedram.init import get_sdram_phy_c_header
|
||||
write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"),
|
||||
get_sdram_phy_c_header(
|
||||
sdram_contents = get_sdram_phy_c_header(
|
||||
self.soc.sdram.controller.settings.phy,
|
||||
self.soc.sdram.controller.settings.timing))
|
||||
self.soc.sdram.controller.settings.timing)
|
||||
write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"), sdram_contents)
|
||||
|
||||
def _generate_csr_map(self):
|
||||
# JSON Export.
|
||||
if self.csr_json is not None:
|
||||
csr_dir = os.path.dirname(os.path.realpath(self.csr_json))
|
||||
os.makedirs(csr_dir, exist_ok=True)
|
||||
write_to_file(self.csr_json, export.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
|
||||
csr_json_contents = export.get_csr_json(
|
||||
csr_regions = self.soc.csr_regions,
|
||||
constants = self.soc.constants,
|
||||
mem_regions = self.soc.mem_regions)
|
||||
write_to_file(os.path.realpath(self.csr_json), csr_json_contents)
|
||||
|
||||
# CSV Export.
|
||||
if self.csr_csv is not None:
|
||||
csr_dir = os.path.dirname(os.path.realpath(self.csr_csv))
|
||||
os.makedirs(csr_dir, exist_ok=True)
|
||||
write_to_file(self.csr_csv, export.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
|
||||
csr_csv_contents = export.get_csr_csv(
|
||||
csr_regions = self.soc.csr_regions,
|
||||
constants = self.soc.constants,
|
||||
mem_regions = self.soc.mem_regions)
|
||||
write_to_file(os.path.realpath(self.csr_csv), csr_csv_contents)
|
||||
|
||||
# SVD Export.
|
||||
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 _generate_mem_region_map(self):
|
||||
if self.memory_x is not None:
|
||||
memory_x_dir = os.path.dirname(os.path.realpath(self.memory_x))
|
||||
os.makedirs(memory_x_dir, exist_ok=True)
|
||||
write_to_file(self.memory_x, export.get_memory_x(self.soc))
|
||||
csr_svd_contents = export.get_csr_svd(self.soc)
|
||||
write_to_file(os.path.realpath(self.csr_svd), csr_svd_contents)
|
||||
|
||||
def _prepare_rom_software(self):
|
||||
# Create directories for all software packages.
|
||||
for name, src_dir in self.software_packages:
|
||||
dst_dir = os.path.join(self.software_dir, name)
|
||||
os.makedirs(dst_dir, exist_ok=True)
|
||||
_create_dir(os.path.join(self.software_dir, name))
|
||||
|
||||
def _generate_rom_software(self, compile_bios=True):
|
||||
# Compile all software packages.
|
||||
for name, src_dir in self.software_packages:
|
||||
# Skip BIOS compilation when disabled.
|
||||
if name == "bios" and not compile_bios:
|
||||
pass
|
||||
else:
|
||||
continue
|
||||
# Compile software package.
|
||||
dst_dir = os.path.join(self.software_dir, name)
|
||||
makefile = os.path.join(src_dir, "Makefile")
|
||||
if self.compile_software:
|
||||
subprocess.check_call(["make", "-C", dst_dir, "-f", makefile])
|
||||
|
||||
def _initialize_rom_software(self):
|
||||
# Get BIOS data from compiled BIOS binary.
|
||||
bios_file = os.path.join(self.software_dir, "bios", "bios.bin")
|
||||
bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
|
||||
|
||||
# Initialize SoC with with BIOS data.
|
||||
self.soc.initialize_rom(bios_data)
|
||||
|
||||
def build(self, **kwargs):
|
||||
# Pass Output Directory to Platform.
|
||||
self.soc.platform.output_dir = self.output_dir
|
||||
os.makedirs(self.gateware_dir, exist_ok=True)
|
||||
os.makedirs(self.software_dir, exist_ok=True)
|
||||
|
||||
# Create Gateware/Software directories.
|
||||
_create_dir(self.gateware_dir)
|
||||
_create_dir(self.software_dir)
|
||||
|
||||
# Finalize the SoC.
|
||||
self.soc.finalize()
|
||||
|
||||
# Generate Software Includes/Files.
|
||||
self._generate_includes()
|
||||
|
||||
# Export SoC Mapping.
|
||||
self._generate_csr_map()
|
||||
self._generate_mem_region_map()
|
||||
|
||||
# Compile the BIOS when the SoC uses it.
|
||||
if self.soc.cpu_type is not None:
|
||||
if self.soc.cpu.use_rom:
|
||||
# Prepare/Generate ROM software.
|
||||
self._prepare_rom_software()
|
||||
self._generate_rom_software(not self.soc.integrated_rom_initialized)
|
||||
|
||||
# Initialize ROM.
|
||||
if self.soc.integrated_rom_size and self.compile_software:
|
||||
if not self.soc.integrated_rom_initialized:
|
||||
self._initialize_rom_software()
|
||||
|
||||
# Translate compile_gateware to run.
|
||||
if "run" not in kwargs:
|
||||
kwargs["run"] = self.compile_gateware
|
||||
|
||||
# Build SoC and pass Verilog Name Space to do_exit.
|
||||
vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
|
||||
self.soc.do_exit(vns=vns)
|
||||
|
||||
# Generate SoC Documentation.
|
||||
if self.generate_doc:
|
||||
from litex.soc.doc import generate_docs
|
||||
doc_dir = os.path.join(self.output_dir, "doc")
|
||||
|
@ -225,38 +283,21 @@ class Builder:
|
|||
|
||||
return vns
|
||||
|
||||
# Builder Arguments --------------------------------------------------------------------------------
|
||||
|
||||
def builder_args(parser):
|
||||
parser.add_argument("--output-dir", default=None,
|
||||
help="base output directory for generated "
|
||||
"source files and binaries (customizable "
|
||||
"with --{gateware,software,include,generated}-dir)")
|
||||
parser.add_argument("--gateware-dir", default=None,
|
||||
help="output directory for gateware files")
|
||||
parser.add_argument("--software-dir", default=None,
|
||||
help="base output directory for software files")
|
||||
parser.add_argument("--include-dir", default=None,
|
||||
help="output directory for header files")
|
||||
parser.add_argument("--generated-dir", default=None,
|
||||
help="output directory for various generated files")
|
||||
parser.add_argument("--no-compile-software", action="store_true",
|
||||
help="do not compile the software, only generate "
|
||||
"build infrastructure")
|
||||
parser.add_argument("--no-compile-gateware", action="store_true",
|
||||
help="do not compile the gateware, only generate "
|
||||
"HDL source files and build scripts")
|
||||
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")
|
||||
parser.add_argument("--csr-svd", default=None,
|
||||
help="store CSR map in SVD format into the "
|
||||
"specified file")
|
||||
parser.add_argument("--memory-x", default=None,
|
||||
help="store Mem regions in memory-x format into the "
|
||||
"specified file")
|
||||
parser.add_argument("--doc", action="store_true", help="Generate Documentation")
|
||||
parser.add_argument("--output-dir", default=None, help="Base Output directory (customizable with --{gateware,software,include,generated}-dir).")
|
||||
parser.add_argument("--gateware-dir", default=None, help="Output directory for Gateware files.")
|
||||
parser.add_argument("--software-dir", default=None, help="Output directory for Software files.")
|
||||
parser.add_argument("--include-dir", default=None, help="Output directory for Header files.")
|
||||
parser.add_argument("--generated-dir", default=None, help="Output directory for Generated files.")
|
||||
parser.add_argument("--no-compile-software", action="store_true", help="Disable Software compilation.")
|
||||
parser.add_argument("--no-compile-gateware", action="store_true", help="Disable Gateware compilation.")
|
||||
parser.add_argument("--csr-csv", default=None, help="Write SoC mapping to the specified CSV file.")
|
||||
parser.add_argument("--csr-json", default=None, help="Write SoC mapping to the specified JSON file.")
|
||||
parser.add_argument("--csr-svd", default=None, help="Write SoC mapping to the specified SVD file.")
|
||||
parser.add_argument("--memory-x", default=None, help="Write SoC Memory Regions to the specified Memory-X file.")
|
||||
parser.add_argument("--doc", action="store_true", help="Generate SoC Documentation.")
|
||||
|
||||
|
||||
def builder_argdict(args):
|
||||
|
|
Loading…
Reference in New Issue