software: create liblitescard and move sdcard init/test code to it.
[litex.git] / litex / soc / integration / builder.py
1 # This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
2 # This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2018-2019 Antmicro <www.antmicro.com>
4 # This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
5 # This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell <mithro@mithis.com>
6 # This file is Copyright (c) 2018 William D. Jones <thor0505@comcast.net>
7 # This file is Copyright (c) 2020 Xiretza <xiretza@xiretza.xyz>
8 # This file is Copyright (c) 2020 Piotr Esden-Tempski <piotr@esden.net>
9 # License: BSD
10
11
12 import os
13 import subprocess
14 import struct
15 import shutil
16
17 from litex import get_data_mod
18 from litex.build.tools import write_to_file
19 from litex.soc.integration import export, soc_core
20
21 __all__ = ["soc_software_packages", "soc_directory",
22 "Builder", "builder_args", "builder_argdict"]
23
24
25 soc_software_packages = [
26 "libcompiler_rt",
27 "libbase",
28 "liblitedram",
29 "libliteeth",
30 "liblitesdcard",
31 "bios"
32 ]
33
34
35 soc_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
36
37
38 def _makefile_escape(s):
39 return s.replace("\\", "\\\\")
40
41
42 class Builder:
43 def __init__(self, soc,
44 output_dir = None,
45 gateware_dir = None,
46 software_dir = None,
47 include_dir = None,
48 generated_dir = None,
49 compile_software = True,
50 compile_gateware = True,
51 csr_json = None,
52 csr_csv = None,
53 csr_svd = None,
54 memory_x = None,
55 bios_options = None):
56 self.soc = soc
57
58 # From Python doc: makedirs() will become confused if the path
59 # elements to create include '..'
60 self.output_dir = os.path.abspath(output_dir or "soc_{}_{}".format(soc.__class__.__name__.lower(), soc.platform.name))
61 self.gateware_dir = os.path.abspath(gateware_dir or os.path.join(self.output_dir, "gateware"))
62 self.software_dir = os.path.abspath(software_dir or os.path.join(self.output_dir, "software"))
63 self.include_dir = os.path.abspath(include_dir or os.path.join(self.software_dir, "include"))
64 self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated"))
65
66 self.compile_software = compile_software
67 self.compile_gateware = compile_gateware
68 self.csr_csv = csr_csv
69 self.csr_json = csr_json
70 self.csr_svd = csr_svd
71 self.memory_x = memory_x
72 self.bios_options = bios_options
73
74 self.software_packages = []
75 for name in soc_software_packages:
76 self.add_software_package(name)
77
78 def add_software_package(self, name, src_dir=None):
79 if src_dir is None:
80 src_dir = os.path.join(soc_directory, "software", name)
81 self.software_packages.append((name, src_dir))
82
83 def _generate_includes(self):
84 os.makedirs(self.include_dir, exist_ok=True)
85 os.makedirs(self.generated_dir, exist_ok=True)
86
87 if self.soc.cpu_type is not None:
88 variables_contents = []
89 def define(k, v):
90 variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
91
92 for k, v in export.get_cpu_mak(self.soc.cpu, self.compile_software):
93 define(k, v)
94 # Distinguish between LiteX and MiSoC.
95 define("LITEX", "1")
96 # Distinguish between applications running from main RAM and
97 # flash for user-provided software packages.
98 exec_profiles = {
99 "COPY_TO_MAIN_RAM" : "0",
100 "EXECUTE_IN_PLACE" : "0"
101 }
102 if "main_ram" in self.soc.mem_regions.keys():
103 exec_profiles["COPY_TO_MAIN_RAM"] = "1"
104 else:
105 exec_profiles["EXECUTE_IN_PLACE"] = "1"
106 for k, v in exec_profiles.items():
107 define(k, v)
108 define(
109 "COMPILER_RT_DIRECTORY",
110 get_data_mod("software", "compiler_rt").data_location)
111 define("SOC_DIRECTORY", soc_directory)
112 variables_contents.append("export BUILDINC_DIRECTORY\n")
113 define("BUILDINC_DIRECTORY", self.include_dir)
114 for name, src_dir in self.software_packages:
115 define(name.upper() + "_DIRECTORY", src_dir)
116
117 if self.bios_options is not None:
118 for option in self.bios_options:
119 define(option, "1")
120
121 write_to_file(
122 os.path.join(self.generated_dir, "variables.mak"),
123 "".join(variables_contents))
124 write_to_file(
125 os.path.join(self.generated_dir, "output_format.ld"),
126 export.get_linker_output_format(self.soc.cpu))
127 write_to_file(
128 os.path.join(self.generated_dir, "regions.ld"),
129 export.get_linker_regions(self.soc.mem_regions))
130
131 write_to_file(
132 os.path.join(self.generated_dir, "mem.h"),
133 export.get_mem_header(self.soc.mem_regions))
134 write_to_file(
135 os.path.join(self.generated_dir, "soc.h"),
136 export.get_soc_header(self.soc.constants))
137 write_to_file(
138 os.path.join(self.generated_dir, "csr.h"),
139 export.get_csr_header(self.soc.csr_regions,
140 self.soc.constants)
141 )
142 write_to_file(
143 os.path.join(self.generated_dir, "git.h"),
144 export.get_git_header()
145 )
146
147 if hasattr(self.soc, "sdram"):
148 from litedram.init import get_sdram_phy_c_header
149 write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"),
150 get_sdram_phy_c_header(
151 self.soc.sdram.controller.settings.phy,
152 self.soc.sdram.controller.settings.timing))
153
154 def _generate_csr_map(self):
155 if self.csr_json is not None:
156 csr_dir = os.path.dirname(os.path.realpath(self.csr_json))
157 os.makedirs(csr_dir, exist_ok=True)
158 write_to_file(self.csr_json, export.get_csr_json(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
159
160 if self.csr_csv is not None:
161 csr_dir = os.path.dirname(os.path.realpath(self.csr_csv))
162 os.makedirs(csr_dir, exist_ok=True)
163 write_to_file(self.csr_csv, export.get_csr_csv(self.soc.csr_regions, self.soc.constants, self.soc.mem_regions))
164
165 if self.csr_svd is not None:
166 svd_dir = os.path.dirname(os.path.realpath(self.csr_svd))
167 os.makedirs(svd_dir, exist_ok=True)
168 write_to_file(self.csr_svd, export.get_csr_svd(self.soc))
169
170 def _generate_mem_region_map(self):
171 if self.memory_x is not None:
172 memory_x_dir = os.path.dirname(os.path.realpath(self.memory_x))
173 os.makedirs(memory_x_dir, exist_ok=True)
174 write_to_file(self.memory_x, export.get_memory_x(self.soc))
175
176 def _prepare_rom_software(self):
177 for name, src_dir in self.software_packages:
178 dst_dir = os.path.join(self.software_dir, name)
179 os.makedirs(dst_dir, exist_ok=True)
180
181 def _generate_rom_software(self, compile_bios=True):
182 for name, src_dir in self.software_packages:
183 if name == "bios" and not compile_bios:
184 pass
185 else:
186 dst_dir = os.path.join(self.software_dir, name)
187 makefile = os.path.join(src_dir, "Makefile")
188 if self.compile_software:
189 subprocess.check_call(["make", "-C", dst_dir, "-f", makefile])
190
191 def _initialize_rom_software(self):
192 bios_file = os.path.join(self.software_dir, "bios", "bios.bin")
193 bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
194 self.soc.initialize_rom(bios_data)
195
196 def build(self, **kwargs):
197 self.soc.platform.output_dir = self.output_dir
198 os.makedirs(self.gateware_dir, exist_ok=True)
199 os.makedirs(self.software_dir, exist_ok=True)
200
201 self.soc.finalize()
202
203 self._generate_includes()
204 self._generate_csr_map()
205 self._generate_mem_region_map()
206 if self.soc.cpu_type is not None:
207 if self.soc.cpu.use_rom:
208 self._prepare_rom_software()
209 self._generate_rom_software(not self.soc.integrated_rom_initialized)
210 if self.soc.integrated_rom_size and self.compile_software:
211 if not self.soc.integrated_rom_initialized:
212 self._initialize_rom_software()
213
214 if "run" not in kwargs:
215 kwargs["run"] = self.compile_gateware
216 vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
217 self.soc.do_exit(vns=vns)
218 return vns
219
220
221 def builder_args(parser):
222 parser.add_argument("--output-dir", default=None,
223 help="base output directory for generated "
224 "source files and binaries (customizable "
225 "with --{gateware,software,include,generated}-dir)")
226 parser.add_argument("--gateware-dir", default=None,
227 help="output directory for gateware files")
228 parser.add_argument("--software-dir", default=None,
229 help="base output directory for software files")
230 parser.add_argument("--include-dir", default=None,
231 help="output directory for header files")
232 parser.add_argument("--generated-dir", default=None,
233 help="output directory for various generated files")
234 parser.add_argument("--no-compile-software", action="store_true",
235 help="do not compile the software, only generate "
236 "build infrastructure")
237 parser.add_argument("--no-compile-gateware", action="store_true",
238 help="do not compile the gateware, only generate "
239 "HDL source files and build scripts")
240 parser.add_argument("--csr-csv", default=None,
241 help="store CSR map in CSV format into the "
242 "specified file")
243 parser.add_argument("--csr-json", default=None,
244 help="store CSR map in JSON format into the "
245 "specified file")
246 parser.add_argument("--csr-svd", default=None,
247 help="store CSR map in SVD format into the "
248 "specified file")
249 parser.add_argument("--memory-x", default=None,
250 help="store Mem regions in memory-x format into the "
251 "specified file")
252
253
254 def builder_argdict(args):
255 return {
256 "output_dir": args.output_dir,
257 "gateware_dir": args.gateware_dir,
258 "software_dir": args.software_dir,
259 "include_dir": args.include_dir,
260 "generated_dir": args.generated_dir,
261 "compile_software": not args.no_compile_software,
262 "compile_gateware": not args.no_compile_gateware,
263 "csr_csv": args.csr_csv,
264 "csr_json": args.csr_json,
265 "csr_svd": args.csr_svd,
266 "memory_x": args.memory_x,
267 }