6 from litex
.build
.tools
import write_to_file
7 from litex
.soc
.integration
import cpu_interface
, soc_sdram
, sdram_init
10 __all__
= ["soc_software_packages", "soc_directory",
11 "Builder", "builder_args", "builder_argdict"]
14 soc_software_packages
= [
22 soc_directory
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(__file__
), ".."))
25 def _makefile_escape(s
):
26 return s
.replace("\\", "\\\\")
30 def __init__(self
, soc
, output_dir
=None,
31 compile_software
=True, compile_gateware
=True,
32 gateware_toolchain_path
=None,
35 if output_dir
is None:
36 output_dir
= "soc_{}_{}".format(
37 soc
.__class
__.__name
__.lower(),
39 # From Python doc: makedirs() will become confused if the path
40 # elements to create include '..'
41 self
.output_dir
= os
.path
.abspath(output_dir
)
42 self
.compile_software
= compile_software
43 self
.compile_gateware
= compile_gateware
44 self
.gateware_toolchain_path
= gateware_toolchain_path
45 self
.csr_csv
= csr_csv
47 self
.software_packages
= []
48 for name
in soc_software_packages
:
49 self
.add_software_package(name
)
51 def add_software_package(self
, name
, src_dir
=None):
53 src_dir
= os
.path
.join(soc_directory
, "software", name
)
54 self
.software_packages
.append((name
, src_dir
))
56 def _generate_includes(self
):
57 cpu_type
= self
.soc
.cpu_type
58 memory_regions
= self
.soc
.get_memory_regions()
59 flash_boot_address
= getattr(self
.soc
, "flash_boot_address", None)
60 csr_regions
= self
.soc
.get_csr_regions()
61 constants
= self
.soc
.get_constants()
62 if isinstance(self
.soc
, soc_sdram
.SoCSDRAM
) and self
.soc
._sdram
_phy
:
63 sdram_phy_settings
= self
.soc
._sdram
_phy
[0].settings
65 sdram_phy_settings
= None
67 buildinc_dir
= os
.path
.join(self
.output_dir
, "software", "include")
68 generated_dir
= os
.path
.join(buildinc_dir
, "generated")
69 os
.makedirs(generated_dir
, exist_ok
=True)
71 variables_contents
= []
73 variables_contents
.append("{}={}\n".format(k
, _makefile_escape(v
)))
74 for k
, v
in cpu_interface
.get_cpu_mak(cpu_type
):
76 define("SOC_DIRECTORY", soc_directory
)
77 variables_contents
.append("export BUILDINC_DIRECTORY\n")
78 define("BUILDINC_DIRECTORY", buildinc_dir
)
79 for name
, src_dir
in self
.software_packages
:
80 define(name
.upper() + "_DIRECTORY", src_dir
)
82 os
.path
.join(generated_dir
, "variables.mak"),
83 "".join(variables_contents
))
86 os
.path
.join(generated_dir
, "output_format.ld"),
87 cpu_interface
.get_linker_output_format(cpu_type
))
89 os
.path
.join(generated_dir
, "regions.ld"),
90 cpu_interface
.get_linker_regions(memory_regions
))
93 os
.path
.join(generated_dir
, "mem.h"),
94 cpu_interface
.get_mem_header(memory_regions
, flash_boot_address
))
96 os
.path
.join(generated_dir
, "csr.h"),
97 cpu_interface
.get_csr_header(csr_regions
, constants
))
99 if sdram_phy_settings
is not None:
101 os
.path
.join(generated_dir
, "sdram_phy.h"),
102 sdram_init
.get_sdram_phy_header(sdram_phy_settings
))
104 def _generate_csr_csv(self
):
105 memory_regions
= self
.soc
.get_memory_regions()
106 csr_regions
= self
.soc
.get_csr_regions()
107 constants
= self
.soc
.get_constants()
109 csr_dir
= os
.path
.dirname(os
.path
.realpath(self
.csr_csv
))
110 os
.makedirs(csr_dir
, exist_ok
=True)
113 cpu_interface
.get_csr_csv(csr_regions
, constants
, memory_regions
))
115 def _prepare_software(self
):
116 for name
, src_dir
in self
.software_packages
:
117 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
118 os
.makedirs(dst_dir
, exist_ok
=True)
120 def _generate_software(self
, compile_bios
=True):
121 for name
, src_dir
in self
.software_packages
:
122 if name
== "bios" and not compile_bios
:
125 dst_dir
= os
.path
.join(self
.output_dir
, "software", name
)
126 makefile
= os
.path
.join(src_dir
, "Makefile")
127 if self
.compile_software
:
128 subprocess
.check_call(["make", "-C", dst_dir
, "-f", makefile
])
130 def _initialize_rom(self
):
131 bios_file
= os
.path
.join(self
.output_dir
, "software", "bios",
133 endianness
= cpu_interface
.cpu_endianness
[self
.soc
.cpu_type
]
134 with
open(bios_file
, "rb") as boot_file
:
137 w
= boot_file
.read(4)
140 if endianness
== 'little':
141 boot_data
.append(struct
.unpack("<I", w
)[0])
143 boot_data
.append(struct
.unpack(">I", w
)[0])
144 self
.soc
.initialize_rom(boot_data
)
146 def build(self
, toolchain_path
=None, **kwargs
):
149 os
.makedirs(self
.output_dir
, exist_ok
=True)
151 if self
.soc
.cpu_type
is not None:
152 self
._prepare
_software
()
153 self
._generate
_includes
()
154 self
._generate
_software
(not self
.soc
.integrated_rom_initialized
)
155 if self
.soc
.integrated_rom_size
and self
.compile_software
:
156 if not self
.soc
.integrated_rom_initialized
:
157 self
._initialize
_rom
()
159 if self
.csr_csv
is not None:
160 self
._generate
_csr
_csv
()
162 if self
.gateware_toolchain_path
is not None:
163 toolchain_path
= self
.gateware_toolchain_path
165 if "run" not in kwargs
:
166 kwargs
["run"] = self
.compile_gateware
167 vns
= self
.soc
.build(build_dir
=os
.path
.join(self
.output_dir
, "gateware"),
168 toolchain_path
=toolchain_path
, **kwargs
)
172 def builder_args(parser
):
173 parser
.add_argument("--output-dir", default
=None,
174 help="output directory for generated "
175 "source files and binaries")
176 parser
.add_argument("--no-compile-software", action
="store_true",
177 help="do not compile the software, only generate "
178 "build infrastructure")
179 parser
.add_argument("--no-compile-gateware", action
="store_true",
180 help="do not compile the gateware, only generate "
181 "HDL source files and build scripts")
182 parser
.add_argument("--gateware-toolchain-path", default
=None,
183 help="set gateware toolchain (ISE, Quartus, etc.) "
185 parser
.add_argument("--csr-csv", default
=None,
186 help="store CSR map in CSV format into the "
190 def builder_argdict(args
):
192 "output_dir": args
.output_dir
,
193 "compile_software": not args
.no_compile_software
,
194 "compile_gateware": not args
.no_compile_gateware
,
195 "gateware_toolchain_path": args
.gateware_toolchain_path
,
196 "csr_csv": args
.csr_csv