diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index 06678bcb8..4c8df1aa9 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -36,18 +36,25 @@ def _makefile_escape(s): class Builder: - def __init__(self, soc, output_dir=None, + def __init__(self, soc, + output_dir=None, + gateware_dir=None, + software_dir=None, + include_dir=None, + generated_dir=None, compile_software=True, compile_gateware=True, gateware_toolchain_path=None, csr_json=None, csr_csv=None): self.soc = soc - if output_dir is None: - output_dir = "soc_{}_{}".format( - soc.__class__.__name__.lower(), - soc.platform.name) + # From Python doc: makedirs() will become confused if the path # elements to create include '..' - self.output_dir = os.path.abspath(output_dir) + self.output_dir = os.path.abspath(output_dir or "soc_{}_{}".format(soc.__class__.__name__.lower(), 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")) + self.compile_software = compile_software self.compile_gateware = compile_gateware self.gateware_toolchain_path = gateware_toolchain_path @@ -64,14 +71,14 @@ class Builder: self.software_packages.append((name, src_dir)) def _generate_includes(self): - buildinc_dir = os.path.join(self.output_dir, "software", "include") - generated_dir = os.path.join(buildinc_dir, "generated") - os.makedirs(generated_dir, exist_ok=True) + os.makedirs(self.include_dir, exist_ok=True) + os.makedirs(self.generated_dir, exist_ok=True) if self.soc.cpu_type is not None: variables_contents = [] def define(k, 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): define(k, v) # Distinguish between LiteX and MiSoC. @@ -90,37 +97,39 @@ class Builder: define(k, v) define("SOC_DIRECTORY", soc_directory) variables_contents.append("export BUILDINC_DIRECTORY\n") - define("BUILDINC_DIRECTORY", buildinc_dir) + define("BUILDINC_DIRECTORY", self.include_dir) for name, src_dir in self.software_packages: define(name.upper() + "_DIRECTORY", src_dir) + write_to_file( - os.path.join(generated_dir, "variables.mak"), + os.path.join(self.generated_dir, "variables.mak"), "".join(variables_contents)) write_to_file( - os.path.join(generated_dir, "output_format.ld"), + os.path.join(self.generated_dir, "output_format.ld"), cpu_interface.get_linker_output_format(self.soc.cpu)) write_to_file( - os.path.join(generated_dir, "regions.ld"), + os.path.join(self.generated_dir, "regions.ld"), cpu_interface.get_linker_regions(self.soc.mem_regions)) + write_to_file( - os.path.join(generated_dir, "mem.h"), + os.path.join(self.generated_dir, "mem.h"), cpu_interface.get_mem_header(self.soc.mem_regions)) write_to_file( - os.path.join(generated_dir, "soc.h"), + os.path.join(self.generated_dir, "soc.h"), cpu_interface.get_soc_header(self.soc.constants)) write_to_file( - os.path.join(generated_dir, "csr.h"), + os.path.join(self.generated_dir, "csr.h"), cpu_interface.get_csr_header(self.soc.csr_regions, self.soc.constants) ) write_to_file( - os.path.join(generated_dir, "git.h"), + os.path.join(self.generated_dir, "git.h"), cpu_interface.get_git_header() ) if hasattr(self.soc, "sdram"): from litedram.init import get_sdram_phy_c_header - write_to_file(os.path.join(generated_dir, "sdram_phy.h"), + write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"), get_sdram_phy_c_header( self.soc.sdram.controller.settings.phy, self.soc.sdram.controller.settings.timing)) @@ -138,7 +147,7 @@ class Builder: def _prepare_software(self): for name, src_dir in self.software_packages: - dst_dir = os.path.join(self.output_dir, "software", name) + dst_dir = os.path.join(self.software_dir, name) os.makedirs(dst_dir, exist_ok=True) def _generate_software(self, compile_bios=True): @@ -146,20 +155,20 @@ class Builder: if name == "bios" and not compile_bios: pass else: - dst_dir = os.path.join(self.output_dir, "software", name) + 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(self): - bios_file = os.path.join(self.output_dir, "software", "bios","bios.bin") + bios_file = os.path.join(self.software_dir, "bios", "bios.bin") bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness) self.soc.initialize_rom(bios_data) def build(self, toolchain_path=None, **kwargs): self.soc.platform.output_dir = self.output_dir - os.makedirs(os.path.join(self.output_dir, "gateware"), exist_ok=True) - os.makedirs(os.path.join(self.output_dir, "software"), exist_ok=True) + os.makedirs(self.gateware_dir, exist_ok=True) + os.makedirs(self.software_dir, exist_ok=True) self.soc.finalize() @@ -178,7 +187,7 @@ class Builder: if "run" not in kwargs: kwargs["run"] = self.compile_gateware - vns = self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"), + vns = self.soc.build(build_dir=self.gateware_dir, toolchain_path=toolchain_path, **kwargs) self.soc.do_exit(vns=vns) return vns @@ -186,8 +195,17 @@ class Builder: def builder_args(parser): parser.add_argument("--output-dir", default=None, - help="output directory for generated " - "source files and binaries") + 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") @@ -208,6 +226,10 @@ def builder_args(parser): def builder_argdict(args): return { "output_dir": args.output_dir, + "gateware_dir": args.gateware_dir, + "software_dir": args.software_dir, + "include_dir": args.include_dir, + "generated_dir": args.generated_dir, "compile_software": not args.no_compile_software, "compile_gateware": not args.no_compile_gateware, "gateware_toolchain_path": args.gateware_toolchain_path,