From 94ade5e6371287212fcafcb4011039394fcd7357 Mon Sep 17 00:00:00 2001 From: Artem Balyshev Date: Mon, 19 Feb 2024 13:06:59 +0300 Subject: [PATCH] [onert-micro] Add Concatenation kernel This pr adds first Concatenation kernel with common PALUtils. ONE-DCO-1.0-Signed-off-by: Artem Balyshev --- .../include/pal/common/PALConcatenation.h | 74 ++++++ .../onert-micro/include/pal/common/PALUtils.h | 219 ++++++++++++++++++ .../concatenation/FloatConcatenationKernel.h | 105 +++++++++ .../concatenation/IntConcatenationKernel.h | 168 ++++++++++++++ .../concatenation/NegConcatenationKernel.h | 215 +++++++++++++++++ .../concatenation/TestDataConcatenationBase.h | 63 +++++ .../src/execute/kernels/Concatenation.cpp | 117 ++++++++++ .../kernels/tests/Concatenation.test.cpp | 84 +++++++ .../src/import/kernels/Concatenation.cpp | 94 ++++++++ 9 files changed, 1139 insertions(+) create mode 100644 onert-micro/onert-micro/include/pal/common/PALConcatenation.h create mode 100644 onert-micro/onert-micro/include/pal/common/PALUtils.h create mode 100644 onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h create mode 100644 onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp create mode 100644 onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp create mode 100644 onert-micro/onert-micro/src/import/kernels/Concatenation.cpp diff --git a/onert-micro/onert-micro/include/pal/common/PALConcatenation.h b/onert-micro/onert-micro/include/pal/common/PALConcatenation.h new file mode 100644 index 00000000000..dccfe18ac3c --- /dev/null +++ b/onert-micro/onert-micro/include/pal/common/PALConcatenation.h @@ -0,0 +1,74 @@ +/* + * 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_CONCATENATION_H +#define ONERT_MICRO_EXECUTE_PAL_CONCATENATION_H + +#include "PALUtils.h" + +namespace onert_micro +{ +namespace execute +{ +namespace pal +{ +template +OMStatus Concatenation(core::ConcatenationParams ¶ms, std::vector &input_shapes, + std::vector &input_data, + const core::OMRuntimeShape &output_shape, Scalar *output_data) +{ + int axis = params.axis; + int inputs_count = params.num_inputs; + const int concat_dimensions = output_shape.dimensionsCount(); + + int64_t concat_size = 0; + for (int i = 0; i < inputs_count; i++) + { + concat_size += input_shapes[i]; + } + int64_t outer_size = 1; + for (int i = 0; i < axis; ++i) + { + outer_size *= output_shape.dims(i); + } + // For all input arrays, + int64_t base_inner_size = 1; + for (int i = axis + 1; i < concat_dimensions; ++i) + { + base_inner_size *= output_shape.dims(i); + } + + Scalar *output_ptr = output_data; + for (int k = 0; k < outer_size; k++) + { + for (int i = 0; i < inputs_count; ++i) + { + const int copy_size = input_shapes[i] * base_inner_size; + const Scalar *input_ptr = input_data[i] + k * copy_size; + memcpy(output_ptr, input_ptr, copy_size * sizeof(Scalar)); + output_ptr += copy_size; + } + } + + return Ok; +} + +} // namespace pal +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_EXECUTE_PAL_CONCATENATION_H diff --git a/onert-micro/onert-micro/include/pal/common/PALUtils.h b/onert-micro/onert-micro/include/pal/common/PALUtils.h new file mode 100644 index 00000000000..d48e3cd54c7 --- /dev/null +++ b/onert-micro/onert-micro/include/pal/common/PALUtils.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * Copyright 2017 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_UTILS_H +#define ONERT_MICRO_EXECUTE_PAL_UTILS_H + +#include + +namespace onert_micro +{ +namespace execute +{ +namespace pal +{ + +// Table of sigmoid(i/24) at 0.16 format - 256 elements. +// We use combined sigmoid and tanh look-up table, since +// tanh(x) = 2*sigmoid(2*x) -1. +// Both functions are symmetric, so the LUT table is only needed +// for the absolute value of the input. +static const uint16_t sigmoid_table_uint16[256] = { + 32768, 33451, 34133, 34813, 35493, 36169, 36843, 37513, 38180, 38841, 39498, 40149, 40794, 41432, + 42064, 42688, 43304, 43912, 44511, 45102, 45683, 46255, 46817, 47369, 47911, 48443, 48964, 49475, + 49975, 50464, 50942, 51409, 51865, 52311, 52745, 53169, 53581, 53983, 54374, 54755, 55125, 55485, + 55834, 56174, 56503, 56823, 57133, 57433, 57724, 58007, 58280, 58544, 58800, 59048, 59288, 59519, + 59743, 59959, 60168, 60370, 60565, 60753, 60935, 61110, 61279, 61441, 61599, 61750, 61896, 62036, + 62172, 62302, 62428, 62549, 62666, 62778, 62886, 62990, 63090, 63186, 63279, 63368, 63454, 63536, + 63615, 63691, 63765, 63835, 63903, 63968, 64030, 64090, 64148, 64204, 64257, 64308, 64357, 64405, + 64450, 64494, 64536, 64576, 64614, 64652, 64687, 64721, 64754, 64786, 64816, 64845, 64873, 64900, + 64926, 64950, 64974, 64997, 65019, 65039, 65060, 65079, 65097, 65115, 65132, 65149, 65164, 65179, + 65194, 65208, 65221, 65234, 65246, 65258, 65269, 65280, 65291, 65301, 65310, 65319, 65328, 65337, + 65345, 65352, 65360, 65367, 65374, 65381, 65387, 65393, 65399, 65404, 65410, 65415, 65420, 65425, + 65429, 65433, 65438, 65442, 65445, 65449, 65453, 65456, 65459, 65462, 65465, 65468, 65471, 65474, + 65476, 65479, 65481, 65483, 65485, 65488, 65489, 65491, 65493, 65495, 65497, 65498, 65500, 65501, + 65503, 65504, 65505, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, + 65517, 65518, 65519, 65520, 65520, 65521, 65522, 65522, 65523, 65523, 65524, 65524, 65525, 65525, + 65526, 65526, 65526, 65527, 65527, 65528, 65528, 65528, 65529, 65529, 65529, 65529, 65530, 65530, + 65530, 65530, 65531, 65531, 65531, 65531, 65531, 65532, 65532, 65532, 65532, 65532, 65532, 65533, + 65533, 65533, 65533, 65533, 65533, 65533, 65533, 65534, 65534, 65534, 65534, 65534, 65534, 65534, + 65534, 65534, 65534, 65535}; + +inline std::int32_t saturatingRoundingDoublingHighMul(std::int32_t a, std::int32_t b) +{ + bool overflow = a == b && a == std::numeric_limits::min(); + std::int64_t a_64(a); + std::int64_t b_64(b); + std::int64_t ab_64 = a_64 * b_64; + std::int32_t nudge = ab_64 >= 0 ? (1 << 30) : (1 - (1 << 30)); + std::int32_t ab_x2_high32 = static_cast((ab_64 + nudge) / (1ll << 31)); + return overflow ? std::numeric_limits::max() : ab_x2_high32; +} + +// Correctly-rounded-to-nearest division by a power-of-two. +// Also known as a rounding arithmetic right shift. +inline int32_t roundingDivideByPOT(int32_t x, int32_t exponent) +{ + assert(exponent >= 0); + assert(exponent <= 31); + const int32_t mask = int32_t((1ll << exponent) - 1); + const int32_t zero = int32_t(0); + const int32_t one = int32_t(1); + const int32_t remainder = x & mask; + const int32_t threshold = (mask >> 1) + ((x < zero ? one : zero) & one); + return (x >> exponent) + ((remainder > threshold ? one : zero) & one); +} + +inline int32_t multiplyByQuantizedMultiplier(int32_t x, int32_t quantized_multiplier, int shift) +{ + int left_shift = shift > 0 ? shift : 0; + int right_shift = shift > 0 ? 0 : -shift; + return roundingDivideByPOT( + saturatingRoundingDoublingHighMul(x * (1 << left_shift), quantized_multiplier), right_shift); +} + +inline int32_t multiplyByQuantizedMultiplierSmallerThanOneExp(int32_t x, + int32_t quantized_multiplier, + int left_shift) +{ + return roundingDivideByPOT(saturatingRoundingDoublingHighMul(x, quantized_multiplier), + -left_shift); +} + +template inline void getActivationParams(const P ¶ms, int32_t *min, int32_t *max) +{ + *min = params.int32_activation_min; + *max = params.int32_activation_max; +} + +template inline void getActivationParams(const P ¶ms, float *min, float *max) +{ + *min = params.float_activation_min; + *max = params.float_activation_max; +} + +template inline void getActivationParams(const P ¶ms, int64_t *min, int64_t *max) +{ + *min = params.int64_activation_min; + *max = params.int64_activation_max; +} + +// Gets offset of index if reducing on axis. When reducing, the flattened offset +// will not change, if the input index changes on the given axis. For example, +// if you have a 3D tensor and you are reducing to 2D by eliminating axis 0, +// then index (0, 1, 2) and index (1, 1, 2) will map to the same flattened +// offset. +inline size_t reducedOutputOffset(const int32_t num_dims, const int32_t *dims, const int32_t *index, + const int32_t num_axis, const int32_t *axis) +{ + if (num_dims == 0) + { + return 0; + } + size_t offset = 0; + for (int idx = 0; idx < num_dims; ++idx) + { + // if we need to skip this axis + bool is_axis = false; + if (axis != nullptr) + { + for (int axis_idx = 0; axis_idx < num_axis; ++axis_idx) + { + if (idx == axis[axis_idx]) + { + is_axis = true; + break; + } + } + } + if (!is_axis) + { + offset = offset * static_cast(dims[idx]) + static_cast(index[idx]); + } + } + return offset; +} + +// Gets next index to iterate through a multidimensional array. +inline bool nextIndex(const int32_t num_dims, const int32_t *dims, int32_t *current) +{ + if (num_dims == 0) + { + return false; + } + int carry = 1; + for (int idx = num_dims - 1; idx >= 0; --idx) + { + int current_val = current[idx] + carry; + if (dims[idx] == current_val) + { + current[idx] = 0; + } + else + { + current[idx] = current_val; + carry = 0; + break; + } + } + return (carry == 0); +} + +// Get common shape dim, assert that they all agree. +inline int MatchingDim(const core::OMRuntimeShape &shape1, int index1, + const core::OMRuntimeShape &shape2, int index2) +{ + assert(shape1.dims(index1) == shape2.dims(index2)); + return shape1.dims(index1); +} + +// Data is required to be contiguous, and so many operators can use either the +// full array flat size or the flat size with one dimension skipped (commonly +// the depth). +inline int flatSizeSkipDim(const int32_t *dims_data, int skip_dim, int num_dims) +{ + int flat_size = 1; + for (int i = 0; i < num_dims; ++i) + { + flat_size *= (i == skip_dim) ? 1 : dims_data[i]; + } + return flat_size; +} + +inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3) +{ + return ((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3; +} + +inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3, int i4) +{ + return (((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3) * dims_data[4] + i4; +} + +template +inline T activationFunctionWithMinMax(T x, T output_activation_min, T output_activation_max) +{ + using std::max; + using std::min; + return min(max(x, output_activation_min), output_activation_max); +} + +} // namespace pal +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_EXECUTE_PAL_UTILS_H diff --git a/onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h new file mode 100644 index 00000000000..65fb2f26fcf --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h @@ -0,0 +1,105 @@ +/* + * 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_CONCATENATION_KERNEL_FLOAT_H +#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H + +#include "TestDataConcatenationBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace concatenation_float +{ + +/* + * Concatenation Kernel: + * + * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2) + * \ / + * Concatenation + * | + * Output(1, 4, 4, 3) + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x74, 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, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 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, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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 input1_data = { + -2.0978436, -25.836285, 7.9663463, -52.951416, -9.174321, -10.963295, 1.4337301, -39.000927, + -11.76153, -24.070623, -21.426125, -32.041714, -2.29292, -7.595441, -15.297459, -20.068735}; +const std::vector input2_data = { + -23.881905, -8.470397, -52.49611, -21.756306, 1.581161, -26.177217, -39.463478, -2.172443, + -30.588694, -7.90017, -17.604687, -27.376356, -26.49272, -15.772057, 8.418157, -36.710365, + -35.77088, -27.592611, -5.0617495, -7.8632812, 10.318075, -33.451294, -53.1594, -33.312737, + -6.132754, -21.647987, -38.427383, -41.75349, -22.417152, -1.243468, -19.772722, -55.897236}; +const std::vector reference_output_data = { + -2.0978436, -23.881905, -8.470397, -25.836285, -52.49611, -21.756306, 7.9663463, 1.581161, + -26.177217, -52.951416, -39.463478, -2.172443, -9.174321, -30.588694, -7.90017, -10.963295, + -17.604687, -27.376356, 1.4337301, -26.49272, -15.772057, -39.000927, 8.418157, -36.710365, + -11.76153, -35.77088, -27.592611, -24.070623, -5.0617495, -7.8632812, -21.426125, 10.318075, + -33.451294, -32.041714, -53.1594, -33.312737, -2.29292, -6.132754, -21.647987, -7.595441, + -38.427383, -41.75349, -15.297459, -22.417152, -1.243468, -20.068735, -19.772722, -55.897236}; + +} // namespace concatenation_float + +class TestDataFloatConcatenation : public TestDataConcatenationBase +{ +public: + TestDataFloatConcatenation() + { + _input1_data = concatenation_float::input1_data; + _input2_data = concatenation_float::input2_data; + _reference_output_data = concatenation_float::reference_output_data; + _test_kernel_model_circle = concatenation_float::test_kernel_model_circle; + } + + ~TestDataFloatConcatenation() override = default; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H diff --git a/onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h new file mode 100644 index 00000000000..8e8995c4794 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h @@ -0,0 +1,168 @@ +/* + * 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_CONCATENATION_KERNEL_INT_H +#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_INT_H + +#include "TestDataConcatenationBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace concatenation_int32 +{ + +/* + * Concatenation Kernel: + * + * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2) + * \ / + * Concatenation + * | + * Output(1, 4, 4, 3) + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x74, 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, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 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, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 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, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 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, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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 input1_data = {-9, -22, -32, 7, -23, -8, -23, -32, + -31, -25, -8, -22, -23, 1, -24, -32}; +const std::vector input2_data = {-29, -31, -8, -23, 16, -23, -38, 7, -36, -22, -32, + -24, -23, -18, -33, -23, -38, -24, -38, -14, -16, -13, + -15, -22, -38, -53, -5, -40, -23, -22, -23, -41}; +const std::vector reference_output_data = { + -9, -29, -31, -22, -8, -23, -32, 16, -23, 7, -38, 7, -23, -36, -22, -8, + -32, -24, -23, -23, -18, -32, -33, -23, -31, -38, -24, -25, -38, -14, -8, -16, + -13, -22, -15, -22, -23, -38, -53, 1, -5, -40, -24, -23, -22, -32, -23, -41}; + +} // namespace concatenation_int32 + +namespace concatenation_int64 +{ + +/* + * Concatenation Kernel: + * + * Input_1(1, 4, 4, 1) Input_2(1, 4, 4, 2) + * \ / + * Concatenation + * | + * Output(1, 4, 4, 3) + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x74, 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, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 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, 0x04, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 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, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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 input1_data = {35, 35, 35, 35, 30, 40, 45, 30, + 35, 35, 35, 40, 35, 30, 25, 30}; +const std::vector input2_data = {25, 35, 35, 30, 40, 35, 30, 35, 35, 35, 40, + 25, 35, 30, 40, 35, 35, 35, 30, 30, 35, 35, + 45, 50, 45, 35, 35, 40, 35, 35, 30, 35}; +const std::vector reference_output_data = { + 35, 25, 35, 35, 35, 30, 35, 40, 35, 35, 30, 35, 30, 35, 35, 40, 40, 25, 45, 35, 30, 30, 40, 35, + 35, 35, 35, 35, 30, 30, 35, 35, 35, 40, 45, 50, 35, 45, 35, 30, 35, 40, 25, 35, 35, 30, 30, 35}; + +} // namespace concatenation_int64 + +class TestDataS32Concatenation : public TestDataConcatenationBase +{ +public: + TestDataS32Concatenation() + { + _input1_data = concatenation_int32::input1_data; + _input2_data = concatenation_int32::input2_data; + _reference_output_data = concatenation_int32::reference_output_data; + _test_kernel_model_circle = concatenation_int32::test_kernel_model_circle; + } + + ~TestDataS32Concatenation() override = default; +}; + +class TestDataS64Concatenation : public TestDataConcatenationBase +{ +public: + TestDataS64Concatenation() + { + _input1_data = concatenation_int64::input1_data; + _input2_data = concatenation_int64::input2_data; + _reference_output_data = concatenation_int64::reference_output_data; + _test_kernel_model_circle = concatenation_int64::test_kernel_model_circle; + } + + ~TestDataS64Concatenation() override = default; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_INT_H diff --git a/onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h new file mode 100644 index 00000000000..add38b434f2 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h @@ -0,0 +1,215 @@ +/* + * 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_CONCATENATION_KERNEL_H +#define ONERT_MICRO_TEST_MODELS_NEG_CONCATENATION_KERNEL_H + +#include "TestDataConcatenationBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace input_type_mismatch_concatenation +{ + +/* + * Concatenation Kernel with input1 type != input2 type: + * + * Input_1(1, 4, 4, 1)- Int32 Input_2(1, 4, 4, 2) - Float32 + * \ / + * Concatenation + * | + * Output(1, 4, 4, 3) + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x68, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x74, 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, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 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, 0x02, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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 input_type_mismatch_concatenation + +namespace concatenation_with_relu +{ + +/* + * Concatenation Kernel with relu activation: + * + * Input_1(1, 4, 4, 1)- Float32 Input_2(1, 4, 4, 2) - Float32 + * \ / + * Concatenation(ReLU) + * | + * Output(1, 4, 4, 3) - Float32 + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x78, 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, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 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, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 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 concatenation_with_relu + +namespace concatenation_with_wrong_axis +{ + +/* + * Concatenation Kernel with wrong axis params: + * + * Input_1(1, 4, 4, 1)- Float32 Input_2(1, 4, 4, 2) - Float32 + * \ / + * Concatenation(axis = 6, should be < 4) + * | + * Output(1, 4, 4, 3) - Float32 + */ +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, + 0x34, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf4, 0xff, 0xff, 0xff, 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, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x78, 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, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 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, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 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 concatenation_with_wrong_axis + +class TestDataInputTypeMismatchConcatenation : public NegTestDataBase +{ +public: + TestDataInputTypeMismatchConcatenation() + { + _test_kernel_model_circle = input_type_mismatch_concatenation::test_kernel_model_circle; + } + + ~TestDataInputTypeMismatchConcatenation() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +class TestDataReluConcatenation : public NegTestDataBase +{ +public: + TestDataReluConcatenation() + { + _test_kernel_model_circle = concatenation_with_relu::test_kernel_model_circle; + } + + ~TestDataReluConcatenation() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +class TestDataWrongAxisConcatenation : public NegTestDataBase +{ +public: + TestDataWrongAxisConcatenation() + { + _test_kernel_model_circle = concatenation_with_wrong_axis::test_kernel_model_circle; + } + + ~TestDataWrongAxisConcatenation() 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_CONCATENATION_KERNEL_H diff --git a/onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h b/onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h new file mode 100644 index 00000000000..c76bca06600 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h @@ -0,0 +1,63 @@ +/* + * 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_CONCATENATION_KERNEL_BASE_H +#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_BASE_H + +#include "test_models/TestDataBase.h" + +namespace onert_micro +{ +namespace test_model +{ + +template class TestDataConcatenationBase : public TestDataBase +{ +public: + TestDataConcatenationBase() = 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 _input1_data; + case 1: + return _input2_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 _input1_data; + std::vector _input2_data; + std::vector _reference_output_data; + const unsigned char *_test_kernel_model_circle; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_BASE_H diff --git a/onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp b/onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp new file mode 100644 index 00000000000..b4ed31ec999 --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp @@ -0,0 +1,117 @@ +/* + * 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 "core/OMUtils.h" +#include "core/OMRuntimeShape.h" +#include "core/OMKernelData.h" + +#include "execute/OMUtils.h" +#include "execute/OMKernelExecutionBuilder.h" +#include "execute/OMRuntimeKernel.h" + +#include "OMStatus.h" +#include "PALConcatenation.h" + +using namespace onert_micro; +using namespace onert_micro::execute; + +namespace +{ + +constexpr uint32_t numOutput = 1; + +template OMStatus evalGeneric(OMRuntimeKernel &runtime_kernel) +{ + auto output = runtime_kernel.outputs[0]; + + const auto *options = runtime_kernel.first_operator->builtin_options_as_ConcatenationOptions(); + + core::OMRuntimeShape output_shape(output); + + int axis = options->axis(); + if (axis < 0) + axis += output_shape.dimensionsCount(); + + const auto input_size = runtime_kernel.inputs_num; + + std::vector all_input_data(input_size); + std::vector all_shape(input_size); + + OMStatus status = Ok; + for (int32_t i = 0; i < input_size; ++i) + { + const auto *tensor = runtime_kernel.inputs[i]; + core::OMRuntimeShape shape(tensor); + + uint8_t *tensor_data = runtime_kernel.inputs_data[i]; + all_input_data[i] = core::utils::castInputData(tensor_data); + all_shape[i] = shape.dims(axis); + } + + auto *output_data = core::utils::castOutputData(runtime_kernel.outputs_data[0]); + + core::ConcatenationParams params{}; + params.axis = axis; + params.num_inputs = input_size; + status = pal::Concatenation(params, all_shape, all_input_data, output_shape, output_data); + + return status; +} + +} // namespace + +OMStatus onert_micro::execute::execute_kernel_CircleConcatenation(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; + + execute::OMRuntimeKernel runtime_kernel; + runtime_kernel.readKernel(op_index, runtime_context); + + const auto *t0 = runtime_kernel.inputs[0]; + OMStatus status = Ok; + + status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); + + if (status != Ok) + return status; + + switch (t0->type()) + { +#ifndef DIS_FLOAT + case circle::TensorType_FLOAT32: + status = evalGeneric(runtime_kernel); + break; +#endif // DIS_FLOAT +#ifndef DIS_QUANT + case circle::TensorType_INT8: + status = evalGeneric(runtime_kernel); + break; +#endif // DIS_QUANT + case circle::TensorType_INT32: + status = evalGeneric(runtime_kernel); + break; + case circle::TensorType_INT64: + status = evalGeneric(runtime_kernel); + break; + default: + assert(false && "Unsupported type."); + status = UnsupportedType; + } + + return status; +} diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp new file mode 100644 index 00000000000..0d142568d53 --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp @@ -0,0 +1,84 @@ +/* + * 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 "execute/OMTestUtils.h" +#include "test_models/concatenation/FloatConcatenationKernel.h" +#include "test_models/concatenation/NegConcatenationKernel.h" +#include "test_models/concatenation/IntConcatenationKernel.h" + +namespace onert_micro +{ +namespace execute +{ +namespace testing +{ + +using namespace testing; + +class ConcatenationTest : public ::testing::Test +{ + // Do nothing +}; + +TEST_F(ConcatenationTest, INT64_P) +{ + test_model::TestDataS64Concatenation test_data_kernel; + std::vector output_data_vector = + onert_micro::execute::testing::checkKernel(2, &test_data_kernel); + EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0)); +} + +TEST_F(ConcatenationTest, INT32_P) +{ + test_model::TestDataS32Concatenation test_data_kernel; + std::vector output_data_vector = + onert_micro::execute::testing::checkKernel(2, &test_data_kernel); + EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0)); +} + +TEST_F(ConcatenationTest, Float_P) +{ + test_model::TestDataFloatConcatenation test_data_kernel; + std::vector output_data_vector = + onert_micro::execute::testing::checkKernel(2, &test_data_kernel); + EXPECT_THAT(output_data_vector, + FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f)); +} + +TEST_F(ConcatenationTest, Input_type_mismatch_NEG) +{ + test_model::TestDataInputTypeMismatchConcatenation test_data_kernel; + + EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), ""); +} + +TEST_F(ConcatenationTest, With_activation_NEG) +{ + test_model::TestDataReluConcatenation test_data_kernel; + + EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), ""); +} + +TEST_F(ConcatenationTest, Wrong_axis_NEG) +{ + test_model::TestDataWrongAxisConcatenation test_data_kernel; + + EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), ""); +} + +} // namespace testing +} // namespace execute +} // namespace onert_micro diff --git a/onert-micro/onert-micro/src/import/kernels/Concatenation.cpp b/onert-micro/onert-micro/src/import/kernels/Concatenation.cpp new file mode 100644 index 00000000000..fb632ad5cb1 --- /dev/null +++ b/onert-micro/onert-micro/src/import/kernels/Concatenation.cpp @@ -0,0 +1,94 @@ +/* + * 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 "import/OMKernelConfigureBuilder.h" +#include "core/OMUtils.h" +#include "OMStatus.h" +#include "execute/OMRuntimeKernel.h" + +#include "core/OMDataType.h" + +using namespace onert_micro; +using namespace onert_micro::core; + +OMStatus +onert_micro::import::configure_kernel_CircleConcatenation(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 int num_inputs = runtime_kernel.inputs_num; + + const auto *t0 = runtime_kernel.inputs[0]; + const auto *output = runtime_kernel.outputs[0]; + + const auto *params = runtime_kernel.first_operator->builtin_options_as_ConcatenationOptions(); + + // TODO: Support concat with fused activation function + if (params->fused_activation_function() != circle::ActivationFunctionType_NONE) + return UnknownError; + + OMRuntimeShape input_shape(t0); + int axis = params->axis(); + if (axis < 0) + axis += input_shape.dimensionsCount(); + + if (axis < 0 or axis > input_shape.dimensionsCount()) + return FailedCheckCondition; + + for (int i = 1; i < num_inputs; ++i) + { + const auto *tensor = runtime_kernel.inputs[i]; + if (tensor->type() != t0->type()) + return FailedCheckCondition; + } + + if (t0->type() != circle::TensorType_INT8 and t0->type() != circle::TensorType_INT16) + return Ok; + +#ifndef DIS_QUANT + // If input tensors are INT8 or INT16 type then quantization parameters of all input tensors and + // the output should be the same + for (int i = 0; i < num_inputs; ++i) + { + const auto *tensor = runtime_kernel.inputs[i]; + + if (tensor->quantization() == nullptr) + return FailedCheckCondition; + + if (tensor->quantization()->scale()->size() != 1) + return FailedCheckCondition; + + if (tensor->quantization()->zero_point()->size() != 1) + return FailedCheckCondition; + + if (*tensor->quantization()->scale()->begin() != *output->quantization()->scale()->begin()) + return FailedCheckCondition; + + if (*tensor->quantization()->zero_point()->begin() != + *output->quantization()->zero_point()->begin()) + return FailedCheckCondition; + } +#endif // DIS_QUANT + + return Ok; +}