blob: a4b93f1093b694d571aa2c7e689769b72d5711b4 [file] [log] [blame]
Rickard Bolin646314e2024-01-31 08:42:00 +00001# SPDX-FileCopyrightText: Copyright 2020-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Tim Hall79d07d22020-04-27 18:20:16 +01002#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the License); you may
6# not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an AS IS BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Rickard Bolinbc6ee582022-11-04 08:24:29 +000016#
Tim Hall79d07d22020-04-27 18:20:16 +010017# Description:
18# Main entry point for the Vela compiler.
19#
20# Provides command line interface, options parsing, and network loading. Before calling the compiler driver.
Diego Russoe8a10452020-04-21 17:39:10 +010021import argparse
Rickard Bolin1538dce2022-04-25 11:07:56 +000022import glob
Tim Hall1bd531d2020-11-01 20:59:36 +000023import os
Diego Russoea6111a2020-04-14 18:41:58 +010024import sys
Tim Hall79d07d22020-04-27 18:20:16 +010025import time
Tim Hall79d07d22020-04-27 18:20:16 +010026
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010027import flatbuffers
28
Tim Hall79d07d22020-04-27 18:20:16 +010029from . import architecture_features
Diego Russoe8a10452020-04-21 17:39:10 +010030from . import compiler_driver
31from . import model_reader
Diqing Zhong5e5a7842021-08-16 17:24:09 +020032from . import rawdata_writer
Diego Russoe8a10452020-04-21 17:39:10 +010033from . import scheduler
Tim Hall79d07d22020-04-27 18:20:16 +010034from . import stats_writer
35from . import tflite_writer
Tim Hall79d07d22020-04-27 18:20:16 +010036from ._version import __version__
Louis Verhaard11831ce2020-11-18 18:53:24 +010037from .api import API_VERSION
Tim Halle6ccd872020-11-09 16:46:37 +000038from .debug_database import DebugDatabase
Louis Verhaard7db78962020-05-25 15:05:26 +020039from .errors import InputFileError
Henrik G Olssonea9b23c2021-03-23 17:34:49 +010040from .errors import VelaError
Tim Hallcda4fcb2022-05-19 12:36:58 +010041from .hillclimb_allocation import HillClimbAllocator
Jonas Ohlsson45e653d2021-07-26 16:13:12 +020042from .nn_graph import NetworkType
Diego Russoe8a10452020-04-21 17:39:10 +010043from .nn_graph import TensorAllocator
Diego Russoea6111a2020-04-14 18:41:58 +010044from .tensor import MemArea
Jacob Bohlin0628a8c2020-08-28 13:25:14 +020045from .tensor import Tensor
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010046from .tflite.Model import Model
Michael McGeagh837dc1b2020-11-10 12:38:25 +000047from .tflite_mapping import builtin_operator_map
Tim Halla3fe6652022-03-03 17:43:16 +000048from .tflite_mapping import builtin_operator_name_map
Fredrik Svedberg88d5b122022-09-16 16:24:55 +020049from .tflite_mapping import optype_to_builtintype
Jonas Ohlsson45e653d2021-07-26 16:13:12 +020050from .tflite_model_semantic import TFLiteSemantic
51from .tflite_supported_operators import TFLiteSupportedOperators
52from .tosa_model_semantic import TosaSemantic
53from .tosa_supported_operators import TosaSupportedOperators
Louis Verhaard52078302020-11-18 13:35:06 +010054from ethosu.vela.architecture_features import ArchitectureFeatures
Tim Hall79d07d22020-04-27 18:20:16 +010055
Rickard Bolin7ce6b322022-06-02 09:30:33 +000056CONFIG_FILES_PATH = os.path.normpath(os.path.join(__file__, "..", "..", "config_files"))
Rickard Bolin1538dce2022-04-25 11:07:56 +000057
Tim Hall79d07d22020-04-27 18:20:16 +010058
Tim Halle6ccd872020-11-09 16:46:37 +000059def process(input_name, enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options):
Tim Hall79d07d22020-04-27 18:20:16 +010060 if compiler_options.timing:
61 start = time.time()
62
Tim Halle6ccd872020-11-09 16:46:37 +000063 os.makedirs(compiler_options.output_dir, exist_ok=True)
64 output_basename = os.path.join(compiler_options.output_dir, os.path.splitext(os.path.basename(input_name))[0])
65 DebugDatabase.show_warnings = enable_debug_db
66
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020067 nng, network_type = model_reader.read_model(input_name, model_reader_options)
Tim Hall79d07d22020-04-27 18:20:16 +010068
69 if not nng:
Michael McGeagh7a6f8432020-12-02 15:29:22 +000070 raise InputFileError(input_name, "Input file could not be read")
Tim Hall79d07d22020-04-27 18:20:16 +010071
72 if compiler_options.verbose_operators:
73 nng.print_operators()
74
75 if compiler_options.timing:
76 stop = time.time()
77 print("Model reading took %f s" % (stop - start))
78 start = time.time()
79
wilisa0189a8cdd2022-08-22 16:13:06 +000080 compiler_driver.compiler_driver(nng, arch, compiler_options, scheduler_options, network_type, output_basename)
Tim Hall79d07d22020-04-27 18:20:16 +010081
Tim Halle6ccd872020-11-09 16:46:37 +000082 summary_csv_file = "{0}_summary_{1}.csv".format(output_basename, arch.system_config)
Tim Hall79d07d22020-04-27 18:20:16 +010083 stats_writer.write_summary_metrics_csv(nng, summary_csv_file, arch)
84
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +020085 stats_writer.print_performance_metrics(
86 nng,
87 show_cpu_operations=compiler_options.show_cpu_operations,
88 verbose_weights=compiler_options.verbose_weights,
89 arch=arch,
90 )
Tim Hall79d07d22020-04-27 18:20:16 +010091
Diqing Zhong5e5a7842021-08-16 17:24:09 +020092 output_tfl_filename = output_basename + "_vela.tflite"
Patrik Gustavssonb081d672021-08-25 13:49:25 +020093 if input_name.endswith(".tflite"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020094 tflite_writer.write_tflite(nng, output_tfl_filename)
Patrik Gustavssonc74682c2021-08-17 14:26:38 +020095 if input_name.endswith(".tosa"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020096 rawdata_writer.write_rawdata_output(nng, arch, output_basename)
Tim Halle6ccd872020-11-09 16:46:37 +000097
98 if enable_debug_db:
Diqing Zhong5e5a7842021-08-16 17:24:09 +020099 file_offsets = calculate_operator_file_offsets(output_tfl_filename)
erik.andersson@arm.comad45f792021-02-03 10:20:16 +0100100 for idx, offset in enumerate(sorted(file_offsets)):
101 sg = find_subgraph_with_command_stream_order(nng, idx)
102 if sg is not None:
103 DebugDatabase.set_stream_offset(sg, offset)
Tim Halle6ccd872020-11-09 16:46:37 +0000104 debug_filename = output_basename + "_debug.xml"
Diqing Zhong5e5a7842021-08-16 17:24:09 +0200105 DebugDatabase.write(debug_filename, input_name, output_tfl_filename)
Tim Hall79d07d22020-04-27 18:20:16 +0100106
107 if compiler_options.timing:
108 stop = time.time()
109 print("Compiler driver took %f s" % (stop - start))
110
111 return nng
112
113
erik.andersson@arm.comad45f792021-02-03 10:20:16 +0100114def find_subgraph_with_command_stream_order(nng, idx):
115 for sg in nng.subgraphs:
116 if sg.generated_stream_id == idx:
117 return sg
118 return None
119
120
121def calculate_operator_file_offsets(name: str):
122 # Read the vela optimized tflite file
123 with open(name, "rb") as f:
124 buf = bytearray(f.read())
125 # Calculate the file offsets for each custom operator
126 file_offsets = []
127 model = Model.GetRootAsModel(buf, 0)
128 for idx in range(model.SubgraphsLength()): # However only one subgraph is supported as of now
129 sg = model.Subgraphs(idx)
130 for idx in range(sg.OperatorsLength()):
131 operator = sg.Operators(idx)
132 if model.OperatorCodes(operator.OpcodeIndex()).CustomCode() is not None:
133 tensor_idx = operator.Inputs(0)
134 tensor = sg.Tensors(tensor_idx)
135 buffer = model.Buffers(tensor.Buffer())
136 offset = flatbuffers.number_types.UOffsetTFlags.py_type(buffer._tab.Offset(4))
137 file_offsets.append(buffer._tab.Vector(offset))
138 return file_offsets
139
140
Tim Hall79d07d22020-04-27 18:20:16 +0100141def print_subgraph_io_summary(nng):
142 """Print a summary of all the input and output tensor sizes for all subgraphs.
143 Also displays the total tensor size and the memory used area for sram.
144 """
145
146 print("Subgraph IO Summary")
147 print("-------------------")
James Ward93389782021-10-14 12:58:02 +0100148 print(f"NNG: {nng.name}")
Tim Hall79d07d22020-04-27 18:20:16 +0100149 max_sg_size = 0
150 for sg in reversed(nng.subgraphs):
James Ward93389782021-10-14 12:58:02 +0100151 print(f" NNG Subgraph: {sg.name} = {sg.placement}")
Tim Hall79d07d22020-04-27 18:20:16 +0100152 sg_size = 0
153
James Ward93389782021-10-14 12:58:02 +0100154 if hasattr(sg, "scratch_tensor") and sg.scratch_tensor is not None:
155 sg_tensors = sg.input_tensors + [sg.scratch_tensor] + sg.output_tensors
156 else:
157 sg_tensors = sg.input_tensors + sg.output_tensors
Tim Hall79d07d22020-04-27 18:20:16 +0100158
James Ward93389782021-10-14 12:58:02 +0100159 for tens in sg_tensors:
160 if tens in sg.input_tensors:
161 tens_dir = "In"
162 elif tens in sg.output_tensors:
163 tens_dir = "Out"
164 else:
165 tens_dir = "In/Out"
Tim Hall79d07d22020-04-27 18:20:16 +0100166
James Ward93389782021-10-14 12:58:02 +0100167 size = tens.elements() * tens.element_size() / 1024.0
168 sg_size = sg_size + size
169 print(f" Tensor [{tens_dir}]: {tens.name} = {size} KiB")
170
171 print(f" Total Size = {sg_size} KiB")
172 print(f" SRAM Memory Used = {sg.memory_used.get(MemArea.Sram, 0) / 1024.0} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100173 max_sg_size = max(sg_size, max_sg_size)
174
James Ward93389782021-10-14 12:58:02 +0100175 print(f" Maximum NNG Subgraph Size = {max_sg_size} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100176
177
Alexander Hansson2466d812023-05-17 12:38:46 +0000178def generate_license():
179 lines = [
180 "<!--",
Rickard Bolin646314e2024-01-31 08:42:00 +0000181 "SPDX-FileCopyrightText: Copyright 2020-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>",
Alexander Hansson2466d812023-05-17 12:38:46 +0000182 "",
183 "SPDX-License-Identifier: Apache-2.0",
184 "",
185 "Licensed under the Apache License, Version 2.0 (the License); you may",
186 "not use this file except in compliance with the License.",
187 "You may obtain a copy of the License at",
188 "",
189 "www.apache.org/licenses/LICENSE-2.0",
190 "",
191 "Unless required by applicable law or agreed to in writing, software",
192 "distributed under the License is distributed on an AS IS BASIS, WITHOUT",
193 "WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
194 "See the License for the specific language governing permissions and",
195 "limitations under the License.",
196 "-->",
Tim Hallfd271112023-05-17 13:19:12 +0100197 "",
Alexander Hansson2466d812023-05-17 12:38:46 +0000198 ]
199 return lines
200
201
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000202def generate_supported_ops():
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200203 # Exclude network type from generation by adding value to exclude list.
204 # To easily exclude NetworkType from generated documentation.
205 exclude_generation_network_type_value = [NetworkType.TOSA.value]
206
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200207 def _exclude_list_names(constraint, exclude_list):
208 constraints_excluded_names = [
209 optype_to_builtintype(op) for op, exclude_constraint in exclude_list if constraint in exclude_constraint
210 ]
211 return f" - [{', '.join(sorted(constraints_excluded_names))}]" if constraints_excluded_names else ""
212
Alexander Hansson2466d812023-05-17 12:38:46 +0000213 lines = generate_license()
214 lines += [
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000215 "# Supported Ops",
216 "",
217 "This file was automatically generated by Vela using the `--supported-ops-report` parameter. ",
218 f"Vela version: `{__version__}`",
219 "",
Michael McGeagh54a61112020-11-24 14:58:51 +0000220 "This file complies with",
Johan Gunnarssonf4aa7f72023-09-26 15:44:50 +0200221 "[**Gitiles Markdown syntax**](https://gerrit.googlesource.com/gitiles/+/HEAD/Documentation/markdown.md)",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000222 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200223 "Summary table of constraints for:",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000224 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200225
226 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200227 if network_type.value in exclude_generation_network_type_value:
228 continue
229
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200230 lines += [
231 f"- [{network_type.name}](#{network_type.name.lower()}-summary-table)",
232 ]
233
234 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200235 if network_type.value in exclude_generation_network_type_value:
236 continue
237
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000238 lines += [
239 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200240 f"## {network_type.name} Summary Table",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000241 "",
242 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200243 if network_type == NetworkType.TFLite:
244 lines += [
245 "The table below contains TFLite operators that can be placed on the Ethos-U NPU. ",
246 "If the constraints are not met, then that operator will be scheduled on the CPU instead. ",
247 "For any other TFLite operator not listed, will be left untouched and scheduled on the CPU. ",
248 "Please check the supported operator list for your chosen runtime for further information.",
249 "",
250 "| Operator | TFLite Constraints |",
251 "| --- | --- |",
252 ]
253 semantic_checker = TFLiteSemantic()
254 supported = TFLiteSupportedOperators()
255 elif network_type == NetworkType.TOSA:
256 lines += [
257 "The table below contains TOSA operators that can be placed on the Ethos-U NPU. ",
258 "Note: There is limited support for compiling a TOSA neural network (EXPERIMENTAL). ",
259 "The related constraints have not yet been populated in the list.",
260 "",
261 "| Operator | TOSA Constraints |",
262 "| --- | --- |",
263 ]
264 semantic_checker = TosaSemantic()
265 supported = TosaSupportedOperators()
266 else:
267 raise ValueError
268
269 op_constraint_links = []
Tim Halla3fe6652022-03-03 17:43:16 +0000270 op_list = sorted(((op, builtin_operator_name_map[op]) for op in builtin_operator_map), key=lambda x: x[1])
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200271 for op, name in op_list:
272 internal_op = builtin_operator_map[op][0]
273 if internal_op in TFLiteSupportedOperators.supported_operators:
274 links = f"[Generic](#{network_type.name.lower()}-generic-constraints)"
275 if (
276 internal_op in supported.specific_constraints
277 or internal_op in semantic_checker.specific_constraints
278 ):
279 links += f", [Specific](#{network_type.name.lower()}-{name.lower()}-constraints)"
280 op_constraint_links.append((internal_op, name))
281 lines.append(f"| {name} | {links} |")
282 lines += [
283 "",
284 f"### {network_type.name} Generic Constraints",
285 "",
Ayaan Masood4965fae2022-06-29 11:30:57 +0100286 "This is a list of constraints most NPU operators must satisfy in order to be scheduled on the NPU.",
287 "(Operators excluded from certain constraints are shown in brackets [ ] )\n" "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200288 ]
289 for constraint in semantic_checker.generic_constraints:
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000290 # Markdown needs two spaces at the end of a line to render it as a separate line
291 reason = constraint.__doc__.replace("\n", " \n")
Ayaan Masood4965fae2022-06-29 11:30:57 +0100292 exclude_list = TFLiteSemantic.get_generic_constraint_exclude_list().items()
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200293 lines.append(f"- {reason}{_exclude_list_names(constraint, exclude_list)}")
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200294 for constraint in supported.generic_constraints:
295 # Markdown needs two spaces at the end of a line to render it as a separate line
296 reason = constraint.__doc__.replace("\n", " \n")
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200297 exclude_list = supported.generic_constraints_exceptions.items()
298 lines.append(f"- {reason}{_exclude_list_names(constraint, exclude_list)}")
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200299 for op, name in op_constraint_links:
300 lines += [
301 "",
302 f"### {network_type.name} {name} Constraints",
303 "",
304 f"This is a list of constraints that the {name} operator must satisfy in order to be scheduled on the"
305 " NPU.",
306 "",
307 ]
308 for constraint in semantic_checker.specific_constraints[op]:
309 # Markdown needs two spaces at the end of a line to render it as a separate line
310 reason = constraint.__doc__.replace("\n", " \n")
311 lines.append(f"- {reason}")
312 for constraint in supported.specific_constraints[op]:
313 # Markdown needs two spaces at the end of a line to render it as a separate line
314 reason = constraint.__doc__.replace("\n", " \n")
315 lines.append(f"- {reason}")
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000316
317 # Note. this will generate the file in the CWD
318 filepath = os.path.join(os.getcwd(), "SUPPORTED_OPS.md")
319 with open(filepath, "wt") as md:
320 md.writelines(line + "\n" for line in lines)
321 print(f"Report file: {filepath}")
322
323
Rickard Bolin1538dce2022-04-25 11:07:56 +0000324def list_config_files():
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000325 print("Available config files:")
326 path_length = len(CONFIG_FILES_PATH + os.path.sep)
Rickard Bolin1538dce2022-04-25 11:07:56 +0000327 for config in glob.glob(os.path.join(CONFIG_FILES_PATH, "*", "*.ini")):
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000328 print(config[path_length:])
Rickard Bolin1538dce2022-04-25 11:07:56 +0000329
330
Tim Hall79d07d22020-04-27 18:20:16 +0100331def main(args=None):
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100332 try:
333 if args is None:
334 args = sys.argv[1:]
Tim Hall79d07d22020-04-27 18:20:16 +0100335
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100336 parser = argparse.ArgumentParser(prog="vela", description="Neural network model compiler for Arm Ethos-U NPUs")
337 parser.add_argument("--version", action="version", version=__version__)
338 parser.add_argument(
339 "--api-version", action="version", version=API_VERSION, help="Displays the version of the external API."
340 )
341 parser.add_argument(
342 "--supported-ops-report",
343 action="store_true",
344 help="Generate the SUPPORTED_OPS.md file in the current working directory and exit",
Tim Hallb9b515c2020-11-01 21:27:19 +0000345 )
Jacob Bohlin0628a8c2020-08-28 13:25:14 +0200346
Rickard Bolin1538dce2022-04-25 11:07:56 +0000347 parser.add_argument(
348 "--list-config-files",
349 action="store_true",
350 help=(
351 "Display all available configurations in the `config_files` folder and exit. To select config file, "
352 "use the --config argument with one of the listed config files (For example: --config Arm/vela.ini )"
353 ),
354 )
355
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100356 # set network nargs to be optional to allow the support-ops-report CLI option to be used standalone
357 parser.add_argument(
358 "network",
359 metavar="NETWORK",
360 type=str,
361 default=None,
362 nargs="?",
363 help="Filename of the input TensorFlow Lite for Microcontrollers network",
364 )
365 parser.add_argument(
366 "--output-dir", type=str, default="output", help="Output directory to write files to (default: %(default)s)"
367 )
368 parser.add_argument(
369 "--enable-debug-db",
370 action="store_true",
371 default=None,
372 help="Enables the calculation and writing of a network debug database to output directory",
373 )
374 parser.add_argument(
375 "--config",
376 type=str,
377 action="append",
378 help="Vela configuration file(s) in Python ConfigParser .ini file format",
379 )
380 parser.add_argument("--verbose-all", action="store_true", help="Enable all verbose options")
381 parser.add_argument(
382 "--verbose-config", action="store_true", help="Verbose system configuration and memory mode"
383 )
384 parser.add_argument("--verbose-graph", action="store_true", help="Verbose graph rewriter")
385 parser.add_argument("--verbose-quantization", action="store_true", help="Verbose quantization")
386 parser.add_argument("--verbose-packing", action="store_true", help="Verbose pass packing")
387 parser.add_argument("--verbose-tensor-purpose", action="store_true", help="Verbose tensor purpose")
388 parser.add_argument("--verbose-tensor-format", action="store_true", help="Verbose tensor format")
389 parser.add_argument("--verbose-schedule", action="store_true", help="Verbose schedule")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100390 parser.add_argument("--verbose-allocation", action="store_true", help="Verbose tensor allocation")
391 parser.add_argument(
392 "--verbose-high-level-command-stream", action="store_true", help="Verbose high level command stream"
393 )
394 parser.add_argument(
395 "--verbose-register-command-stream", action="store_true", help="Verbose register command stream"
396 )
397 parser.add_argument("--verbose-operators", action="store_true", help="Verbose operator list")
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200398 parser.add_argument("--verbose-weights", action="store_true", help="Verbose weights information")
Tim Hallc1be0872022-03-03 17:50:52 +0000399 parser.add_argument("--verbose-performance", action="store_true", help="Verbose performance information")
Raul Farkas1c54ac12023-04-26 07:49:15 +0100400 parser.add_argument("--verbose-progress", action="store_true", help="Verbose progress information")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100401 parser.add_argument(
402 "--show-cpu-operations", action="store_true", help="Show the operations that fall back to the CPU"
403 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100404 parser.add_argument("--timing", action="store_true", help="Time the compiler doing operations")
405 parser.add_argument(
wilisa0146c94772023-02-08 09:56:14 +0000406 "--force-symmetric-int-weights",
407 action="store_true",
408 help="Forces all zero points to 0 for signed integer weights",
409 )
410 parser.add_argument(
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100411 "--accelerator-config",
412 type=str,
413 default="ethos-u55-256",
414 choices=list(architecture_features.Accelerator.member_list()),
415 help="Accelerator configuration to use (default: %(default)s)",
416 )
417 parser.add_argument(
418 "--system-config",
419 type=str,
420 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
421 help="System configuration to select from the Vela configuration file (default: %(default)s)",
422 )
423 parser.add_argument(
424 "--memory-mode",
425 type=str,
426 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
427 help="Memory mode to select from the Vela configuration file (default: %(default)s)",
428 )
429 parser.add_argument(
430 "--tensor-allocator",
431 default=TensorAllocator.HillClimb,
432 type=lambda s: TensorAllocator[s],
433 choices=list(TensorAllocator),
434 help="Tensor Allocator algorithm (default: %(default)s)",
435 )
436 parser.add_argument(
437 "--show-subgraph-io-summary",
438 action="store_true",
439 help="Shows a summary of all the subgraphs and their inputs and outputs",
440 )
441 parser.add_argument(
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100442 "--max-block-dependency",
443 type=int,
444 default=architecture_features.ArchitectureFeatures.MAX_BLOCKDEP,
445 choices=range(0, architecture_features.ArchitectureFeatures.MAX_BLOCKDEP + 1),
446 help=(
447 "Set the maximum value that can be used for the block dependency between npu kernel operations"
448 " (default: %(default)s)"
449 ),
450 )
451 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100452 "--optimise",
453 type=lambda s: scheduler.OptimizationStrategy[s],
454 default=scheduler.OptimizationStrategy.Performance,
455 choices=list(scheduler.OptimizationStrategy),
456 help=(
457 "Set the optimisation strategy. The Size strategy results in minimal SRAM usage (does not use"
458 " arena-cache-size). The Performance strategy results in maximal performance (uses the arena-cache-size"
459 " if specified) (default: %(default)s)"
460 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100461 )
462 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100463 "--arena-cache-size",
464 type=int,
465 help=(
466 "Set the size of the arena cache memory area, in bytes. If specified, this option overrides the memory"
467 " mode attribute with the same name in a Vela configuration file"
468 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100469 )
470 parser.add_argument(
471 "--cpu-tensor-alignment",
472 type=int,
473 default=Tensor.AllocationQuantum,
474 help=(
475 "Controls the allocation byte alignment of cpu tensors including Ethos-U Custom"
Tim Hall27429472023-11-16 11:36:19 +0000476 " operator inputs and outputs (default: %(default)s Bytes)"
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100477 ),
478 )
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200479 parser.add_argument(
480 "--recursion-limit",
481 type=int,
482 default=1000,
483 help="Set the recursion depth limit, may result in RecursionError if too low (default: %(default)s)",
484 )
Tim Hallcda4fcb2022-05-19 12:36:58 +0100485 parser.add_argument(
486 "--hillclimb-max-iterations",
487 type=int,
488 default=HillClimbAllocator.MAX_ITERATIONS,
489 help=(
490 "Set the maximum number of iterations the Hill Climb tensor allocator will run (default: %(default)s)"
491 ),
492 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100493 args = parser.parse_args(args=args)
Louis Verhaard52078302020-11-18 13:35:06 +0100494
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100495 # Generate the supported ops report and exit
496 if args.supported_ops_report:
497 generate_supported_ops()
498 return 0
Louis Verhaard52078302020-11-18 13:35:06 +0100499
Rickard Bolin1538dce2022-04-25 11:07:56 +0000500 if args.list_config_files:
501 list_config_files()
502 return 0
503
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100504 if args.network is None:
505 parser.error("the following argument is required: NETWORK")
Michael McGeagh2fa40ae2020-12-02 10:55:04 +0000506
Rickard Bolin1538dce2022-04-25 11:07:56 +0000507 def _parse_config(config):
Rickard Bolin7ce6b322022-06-02 09:30:33 +0000508 # Make sure the correct separator is used depending on OS
509 config = os.path.normpath(config)
510
Rickard Bolin1538dce2022-04-25 11:07:56 +0000511 if not config.endswith(".ini"):
512 raise InputFileError(config, "Configuration files must use the .ini extension")
513
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000514 if (
515 len(config.split(os.path.sep)) == 2
516 and not config.startswith(os.path.sep)
517 and not config.startswith(".")
518 and not config.startswith("~")
519 ):
Rickard Bolin1538dce2022-04-25 11:07:56 +0000520 config_path = os.path.join(CONFIG_FILES_PATH, config)
521 else:
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000522 # Check if the configuration file is correctly placed inside the config_files directory
523 if os.access(os.path.join(CONFIG_FILES_PATH, *config.split(os.path.sep)[-2:]), os.R_OK):
524 rel_path = os.path.join(*config.split(os.path.sep)[-2:])
525 print(
526 f"Warning: Consider accessing the configuration by --config {rel_path} since it is located "
527 "inside the config_files directory."
528 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000529 config_path = config
530
531 if not os.access(config_path, os.R_OK):
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000532 raise InputFileError(
533 config_path,
534 "File not found or is not readable. The configuration file is either not located in a folder "
535 "directly under the `config_files` directory or its path has not been provided correctly.",
536 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000537
538 return config_path
539
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100540 # check all config files exist because they will be read as a group
Rickard Bolin1538dce2022-04-25 11:07:56 +0000541 config_files = [_parse_config(cfg) for cfg in args.config] if args.config else None
Tim Hall79d07d22020-04-27 18:20:16 +0100542
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100543 if args.cpu_tensor_alignment < 16 or args.cpu_tensor_alignment & (args.cpu_tensor_alignment - 1) != 0:
544 parser.error(
545 "Invalid argument to --cpu-tensor-alignment = {} (must be greater than or equal to 16 and a power of 2)"
546 "".format(args.cpu_tensor_alignment)
547 )
Tim Hall79d07d22020-04-27 18:20:16 +0100548
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100549 if args.system_config == ArchitectureFeatures.DEFAULT_CONFIG:
550 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for system configuration")
Tim Hall79d07d22020-04-27 18:20:16 +0100551
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100552 if args.memory_mode == ArchitectureFeatures.DEFAULT_CONFIG:
553 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for memory mode")
Tim Hall79d07d22020-04-27 18:20:16 +0100554
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100555 if args.verbose_all:
556 for v in vars(args):
557 if v.startswith("verbose") and v != "verbose_all":
558 setattr(args, v, True)
559
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200560 sys.setrecursionlimit(args.recursion_limit)
561
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100562 arch = architecture_features.ArchitectureFeatures(
Rickard Bolin1538dce2022-04-25 11:07:56 +0000563 vela_config_files=config_files,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100564 system_config=args.system_config,
565 memory_mode=args.memory_mode,
566 accelerator_config=args.accelerator_config,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100567 max_blockdep=args.max_block_dependency,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100568 verbose_config=args.verbose_config,
Tim Halld8339a72021-05-27 18:49:40 +0100569 arena_cache_size=args.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100570 )
571
572 compiler_options = compiler_driver.CompilerOptions(
573 verbose_graph=args.verbose_graph,
574 verbose_quantization=args.verbose_quantization,
575 verbose_packing=args.verbose_packing,
576 verbose_tensor_purpose=args.verbose_tensor_purpose,
577 verbose_tensor_format=args.verbose_tensor_format,
578 verbose_allocation=args.verbose_allocation,
579 verbose_high_level_command_stream=args.verbose_high_level_command_stream,
580 verbose_register_command_stream=args.verbose_register_command_stream,
581 verbose_operators=args.verbose_operators,
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200582 verbose_weights=args.verbose_weights,
Tim Hallc1be0872022-03-03 17:50:52 +0000583 verbose_performance=args.verbose_performance,
Raul Farkas1c54ac12023-04-26 07:49:15 +0100584 verbose_progress=args.verbose_progress,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100585 show_cpu_operations=args.show_cpu_operations,
586 tensor_allocator=args.tensor_allocator,
587 timing=args.timing,
wilisa0146c94772023-02-08 09:56:14 +0000588 force_symmetric_int_weights=args.force_symmetric_int_weights,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100589 output_dir=args.output_dir,
590 cpu_tensor_alignment=args.cpu_tensor_alignment,
Tim Hallcda4fcb2022-05-19 12:36:58 +0100591 hillclimb_max_iterations=args.hillclimb_max_iterations,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100592 )
593
594 scheduler_options = scheduler.SchedulerOptions(
Tim Halld8339a72021-05-27 18:49:40 +0100595 optimization_strategy=args.optimise,
596 sram_target=arch.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100597 verbose_schedule=args.verbose_schedule,
Raul Farkas1c54ac12023-04-26 07:49:15 +0100598 verbose_progress=args.verbose_progress,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100599 )
600
601 model_reader_options = model_reader.ModelReaderOptions()
602
603 nng = process(
604 args.network, args.enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options
605 )
606
607 if args.show_subgraph_io_summary:
608 print_subgraph_io_summary(nng)
609
610 return 0
611 except VelaError as e:
612 print(e.data)
613 return 1