From f80de7f17c15e0296809ad9fd235e1cd30d6265f Mon Sep 17 00:00:00 2001 From: francovaro Date: Mon, 5 Aug 2024 16:40:22 +0200 Subject: [PATCH] SDK release v1.55.4 --- EdgeImpulse.EI-SDK.pdsc | 19 +- EdgeImpulse.pidx | 4 +- .../classifier/ei_model_types.h | 16 + .../classifier/ei_run_classifier.h | 2 + .../edge-impulse-sdk/classifier/ei_run_dsp.h | 8 + .../inferencing_engines/ethos_linux.h | 264 +++++++ .../edge-impulse-sdk/dsp/returntypes.h | 2 + .../porting/clib/debug_log.cpp | 32 + .../porting/clib/ei_classifier_porting.cpp | 82 ++ .../LICENSE-GPL-2.0.txt | 339 ++++++++ .../ethos-u-driver-stack-imx/LICENSE.txt | 201 +++++ .../Linux-syscall-note | 24 + .../ethos-u-driver-stack-imx/README.md | 23 + .../porting/ethos-u-driver-stack-imx/SCR.txt | 39 + .../ethos-u-driver-stack-imx/SECURITY.md | 85 ++ .../driver_library/include/ethosu.hpp | 368 +++++++++ .../driver_library/src/ethosu.cpp | 732 ++++++++++++++++++ .../kernel_driver/include/uapi/ethosu.h | 285 +++++++ .../porting/himax-we2/ethosu_driver.c | 16 + 19 files changed, 2533 insertions(+), 8 deletions(-) create mode 100644 edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h create mode 100644 edgeimpulse/edge-impulse-sdk/porting/clib/debug_log.cpp create mode 100644 edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp create mode 100644 edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h create mode 100644 edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c diff --git a/EdgeImpulse.EI-SDK.pdsc b/EdgeImpulse.EI-SDK.pdsc index 10bbafc..56d4fec 100644 --- a/EdgeImpulse.EI-SDK.pdsc +++ b/EdgeImpulse.EI-SDK.pdsc @@ -5,13 +5,16 @@ EI-SDK LICENSE-apache-2.0.txt Edge Impulse SDK - https://github.com/edgeimpulse/edge-impulse-sdk-pack/releases/download/v1.54.8/ + https://github.com/edgeimpulse/edge-impulse-sdk-pack/releases/download/v1.55.4/ hello@edgeimpulse.com https://github.com/edgeimpulse/edge-impulse-sdk-pack.git - + EI-SDK + + EI-SDK + EI-SDK @@ -98,9 +101,6 @@ EI-SDK - - - EI-SDK @@ -146,12 +146,13 @@ - + Edge Impulse SDK + @@ -335,6 +336,8 @@ + + @@ -348,6 +351,7 @@ + @@ -389,6 +393,7 @@ + @@ -624,6 +629,7 @@ + @@ -661,6 +667,7 @@ + diff --git a/EdgeImpulse.pidx b/EdgeImpulse.pidx index 3481163..b8e5c56 100644 --- a/EdgeImpulse.pidx +++ b/EdgeImpulse.pidx @@ -2,8 +2,8 @@ EdgeImpulse https://raw.githubusercontent.com/edgeimpulse/edge-impulse-sdk-pack/main/ - 2024-07-30 10:53:15 + 2024-08-05 16:39:10 - + diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h index e181cd8..39754ed 100644 --- a/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h +++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h @@ -42,6 +42,7 @@ #define EI_CLASSIFIER_SYNTIANT 10 #define EI_CLASSIFIER_ONNX_TIDL 11 #define EI_CLASSIFIER_MEMRYX 12 +#define EI_CLASSIFIER_ETHOS_LINUX 13 #define EI_CLASSIFIER_SENSOR_UNKNOWN -1 #define EI_CLASSIFIER_SENSOR_MICROPHONE 1 @@ -149,6 +150,21 @@ typedef struct { size_t arena_size; } ei_config_tflite_graph_t; +typedef struct { + uint16_t implementation_version; + uint8_t input_datatype; + bool input_quantized; + float input_scale; + float input_zeropoint; + uint8_t output_datatype; + bool output_quantized; + float output_scale; + float output_zeropoint; + const unsigned char *model; + size_t model_size; + size_t arena_size; +} ei_config_ethos_graph_t; + typedef struct { uint16_t implementation_version; TfLiteStatus (*model_init)(void*(*alloc_fnc)(size_t, size_t)); diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h index d9b0e6f..9921e44 100644 --- a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h +++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h @@ -58,6 +58,8 @@ #include "edge-impulse-sdk/classifier/inferencing_engines/onnx_tidl.h" #elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_MEMRYX #include "edge-impulse-sdk/classifier/inferencing_engines/memryx.h" +#elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX +#include "edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h" #elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_NONE // noop #else diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h index e46612c..00d789e 100644 --- a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h +++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h @@ -26,8 +26,16 @@ #include "model-parameters/model_metadata.h" #if EI_CLASSIFIER_HR_ENABLED +#if EI_CLASSIFIER_HR_LIB +// Forward declare only the part of the class we need to link later +class hr_class { +public: + static DspHandle* create(void* config, float frequency); +}; +#else #include "edge-impulse-sdk/dsp/ei_hr.hpp" #endif +#endif #if defined(__cplusplus) && EI_C_LINKAGE == 1 extern "C" { diff --git a/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h b/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h new file mode 100644 index 0000000..3f162fe --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2024 EdgeImpulse Inc. + * + * 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 + * http://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_ +#define _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_ + +#if (EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX) +// check if the model is quantized on the build stage to fail quickly +#if EI_CLASSIFIER_QUANTIZATION_ENABLED == 0 +#error "Ethos does not support float32 models" +#endif + +#include "model-parameters/model_metadata.h" +#include +#include "edge-impulse-sdk/classifier/ei_fill_result_struct.h" +#include "edge-impulse-sdk/classifier/ei_model_types.h" +#include "edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp" +#include "edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h" + +std::shared_ptr network; +// by default Device uses /dev/ethosu0 +static EthosU::Device device; +static bool init_done = false; + +bool init_ethos(const uint8_t *model_arr, size_t model_arr_size, bool debug) +{ + int ret; + try { + // eioctl thros exception if ioctl returns negative value + ret = device.ioctl(ETHOSU_IOCTL_PING); + } + catch (EthosU::Exception &e) { + ei_printf("ERR: EthosU device not found: %s\n", e.what()); + return false; + } + + try { + // eioctl thros exception if ioctl returns negative value + ret = device.ioctl(ETHOSU_IOCTL_VERSION_REQ); + } + catch (EthosU::Exception &e) { + ei_printf("ERR: EthosU version request failed: %s\n", e.what()); + return false; + } + + if (debug) { + try { + EthosU::Capabilities capabilities = device.capabilities(); + } + catch (EthosU::Exception &e) { + ei_printf("ERR: EthosU capabilities request failed: %s\n", e.what()); + return false; + } + + // std::cout << "Capabilities:" << std::endl + // << "\tversion_status:" << unsigned(capabilities.hwId.versionStatus) << std::endl + // << "\tversion:" << capabilities.hwId.version << std::endl + // << "\tproduct:" << capabilities.hwId.product << std::endl + // << "\tarchitecture:" << capabilities.hwId.architecture << std::endl + // << "\tdriver:" << capabilities.driver << std::endl + // << "\tmacs_per_cc:" << unsigned(capabilities.hwCfg.macsPerClockCycle) << std::endl + // << "\tcmd_stream_version:" << unsigned(capabilities.hwCfg.cmdStreamVersion) << std::endl + // << "\tcustom_dma:" << std::boolalpha << capabilities.hwCfg.customDma << std::endl; + } + + std::shared_ptr modelBuffer = std::make_shared(device, model_arr_size); + // TODO: not sure why we need to do that, but Buffer constructor calls mmap + // while resize calls ioct ETHOSU_IOCTL_BUFFER_SET on the ethos device + modelBuffer->resize(model_arr_size); + std::copy(model_arr, model_arr + model_arr_size, modelBuffer->data()); + + // std::shared_ptr networkBuffer = allocAndFill(device, "lamp-plant-int8_vela.tflite"); + network = std::make_shared(device, modelBuffer); + + if(network->getIfmDims().size() > 1) { + ei_printf("ERR: Only single input models are supported\n"); + return false; + } + + init_done = true; + + return true; +} + +EI_IMPULSE_ERROR run_nn_inference( + const ei_impulse_t *impulse, + ei_feature_t *fmatrix, + uint32_t learn_block_index, + uint32_t* input_block_ids, + uint32_t input_block_ids_size, + ei_impulse_result_t *result, + void *config_ptr, + bool debug) +{ + ei_learning_block_config_tflite_graph_t *block_config = (ei_learning_block_config_tflite_graph_t*)config_ptr; + ei_config_ethos_graph_t *io_details = ((ei_config_ethos_graph_t*)block_config->graph_config); + std::vector> ifm; + std::vector> ofm; + ei::matrix_t* matrix; + + + if (!init_done) { + if(!init_ethos(io_details->model, io_details->model_size, debug)) { + return EI_IMPULSE_DEVICE_INIT_ERROR; + } + } + + // so far only single input models are supported + // get the size of the first input tensor + auto ifmSize = network->getIfmDims()[0]; + // create a buffer for the input tensor + std::shared_ptr buffer = std::make_shared(device, ifmSize); + // resize the buffer to the size of the input tensor + // TODO: not sure if we need to call it, but the reference code does + buffer->resize(ifmSize); + // // inputType is an enum TensorType + // auto inputType = network->getIfmTypes()[0]; + // // inputShape is a vecor of dims + // auto inputShape = network->getIfmShapes()[0]; + + // get the matrix with input features + for (size_t i = 0; i < input_block_ids_size; i++) { +#if EI_CLASSIFIER_SINGLE_FEATURE_INPUT == 0 + uint16_t cur_mtx = input_block_ids[i]; + matrix = NULL; + + if (!find_mtx_by_idx(fmatrix, &matrix, cur_mtx, impulse->dsp_blocks_size + impulse->learning_blocks_size)) { + ei_printf("ERR: Cannot find matrix with id %zu\n", cur_mtx); + return EI_IMPULSE_INVALID_SIZE; + } +#else + matrix = fmatrix[0].matrix; +#endif + } + + if(ifmSize != matrix->rows * matrix->cols) { + ei_printf("ERR: Input size mismatch\n"); + return EI_IMPULSE_INVALID_SIZE; + } + + // copy rescale the input features to int8 and copy to input buffer + for (size_t i = 0; i < ifmSize; i++) { + buffer->data()[i] = (int8_t)((matrix->buffer[i] / io_details->input_scale) + io_details->input_zeropoint); + } + + // put the data into the input tensor + ifm.push_back(buffer); + + // create a buffer for the output tensor + auto ofmSize = network->getOfmDims()[0]; + ofm.push_back(std::make_shared(device, ofmSize)); + + // get start time of the inference + uint64_t ctx_start_us = ei_read_timer_us(); + + // start inference + EthosU::Inference inference(network, ifm.begin(), ifm.end(), ofm.begin(), ofm.end()); + + // wait in 1 second (wait gets nanoseconds) + if (inference.wait(1000 * 1000 * 1000)) { + return EI_IMPULSE_INFERENCE_ERROR; + } + + // get end time of the inference + uint64_t ctx_end_us = ei_read_timer_us(); + + // check if inference ended successfully + if (inference.status() != EthosU::InferenceStatus::OK) { + return EI_IMPULSE_INFERENCE_ERROR; + } + + // calculate inference time + result->timing.classification_us = ctx_end_us - ctx_start_us; + result->timing.classification = (int)(result->timing.classification_us / 1000); + + // get output data from the output tensor + auto data = inference.getOfmBuffers()[0]->data(); + + EI_IMPULSE_ERROR fill_res = EI_IMPULSE_OK; + + if(block_config->object_detection) { + switch (block_config->object_detection_last_layer) { + case EI_CLASSIFIER_LAST_LAYER_FOMO: { + fill_res = fill_result_struct_i8_fomo( + impulse, + block_config, + result, + (int8_t*)data, + io_details->output_zeropoint, + io_details->output_scale, + impulse->fomo_output_size, + impulse->fomo_output_size); + break; + } + case EI_CLASSIFIER_LAST_LAYER_SSD: { + ei_printf("ERR: MobileNet SSD models are not supported by Ethos\n"); + return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED; + } + case EI_CLASSIFIER_LAST_LAYER_YOLOV5: + case EI_CLASSIFIER_LAST_LAYER_YOLOV5_V5_DRPAI: { + int version = block_config->object_detection_last_layer == EI_CLASSIFIER_LAST_LAYER_YOLOV5_V5_DRPAI ? + 5 : 6; + + if (network->getOfmTypes()[0] == EthosU::TensorType_INT8) { + fill_res = fill_result_struct_quantized_yolov5( + impulse, + block_config, + result, + version, + (int8_t*)data, + io_details->output_zeropoint, + io_details->output_scale, + impulse->tflite_output_features_count, + debug); + } + else if (network->getOfmTypes()[0] == EthosU::TensorType_UINT8) { + fill_res = fill_result_struct_quantized_yolov5( + impulse, + block_config, + result, + version, + (uint8_t*)data, + io_details->output_zeropoint, + io_details->output_scale, + impulse->tflite_output_features_count, + debug); + } + else { + ei_printf("ERR: Invalid output type (%d) for YOLOv5 last layer\n", network->getOfmTypes()[0]); + return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED; + } + break; + } + case EI_CLASSIFIER_LAST_LAYER_YOLOX: + case EI_CLASSIFIER_LAST_LAYER_YOLOV7: + default: { + ei_printf("ERR: Object Detection layer (%d) not supported\n", block_config->object_detection_last_layer); + return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED; + } + } + } + else { + fill_res = fill_result_struct_i8(impulse, result, (int8_t*)data, io_details->output_zeropoint, io_details->output_scale, debug); + } + + return fill_res; +} + +#endif // (EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX) +#endif // _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_ diff --git a/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h b/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h index a7e7191..d7906ac 100644 --- a/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h +++ b/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h @@ -41,6 +41,8 @@ typedef enum { EI_IMPULSE_INVALID_SIZE = -24, /** +#include + +// Redirect TFLite DebugLog to ei_printf +#if defined(__cplusplus) && EI_C_LINKAGE == 1 +extern "C" +#endif // defined(__cplusplus) && EI_C_LINKAGE == 1 +void DebugLog(const char* s) { + ei_printf("%s", s); +} + +#endif diff --git a/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp b/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp new file mode 100644 index 0000000..0ff802b --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 EdgeImpulse Inc. + * + * 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 + * http://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "edge-impulse-sdk/porting/ei_classifier_porting.h" +#if EI_PORTING_CLIB == 1 +#include +#include + +__attribute__((weak)) EI_IMPULSE_ERROR ei_run_impulse_check_canceled() { + return EI_IMPULSE_OK; +} + +/** + * Cancelable sleep, can be triggered with signal from other thread + */ +__attribute__((weak)) EI_IMPULSE_ERROR ei_sleep(int32_t time_ms) { + return EI_IMPULSE_OK; +} + +uint64_t ei_read_timer_ms() { + return ei_read_timer_us() / 1000; +} + +uint64_t ei_read_timer_us() { + return 0; +} + +__attribute__((weak)) void ei_printf(const char *format, ...) { + va_list myargs; + va_start(myargs, format); + vprintf(format, myargs); + va_end(myargs); +} + +__attribute__((weak)) void ei_printf_float(float f) { + ei_printf("%f", f); +} + +__attribute__((weak)) void ei_putchar(char data) +{ + putchar(data); +} + +__attribute__((weak)) char ei_getchar(void) +{ + return getchar(); +} + +__attribute__((weak)) void *ei_malloc(size_t size) { + return malloc(size); +} + +__attribute__((weak)) void *ei_calloc(size_t nitems, size_t size) { + return calloc(nitems, size); +} + +__attribute__((weak)) void ei_free(void *ptr) { + free(ptr); +} + +#if defined(__cplusplus) && EI_C_LINKAGE == 1 +extern "C" +#endif +__attribute__((weak)) void DebugLog(const char* s) { + ei_printf("%s", s); +} + +#endif // EI_PORTING_CLIB == 1 diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + http://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. diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note new file mode 100644 index 0000000..adbe756 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note @@ -0,0 +1,24 @@ +SPDX-Exception-Identifier: Linux-syscall-note +SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html +SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later +Usage-Guide: + This exception is used together with one of the above SPDX-Licenses + to mark user space API (uapi) header files so they can be included + into non GPL compliant user space application code. + To use this exception add it with the keyword WITH to one of the + identifiers in the SPDX-Licenses tag: + SPDX-License-Identifier: WITH Linux-syscall-note +License-Text: + + NOTE! This copyright does *not* cover user programs that use kernel + services by normal system calls - this is merely considered normal use + of the kernel, and does *not* fall under the heading of "derived work". + Also note that the GPL below is copyrighted by the Free Software + Foundation, but the instance of code that it refers to (the Linux + kernel) is copyrighted by me and others who actually wrote it. + + Also note that the only valid version of the GPL as far as the kernel + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + Linus Torvalds diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md new file mode 100644 index 0000000..d062431 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md @@ -0,0 +1,23 @@ +# Linux driver stack for Arm(R) Ethos(TM)-U + +The driver was imported from [The Ethos-U Driver Stack iMX](https://github.com/nxp-imx/ethos-u-driver-stack-imx/tree/2acb7e2626fe3ff8764019e385829105a6e210bb) + +The [most recent version](https://github.com/nxp-imx/ethos-u-driver-stack-imx/tree/lf-6.6.3_1.0.0) + +# Licenses + +The kernel drivers are provided under a GPL v2 license. All other software +componantes are provided under an Apache 2.0 license. + +Please see [LICENSE-APACHE-2.0.txt](LICENSE-APACHE-2.0.txt), +[LICENSE-GPL-2.0.txt](LICENSE-GPL-2.0.txt) and [Linux-syscall-note](Linux-syscall-note) +for more information. + +# Security + +Please see [Security](SECURITY.md). + +# Trademark notice + +Arm, Cortex and Ethos are registered trademarks of Arm Limited (or its +subsidiaries) in the US and/or elsewhere. diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt new file mode 100644 index 0000000..4f2e390 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt @@ -0,0 +1,39 @@ +NXP Software Content Register + +Package: ethos-u-driver-stack-imx.git +Outgoing License: Apache-2.0 +License File: LICENSE.txt +Type of Content: source +Description and comments: ethos-u-driver-stack is the user space driver library for ethos-u NPU on iMX93 platform +Release Location: https://github.com/nxp-imx/ethos-u-driver-stack-imx +Origin: NXP (BSD-3-Clause) + ARM Limited ethos-u-linux-driver-stack v23.08 (Apache-2.0) - https://git.mlplatform.org/ml/ethos-u/ethos-u-linux-driver-stack.git + + +-------------------------------------------- +Included kernel header file +-------------------------------------------- +Component: kernel_driver inteface header file +Outgoing License: GPL-2.0-only WITH Linux-syscall-note +License File: LICENSE-GPL-2.0.txt and Linux-syscall-note +Package Category: Ethos-u Linux kernel driver header file +Type of Content: header file +Description and comments: Linux kernel driver header file, the driver stack will include this header + file to use linux kernel syscall. +Origin: ARM ethos-u-linux-driver-stack v23.08 (Apache-2.0) - https://git.mlplatform.org/ml/ethos-u/ethos-u-linux-driver-stack.git +File location: kernel_driver/include/ethos-u.h + +-------------------------------------------- +Auto generated header file by flatbuffers +-------------------------------------------- +Component: flatbuffers header file +Outgoing License: Apache-2.0 +License File: LICENSE.txt +Package Category: Auto generated header file by flatbuffers +Type of Content: header file +Description and comments: FlatBuffers is a cross platform serialization library architected for maximum memory efficiency +Origin: Google flatbuffers 1.12.0 (Apache-2.0) - https://github.com/google/flatbuffers +File location: driver_library/src/autogen/tflite_schema.hpp + + + diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md new file mode 100644 index 0000000..29c6ce4 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md @@ -0,0 +1,85 @@ +# Security + +If you believe you have identified a security related issue or vulnerability, +then we encourage you to responsibly disclose it to us as soon as possible. + +## Reporting vulnerabilities + +Arm takes security issues seriously and welcomes feedback from researchers and +the security community in order to improve the security of its products and +services. We operate a coordinated disclosure policy for disclosing +vulnerabilities and other security issues. + +Security issues can be complex and one single timescale doesn't fit all +circumstances. We will make best endeavours to inform you when we expect +security notifications and fixes to be available and facilitate coordinated +disclosure when notifications and patches/mitigations are available. + +### Report + +For all security issues, contact Arm by email at +[arm-security@arm.com](mailto:arm-security@arm.com). In the body of the email +include as much information as possible about the issue or vulnerability and any +additional contact details. + +### Secure submission using PGP + +We support and encourage secure submission of vulnerability reports using PGP, +using the key below. If you would like replies to be encrypted, please provide +your own public key through a secure mechanism. + +~~~none +-----BEGIN PGP PUBLIC KEY BLOCK----- +mQINBFr7/RMBEACjHR5QZL/z1t2aLCRNXLE4KJiQmCo7edU5Be+7MTjIJDzZNu68 +lNEUYRoLexeayif8eC4T19bUsSbGpxHiYsFFjV8ewLXDyDJRRuaBGPfQ5rn/mE6X +Nvu+9Pputr+mB1R3CXcvrNkhmzPkK7zVM15oeyBMhogqPssuT4OeMduQdip8smfK +xTMk91RrJTLb+G3eE1tf+81kXBYvzp2e24Sn0/VeYe0IWnBobjVBZk3TmcYxDvz5 +Y47fU9V6cNj3Zq4VYrgxuLoFCA2VtetyiFQm5IYa3Bt3SWcAwihr8nbR2HoNdWyA +u8wJYYVzSq3hvT5l/IjTHxEcY+6RBq8poDSsftzvX386u9hmw7sJQFlTw6/pUjdr +gbsZ2ZzRBzKtU17ercpn4kU6VgVP3WRB5HiTFFkEpZuqAznOYaHbMq4dfd/g7Quq +C0VTbWiJnhku2i+g4BdHHRDtIF6U3aVQAfbrDb1LjVTa65p5ULOeY3HRAWtMNtu/ +Cj8cD98JDanzXtcnisds8vMQ8LZ6iMFChEnF8K4V0eLw9Ju6CMNiFYY7SEBndD/H +M4KcU4li7mROSbJcshgEbe1SYkxdMuI9eY4DNYxl3VjxoPUGzeqXo/ADFKE9bHsi +GTyEoij4ku0HspLVKnYHXn/LqHGwEcwjF8zphS+w5cn/e01akYwz5EVSQwARAQAB +tB1Bcm0gU3VwcG9ydCA8c3VwcG9ydEBhcm0uY29tPokCTgQTAQgAOBYhBN9zqDwZ +RL/vF0ihcdfNKdz4bBRiBQJa+/0TAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA +AAoJENfNKdz4bBRibK0P/jLlJR/QYypcjb+8BnHT9tCDgcV2KFYXS15VpbSNviN9 +Xs/UOnSadoGUMGCXDyb1PRNn98yUn7JlNR9rtsqPRmkpbo5cuw46ehgxjVlfcHnk +CttaE8Davx6zo0fyrBib2+oVVW8usi9+uRK4vhhPUicO3oXwzldsVFz+RbpubZxc +Bg/CZ+dQ2jMKOv1zDtInOG6OBnbQZRAeiWXgGhcIoPZ4zBQOi8nr0+bLcfvMeZi2 +uz6uKnylpXwZbl4ijcG8MKV/ei+7du+SzA9NY0WOT2g3FXDREWUhjKs8bmEZgIx4 +QgvDNpxAUThF+TqQ7zrsA8nT8POvDD0MhN/Z+A3QdPTdcaZFaXzIdxbDg+0FKmzu +OgtQBH4C01RWrkmZlhO5w7/Qjt0vLlhfyQIL9BW/HeEPtjnH2Hnq8xYnZhlVqJEh +FJU7F9sMvyiJiKviobFTd6AmpVkhxhcJ3k2L2C03imTsmUwAoejQCXwiYcOhyQ2t +Z9Nk8YIZTEw2urGFi4HSQPwPq2j/2j7ABJ4rlzJvO6vs5ppGkumvzIIP9JnpVXbp +wcbK6Ev6KdkX4s14Mzd6Hsd8LpL8t5nHhxUey6G0xKe2eSlHVm5Mlfhoete9UmIZ +dzIOZkgTgWXlYXRIxwGQ2Pss7pURtofykvLklq4jcobQuHxurl9cteodETfbWk/J +uQINBFr7/RMBEADWZG8eqt5D22g3T7ehnH/T3fuTX8LPUBnODMWGAEUY8uv64To8 +46odvrXFgWBgCf0sROEyJchc3SGLyR9S4lJsVJRde3QLN3WZkHlB4pSn4IQHFyQd +wsLQi+S9uggHMPlQ6MNvc5n0P3k5bT9fLUmtJWJ3QVjW7k963ZXpzf1zbQJqs30w +rlqGUZllfRoYQTfcYxFEaUFhwRJ//skNImWH8Vz+PTnqg2zRtFn3usrBV4GpNvsM +6jy+YEsSvUa7IY8k4wpPzEhIfqDjGbZxFSQ1H1G+mLUL+DD7oGffej/ZoC86TIdM +p6ew1rGhJdQBLh9nx+1ADOLWjNo2R0h60u7VR5q/K6V4fwWmeGFipPXZCD92I+nR +t/cjznwNyD/6J9YrBMF7mbGrS1TyfLaLt4tpdcBnsgqDTodd5OmG65mroXsg/lNO +7YZdecLZ34krfaLrWTtKkqULXbppB+uQvbVj8p8ONRImn6bZ+iAhnNaH9wJ06ico +b1F0imJ2SJWnFr6PzPRr0gPStLgu9wrRKheaORwF/H/HxSyPZxNVxFqu81q518A/ +plhub9INQLaxHf/TTjXpqZCcfdNTYUAW8rwbQfW9doSIT4lHY8bJXktb6BsVjkFj +PzDeYpXeOoTWetQqsEuTdg/F+qg041QBLtNj9Lr3Vy3StgMciRUIP8m0XwARAQAB +iQI2BBgBCAAgFiEE33OoPBlEv+8XSKFx180p3PhsFGIFAlr7/RMCGwwACgkQ180p +3PhsFGLWMA//V/XKrnI2YBh/SptUrgg7knPXva45bb7tGSH1fJg8f/wqycOSFFCY +ES45boA5jlQ3z8uw6BYCz5KeOucGhxAMw+x5EDdxZ33ksY5zqXB35WaMXzEwGYYb +E113/yhOsTbzu4bBKABSXbJO98MdAWvWpyCpp2MHIR3S9+ycM7/FMZ5xi3czZNRg +9+WZP+7W4qWhJptQ0kBh5C3N/tiltju5WQ2Y7XIn+5dMOJdtseFS7CNerxXZGAtH +nfRxaD/4ENdbWOwaVJiVW7+ioUJz09OWgy0gLYSDW+hciDnW1QAaJLpdAbniGZ0S +JsTmaZla8JnUKqZPgbFfA2OcnH9H+DWc0pHv17c5tJzTMP7rgirgGRX/U2LOzmFZ +1UxjQj5nn3Oa5frXbIAzb8xKiR0VDaquCM/3sti1AesYiS0Gw0Sqnw8qpFypgFXN +CKVgYXppIT+TmbDbNJDOB2UycxeI4vbiBwU8fI4qSpW12WsGdAJt/rx3UsyhZ+02 +4aSqDHzhJmtDPQ6lnaKe1fUkC90tgp8loVGmriWQx82jAQMqATVjIklTpE4vm00f +ocQIWOKEE90mKNEoV6rNbfl5QevmapTVdV/pmrRBzhbsa1uAUS4HZdH0Nf/OXEyv +yYCr2gCFPymkkRYhPr2w5EgbWyzLaBIwqjyIbXaveuB3DYi2Lhbf64I= +=EaN7 +-----END PGP PUBLIC KEY BLOCK----- +~~~ + +For more information visit + \ No newline at end of file diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp new file mode 100644 index 0000000..c361db4 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2020-2022 Arm Limited. + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#define DEFAULT_ARENA_SIZE_OF_MB 16 +#define ETHOSU_PMU_EVENT_MAX 4 + +/* + *The following undef are necessary to avoid clash with macros in GNU C Library + * if removed the following warning/error are produced: + * + * In the GNU C Library, "major" ("minor") is defined + * by . For historical compatibility, it is + * currently defined by as well, but we plan to + * remove this soon. To use "major" ("minor"), include + * directly. If you did not intend to use a system-defined macro + * "major" ("minor"), you should undefine it after including . + */ +#undef major +#undef minor + +namespace EthosU { + +class Exception : public std::exception { +public: + Exception(const char *msg); + virtual ~Exception() throw(); + virtual const char *what() const throw(); + +private: + std::string msg; +}; + +/** + * Sematic Version : major.minor.patch + */ +class SemanticVersion { +public: + SemanticVersion(uint32_t _major = 0, uint32_t _minor = 0, uint32_t _patch = 0) : + major(_major), minor(_minor), patch(_patch){}; + + bool operator==(const SemanticVersion &other); + bool operator<(const SemanticVersion &other); + bool operator<=(const SemanticVersion &other); + bool operator!=(const SemanticVersion &other); + bool operator>(const SemanticVersion &other); + bool operator>=(const SemanticVersion &other); + + uint32_t major; + uint32_t minor; + uint32_t patch; +}; + +std::ostream &operator<<(std::ostream &out, const SemanticVersion &v); + +/* + * Hardware Identifier + * @versionStatus: Version status + * @version: Version revision + * @product: Product revision + * @architecture: Architecture revison + */ +struct HardwareId { +public: + HardwareId(uint32_t _versionStatus, + const SemanticVersion &_version, + const SemanticVersion &_product, + const SemanticVersion &_architecture) : + versionStatus(_versionStatus), + version(_version), product(_product), architecture(_architecture) {} + + uint32_t versionStatus; + SemanticVersion version; + SemanticVersion product; + SemanticVersion architecture; +}; + +/* + * Hardware Configuration + * @macsPerClockCycle: MACs per clock cycle + * @cmdStreamVersion: NPU command stream version + * @customDma: Custom DMA enabled + */ +struct HardwareConfiguration { +public: + HardwareConfiguration(uint32_t _macsPerClockCycle, uint32_t _cmdStreamVersion, bool _customDma) : + macsPerClockCycle(_macsPerClockCycle), cmdStreamVersion(_cmdStreamVersion), customDma(_customDma) {} + + uint32_t macsPerClockCycle; + uint32_t cmdStreamVersion; + bool customDma; +}; + +/** + * Device capabilities + * @hwId: Hardware + * @driver: Driver revision + * @hwCfg Hardware configuration + */ +class Capabilities { +public: + Capabilities(const HardwareId &_hwId, const HardwareConfiguration &_hwCfg, const SemanticVersion &_driver) : + hwId(_hwId), hwCfg(_hwCfg), driver(_driver) {} + + HardwareId hwId; + HardwareConfiguration hwCfg; + SemanticVersion driver; +}; + +class Device { +public: + Device(const char *device = "/dev/ethosu0"); + virtual ~Device() noexcept(false); + + int ioctl(unsigned long cmd, void *data = nullptr) const; + Capabilities capabilities() const; + +private: + int fd; +}; + +class Buffer { +public: + Buffer(const Device &device, const size_t capacity); + virtual ~Buffer() noexcept(false); + + size_t capacity() const; + void clear() const; + char *data() const; + void resize(size_t size, size_t offset = 0) const; + size_t offset() const; + size_t size() const; + + int getFd() const; + +private: + int fd; + char *dataPtr; + const size_t dataCapacity; +}; + +class Network { +public: + Network(const Device &device, std::shared_ptr &buffer); + Network(const Device &device, const unsigned index); + virtual ~Network() noexcept(false); + + int ioctl(unsigned long cmd, void *data = nullptr); + std::shared_ptr getBuffer(); + const std::vector &getIfmDims() const; + size_t getIfmSize() const; + const std::vector &getOfmDims() const; + size_t getOfmSize() const; + + size_t getInputCount() const; + size_t getOutputCount() const; + int32_t getInputDataOffset(int index); + int32_t getOutputDataOffset(int index); + const std::vector> &getIfmShapes() const; + const std::vector> &getOfmShapes() const; + const std::vector &getIfmTypes() const; + const std::vector &getOfmTypes() const; + const Device &getDevice() const; + bool isVelaModel() const; + +private: + void collectNetworkInfo(); + + int fd; + std::shared_ptr buffer; + std::vector ifmDims; + std::vector ofmDims; + std::vector ifmDataOffset; + std::vector ofmDataOffset; + std::vector> ifmShapes; + std::vector> ofmShapes; + std::vector ifmTypes; + std::vector ofmTypes; + const Device &device; + bool _isVelaModel; +}; + +enum class InferenceStatus { + OK, + ERROR, + RUNNING, + REJECTED, + ABORTED, + ABORTING, +}; + +std::ostream &operator<<(std::ostream &out, const InferenceStatus &v); + +class Inference { +public: + template + Inference(const std::shared_ptr &network, + const T &ifmBegin, + const T &ifmEnd, + const T &ofmBegin, + const T &ofmEnd) : + network(network) { + std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers)); + std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers)); + std::vector counterConfigs = initializeCounterConfig(); + + // Init tensor arena buffer + size_t arena_buffer_size = DEFAULT_ARENA_SIZE_OF_MB << 20; + arenaBuffer = std::make_shared(network->getDevice(), arena_buffer_size); + arenaBuffer->resize(arena_buffer_size); + + create(counterConfigs, false); + } + template + Inference(const std::shared_ptr &network, + const T &ifmBegin, + const T &ifmEnd, + const T &ofmBegin, + const T &ofmEnd, + const U &counters, + bool enableCycleCounter) : + network(network) { + std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers)); + std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers)); + std::vector counterConfigs = initializeCounterConfig(); + + if (counters.size() > counterConfigs.size()) + throw EthosU::Exception("PMU Counters argument to large."); + + // Init tensor arena buffer + size_t arena_buffer_size = DEFAULT_ARENA_SIZE_OF_MB << 20; + arenaBuffer = std::make_shared(network->getDevice(), arena_buffer_size); + arenaBuffer->resize(arena_buffer_size); + + std::copy(counters.begin(), counters.end(), counterConfigs.begin()); + create(counterConfigs, enableCycleCounter); + } + + template + Inference(const std::shared_ptr &network, + const T &arenaBuffer, + const U &counters, + bool enableCycleCounter) : + network(network), arenaBuffer(arenaBuffer) { + + std::vector counterConfigs = initializeCounterConfig(); + + if (counters.size() > counterConfigs.size()) + throw EthosU::Exception("PMU Counters argument to large."); + + std::copy(counters.begin(), counters.end(), counterConfigs.begin()); + create(counterConfigs, enableCycleCounter); + } + + + virtual ~Inference() noexcept(false); + + bool wait(int64_t timeoutNanos = -1) const; + const std::vector getPmuCounters() const; + uint64_t getCycleCounter() const; + bool cancel() const; + InferenceStatus status() const; + int getFd() const; + const std::shared_ptr getNetwork() const; + std::vector> &getIfmBuffers(); + std::vector> &getOfmBuffers(); + + static uint32_t getMaxPmuEventCounters(); + + char* getInputData(int index = 0); + char* getOutputData(int index = 0); + +private: + void create(std::vector &counterConfigs, bool enableCycleCounter); + std::vector initializeCounterConfig(); + + int fd; + const std::shared_ptr network; + std::vector> ifmBuffers; + std::vector> ofmBuffers; + std::shared_ptr arenaBuffer; +}; + +struct TensorInfo{ + int type; + std::vector shape; +}; + +//Define tflite::TensorType here +enum TensorType{ + TensorType_FLOAT32 = 0, + TensorType_FLOAT16 = 1, + TensorType_INT32 = 2, + TensorType_UINT8 = 3, + TensorType_INT64 = 4, + TensorType_STRING = 5, + TensorType_BOOL = 6, + TensorType_INT16 = 7, + TensorType_COMPLEX64 = 8, + TensorType_INT8 = 9, + TensorType_FLOAT64 = 10, + TensorType_MIN = TensorType_FLOAT32, + TensorType_MAX = TensorType_FLOAT64 + +}; + +class Interpreter { +public: + Interpreter(const char *model, const char *device = "/dev/ethosu0", + int64_t arenaSizeOfMB = DEFAULT_ARENA_SIZE_OF_MB); + Interpreter(const std::string &model) : Interpreter(model.c_str()) {} + + void SetPmuCycleCounters(std::vector counters, bool enableCycleCounter = true); + std::vector GetPmuCounters(); + uint64_t GetCycleCounter(); + + void Invoke(int64_t timeoutNanos = 60000000000); + + template + T* typed_input_buffer(int index) { + int32_t offset = network->getInputDataOffset(index); + return (T*)(arenaBuffer->data() + offset); + } + + template + T* typed_output_buffer(int index) { + int32_t offset = network->getOutputDataOffset(index); + return (T*)(arenaBuffer->data() + offset); + } + + std::vector GetInputInfo(); + std::vector GetOutputInfo(); + +private: + Device device; + std::shared_ptr networkBuffer; + std::shared_ptr arenaBuffer; + std::shared_ptr network; + std::shared_ptr inference; + + int64_t arenaSizeOfMB; + std::vector pmuCounters; + bool enableCycleCounter; +}; + +} // namespace EthosU diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp new file mode 100644 index 0000000..0393a05 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2020-2022 Arm Limited. + * + * 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. + */ + +#ifdef EI_ETHOS_LINUX +#include "../include/ethosu.hpp" +#include "../../kernel_driver/include/uapi/ethosu.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +enum class Severity { Error, Warning, Info, Debug }; + +class Log { +public: + Log(const Severity _severity = Severity::Error) : severity(_severity) {} + + ~Log() = default; + + template + const Log &operator<<(const T &d) const { + if (level >= severity) { + cout << d; + } + + return *this; + } + + const Log &operator<<(ostream &(*manip)(ostream &)) const { + if (level >= severity) { + manip(cout); + } + + return *this; + } + +private: + static Severity getLogLevel() { + if (const char *e = getenv("ETHOSU_LOG_LEVEL")) { + const string env(e); + + if (env == "Error") { + return Severity::Error; + } else if (env == "Warning") { + return Severity::Warning; + } else if (env == "Info") { + return Severity::Info; + } else if (env == "Debug") { + return Severity::Debug; + } else { + cerr << "Unsupported log level '" << env << "'" << endl; + } + } + + return Severity::Warning; + } + + static const Severity level; + const Severity severity; +}; + +const Severity Log::level = Log::getLogLevel(); + +} // namespace + +namespace EthosU { +__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) { + int ret = ::ioctl(fd, cmd, data); + if (ret < 0) { + throw EthosU::Exception("IOCTL failed"); + } + + Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret + << endl; + + return ret; +} + +__attribute__((weak)) int eopen(const char *pathname, int flags) { + int fd = ::open(pathname, flags); + if (fd < 0) { + throw Exception("Failed to open device"); + } + + Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl; + + return fd; +} + +__attribute__((weak)) int +eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) { + int result = ::ppoll(fds, nfds, tmo_p, sigmask); + if (result < 0) { + throw Exception("Failed to wait for ppoll event or signal"); + } + + return result; +} + +__attribute__((weak)) int eclose(int fd) { + Log(Severity::Debug) << "close. fd=" << fd << endl; + + int result = ::close(fd); + if (result < 0) { + throw Exception("Failed to close file"); + } + + return result; +} +__attribute((weak)) void *emmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { + void *ptr = ::mmap(addr, length, prot, flags, fd, offset); + if (ptr == MAP_FAILED) { + throw Exception("Failed to mmap file"); + } + + Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length + << ", ptr=" << hex << ptr << endl; + + return ptr; +} + +__attribute__((weak)) int emunmap(void *addr, size_t length) { + Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl; + + int result = ::munmap(addr, length); + if (result < 0) { + throw Exception("Failed to munmap file"); + } + + return result; +} + +} // namespace EthosU + +namespace EthosU { + +/**************************************************************************** + * Exception + ****************************************************************************/ + +Exception::Exception(const char *msg) : msg(msg) {} + +Exception::~Exception() throw() {} + +const char *Exception::what() const throw() { + return msg.c_str(); +} + +/**************************************************************************** + * Semantic Version + ****************************************************************************/ + +bool SemanticVersion::operator==(const SemanticVersion &other) { + return other.major == major && other.minor == minor && other.patch == patch; +} + +bool SemanticVersion::operator<(const SemanticVersion &other) { + if (other.major > major) + return true; + if (other.minor > minor) + return true; + return other.patch > patch; +} + +bool SemanticVersion::operator<=(const SemanticVersion &other) { + return *this < other || *this == other; +} + +bool SemanticVersion::operator!=(const SemanticVersion &other) { + return !(*this == other); +} + +bool SemanticVersion::operator>(const SemanticVersion &other) { + return !(*this <= other); +} + +bool SemanticVersion::operator>=(const SemanticVersion &other) { + return !(*this < other); +} + +ostream &operator<<(ostream &out, const SemanticVersion &v) { + return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch) + << " }"; +} + +/**************************************************************************** + * Device + ****************************************************************************/ +Device::Device(const char *device) { + fd = eopen(device, O_RDWR | O_NONBLOCK); + Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl; +} + +Device::~Device() noexcept(false) { + eclose(fd); + Log(Severity::Info) << "~Device(). this=" << this << endl; +} + +int Device::ioctl(unsigned long cmd, void *data) const { + return eioctl(fd, cmd, data); +} + +Capabilities Device::capabilities() const { + ethosu_uapi_device_capabilities uapi; + (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast(&uapi)); + + Capabilities capabilities( + HardwareId(uapi.hw_id.version_status, + SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor), + SemanticVersion(uapi.hw_id.product_major), + SemanticVersion(uapi.hw_id.arch_major_rev, uapi.hw_id.arch_minor_rev, uapi.hw_id.arch_patch_rev)), + HardwareConfiguration(uapi.hw_cfg.macs_per_cc, uapi.hw_cfg.cmd_stream_version, bool(uapi.hw_cfg.custom_dma)), + SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev)); + return capabilities; +} + +/**************************************************************************** + * Buffer + ****************************************************************************/ + +Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) { + ethosu_uapi_buffer_create uapi = {static_cast(dataCapacity)}; + fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast(&uapi)); + + void *d; + try { + d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + } catch (std::exception &e) { + try { + eclose(fd); + } catch (...) { std::throw_with_nested(e); } + throw; + } + + dataPtr = reinterpret_cast(d); + + Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd + << ", dataPtr=" << static_cast(dataPtr) << endl; +} + +Buffer::~Buffer() noexcept(false) { + try { + emunmap(dataPtr, dataCapacity); + } catch (std::exception &e) { + try { + eclose(fd); + } catch (...) { std::throw_with_nested(e); } + throw; + } + + eclose(fd); + + Log(Severity::Info) << "~Buffer(). this=" << this << endl; +} + +size_t Buffer::capacity() const { + return dataCapacity; +} + +void Buffer::clear() const { + resize(0, 0); +} + +char *Buffer::data() const { + return dataPtr + offset(); +} + +void Buffer::resize(size_t size, size_t offset) const { + ethosu_uapi_buffer uapi; + uapi.offset = offset; + uapi.size = size; + eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast(&uapi)); +} + +size_t Buffer::offset() const { + ethosu_uapi_buffer uapi; + eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi)); + return uapi.offset; +} + +size_t Buffer::size() const { + ethosu_uapi_buffer uapi; + eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi)); + return uapi.size; +} + +int Buffer::getFd() const { + return fd; +} + +/**************************************************************************** + * Network + ****************************************************************************/ + +Network::Network(const Device &device, shared_ptr &buffer) : device(device), fd(-1), buffer(buffer) { + // Create buffer handle + ethosu_uapi_network_create uapi; + uapi.type = ETHOSU_UAPI_NETWORK_BUFFER; + uapi.fd = buffer->getFd(); + fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast(&uapi)); + try { + collectNetworkInfo(); + } catch (std::exception &e) { + try { + eclose(fd); + } catch (...) { std::throw_with_nested(e); } + throw; + } + + Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl; +} + +Network::Network(const Device &device, const unsigned index) : device(device), fd(-1) { + // Create buffer handle + ethosu_uapi_network_create uapi; + uapi.type = ETHOSU_UAPI_NETWORK_INDEX; + uapi.index = index; + fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast(&uapi)); + try { + collectNetworkInfo(); + } catch (std::exception &e) { + try { + eclose(fd); + } catch (...) { std::throw_with_nested(e); } + throw; + } + + Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl; +} + +void Network::collectNetworkInfo() { + ethosu_uapi_network_info info; + ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast(&info)); + + _isVelaModel = info.is_vela; + + for (uint32_t i = 0; i < info.ifm_count; i++) { + ifmDims.push_back(info.ifm_size[i]); + ifmTypes.push_back(info.ifm_types[i]); + ifmDataOffset.push_back(info.ifm_offset[i]); + + std::vector shape; + for (uint32_t j = 0; j < info.ifm_dims[i]; j++) { + shape.push_back(info.ifm_shapes[i][j]); + } + ifmShapes.push_back(shape); + } + + for (uint32_t i = 0; i < info.ofm_count; i++) { + ofmDims.push_back(info.ofm_size[i]); + ofmTypes.push_back(info.ofm_types[i]); + ofmDataOffset.push_back(info.ofm_offset[i]); + + std::vector shape; + for (uint32_t j = 0; j < info.ofm_dims[i]; j++) { + shape.push_back(info.ofm_shapes[i][j]); + } + ofmShapes.push_back(shape); + } +} + +Network::~Network() noexcept(false) { + eclose(fd); + Log(Severity::Info) << "~Network(). this=" << this << endl; +} + +int Network::ioctl(unsigned long cmd, void *data) { + return eioctl(fd, cmd, data); +} + +shared_ptr Network::getBuffer() { + return buffer; +} + +const std::vector &Network::getIfmDims() const { + return ifmDims; +} + +size_t Network::getIfmSize() const { + size_t size = 0; + + for (auto s : ifmDims) { + size += s; + } + + return size; +} + +const std::vector &Network::getOfmDims() const { + return ofmDims; +} + +size_t Network::getOfmSize() const { + size_t size = 0; + + for (auto s : ofmDims) { + size += s; + } + + return size; +} + +size_t Network::getInputCount() const { + return ifmTypes.size(); +} + +size_t Network::getOutputCount() const { + return ofmTypes.size(); +} + +int32_t Network::getInputDataOffset(int index){ + if (index >= ifmDataOffset.size()){ + throw Exception("Invalid input index or non vela model"); + } + return ifmDataOffset[index]; +} + +int32_t Network::getOutputDataOffset(int index){ + if (index >= ofmDataOffset.size()){ + throw Exception("Invalid output index or non vela model"); + } + return ofmDataOffset[index]; +} + +const std::vector> &Network::getIfmShapes() const { + return ifmShapes; +} + +const std::vector> &Network::getOfmShapes() const { + return ofmShapes; +} + +const std::vector &Network::getIfmTypes() const { + return ifmTypes; +} + +const std::vector &Network::getOfmTypes() const { + return ofmTypes; +} + +const Device &Network::getDevice() const { + return device; +} + +bool Network::isVelaModel() const { + return _isVelaModel; +} + +/**************************************************************************** + * Inference + ****************************************************************************/ + +ostream &operator<<(ostream &out, const InferenceStatus &status) { + switch (status) { + case InferenceStatus::OK: + return out << "ok"; + case InferenceStatus::ERROR: + return out << "error"; + case InferenceStatus::RUNNING: + return out << "running"; + case InferenceStatus::REJECTED: + return out << "rejected"; + case InferenceStatus::ABORTED: + return out << "aborted"; + case InferenceStatus::ABORTING: + return out << "aborting"; + } + throw Exception("Unknown inference status"); +} + +Inference::~Inference() noexcept(false) { + eclose(fd); + Log(Severity::Info) << "~Inference(). this=" << this << endl; +} + +void Inference::create(std::vector &counterConfigs, bool cycleCounterEnable = false) { + ethosu_uapi_inference_create uapi; + + if (ifmBuffers.size() > ETHOSU_FD_MAX) { + throw Exception("IFM buffer overflow"); + } + + if (ofmBuffers.size() > ETHOSU_FD_MAX) { + throw Exception("OFM buffer overflow"); + } + + if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) { + throw Exception("Wrong size of counter configurations"); + } + + uapi.ifm_count = 0; + uapi.ifm_fd[uapi.ifm_count++] = arenaBuffer->getFd(); + for (auto it : ifmBuffers) { + uapi.ifm_fd[uapi.ifm_count++] = it->getFd(); + } + + uapi.ofm_count = 0; + for (auto it : ofmBuffers) { + uapi.ofm_fd[uapi.ofm_count++] = it->getFd(); + } + + for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) { + uapi.pmu_config.events[i] = counterConfigs[i]; + } + + uapi.pmu_config.cycle_count = cycleCounterEnable; + + fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast(&uapi)); + + Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl; +} + +std::vector Inference::initializeCounterConfig() { + return std::vector(ETHOSU_PMU_EVENT_MAX, 0); +} + +uint32_t Inference::getMaxPmuEventCounters() { + return ETHOSU_PMU_EVENT_MAX; +} + +bool Inference::wait(int64_t timeoutNanos) const { + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + pfd.revents = 0; + + // if timeout negative wait forever + if (timeoutNanos < 0) { + return eppoll(&pfd, 1, NULL, NULL); + } + + struct timespec tmo_p; + int64_t nanosec = 1000000000; + tmo_p.tv_sec = timeoutNanos / nanosec; + tmo_p.tv_nsec = timeoutNanos % nanosec; + + return eppoll(&pfd, 1, &tmo_p, NULL) == 0; +} + +bool Inference::cancel() const { + ethosu_uapi_cancel_inference_status uapi; + eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast(&uapi)); + return uapi.status == ETHOSU_UAPI_STATUS_OK; +} + +InferenceStatus Inference::status() const { + ethosu_uapi_result_status uapi; + + eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi)); + + switch (uapi.status) { + case ETHOSU_UAPI_STATUS_OK: + return InferenceStatus::OK; + case ETHOSU_UAPI_STATUS_ERROR: + return InferenceStatus::ERROR; + case ETHOSU_UAPI_STATUS_RUNNING: + return InferenceStatus::RUNNING; + case ETHOSU_UAPI_STATUS_REJECTED: + return InferenceStatus::REJECTED; + case ETHOSU_UAPI_STATUS_ABORTED: + return InferenceStatus::ABORTED; + case ETHOSU_UAPI_STATUS_ABORTING: + return InferenceStatus::ABORTING; + } + + throw Exception("Unknown inference status"); +} + +const std::vector Inference::getPmuCounters() const { + ethosu_uapi_result_status uapi; + std::vector counterValues = std::vector(ETHOSU_PMU_EVENT_MAX, 0); + + eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi)); + + for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) { + if (uapi.pmu_config.events[i]) { + counterValues.at(i) = uapi.pmu_count.events[i]; + } + } + + return counterValues; +} + +uint64_t Inference::getCycleCounter() const { + ethosu_uapi_result_status uapi; + + eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi)); + + return uapi.pmu_count.cycle_count; +} + +int Inference::getFd() const { + return fd; +} + +const shared_ptr Inference::getNetwork() const { + return network; +} + +vector> &Inference::getIfmBuffers() { + return ifmBuffers; +} + +vector> &Inference::getOfmBuffers() { + return ofmBuffers; +} + +/**************************************************************************** + * Interpreter + ****************************************************************************/ +Interpreter::Interpreter(const char *model, const char *_device, int64_t _arenaSizeOfMB): + device(_device), arenaSizeOfMB(_arenaSizeOfMB){ + //Send capabilities request + Capabilities capabilities = device.capabilities(); + + cout << "Capabilities:" << endl + << "\tversion_status:" << unsigned(capabilities.hwId.versionStatus) << endl + << "\tversion:" << capabilities.hwId.version << endl + << "\tproduct:" << capabilities.hwId.product << endl + << "\tarchitecture:" << capabilities.hwId.architecture << endl + << "\tdriver:" << capabilities.driver << endl + << "\tmacs_per_cc:" << unsigned(capabilities.hwCfg.macsPerClockCycle) << endl + << "\tcmd_stream_version:" << unsigned(capabilities.hwCfg.cmdStreamVersion) << endl + << "\tcustom_dma:" << std::boolalpha << capabilities.hwCfg.customDma << endl; + + // Init network + ifstream stream(model, ios::binary); + if (!stream.is_open()) { + throw Exception("Failed to open model file"); + } + + stream.seekg(0, ios_base::end); + size_t size = stream.tellg(); + stream.seekg(0, ios_base::beg); + + networkBuffer = make_shared(device, size); + networkBuffer->resize(size); + stream.read(networkBuffer->data(), size); + network = make_shared(device, networkBuffer); + if (!network->isVelaModel()) { + throw Exception("Only support models compiled by vela."); + } + + // Init tensor arena buffer + size_t arena_buffer_size = arenaSizeOfMB << 20; + arenaBuffer = make_shared(device, arena_buffer_size); + arenaBuffer->resize(arena_buffer_size); +} + +void Interpreter::SetPmuCycleCounters(vector counters, bool cycleCounter) { + if (counters.size() != ETHOSU_PMU_EVENT_MAX){ + throw Exception("PMU event count is invalid."); + } + + pmuCounters = counters; + enableCycleCounter = cycleCounter; +} + +void Interpreter::Invoke(int64_t timeoutNanos) { + inference = make_shared(network, arenaBuffer, + pmuCounters, enableCycleCounter); + inference->wait(timeoutNanos); + + if (inference->status() != InferenceStatus::OK) { + throw Exception("Failed to invoke."); + } +} + +std::vector Interpreter::GetPmuCounters() { + return inference->getPmuCounters(); +} + +uint64_t Interpreter::GetCycleCounter() { + return inference->getCycleCounter(); +} + +std::vector Interpreter::GetInputInfo() { + std::vector ret; + auto types = network->getIfmTypes(); + auto shapes = network->getIfmShapes(); + + for (int i = 0; i < network->getInputCount(); i ++) { + ret.push_back(TensorInfo{types[i], shapes[i]}); + } + + return ret; +} + +std::vector Interpreter::GetOutputInfo(){ + std::vector ret; + auto types = network->getOfmTypes(); + auto shapes = network->getOfmShapes(); + + for (int i = 0; i < network->getOutputCount(); i ++) { + ret.push_back(TensorInfo{types[i], shapes[i]}); + } + + return ret; +} + +} // namespace EthosU + +#endif // EI_ETHOS_LINUX diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h new file mode 100644 index 0000000..ae3efbc --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2020-2023 Arm Limited. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + * SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note + */ + +#ifndef ETHOSU_H +#define ETHOSU_H + +/**************************************************************************** + * Includes + ****************************************************************************/ + +#include +#include +#include + +#ifdef __cplusplus +namespace EthosU { +#endif + +/**************************************************************************** + * Defines + ****************************************************************************/ + +#define ETHOSU_IOCTL_BASE 0x01 +#define ETHOSU_IO(nr) _IO(ETHOSU_IOCTL_BASE, nr) +#define ETHOSU_IOR(nr, type) _IOR(ETHOSU_IOCTL_BASE, nr, type) +#define ETHOSU_IOW(nr, type) _IOW(ETHOSU_IOCTL_BASE, nr, type) +#define ETHOSU_IOWR(nr, type) _IOWR(ETHOSU_IOCTL_BASE, nr, type) + +#define ETHOSU_IOCTL_PING ETHOSU_IO(0x00) +#define ETHOSU_IOCTL_VERSION_REQ ETHOSU_IO(0x01) +#define ETHOSU_IOCTL_CAPABILITIES_REQ ETHOSU_IOR(0x02, \ + struct ethosu_uapi_device_capabilities) +#define ETHOSU_IOCTL_BUFFER_CREATE ETHOSU_IOR(0x10, \ + struct ethosu_uapi_buffer_create) +#define ETHOSU_IOCTL_BUFFER_SET ETHOSU_IOR(0x11, \ + struct ethosu_uapi_buffer) +#define ETHOSU_IOCTL_BUFFER_GET ETHOSU_IOW(0x12, \ + struct ethosu_uapi_buffer) +#define ETHOSU_IOCTL_NETWORK_CREATE ETHOSU_IOR(0x20, \ + struct ethosu_uapi_network_create) +#define ETHOSU_IOCTL_NETWORK_INFO ETHOSU_IOR(0x21, \ + struct ethosu_uapi_network_info) +#define ETHOSU_IOCTL_INFERENCE_CREATE ETHOSU_IOR(0x30, \ + struct ethosu_uapi_inference_create) +#define ETHOSU_IOCTL_INFERENCE_STATUS ETHOSU_IOR(0x31, \ + struct ethosu_uapi_result_status) +#define ETHOSU_IOCTL_INFERENCE_CANCEL ETHOSU_IOR(0x32, \ + struct ethosu_uapi_cancel_inference_status) + +/* Maximum number of IFM/OFM file descriptors per network */ +#define ETHOSU_FD_MAX 16 +/* Maximum number of dimensions for input and output */ +#define ETHOSU_DIM_MAX 8 + +/* Maximum number of PMUs available */ +#define ETHOSU_PMU_EVENT_MAX 4 + +/**************************************************************************** + * Types + ****************************************************************************/ + +/** + * enum ethosu_uapi_status - Status + */ +enum ethosu_uapi_status { + ETHOSU_UAPI_STATUS_OK, + ETHOSU_UAPI_STATUS_ERROR, + ETHOSU_UAPI_STATUS_RUNNING, + ETHOSU_UAPI_STATUS_REJECTED, + ETHOSU_UAPI_STATUS_ABORTED, + ETHOSU_UAPI_STATUS_ABORTING, +}; + +/** + * struct ethosu_uapi_buffer_create - Create buffer request + * @capacity: Maximum capacity of the buffer + */ +struct ethosu_uapi_buffer_create { + __u32 capacity; +}; + +/** + * struct ethosu_uapi_buffer - Buffer descriptor + * @offset: Offset to where the data starts + * @size: Size of the data + * + * 'offset + size' must not exceed the capacity of the buffer. + */ +struct ethosu_uapi_buffer { + __u32 offset; + __u32 size; +}; + +/** + * enum ethosu_uapi_network_create - Network buffer type. + * @ETHOSU_UAPI_NETWORK_BUFFER: Network is stored in a buffer handle. + * @ETHOSU_UAPI_NETWORK_INDEX: Network is built into firmware and referenced by + * index. + */ +enum ethosu_uapi_network_type { + ETHOSU_UAPI_NETWORK_BUFFER = 1, + ETHOSU_UAPI_NETWORK_INDEX +}; + +/** + * struct ethosu_uapi_network_create - Create network request + * @type: Buffer type. See @ethosu_uapi_network_type. + * @fd: Buffer file descriptor + * @index: Buffer index compiled into firmware binary. + */ +struct ethosu_uapi_network_create { + uint32_t type; + union { + __u32 fd; + __u32 index; + }; +}; + +/** + * struct ethosu_uapi_network_info - Network info + * @desc: Network description + * @ifm_count: Number of IFM buffers + * @ifm_size: IFM buffer sizes + * @ifm_types: IFM data types + * @ifm_offset: IFM data offset in arena + * @ifm_dims: IFM buffer dimensions + * @ifm_shapes: IFM buffer shapes + * @ofm_count: Number of OFM buffers + * @ofm_size: OFM buffer sizes + * @ofm_offset: OFM data offset in arena + * @ofm_dims: OFM buffer dimensions + * @ofm_shapes: OFM buffer shapes + */ +struct ethosu_uapi_network_info { + char desc[32]; + __u32 is_vela; + __u32 ifm_count; + __u32 ifm_size[ETHOSU_FD_MAX]; + __u32 ifm_types[ETHOSU_FD_MAX]; + __u32 ifm_offset[ETHOSU_FD_MAX]; + __u32 ifm_dims[ETHOSU_FD_MAX]; + __u32 ifm_shapes[ETHOSU_FD_MAX][ETHOSU_DIM_MAX]; + __u32 ofm_count; + __u32 ofm_size[ETHOSU_FD_MAX]; + __u32 ofm_types[ETHOSU_FD_MAX]; + __u32 ofm_offset[ETHOSU_FD_MAX]; + __u32 ofm_dims[ETHOSU_FD_MAX]; + __u32 ofm_shapes[ETHOSU_FD_MAX][ETHOSU_DIM_MAX]; +}; + +/** + * struct ethosu_uapi_pmu_config - Configure performance counters + * @events: Array of counters to configure, set to non-zero for + * each counter to enable corresponding event. + * @cycle_count: Set to enable the cycle counter. + */ +struct ethosu_uapi_pmu_config { + __u32 events[ETHOSU_PMU_EVENT_MAX]; + __u32 cycle_count; +}; + +/** + * struct ethosu_uapi_pmu_counts - Status of performance counters + * @events: Count for respective configured events. + * @cycle_count: Count for cycle counter. + */ +struct ethosu_uapi_pmu_counts { + __u32 events[ETHOSU_PMU_EVENT_MAX]; + __u64 cycle_count; +}; + +/** + * struct ethosu_uapi_device_hw_id - Device hardware identification + * @version_status: Version status + * @version_minor: Version minor + * @version_major: Version major + * @product_major: Product major + * @arch_patch_rev: Architecture version patch + * @arch_minor_rev: Architecture version minor + * @arch_major_rev: Architecture version major + */ +struct ethosu_uapi_device_hw_id { + __u32 version_status; + __u32 version_minor; + __u32 version_major; + __u32 product_major; + __u32 arch_patch_rev; + __u32 arch_minor_rev; + __u32 arch_major_rev; +}; + +/** + * struct ethosu_uapi_device_hw_cfg - Device hardware configuration + * @macs_per_cc: MACs per clock cycle + * @cmd_stream_version: NPU command stream version + * @custom_dma: Custom DMA enabled + */ +struct ethosu_uapi_device_hw_cfg { + __u32 macs_per_cc; + __u32 cmd_stream_version; + __u32 custom_dma; +}; + +/** + * struct ethosu_uapi_device_capabilities - Device capabilities + * @hw_id: Hardware identification + * @hw_cfg: Hardware configuration + * @driver_patch_rev: Driver version patch + * @driver_minor_rev: Driver version minor + * @driver_major_rev: Driver version major + */ +struct ethosu_uapi_device_capabilities { + struct ethosu_uapi_device_hw_id hw_id; + struct ethosu_uapi_device_hw_cfg hw_cfg; + __u32 driver_patch_rev; + __u32 driver_minor_rev; + __u32 driver_major_rev; +}; + +/** + * enum ethosu_uapi_inference_type - Inference type + */ +enum ethosu_uapi_inference_type { + ETHOSU_UAPI_INFERENCE_MODEL = 0, + ETHOSU_UAPI_INFERENCE_OP +}; + +/** + * struct ethosu_uapi_inference_create - Create network request + * @ifm_count: Number of IFM file descriptors + * @ifm_fd: IFM buffer file descriptors + * @ofm_count: Number of OFM file descriptors + * @ofm_fd: OFM buffer file descriptors + */ +struct ethosu_uapi_inference_create { + __u32 ifm_count; + __u32 ifm_fd[ETHOSU_FD_MAX]; + __u32 ofm_count; + __u32 ofm_fd[ETHOSU_FD_MAX]; + enum ethosu_uapi_inference_type inference_type; + struct ethosu_uapi_pmu_config pmu_config; +}; + +/** + * struct ethosu_uapi_result_status - Status of inference + * @status Status of run inference. + * @pmu_config Configured performance counters. + * @pmu_count Perfomance counters values, when status is + * ETHOSU_UAPI_STATUS_OK. + */ +struct ethosu_uapi_result_status { + enum ethosu_uapi_status status; + struct ethosu_uapi_pmu_config pmu_config; + struct ethosu_uapi_pmu_counts pmu_count; +}; + +/** + * struct ethosu_uapi_cancel_status - Status of inference cancellation. + * @status OK if inference cancellation was performed, ERROR otherwise. + */ +struct ethosu_uapi_cancel_inference_status { + enum ethosu_uapi_status status; +}; + +#ifdef __cplusplus +} /* namespace EthosU */ +#endif +#endif diff --git a/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c b/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c new file mode 100644 index 0000000..322f0c6 --- /dev/null +++ b/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c @@ -0,0 +1,16 @@ +#include "../ei_classifier_porting.h" +#if EI_PORTING_HIMAX_WE2 == 1 +#include "WE2_core.h" + +// Impelements weak functions from edge-impulse-sdk/porting/ethos-core-driver/src/ethosu_driver.c +void ethosu_flush_dcache(uint32_t *p, size_t bytes) +{ + hx_CleanDCache_by_Addr((volatile void *)p, bytes); +} + +void ethosu_invalidate_dcache(uint32_t *p, size_t bytes) +{ + hx_InvalidateDCache_by_Addr((volatile void *)p, bytes); +} + +#endif // #if EI_PORTING_HIMAX_WE2 == 1 \ No newline at end of file