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) 2019 Mateusz Holenko <mholenko@antmicro.com>
4 # This file is Copyright (c) 2018 Peter Gielda <pgielda@antmicro.com>
5 # This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
6 # This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell <mithro@mithis.com>
7 # This file is Copyright (c) 2018 William D. Jones <thor0505@comcast.net>
16 from litex
.build
.tools
import write_to_file
17 from litex
.soc
.integration
import cpu_interface
, soc_core
, soc_sdram
19 from litedram
.init
import get_sdram_phy_c_header
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
, output_dir
=None,
42 compile_software
=True, compile_gateware
=True,
43 gateware_toolchain_path
=None,
44 csr_json
=None, csr_csv
=None):
46 if output_dir
is None:
47 output_dir
= "soc_{}_{}".format(
48 soc
.__class
__.__name
__.lower(),
50 # From Python doc: makedirs() will become confused if the path
51 # elements to create include '..'
52 self
.output_dir
= os
.path
.abspath(output_dir
)
53 self
.compile_software
= compile_software
54 self
.compile_gateware
= compile_gateware
55 self
.gateware_toolchain_path
= gateware_toolchain_path
56 self
.csr_csv
= csr_csv
57 self
.csr_json
= csr_json
59 self
.software_packages
= []
60 for name
in soc_software_packages
:
61 self
.add_software_package(name
)
63 def add_software_package(self
, name
, src_dir
=None):
65 src_dir
= os
.path
.join(soc_directory
, "software", name
)
66 self
.software_packages
.append((name
, src_dir
))
68 def _generate_includes(self
):
69 cpu_type
= self
.soc
.cpu_type
70 memory_regions
= self
.soc
.get_memory_regions()
71 flash_boot_address
= getattr(self
.soc
, "flash_boot_address", None)
72 shadow_base
= getattr(self
.soc
, "shadow_base", None)
73 csr_regions
= self
.soc
.get_csr_regions()
74 constants
= self
.soc
.get_constants()
76 buildinc_dir
= os
.path
.join(self
.output_dir
, "software", "include")
77 generated_dir
= os
.path
.join(buildinc_dir
, "generated")
78 os
.makedirs(generated_dir
, exist_ok
=True)
80 variables_contents
= []
82 variables_contents
.append("{}={}\n".format(k
, _makefile_escape(v
)))
83 for k
, v
in cpu_interface
.get_cpu_mak(self
.soc
.cpu
):
85 # Distinguish between LiteX and MiSoC.
87 # Distinguish between applications running from main RAM and
88 # flash for user-provided software packages.
90 "COPY_TO_MAIN_RAM" : "0",
91 "EXECUTE_IN_PLACE" : "0"
93 if "main_ram" in (m
[0] for m
in memory_regions
):
94 exec_profiles
["COPY_TO_MAIN_RAM"] = "1"
96 exec_profiles
["EXECUTE_IN_PLACE"] = "1"
97 for k
, v
in exec_profiles
.items():
99 define("SOC_DIRECTORY", soc_directory
)
100 variables_contents
.append("export BUILDINC_DIRECTORY\n")
101 define("BUILDINC_DIRECTORY", buildinc_dir
)
102 for name
, src_dir
in self
.software_packages
:
103 define(name
.upper() + "_DIRECTORY", src_dir
)
105 os
.path
.join(generated_dir
, "variables.mak"),
106 "".join(variables_contents
))
108 os
.path
.join(generated_dir
, "output_format.ld"),
109 cpu_interface
.get_linker_output_format(self
.soc
.cpu
))
111 os
.path
.join(generated_dir
, "regions.ld"),
112 cpu_interface
.get_linker_regions(memory_regions
))
114 os
.path
.join(generated_dir
, "mem.h"),
115 cpu_interface
.get_mem_header(memory_regions
, flash_boot_address
, shadow_base
))
117 os
.path
.join(generated_dir
, "csr.h"),
118 cpu_interface
.get_csr_header(csr_regions
, constants
))
120 os
.path
.join(generated_dir
, "git.h"),
121 cpu_interface
.get_git_header()
124 if isinstance(self
.soc
, soc_sdram
.SoCSDRAM
):
125 if hasattr(self
.soc
, "sdram"):
127 os
.path
.join(generated_dir
, "sdram_phy.h"),
128 get_sdram_phy_c_header(
129 self
.soc
.sdram
.controller
.settings
.phy
,
130 self
.soc
.sdram
.controller
.settings
.timing
))
132 def _generate_csr_map(self
, csr_json
=None, csr_csv
=None):
133 memory_regions
= self
.soc
.get_memory_regions()
134 csr_regions
= self
.soc
.get_csr_regions()
135 constants
= self
.soc
.get_constants()
137 shadow_base
= getattr(self
.soc
, "shadow_base", None)
139 constants
.append(('shadow_base', shadow_base
))
141 flash_boot_address
= getattr(self
.soc
, "flash_boot_address", None)
142 if flash_boot_address
:
143 constants
.append(('flash_boot_address', flash_boot_address
))
145 if csr_json
is not None:
146 csr_dir
= os
.path
.dirname(os
.path
.realpath(csr_json
))
147 os
.makedirs(csr_dir
, exist_ok
=True)
148 write_to_file(csr_json
, cpu_interface
.get_csr_json(csr_regions
, constants
, memory_regions
))
150 if csr_csv
is not None:
151 csr_dir
= os
.path
.dirname(os
.path
.realpath(csr_csv
))
152 os
.makedirs(csr_dir
, exist_ok
=True)
153 write_to_file(csr_csv
, cpu_interface
.get_csr_csv(csr_regions
, constants
, memory_regions
))
155 def _prepare_software(self
):
156 for name
, src_dir
in self
.software_packages
:
157 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
158 os
.makedirs(dst_dir
, exist_ok
=True)
160 def _generate_software(self
, compile_bios
=True):
161 for name
, src_dir
in self
.software_packages
:
162 if name
== "bios" and not compile_bios
:
165 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
166 makefile
= os
.path
.join(src_dir
, "Makefile")
167 if self
.compile_software
:
168 subprocess
.check_call(["make", "-C", dst_dir
, "-f", makefile
])
170 def _initialize_rom(self
):
171 bios_file
= os
.path
.join(self
.output_dir
, "software", "bios","bios.bin")
172 bios_data
= soc_core
.get_mem_data(bios_file
, self
.soc
.cpu
.endianness
)
173 self
.soc
.initialize_rom(bios_data
)
175 def build(self
, toolchain_path
=None, **kwargs
):
178 os
.makedirs(self
.output_dir
, exist_ok
=True)
180 if self
.soc
.cpu_type
is not None:
181 self
._prepare
_software
()
182 self
._generate
_includes
()
183 self
._generate
_software
(not self
.soc
.integrated_rom_initialized
)
184 if self
.soc
.integrated_rom_size
and self
.compile_software
:
185 if not self
.soc
.integrated_rom_initialized
:
186 self
._initialize
_rom
()
188 self
._generate
_csr
_map
(self
.csr_json
, self
.csr_csv
)
190 if self
.gateware_toolchain_path
is not None:
191 toolchain_path
= self
.gateware_toolchain_path
193 if "run" not in kwargs
:
194 kwargs
["run"] = self
.compile_gateware
195 vns
= self
.soc
.build(build_dir
=os
.path
.join(self
.output_dir
, "gateware"),
196 toolchain_path
=toolchain_path
, **kwargs
)
197 self
.soc
.do_exit(vns
=vns
)
201 def builder_args(parser
):
202 parser
.add_argument("--output-dir", default
=None,
203 help="output directory for generated "
204 "source files and binaries")
205 parser
.add_argument("--no-compile-software", action
="store_true",
206 help="do not compile the software, only generate "
207 "build infrastructure")
208 parser
.add_argument("--no-compile-gateware", action
="store_true",
209 help="do not compile the gateware, only generate "
210 "HDL source files and build scripts")
211 parser
.add_argument("--gateware-toolchain-path", default
=None,
212 help="set gateware toolchain (ISE, Quartus, etc.) "
214 parser
.add_argument("--csr-csv", default
=None,
215 help="store CSR map in CSV format into the "
217 parser
.add_argument("--csr-json", default
=None,
218 help="store CSR map in JSON format into the "
222 def builder_argdict(args
):
224 "output_dir": args
.output_dir
,
225 "compile_software": not args
.no_compile_software
,
226 "compile_gateware": not args
.no_compile_gateware
,
227 "gateware_toolchain_path": args
.gateware_toolchain_path
,
228 "csr_csv": args
.csr_csv