blob: 90cff0346f2ca4a5ab17438d53b968d55186cb57 [file] [log] [blame]
erik.andersson@arm.comad45f792021-02-03 10:20:16 +01001# Copyright (C) 2020-2021 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
Jonas Ohlsson45e653d2021-07-26 16:13:12 +020048from .tflite_model_semantic import TFLiteSemantic
49from .tflite_supported_operators import TFLiteSupportedOperators
50from .tosa_model_semantic import TosaSemantic
51from .tosa_supported_operators import TosaSupportedOperators
Louis Verhaard52078302020-11-18 13:35:06 +010052from ethosu.vela.architecture_features import ArchitectureFeatures
Tim Hall79d07d22020-04-27 18:20:16 +010053
Rickard Bolin7ce6b322022-06-02 09:30:33 +000054CONFIG_FILES_PATH = os.path.normpath(os.path.join(__file__, "..", "..", "config_files"))
Rickard Bolin1538dce2022-04-25 11:07:56 +000055
Tim Hall79d07d22020-04-27 18:20:16 +010056
Tim Halle6ccd872020-11-09 16:46:37 +000057def process(input_name, enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options):
Tim Hall79d07d22020-04-27 18:20:16 +010058 if compiler_options.timing:
59 start = time.time()
60
Tim Halle6ccd872020-11-09 16:46:37 +000061 os.makedirs(compiler_options.output_dir, exist_ok=True)
62 output_basename = os.path.join(compiler_options.output_dir, os.path.splitext(os.path.basename(input_name))[0])
63 DebugDatabase.show_warnings = enable_debug_db
64
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020065 nng, network_type = model_reader.read_model(input_name, model_reader_options)
Tim Hall79d07d22020-04-27 18:20:16 +010066
67 if not nng:
Michael McGeagh7a6f8432020-12-02 15:29:22 +000068 raise InputFileError(input_name, "Input file could not be read")
Tim Hall79d07d22020-04-27 18:20:16 +010069
70 if compiler_options.verbose_operators:
71 nng.print_operators()
72
73 if compiler_options.timing:
74 stop = time.time()
75 print("Model reading took %f s" % (stop - start))
76 start = time.time()
77
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020078 compiler_driver.compiler_driver(nng, arch, compiler_options, scheduler_options, network_type)
Tim Hall79d07d22020-04-27 18:20:16 +010079
Tim Halle6ccd872020-11-09 16:46:37 +000080 summary_csv_file = "{0}_summary_{1}.csv".format(output_basename, arch.system_config)
Tim Hall79d07d22020-04-27 18:20:16 +010081 stats_writer.write_summary_metrics_csv(nng, summary_csv_file, arch)
82
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +020083 stats_writer.print_performance_metrics(
84 nng,
85 show_cpu_operations=compiler_options.show_cpu_operations,
86 verbose_weights=compiler_options.verbose_weights,
87 arch=arch,
88 )
Tim Hall79d07d22020-04-27 18:20:16 +010089
Diqing Zhong5e5a7842021-08-16 17:24:09 +020090 output_tfl_filename = output_basename + "_vela.tflite"
Patrik Gustavssonb081d672021-08-25 13:49:25 +020091 if input_name.endswith(".tflite"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020092 tflite_writer.write_tflite(nng, output_tfl_filename)
Patrik Gustavssonc74682c2021-08-17 14:26:38 +020093 if input_name.endswith(".tosa"):
Diqing Zhong5e5a7842021-08-16 17:24:09 +020094 rawdata_writer.write_rawdata_output(nng, arch, output_basename)
Tim Halle6ccd872020-11-09 16:46:37 +000095
96 if enable_debug_db:
Diqing Zhong5e5a7842021-08-16 17:24:09 +020097 file_offsets = calculate_operator_file_offsets(output_tfl_filename)
erik.andersson@arm.comad45f792021-02-03 10:20:16 +010098 for idx, offset in enumerate(sorted(file_offsets)):
99 sg = find_subgraph_with_command_stream_order(nng, idx)
100 if sg is not None:
101 DebugDatabase.set_stream_offset(sg, offset)
Tim Halle6ccd872020-11-09 16:46:37 +0000102 debug_filename = output_basename + "_debug.xml"
Diqing Zhong5e5a7842021-08-16 17:24:09 +0200103 DebugDatabase.write(debug_filename, input_name, output_tfl_filename)
Tim Hall79d07d22020-04-27 18:20:16 +0100104
105 if compiler_options.timing:
106 stop = time.time()
107 print("Compiler driver took %f s" % (stop - start))
108
109 return nng
110
111
erik.andersson@arm.comad45f792021-02-03 10:20:16 +0100112def find_subgraph_with_command_stream_order(nng, idx):
113 for sg in nng.subgraphs:
114 if sg.generated_stream_id == idx:
115 return sg
116 return None
117
118
119def calculate_operator_file_offsets(name: str):
120 # Read the vela optimized tflite file
121 with open(name, "rb") as f:
122 buf = bytearray(f.read())
123 # Calculate the file offsets for each custom operator
124 file_offsets = []
125 model = Model.GetRootAsModel(buf, 0)
126 for idx in range(model.SubgraphsLength()): # However only one subgraph is supported as of now
127 sg = model.Subgraphs(idx)
128 for idx in range(sg.OperatorsLength()):
129 operator = sg.Operators(idx)
130 if model.OperatorCodes(operator.OpcodeIndex()).CustomCode() is not None:
131 tensor_idx = operator.Inputs(0)
132 tensor = sg.Tensors(tensor_idx)
133 buffer = model.Buffers(tensor.Buffer())
134 offset = flatbuffers.number_types.UOffsetTFlags.py_type(buffer._tab.Offset(4))
135 file_offsets.append(buffer._tab.Vector(offset))
136 return file_offsets
137
138
Tim Hall79d07d22020-04-27 18:20:16 +0100139def print_subgraph_io_summary(nng):
140 """Print a summary of all the input and output tensor sizes for all subgraphs.
141 Also displays the total tensor size and the memory used area for sram.
142 """
143
144 print("Subgraph IO Summary")
145 print("-------------------")
James Ward93389782021-10-14 12:58:02 +0100146 print(f"NNG: {nng.name}")
Tim Hall79d07d22020-04-27 18:20:16 +0100147 max_sg_size = 0
148 for sg in reversed(nng.subgraphs):
James Ward93389782021-10-14 12:58:02 +0100149 print(f" NNG Subgraph: {sg.name} = {sg.placement}")
Tim Hall79d07d22020-04-27 18:20:16 +0100150 sg_size = 0
151
James Ward93389782021-10-14 12:58:02 +0100152 if hasattr(sg, "scratch_tensor") and sg.scratch_tensor is not None:
153 sg_tensors = sg.input_tensors + [sg.scratch_tensor] + sg.output_tensors
154 else:
155 sg_tensors = sg.input_tensors + sg.output_tensors
Tim Hall79d07d22020-04-27 18:20:16 +0100156
James Ward93389782021-10-14 12:58:02 +0100157 for tens in sg_tensors:
158 if tens in sg.input_tensors:
159 tens_dir = "In"
160 elif tens in sg.output_tensors:
161 tens_dir = "Out"
162 else:
163 tens_dir = "In/Out"
Tim Hall79d07d22020-04-27 18:20:16 +0100164
James Ward93389782021-10-14 12:58:02 +0100165 size = tens.elements() * tens.element_size() / 1024.0
166 sg_size = sg_size + size
167 print(f" Tensor [{tens_dir}]: {tens.name} = {size} KiB")
168
169 print(f" Total Size = {sg_size} KiB")
170 print(f" SRAM Memory Used = {sg.memory_used.get(MemArea.Sram, 0) / 1024.0} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100171 max_sg_size = max(sg_size, max_sg_size)
172
James Ward93389782021-10-14 12:58:02 +0100173 print(f" Maximum NNG Subgraph Size = {max_sg_size} KiB")
Tim Hall79d07d22020-04-27 18:20:16 +0100174
175
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000176def generate_supported_ops():
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200177 # Exclude network type from generation by adding value to exclude list.
178 # To easily exclude NetworkType from generated documentation.
179 exclude_generation_network_type_value = [NetworkType.TOSA.value]
180
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000181 lines = [
182 "# Supported Ops",
183 "",
184 "This file was automatically generated by Vela using the `--supported-ops-report` parameter. ",
185 f"Vela version: `{__version__}`",
186 "",
Michael McGeagh54a61112020-11-24 14:58:51 +0000187 "This file complies with",
188 "[**Gitiles Markdown syntax**](https://github.com/google/gitiles/blob/master/Documentation/markdown.md)",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000189 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200190 "Summary table of constraints for:",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000191 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200192
193 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200194 if network_type.value in exclude_generation_network_type_value:
195 continue
196
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200197 lines += [
198 f"- [{network_type.name}](#{network_type.name.lower()}-summary-table)",
199 ]
200
201 for network_type in NetworkType:
Jonas Ohlsson0957e3e2021-09-01 15:57:21 +0200202 if network_type.value in exclude_generation_network_type_value:
203 continue
204
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000205 lines += [
206 "",
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200207 f"## {network_type.name} Summary Table",
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000208 "",
209 ]
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200210 if network_type == NetworkType.TFLite:
211 lines += [
212 "The table below contains TFLite operators that can be placed on the Ethos-U NPU. ",
213 "If the constraints are not met, then that operator will be scheduled on the CPU instead. ",
214 "For any other TFLite operator not listed, will be left untouched and scheduled on the CPU. ",
215 "Please check the supported operator list for your chosen runtime for further information.",
216 "",
217 "| Operator | TFLite Constraints |",
218 "| --- | --- |",
219 ]
220 semantic_checker = TFLiteSemantic()
221 supported = TFLiteSupportedOperators()
222 elif network_type == NetworkType.TOSA:
223 lines += [
224 "The table below contains TOSA operators that can be placed on the Ethos-U NPU. ",
225 "Note: There is limited support for compiling a TOSA neural network (EXPERIMENTAL). ",
226 "The related constraints have not yet been populated in the list.",
227 "",
228 "| Operator | TOSA Constraints |",
229 "| --- | --- |",
230 ]
231 semantic_checker = TosaSemantic()
232 supported = TosaSupportedOperators()
233 else:
234 raise ValueError
235
236 op_constraint_links = []
Tim Halla3fe6652022-03-03 17:43:16 +0000237 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 +0200238 for op, name in op_list:
239 internal_op = builtin_operator_map[op][0]
240 if internal_op in TFLiteSupportedOperators.supported_operators:
241 links = f"[Generic](#{network_type.name.lower()}-generic-constraints)"
242 if (
243 internal_op in supported.specific_constraints
244 or internal_op in semantic_checker.specific_constraints
245 ):
246 links += f", [Specific](#{network_type.name.lower()}-{name.lower()}-constraints)"
247 op_constraint_links.append((internal_op, name))
248 lines.append(f"| {name} | {links} |")
249 lines += [
250 "",
251 f"### {network_type.name} Generic Constraints",
252 "",
253 "This is a list of constraints that all NPU operators must satisfy in order to be scheduled on the NPU.",
254 "",
255 ]
256 for constraint in semantic_checker.generic_constraints:
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000257 # Markdown needs two spaces at the end of a line to render it as a separate line
258 reason = constraint.__doc__.replace("\n", " \n")
259 lines.append(f"- {reason}")
Jonas Ohlsson45e653d2021-07-26 16:13:12 +0200260 for constraint in supported.generic_constraints:
261 # Markdown needs two spaces at the end of a line to render it as a separate line
262 reason = constraint.__doc__.replace("\n", " \n")
263 lines.append(f"- {reason}")
264 for op, name in op_constraint_links:
265 lines += [
266 "",
267 f"### {network_type.name} {name} Constraints",
268 "",
269 f"This is a list of constraints that the {name} operator must satisfy in order to be scheduled on the"
270 " NPU.",
271 "",
272 ]
273 for constraint in semantic_checker.specific_constraints[op]:
274 # Markdown needs two spaces at the end of a line to render it as a separate line
275 reason = constraint.__doc__.replace("\n", " \n")
276 lines.append(f"- {reason}")
277 for constraint in supported.specific_constraints[op]:
278 # Markdown needs two spaces at the end of a line to render it as a separate line
279 reason = constraint.__doc__.replace("\n", " \n")
280 lines.append(f"- {reason}")
Michael McGeagh837dc1b2020-11-10 12:38:25 +0000281
282 # Note. this will generate the file in the CWD
283 filepath = os.path.join(os.getcwd(), "SUPPORTED_OPS.md")
284 with open(filepath, "wt") as md:
285 md.writelines(line + "\n" for line in lines)
286 print(f"Report file: {filepath}")
287
288
Rickard Bolin1538dce2022-04-25 11:07:56 +0000289def list_config_files():
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000290 print("Available config files:")
291 path_length = len(CONFIG_FILES_PATH + os.path.sep)
Rickard Bolin1538dce2022-04-25 11:07:56 +0000292 for config in glob.glob(os.path.join(CONFIG_FILES_PATH, "*", "*.ini")):
Rickard Bolin9b8b4482022-05-24 07:43:03 +0000293 print(config[path_length:])
Rickard Bolin1538dce2022-04-25 11:07:56 +0000294
295
Tim Hall79d07d22020-04-27 18:20:16 +0100296def main(args=None):
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100297 try:
298 if args is None:
299 args = sys.argv[1:]
Tim Hall79d07d22020-04-27 18:20:16 +0100300
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100301 parser = argparse.ArgumentParser(prog="vela", description="Neural network model compiler for Arm Ethos-U NPUs")
302 parser.add_argument("--version", action="version", version=__version__)
303 parser.add_argument(
304 "--api-version", action="version", version=API_VERSION, help="Displays the version of the external API."
305 )
306 parser.add_argument(
307 "--supported-ops-report",
308 action="store_true",
309 help="Generate the SUPPORTED_OPS.md file in the current working directory and exit",
Tim Hallb9b515c2020-11-01 21:27:19 +0000310 )
Jacob Bohlin0628a8c2020-08-28 13:25:14 +0200311
Rickard Bolin1538dce2022-04-25 11:07:56 +0000312 parser.add_argument(
313 "--list-config-files",
314 action="store_true",
315 help=(
316 "Display all available configurations in the `config_files` folder and exit. To select config file, "
317 "use the --config argument with one of the listed config files (For example: --config Arm/vela.ini )"
318 ),
319 )
320
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100321 # set network nargs to be optional to allow the support-ops-report CLI option to be used standalone
322 parser.add_argument(
323 "network",
324 metavar="NETWORK",
325 type=str,
326 default=None,
327 nargs="?",
328 help="Filename of the input TensorFlow Lite for Microcontrollers network",
329 )
330 parser.add_argument(
331 "--output-dir", type=str, default="output", help="Output directory to write files to (default: %(default)s)"
332 )
333 parser.add_argument(
334 "--enable-debug-db",
335 action="store_true",
336 default=None,
337 help="Enables the calculation and writing of a network debug database to output directory",
338 )
339 parser.add_argument(
340 "--config",
341 type=str,
342 action="append",
343 help="Vela configuration file(s) in Python ConfigParser .ini file format",
344 )
345 parser.add_argument("--verbose-all", action="store_true", help="Enable all verbose options")
346 parser.add_argument(
347 "--verbose-config", action="store_true", help="Verbose system configuration and memory mode"
348 )
349 parser.add_argument("--verbose-graph", action="store_true", help="Verbose graph rewriter")
350 parser.add_argument("--verbose-quantization", action="store_true", help="Verbose quantization")
351 parser.add_argument("--verbose-packing", action="store_true", help="Verbose pass packing")
352 parser.add_argument("--verbose-tensor-purpose", action="store_true", help="Verbose tensor purpose")
353 parser.add_argument("--verbose-tensor-format", action="store_true", help="Verbose tensor format")
354 parser.add_argument("--verbose-schedule", action="store_true", help="Verbose schedule")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100355 parser.add_argument("--verbose-allocation", action="store_true", help="Verbose tensor allocation")
356 parser.add_argument(
357 "--verbose-high-level-command-stream", action="store_true", help="Verbose high level command stream"
358 )
359 parser.add_argument(
360 "--verbose-register-command-stream", action="store_true", help="Verbose register command stream"
361 )
362 parser.add_argument("--verbose-operators", action="store_true", help="Verbose operator list")
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200363 parser.add_argument("--verbose-weights", action="store_true", help="Verbose weights information")
Tim Hallc1be0872022-03-03 17:50:52 +0000364 parser.add_argument("--verbose-performance", action="store_true", help="Verbose performance information")
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100365 parser.add_argument(
366 "--show-cpu-operations", action="store_true", help="Show the operations that fall back to the CPU"
367 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100368 parser.add_argument("--timing", action="store_true", help="Time the compiler doing operations")
369 parser.add_argument(
370 "--accelerator-config",
371 type=str,
372 default="ethos-u55-256",
373 choices=list(architecture_features.Accelerator.member_list()),
374 help="Accelerator configuration to use (default: %(default)s)",
375 )
376 parser.add_argument(
377 "--system-config",
378 type=str,
379 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
380 help="System configuration to select from the Vela configuration file (default: %(default)s)",
381 )
382 parser.add_argument(
383 "--memory-mode",
384 type=str,
385 default=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
386 help="Memory mode to select from the Vela configuration file (default: %(default)s)",
387 )
388 parser.add_argument(
389 "--tensor-allocator",
390 default=TensorAllocator.HillClimb,
391 type=lambda s: TensorAllocator[s],
392 choices=list(TensorAllocator),
393 help="Tensor Allocator algorithm (default: %(default)s)",
394 )
395 parser.add_argument(
396 "--show-subgraph-io-summary",
397 action="store_true",
398 help="Shows a summary of all the subgraphs and their inputs and outputs",
399 )
400 parser.add_argument(
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100401 "--max-block-dependency",
402 type=int,
403 default=architecture_features.ArchitectureFeatures.MAX_BLOCKDEP,
404 choices=range(0, architecture_features.ArchitectureFeatures.MAX_BLOCKDEP + 1),
405 help=(
406 "Set the maximum value that can be used for the block dependency between npu kernel operations"
407 " (default: %(default)s)"
408 ),
409 )
410 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100411 "--optimise",
412 type=lambda s: scheduler.OptimizationStrategy[s],
413 default=scheduler.OptimizationStrategy.Performance,
414 choices=list(scheduler.OptimizationStrategy),
415 help=(
416 "Set the optimisation strategy. The Size strategy results in minimal SRAM usage (does not use"
417 " arena-cache-size). The Performance strategy results in maximal performance (uses the arena-cache-size"
418 " if specified) (default: %(default)s)"
419 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100420 )
421 parser.add_argument(
Tim Halld8339a72021-05-27 18:49:40 +0100422 "--arena-cache-size",
423 type=int,
424 help=(
425 "Set the size of the arena cache memory area, in bytes. If specified, this option overrides the memory"
426 " mode attribute with the same name in a Vela configuration file"
427 ),
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100428 )
429 parser.add_argument(
430 "--cpu-tensor-alignment",
431 type=int,
432 default=Tensor.AllocationQuantum,
433 help=(
434 "Controls the allocation byte alignment of cpu tensors including Ethos-U Custom"
435 " operator inputs and outputs (default: %(default)s)"
436 ),
437 )
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200438 parser.add_argument(
439 "--recursion-limit",
440 type=int,
441 default=1000,
442 help="Set the recursion depth limit, may result in RecursionError if too low (default: %(default)s)",
443 )
Tim Hallcda4fcb2022-05-19 12:36:58 +0100444 parser.add_argument(
445 "--hillclimb-max-iterations",
446 type=int,
447 default=HillClimbAllocator.MAX_ITERATIONS,
448 help=(
449 "Set the maximum number of iterations the Hill Climb tensor allocator will run (default: %(default)s)"
450 ),
451 )
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100452 args = parser.parse_args(args=args)
Louis Verhaard52078302020-11-18 13:35:06 +0100453
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100454 # Generate the supported ops report and exit
455 if args.supported_ops_report:
456 generate_supported_ops()
457 return 0
Louis Verhaard52078302020-11-18 13:35:06 +0100458
Rickard Bolin1538dce2022-04-25 11:07:56 +0000459 if args.list_config_files:
460 list_config_files()
461 return 0
462
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100463 if args.network is None:
464 parser.error("the following argument is required: NETWORK")
Michael McGeagh2fa40ae2020-12-02 10:55:04 +0000465
Rickard Bolin1538dce2022-04-25 11:07:56 +0000466 def _parse_config(config):
Rickard Bolin7ce6b322022-06-02 09:30:33 +0000467 # Make sure the correct separator is used depending on OS
468 config = os.path.normpath(config)
469
Rickard Bolin1538dce2022-04-25 11:07:56 +0000470 if not config.endswith(".ini"):
471 raise InputFileError(config, "Configuration files must use the .ini extension")
472
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000473 if (
474 len(config.split(os.path.sep)) == 2
475 and not config.startswith(os.path.sep)
476 and not config.startswith(".")
477 and not config.startswith("~")
478 ):
Rickard Bolin1538dce2022-04-25 11:07:56 +0000479 config_path = os.path.join(CONFIG_FILES_PATH, config)
480 else:
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000481 # Check if the configuration file is correctly placed inside the config_files directory
482 if os.access(os.path.join(CONFIG_FILES_PATH, *config.split(os.path.sep)[-2:]), os.R_OK):
483 rel_path = os.path.join(*config.split(os.path.sep)[-2:])
484 print(
485 f"Warning: Consider accessing the configuration by --config {rel_path} since it is located "
486 "inside the config_files directory."
487 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000488 config_path = config
489
490 if not os.access(config_path, os.R_OK):
Rickard Bolin6d7a4f02022-05-24 14:17:58 +0000491 raise InputFileError(
492 config_path,
493 "File not found or is not readable. The configuration file is either not located in a folder "
494 "directly under the `config_files` directory or its path has not been provided correctly.",
495 )
Rickard Bolin1538dce2022-04-25 11:07:56 +0000496
497 return config_path
498
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100499 # check all config files exist because they will be read as a group
Rickard Bolin1538dce2022-04-25 11:07:56 +0000500 config_files = [_parse_config(cfg) for cfg in args.config] if args.config else None
Tim Hall79d07d22020-04-27 18:20:16 +0100501
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100502 if args.cpu_tensor_alignment < 16 or args.cpu_tensor_alignment & (args.cpu_tensor_alignment - 1) != 0:
503 parser.error(
504 "Invalid argument to --cpu-tensor-alignment = {} (must be greater than or equal to 16 and a power of 2)"
505 "".format(args.cpu_tensor_alignment)
506 )
Tim Hall79d07d22020-04-27 18:20:16 +0100507
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100508 if args.system_config == ArchitectureFeatures.DEFAULT_CONFIG:
509 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for system configuration")
Tim Hall79d07d22020-04-27 18:20:16 +0100510
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100511 if args.memory_mode == ArchitectureFeatures.DEFAULT_CONFIG:
512 print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for memory mode")
Tim Hall79d07d22020-04-27 18:20:16 +0100513
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100514 if args.verbose_all:
515 for v in vars(args):
516 if v.startswith("verbose") and v != "verbose_all":
517 setattr(args, v, True)
518
Dwight Lidmanb9c95422021-08-18 19:24:14 +0200519 sys.setrecursionlimit(args.recursion_limit)
520
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100521 arch = architecture_features.ArchitectureFeatures(
Rickard Bolin1538dce2022-04-25 11:07:56 +0000522 vela_config_files=config_files,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100523 system_config=args.system_config,
524 memory_mode=args.memory_mode,
525 accelerator_config=args.accelerator_config,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100526 max_blockdep=args.max_block_dependency,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100527 verbose_config=args.verbose_config,
Tim Halld8339a72021-05-27 18:49:40 +0100528 arena_cache_size=args.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100529 )
530
531 compiler_options = compiler_driver.CompilerOptions(
532 verbose_graph=args.verbose_graph,
533 verbose_quantization=args.verbose_quantization,
534 verbose_packing=args.verbose_packing,
535 verbose_tensor_purpose=args.verbose_tensor_purpose,
536 verbose_tensor_format=args.verbose_tensor_format,
537 verbose_allocation=args.verbose_allocation,
538 verbose_high_level_command_stream=args.verbose_high_level_command_stream,
539 verbose_register_command_stream=args.verbose_register_command_stream,
540 verbose_operators=args.verbose_operators,
Fredrik Svedbergf5c07c42021-04-23 14:36:42 +0200541 verbose_weights=args.verbose_weights,
Tim Hallc1be0872022-03-03 17:50:52 +0000542 verbose_performance=args.verbose_performance,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100543 show_cpu_operations=args.show_cpu_operations,
544 tensor_allocator=args.tensor_allocator,
545 timing=args.timing,
546 output_dir=args.output_dir,
547 cpu_tensor_alignment=args.cpu_tensor_alignment,
Tim Hallcda4fcb2022-05-19 12:36:58 +0100548 hillclimb_max_iterations=args.hillclimb_max_iterations,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100549 )
550
551 scheduler_options = scheduler.SchedulerOptions(
Tim Halld8339a72021-05-27 18:49:40 +0100552 optimization_strategy=args.optimise,
553 sram_target=arch.arena_cache_size,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100554 verbose_schedule=args.verbose_schedule,
Henrik G Olssonea9b23c2021-03-23 17:34:49 +0100555 )
556
557 model_reader_options = model_reader.ModelReaderOptions()
558
559 nng = process(
560 args.network, args.enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options
561 )
562
563 if args.show_subgraph_io_summary:
564 print_subgraph_io_summary(nng)
565
566 return 0
567 except VelaError as e:
568 print(e.data)
569 return 1