blob: 7740711e3dd0f378c9a94cd52d46939d26d63391 [file] [log] [blame]
wilisa0189a8cdd2022-08-22 16:13:06 +00001# Copyright (C) 2020-2022 Arm Limited or its affiliates. All rights reserved.
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.
Tim Hall79d07d22020-04-27 18:20:16 +010016# Description:
17# Main entry point for the Vela compiler.
18#
19# Provides command line interface, options parsing, and network loading. Before calling the compiler driver.
Diego Russoe8a10452020-04-21 17:39:10 +010020import argparse
Rickard Bolin1538dce2022-04-25 11:07:56 +000021import glob
Tim Hall1bd531d2020-11-01 20:59:36 +000022import os
Diego Russoea6111a2020-04-14 18:41:58 +010023import sys
Tim Hall79d07d22020-04-27 18:20:16 +010024import time
Tim Hall79d07d22020-04-27 18:20:16 +010025
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010026import flatbuffers
27
Tim Hall79d07d22020-04-27 18:20:16 +010028from . import architecture_features
Diego Russoe8a10452020-04-21 17:39:10 +010029from . import compiler_driver
30from . import model_reader
Diqing Zhong5e5a7842021-08-16 17:24:09 +020031from . import rawdata_writer
Diego Russoe8a10452020-04-21 17:39:10 +010032from . import scheduler
Tim Hall79d07d22020-04-27 18:20:16 +010033from . import stats_writer
34from . import tflite_writer
Tim Hall79d07d22020-04-27 18:20:16 +010035from ._version import __version__
Louis Verhaard11831ce2020-11-18 18:53:24 +010036from .api import API_VERSION
Tim Halle6ccd872020-11-09 16:46:37 +000037from .debug_database import DebugDatabase
Louis Verhaard7db78962020-05-25 15:05:26 +020038from .errors import InputFileError
Henrik G Olssonea9b23c2021-03-23 17:34:49 +010039from .errors import VelaError
Tim Hallcda4fcb2022-05-19 12:36:58 +010040from .hillclimb_allocation import HillClimbAllocator
Jonas Ohlsson45e653d2021-07-26 16:13:12 +020041from .nn_graph import NetworkType
Diego Russoe8a10452020-04-21 17:39:10 +010042from .nn_graph import TensorAllocator
Diego Russoea6111a2020-04-14 18:41:58 +010043from .tensor import MemArea
Jacob Bohlin0628a8c2020-08-28 13:25:14 +020044from .tensor import Tensor
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010045from .tflite.Model import Model
Michael McGeagh837dc1b2020-11-10 12:38:25 +000046from .tflite_mapping import builtin_operator_map
Tim Halla3fe6652022-03-03 17:43:16 +000047from .tflite_mapping import builtin_operator_name_map
Fredrik Svedberg88d5b122022-09-16 16:24:55 +020048from .tflite_mapping import optype_to_builtintype
Jonas Ohlsson45e653d2021-07-26 16:13:12 +020049from .tflite_model_semantic import TFLiteSemantic
50from .tflite_supported_operators import TFLiteSupportedOperators
51from .tosa_model_semantic import TosaSemantic
52from .tosa_supported_operators import TosaSupportedOperators
Louis Verhaard52078302020-11-18 13:35:06 +010053from ethosu.vela.architecture_features import ArchitectureFeatures
Tim Hall79d07d22020-04-27 18:20:16 +010054
Rickard Bolin7ce6b322022-06-02 09:30:33 +000055CONFIG_FILES_PATH = os.path.normpath(os.path.join(__file__, "..", "..", "config_files"))
Rickard Bolin1538dce2022-04-25 11:07:56 +000056
Tim Hall79d07d22020-04-27 18:20:16 +010057
Tim Halle6ccd872020-11-09 16:46:37 +000058def process(input_name, enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options):
Tim Hall79d07d22020-04-27 18:20:16 +010059 if compiler_options.timing:
60 start = time.time()
61
Tim Halle6ccd872020-11-09 16:46:37 +000062 os.makedirs(compiler_options.output_dir, exist_ok=True)
63 output_basename = os.path.join(compiler_options.output_dir, os.path.splitext(os.path.basename(input_name))[0])
64 DebugDatabase.show_warnings = enable_debug_db
65
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020066 nng, network_type = model_reader.read_model(input_name, model_reader_options)
Tim Hall79d07d22020-04-27 18:20:16 +010067
68 if not nng:
Michael McGeagh7a6f8432020-12-02 15:29:22 +000069 raise InputFileError(input_name, "Input file could not be read")
Tim Hall79d07d22020-04-27 18:20:16 +010070
71 if compiler_options.verbose_operators:
72 nng.print_operators()
73
74 if compiler_options.timing:
75 stop = time.time()
76 print("Model reading took %f s" % (stop - start))
77 start = time.time()
78
wilisa0189a8cdd2022-08-22 16:13:06 +000079 compiler_driver.compiler_driver(nng, arch, compiler_options, scheduler_options, network_type, output_basename)
Tim Hall79d07d22020-04-27 18:20:16 +010080
Tim Halle6ccd872020-11-09 16:46:37 +000081 summary_csv_file = "{0}_summary_{1}.csv".format(output_basename, arch.system_config)
Tim Hall79d07d22020-04-27 18:20:16 +010082 stats_writer.write_summary_metrics_csv(nng, summary_csv_file, arch)
83
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +020084 stats_writer.print_performance_metrics(
85 nng,
86 show_cpu_operations=compiler_options.show_cpu_operations,
87 verbose_weights=compiler_options.verbose_weights,
88 arch=arch,
89 )
Tim Hall79d07d22020-04-27 18:20:16 +010090
Diqing Zhong5e5a7842021-08-16 17:24:09 +020091 output_tfl_filename = output_basename + "_vela.tflite"
Patrik Gustavssonb081d672021-08-25 13:49:25 +020092 if input_name.endswith(".tflite"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020093 tflite_writer.write_tflite(nng, output_tfl_filename)
Patrik Gustavssonc74682c2021-08-17 14:26:38 +020094 if input_name.endswith(".tosa"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020095 rawdata_writer.write_rawdata_output(nng, arch, output_basename)
Tim Halle6ccd872020-11-09 16:46:37 +000096
97 if enable_debug_db:
Diqing Zhong5e5a7842021-08-16 17:24:09 +020098 file_offsets = calculate_operator_file_offsets(output_tfl_filename)
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010099 for idx, offset in enumerate(sorted(file_offsets)):
100 sg = find_subgraph_with_command_stream_order(nng, idx)
101 if sg is not None:
102 DebugDatabase.set_stream_offset(sg, offset)
Tim Halle6ccd872020-11-09 16:46:37 +0000103 debug_filename = output_basename + "_debug.xml"
Diqing Zhong5e5a7842021-08-16 17:24:09 +0200104 DebugDatabase.write(debug_filename, input_name, output_tfl_filename)
Tim Hall79d07d22020-04-27 18:20:16 +0100105
106 if compiler_options.timing:
107 stop = time.time()
108 print("Compiler driver took %f s" % (stop - start))
109
110 return nng
111
112
erik.andersson@arm.comad45f792021-02-03 10:20:16 +0100113def find_subgraph_with_command_stream_order(nng, idx):
114 for sg in nng.subgraphs:
115 if sg.generated_stream_id == idx:
116 return sg
117 return None
118
119
120def calculate_operator_file_offsets(name: str):
121 # Read the vela optimized tflite file
122 with open(name, "rb") as f:
123 buf = bytearray(f.read())
124 # Calculate the file offsets for each custom operator
125 file_offsets = []
126 model = Model.GetRootAsModel(buf, 0)
127 for idx in range(model.SubgraphsLength()): # However only one subgraph is supported as of now
128 sg = model.Subgraphs(idx)
129 for idx in range(sg.OperatorsLength()):
130 operator = sg.Operators(idx)
131 if model.OperatorCodes(operator.OpcodeIndex()).CustomCode() is not None:
132 tensor_idx = operator.Inputs(0)
133 tensor = sg.Tensors(tensor_idx)
134 buffer = model.Buffers(tensor.Buffer())
135 offset = flatbuffers.number_types.UOffsetTFlags.py_type(buffer._tab.Offset(4))
136 file_offsets.append(buffer._tab.Vector(offset))
137 return file_offsets
138
139
Tim Hall79d07d22020-04-27 18:20:16 +0100140def print_subgraph_io_summary(nng):
141 """Print a summary of all the input and output tensor sizes for all subgraphs.
142 Also displays the total tensor size and the memory used area for sram.
143 """
144
145 print("Subgraph IO Summary")
146 print("-------------------")
James Ward93389782021-10-14 12:58:02 +0100147 print(f"NNG: {nng.name}")
Tim Hall79d07d22020-04-27 18:20:16 +0100148 max_sg_size = 0
149 for sg in reversed(nng.subgraphs):
James Ward93389782021-10-14 12:58:02 +0100150 print(f" NNG Subgraph: {sg.name} = {sg.placement}")
Tim Hall79d07d22020-04-27 18:20:16 +0100151 sg_size = 0
152
James Ward93389782021-10-14 12:58:02 +0100153 if hasattr(sg, "scratch_tensor") and sg.scratch_tensor is not None:
154 sg_tensors = sg.input_tensors + [sg.scratch_tensor] + sg.output_tensors
155 else:
156 sg_tensors = sg.input_tensors + sg.output_tensors
Tim Hall79d07d22020-04-27 18:20:16 +0100157
James Ward93389782021-10-14 12:58:02 +0100158 for tens in sg_tensors:
159 if tens in sg.input_tensors:
160 tens_dir = "In"
161 elif tens in sg.output_tensors:
162 tens_dir = "Out"
163 else:
164 tens_dir = "In/Out"
Tim Hall79d07d22020-04-27 18:20:16 +0100165
James Ward93389782021-10-14 12:58:02 +0100166 size = tens.elements() * tens.element_size() / 1024.0
167 sg_size = sg_size + size
168 print(f" Tensor [{tens_dir}]: {tens.name} = {size} KiB")
169
170 print(f" Total Size = {sg_size} KiB")
171 print(f" SRAM Memory Used = {sg.memory_used.get(MemArea.Sram, 0) / 1024.0} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100172 max_sg_size = max(sg_size, max_sg_size)
173
James Ward93389782021-10-14 12:58:02 +0100174 print(f" Maximum NNG Subgraph Size = {max_sg_size} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100175
176
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000177def generate_supported_ops():
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200178 # Exclude network type from generation by adding value to exclude list.
179 # To easily exclude NetworkType from generated documentation.
180 exclude_generation_network_type_value = [NetworkType.TOSA.value]
181
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200182 def _exclude_list_names(constraint, exclude_list):
183 constraints_excluded_names = [
184 optype_to_builtintype(op) for op, exclude_constraint in exclude_list if constraint in exclude_constraint
185 ]
186 return f" - [{', '.join(sorted(constraints_excluded_names))}]" if constraints_excluded_names else ""
187
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000188 lines = [
189 "# Supported Ops",
190 "",
191 "This file was automatically generated by Vela using the `--supported-ops-report` parameter. ",
192 f"Vela version: `{__version__}`",
193 "",
Michael McGeagh54a61112020-11-24 14:58:51 +0000194 "This file complies with",
195 "[**Gitiles Markdown syntax**](https://github.com/google/gitiles/blob/master/Documentation/markdown.md)",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000196 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200197 "Summary table of constraints for:",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000198 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200199
200 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200201 if network_type.value in exclude_generation_network_type_value:
202 continue
203
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200204 lines += [
205 f"- [{network_type.name}](#{network_type.name.lower()}-summary-table)",
206 ]
207
208 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200209 if network_type.value in exclude_generation_network_type_value:
210 continue
211
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000212 lines += [
213 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200214 f"## {network_type.name} Summary Table",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000215 "",
216 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200217 if network_type == NetworkType.TFLite:
218 lines += [
219 "The table below contains TFLite operators that can be placed on the Ethos-U NPU. ",
220 "If the constraints are not met, then that operator will be scheduled on the CPU instead. ",
221 "For any other TFLite operator not listed, will be left untouched and scheduled on the CPU. ",
222 "Please check the supported operator list for your chosen runtime for further information.",
223 "",
224 "| Operator | TFLite Constraints |",
225 "| --- | --- |",
226 ]
227 semantic_checker = TFLiteSemantic()
228 supported = TFLiteSupportedOperators()
229 elif network_type == NetworkType.TOSA:
230 lines += [
231 "The table below contains TOSA operators that can be placed on the Ethos-U NPU. ",
232 "Note: There is limited support for compiling a TOSA neural network (EXPERIMENTAL). ",
233 "The related constraints have not yet been populated in the list.",
234 "",
235 "| Operator | TOSA Constraints |",
236 "| --- | --- |",
237 ]
238 semantic_checker = TosaSemantic()
239 supported = TosaSupportedOperators()
240 else:
241 raise ValueError
242
243 op_constraint_links = []
Tim Halla3fe6652022-03-03 17:43:16 +0000244 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 +0200245 for op, name in op_list:
246 internal_op = builtin_operator_map[op][0]
247 if internal_op in TFLiteSupportedOperators.supported_operators:
248 links = f"[Generic](#{network_type.name.lower()}-generic-constraints)"
249 if (
250 internal_op in supported.specific_constraints
251 or internal_op in semantic_checker.specific_constraints
252 ):
253 links += f", [Specific](#{network_type.name.lower()}-{name.lower()}-constraints)"
254 op_constraint_links.append((internal_op, name))
255 lines.append(f"| {name} | {links} |")
256 lines += [
257 "",
258 f"### {network_type.name} Generic Constraints",
259 "",
Ayaan Masood4965fae2022-06-29 11:30:57 +0100260 "This is a list of constraints most NPU operators must satisfy in order to be scheduled on the NPU.",
261 "(Operators excluded from certain constraints are shown in brackets [ ] )\n" "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200262 ]
263 for constraint in semantic_checker.generic_constraints:
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000264 # Markdown needs two spaces at the end of a line to render it as a separate line
265 reason = constraint.__doc__.replace("\n", " \n")
Ayaan Masood4965fae2022-06-29 11:30:57 +0100266 exclude_list = TFLiteSemantic.get_generic_constraint_exclude_list().items()
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200267 lines.append(f"- {reason}{_exclude_list_names(constraint, exclude_list)}")
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200268 for constraint in supported.generic_constraints:
269 # Markdown needs two spaces at the end of a line to render it as a separate line
270 reason = constraint.__doc__.replace("\n", " \n")
Fredrik Svedberg88d5b122022-09-16 16:24:55 +0200271 exclude_list = supported.generic_constraints_exceptions.items()
272 lines.append(f"- {reason}{_exclude_list_names(constraint, exclude_list)}")
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200273 for op, name in op_constraint_links:
274 lines += [
275 "",
276 f"### {network_type.name} {name} Constraints",
277 "",
278 f"This is a list of constraints that the {name} operator must satisfy in order to be scheduled on the"
279 " NPU.",
280 "",
281 ]
282 for constraint in semantic_checker.specific_constraints[op]:
283 # Markdown needs two spaces at the end of a line to render it as a separate line
284 reason = constraint.__doc__.replace("\n", " \n")
285 lines.append(f"- {reason}")
286 for constraint in supported.specific_constraints[op]:
287 # Markdown needs two spaces at the end of a line to render it as a separate line
288 reason = constraint.__doc__.replace("\n", " \n")
289 lines.append(f"- {reason}")
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000290
291 # Note. this will generate the file in the CWD
292 filepath = os.path.join(os.getcwd(), "SUPPORTED_OPS.md")
293 with open(filepath, "wt") as md:
294 md.writelines(line + "\n" for line in lines)
295 print(f"Report file: {filepath}")
296
297
Rickard Bolin1538dce2022-04-25 11:07:56 +0000298def list_config_files():
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000299 print("Available config files:")
300 path_length = len(CONFIG_FILES_PATH + os.path.sep)
Rickard Bolin1538dce2022-04-25 11:07:56 +0000301 for config in glob.glob(os.path.join(CONFIG_FILES_PATH, "*", "*.ini")):
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000302 print(config[path_length:])
Rickard Bolin1538dce2022-04-25 11:07:56 +0000303
304
Tim Hall79d07d22020-04-27 18:20:16 +0100305def main(args=None):
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100306 try:
307 if args is None:
308 args = sys.argv[1:]
Tim Hall79d07d22020-04-27 18:20:16 +0100309
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100310 parser = argparse.ArgumentParser(prog="vela", description="Neural network model compiler for Arm Ethos-U NPUs")
311 parser.add_argument("--version", action="version", version=__version__)
312 parser.add_argument(
313 "--api-version", action="version", version=API_VERSION, help="Displays the version of the external API."
314 )
315 parser.add_argument(
316 "--supported-ops-report",
317 action="store_true",
318 help="Generate the SUPPORTED_OPS.md file in the current working directory and exit",
Tim Hallb9b515c2020-11-01 21:27:19 +0000319 )
Jacob Bohlin0628a8c2020-08-28 13:25:14 +0200320
Rickard Bolin1538dce2022-04-25 11:07:56 +0000321 parser.add_argument(
322 "--list-config-files",
323 action="store_true",
324 help=(
325 "Display all available configurations in the `config_files` folder and exit. To select config file, "
326 "use the --config argument with one of the listed config files (For example: --config Arm/vela.ini )"
327 ),
328 )
329
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100330 # set network nargs to be optional to allow the support-ops-report CLI option to be used standalone
331 parser.add_argument(
332 "network",
333 metavar="NETWORK",
334 type=str,
335 default=None,
336 nargs="?",
337 help="Filename of the input TensorFlow Lite for Microcontrollers network",
338 )
339 parser.add_argument(
340 "--output-dir", type=str, default="output", help="Output directory to write files to (default: %(default)s)"
341 )
342 parser.add_argument(
343 "--enable-debug-db",
344 action="store_true",
345 default=None,
346 help="Enables the calculation and writing of a network debug database to output directory",
347 )
348 parser.add_argument(
349 "--config",
350 type=str,
351 action="append",
352 help="Vela configuration file(s) in Python ConfigParser .ini file format",
353 )
354 parser.add_argument("--verbose-all", action="store_true", help="Enable all verbose options")
355 parser.add_argument(
356 "--verbose-config", action="store_true", help="Verbose system configuration and memory mode"
357 )
358 parser.add_argument("--verbose-graph", action="store_true", help="Verbose graph rewriter")
359 parser.add_argument("--verbose-quantization", action="store_true", help="Verbose quantization")
360 parser.add_argument("--verbose-packing", action="store_true", help="Verbose pass packing")
361 parser.add_argument("--verbose-tensor-purpose", action="store_true", help="Verbose tensor purpose")
362 parser.add_argument("--verbose-tensor-format", action="store_true", help="Verbose tensor format")
363 parser.add_argument("--verbose-schedule", action="store_true", help="Verbose schedule")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100364 parser.add_argument("--verbose-allocation", action="store_true", help="Verbose tensor allocation")
365 parser.add_argument(
366 "--verbose-high-level-command-stream", action="store_true", help="Verbose high level command stream"
367 )
368 parser.add_argument(
369 "--verbose-register-command-stream", action="store_true", help="Verbose register command stream"
370 )
371 parser.add_argument("--verbose-operators", action="store_true", help="Verbose operator list")
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200372 parser.add_argument("--verbose-weights", action="store_true", help="Verbose weights information")
Tim Hallc1be0872022-03-03 17:50:52 +0000373 parser.add_argument("--verbose-performance", action="store_true", help="Verbose performance information")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100374 parser.add_argument(
375 "--show-cpu-operations", action="store_true", help="Show the operations that fall back to the CPU"
376 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100377 parser.add_argument("--timing", action="store_true", help="Time the compiler doing operations")
378 parser.add_argument(
379 "--accelerator-config",
380 type=str,
381 default="ethos-u55-256",
382 choices=list(architecture_features.Accelerator.member_list()),
383 help="Accelerator configuration to use (default: %(default)s)",
384 )
385 parser.add_argument(
386 "--system-config",
387 type=str,
388 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
389 help="System configuration to select from the Vela configuration file (default: %(default)s)",
390 )
391 parser.add_argument(
392 "--memory-mode",
393 type=str,
394 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
395 help="Memory mode to select from the Vela configuration file (default: %(default)s)",
396 )
397 parser.add_argument(
398 "--tensor-allocator",
399 default=TensorAllocator.HillClimb,
400 type=lambda s: TensorAllocator[s],
401 choices=list(TensorAllocator),
402 help="Tensor Allocator algorithm (default: %(default)s)",
403 )
404 parser.add_argument(
405 "--show-subgraph-io-summary",
406 action="store_true",
407 help="Shows a summary of all the subgraphs and their inputs and outputs",
408 )
409 parser.add_argument(
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100410 "--max-block-dependency",
411 type=int,
412 default=architecture_features.ArchitectureFeatures.MAX_BLOCKDEP,
413 choices=range(0, architecture_features.ArchitectureFeatures.MAX_BLOCKDEP + 1),
414 help=(
415 "Set the maximum value that can be used for the block dependency between npu kernel operations"
416 " (default: %(default)s)"
417 ),
418 )
419 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100420 "--optimise",
421 type=lambda s: scheduler.OptimizationStrategy[s],
422 default=scheduler.OptimizationStrategy.Performance,
423 choices=list(scheduler.OptimizationStrategy),
424 help=(
425 "Set the optimisation strategy. The Size strategy results in minimal SRAM usage (does not use"
426 " arena-cache-size). The Performance strategy results in maximal performance (uses the arena-cache-size"
427 " if specified) (default: %(default)s)"
428 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100429 )
430 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100431 "--arena-cache-size",
432 type=int,
433 help=(
434 "Set the size of the arena cache memory area, in bytes. If specified, this option overrides the memory"
435 " mode attribute with the same name in a Vela configuration file"
436 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100437 )
438 parser.add_argument(
439 "--cpu-tensor-alignment",
440 type=int,
441 default=Tensor.AllocationQuantum,
442 help=(
443 "Controls the allocation byte alignment of cpu tensors including Ethos-U Custom"
444 " operator inputs and outputs (default: %(default)s)"
445 ),
446 )
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200447 parser.add_argument(
448 "--recursion-limit",
449 type=int,
450 default=1000,
451 help="Set the recursion depth limit, may result in RecursionError if too low (default: %(default)s)",
452 )
Tim Hallcda4fcb2022-05-19 12:36:58 +0100453 parser.add_argument(
454 "--hillclimb-max-iterations",
455 type=int,
456 default=HillClimbAllocator.MAX_ITERATIONS,
457 help=(
458 "Set the maximum number of iterations the Hill Climb tensor allocator will run (default: %(default)s)"
459 ),
460 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100461 args = parser.parse_args(args=args)
Louis Verhaard52078302020-11-18 13:35:06 +0100462
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100463 # Generate the supported ops report and exit
464 if args.supported_ops_report:
465 generate_supported_ops()
466 return 0
Louis Verhaard52078302020-11-18 13:35:06 +0100467
Rickard Bolin1538dce2022-04-25 11:07:56 +0000468 if args.list_config_files:
469 list_config_files()
470 return 0
471
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100472 if args.network is None:
473 parser.error("the following argument is required: NETWORK")
Michael McGeagh2fa40ae2020-12-02 10:55:04 +0000474
Rickard Bolin1538dce2022-04-25 11:07:56 +0000475 def _parse_config(config):
Rickard Bolin7ce6b322022-06-02 09:30:33 +0000476 # Make sure the correct separator is used depending on OS
477 config = os.path.normpath(config)
478
Rickard Bolin1538dce2022-04-25 11:07:56 +0000479 if not config.endswith(".ini"):
480 raise InputFileError(config, "Configuration files must use the .ini extension")
481
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000482 if (
483 len(config.split(os.path.sep)) == 2
484 and not config.startswith(os.path.sep)
485 and not config.startswith(".")
486 and not config.startswith("~")
487 ):
Rickard Bolin1538dce2022-04-25 11:07:56 +0000488 config_path = os.path.join(CONFIG_FILES_PATH, config)
489 else:
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000490 # Check if the configuration file is correctly placed inside the config_files directory
491 if os.access(os.path.join(CONFIG_FILES_PATH, *config.split(os.path.sep)[-2:]), os.R_OK):
492 rel_path = os.path.join(*config.split(os.path.sep)[-2:])
493 print(
494 f"Warning: Consider accessing the configuration by --config {rel_path} since it is located "
495 "inside the config_files directory."
496 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000497 config_path = config
498
499 if not os.access(config_path, os.R_OK):
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000500 raise InputFileError(
501 config_path,
502 "File not found or is not readable. The configuration file is either not located in a folder "
503 "directly under the `config_files` directory or its path has not been provided correctly.",
504 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000505
506 return config_path
507
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100508 # check all config files exist because they will be read as a group
Rickard Bolin1538dce2022-04-25 11:07:56 +0000509 config_files = [_parse_config(cfg) for cfg in args.config] if args.config else None
Tim Hall79d07d22020-04-27 18:20:16 +0100510
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100511 if args.cpu_tensor_alignment < 16 or args.cpu_tensor_alignment & (args.cpu_tensor_alignment - 1) != 0:
512 parser.error(
513 "Invalid argument to --cpu-tensor-alignment = {} (must be greater than or equal to 16 and a power of 2)"
514 "".format(args.cpu_tensor_alignment)
515 )
Tim Hall79d07d22020-04-27 18:20:16 +0100516
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100517 if args.system_config == ArchitectureFeatures.DEFAULT_CONFIG:
518 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for system configuration")
Tim Hall79d07d22020-04-27 18:20:16 +0100519
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100520 if args.memory_mode == ArchitectureFeatures.DEFAULT_CONFIG:
521 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for memory mode")
Tim Hall79d07d22020-04-27 18:20:16 +0100522
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100523 if args.verbose_all:
524 for v in vars(args):
525 if v.startswith("verbose") and v != "verbose_all":
526 setattr(args, v, True)
527
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200528 sys.setrecursionlimit(args.recursion_limit)
529
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100530 arch = architecture_features.ArchitectureFeatures(
Rickard Bolin1538dce2022-04-25 11:07:56 +0000531 vela_config_files=config_files,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100532 system_config=args.system_config,
533 memory_mode=args.memory_mode,
534 accelerator_config=args.accelerator_config,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100535 max_blockdep=args.max_block_dependency,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100536 verbose_config=args.verbose_config,
Tim Halld8339a72021-05-27 18:49:40 +0100537 arena_cache_size=args.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100538 )
539
540 compiler_options = compiler_driver.CompilerOptions(
541 verbose_graph=args.verbose_graph,
542 verbose_quantization=args.verbose_quantization,
543 verbose_packing=args.verbose_packing,
544 verbose_tensor_purpose=args.verbose_tensor_purpose,
545 verbose_tensor_format=args.verbose_tensor_format,
546 verbose_allocation=args.verbose_allocation,
547 verbose_high_level_command_stream=args.verbose_high_level_command_stream,
548 verbose_register_command_stream=args.verbose_register_command_stream,
549 verbose_operators=args.verbose_operators,
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200550 verbose_weights=args.verbose_weights,
Tim Hallc1be0872022-03-03 17:50:52 +0000551 verbose_performance=args.verbose_performance,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100552 show_cpu_operations=args.show_cpu_operations,
553 tensor_allocator=args.tensor_allocator,
554 timing=args.timing,
555 output_dir=args.output_dir,
556 cpu_tensor_alignment=args.cpu_tensor_alignment,
Tim Hallcda4fcb2022-05-19 12:36:58 +0100557 hillclimb_max_iterations=args.hillclimb_max_iterations,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100558 )
559
560 scheduler_options = scheduler.SchedulerOptions(
Tim Halld8339a72021-05-27 18:49:40 +0100561 optimization_strategy=args.optimise,
562 sram_target=arch.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100563 verbose_schedule=args.verbose_schedule,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100564 )
565
566 model_reader_options = model_reader.ModelReaderOptions()
567
568 nng = process(
569 args.network, args.enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options
570 )
571
572 if args.show_subgraph_io_summary:
573 print_subgraph_io_summary(nng)
574
575 return 0
576 except VelaError as e:
577 print(e.data)
578 return 1