aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Verhaard <louis.verhaard@arm.com>2020-11-18 13:35:06 +0100
committerLouis Verhaard <louis.verhaard@arm.com>2020-11-23 13:39:56 +0100
commit5207830e53d454793cebfffa96d366ded79d71da (patch)
treeb99da4124607c6d20ceef9605eccf89e150ba666
parentaeae56770f3c19182d32cc63fd32396e061a7648 (diff)
downloadethos-u-vela-5207830e53d454793cebfffa96d366ded79d71da.tar.gz
MLBEDSW-3425: Added external API for driver actions
Added external API to add driver actions to a command stream. Change-Id: Ie4779c1c745defc5769fa694358470cd6aea191c Signed-off-by: Louis Verhaard <louis.verhaard@arm.com>
-rw-r--r--ethosu/vela/api.py16
-rw-r--r--ethosu/vela/architecture_features.py17
-rw-r--r--ethosu/vela/driver_actions.py26
-rw-r--r--ethosu/vela/npu_serialisation.py14
-rw-r--r--ethosu/vela/register_command_stream_generator.py13
-rw-r--r--ethosu/vela/test/extapi/test_extapi_create_payload.py42
-rw-r--r--ethosu/vela/test/testutil.py12
-rw-r--r--ethosu/vela/vela.py7
8 files changed, 110 insertions, 37 deletions
diff --git a/ethosu/vela/api.py b/ethosu/vela/api.py
index f64a38f..22f81d0 100644
--- a/ethosu/vela/api.py
+++ b/ethosu/vela/api.py
@@ -453,3 +453,19 @@ def npu_generate_register_command_stream(npu_op_list: List[NpuOperation], accele
from . import register_command_stream_generator
return register_command_stream_generator.generate_register_command_stream(npu_op_list, accelerator)
+
+
+def npu_create_driver_payload(register_command_stream: List[int], accelerator: NpuAccelerator) -> bytes:
+ """
+ Public facing API for generating driver payload, containing a driver header
+ and the given Ethos-U register command stream.
+ Returns the payload, in little endian format, which must be placed in memory on a 16-byte aligned
+ address.
+
+ :param register_command_stream: List[int] register commands, as a list of 32-bit integers
+ :param accelerator: NpuAccelerator enum to pick the correct accelerator
+ :return driver payload, as a byte array
+ """
+ from . import driver_actions
+
+ return driver_actions.npu_create_driver_payload(register_command_stream, accelerator)
diff --git a/ethosu/vela/architecture_features.py b/ethosu/vela/architecture_features.py
index 18846cf..9f27b7e 100644
--- a/ethosu/vela/architecture_features.py
+++ b/ethosu/vela/architecture_features.py
@@ -605,7 +605,6 @@ class ArchitectureFeatures:
return mem_port_mapping[mem_port]
def _set_default_sys_config(self):
- print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for system configuration")
# ArchitectureFeatures.DEFAULT_CONFIG values
if self.is_ethos_u65_system:
# Default Ethos-U65 system configuration
@@ -625,7 +624,6 @@ class ArchitectureFeatures:
self.memory_clock_scales[MemArea.OffChipFlash] = 0.125 # 1 / 8
def _set_default_mem_mode(self):
- print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for memory mode")
# ArchitectureFeatures.DEFAULT_CONFIG values
if self.is_ethos_u65_system:
# Default Ethos-U65 memory mode
@@ -815,3 +813,18 @@ class ArchitectureFeatures:
result = self.vela_config.get(section, key)
return result
+
+
+def create_default_arch(accelerator: Accelerator) -> ArchitectureFeatures:
+ """Creates architecture features object using default settings"""
+ return ArchitectureFeatures(
+ vela_config_files=None,
+ accelerator_config=accelerator.value,
+ system_config=ArchitectureFeatures.DEFAULT_CONFIG,
+ memory_mode=ArchitectureFeatures.DEFAULT_CONFIG,
+ override_block_config=None,
+ block_config_limit=None,
+ max_blockdep=ArchitectureFeatures.MAX_BLOCKDEP,
+ weight_estimation_scaling=1.0,
+ verbose_config=False,
+ )
diff --git a/ethosu/vela/driver_actions.py b/ethosu/vela/driver_actions.py
index 29c2b18..86bed11 100644
--- a/ethosu/vela/driver_actions.py
+++ b/ethosu/vela/driver_actions.py
@@ -15,10 +15,15 @@
# limitations under the License.
# Description:
# Creates driver actions that are embedded in the custom operator payload.
+import struct
from typing import List
import numpy as np
+from .api import NpuAccelerator
+from .architecture_features import Accelerator
+from .architecture_features import ArchitectureFeatures
+from .architecture_features import create_default_arch
from .ethos_u55_regs.ethos_u55_regs import ARCH_VER
from .ethos_u55_regs.ethos_u55_regs import config_r
from .ethos_u55_regs.ethos_u55_regs import id_r
@@ -106,3 +111,24 @@ def emit_reg_read(data: List[int], reg_index: int, reg_count: int = 1):
def emit_dump_shram(data: List[int]):
assert data is not None
data.append(make_da_tag(DACommands.DumpSHRAM, 0, 0))
+
+
+def create_driver_payload(register_command_stream: List[int], arch: ArchitectureFeatures) -> bytes:
+ """Creates driver header and includes the given command
+ """
+ # Prepare driver actions for this command tensor
+ da_list = []
+ emit_fourcc(da_list, "COP1")
+ emit_config(da_list, 0, 1, arch)
+ emit_cmd_stream_header(da_list, len(register_command_stream))
+
+ # Append command stream words
+ da_list.extend(register_command_stream)
+ # Convert to bytes, in little endian format
+ return struct.pack("<{0}I".format(len(da_list)), *da_list)
+
+
+def npu_create_driver_payload(register_command_stream: List[int], accelerator: NpuAccelerator) -> bytes:
+ """Internal implementation of the public facing API to create driver payload"""
+ arch = create_default_arch(Accelerator.from_npu_accelerator(accelerator))
+ return create_driver_payload(register_command_stream, arch)
diff --git a/ethosu/vela/npu_serialisation.py b/ethosu/vela/npu_serialisation.py
index 04534cc..a11907b 100644
--- a/ethosu/vela/npu_serialisation.py
+++ b/ethosu/vela/npu_serialisation.py
@@ -15,8 +15,6 @@
# limitations under the License.
# Description:
# Serialises and packs an NPU subgraph into tensors.
-import struct
-
import numpy as np
from . import driver_actions
@@ -70,17 +68,7 @@ def serialise_npu_subgraph_into_tensors(nng, sg, arch, scratch_tens, scratch_fas
flash_size = sg.memory_used.get(flash_area, 0)
scratch_size = sg.memory_used.get(scratch_area, 0)
- # Prepare driver actions for this command tensor
- da_list = []
- driver_actions.emit_fourcc(da_list, "COP1")
- driver_actions.emit_config(da_list, 0, 1, arch)
- driver_actions.emit_cmd_stream_header(da_list, len(sg.register_command_stream))
-
- # Append command stream words
- da_list.extend(sg.register_command_stream)
-
- # Convert to bytes
- payload_bytes = struct.pack("<{0}I".format(len(da_list)), *da_list)
+ payload_bytes = driver_actions.create_driver_payload(sg.register_command_stream, arch)
command_stream_size_bytes = len(payload_bytes)
diff --git a/ethosu/vela/register_command_stream_generator.py b/ethosu/vela/register_command_stream_generator.py
index 04f7072..9d79d58 100644
--- a/ethosu/vela/register_command_stream_generator.py
+++ b/ethosu/vela/register_command_stream_generator.py
@@ -55,6 +55,7 @@ from .api import NpuTileBox
from .architecture_features import Accelerator
from .architecture_features import ArchitectureFeatures
from .architecture_features import Block
+from .architecture_features import create_default_arch
from .architecture_features import Rect
from .architecture_features import SharedBufferArea
from .architecture_features import SHRAMElements
@@ -1282,16 +1283,6 @@ def generate_register_command_stream(npu_op_list: List[NpuOperation], npu_accele
"""
accelerator = Accelerator.from_npu_accelerator(npu_accelerator)
emit = CommandStreamEmitter()
- arch = ArchitectureFeatures(
- vela_config_files=None,
- accelerator_config=accelerator.value,
- system_config=ArchitectureFeatures.DEFAULT_CONFIG,
- memory_mode=ArchitectureFeatures.DEFAULT_CONFIG,
- override_block_config=None,
- block_config_limit=None,
- max_blockdep=ArchitectureFeatures.MAX_BLOCKDEP,
- weight_estimation_scaling=1.0,
- verbose_config=False,
- )
+ arch = create_default_arch(accelerator)
generate_command_stream(emit, npu_op_list, arch)
return emit.to_list()
diff --git a/ethosu/vela/test/extapi/test_extapi_create_payload.py b/ethosu/vela/test/extapi/test_extapi_create_payload.py
new file mode 100644
index 0000000..06dd220
--- /dev/null
+++ b/ethosu/vela/test/extapi/test_extapi_create_payload.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2020 Arm Limited or its affiliates. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Description:
+# Contains unit tests for npu_create_driver_payload API for an external consumer
+import random
+
+import pytest
+
+from ethosu.vela.api import npu_create_driver_payload
+from ethosu.vela.api import NpuAccelerator
+
+
+@pytest.mark.parametrize("accelerator", list(NpuAccelerator))
+def test_create_driver_payload(accelerator: NpuAccelerator):
+ """Tests npu_create_driver_payload"""
+ # Generate a random command stream with defined beginning and end
+ random.seed(0)
+ num_commands = 793
+ register_command_stream = random.choices(range(1 << 32), k=num_commands)
+ register_command_stream[0] = 0xFEDCBA98
+ register_command_stream[-1] = 0xA0B1C2D3
+ payload = npu_create_driver_payload(register_command_stream, accelerator)
+ header_size = 32 # expected driver header size in bytes
+ assert len(payload) == header_size + 4 * num_commands
+ # Check that the first register command is located directly after the header
+ assert list(payload[header_size : header_size + 4]) == [0x98, 0xBA, 0xDC, 0xFE]
+ # Check that the last register command is present in the payload
+ assert list(payload[-4:]) == [0xD3, 0xC2, 0xB1, 0xA0]
diff --git a/ethosu/vela/test/testutil.py b/ethosu/vela/test/testutil.py
index 7cdd4f5..ee407b6 100644
--- a/ethosu/vela/test/testutil.py
+++ b/ethosu/vela/test/testutil.py
@@ -27,17 +27,7 @@ from ethosu.vela.tensor import Tensor
def create_arch():
- return architecture_features.ArchitectureFeatures(
- vela_config_files=None,
- accelerator_config=architecture_features.Accelerator.Ethos_U55_128.value,
- system_config=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
- memory_mode=architecture_features.ArchitectureFeatures.DEFAULT_CONFIG,
- override_block_config=None,
- block_config_limit=None,
- max_blockdep=0,
- weight_estimation_scaling=1.0,
- verbose_config=False,
- )
+ return architecture_features.create_default_arch(architecture_features.Accelerator.Ethos_U55_128)
def default_quant_params():
diff --git a/ethosu/vela/vela.py b/ethosu/vela/vela.py
index 6fc5c47..7b76685 100644
--- a/ethosu/vela/vela.py
+++ b/ethosu/vela/vela.py
@@ -41,6 +41,7 @@ from .tensor import MemArea
from .tensor import Tensor
from .tflite_mapping import builtin_operator_map
from .tflite_mapping import builtin_type_name
+from ethosu.vela.architecture_features import ArchitectureFeatures
def process(input_name, enable_debug_db, arch, model_reader_options, compiler_options, scheduler_options):
@@ -372,6 +373,12 @@ def main(args=None):
"".format(args.cpu_tensor_alignment)
)
+ if args.system_config == ArchitectureFeatures.DEFAULT_CONFIG:
+ print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for system configuration")
+
+ if args.memory_mode == ArchitectureFeatures.DEFAULT_CONFIG:
+ print(f"Warning: Using {ArchitectureFeatures.DEFAULT_CONFIG} values for memory mode")
+
arch = architecture_features.ArchitectureFeatures(
vela_config_files=args.config,
system_config=args.system_config,