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
20 from litex
.soc
.cores
import cpu
23 "soc_software_packages",
31 soc_software_packages
= [
42 soc_directory
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(__file__
), ".."))
45 def _makefile_escape(s
):
46 return s
.replace("\\", "\\\\")
50 def __init__(self
, soc
,
56 compile_software
= True,
57 compile_gateware
= True,
65 # From Python doc: makedirs() will become confused if the path elements to create include '..'
66 self
.output_dir
= os
.path
.abspath(output_dir
or os
.path
.join("build", soc
.platform
.name
))
67 self
.gateware_dir
= os
.path
.abspath(gateware_dir
or os
.path
.join(self
.output_dir
, "gateware"))
68 self
.software_dir
= os
.path
.abspath(software_dir
or os
.path
.join(self
.output_dir
, "software"))
69 self
.include_dir
= os
.path
.abspath(include_dir
or os
.path
.join(self
.software_dir
, "include"))
70 self
.generated_dir
= os
.path
.abspath(generated_dir
or os
.path
.join(self
.include_dir
, "generated"))
72 self
.compile_software
= compile_software
73 self
.compile_gateware
= compile_gateware
74 self
.csr_csv
= csr_csv
75 self
.csr_json
= csr_json
76 self
.csr_svd
= csr_svd
77 self
.memory_x
= memory_x
78 self
.bios_options
= bios_options
80 self
.software_packages
= []
81 for name
in soc_software_packages
:
82 self
.add_software_package(name
)
84 def add_software_package(self
, name
, src_dir
=None):
86 src_dir
= os
.path
.join(soc_directory
, "software", name
)
87 self
.software_packages
.append((name
, src_dir
))
89 def _generate_includes(self
):
90 os
.makedirs(self
.include_dir
, exist_ok
=True)
91 os
.makedirs(self
.generated_dir
, exist_ok
=True)
93 if self
.soc
.cpu_type
not in [None, "zynq7000"]:
94 variables_contents
= []
96 variables_contents
.append("{}={}\n".format(k
, _makefile_escape(v
)))
98 for k
, v
in export
.get_cpu_mak(self
.soc
.cpu
, self
.compile_software
):
101 "COMPILER_RT_DIRECTORY",
102 get_data_mod("software", "compiler_rt").data_location
)
103 define("SOC_DIRECTORY", soc_directory
)
104 variables_contents
.append("export BUILDINC_DIRECTORY\n")
105 define("BUILDINC_DIRECTORY", self
.include_dir
)
106 for name
, src_dir
in self
.software_packages
:
107 define(name
.upper() + "_DIRECTORY", src_dir
)
109 if self
.bios_options
is not None:
110 for option
in self
.bios_options
:
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(
132 regions
= self
.soc
.csr_regions
,
133 constants
= self
.soc
.constants
,
134 csr_base
= self
.soc
.mem_regions
['csr'].origin
138 os
.path
.join(self
.generated_dir
, "git.h"),
139 export
.get_git_header()
142 if hasattr(self
.soc
, "sdram"):
143 from litedram
.init
import get_sdram_phy_c_header
144 write_to_file(os
.path
.join(self
.generated_dir
, "sdram_phy.h"),
145 get_sdram_phy_c_header(
146 self
.soc
.sdram
.controller
.settings
.phy
,
147 self
.soc
.sdram
.controller
.settings
.timing
))
149 def _generate_csr_map(self
):
150 if self
.csr_json
is not None:
151 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_json
))
152 os
.makedirs(csr_dir
, exist_ok
=True)
153 write_to_file(self
.csr_json
, export
.get_csr_json(self
.soc
.csr_regions
, self
.soc
.constants
, self
.soc
.mem_regions
))
155 if self
.csr_csv
is not None:
156 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_csv
))
157 os
.makedirs(csr_dir
, exist_ok
=True)
158 write_to_file(self
.csr_csv
, export
.get_csr_csv(self
.soc
.csr_regions
, self
.soc
.constants
, self
.soc
.mem_regions
))
160 if self
.csr_svd
is not None:
161 svd_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_svd
))
162 os
.makedirs(svd_dir
, exist_ok
=True)
163 write_to_file(self
.csr_svd
, export
.get_csr_svd(self
.soc
))
165 def _generate_mem_region_map(self
):
166 if self
.memory_x
is not None:
167 memory_x_dir
= os
.path
.dirname(os
.path
.realpath(self
.memory_x
))
168 os
.makedirs(memory_x_dir
, exist_ok
=True)
169 write_to_file(self
.memory_x
, export
.get_memory_x(self
.soc
))
171 def _prepare_rom_software(self
):
172 for name
, src_dir
in self
.software_packages
:
173 dst_dir
= os
.path
.join(self
.software_dir
, name
)
174 os
.makedirs(dst_dir
, exist_ok
=True)
176 def _generate_rom_software(self
, compile_bios
=True):
177 for name
, src_dir
in self
.software_packages
:
178 if name
== "bios" and not compile_bios
:
181 dst_dir
= os
.path
.join(self
.software_dir
, name
)
182 makefile
= os
.path
.join(src_dir
, "Makefile")
183 if self
.compile_software
:
184 subprocess
.check_call(["make", "-C", dst_dir
, "-f", makefile
])
186 def _initialize_rom_software(self
):
187 bios_file
= os
.path
.join(self
.software_dir
, "bios", "bios.bin")
188 bios_data
= soc_core
.get_mem_data(bios_file
, self
.soc
.cpu
.endianness
)
189 self
.soc
.initialize_rom(bios_data
)
191 def build(self
, **kwargs
):
192 self
.soc
.platform
.output_dir
= self
.output_dir
193 os
.makedirs(self
.gateware_dir
, exist_ok
=True)
194 os
.makedirs(self
.software_dir
, exist_ok
=True)
198 self
._generate
_includes
()
199 self
._generate
_csr
_map
()
200 self
._generate
_mem
_region
_map
()
201 if self
.soc
.cpu_type
is not None:
202 if self
.soc
.cpu
.use_rom
:
203 self
._prepare
_rom
_software
()
204 self
._generate
_rom
_software
(not self
.soc
.integrated_rom_initialized
)
205 if self
.soc
.integrated_rom_size
and self
.compile_software
:
206 if not self
.soc
.integrated_rom_initialized
:
207 self
._initialize
_rom
_software
()
209 if "run" not in kwargs
:
210 kwargs
["run"] = self
.compile_gateware
211 vns
= self
.soc
.build(build_dir
=self
.gateware_dir
, **kwargs
)
212 self
.soc
.do_exit(vns
=vns
)
216 def builder_args(parser
):
217 parser
.add_argument("--output-dir", default
=None,
218 help="base output directory for generated "
219 "source files and binaries (customizable "
220 "with --{gateware,software,include,generated}-dir)")
221 parser
.add_argument("--gateware-dir", default
=None,
222 help="output directory for gateware files")
223 parser
.add_argument("--software-dir", default
=None,
224 help="base output directory for software files")
225 parser
.add_argument("--include-dir", default
=None,
226 help="output directory for header files")
227 parser
.add_argument("--generated-dir", default
=None,
228 help="output directory for various generated files")
229 parser
.add_argument("--no-compile-software", action
="store_true",
230 help="do not compile the software, only generate "
231 "build infrastructure")
232 parser
.add_argument("--no-compile-gateware", action
="store_true",
233 help="do not compile the gateware, only generate "
234 "HDL source files and build scripts")
235 parser
.add_argument("--csr-csv", default
=None,
236 help="store CSR map in CSV format into the "
238 parser
.add_argument("--csr-json", default
=None,
239 help="store CSR map in JSON format into the "
241 parser
.add_argument("--csr-svd", default
=None,
242 help="store CSR map in SVD format into the "
244 parser
.add_argument("--memory-x", default
=None,
245 help="store Mem regions in memory-x format into the "
249 def builder_argdict(args
):
251 "output_dir": args
.output_dir
,
252 "gateware_dir": args
.gateware_dir
,
253 "software_dir": args
.software_dir
,
254 "include_dir": args
.include_dir
,
255 "generated_dir": args
.generated_dir
,
256 "compile_software": not args
.no_compile_software
,
257 "compile_gateware": not args
.no_compile_gateware
,
258 "csr_csv": args
.csr_csv
,
259 "csr_json": args
.csr_json
,
260 "csr_svd": args
.csr_svd
,
261 "memory_x": args
.memory_x
,