From 932c4c856feb0a4b2db4b4b78e2a22cfbf7ab456 Mon Sep 17 00:00:00 2001 From: Artem Balyshev Date: Wed, 28 Feb 2024 13:34:20 +0300 Subject: [PATCH] [onert-micro] Add MaxPool2D This pr adds MaxPool2D refactored kernel into onert-micro. ONE-DCO-1.0-Signed-off-by: Artem Balyshev --- onert-micro/onert-micro/include/OMStatus.h | 1 + .../include/pal/common/PALMaxPool2DCommon.h | 95 +++++++++ .../include/pal/mcu/KernelsToBuild.lst | 3 + .../include/pal/mcu/PALMaxPool2D.h | 41 ++++ .../maxpool2d/FloatMaxPool2DKernel.h | 107 ++++++++++ .../maxpool2d/NegMaxPool2DKernel.h | 201 ++++++++++++++++++ .../maxpool2d/TestDataMaxPool2DBase.h | 60 ++++++ .../src/execute/kernels/MaxPool2D.cpp | 120 +++++++++++ .../src/import/kernels/MaxPool2D.cpp | 90 ++++++++ 9 files changed, 718 insertions(+) create mode 100644 onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h create mode 100644 onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h create mode 100644 onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h create mode 100644 onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp create mode 100644 onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp diff --git a/onert-micro/onert-micro/include/OMStatus.h b/onert-micro/onert-micro/include/OMStatus.h index b7a41116d27..c7d522a812d 100644 --- a/onert-micro/onert-micro/include/OMStatus.h +++ b/onert-micro/onert-micro/include/OMStatus.h @@ -30,6 +30,7 @@ enum OMStatus ModelNotImport, FailedCheckCondition, NoQuantization, + UnsupportedQuantizationType, UnsupportedDynamicShapeCase, }; diff --git a/onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h new file mode 100644 index 00000000000..65ddafec625 --- /dev/null +++ b/onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * Copyright 2020 The TensorFlow Authors. All Rights Reserved. + * + * 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. + */ + +#ifndef ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H +#define ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H + +#include "Params.h" +#include "PALUtils.h" + +#include "core/OMKernelData.h" + +namespace onert_micro +{ +namespace execute +{ +namespace pal +{ + +OMStatus MaxPool(const core::Pool2DParams ¶ms, const core::OMRuntimeShape &input_shape, + const float *input_data, const core::OMRuntimeShape &output_shape, + float *output_data) +{ + const int32_t batches = input_shape.dims(0); + const int32_t depth = output_shape.dims(3); + const int32_t input_height = input_shape.dims(1); + const int32_t input_width = input_shape.dims(2); + const int32_t output_height = output_shape.dims(1); + const int32_t output_width = output_shape.dims(2); + const int32_t stride_height = params.stride_h; + const int32_t stride_width = params.stride_w; + for (int batch = 0; batch < batches; ++batch) + { + for (int out_y = 0; out_y < output_height; ++out_y) + { + for (int out_x = 0; out_x < output_width; ++out_x) + { + for (int channel = 0; channel < depth; ++channel) + { + const int in_x_origin = (out_x * stride_width) - params.pad_w; + const int in_y_origin = (out_y * stride_height) - params.pad_h; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = std::min(params.filter_w, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = std::min(params.filter_h, input_height - in_y_origin); + float max = std::numeric_limits::lowest(); + for (int filter_y = filter_y_start; filter_y < filter_y_end; ++filter_y) + { + for (int filter_x = filter_x_start; filter_x < filter_x_end; ++filter_x) + { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + + const int input_data_offset = + ((batch * input_shape.dims(1) + in_y) * input_shape.dims(2) + in_x) * + input_shape.dims(3) + + channel; + + max = std::max(max, input_data[input_data_offset]); + } + } + const int output_data_offset = + ((batch * output_shape.dims(1) + out_y) * output_shape.dims(2) + out_x) * + output_shape.dims(3) + + channel; + + output_data[output_data_offset] = + std::min(std::max(max, params.activation_min), params.activation_max); + } + } + } + } + return Ok; +} + +} // namespace pal +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H diff --git a/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst b/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst index 5bc3135af80..1b565002c68 100644 --- a/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst +++ b/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst @@ -2,3 +2,6 @@ REGISTER_KERNEL(ABS, Abs) REGISTER_KERNEL(ADD, Add) REGISTER_KERNEL(LOGISTIC, Logistic) REGISTER_KERNEL(CONCATENATION, Concatenation) +REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D) +REGISTER_KERNEL(MUL, Mul) +REGISTER_KERNEL(SUB, Sub) diff --git a/onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h b/onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h new file mode 100644 index 00000000000..3b17008b8e6 --- /dev/null +++ b/onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * Copyright 2020 The TensorFlow Authors. All Rights Reserved. + * + * 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. + */ + +#ifndef ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H +#define ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H + +#include "PALMaxPool2DCommon.h" + +namespace onert_micro +{ +namespace execute +{ +namespace pal +{ + +OMStatus MaxPool(const core::Pool2DParams &, const core::OMRuntimeShape &, const uint8_t *, + const core::OMRuntimeShape &, uint8_t *, circle::TensorType) +{ + assert(false && "Not impl yet"); + return UnsupportedType; +} + +} // namespace pal +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h b/onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h new file mode 100644 index 00000000000..536399139b4 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#ifndef ONERT_MICRO_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H +#define ONERT_MICRO_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H + +#include "TestDataMaxPool2DBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace maxpool2d_float +{ +/* + * maxpool2d Kernel: + * + * Input(1, 3, 5, 1) + * | + * MaxPool2D + * | + * Output(1, 2, 2, 1) + */ +const unsigned char test_kernel_model_circle[] = { + 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xbc, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xa8, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x96, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x39, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd0, 0xfe, 0xff, 0xff, 0xd4, 0xfe, 0xff, 0xff, 0xd8, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xba, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, + 0x11, 0x00, 0x00, 0x00, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, + 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x78, 0x3a, 0x30, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, + 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00}; + +const std::vector input_data = { + 1, -1, 0, -2, 2, // + -7, -6, -5, -4, -3, // + 5, 4, 3, 6, 7, // +}; + +const std::vector reference_output_data{ + 1, 2, // + 5, 7, // +}; + +} // namespace maxpool2d_float + +class TestDataFloatMaxPool2D : public TestDataMaxPool2DBase +{ +public: + TestDataFloatMaxPool2D() + { + _input_data = maxpool2d_float::input_data; + _reference_output_data = maxpool2d_float::reference_output_data; + _test_kernel_model_circle = maxpool2d_float::test_kernel_model_circle; + } + + ~TestDataFloatMaxPool2D() override = default; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h b/onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h new file mode 100644 index 00000000000..a0c4fda2e05 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#ifndef ONERT_MICRO_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H +#define ONERT_MICRO_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H + +#include "TestDataMaxPool2DBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace neg_maxpool2d_kernel +{ +/* + * maxpool2d Kernel with input_type != output_type: + * + * Input(1, 8, 8, 1) = Float32 + * | + * MaxPool2D + * | + * Output(1, 7, 7, 1) = Int32 + */ +const unsigned char test_kernel_model_circle[] = { + 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, + 0x65, 0x00, 0x00, 0x00}; +} // namespace neg_maxpool2d_kernel + +namespace neg_invalid_input_shape_maxpool2d_kernel +{ +/* + * maxpool2d Kernel with invalid input shape rank=5 (should be == 4): + * + * Input(1, 1, 8, 8, 1) = Int32 + * | + * MaxPool2D + * | + * Output(1, 7, 7, 1) = Int32 + */ +const unsigned char test_kernel_model_circle[] = { + 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, 0x74, 0x65, 0x32, 0x63, + 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00}; +} // namespace neg_invalid_input_shape_maxpool2d_kernel + +namespace neg_no_quant_params_maxpool2d_kernel +{ +/* + * maxpool2d Kernel S16 without quant params: + * + * Input(1, 1, 8, 8, 1) = INT16 + * | + * MaxPool2D (no quant params) + * | + * Output(1, 7, 7, 1) = INT16 + */ +const unsigned char test_kernel_model_circle[] = { + 0x18, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xfc, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0f, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x4e, 0x45, 0x2d, 0x74, 0x66, 0x6c, 0x69, + 0x74, 0x65, 0x32, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x00, 0x00, 0x00}; +} // namespace neg_no_quant_params_maxpool2d_kernel + +class NegTestDataInputOutputTypeMismatchMaxPool2DKernel : public NegTestDataBase +{ +public: + NegTestDataInputOutputTypeMismatchMaxPool2DKernel() + { + _test_kernel_model_circle = neg_maxpool2d_kernel::test_kernel_model_circle; + } + + ~NegTestDataInputOutputTypeMismatchMaxPool2DKernel() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +class NegTestDataInvalidInputShapeMaxPool2DKernel : public NegTestDataBase +{ +public: + NegTestDataInvalidInputShapeMaxPool2DKernel() + { + _test_kernel_model_circle = neg_invalid_input_shape_maxpool2d_kernel::test_kernel_model_circle; + } + + ~NegTestDataInvalidInputShapeMaxPool2DKernel() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +class NegTestDataNoQuantParamsMaxPool2DKernel : public NegTestDataBase +{ +public: + NegTestDataNoQuantParamsMaxPool2DKernel() + { + _test_kernel_model_circle = neg_no_quant_params_maxpool2d_kernel::test_kernel_model_circle; + } + + ~NegTestDataNoQuantParamsMaxPool2DKernel() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h b/onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h new file mode 100644 index 00000000000..1acb897370e --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#ifndef ONERT_MICRO_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H +#define ONERT_MICRO_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H + +#include "test_models/TestDataBase.h" + +namespace onert_micro +{ +namespace test_model +{ + +template class TestDataMaxPool2DBase : public TestDataBase +{ +public: + TestDataMaxPool2DBase() = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + + const std::vector &get_input_data_by_index(int i) override final + { + switch (i) + { + case 0: + return _input_data; + default: + assert(false && "Wrong input index"); + } + } + + const std::vector &get_output_data_by_index(int i) override final + { + assert(i == 0); + return _reference_output_data; + } + +protected: + std::vector _input_data; + std::vector _reference_output_data; + const unsigned char *_test_kernel_model_circle; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H diff --git a/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp new file mode 100644 index 00000000000..78f8b72a9e1 --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#include "OMStatus.h" + +#include "core/OMUtils.h" +#include "core/OMKernelData.h" + +#include "execute/OMKernelExecutionBuilder.h" +#include "execute/OMUtils.h" +#include "execute/OMRuntimeKernel.h" + +#include "PALMaxPool2D.h" + +using namespace onert_micro; +using namespace onert_micro::execute; + +namespace +{ + +constexpr uint32_t inputTensorIdx = 0; +constexpr uint32_t outputTensorIdx = 0; + +} // namespace + +// NOTE: doesnt currently support dynamic shapes +OMStatus onert_micro::execute::execute_kernel_CircleMaxPool2D(const OMExecuteArgs &execute_args) +{ + core::OMRuntimeContext &runtime_context = execute_args.runtime_context; + core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage; + uint16_t op_index = execute_args.kernel_index; + + const circle::Tensor *input = nullptr; + const circle::Tensor *output = nullptr; + + uint8_t *input_data = nullptr; + uint8_t *output_data = nullptr; + + OMStatus status = Ok; + + const circle::Pool2DOptions *options = nullptr; + { + OMRuntimeKernel runtime_kernel; + runtime_kernel.readKernel(op_index, runtime_context); + + input = runtime_kernel.inputs[inputTensorIdx]; + output = runtime_kernel.outputs[outputTensorIdx]; + + assert(input != nullptr); + assert(output != nullptr); + + status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); + if (status != Ok) + return status; + + input_data = runtime_kernel.inputs_data[inputTensorIdx]; + output_data = runtime_kernel.outputs_data[outputTensorIdx]; + + options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); + } + + assert(input_data != nullptr); + assert(output_data != nullptr); + assert(options != nullptr); + + core::OMRuntimeShape input_shape(input); + + int32_t padding_h = 0; + int32_t padding_w = 0; + + const int input_width = input_shape.dims(2); + const int input_height = input_shape.dims(1); + execute::computePaddingHeightWidth( + options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */, + 1 /* dilation_rate_width */, input_height, input_width, options->filter_height(), + options->filter_width(), options->padding(), &padding_h, &padding_w); + + core::Pool2DParams params{}; + params.pad_h = padding_h; + params.pad_w = padding_w; + params.stride_h = options->stride_h(); + params.stride_w = options->stride_w(); + params.filter_h = options->filter_height(); + params.filter_w = options->filter_width(); + + switch (input->type()) + { +#ifndef DIS_FLOAT + case circle::TensorType_FLOAT32: + { + calculateActivationRange(options->fused_activation_function(), ¶ms.activation_min, + ¶ms.activation_max); + status = + pal::MaxPool(params, input_shape, core::utils::castInputData(input_data), + core::OMRuntimeShape(output), core::utils::castOutputData(output_data)); + } + break; +#endif // DIS_FLOAT + default: + { + status = UnsupportedType; + assert(false && "Unsupported type."); + } + } + + return status; +} diff --git a/onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp new file mode 100644 index 00000000000..ca8c590fdd3 --- /dev/null +++ b/onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#include "OMStatus.h" + +#include "core/OMUtils.h" +#include "core/OMKernelData.h" + +#include "import/OMKernelConfigureBuilder.h" + +#include "execute/OMRuntimeKernel.h" +#include "execute/OMUtils.h" + +using namespace onert_micro; +using namespace onert_micro::core; + +namespace +{ + +constexpr uint32_t inputTensorIdx = 0; +constexpr uint32_t outputTensorIdx = 0; + +} // namespace + +OMStatus onert_micro::import::configure_kernel_CircleMaxPool2D(const OMConfigureArgs &config_args) +{ + OMRuntimeContext &runtime_context = config_args.runtime_context; + uint16_t op_index = config_args.kernel_index; + + onert_micro::execute::OMRuntimeKernel runtime_kernel; + + OMStatus status = runtime_kernel.readKernel(op_index, runtime_context); + if (status != Ok) + return status; + + const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx]; + const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx]; + + assert(input != nullptr); + assert(output != nullptr); + + status = utils::checkCondition(input->type() == output->type()); + if (status != Ok) + return status; + + OMRuntimeShape input_shape(input); + OMRuntimeShape output_shape(output); + + status = utils::checkCondition(input_shape.dimensionsCount() == output_shape.dimensionsCount()); + if (status != Ok) + return status; + + status = utils::checkCondition(input_shape.dimensionsCount() == 4); + + auto option = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); + + if (option == nullptr) + return UnknownError; + + assert(option != nullptr); + + if (input->type() != circle::TensorType_INT8 and input->type() != circle::TensorType_INT16) + return status; + + // Check quantization params + if (input->quantization() == nullptr) + { + return NoQuantization; + } + + if (input->quantization()->scale()->size() != 1) + { + return UnsupportedType; + } + + return status; +}