From b5f7cfe253dfeadd83caf60fde34b5b66f356782 Mon Sep 17 00:00:00 2001 From: Kristofer Jonsson Date: Wed, 10 Mar 2021 17:13:52 +0100 Subject: Driver unit tests Add driver unit tests that runs simple command streams directly on top of the NPU driver. Change-Id: I3fcce2a2bfbd458d14186b8fd13ba47174f49562 --- applications/CMakeLists.txt | 6 +- applications/driver_unit_tests/CMakeLists.txt | 30 ++ applications/driver_unit_tests/command_stream.cpp | 179 ++++++++++ applications/driver_unit_tests/command_stream.hpp | 114 ++++++ applications/driver_unit_tests/conv.cpp | 402 ++++++++++++++++++++++ applications/driver_unit_tests/irq.cpp | 72 ++++ targets/corstone-300/platform.ld | 55 +-- targets/corstone-300/platform.scatter | 55 ++- 8 files changed, 883 insertions(+), 30 deletions(-) create mode 100644 applications/driver_unit_tests/CMakeLists.txt create mode 100644 applications/driver_unit_tests/command_stream.cpp create mode 100644 applications/driver_unit_tests/command_stream.hpp create mode 100644 applications/driver_unit_tests/conv.cpp create mode 100644 applications/driver_unit_tests/irq.cpp diff --git a/applications/CMakeLists.txt b/applications/CMakeLists.txt index 291643f..154b599 100644 --- a/applications/CMakeLists.txt +++ b/applications/CMakeLists.txt @@ -16,12 +16,14 @@ # limitations under the License. # +add_subdirectory(baremetal) + +add_subdirectory(driver_unit_tests) + add_subdirectory(freertos) add_subdirectory(hello_world) -add_subdirectory(baremetal) - if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") # Only armclang supported for now add_subdirectory(trustzone_inference) diff --git a/applications/driver_unit_tests/CMakeLists.txt b/applications/driver_unit_tests/CMakeLists.txt new file mode 100644 index 0000000..b679358 --- /dev/null +++ b/applications/driver_unit_tests/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Copyright (c) 2021 Arm Limited. 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. +# + +add_library(driver_unit INTERFACE) + +target_sources(driver_unit INTERFACE + command_stream.cpp) + +ethosu_add_executable_test(driver_unit_irq PRIVATE + SOURCES irq.cpp + LIBRARIES driver_unit) + +ethosu_add_executable_test(driver_unit_conv PRIVATE + SOURCES conv.cpp + LIBRARIES driver_unit) diff --git a/applications/driver_unit_tests/command_stream.cpp b/applications/driver_unit_tests/command_stream.cpp new file mode 100644 index 0000000..07f7f22 --- /dev/null +++ b/applications/driver_unit_tests/command_stream.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Arm Limited. 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. + */ + +/**************************************************************************** + * Includes + ****************************************************************************/ + +#include "command_stream.hpp" + +#include +#include + +using namespace std; + +namespace EthosU { +namespace CommandStream { + +/**************************************************************************** + * DataPointer + ****************************************************************************/ + +DataPointer::DataPointer() : data(nullptr), size(0) {} + +DataPointer::DataPointer(const char *_data, size_t _size) : data(_data), size(_size) {} + +bool DataPointer::operator!=(const DataPointer &other) { + if (size != other.size) { + return true; + } + + for (size_t i = 0; i < size; i++) { + if (data[i] != other.data[i]) { + return true; + } + } + + return false; +} + +/**************************************************************************** + * PmuConfig + ****************************************************************************/ + +Pmu::Pmu(ethosu_driver *_drv, const PmuEvents &_config) : + drv(_drv), + config(_config) +{ + // Enable PMU block + ETHOSU_PMU_Enable_v2(drv); + + // Enable cycle counter + ETHOSU_PMU_CNTR_Enable_v2(drv, ETHOSU_PMU_CCNT_Msk); + + // Configure event types + for (size_t i = 0; i < config.size(); i++) { + ETHOSU_PMU_Set_EVTYPER_v2(drv, i, config[i]); + ETHOSU_PMU_CNTR_Enable_v2(drv, 1 << i); + } +} + +void Pmu::clear() { + ETHOSU_PMU_CYCCNT_Reset_v2(drv); + ETHOSU_PMU_EVCNTR_ALL_Reset_v2(drv); +} + +void Pmu::print() { + printf("PMU={cycleCount=%llu, events=[%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 "]}\n", + ETHOSU_PMU_Get_CCNTR_v2(drv), + ETHOSU_PMU_Get_EVCNTR_v2(drv, 0), + ETHOSU_PMU_Get_EVCNTR_v2(drv, 1), + ETHOSU_PMU_Get_EVCNTR_v2(drv, 2), + ETHOSU_PMU_Get_EVCNTR_v2(drv, 3)); +} + +uint64_t Pmu::getCycleCount() const { + return ETHOSU_PMU_Get_CCNTR_v2(drv); +} + +uint32_t Pmu::getEventCount(size_t index) const { + return ETHOSU_PMU_Get_EVCNTR_v2(drv, index); +} + +/**************************************************************************** + * CommandStream + ****************************************************************************/ + +CommandStream::CommandStream(const DataPointer &_commandStream, + const BasePointers &_basePointers, + const PmuEvents &_pmuEvents) : + drv(ethosu_reserve_driver()), + commandStream(_commandStream), + basePointers(_basePointers), + pmu(drv, _pmuEvents) +{ + // Disable clock gating, else the NPU PMU will be clock gated and report too few cycles + ethosu_set_clock_and_power(&drv->dev, ETHOSU_CLOCK_Q_DISABLE, ETHOSU_POWER_Q_DISABLE); + + // Use simplified driver setup + ethosu_set_power_mode_v2(drv, true); +} + +CommandStream::~CommandStream() { + ethosu_set_power_mode_v2(drv, false); + ethosu_release_driver(drv); +} + +int CommandStream::run(size_t repeat) { + // Base pointer array + uint64_t baseAddress[ETHOSU_DRIVER_BASEP_INDEXES]; + size_t baseAddressSize[ETHOSU_DRIVER_BASEP_INDEXES]; + for (size_t i = 0; i < ETHOSU_DRIVER_BASEP_INDEXES; i++) { + baseAddress[i] = reinterpret_cast(basePointers[i].data); + baseAddressSize[i] = reinterpret_cast(basePointers[i].size); + } + + while (repeat-- > 0) { + int error = ethosu_invoke_v3(drv, commandStream.data, commandStream.size, baseAddress, baseAddressSize, ETHOSU_DRIVER_BASEP_INDEXES); + + if (error != 0) { + printf("Inference failed. error=%d\n", error); + return 1; + } + + // Wait for interrupt + while (true) { + uint16_t status; + ethosu_get_status_mask(&drv->dev, &status); + + // Return if NPU raise error status + if (status & 0xcc) { + printf("Job failed with error. status=0x%08x\n", status); + return 1; + } + + // Break loop if job is no longer running + if ((status & 1) == 0) { + break; + } + + // Sleep waiting on interrupt + __WFI(); + } + } + + return 0; +} + +DataPointer &CommandStream::getCommandStream() +{ + return commandStream; +} + +BasePointers &CommandStream::getBasePointers() +{ + return basePointers; +} + +Pmu &CommandStream::getPmu() +{ + return pmu; +} + +}; // namespace CommandStream +}; // namespace EthosU diff --git a/applications/driver_unit_tests/command_stream.hpp b/applications/driver_unit_tests/command_stream.hpp new file mode 100644 index 0000000..ec55d5e --- /dev/null +++ b/applications/driver_unit_tests/command_stream.hpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021 Arm Limited. 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. + */ + +#ifndef COMMAND_STREAM_HPP +#define COMMAND_STREAM_HPP + +/**************************************************************************** + * Includes + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Types + ****************************************************************************/ + +namespace EthosU { +namespace CommandStream { + +/**************************************************************************** + * DataPointer + ****************************************************************************/ + +struct DataPointer { + DataPointer(); + DataPointer(const char *_data, size_t _size); + + bool operator!=(const DataPointer &other); + + const char *data; + size_t size; +}; + +/**************************************************************************** + * Pmu + ****************************************************************************/ + +using PmuEvents = std::array; + +class Pmu { +public: + Pmu(ethosu_driver *_drv, const PmuEvents &_config = {}); + + void clear(); + void print(); + + uint64_t getCycleCount() const; + uint32_t getEventCount(size_t index) const; + +private: + ethosu_driver *drv; + PmuEvents config; +}; + +/**************************************************************************** + * CommandStream + ****************************************************************************/ + +using BasePointers = std::array; + +class CommandStream { +public: + CommandStream(const DataPointer &_commandStream, + const BasePointers &_pointers = {}, + const PmuEvents &_pmuEvents = {}); + virtual ~CommandStream(); + + int run(size_t repeat = 1); + + DataPointer &getCommandStream(); + BasePointers &getBasePointers(); + Pmu &getPmu(); + +private: + ethosu_driver *drv; + DataPointer commandStream; + BasePointers basePointers; + Pmu pmu; +}; + +#define DRIVER_ACTION_MAGIC() \ + 'C', 'O', 'P', '1', + +#define DRIVER_ACTION_COMMAND_STREAM(length) \ + 0x02, (length >> 16) & 0xff, length & 0xff, (length >> 8) & 0xff, + +#define DRIVER_ACTION_NOP() \ + 0x05, 0x00, 0x00, 0x00, + +#define NPU_OP_STOP(mask) \ + (mask >> 8) && 0xff, mask & 0xff, 0x08, 0x00, + +}; // namespace CommandStream +}; // namespace EthosU + +#endif /* COMMAND_STREAM_HPP */ diff --git a/applications/driver_unit_tests/conv.cpp b/applications/driver_unit_tests/conv.cpp new file mode 100644 index 0000000..2385908 --- /dev/null +++ b/applications/driver_unit_tests/conv.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2021 Arm Limited. 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. + */ + +/**************************************************************************** + * Includes + ****************************************************************************/ + +#include "command_stream.hpp" + +#include + +using namespace std; +using namespace EthosU::CommandStream; + +/**************************************************************************** + * Data + ****************************************************************************/ + +__attribute__((section(".sram.data"), aligned(16))) char commandStream[] = { + DRIVER_ACTION_MAGIC() + DRIVER_ACTION_NOP() + DRIVER_ACTION_NOP() + DRIVER_ACTION_COMMAND_STREAM(84) + + 0x30, 0x01, 0x00, 0x00, // cmd0.NPU_SET_DMA0_SRC_REGION 0 - + 0x30, 0x40, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, // cmd1.NPU_SET_DMA0_SRC 0 0x00000030 (48) + 0x31, 0x01, 0x01, 0x00, // cmd0.NPU_SET_DMA0_DST_REGION 1 - + 0x31, 0x40, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, // cmd1.NPU_SET_DMA0_DST 0 0x00000480 (1152) + 0x32, 0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, // cmd1.NPU_SET_DMA0_LEN 0 0x00000050 (80) + 0x10, 0x00, 0x00, 0x00, // cmd0.NPU_OP_DMA_START 0 - + 0x0f, 0x01, 0x01, 0x00, // cmd0.NPU_SET_IFM_REGION 1 - + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_BASE0 0 0x00000000 (0) + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_BASE1 0 0x00000000 (0) + 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_BASE2 0 0x00000000 (0) + 0x03, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_BASE3 0 0x00000000 (0) + 0x0b, 0x01, 0x07, 0x00, // cmd0.NPU_SET_IFM_HEIGHT0_M1 7 - + 0x0c, 0x01, 0x07, 0x00, // cmd0.NPU_SET_IFM_HEIGHT1_M1 7 - + 0x0a, 0x01, 0x07, 0x00, // cmd0.NPU_SET_IFM_WIDTH0_M1 7 - + 0x04, 0x01, 0x0f, 0x00, // cmd0.NPU_SET_IFM_DEPTH_M1 15 - + 0x06, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_STRIDE_C 0 0x00000001 (1) + 0x05, 0x40, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_STRIDE_Y 0 0x00000080 (128) + 0x04, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // cmd1.NPU_SET_IFM_STRIDE_X 0 0x00000010 (16) + 0x09, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_ZERO_POINT 0 - + 0x05, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_PRECISION 0 - + 0x07, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_UPSCALE 0 - + 0x00, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_PAD_TOP 0 - + 0x01, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_PAD_LEFT 0 - + 0x03, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_PAD_BOTTOM 0 - + 0x02, 0x01, 0x00, 0x00, // cmd0.NPU_SET_IFM_PAD_RIGHT 0 - + 0x1f, 0x01, 0x01, 0x00, // cmd0.NPU_SET_OFM_REGION 1 - + 0x10, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // cmd1.NPU_SET_OFM_BASE0 0 0x00000400 (1024) + 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_BASE1 0 0x00000000 (0) + 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_BASE2 0 0x00000000 (0) + 0x13, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_BASE3 0 0x00000000 (0) + 0x1b, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_HEIGHT0_M1 7 - + 0x1c, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_HEIGHT1_M1 7 - + 0x1a, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_WIDTH0_M1 7 - + 0x12, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_HEIGHT_M1 7 - + 0x11, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_WIDTH_M1 7 - + 0x13, 0x01, 0x01, 0x00, // cmd0.NPU_SET_OFM_DEPTH_M1 1 - + 0x16, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_STRIDE_C 0 0x00000001 (1) + 0x15, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_STRIDE_Y 0 0x00000010 (16) + 0x14, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // cmd1.NPU_SET_OFM_STRIDE_X 0 0x00000002 (2) + 0x18, 0x01, 0x00, 0x00, // cmd0.NPU_SET_OFM_ZERO_POINT 0 - + 0x14, 0x01, 0x00, 0x00, // cmd0.NPU_SET_OFM_PRECISION 0 - + 0x21, 0x01, 0x00, 0x00, // cmd0.NPU_SET_KERNEL_HEIGHT_M1 0 - + 0x20, 0x01, 0x00, 0x00, // cmd0.NPU_SET_KERNEL_WIDTH_M1 0 - + 0x22, 0x01, 0x00, 0x00, // cmd0.NPU_SET_KERNEL_STRIDE 0 - + 0x28, 0x01, 0x01, 0x00, // cmd0.NPU_SET_WEIGHT_REGION 1 - + 0x20, 0x40, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, // cmd1.NPU_SET_WEIGHT_BASE 0 0x00000480 (1152) + 0x21, 0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, // cmd1.NPU_SET_WEIGHT_LENGTH 0 0x00000050 (80) + 0x29, 0x01, 0x00, 0x00, // cmd0.NPU_SET_SCALE_REGION 0 - + 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cmd1.NPU_SET_SCALE_BASE 0 0x00000000 (0) + 0x23, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // cmd1.NPU_SET_SCALE_LENGTH 0 0x00000020 (32) + 0x25, 0x01, 0x00, 0x00, // cmd0.NPU_SET_ACTIVATION 0 - + 0x26, 0x01, 0x00, 0x00, // cmd0.NPU_SET_ACTIVATION_MIN 0 - + 0x27, 0x01, 0xff, 0x00, // cmd0.NPU_SET_ACTIVATION_MAX 255 - + 0x16, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_BLK_HEIGHT_M1 7 - + 0x15, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_BLK_WIDTH_M1 7 - + 0x17, 0x01, 0x07, 0x00, // cmd0.NPU_SET_OFM_BLK_DEPTH_M1 7 - + 0x0d, 0x01, 0x06, 0x00, // cmd0.NPU_SET_IFM_IB_END 10 - + 0x2d, 0x01, 0x0e, 0x00, // cmd0.NPU_SET_AB_START 30 - + 0x24, 0x01, 0x00, 0x00, // cmd0.NPU_SET_ACC_FORMAT 0 - + 0x2f, 0x01, 0x00, 0x00, // cmd0.NPU_SET_BLOCKDEP 0 - + 0x11, 0x00, 0x00, 0x00, // cmd0.NPU_OP_DMA_WAIT 0 - + 0x02, 0x00, 0x00, 0x00, // cmd0.NPU_OP_CONV 0 - + 0x00, 0x00, 0xff, 0xff, // cmd0.NPU_OP_STOP 65535 - +}; + +__attribute__((section(".sram.data"), aligned(16))) char weightsBiases0[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa4, 0x7b, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0xa4, 0x7b, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x5c, 0xe6, 0x4d, 0xf9, 0xef, 0x6f, 0xcf, 0x5e, 0x2e, 0xbe, 0x0d, 0xbd, 0x4c, 0xfc, + 0x0b, 0xeb, 0xa9, 0x29, 0xd9, 0x27, 0xe7, 0xa4, 0xf4, 0x63, 0xf3, 0x92, 0x42, 0x32, 0xa2, 0x81, + 0x51, 0x01, 0xc1, 0x00, 0x00, 0xf0, 0xaf, 0xeb, 0xcd, 0xc3, 0xe1, 0x12, 0xb7, 0x44, 0xff, 0x4f, + 0xbb, 0x39, 0x01, 0x08, 0x9e, 0x96, 0x87, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x4c, 0x35, 0x30, + 0x89, 0x1d, 0x00, 0xe0, 0xfc, 0xff, 0xbf, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +__attribute__((section(".sram.data"), aligned(16))) char scratch[] = { + 0xac, 0x0a, 0x7f, 0x8c, 0x2f, 0xaa, 0xc4, 0x97, 0x75, 0xa6, 0x16, 0xb7, 0xc0, 0xcc, 0x21, 0xd8, + 0x43, 0xb3, 0x4e, 0x9a, 0xfb, 0x52, 0xa2, 0xdb, 0xc3, 0x76, 0x7d, 0x8b, 0x67, 0x7d, 0xe5, 0xd8, + 0x09, 0xa4, 0x74, 0x6c, 0xd3, 0xde, 0xa1, 0x9f, 0x15, 0x51, 0x59, 0xa5, 0xf2, 0xd6, 0x66, 0x62, + 0x24, 0xb7, 0x05, 0x70, 0x57, 0x3a, 0x2b, 0x4c, 0x46, 0x3c, 0x4b, 0xe4, 0xd8, 0xbd, 0x84, 0x0e, + 0x58, 0x9a, 0xb2, 0xf6, 0x8c, 0xcd, 0xcc, 0x45, 0x3a, 0x39, 0x29, 0x62, 0xc1, 0x42, 0x48, 0x7a, + 0xe6, 0x7d, 0xae, 0xca, 0x27, 0x4a, 0xea, 0xcf, 0x57, 0xa8, 0x65, 0x87, 0xae, 0xc8, 0xdf, 0x7a, + 0x58, 0x5e, 0x6b, 0x91, 0x51, 0x8b, 0x8d, 0x64, 0xa5, 0xe6, 0xf3, 0xec, 0x19, 0x42, 0x09, 0xd6, + 0x4d, 0x6b, 0x2f, 0x12, 0x48, 0x98, 0x5f, 0x56, 0x09, 0x1b, 0x4e, 0x16, 0x94, 0x97, 0xee, 0xa5, + 0x73, 0x08, 0x2d, 0x05, 0xd0, 0x13, 0x45, 0x5e, 0xf3, 0x92, 0x26, 0xd5, 0xc5, 0x1e, 0x08, 0xf5, + 0xfe, 0x47, 0x35, 0xc7, 0x4f, 0x07, 0xee, 0x23, 0xaf, 0x1d, 0xb9, 0xde, 0xc0, 0x09, 0xbe, 0xde, + 0x52, 0xbb, 0x86, 0xfa, 0x63, 0x60, 0x3e, 0x79, 0xd8, 0xa7, 0x95, 0xcc, 0xb1, 0x7c, 0x08, 0xcd, + 0xf3, 0x82, 0x23, 0x76, 0x1d, 0x03, 0x3e, 0x85, 0x93, 0xc2, 0xd0, 0xc7, 0x93, 0x0c, 0xcb, 0xad, + 0x8e, 0x3b, 0x47, 0x1e, 0xa7, 0x61, 0x7b, 0xb8, 0x20, 0xdd, 0xd1, 0xa3, 0xc1, 0x3f, 0xff, 0x94, + 0x09, 0xcd, 0xb2, 0x24, 0xb9, 0x4a, 0x91, 0x89, 0x7f, 0xd2, 0xd5, 0xf1, 0x20, 0xa2, 0x34, 0xc2, + 0x1f, 0xda, 0x97, 0x85, 0xca, 0xc2, 0x1c, 0x1b, 0xf4, 0x48, 0x27, 0x6a, 0x97, 0xe0, 0x3d, 0x79, + 0xa3, 0xea, 0xb9, 0x43, 0xfe, 0x79, 0xb3, 0x2f, 0xcb, 0x2d, 0x34, 0xc6, 0x72, 0xab, 0xa6, 0xbc, + 0xb7, 0x44, 0xc6, 0x74, 0x1c, 0xd8, 0x6f, 0x37, 0x22, 0xe3, 0x84, 0x91, 0x80, 0xa8, 0x9d, 0x22, + 0x80, 0x68, 0xcf, 0x04, 0xa4, 0xe7, 0xfa, 0x52, 0x35, 0x5c, 0x1d, 0x9e, 0x85, 0x17, 0x51, 0x26, + 0x26, 0x4e, 0xb2, 0x9c, 0xe8, 0x0d, 0xea, 0x38, 0xf4, 0x62, 0xef, 0x9d, 0x11, 0xf1, 0xf0, 0x62, + 0x4f, 0x79, 0x99, 0xf1, 0x84, 0xb1, 0x10, 0xe7, 0x69, 0xc6, 0x8b, 0xae, 0x2a, 0xec, 0x2f, 0x73, + 0xba, 0xb5, 0x08, 0x5c, 0x1f, 0xba, 0xf1, 0x9c, 0x78, 0x53, 0xe1, 0x6f, 0x01, 0x51, 0x00, 0xe7, + 0x41, 0xf5, 0x97, 0xb2, 0xe7, 0x6f, 0x6a, 0x19, 0xa9, 0xef, 0x6a, 0x0f, 0x39, 0x68, 0x45, 0xf8, + 0x23, 0x39, 0xb1, 0xaa, 0x66, 0x2f, 0x34, 0xa7, 0x77, 0xec, 0xae, 0xab, 0x0b, 0xbb, 0xc0, 0x2b, + 0xae, 0xa1, 0xdb, 0x35, 0x52, 0xdc, 0xaf, 0x5b, 0x5b, 0x50, 0x01, 0x21, 0x80, 0xf7, 0x2c, 0xc0, + 0x8e, 0xe9, 0xbf, 0x50, 0x63, 0xca, 0x9a, 0x9b, 0x35, 0x26, 0x1c, 0x5d, 0x8c, 0x4b, 0x36, 0x53, + 0x79, 0x6a, 0xf8, 0x91, 0xaa, 0x3f, 0xd6, 0x09, 0x54, 0x30, 0x48, 0x70, 0xcb, 0xc8, 0x5f, 0xa2, + 0x44, 0x11, 0x06, 0xfd, 0x06, 0xb3, 0x7d, 0xf5, 0xc4, 0x9b, 0x1f, 0x1a, 0x2f, 0x44, 0x1d, 0xa7, + 0x7f, 0xf2, 0x78, 0x35, 0xf4, 0x37, 0x93, 0xa2, 0x83, 0x94, 0x4b, 0x29, 0xcc, 0xf3, 0xcb, 0xfe, + 0x64, 0x1b, 0x32, 0xa7, 0xb4, 0x24, 0xf4, 0x94, 0xe8, 0xb7, 0xd7, 0x40, 0x4e, 0x0f, 0x14, 0x6a, + 0x8f, 0x24, 0x60, 0x77, 0x94, 0xc6, 0x85, 0x79, 0xe3, 0xac, 0x92, 0x3e, 0xba, 0x5b, 0x9e, 0x9f, + 0x17, 0x3b, 0xb2, 0x28, 0xcf, 0xaa, 0x87, 0x56, 0x8d, 0x8b, 0x41, 0x1c, 0x75, 0x91, 0xbc, 0xac, + 0x55, 0x37, 0x05, 0xa8, 0x30, 0x22, 0x34, 0x51, 0x31, 0xf5, 0x5f, 0x23, 0x45, 0xa6, 0x41, 0xc7, + 0xa9, 0x38, 0x53, 0x32, 0xa3, 0x16, 0x17, 0xf3, 0xc0, 0xc5, 0x64, 0x5e, 0x5f, 0x5c, 0x9b, 0xa9, + 0xc5, 0x9c, 0x2c, 0xd2, 0x5e, 0x6e, 0x79, 0x03, 0x00, 0xa1, 0xdb, 0x18, 0x71, 0xd7, 0x72, 0x9f, + 0xb2, 0x8e, 0x83, 0xd6, 0x24, 0xf5, 0x74, 0xac, 0xa2, 0xe7, 0x99, 0x18, 0x30, 0x63, 0xd1, 0xf8, + 0x5d, 0x3f, 0xf9, 0xf9, 0x83, 0x49, 0xd1, 0xe0, 0x62, 0x86, 0xf9, 0x77, 0x2a, 0xbe, 0x76, 0x82, + 0xcd, 0x03, 0x0d, 0xfa, 0x70, 0x51, 0x43, 0x0e, 0xe7, 0x27, 0xd7, 0x9a, 0x95, 0x2b, 0x7f, 0x73, + 0xc9, 0x60, 0x40, 0xbd, 0x7f, 0xe9, 0x1d, 0x05, 0x00, 0x36, 0x08, 0x0a, 0x8a, 0xf7, 0x13, 0x71, + 0x72, 0x09, 0x66, 0x48, 0x2b, 0x32, 0xc6, 0xfa, 0xba, 0x33, 0xc5, 0x1e, 0x7f, 0x8d, 0x04, 0x5c, + 0x17, 0xd8, 0xcf, 0x4b, 0xbb, 0xd6, 0x1b, 0x7b, 0x82, 0xf0, 0x64, 0x1e, 0x79, 0x19, 0x4c, 0xb0, + 0x62, 0x58, 0x67, 0x51, 0x3e, 0xde, 0x66, 0xe1, 0xa3, 0x23, 0x0d, 0x6a, 0xde, 0x7a, 0x11, 0xeb, + 0x7b, 0xf8, 0x6b, 0x10, 0xc3, 0xa7, 0x81, 0x37, 0x52, 0xda, 0x45, 0xb1, 0xae, 0x37, 0xb0, 0x90, + 0xe3, 0xca, 0x0c, 0x91, 0x94, 0x5c, 0x77, 0xdd, 0xd1, 0x90, 0xf0, 0x43, 0x32, 0xca, 0x4b, 0x82, + 0x9b, 0x95, 0xf3, 0x85, 0x0e, 0x5b, 0xae, 0xea, 0x29, 0x7c, 0x0c, 0x18, 0x3a, 0xfc, 0xd0, 0xeb, + 0xc1, 0x3a, 0x71, 0x93, 0x24, 0xdc, 0x46, 0x15, 0x0a, 0x5b, 0xe6, 0xed, 0x56, 0x90, 0x18, 0x47, + 0x2b, 0xbc, 0x8d, 0x51, 0x68, 0x33, 0x65, 0x02, 0x0b, 0x68, 0xdb, 0xaa, 0x02, 0xbb, 0xa3, 0xd7, + 0x33, 0x81, 0xbd, 0x21, 0x50, 0x34, 0xad, 0xa5, 0x20, 0x38, 0x61, 0xb7, 0xb6, 0x14, 0x65, 0xd7, + 0x80, 0x84, 0x16, 0x4a, 0x26, 0x5b, 0xc5, 0x43, 0x13, 0xa1, 0xe5, 0x2e, 0xae, 0x94, 0xd7, 0x65, + 0x2a, 0xb6, 0x25, 0x96, 0x73, 0xb5, 0x85, 0x8d, 0xb8, 0xc4, 0x25, 0x05, 0xbc, 0x89, 0x39, 0x2a, + 0xe8, 0x69, 0x35, 0xd4, 0x4d, 0xbe, 0xab, 0x5e, 0x1e, 0xb9, 0x33, 0x01, 0x18, 0x35, 0x7d, 0x25, + 0x7d, 0x62, 0x85, 0xad, 0x02, 0x83, 0xd2, 0x91, 0x03, 0x3e, 0x1f, 0x45, 0x5e, 0x20, 0x28, 0xb4, + 0xe2, 0xac, 0x35, 0xbc, 0x6b, 0x97, 0xd9, 0x49, 0x0d, 0xfd, 0x51, 0xf6, 0x70, 0xf7, 0xeb, 0x6e, + 0x28, 0x49, 0xae, 0x3f, 0x48, 0x35, 0x90, 0xc1, 0x13, 0x0c, 0x7f, 0x93, 0x5f, 0xb2, 0x66, 0x65, + 0x48, 0x0f, 0x90, 0x97, 0x9a, 0xc5, 0x62, 0xe5, 0xc2, 0x19, 0x7f, 0x92, 0xf8, 0x54, 0x90, 0xa3, + 0xb4, 0xe0, 0x1b, 0x39, 0x43, 0xe9, 0x3c, 0xe4, 0xec, 0x5b, 0xe7, 0xf3, 0x3d, 0x1f, 0x18, 0xae, + 0x0e, 0xcf, 0x76, 0x72, 0x60, 0x9f, 0xfe, 0x72, 0x04, 0x3d, 0xae, 0xd8, 0xc3, 0x9f, 0x83, 0xfa, + 0xed, 0x12, 0x11, 0xb3, 0x8b, 0x68, 0xbf, 0x1d, 0xfc, 0xd3, 0x24, 0x4c, 0x56, 0xaa, 0x5b, 0xc4, + 0xcd, 0x0d, 0x55, 0xd0, 0x79, 0x0b, 0x6d, 0x69, 0x6d, 0x66, 0x81, 0x65, 0x4b, 0x93, 0xe9, 0xac, + 0xb8, 0xfa, 0x8f, 0xe1, 0x10, 0xa6, 0xf2, 0x3f, 0x98, 0x4c, 0xce, 0x94, 0x9d, 0x13, 0x2f, 0x50, + 0x95, 0x68, 0xb9, 0xe1, 0x6e, 0x84, 0x25, 0xf7, 0x19, 0xc0, 0x49, 0xb1, 0xd0, 0xa5, 0xa5, 0x96, + 0xbc, 0x43, 0xaa, 0xb9, 0x79, 0x07, 0xe0, 0xa8, 0x76, 0xcb, 0x56, 0x80, 0x75, 0x34, 0x80, 0x88, + 0xbd, 0xe5, 0xc1, 0xf4, 0x53, 0x36, 0x04, 0x3b, 0xa1, 0x8a, 0xdc, 0xa4, 0x68, 0x27, 0x16, 0x65, + 0xa0, 0xc3, 0x81, 0x6c, 0xe4, 0x3c, 0x6a, 0x9e, 0xfb, 0x95, 0x3c, 0x9b, 0xfb, 0xea, 0x90, 0x79, + 0x79, 0xd8, 0xe9, 0x04, 0x46, 0x95, 0x5a, 0x78, 0xd5, 0x01, 0x34, 0x4d, 0x1f, 0xa9, 0x50, 0xb7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +__attribute__((section(".sram.data"), aligned(16))) char fastScratch[] = { + 0xac, 0x0a, 0x7f, 0x8c, 0x2f, 0xaa, 0xc4, 0x97, 0x75, 0xa6, 0x16, 0xb7, 0xc0, 0xcc, 0x21, 0xd8, + 0x43, 0xb3, 0x4e, 0x9a, 0xfb, 0x52, 0xa2, 0xdb, 0xc3, 0x76, 0x7d, 0x8b, 0x67, 0x7d, 0xe5, 0xd8, + 0x09, 0xa4, 0x74, 0x6c, 0xd3, 0xde, 0xa1, 0x9f, 0x15, 0x51, 0x59, 0xa5, 0xf2, 0xd6, 0x66, 0x62, + 0x24, 0xb7, 0x05, 0x70, 0x57, 0x3a, 0x2b, 0x4c, 0x46, 0x3c, 0x4b, 0xe4, 0xd8, 0xbd, 0x84, 0x0e, + 0x58, 0x9a, 0xb2, 0xf6, 0x8c, 0xcd, 0xcc, 0x45, 0x3a, 0x39, 0x29, 0x62, 0xc1, 0x42, 0x48, 0x7a, + 0xe6, 0x7d, 0xae, 0xca, 0x27, 0x4a, 0xea, 0xcf, 0x57, 0xa8, 0x65, 0x87, 0xae, 0xc8, 0xdf, 0x7a, + 0x58, 0x5e, 0x6b, 0x91, 0x51, 0x8b, 0x8d, 0x64, 0xa5, 0xe6, 0xf3, 0xec, 0x19, 0x42, 0x09, 0xd6, + 0x4d, 0x6b, 0x2f, 0x12, 0x48, 0x98, 0x5f, 0x56, 0x09, 0x1b, 0x4e, 0x16, 0x94, 0x97, 0xee, 0xa5, + 0x73, 0x08, 0x2d, 0x05, 0xd0, 0x13, 0x45, 0x5e, 0xf3, 0x92, 0x26, 0xd5, 0xc5, 0x1e, 0x08, 0xf5, + 0xfe, 0x47, 0x35, 0xc7, 0x4f, 0x07, 0xee, 0x23, 0xaf, 0x1d, 0xb9, 0xde, 0xc0, 0x09, 0xbe, 0xde, + 0x52, 0xbb, 0x86, 0xfa, 0x63, 0x60, 0x3e, 0x79, 0xd8, 0xa7, 0x95, 0xcc, 0xb1, 0x7c, 0x08, 0xcd, + 0xf3, 0x82, 0x23, 0x76, 0x1d, 0x03, 0x3e, 0x85, 0x93, 0xc2, 0xd0, 0xc7, 0x93, 0x0c, 0xcb, 0xad, + 0x8e, 0x3b, 0x47, 0x1e, 0xa7, 0x61, 0x7b, 0xb8, 0x20, 0xdd, 0xd1, 0xa3, 0xc1, 0x3f, 0xff, 0x94, + 0x09, 0xcd, 0xb2, 0x24, 0xb9, 0x4a, 0x91, 0x89, 0x7f, 0xd2, 0xd5, 0xf1, 0x20, 0xa2, 0x34, 0xc2, + 0x1f, 0xda, 0x97, 0x85, 0xca, 0xc2, 0x1c, 0x1b, 0xf4, 0x48, 0x27, 0x6a, 0x97, 0xe0, 0x3d, 0x79, + 0xa3, 0xea, 0xb9, 0x43, 0xfe, 0x79, 0xb3, 0x2f, 0xcb, 0x2d, 0x34, 0xc6, 0x72, 0xab, 0xa6, 0xbc, + 0xb7, 0x44, 0xc6, 0x74, 0x1c, 0xd8, 0x6f, 0x37, 0x22, 0xe3, 0x84, 0x91, 0x80, 0xa8, 0x9d, 0x22, + 0x80, 0x68, 0xcf, 0x04, 0xa4, 0xe7, 0xfa, 0x52, 0x35, 0x5c, 0x1d, 0x9e, 0x85, 0x17, 0x51, 0x26, + 0x26, 0x4e, 0xb2, 0x9c, 0xe8, 0x0d, 0xea, 0x38, 0xf4, 0x62, 0xef, 0x9d, 0x11, 0xf1, 0xf0, 0x62, + 0x4f, 0x79, 0x99, 0xf1, 0x84, 0xb1, 0x10, 0xe7, 0x69, 0xc6, 0x8b, 0xae, 0x2a, 0xec, 0x2f, 0x73, + 0xba, 0xb5, 0x08, 0x5c, 0x1f, 0xba, 0xf1, 0x9c, 0x78, 0x53, 0xe1, 0x6f, 0x01, 0x51, 0x00, 0xe7, + 0x41, 0xf5, 0x97, 0xb2, 0xe7, 0x6f, 0x6a, 0x19, 0xa9, 0xef, 0x6a, 0x0f, 0x39, 0x68, 0x45, 0xf8, + 0x23, 0x39, 0xb1, 0xaa, 0x66, 0x2f, 0x34, 0xa7, 0x77, 0xec, 0xae, 0xab, 0x0b, 0xbb, 0xc0, 0x2b, + 0xae, 0xa1, 0xdb, 0x35, 0x52, 0xdc, 0xaf, 0x5b, 0x5b, 0x50, 0x01, 0x21, 0x80, 0xf7, 0x2c, 0xc0, + 0x8e, 0xe9, 0xbf, 0x50, 0x63, 0xca, 0x9a, 0x9b, 0x35, 0x26, 0x1c, 0x5d, 0x8c, 0x4b, 0x36, 0x53, + 0x79, 0x6a, 0xf8, 0x91, 0xaa, 0x3f, 0xd6, 0x09, 0x54, 0x30, 0x48, 0x70, 0xcb, 0xc8, 0x5f, 0xa2, + 0x44, 0x11, 0x06, 0xfd, 0x06, 0xb3, 0x7d, 0xf5, 0xc4, 0x9b, 0x1f, 0x1a, 0x2f, 0x44, 0x1d, 0xa7, + 0x7f, 0xf2, 0x78, 0x35, 0xf4, 0x37, 0x93, 0xa2, 0x83, 0x94, 0x4b, 0x29, 0xcc, 0xf3, 0xcb, 0xfe, + 0x64, 0x1b, 0x32, 0xa7, 0xb4, 0x24, 0xf4, 0x94, 0xe8, 0xb7, 0xd7, 0x40, 0x4e, 0x0f, 0x14, 0x6a, + 0x8f, 0x24, 0x60, 0x77, 0x94, 0xc6, 0x85, 0x79, 0xe3, 0xac, 0x92, 0x3e, 0xba, 0x5b, 0x9e, 0x9f, + 0x17, 0x3b, 0xb2, 0x28, 0xcf, 0xaa, 0x87, 0x56, 0x8d, 0x8b, 0x41, 0x1c, 0x75, 0x91, 0xbc, 0xac, + 0x55, 0x37, 0x05, 0xa8, 0x30, 0x22, 0x34, 0x51, 0x31, 0xf5, 0x5f, 0x23, 0x45, 0xa6, 0x41, 0xc7, + 0xa9, 0x38, 0x53, 0x32, 0xa3, 0x16, 0x17, 0xf3, 0xc0, 0xc5, 0x64, 0x5e, 0x5f, 0x5c, 0x9b, 0xa9, + 0xc5, 0x9c, 0x2c, 0xd2, 0x5e, 0x6e, 0x79, 0x03, 0x00, 0xa1, 0xdb, 0x18, 0x71, 0xd7, 0x72, 0x9f, + 0xb2, 0x8e, 0x83, 0xd6, 0x24, 0xf5, 0x74, 0xac, 0xa2, 0xe7, 0x99, 0x18, 0x30, 0x63, 0xd1, 0xf8, + 0x5d, 0x3f, 0xf9, 0xf9, 0x83, 0x49, 0xd1, 0xe0, 0x62, 0x86, 0xf9, 0x77, 0x2a, 0xbe, 0x76, 0x82, + 0xcd, 0x03, 0x0d, 0xfa, 0x70, 0x51, 0x43, 0x0e, 0xe7, 0x27, 0xd7, 0x9a, 0x95, 0x2b, 0x7f, 0x73, + 0xc9, 0x60, 0x40, 0xbd, 0x7f, 0xe9, 0x1d, 0x05, 0x00, 0x36, 0x08, 0x0a, 0x8a, 0xf7, 0x13, 0x71, + 0x72, 0x09, 0x66, 0x48, 0x2b, 0x32, 0xc6, 0xfa, 0xba, 0x33, 0xc5, 0x1e, 0x7f, 0x8d, 0x04, 0x5c, + 0x17, 0xd8, 0xcf, 0x4b, 0xbb, 0xd6, 0x1b, 0x7b, 0x82, 0xf0, 0x64, 0x1e, 0x79, 0x19, 0x4c, 0xb0, + 0x62, 0x58, 0x67, 0x51, 0x3e, 0xde, 0x66, 0xe1, 0xa3, 0x23, 0x0d, 0x6a, 0xde, 0x7a, 0x11, 0xeb, + 0x7b, 0xf8, 0x6b, 0x10, 0xc3, 0xa7, 0x81, 0x37, 0x52, 0xda, 0x45, 0xb1, 0xae, 0x37, 0xb0, 0x90, + 0xe3, 0xca, 0x0c, 0x91, 0x94, 0x5c, 0x77, 0xdd, 0xd1, 0x90, 0xf0, 0x43, 0x32, 0xca, 0x4b, 0x82, + 0x9b, 0x95, 0xf3, 0x85, 0x0e, 0x5b, 0xae, 0xea, 0x29, 0x7c, 0x0c, 0x18, 0x3a, 0xfc, 0xd0, 0xeb, + 0xc1, 0x3a, 0x71, 0x93, 0x24, 0xdc, 0x46, 0x15, 0x0a, 0x5b, 0xe6, 0xed, 0x56, 0x90, 0x18, 0x47, + 0x2b, 0xbc, 0x8d, 0x51, 0x68, 0x33, 0x65, 0x02, 0x0b, 0x68, 0xdb, 0xaa, 0x02, 0xbb, 0xa3, 0xd7, + 0x33, 0x81, 0xbd, 0x21, 0x50, 0x34, 0xad, 0xa5, 0x20, 0x38, 0x61, 0xb7, 0xb6, 0x14, 0x65, 0xd7, + 0x80, 0x84, 0x16, 0x4a, 0x26, 0x5b, 0xc5, 0x43, 0x13, 0xa1, 0xe5, 0x2e, 0xae, 0x94, 0xd7, 0x65, + 0x2a, 0xb6, 0x25, 0x96, 0x73, 0xb5, 0x85, 0x8d, 0xb8, 0xc4, 0x25, 0x05, 0xbc, 0x89, 0x39, 0x2a, + 0xe8, 0x69, 0x35, 0xd4, 0x4d, 0xbe, 0xab, 0x5e, 0x1e, 0xb9, 0x33, 0x01, 0x18, 0x35, 0x7d, 0x25, + 0x7d, 0x62, 0x85, 0xad, 0x02, 0x83, 0xd2, 0x91, 0x03, 0x3e, 0x1f, 0x45, 0x5e, 0x20, 0x28, 0xb4, + 0xe2, 0xac, 0x35, 0xbc, 0x6b, 0x97, 0xd9, 0x49, 0x0d, 0xfd, 0x51, 0xf6, 0x70, 0xf7, 0xeb, 0x6e, + 0x28, 0x49, 0xae, 0x3f, 0x48, 0x35, 0x90, 0xc1, 0x13, 0x0c, 0x7f, 0x93, 0x5f, 0xb2, 0x66, 0x65, + 0x48, 0x0f, 0x90, 0x97, 0x9a, 0xc5, 0x62, 0xe5, 0xc2, 0x19, 0x7f, 0x92, 0xf8, 0x54, 0x90, 0xa3, + 0xb4, 0xe0, 0x1b, 0x39, 0x43, 0xe9, 0x3c, 0xe4, 0xec, 0x5b, 0xe7, 0xf3, 0x3d, 0x1f, 0x18, 0xae, + 0x0e, 0xcf, 0x76, 0x72, 0x60, 0x9f, 0xfe, 0x72, 0x04, 0x3d, 0xae, 0xd8, 0xc3, 0x9f, 0x83, 0xfa, + 0xed, 0x12, 0x11, 0xb3, 0x8b, 0x68, 0xbf, 0x1d, 0xfc, 0xd3, 0x24, 0x4c, 0x56, 0xaa, 0x5b, 0xc4, + 0xcd, 0x0d, 0x55, 0xd0, 0x79, 0x0b, 0x6d, 0x69, 0x6d, 0x66, 0x81, 0x65, 0x4b, 0x93, 0xe9, 0xac, + 0xb8, 0xfa, 0x8f, 0xe1, 0x10, 0xa6, 0xf2, 0x3f, 0x98, 0x4c, 0xce, 0x94, 0x9d, 0x13, 0x2f, 0x50, + 0x95, 0x68, 0xb9, 0xe1, 0x6e, 0x84, 0x25, 0xf7, 0x19, 0xc0, 0x49, 0xb1, 0xd0, 0xa5, 0xa5, 0x96, + 0xbc, 0x43, 0xaa, 0xb9, 0x79, 0x07, 0xe0, 0xa8, 0x76, 0xcb, 0x56, 0x80, 0x75, 0x34, 0x80, 0x88, + 0xbd, 0xe5, 0xc1, 0xf4, 0x53, 0x36, 0x04, 0x3b, 0xa1, 0x8a, 0xdc, 0xa4, 0x68, 0x27, 0x16, 0x65, + 0xa0, 0xc3, 0x81, 0x6c, 0xe4, 0x3c, 0x6a, 0x9e, 0xfb, 0x95, 0x3c, 0x9b, 0xfb, 0xea, 0x90, 0x79, + 0x79, 0xd8, 0xe9, 0x04, 0x46, 0x95, 0x5a, 0x78, 0xd5, 0x01, 0x34, 0x4d, 0x1f, 0xa9, 0x50, 0xb7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +char input0[] = { + 0xac, 0x0a, 0x7f, 0x8c, 0x2f, 0xaa, 0xc4, 0x97, 0x75, 0xa6, 0x16, 0xb7, 0xc0, 0xcc, 0x21, 0xd8, + 0x43, 0xb3, 0x4e, 0x9a, 0xfb, 0x52, 0xa2, 0xdb, 0xc3, 0x76, 0x7d, 0x8b, 0x67, 0x7d, 0xe5, 0xd8, + 0x09, 0xa4, 0x74, 0x6c, 0xd3, 0xde, 0xa1, 0x9f, 0x15, 0x51, 0x59, 0xa5, 0xf2, 0xd6, 0x66, 0x62, + 0x24, 0xb7, 0x05, 0x70, 0x57, 0x3a, 0x2b, 0x4c, 0x46, 0x3c, 0x4b, 0xe4, 0xd8, 0xbd, 0x84, 0x0e, + 0x58, 0x9a, 0xb2, 0xf6, 0x8c, 0xcd, 0xcc, 0x45, 0x3a, 0x39, 0x29, 0x62, 0xc1, 0x42, 0x48, 0x7a, + 0xe6, 0x7d, 0xae, 0xca, 0x27, 0x4a, 0xea, 0xcf, 0x57, 0xa8, 0x65, 0x87, 0xae, 0xc8, 0xdf, 0x7a, + 0x58, 0x5e, 0x6b, 0x91, 0x51, 0x8b, 0x8d, 0x64, 0xa5, 0xe6, 0xf3, 0xec, 0x19, 0x42, 0x09, 0xd6, + 0x4d, 0x6b, 0x2f, 0x12, 0x48, 0x98, 0x5f, 0x56, 0x09, 0x1b, 0x4e, 0x16, 0x94, 0x97, 0xee, 0xa5, + 0x73, 0x08, 0x2d, 0x05, 0xd0, 0x13, 0x45, 0x5e, 0xf3, 0x92, 0x26, 0xd5, 0xc5, 0x1e, 0x08, 0xf5, + 0xfe, 0x47, 0x35, 0xc7, 0x4f, 0x07, 0xee, 0x23, 0xaf, 0x1d, 0xb9, 0xde, 0xc0, 0x09, 0xbe, 0xde, + 0x52, 0xbb, 0x86, 0xfa, 0x63, 0x60, 0x3e, 0x79, 0xd8, 0xa7, 0x95, 0xcc, 0xb1, 0x7c, 0x08, 0xcd, + 0xf3, 0x82, 0x23, 0x76, 0x1d, 0x03, 0x3e, 0x85, 0x93, 0xc2, 0xd0, 0xc7, 0x93, 0x0c, 0xcb, 0xad, + 0x8e, 0x3b, 0x47, 0x1e, 0xa7, 0x61, 0x7b, 0xb8, 0x20, 0xdd, 0xd1, 0xa3, 0xc1, 0x3f, 0xff, 0x94, + 0x09, 0xcd, 0xb2, 0x24, 0xb9, 0x4a, 0x91, 0x89, 0x7f, 0xd2, 0xd5, 0xf1, 0x20, 0xa2, 0x34, 0xc2, + 0x1f, 0xda, 0x97, 0x85, 0xca, 0xc2, 0x1c, 0x1b, 0xf4, 0x48, 0x27, 0x6a, 0x97, 0xe0, 0x3d, 0x79, + 0xa3, 0xea, 0xb9, 0x43, 0xfe, 0x79, 0xb3, 0x2f, 0xcb, 0x2d, 0x34, 0xc6, 0x72, 0xab, 0xa6, 0xbc, + 0xb7, 0x44, 0xc6, 0x74, 0x1c, 0xd8, 0x6f, 0x37, 0x22, 0xe3, 0x84, 0x91, 0x80, 0xa8, 0x9d, 0x22, + 0x80, 0x68, 0xcf, 0x04, 0xa4, 0xe7, 0xfa, 0x52, 0x35, 0x5c, 0x1d, 0x9e, 0x85, 0x17, 0x51, 0x26, + 0x26, 0x4e, 0xb2, 0x9c, 0xe8, 0x0d, 0xea, 0x38, 0xf4, 0x62, 0xef, 0x9d, 0x11, 0xf1, 0xf0, 0x62, + 0x4f, 0x79, 0x99, 0xf1, 0x84, 0xb1, 0x10, 0xe7, 0x69, 0xc6, 0x8b, 0xae, 0x2a, 0xec, 0x2f, 0x73, + 0xba, 0xb5, 0x08, 0x5c, 0x1f, 0xba, 0xf1, 0x9c, 0x78, 0x53, 0xe1, 0x6f, 0x01, 0x51, 0x00, 0xe7, + 0x41, 0xf5, 0x97, 0xb2, 0xe7, 0x6f, 0x6a, 0x19, 0xa9, 0xef, 0x6a, 0x0f, 0x39, 0x68, 0x45, 0xf8, + 0x23, 0x39, 0xb1, 0xaa, 0x66, 0x2f, 0x34, 0xa7, 0x77, 0xec, 0xae, 0xab, 0x0b, 0xbb, 0xc0, 0x2b, + 0xae, 0xa1, 0xdb, 0x35, 0x52, 0xdc, 0xaf, 0x5b, 0x5b, 0x50, 0x01, 0x21, 0x80, 0xf7, 0x2c, 0xc0, + 0x8e, 0xe9, 0xbf, 0x50, 0x63, 0xca, 0x9a, 0x9b, 0x35, 0x26, 0x1c, 0x5d, 0x8c, 0x4b, 0x36, 0x53, + 0x79, 0x6a, 0xf8, 0x91, 0xaa, 0x3f, 0xd6, 0x09, 0x54, 0x30, 0x48, 0x70, 0xcb, 0xc8, 0x5f, 0xa2, + 0x44, 0x11, 0x06, 0xfd, 0x06, 0xb3, 0x7d, 0xf5, 0xc4, 0x9b, 0x1f, 0x1a, 0x2f, 0x44, 0x1d, 0xa7, + 0x7f, 0xf2, 0x78, 0x35, 0xf4, 0x37, 0x93, 0xa2, 0x83, 0x94, 0x4b, 0x29, 0xcc, 0xf3, 0xcb, 0xfe, + 0x64, 0x1b, 0x32, 0xa7, 0xb4, 0x24, 0xf4, 0x94, 0xe8, 0xb7, 0xd7, 0x40, 0x4e, 0x0f, 0x14, 0x6a, + 0x8f, 0x24, 0x60, 0x77, 0x94, 0xc6, 0x85, 0x79, 0xe3, 0xac, 0x92, 0x3e, 0xba, 0x5b, 0x9e, 0x9f, + 0x17, 0x3b, 0xb2, 0x28, 0xcf, 0xaa, 0x87, 0x56, 0x8d, 0x8b, 0x41, 0x1c, 0x75, 0x91, 0xbc, 0xac, + 0x55, 0x37, 0x05, 0xa8, 0x30, 0x22, 0x34, 0x51, 0x31, 0xf5, 0x5f, 0x23, 0x45, 0xa6, 0x41, 0xc7, + 0xa9, 0x38, 0x53, 0x32, 0xa3, 0x16, 0x17, 0xf3, 0xc0, 0xc5, 0x64, 0x5e, 0x5f, 0x5c, 0x9b, 0xa9, + 0xc5, 0x9c, 0x2c, 0xd2, 0x5e, 0x6e, 0x79, 0x03, 0x00, 0xa1, 0xdb, 0x18, 0x71, 0xd7, 0x72, 0x9f, + 0xb2, 0x8e, 0x83, 0xd6, 0x24, 0xf5, 0x74, 0xac, 0xa2, 0xe7, 0x99, 0x18, 0x30, 0x63, 0xd1, 0xf8, + 0x5d, 0x3f, 0xf9, 0xf9, 0x83, 0x49, 0xd1, 0xe0, 0x62, 0x86, 0xf9, 0x77, 0x2a, 0xbe, 0x76, 0x82, + 0xcd, 0x03, 0x0d, 0xfa, 0x70, 0x51, 0x43, 0x0e, 0xe7, 0x27, 0xd7, 0x9a, 0x95, 0x2b, 0x7f, 0x73, + 0xc9, 0x60, 0x40, 0xbd, 0x7f, 0xe9, 0x1d, 0x05, 0x00, 0x36, 0x08, 0x0a, 0x8a, 0xf7, 0x13, 0x71, + 0x72, 0x09, 0x66, 0x48, 0x2b, 0x32, 0xc6, 0xfa, 0xba, 0x33, 0xc5, 0x1e, 0x7f, 0x8d, 0x04, 0x5c, + 0x17, 0xd8, 0xcf, 0x4b, 0xbb, 0xd6, 0x1b, 0x7b, 0x82, 0xf0, 0x64, 0x1e, 0x79, 0x19, 0x4c, 0xb0, + 0x62, 0x58, 0x67, 0x51, 0x3e, 0xde, 0x66, 0xe1, 0xa3, 0x23, 0x0d, 0x6a, 0xde, 0x7a, 0x11, 0xeb, + 0x7b, 0xf8, 0x6b, 0x10, 0xc3, 0xa7, 0x81, 0x37, 0x52, 0xda, 0x45, 0xb1, 0xae, 0x37, 0xb0, 0x90, + 0xe3, 0xca, 0x0c, 0x91, 0x94, 0x5c, 0x77, 0xdd, 0xd1, 0x90, 0xf0, 0x43, 0x32, 0xca, 0x4b, 0x82, + 0x9b, 0x95, 0xf3, 0x85, 0x0e, 0x5b, 0xae, 0xea, 0x29, 0x7c, 0x0c, 0x18, 0x3a, 0xfc, 0xd0, 0xeb, + 0xc1, 0x3a, 0x71, 0x93, 0x24, 0xdc, 0x46, 0x15, 0x0a, 0x5b, 0xe6, 0xed, 0x56, 0x90, 0x18, 0x47, + 0x2b, 0xbc, 0x8d, 0x51, 0x68, 0x33, 0x65, 0x02, 0x0b, 0x68, 0xdb, 0xaa, 0x02, 0xbb, 0xa3, 0xd7, + 0x33, 0x81, 0xbd, 0x21, 0x50, 0x34, 0xad, 0xa5, 0x20, 0x38, 0x61, 0xb7, 0xb6, 0x14, 0x65, 0xd7, + 0x80, 0x84, 0x16, 0x4a, 0x26, 0x5b, 0xc5, 0x43, 0x13, 0xa1, 0xe5, 0x2e, 0xae, 0x94, 0xd7, 0x65, + 0x2a, 0xb6, 0x25, 0x96, 0x73, 0xb5, 0x85, 0x8d, 0xb8, 0xc4, 0x25, 0x05, 0xbc, 0x89, 0x39, 0x2a, + 0xe8, 0x69, 0x35, 0xd4, 0x4d, 0xbe, 0xab, 0x5e, 0x1e, 0xb9, 0x33, 0x01, 0x18, 0x35, 0x7d, 0x25, + 0x7d, 0x62, 0x85, 0xad, 0x02, 0x83, 0xd2, 0x91, 0x03, 0x3e, 0x1f, 0x45, 0x5e, 0x20, 0x28, 0xb4, + 0xe2, 0xac, 0x35, 0xbc, 0x6b, 0x97, 0xd9, 0x49, 0x0d, 0xfd, 0x51, 0xf6, 0x70, 0xf7, 0xeb, 0x6e, + 0x28, 0x49, 0xae, 0x3f, 0x48, 0x35, 0x90, 0xc1, 0x13, 0x0c, 0x7f, 0x93, 0x5f, 0xb2, 0x66, 0x65, + 0x48, 0x0f, 0x90, 0x97, 0x9a, 0xc5, 0x62, 0xe5, 0xc2, 0x19, 0x7f, 0x92, 0xf8, 0x54, 0x90, 0xa3, + 0xb4, 0xe0, 0x1b, 0x39, 0x43, 0xe9, 0x3c, 0xe4, 0xec, 0x5b, 0xe7, 0xf3, 0x3d, 0x1f, 0x18, 0xae, + 0x0e, 0xcf, 0x76, 0x72, 0x60, 0x9f, 0xfe, 0x72, 0x04, 0x3d, 0xae, 0xd8, 0xc3, 0x9f, 0x83, 0xfa, + 0xed, 0x12, 0x11, 0xb3, 0x8b, 0x68, 0xbf, 0x1d, 0xfc, 0xd3, 0x24, 0x4c, 0x56, 0xaa, 0x5b, 0xc4, + 0xcd, 0x0d, 0x55, 0xd0, 0x79, 0x0b, 0x6d, 0x69, 0x6d, 0x66, 0x81, 0x65, 0x4b, 0x93, 0xe9, 0xac, + 0xb8, 0xfa, 0x8f, 0xe1, 0x10, 0xa6, 0xf2, 0x3f, 0x98, 0x4c, 0xce, 0x94, 0x9d, 0x13, 0x2f, 0x50, + 0x95, 0x68, 0xb9, 0xe1, 0x6e, 0x84, 0x25, 0xf7, 0x19, 0xc0, 0x49, 0xb1, 0xd0, 0xa5, 0xa5, 0x96, + 0xbc, 0x43, 0xaa, 0xb9, 0x79, 0x07, 0xe0, 0xa8, 0x76, 0xcb, 0x56, 0x80, 0x75, 0x34, 0x80, 0x88, + 0xbd, 0xe5, 0xc1, 0xf4, 0x53, 0x36, 0x04, 0x3b, 0xa1, 0x8a, 0xdc, 0xa4, 0x68, 0x27, 0x16, 0x65, + 0xa0, 0xc3, 0x81, 0x6c, 0xe4, 0x3c, 0x6a, 0x9e, 0xfb, 0x95, 0x3c, 0x9b, 0xfb, 0xea, 0x90, 0x79, + 0x79, 0xd8, 0xe9, 0x04, 0x46, 0x95, 0x5a, 0x78, 0xd5, 0x01, 0x34, 0x4d, 0x1f, 0xa9, 0x50, 0xb7 +}; + +char expected0[] = { + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x65, 0xff, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x70, 0xff, 0x50, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x59, 0xff, 0x88, 0xff, 0x00, 0xff, 0x00, 0xff, 0x31, 0xff, 0x7c, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x2a, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x00, 0xff, 0xab, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x73, 0xff, + 0x00, 0xff, 0x9d, 0xff, 0x00, 0xff, 0x00, 0xff, 0xbe, 0xff, 0xa5, 0xff, 0x00, 0xff, 0x5f, 0xff, + 0x00, 0xff, 0xbd, 0xff, 0x00, 0xff, 0x3f, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xff, 0x17, 0xff, 0x00, 0xff, 0x00, 0xff, 0x1f, 0xff, 0x00, 0xff, 0x00, 0xff +}; + +/**************************************************************************** + * Functions + ****************************************************************************/ + +int main() { + CommandStream cs( + DataPointer(commandStream, sizeof(commandStream)), + BasePointers({ + DataPointer(weightsBiases0, sizeof(weightsBiases0)), + DataPointer(scratch, sizeof(scratch)), + DataPointer(fastScratch, sizeof(fastScratch)) + }), + PmuEvents({ + ETHOSU_PMU_CYCLE, + ETHOSU_PMU_NPU_IDLE, + ETHOSU_PMU_NPU_ACTIVE + }) + ); + + const size_t repeat = 100; + + // Input data located inside the scratch buffer + DataPointer inputPointer(scratch, sizeof(input0)); + + // Output data located inside the scratch buffer + DataPointer outputPointer(scratch + 1024, sizeof(expected0)); + + // Expected output data + DataPointer expectedPointer(expected0, sizeof(expected0)); + + // Clear PMU + cs.getPmu().clear(); + + // Run inference + int ret = cs.run(repeat); + uint64_t cycleCount = cs.getPmu().getCycleCount(); + + // Print PMU counters + cs.getPmu().print(); + printf("cycleCount=%llu, cycleCountPerJob=%llu\n", cycleCount, cycleCount / repeat); + + // Compare outut with expected data + if (outputPointer != expectedPointer) { + printf("Output mismatch\n"); + return 1; + } + + return ret; +} diff --git a/applications/driver_unit_tests/irq.cpp b/applications/driver_unit_tests/irq.cpp new file mode 100644 index 0000000..e4b030a --- /dev/null +++ b/applications/driver_unit_tests/irq.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Arm Limited. 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. + */ + +/**************************************************************************** + * Includes + ****************************************************************************/ + +#include "command_stream.hpp" + +#include + +using namespace std; +using namespace EthosU::CommandStream; + +/**************************************************************************** + * Data + ****************************************************************************/ + +__attribute__((section(".sram.data"), aligned(16))) char commandStream[] = { + DRIVER_ACTION_MAGIC() + DRIVER_ACTION_NOP() + DRIVER_ACTION_NOP() + DRIVER_ACTION_COMMAND_STREAM(1) + + NPU_OP_STOP(0) +}; + +/**************************************************************************** + * Functions + ****************************************************************************/ + +int main() { + CommandStream cs( + DataPointer(commandStream, sizeof(commandStream)), + BasePointers(), + PmuEvents({ + ETHOSU_PMU_CYCLE, + ETHOSU_PMU_NPU_IDLE, + ETHOSU_PMU_NPU_ACTIVE + }) + ); + + const size_t repeat = 1000; + + // Clear PMU + cs.getPmu().clear(); + + // Run inference + int ret = cs.run(repeat); + uint64_t cycleCount = cs.getPmu().getCycleCount(); + + // Print PMU counters + cs.getPmu().print(); + printf("cycleCount=%llu, cycleCountPerJob=%llu\n", cycleCount, cycleCount / repeat); + + return ret; +} diff --git a/targets/corstone-300/platform.ld b/targets/corstone-300/platform.ld index a1cdb0e..091a117 100644 --- a/targets/corstone-300/platform.ld +++ b/targets/corstone-300/platform.ld @@ -56,6 +56,15 @@ __SRAM_SIZE = 0x00200000; __STACK_SIZE = 0x00008000; __HEAP_SIZE = 0x00008000; +/*--------------------- Embedded RAM Configuration ---------------------------- + BRAM Configuration + BRAM Base Address <0x0-0xFFFFFFFF:8> + BRAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__BRAM_BASE = 0x11000000; +__BRAM_SIZE = 0x00200000; + /*--------------------- Embedded RAM Configuration ---------------------------- DDR Configuration DDR Base Address <0x0-0xFFFFFFFF:8> @@ -74,6 +83,7 @@ MEMORY ITCM (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE DTCM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE SRAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + BRAM (rwx) : ORIGIN = __BRAM_BASE, LENGTH = __BRAM_SIZE DDR (rwx) : ORIGIN = __DDR_BASE, LENGTH = __DDR_SIZE } @@ -141,7 +151,7 @@ SECTIONS /* * SG veneers: * All SG veneers are placed in the special output section .gnu.sgstubs. Its start address - * must be set, either with the command line option �--section-start� or in a linker script, + * must be set, either with the command line option '--section-start' or in a linker script, * to indicate where to place these veneers in memory. */ /* @@ -169,6 +179,7 @@ SECTIONS LONG (__etext) LONG (__data_start__) LONG (__data_end__ - __data_start__) + /* Add each additional data section here */ __copy_table_end__ = .; } > ITCM @@ -212,7 +223,6 @@ SECTIONS KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); @@ -249,28 +259,34 @@ SECTIONS } > RAM2 */ -#ifndef ETHOSU_FAST_MEMORY_SIZE - .sram : - { - . = ALIGN(16); - *(.bss.tensor_arena) - . = ALIGN(16); - } > SRAM AT > SRAM -#else .sram : { . = ALIGN(16); +#ifdef ETHOSU_FAST_MEMORY_SIZE *(.bss.ethosu_scratch); +#else + *(.bss.tensor_arena) +#endif + . = ALIGN(16); - } > SRAM AT > SRAM + *(.sram.data) + } > BRAM AT > BRAM - .bss.tensor_arena : + .ddr : { . = ALIGN(16); +#ifdef ETHOSU_FAST_MEMORY_SIZE *(.bss.tensor_arena) +#endif . = ALIGN(16); + *(input_data_sec) + + . = ALIGN(16); + *(network_model_sec) + + . = ALIGN (16); + *(expected_output_data_sec) } > DDR AT > DDR -#endif .bss : { @@ -283,7 +299,6 @@ SECTIONS __bss_end__ = .; } > DTCM AT > DTCM - /* * Secondary bss section, optional * @@ -303,18 +318,6 @@ SECTIONS } > RAM2 AT > RAM2 */ - .ddr : - { - /* __attribute__((aligned(16))) is not handled by the cmsis startup code. - * Force the alignement here as a workaround */ - . = ALIGN(4); - *(input_data_sec) - . = ALIGN(16); - *(network_model_sec) - *(expected_output_data_sec) - . = ALIGN (16); - } > DDR - .heap (COPY) : { . = ALIGN(8); diff --git a/targets/corstone-300/platform.scatter b/targets/corstone-300/platform.scatter index dc8f57b..fe63d01 100644 --- a/targets/corstone-300/platform.scatter +++ b/targets/corstone-300/platform.scatter @@ -18,6 +18,55 @@ * limitations under the License. */ +/* + * This is a simplified picture of the Corstone-300 memory system. + * Please refer to the Corstone SSE-300 Technical Reference Manual for + * further information. + * + * https://developer.arm.com/ip-products/subsystem/corstone/corstone-300 + * + * +---------------+ +---------------+ +------+ + * | Ethos-U55 | | Cortex-M55 +--+ ITCM | + * | | | | +------+ + * | | | | + * | | | | +------+ + * | M1 M0 | | +--+ DTCM | + * +---+-------+---+ +-------+-------+ +------+ + * | | | + * | +---+---------------+-----+ + * | | AMBA AXI NIC-400-Lite | + * | +---+-----------------+---+ + * | | | + * +---+-------+------------+ +--+-------+ + * | AMBA AXI NIC-400 | | SSE-300 | + * +---+--------+--------+--+ | SRAM | + * | | | +----------+ + * +---+---+ +--+---+ +--+--+ + * | Flash | | BRAM | | DDR | + * +-------+ +------+ +-----+ + * + * +-----------------------+-------------+-------------+----+--------------------------------------+ + * | Memory region name | Base addr | Size |IDAU| MCC load address + remarks | + * +-----------------------+-------------+-------------+----+--------------------------------------+ + * | ITCM | 0x0000_0000 | 0x0008_0000 | NS | 0x0000_0000; 512 kiB | + * | ITCM | 0x1000_0000 | 0x0008_0000 | S | Secure alias for NS ITCM | + * | FPGA Data SRAM; BRAM | 0x0100_0000 | 0x0020_0000 | NS | 0x0100_0000; 2 MiB | + * | FPGA data SRAM; BRAM | 0x1100_0000 | 0x0020_0000 | S | Secure alias for NS BRAM | + * | DTCM | 0x2000_0000 | 0x0008_0000 | NS | 512 kiB; 4 banks of 128k each | + * | DTCM | 0x3000_0000 | 0x0008_0000 | S | Secure alias for NS DTCM | + * | SSE-300 internal SRAM | 0x2100_0000 | 0x0040_0000 | NS | 2 banks of 2 MiB each; 3cc latency) | + * | SSE-300 internal SRAM | 0x3100_0000 | 0x0040_0000 | S | Secure alias for NS internal SRAM | + * | DDR | 0x6000_0000 | 0x1000_0000 | NS | 0x0800_0000; 256 MiB bank | + * | DDR | 0x7000_0000 | 0x1000_0000 | S | 0x0C00_0000; 256 MiB bank | + * +-----------------------+-------------+-------------+----+--------------------------------------+ + * + * Note: Ethos-U55 can access BRAM, internal SRAM and the DDR sections => activation buffers and + * the model should only be placed in those regions. + * + * Note: Alias regions means that secure and non-secure addresses are mapped to the same physical + * memory banks. + */ + #ifndef STACK_SIZE #define STACK_SIZE 0x8000 #endif @@ -85,8 +134,9 @@ APP_IMAGE LR_START LR_SIZE #if defined(USE_TRUSTZONE) && defined(TRUSTZONE_SECURE) ; MPS3 BRAM ; Shared between Cortex-M and the NPU - BRAM BRAM_START UNINIT (BRAM_SIZE - TZ_NSC_SIZE) + BRAM BRAM_START (BRAM_SIZE - TZ_NSC_SIZE) { + * (.sram.data) } ROM_NSC TZ_NSC_START TZ_NSC_SIZE @@ -95,8 +145,9 @@ APP_IMAGE LR_START LR_SIZE } #else ; MPS3 BRAM - BRAM BRAM_START UNINIT BRAM_SIZE + BRAM BRAM_START BRAM_SIZE { + * (.sram.data) } #endif -- cgit v1.2.1