From 71a197960e067506bcbd4e9c8176aba01180f904 Mon Sep 17 00:00:00 2001 From: Chunseok Lee Date: Tue, 31 Dec 2024 16:01:29 +0900 Subject: [PATCH 1/2] [onert-micro] Enable ReducedProd op - enable reduced product operation in onert-micro - Note that prevoious name for ReducedProd is ReducedCommon(?) ONE-DCO-1.0-Signed-off-by: Chunseok Lee --- .../include/pal/mcu/KernelsToBuild.lst | 2 +- .../include/pal/mcu/PALReduceCommon.h | 117 ++++++++++++ .../reduce_prod/NegReduceProdKernel.h | 150 +++++++++++++++ .../reduce_prod/ReduceProdKernel.h | 177 ++++++++++++++++++ .../reduce_prod/TestDataReduceProdBase.h | 60 ++++++ .../src/execute/kernels/ReduceProd.cpp | 136 ++++++++++++++ .../execute/kernels/tests/ReduceProd.test.cpp | 86 +++++++++ .../src/import/kernels/ReduceProd.cpp | 62 ++++++ 8 files changed, 789 insertions(+), 1 deletion(-) create mode 100644 onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h create mode 100644 onert-micro/onert-micro/include/test_models/reduce_prod/NegReduceProdKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/reduce_prod/ReduceProdKernel.h create mode 100644 onert-micro/onert-micro/include/test_models/reduce_prod/TestDataReduceProdBase.h create mode 100644 onert-micro/onert-micro/src/execute/kernels/ReduceProd.cpp create mode 100644 onert-micro/onert-micro/src/execute/kernels/tests/ReduceProd.test.cpp create mode 100644 onert-micro/onert-micro/src/import/kernels/ReduceProd.cpp diff --git a/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst b/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst index 23dbddc7eb5..b9c9c1ae5ea 100644 --- a/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst +++ b/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst @@ -38,7 +38,7 @@ REGISTER_KERNEL(PAD, Pad) REGISTER_KERNEL(RESHAPE, Reshape) REGISTER_KERNEL(RELU, Relu) REGISTER_KERNEL(RELU6, Relu6) -#/*REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)*/ +REGISTER_KERNEL(REDUCE_PROD, ReduceProd) #/*REGISTER_KERNEL(REDUCE_MAX, ReduceMax)*/ REGISTER_KERNEL(ROUND, Round) REGISTER_KERNEL(LESS, Less) diff --git a/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h b/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h new file mode 100644 index 00000000000..17e294e20d8 --- /dev/null +++ b/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 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_PAL_TANH_H +#define ONERT_MICRO_PAL_TANH_H + +#include "PALUtils.h" + +namespace onert_micro +{ +namespace execute +{ +namespace pal +{ + +// This method parses the input 'axis' to remove duplicates and handle negative +// values, and returns a valid 'out_axis' +inline bool resolveAxis(const int num_dims, const int *axis, const int64_t num_axis, + int *out_num_axis) +{ + int out_axis[2]; + *out_num_axis = 0; // Just in case. + // Short-circuit axis resolution for scalars; the axis will go unused. + if (num_dims == 0) + { + return true; + } + // o(n^2) is fine since out_num_axis should be really small, mostly <= 4 + for (int64_t idx = 0; idx < num_axis; ++idx) + { + // Handle negative index. A positive index 'p_idx' can be represented as a + // negative index 'n_idx' as: n_idx = p_idx-num_dims + // eg: For num_dims=3, [0, 1, 2] is the same as [-3, -2, -1] */ + int current = axis[idx] < 0 ? (axis[idx] + num_dims) : axis[idx]; + if (current < 0 || current >= num_dims) + { + return false; + } + bool is_dup = false; + for (int j = 0; j < *out_num_axis; ++j) + { + if (out_axis[j] == current) + { + is_dup = true; + break; + } + } + if (!is_dup) + { + out_axis[*out_num_axis] = current; + *out_num_axis += 1; + } + } + return true; +} + +// Computes the generic value (i.e., sum/max/min/prod) of elements across +// dimensions given in axis. It needs to pass in init_value and reducer. +template +inline void ReduceGeneric(const T *input_data, const int *input_dims, const int input_num_dims, + T *output_data, const int *axis, const int64_t num_axis_dimensions, + T init_value, const int output_flat_size, T reducer(const T, const T)) +{ + // Return early when input shape has zero dim. + for (int i = 0; i < input_num_dims; ++i) + { + if (input_dims[i] == 0) + return; + } + + for (size_t idx = 0; idx < output_flat_size; ++idx) + { + output_data[idx] = init_value; + } + + // Resolve axis. + int num_resolved_axis = 0; + if (!resolveAxis(input_num_dims, axis, num_axis_dimensions, &num_resolved_axis)) + { + return; + } + + int temp_index[5]; + // Reset input iterator. + for (int idx = 0; idx < input_num_dims; ++idx) + { + temp_index[idx] = 0; + } + // Iterate through input_data. + do + { + size_t input_offset = reducedOutputOffset(input_num_dims, input_dims, temp_index, 0, nullptr); + size_t output_offset = + reducedOutputOffset(input_num_dims, input_dims, temp_index, num_resolved_axis, axis); + output_data[output_offset] = reducer(output_data[output_offset], input_data[input_offset]); + } while (nextIndex(input_num_dims, input_dims, temp_index)); +} + +} // namespace pal +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_PAL_TANH_H diff --git a/onert-micro/onert-micro/include/test_models/reduce_prod/NegReduceProdKernel.h b/onert-micro/onert-micro/include/test_models/reduce_prod/NegReduceProdKernel.h new file mode 100644 index 00000000000..9a3de3473c1 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/reduce_prod/NegReduceProdKernel.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 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_REDUCE_PROD_KERNEL_H +#define ONERT_MICRO_TEST_MODELS_NEG_REDUCE_PROD_KERNEL_H + +#include "TestDataReduceProdBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace neg_input_wrong_type_mismatch_reduce_prod_kernel +{ +/* + * ReduceProd Kernel with wrong input type: + * + * Input(5, 5) - Int16 Axis(1) + * \ / + * ReduceProd(keep_dims=false) + * | + * Output(5) + */ +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, + 0x4c, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 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, + 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 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, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 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, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 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, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 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, 0x51, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 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_input_wrong_type_mismatch_reduce_prod_kernel + +namespace neg_axis_wrong_type_mismatch_reduce_prod_kernel +{ +/* + * ReduceProd Kernel with wrong axis type: + * + * Input(5, 5) Axis(1) - Float32 + * \ / + * ReduceProd(keep_dims=false) + * | + * Output(5) + */ +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, + 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, + 0x8c, 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x94, 0xff, 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, + 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x68, 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, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, + 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x00, 0x00, 0x00, 0x01, 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, + 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 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, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 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_axis_wrong_type_mismatch_reduce_prod_kernel + +class NegTestDataWrongInputTypeReduceProdKernel : public NegTestDataBase +{ +public: + NegTestDataWrongInputTypeReduceProdKernel() + { + _test_kernel_model_circle = + neg_input_wrong_type_mismatch_reduce_prod_kernel::test_kernel_model_circle; + } + + ~NegTestDataWrongInputTypeReduceProdKernel() override = default; + + const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; } + +protected: + const unsigned char *_test_kernel_model_circle; +}; + +class NegTestDataWrongAxisTypeReduceProdKernel : public NegTestDataBase +{ +public: + NegTestDataWrongAxisTypeReduceProdKernel() + { + _test_kernel_model_circle = + neg_axis_wrong_type_mismatch_reduce_prod_kernel::test_kernel_model_circle; + } + + ~NegTestDataWrongAxisTypeReduceProdKernel() 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_REDUCE_PROD_KERNEL_H diff --git a/onert-micro/onert-micro/include/test_models/reduce_prod/ReduceProdKernel.h b/onert-micro/onert-micro/include/test_models/reduce_prod/ReduceProdKernel.h new file mode 100644 index 00000000000..18a40aeb579 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/reduce_prod/ReduceProdKernel.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023 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_REDUCE_PROD_KERNEL_H +#define ONERT_MICRO_TEST_MODELS_REDUCE_PROD_KERNEL_H + +#include "TestDataReduceProdBase.h" + +namespace onert_micro +{ +namespace test_model +{ +namespace reduce_prod_float +{ +/* + * ReduceProd Kernel: + * + * Input(5, 5) Axis(1) + * \ / + * ReduceProd(keep_dims=false) + * | + * Output(5) + */ +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, + 0xd0, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xbc, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x08, 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, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0xda, 0xff, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xcc, 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, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 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, 0x1b, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0xff, 0xff, 0xff, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x92, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x14, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x73, + 0x74, 0x00, 0x00, 0x00, 0x01, 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, 0x1c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, + 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 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, 0x51, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 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 = {11.411349, -16.127048, 2.1805973, 2.4134026, -24.384453, + 7.066084, -2.4375877, -6.3261166, 12.296496, -5.2269707, + -1.1958504, 39.85154, 11.011908, -15.1922455, -5.623905, + 12.9133, 17.127638, -5.8921337, 32.048306, -1.0499363, + 3.921646, -0.9553833, 0.16646576, -19.362396, 2.1621552}; + +const std::vector reference_output_data = {-4.8831299e+03, -2.5635121e+04, 1.4899535e+02, + 2.7976750e+05, 1.6272373e+03}; +} // namespace reduce_prod_float + +namespace reduce_prod_int +{ +/* + * ReduceProd Kernel: + * + * Input(5, 5) Axis(1) + * \ / + * ReduceProd(keep_dims=false) + * | + * Output(5) + */ +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, + 0xd0, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xbc, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x08, 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, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, 0xda, 0xff, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xfe, 0xff, 0xff, 0xd4, 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, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x64, 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, 0x1b, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x9e, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x50, 0x72, 0x6f, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xce, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, + 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 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, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 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 = {-2, -3, -5, 15, -11, 5, 5, 5, 7, 15, -12, 5, 5, + -3, 15, 22, -5, 24, 5, -13, -6, -4, -5, -3, 24}; + +const std::vector reference_output_data = {-15840, -1500, 15000, 4725, 772200}; +} // namespace reduce_prod_int + +class TestDataFloatReduceProd : public TestDataReduceProdBase +{ +public: + TestDataFloatReduceProd() + { + _input_data = reduce_prod_float::input_data; + _reference_output_data = reduce_prod_float::reference_output_data; + _test_kernel_model_circle = reduce_prod_float::test_kernel_model_circle; + } + + ~TestDataFloatReduceProd() override = default; +}; + +class TestDataIntReduceProd : public TestDataReduceProdBase +{ +public: + TestDataIntReduceProd() + { + _input_data = reduce_prod_int::input_data; + _reference_output_data = reduce_prod_int::reference_output_data; + _test_kernel_model_circle = reduce_prod_int::test_kernel_model_circle; + } + + ~TestDataIntReduceProd() override = default; +}; + +} // namespace test_model +} // namespace onert_micro + +#endif // ONERT_MICRO_TEST_MODELS_REDUCE_PROD_KERNEL_H diff --git a/onert-micro/onert-micro/include/test_models/reduce_prod/TestDataReduceProdBase.h b/onert-micro/onert-micro/include/test_models/reduce_prod/TestDataReduceProdBase.h new file mode 100644 index 00000000000..a3d1819fe63 --- /dev/null +++ b/onert-micro/onert-micro/include/test_models/reduce_prod/TestDataReduceProdBase.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 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_REDUCE_PROD_KERNEL_BASE_H +#define ONERT_MICRO_TEST_MODELS_REDUCE_PROD_KERNEL_BASE_H + +#include "test_models/TestDataBase.h" + +namespace onert_micro +{ +namespace test_model +{ + +template class TestDataReduceProdBase : public TestDataBase +{ +public: + TestDataReduceProdBase() = 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_REDUCE_PROD_KERNEL_BASE_H diff --git a/onert-micro/onert-micro/src/execute/kernels/ReduceProd.cpp b/onert-micro/onert-micro/src/execute/kernels/ReduceProd.cpp new file mode 100644 index 00000000000..88fa76173b5 --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/ReduceProd.cpp @@ -0,0 +1,136 @@ +/* + * 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/OMUtils.h" +#include "execute/OMKernelExecutionBuilder.h" +#include "OMStatus.h" +#include "execute/OMRuntimeKernel.h" +#include "core/OMUtils.h" + +#include "core/OMRuntimeShape.h" +#include "PALReduceCommon.h" + +using namespace onert_micro; +using namespace onert_micro::execute; + +namespace +{ + +constexpr uint32_t input1TensorIdx = 0; +constexpr uint32_t input2TensorIdx = 1; +constexpr uint32_t outputTensorIdx = 0; + +template +void reduceProdGeneric(core::OMRuntimeShape &input_shape, const T *input_data, + core::OMRuntimeShape &axis_shape, const int *axis_data, + core::OMRuntimeShape &output_shape, T *output_data, bool keep_dims) +{ + onert_micro::execute::pal::ReduceGeneric( + input_data, input_shape.dimsData(), input_shape.dimensionsCount(), output_data, axis_data, + axis_shape.dimensionsCount(), + /*init_value=*/T(1), output_shape.flatSize(), + [](const T current, const T in) -> T { return in * current; }); +} + +} // namespace + +namespace onert_micro +{ +namespace execute +{ + +OMStatus execute_kernel_CircleReduceProd(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; + const circle::Tensor *axis; + const circle::Tensor *output; + + uint8_t *input_data; + uint8_t *axis_data; + uint8_t *output_data; + + uint16_t input_index = 0; + uint16_t axis_index = 0; + + const circle::ReducerOptions *options; + // Read kernel + { + execute::OMRuntimeKernel runtime_kernel; + runtime_kernel.readKernel(op_index, runtime_context); + + input = runtime_kernel.inputs[input1TensorIdx]; + axis = runtime_kernel.inputs[input2TensorIdx]; + output = runtime_kernel.outputs[outputTensorIdx]; + assert(input != nullptr); + assert(axis != nullptr); + assert(output != nullptr); + + runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); + + input_data = runtime_kernel.inputs_data[input1TensorIdx]; + axis_data = runtime_kernel.inputs_data[input2TensorIdx]; + output_data = runtime_kernel.outputs_data[outputTensorIdx]; + assert(input_data != nullptr); + assert(axis_data != nullptr); + assert(output_data != nullptr); + + options = runtime_kernel.first_operator->builtin_options_as_ReducerOptions(); + + input_index = runtime_kernel.inputs_index[input1TensorIdx]; + axis_index = runtime_kernel.inputs_index[input2TensorIdx]; + } + + OMStatus status; + + core::OMRuntimeShape input_shape(input); + core::OMRuntimeShape axis_shape(axis); + core::OMRuntimeShape output_shape(output); + + switch (input->type()) + { +#ifndef DIS_FLOAT + case circle::TensorType_FLOAT32: + reduceProdGeneric(input_shape, core::utils::castInputData(input_data), + axis_shape, core::utils::castInputData(axis_data), output_shape, + core::utils::castOutputData(output_data), + options->keep_dims()); + break; +#endif // DIS_FLOAT + case circle::TensorType_INT32: + reduceProdGeneric(input_shape, core::utils::castInputData(input_data), + axis_shape, core::utils::castInputData(axis_data), + output_shape, core::utils::castOutputData(output_data), + options->keep_dims()); + break; + case circle::TensorType_INT64: + reduceProdGeneric(input_shape, core::utils::castInputData(input_data), + axis_shape, core::utils::castInputData(axis_data), + output_shape, core::utils::castOutputData(output_data), + options->keep_dims()); + break; + default: + assert(false && "Unsupported type"); + } + + return status; +} + +} // namespace execute +} // namespace onert_micro diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/ReduceProd.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/ReduceProd.test.cpp new file mode 100644 index 00000000000..14224edfe3f --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/tests/ReduceProd.test.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 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/reduce_prod/ReduceProdKernel.h" +#include "test_models/reduce_prod/NegReduceProdKernel.h" + +namespace onert_micro +{ +namespace execute +{ +namespace testing +{ + +using namespace testing; + +class ReduceProdTest : public ::testing::Test +{ + // Do nothing +}; + +template +std::vector checkReduceProdKernel(test_model::TestDataReduceProdBase *test_data_base) +{ + onert_micro::OMInterpreter interpreter; + onert_micro::OMConfig config; + + interpreter.importModel(reinterpret_cast(test_data_base->get_model_ptr()), config); + + interpreter.reset(); + interpreter.allocateInputs(); + + T *input_data = reinterpret_cast(interpreter.getInputDataAt(0)); + + std::copy(test_data_base->get_input_data_by_index(0).begin(), + test_data_base->get_input_data_by_index(0).end(), input_data); + interpreter.run(config); + + T *output_data = reinterpret_cast(interpreter.getOutputDataAt(0)); + const size_t num_elements = interpreter.getOutputSizeAt(0); + std::vector output_data_vector(output_data, output_data + num_elements); + return output_data_vector; +} + +TEST_F(ReduceProdTest, Float_P) +{ + test_model::TestDataFloatReduceProd test_data_kernel; + std::vector output_data_vector = checkReduceProdKernel(&test_data_kernel); + EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0)); +} + +TEST_F(ReduceProdTest, Int_P) +{ + test_model::TestDataIntReduceProd test_data_int_reduce_prod; + std::vector output_data_vector = checkReduceProdKernel(&test_data_int_reduce_prod); + EXPECT_THAT(output_data_vector, test_data_int_reduce_prod.get_output_data_by_index(0)); +} + +TEST_F(ReduceProdTest, Wrong_input_type_NEG) +{ + test_model::NegTestDataWrongInputTypeReduceProdKernel test_data_kernel; + EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), ""); +} + +TEST_F(ReduceProdTest, Wrong_axis_type_NEG) +{ + test_model::NegTestDataWrongAxisTypeReduceProdKernel 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/ReduceProd.cpp b/onert-micro/onert-micro/src/import/kernels/ReduceProd.cpp new file mode 100644 index 00000000000..3f61d4791cb --- /dev/null +++ b/onert-micro/onert-micro/src/import/kernels/ReduceProd.cpp @@ -0,0 +1,62 @@ +/* + * 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/helpers/OMConfigureTISOKernel.h" + +using namespace onert_micro; +using namespace onert_micro::core; + +namespace +{ + +constexpr uint32_t inputTensorIdx = 0; +constexpr uint32_t axisTensorIdx = 1; +constexpr uint32_t outputTensorIdx = 0; + +} // namespace + +namespace onert_micro +{ +namespace import +{ + +OMStatus configure_kernel_CircleReduceProd(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 *axis = runtime_kernel.inputs[axisTensorIdx]; + const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx]; + + assert(input != nullptr); + assert(axis != nullptr); + assert(output != nullptr); + + status = utils::checkCondition(axis->type() == circle::TensorType_INT32); + status = utils::checkCondition(input->type() == output->type()); + + return status; +} + +} // namespace import +} // namespace onert_micro From a3676545adc2bb7118f09aa52a57cf94e329d673 Mon Sep 17 00:00:00 2001 From: Chunseok Lee Date: Fri, 3 Jan 2025 16:31:16 +0900 Subject: [PATCH 2/2] fix buffer overflow --- onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h b/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h index 17e294e20d8..43080e2dde9 100644 --- a/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h +++ b/onert-micro/onert-micro/include/pal/mcu/PALReduceCommon.h @@ -61,6 +61,9 @@ inline bool resolveAxis(const int num_dims, const int *axis, const int64_t num_a } if (!is_dup) { + if (*out_num_axis > 1) { + return false; + } out_axis[*out_num_axis] = current; *out_num_axis += 1; }