aboutsummaryrefslogtreecommitdiff
path: root/src/aiet/resources
diff options
context:
space:
mode:
Diffstat (limited to 'src/aiet/resources')
-rw-r--r--src/aiet/resources/applications/.gitignore6
-rw-r--r--src/aiet/resources/systems/.gitignore6
-rw-r--r--src/aiet/resources/tools/vela/aiet-config.json73
-rw-r--r--src/aiet/resources/tools/vela/aiet-config.json.license3
-rw-r--r--src/aiet/resources/tools/vela/check_model.py75
-rw-r--r--src/aiet/resources/tools/vela/run_vela.py65
-rw-r--r--src/aiet/resources/tools/vela/vela.ini53
7 files changed, 281 insertions, 0 deletions
diff --git a/src/aiet/resources/applications/.gitignore b/src/aiet/resources/applications/.gitignore
new file mode 100644
index 0000000..0226166
--- /dev/null
+++ b/src/aiet/resources/applications/.gitignore
@@ -0,0 +1,6 @@
+# SPDX-FileCopyrightText: Copyright 2022, Arm Limited and/or its affiliates.
+# SPDX-License-Identifier: Apache-2.0
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/src/aiet/resources/systems/.gitignore b/src/aiet/resources/systems/.gitignore
new file mode 100644
index 0000000..0226166
--- /dev/null
+++ b/src/aiet/resources/systems/.gitignore
@@ -0,0 +1,6 @@
+# SPDX-FileCopyrightText: Copyright 2022, Arm Limited and/or its affiliates.
+# SPDX-License-Identifier: Apache-2.0
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/src/aiet/resources/tools/vela/aiet-config.json b/src/aiet/resources/tools/vela/aiet-config.json
new file mode 100644
index 0000000..c12f291
--- /dev/null
+++ b/src/aiet/resources/tools/vela/aiet-config.json
@@ -0,0 +1,73 @@
+[
+ {
+ "name": "vela",
+ "description": "Neural network model compiler for Arm Ethos-U NPUs",
+ "supported_systems": [
+ {
+ "name": "Corstone-300: Cortex-M55+Ethos-U55"
+ },
+ {
+ "name": "Corstone-310: Cortex-M85+Ethos-U55"
+ },
+ {
+ "name": "Corstone-300: Cortex-M55+Ethos-U65",
+ "variables": {
+ "accelerator_config_prefix": "ethos-u65",
+ "system_config": "Ethos_U65_High_End",
+ "shared_sram": "U65_Shared_Sram"
+ },
+ "user_params": {
+ "run": [
+ {
+ "description": "MACs per cycle",
+ "values": [
+ "256",
+ "512"
+ ],
+ "default_value": "512",
+ "alias": "mac"
+ }
+ ]
+ }
+ }
+ ],
+ "variables": {
+ "accelerator_config_prefix": "ethos-u55",
+ "system_config": "Ethos_U55_High_End_Embedded",
+ "shared_sram": "U55_Shared_Sram"
+ },
+ "commands": {
+ "run": [
+ "run_vela {user_params:input} {user_params:output} --config {tool.config_dir}/vela.ini --accelerator-config {variables:accelerator_config_prefix}-{user_params:mac} --system-config {variables:system_config} --memory-mode {variables:shared_sram} --optimise Performance"
+ ]
+ },
+ "user_params": {
+ "run": [
+ {
+ "description": "MACs per cycle",
+ "values": [
+ "32",
+ "64",
+ "128",
+ "256"
+ ],
+ "default_value": "128",
+ "alias": "mac"
+ },
+ {
+ "name": "--input-model",
+ "description": "Path to the TFLite model",
+ "values": [],
+ "alias": "input"
+ },
+ {
+ "name": "--output-model",
+ "description": "Path to the output model file of the vela-optimisation step. The vela output is saved in the parent directory.",
+ "values": [],
+ "default_value": "output_model.tflite",
+ "alias": "output"
+ }
+ ]
+ }
+ }
+]
diff --git a/src/aiet/resources/tools/vela/aiet-config.json.license b/src/aiet/resources/tools/vela/aiet-config.json.license
new file mode 100644
index 0000000..9b83bfc
--- /dev/null
+++ b/src/aiet/resources/tools/vela/aiet-config.json.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: Copyright 2022, Arm Limited and/or its affiliates.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/src/aiet/resources/tools/vela/check_model.py b/src/aiet/resources/tools/vela/check_model.py
new file mode 100644
index 0000000..7c700b1
--- /dev/null
+++ b/src/aiet/resources/tools/vela/check_model.py
@@ -0,0 +1,75 @@
+# SPDX-FileCopyrightText: Copyright 2020, 2022, Arm Limited and/or its affiliates.
+# SPDX-License-Identifier: Apache-2.0
+"""Check if a TFLite model file is Vela-optimised."""
+import struct
+from pathlib import Path
+
+from ethosu.vela.tflite.Model import Model
+
+from aiet.cli.common import InvalidTFLiteFileError
+from aiet.cli.common import ModelOptimisedException
+from aiet.utils.fs import read_file_as_bytearray
+
+
+def get_model_from_file(input_model_file: Path) -> Model:
+ """Generate Model instance from TFLite file using flatc generated code."""
+ buffer = read_file_as_bytearray(input_model_file)
+ try:
+ model = Model.GetRootAsModel(buffer, 0)
+ except (TypeError, RuntimeError, struct.error) as tflite_error:
+ raise InvalidTFLiteFileError(
+ f"Error reading in model from {input_model_file}."
+ ) from tflite_error
+ return model
+
+
+def is_vela_optimised(tflite_model: Model) -> bool:
+ """Return True if 'ethos-u' custom operator found in the Model."""
+ operators = get_operators_from_model(tflite_model)
+
+ custom_codes = get_custom_codes_from_operators(operators)
+
+ return check_custom_codes_for_ethosu(custom_codes)
+
+
+def get_operators_from_model(tflite_model: Model) -> list:
+ """Return list of the unique operator codes used in the Model."""
+ return [
+ tflite_model.OperatorCodes(index)
+ for index in range(tflite_model.OperatorCodesLength())
+ ]
+
+
+def get_custom_codes_from_operators(operators: list) -> list:
+ """Return list of each operator's CustomCode() strings, if they exist."""
+ return [
+ operator.CustomCode()
+ for operator in operators
+ if operator.CustomCode() is not None
+ ]
+
+
+def check_custom_codes_for_ethosu(custom_codes: list) -> bool:
+ """Check for existence of ethos-u string in the custom codes."""
+ return any(
+ custom_code_name.decode("utf-8") == "ethos-u"
+ for custom_code_name in custom_codes
+ )
+
+
+def check_model(tflite_file_name: str) -> None:
+ """Raise an exception if model in given file is Vela optimised."""
+ tflite_path = Path(tflite_file_name)
+
+ tflite_model = get_model_from_file(tflite_path)
+
+ if is_vela_optimised(tflite_model):
+ raise ModelOptimisedException(
+ f"TFLite model in {tflite_file_name} is already "
+ f"vela optimised ('ethos-u' custom op detected)."
+ )
+
+ print(
+ f"TFLite model in {tflite_file_name} is not vela optimised "
+ f"('ethos-u' custom op not detected)."
+ )
diff --git a/src/aiet/resources/tools/vela/run_vela.py b/src/aiet/resources/tools/vela/run_vela.py
new file mode 100644
index 0000000..2c1b0be
--- /dev/null
+++ b/src/aiet/resources/tools/vela/run_vela.py
@@ -0,0 +1,65 @@
+# SPDX-FileCopyrightText: Copyright 2022, Arm Limited and/or its affiliates.
+# SPDX-License-Identifier: Apache-2.0
+"""Wrapper to only run Vela when the input is not already optimised."""
+import shutil
+import subprocess
+from pathlib import Path
+from typing import Tuple
+
+import click
+
+from aiet.cli.common import ModelOptimisedException
+from aiet.resources.tools.vela.check_model import check_model
+
+
+def vela_output_model_path(input_model: str, output_dir: str) -> Path:
+ """Construct the path to the Vela output file."""
+ in_path = Path(input_model)
+ tflite_vela = Path(output_dir) / f"{in_path.stem}_vela{in_path.suffix}"
+ return tflite_vela
+
+
+def execute_vela(vela_args: Tuple, output_dir: Path, input_model: str) -> None:
+ """Execute vela as external call."""
+ cmd = ["vela"] + list(vela_args)
+ cmd += ["--output-dir", str(output_dir)] # Re-add parsed out_dir to arguments
+ cmd += [input_model]
+ subprocess.run(cmd, check=True)
+
+
+@click.command(context_settings=dict(ignore_unknown_options=True))
+@click.option(
+ "--input-model",
+ "-i",
+ type=click.Path(exists=True, file_okay=True, readable=True),
+ required=True,
+)
+@click.option("--output-model", "-o", type=click.Path(), required=True)
+# Collect the remaining arguments to be directly forwarded to Vela
+@click.argument("vela-args", nargs=-1, type=click.UNPROCESSED)
+def run_vela(input_model: str, output_model: str, vela_args: Tuple) -> None:
+ """Check input, run Vela (if needed) and copy optimised file to destination."""
+ output_dir = Path(output_model).parent
+ try:
+ check_model(input_model) # raises an exception if already Vela-optimised
+ execute_vela(vela_args, output_dir, input_model)
+ print("Vela optimisation complete.")
+ src_model = vela_output_model_path(input_model, str(output_dir))
+ except ModelOptimisedException as ex:
+ # Input already optimized: copy input file to destination path and return
+ print(f"Input already vela-optimised.\n{ex}")
+ src_model = Path(input_model)
+ except subprocess.CalledProcessError as ex:
+ print(ex)
+ raise SystemExit(ex.returncode) from ex
+
+ try:
+ shutil.copyfile(src_model, output_model)
+ except (shutil.SameFileError, OSError) as ex:
+ print(ex)
+ raise SystemExit(ex.errno) from ex
+
+
+def main() -> None:
+ """Entry point of check_model application."""
+ run_vela() # pylint: disable=no-value-for-parameter
diff --git a/src/aiet/resources/tools/vela/vela.ini b/src/aiet/resources/tools/vela/vela.ini
new file mode 100644
index 0000000..5996553
--- /dev/null
+++ b/src/aiet/resources/tools/vela/vela.ini
@@ -0,0 +1,53 @@
+; SPDX-FileCopyrightText: Copyright 2021-2022, Arm Limited and/or its affiliates.
+; SPDX-License-Identifier: Apache-2.0
+
+; -----------------------------------------------------------------------------
+; Vela configuration file
+
+; -----------------------------------------------------------------------------
+; System Configuration
+
+; Ethos-U55 High-End Embedded: SRAM (4 GB/s) and Flash (0.5 GB/s)
+[System_Config.Ethos_U55_High_End_Embedded]
+core_clock=500e6
+axi0_port=Sram
+axi1_port=OffChipFlash
+Sram_clock_scale=1.0
+Sram_burst_length=32
+Sram_read_latency=32
+Sram_write_latency=32
+OffChipFlash_clock_scale=0.125
+OffChipFlash_burst_length=128
+OffChipFlash_read_latency=64
+OffChipFlash_write_latency=64
+
+; Ethos-U65 High-End: SRAM (16 GB/s) and DRAM (3.75 GB/s)
+[System_Config.Ethos_U65_High_End]
+core_clock=1e9
+axi0_port=Sram
+axi1_port=Dram
+Sram_clock_scale=1.0
+Sram_burst_length=32
+Sram_read_latency=32
+Sram_write_latency=32
+Dram_clock_scale=0.234375
+Dram_burst_length=128
+Dram_read_latency=500
+Dram_write_latency=250
+
+; -----------------------------------------------------------------------------
+; Memory Mode
+
+; Shared SRAM: the SRAM is shared between the Ethos-U and the Cortex-M software
+; The non-SRAM memory is assumed to be read-only
+[Memory_Mode.U55_Shared_Sram]
+const_mem_area=Axi1
+arena_mem_area=Axi0
+cache_mem_area=Axi0
+arena_cache_size=4194304
+
+[Memory_Mode.U65_Shared_Sram]
+const_mem_area=Axi1
+arena_mem_area=Axi0
+cache_mem_area=Axi0
+arena_cache_size=2097152