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>
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
21 __all__
= ["soc_software_packages", "soc_directory",
22 "Builder", "builder_args", "builder_argdict"]
25 soc_software_packages
= [
33 soc_directory
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(__file__
), ".."))
36 def _makefile_escape(s
):
37 return s
.replace("\\", "\\\\")
41 def __init__(self
, soc
,
47 compile_software
= True,
48 compile_gateware
= True,
55 # From Python doc: makedirs() will become confused if the path
56 # elements to create include '..'
57 self
.output_dir
= os
.path
.abspath(output_dir
or "soc_{}_{}".format(soc
.__class
__.__name
__.lower(), soc
.platform
.name
))
58 self
.gateware_dir
= os
.path
.abspath(gateware_dir
or os
.path
.join(self
.output_dir
, "gateware"))
59 self
.software_dir
= os
.path
.abspath(software_dir
or os
.path
.join(self
.output_dir
, "software"))
60 self
.include_dir
= os
.path
.abspath(include_dir
or os
.path
.join(self
.software_dir
, "include"))
61 self
.generated_dir
= os
.path
.abspath(generated_dir
or os
.path
.join(self
.include_dir
, "generated"))
63 self
.compile_software
= compile_software
64 self
.compile_gateware
= compile_gateware
65 self
.csr_csv
= csr_csv
66 self
.csr_json
= csr_json
67 self
.csr_svd
= csr_svd
68 self
.memory_x
= memory_x
70 self
.software_packages
= []
71 for name
in soc_software_packages
:
72 self
.add_software_package(name
)
74 def add_software_package(self
, name
, src_dir
=None):
76 src_dir
= os
.path
.join(soc_directory
, "software", name
)
77 self
.software_packages
.append((name
, src_dir
))
79 def _generate_includes(self
):
80 os
.makedirs(self
.include_dir
, exist_ok
=True)
81 os
.makedirs(self
.generated_dir
, exist_ok
=True)
83 if self
.soc
.cpu_type
is not None:
84 variables_contents
= []
86 variables_contents
.append("{}={}\n".format(k
, _makefile_escape(v
)))
88 for k
, v
in export
.get_cpu_mak(self
.soc
.cpu
, self
.compile_software
):
90 # Distinguish between LiteX and MiSoC.
92 # Distinguish between applications running from main RAM and
93 # flash for user-provided software packages.
95 "COPY_TO_MAIN_RAM" : "0",
96 "EXECUTE_IN_PLACE" : "0"
98 if "main_ram" in self
.soc
.mem_regions
.keys():
99 exec_profiles
["COPY_TO_MAIN_RAM"] = "1"
101 exec_profiles
["EXECUTE_IN_PLACE"] = "1"
102 for k
, v
in exec_profiles
.items():
105 "COMPILER_RT_DIRECTORY",
106 get_data_mod("software", "compiler_rt").data_location
)
107 define("SOC_DIRECTORY", soc_directory
)
108 variables_contents
.append("export BUILDINC_DIRECTORY\n")
109 define("BUILDINC_DIRECTORY", self
.include_dir
)
110 for name
, src_dir
in self
.software_packages
:
111 define(name
.upper() + "_DIRECTORY", src_dir
)
114 os
.path
.join(self
.generated_dir
, "variables.mak"),
115 "".join(variables_contents
))
117 os
.path
.join(self
.generated_dir
, "output_format.ld"),
118 export
.get_linker_output_format(self
.soc
.cpu
))
120 os
.path
.join(self
.generated_dir
, "regions.ld"),
121 export
.get_linker_regions(self
.soc
.mem_regions
))
124 os
.path
.join(self
.generated_dir
, "mem.h"),
125 export
.get_mem_header(self
.soc
.mem_regions
))
127 os
.path
.join(self
.generated_dir
, "soc.h"),
128 export
.get_soc_header(self
.soc
.constants
))
130 os
.path
.join(self
.generated_dir
, "csr.h"),
131 export
.get_csr_header(self
.soc
.csr_regions
,
135 os
.path
.join(self
.generated_dir
, "git.h"),
136 export
.get_git_header()
139 if hasattr(self
.soc
, "sdram"):
140 from litedram
.init
import get_sdram_phy_c_header
141 write_to_file(os
.path
.join(self
.generated_dir
, "sdram_phy.h"),
142 get_sdram_phy_c_header(
143 self
.soc
.sdram
.controller
.settings
.phy
,
144 self
.soc
.sdram
.controller
.settings
.timing
))
146 def _generate_csr_map(self
):
147 if self
.csr_json
is not None:
148 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_json
))
149 os
.makedirs(csr_dir
, exist_ok
=True)
150 write_to_file(self
.csr_json
, export
.get_csr_json(self
.soc
.csr_regions
, self
.soc
.constants
, self
.soc
.mem_regions
))
152 if self
.csr_csv
is not None:
153 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_csv
))
154 os
.makedirs(csr_dir
, exist_ok
=True)
155 write_to_file(self
.csr_csv
, export
.get_csr_csv(self
.soc
.csr_regions
, self
.soc
.constants
, self
.soc
.mem_regions
))
157 if self
.csr_svd
is not None:
158 svd_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_svd
))
159 os
.makedirs(svd_dir
, exist_ok
=True)
160 write_to_file(self
.csr_svd
, export
.get_csr_svd(self
.soc
))
162 def _generate_mem_region_map(self
):
163 if self
.memory_x
is not None:
164 memory_x_dir
= os
.path
.dirname(os
.path
.realpath(self
.memory_x
))
165 os
.makedirs(memory_x_dir
, exist_ok
=True)
166 write_to_file(self
.memory_x
, export
.get_memory_x(self
.soc
))
168 def _prepare_rom_software(self
):
169 for name
, src_dir
in self
.software_packages
:
170 dst_dir
= os
.path
.join(self
.software_dir
, name
)
171 os
.makedirs(dst_dir
, exist_ok
=True)
173 def _generate_rom_software(self
, compile_bios
=True):
174 for name
, src_dir
in self
.software_packages
:
175 if name
== "bios" and not compile_bios
:
178 dst_dir
= os
.path
.join(self
.software_dir
, name
)
179 makefile
= os
.path
.join(src_dir
, "Makefile")
180 if self
.compile_software
:
181 subprocess
.check_call(["make", "-C", dst_dir
, "-f", makefile
])
183 def _initialize_rom_software(self
):
184 bios_file
= os
.path
.join(self
.software_dir
, "bios", "bios.bin")
185 bios_data
= soc_core
.get_mem_data(bios_file
, self
.soc
.cpu
.endianness
)
186 self
.soc
.initialize_rom(bios_data
)
188 def build(self
, **kwargs
):
189 self
.soc
.platform
.output_dir
= self
.output_dir
190 os
.makedirs(self
.gateware_dir
, exist_ok
=True)
191 os
.makedirs(self
.software_dir
, exist_ok
=True)
195 self
._generate
_includes
()
196 self
._generate
_csr
_map
()
197 self
._generate
_mem
_region
_map
()
198 if self
.soc
.cpu_type
is not None:
199 if self
.soc
.cpu
.use_rom
:
200 self
._prepare
_rom
_software
()
201 self
._generate
_rom
_software
(not self
.soc
.integrated_rom_initialized
)
202 if self
.soc
.integrated_rom_size
and self
.compile_software
:
203 if not self
.soc
.integrated_rom_initialized
:
204 self
._initialize
_rom
_software
()
206 if "run" not in kwargs
:
207 kwargs
["run"] = self
.compile_gateware
208 vns
= self
.soc
.build(build_dir
=self
.gateware_dir
, **kwargs
)
209 self
.soc
.do_exit(vns
=vns
)
213 def builder_args(parser
):
214 parser
.add_argument("--output-dir", default
=None,
215 help="base output directory for generated "
216 "source files and binaries (customizable "
217 "with --{gateware,software,include,generated}-dir)")
218 parser
.add_argument("--gateware-dir", default
=None,
219 help="output directory for gateware files")
220 parser
.add_argument("--software-dir", default
=None,
221 help="base output directory for software files")
222 parser
.add_argument("--include-dir", default
=None,
223 help="output directory for header files")
224 parser
.add_argument("--generated-dir", default
=None,
225 help="output directory for various generated files")
226 parser
.add_argument("--no-compile-software", action
="store_true",
227 help="do not compile the software, only generate "
228 "build infrastructure")
229 parser
.add_argument("--no-compile-gateware", action
="store_true",
230 help="do not compile the gateware, only generate "
231 "HDL source files and build scripts")
232 parser
.add_argument("--csr-csv", default
=None,
233 help="store CSR map in CSV format into the "
235 parser
.add_argument("--csr-json", default
=None,
236 help="store CSR map in JSON format into the "
238 parser
.add_argument("--csr-svd", default
=None,
239 help="store CSR map in SVD format into the "
241 parser
.add_argument("--memory-x", default
=None,
242 help="store Mem regions in memory-x format into the "
246 def builder_argdict(args
):
248 "output_dir": args
.output_dir
,
249 "gateware_dir": args
.gateware_dir
,
250 "software_dir": args
.software_dir
,
251 "include_dir": args
.include_dir
,
252 "generated_dir": args
.generated_dir
,
253 "compile_software": not args
.no_compile_software
,
254 "compile_gateware": not args
.no_compile_gateware
,
255 "csr_csv": args
.csr_csv
,
256 "csr_json": args
.csr_json
,
257 "csr_svd": args
.csr_svd
,
258 "memory_x": args
.memory_x
,