6 from litex
.build
.tools
import write_to_file
7 from litex
.soc
.integration
import cpu_interface
, soc_core
, soc_sdram
9 from litedram
import sdram_init
11 __all__
= ["soc_software_packages", "soc_directory",
12 "Builder", "builder_args", "builder_argdict"]
15 soc_software_packages
= [
23 soc_directory
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(__file__
), ".."))
26 def _makefile_escape(s
):
27 return s
.replace("\\", "\\\\")
31 def __init__(self
, soc
, output_dir
=None,
32 compile_software
=True, compile_gateware
=True,
33 gateware_toolchain_path
=None,
36 if output_dir
is None:
37 output_dir
= "soc_{}_{}".format(
38 soc
.__class
__.__name
__.lower(),
40 # From Python doc: makedirs() will become confused if the path
41 # elements to create include '..'
42 self
.output_dir
= os
.path
.abspath(output_dir
)
43 self
.compile_software
= compile_software
44 self
.compile_gateware
= compile_gateware
45 self
.gateware_toolchain_path
= gateware_toolchain_path
46 self
.csr_csv
= csr_csv
48 self
.software_packages
= []
49 for name
in soc_software_packages
:
50 self
.add_software_package(name
)
52 def add_software_package(self
, name
, src_dir
=None):
54 src_dir
= os
.path
.join(soc_directory
, "software", name
)
55 self
.software_packages
.append((name
, src_dir
))
57 def _generate_includes(self
):
58 cpu_type
= self
.soc
.cpu_type
59 memory_regions
= self
.soc
.get_memory_regions()
60 flash_boot_address
= getattr(self
.soc
, "flash_boot_address", None)
61 shadow_base
= getattr(self
.soc
, "shadow_base", None)
62 csr_regions
= self
.soc
.get_csr_regions()
63 constants
= self
.soc
.get_constants()
65 buildinc_dir
= os
.path
.join(self
.output_dir
, "software", "include")
66 generated_dir
= os
.path
.join(buildinc_dir
, "generated")
67 os
.makedirs(generated_dir
, exist_ok
=True)
69 variables_contents
= []
71 variables_contents
.append("{}={}\n".format(k
, _makefile_escape(v
)))
72 for k
, v
in cpu_interface
.get_cpu_mak(self
.soc
.cpu
):
74 # Distinguish between LiteX and MiSoC.
76 # Distinguish between applications running from main RAM and
77 # flash for user-provided software packages.
79 "COPY_TO_MAIN_RAM" : "0",
80 "EXECUTE_IN_PLACE" : "0"
82 if "main_ram" in (m
[0] for m
in memory_regions
):
83 exec_profiles
["COPY_TO_MAIN_RAM"] = "1"
85 exec_profiles
["EXECUTE_IN_PLACE"] = "1"
86 for k
, v
in exec_profiles
.items():
88 define("SOC_DIRECTORY", soc_directory
)
89 variables_contents
.append("export BUILDINC_DIRECTORY\n")
90 define("BUILDINC_DIRECTORY", buildinc_dir
)
91 for name
, src_dir
in self
.software_packages
:
92 define(name
.upper() + "_DIRECTORY", src_dir
)
94 os
.path
.join(generated_dir
, "variables.mak"),
95 "".join(variables_contents
))
98 os
.path
.join(generated_dir
, "output_format.ld"),
99 cpu_interface
.get_linker_output_format(self
.soc
.cpu
))
101 os
.path
.join(generated_dir
, "regions.ld"),
102 cpu_interface
.get_linker_regions(memory_regions
))
105 os
.path
.join(generated_dir
, "mem.h"),
106 cpu_interface
.get_mem_header(memory_regions
, flash_boot_address
, shadow_base
))
108 os
.path
.join(generated_dir
, "csr.h"),
109 cpu_interface
.get_csr_header(csr_regions
, constants
))
111 if isinstance(self
.soc
, soc_sdram
.SoCSDRAM
):
112 if hasattr(self
.soc
, "sdram"):
114 os
.path
.join(generated_dir
, "sdram_phy.h"),
115 sdram_init
.get_sdram_phy_c_header(
116 self
.soc
.sdram
.controller
.settings
.phy
,
117 self
.soc
.sdram
.controller
.settings
.timing
))
119 def _generate_csr_csv(self
):
120 memory_regions
= self
.soc
.get_memory_regions()
121 csr_regions
= self
.soc
.get_csr_regions()
122 constants
= self
.soc
.get_constants()
124 shadow_base
= getattr(self
.soc
, "shadow_base", None)
126 constants
.append(('shadow_base', shadow_base
))
128 flash_boot_address
= getattr(self
.soc
, "flash_boot_address", None)
129 if flash_boot_address
:
130 constants
.append(('flash_boot_address', flash_boot_address
))
132 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_csv
))
133 os
.makedirs(csr_dir
, exist_ok
=True)
136 cpu_interface
.get_csr_csv(csr_regions
, constants
, memory_regions
))
138 def _prepare_software(self
):
139 for name
, src_dir
in self
.software_packages
:
140 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
141 os
.makedirs(dst_dir
, exist_ok
=True)
143 def _generate_software(self
, compile_bios
=True):
144 for name
, src_dir
in self
.software_packages
:
145 if name
== "bios" and not compile_bios
:
148 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
149 makefile
= os
.path
.join(src_dir
, "Makefile")
150 if self
.compile_software
:
151 subprocess
.check_call(["make", "-C", dst_dir
, "-f", makefile
])
153 def _initialize_rom(self
):
154 bios_file
= os
.path
.join(self
.output_dir
, "software", "bios","bios.bin")
155 bios_data
= soc_core
.get_mem_data(bios_file
, self
.soc
.cpu
.endianness
)
156 self
.soc
.initialize_rom(bios_data
)
158 def build(self
, toolchain_path
=None, **kwargs
):
161 os
.makedirs(self
.output_dir
, exist_ok
=True)
163 if self
.soc
.cpu_type
is not None:
164 self
._prepare
_software
()
165 self
._generate
_includes
()
166 self
._generate
_software
(not self
.soc
.integrated_rom_initialized
)
167 if self
.soc
.integrated_rom_size
and self
.compile_software
:
168 if not self
.soc
.integrated_rom_initialized
:
169 self
._initialize
_rom
()
171 if self
.csr_csv
is not None:
172 self
._generate
_csr
_csv
()
174 if self
.gateware_toolchain_path
is not None:
175 toolchain_path
= self
.gateware_toolchain_path
177 if "run" not in kwargs
:
178 kwargs
["run"] = self
.compile_gateware
179 vns
= self
.soc
.build(build_dir
=os
.path
.join(self
.output_dir
, "gateware"),
180 toolchain_path
=toolchain_path
, **kwargs
)
184 def builder_args(parser
):
185 parser
.add_argument("--output-dir", default
=None,
186 help="output directory for generated "
187 "source files and binaries")
188 parser
.add_argument("--no-compile-software", action
="store_true",
189 help="do not compile the software, only generate "
190 "build infrastructure")
191 parser
.add_argument("--no-compile-gateware", action
="store_true",
192 help="do not compile the gateware, only generate "
193 "HDL source files and build scripts")
194 parser
.add_argument("--gateware-toolchain-path", default
=None,
195 help="set gateware toolchain (ISE, Quartus, etc.) "
197 parser
.add_argument("--csr-csv", default
=None,
198 help="store CSR map in CSV format into the "
202 def builder_argdict(args
):
204 "output_dir": args
.output_dir
,
205 "compile_software": not args
.no_compile_software
,
206 "compile_gateware": not args
.no_compile_gateware
,
207 "gateware_toolchain_path": args
.gateware_toolchain_path
,
208 "csr_csv": args
.csr_csv