From 1ae1a40020021e52b56acc2b003d51e047d45d50 Mon Sep 17 00:00:00 2001 From: Artem Balyshev Date: Thu, 28 Sep 2023 13:57:55 +0300 Subject: [PATCH] [onert-micro] Add float BatchToSpaceND kernels This commit adds float BatchToSpaceND kernels for onert-micro. ONE-DCO-1.0-Signed-off-by: Artem Balyshev --- .../FloatBatchToSpaceNDKernel.h | 96 ++++++++++++++++ .../NegBatchToSpaceNDKernel.h | 97 +++++++++++++++++ .../TestDataBatchToSpaceNDBase.h | 60 ++++++++++ .../pal/cmsisnn/KernelsToBuild.lst | 1 + .../pal/common/PALBatchToSpaceND.h | 101 +++++++++++++++++ .../pal/mcu/KernelsToBuild.lst | 1 + .../src/kernels/BatchToSpaceND.cpp | 98 ++++++----------- .../src/kernels/BatchToSpaceND.h | 45 -------- .../src/kernels/BatchToSpaceND.test.cpp | 103 ++++++++---------- 9 files changed, 432 insertions(+), 170 deletions(-) create mode 100644 onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h create mode 100644 onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h create mode 100644 onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h create mode 100644 onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h delete mode 100644 onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h new file mode 100644 index 00000000000..464fa297a90 --- /dev/null +++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h @@ -0,0 +1,96 @@ +/* + * 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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H +#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H + +#include "TestDataBatchToSpaceNDBase.h" + +namespace luci_interpreter +{ +namespace test_kernel +{ +namespace batch_to_space_nd_float +{ +/* + * BatchToSpaceND Kernel: + * + * Input(4, 1, 1, 1) + * | + * BatchToSpaceND + * | + * 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, + 0x68, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x64, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x6c, 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, 0x18, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x70, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68, + 0x61, 0x70, 0x65, 0x00, 0x01, 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, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x63, 0x72, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 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, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 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 = {13.344007, 88.19333, -0.350749, 45.71498}; +const std::vector reference_output_data = {13.344007, 88.19333, -0.350749, 45.71498}; + +} // namespace batch_to_space_nd_float + +class TestDataFloatBatchToSpaceND : public TestDataBatchToSpaceNDBase +{ +public: + TestDataFloatBatchToSpaceND() + { + _input_data = batch_to_space_nd_float::input_data; + _reference_output_data = batch_to_space_nd_float::reference_output_data; + _test_kernel_model_circle = batch_to_space_nd_float::test_kernel_model_circle; + } + + ~TestDataFloatBatchToSpaceND() override = default; +}; + +} // namespace test_kernel +} // namespace luci_interpreter + +#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h new file mode 100644 index 00000000000..fcbc36d17eb --- /dev/null +++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h @@ -0,0 +1,97 @@ +/* + * 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 LUCI_INTERPRETER_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H +#define LUCI_INTERPRETER_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H + +#include "luci_interpreter/test_models/TestDataBase.h" + +namespace luci_interpreter +{ +namespace test_kernel +{ +namespace neg_input_output_type_mismatch_batch_to_space_nd_kernel +{ +/* + * BatchToSpaceND kernel with input output type mismatch: + * + * Input(4, 1, 1, 1) - Float32 + * | + * BatchToSpaceND + * | + * Output(1, 2, 2 , 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, + 0x68, 0x00, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x64, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x6c, 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, 0x18, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x01, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x63, 0x72, 0x6f, 0x70, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 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, + 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, + 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_output_type_mismatch_batch_to_space_nd_kernel + +class NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel : public NegTestDataBase +{ +public: + NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel() + { + _test_kernel_model_circle = + neg_input_output_type_mismatch_batch_to_space_nd_kernel::test_kernel_model_circle; + } + + ~NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel() 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_kernel +} // namespace luci_interpreter + +#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h new file mode 100644 index 00000000000..c7689b6d0ad --- /dev/null +++ b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.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 LUCI_INTERPRETER_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H +#define LUCI_INTERPRETER_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H + +#include "luci_interpreter/test_models/TestDataBase.h" + +namespace luci_interpreter +{ +namespace test_kernel +{ + +template class TestDataBatchToSpaceNDBase : public TestDataBase +{ +public: + TestDataBatchToSpaceNDBase() = 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_kernel +} // namespace luci_interpreter + +#endif // LUCI_INTERPRETER_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToBuild.lst b/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToBuild.lst index b7a670b50dd..304db841902 100644 --- a/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToBuild.lst +++ b/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToBuild.lst @@ -3,6 +3,7 @@ REGISTER_KERNEL(ADD, Add) REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D) REGISTER_KERNEL(ARG_MAX, ArgMax) REGISTER_KERNEL(ARG_MIN, ArgMin) +REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND) REGISTER_KERNEL(DIV, Div) REGISTER_KERNEL(ADD_N, AddN) REGISTER_KERNEL(CONV_2D, Conv2D) diff --git a/onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h b/onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h new file mode 100644 index 00000000000..67d95f9ae5f --- /dev/null +++ b/onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h @@ -0,0 +1,101 @@ +/* + * 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 LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H +#define LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H + +#include "Params.h" +#include "PALUtils.h" + +#include + +namespace luci_interpreter_pal +{ +namespace +{ +inline luci_interpreter::RuntimeShape +extendShapeBatchToSpace(const luci_interpreter::RuntimeShape &shape) +{ + if (shape.dimensionsCount() == 4) + { + return shape; + } + luci_interpreter::RuntimeShape new_shape(4, 1); + new_shape.setDim(0, shape.dims(0)); + new_shape.setDim(1, shape.dims(1)); + new_shape.setDim(3, shape.dims(2)); + return new_shape; +} +} // namespace + +template +inline void BatchToSpaceND( + const luci_interpreter::RuntimeShape &unextended_input1_shape, const T *input1_data, + const luci_interpreter::RuntimeShape &unextended_input2_shape, const int32_t *block_shape_data, + const luci_interpreter::RuntimeShape &unextended_input3_shape, const int32_t *crops_data, + const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data) +{ + const luci_interpreter::RuntimeShape input1_shape = + extendShapeBatchToSpace(unextended_input1_shape); + const luci_interpreter::RuntimeShape output_shape = + extendShapeBatchToSpace(unextended_output_shape); + + const int output_width = output_shape.dims(2); + const int output_height = output_shape.dims(1); + const int output_batch_size = output_shape.dims(0); + + const int depth = input1_shape.dims(3); + const int input_width = input1_shape.dims(2); + const int input_height = input1_shape.dims(1); + const int input_batch_size = input1_shape.dims(0); + + const int block_shape_height = block_shape_data[0]; + const int block_shape_width = + unextended_input1_shape.dimensionsCount() == 4 ? block_shape_data[1] : 1; + const int crops_top = crops_data[0]; + const int crops_left = unextended_input1_shape.dimensionsCount() == 4 ? crops_data[2] : 0; + for (int in_batch = 0; in_batch < input_batch_size; ++in_batch) + { + const int out_batch = in_batch % output_batch_size; + const int spatial_offset = in_batch / output_batch_size; + for (int in_h = 0; in_h < input_height; ++in_h) + { + const int out_h = in_h * block_shape_height + spatial_offset / block_shape_width - crops_top; + if (out_h < 0 || out_h >= output_height) + { + continue; + } + for (int in_w = 0; in_w < input_width; ++in_w) + { + const int out_w = + in_w * block_shape_width + spatial_offset % block_shape_width - crops_left; + + if (out_w < 0 || out_w >= output_width) + { + continue; + } + T *out = output_data + offset(output_shape.dimsData(), out_batch, out_h, out_w, 0); + const T *in = input1_data + offset(input1_shape.dimsData(), in_batch, in_h, in_w, 0); + memcpy(out, in, depth * sizeof(T)); + } + } + } +} + +} // namespace luci_interpreter_pal + +#endif // LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H diff --git a/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst b/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst index e9d13cb1363..857df7753d7 100644 --- a/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst +++ b/onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst @@ -3,6 +3,7 @@ REGISTER_KERNEL(ADD, Add) REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D) REGISTER_KERNEL(ARG_MAX, ArgMax) REGISTER_KERNEL(ARG_MIN, ArgMin) +REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND) REGISTER_KERNEL(DIV, Div) REGISTER_KERNEL(DEPTHWISE_CONV_2D, DepthwiseConv2D) REGISTER_KERNEL(ADD_N, AddN) diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.cpp b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.cpp index 9ebe28991a9..747c39cfef7 100644 --- a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.cpp +++ b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.cpp @@ -15,90 +15,54 @@ * limitations under the License. */ -#include "kernels/BatchToSpaceND.h" +#include "Builders.h" #include "kernels/Utils.h" +#include "MISOKernel.h" #include "PALBatchToSpaceND.h" namespace luci_interpreter { -namespace kernels -{ - -namespace -{ -const int kInputMinDimensionNum = 3; -const int kInputMaxDimensionNum = 4; -} // namespace - -BatchToSpaceND::BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops, - Tensor *output) - : Kernel({input, block_shape, crops}, {output}) +void configure_kernel_CircleBatchToSpaceND(const circle::Operator *cur_op, + BaseRuntimeGraph *runtime_graph) { + kernels::MISOKernel kernel(cur_op, runtime_graph); + + LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) == + Tensor::element_type(kernel.output())); + LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32); + LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input3()) == DataType::S32); + LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) >= 3); + LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) >= 3); + LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) <= 4); + LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) <= 4); } -void BatchToSpaceND::configure() +void execute_kernel_CircleBatchToSpaceND(const circle::Operator *cur_op, + BaseRuntimeGraph *runtime_graph) { + kernels::MISOKernel kernel(cur_op, runtime_graph); - const auto *block_shape_data = block_shape()->data(); - const auto *crops_data = crops()->data(); - LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= kInputMinDimensionNum); - LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= kInputMaxDimensionNum); - LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type()); - - int spatial_dims_num = input()->shape().num_dims() - 2; - - LUCI_INTERPRETER_CHECK(block_shape()->shape().num_dims() == 1); - LUCI_INTERPRETER_CHECK(block_shape()->shape().dim(0) == spatial_dims_num); - - LUCI_INTERPRETER_CHECK(crops()->shape().num_dims() == 2); - LUCI_INTERPRETER_CHECK(crops()->shape().dim(0) == spatial_dims_num); - LUCI_INTERPRETER_CHECK(crops()->shape().dim(1) == 2); - for (int i = 0; i < spatial_dims_num * 2; ++i) - { - LUCI_INTERPRETER_CHECK(crops_data[i] >= 0); - } - - Shape output_shape = Shape(input()->shape().num_dims()); - int output_batch_size = input()->shape().dim(0); - for (int i = 0; i < spatial_dims_num; ++i) - { - LUCI_INTERPRETER_CHECK(output_batch_size % block_shape_data[i] == 0); - output_batch_size = output_batch_size / block_shape_data[i]; - output_shape.dim(i + 1) = - input()->shape().dim(i + 1) * block_shape_data[i] - crops_data[i * 2] - crops_data[i * 2 + 1]; - } - - output_shape.dim(0) = output_batch_size; - output_shape.dim(input()->shape().num_dims() - 1) = - input()->shape().dim(input()->shape().num_dims() - 1); - - // TODO: enable it only if kernel with dynamic shapes - output()->resize(output_shape); -} - -void BatchToSpaceND::execute() const -{ - switch (input()->element_type()) + switch (Tensor::element_type(kernel.input1())) { +#ifndef DIS_FLOAT case DataType::FLOAT32: + { luci_interpreter_pal::BatchToSpaceND( - getTensorShape(input()), getTensorData(input()), getTensorShape(block_shape()), - getTensorData(block_shape()), getTensorShape(crops()), - getTensorData(crops()), getTensorShape(output()), getTensorData(output())); - break; - case DataType::U8: - luci_interpreter_pal::BatchToSpaceND( - getTensorShape(input()), getTensorData(input()), getTensorShape(block_shape()), - getTensorData(block_shape()), getTensorShape(crops()), - getTensorData(crops()), getTensorShape(output()), - getTensorData(output())); + kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph), + kernels::getTensorData(runtime_graph->getDataByTensor(kernel.input1())), + kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph), + kernels::getTensorData(runtime_graph->getConstDataByTensor(kernel.input2())), + kernels::getTensorRuntimeShape(kernel.input3(), runtime_graph), + kernels::getTensorData(runtime_graph->getConstDataByTensor(kernel.input3())), + kernels::getTensorRuntimeShape(kernel.output(), runtime_graph), + kernels::getTensorData(runtime_graph->getDataByTensor(kernel.output()))); break; + } +#endif // DIS_FLOAT default: - assert(false && "Unsupported type."); + assert(false && "Unsupported type"); } } - -} // namespace kernels } // namespace luci_interpreter diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h deleted file mode 100644 index 57703ea5d87..00000000000 --- a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2021 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 LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H -#define LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H - -#include "core/Kernel.h" - -namespace luci_interpreter -{ -namespace kernels -{ - -class BatchToSpaceND : public Kernel -{ -public: - BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops, - Tensor *output); - - const Tensor *input() const { return _inputs[0]; } - const Tensor *block_shape() const { return _inputs[1]; } - const Tensor *crops() const { return _inputs[2]; } - Tensor *output() const { return _outputs[0]; } - - void configure() override; - void execute() const override; -}; - -} // namespace kernels -} // namespace luci_interpreter - -#endif // LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp index 52647a763d3..783d93e969a 100644 --- a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp +++ b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp @@ -14,87 +14,74 @@ * limitations under the License. */ -#include "kernels/BatchToSpaceND.h" #include "kernels/TestUtils.h" -#include "luci_interpreter/TestMemoryManager.h" +#include "luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h" +#include "luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h" + +#include "loader/ModuleLoader.h" namespace luci_interpreter { -namespace kernels -{ namespace { using namespace testing; +class BatchToSpaceNDTest : public ::testing::Test +{ + // Do nothing +}; + template -void Check(std::initializer_list input_shape, - std::initializer_list block_shape_shape, - std::initializer_list crops_shape, std::initializer_list output_shape, - std::initializer_list input_data, std::initializer_list block_shape_data, - std::initializer_list crops_data, std::initializer_list output_data) +std::vector checkBatchToSpaceNDKernel(test_kernel::TestDataBase *test_data_base) { - std::unique_ptr memory_manager = std::make_unique(); - constexpr DataType element_type = getElementType(); - Tensor input_tensor = - makeInputTensor(input_shape, input_data, memory_manager.get()); - Tensor block_shape_tensor = - makeInputTensor(block_shape_shape, block_shape_data, memory_manager.get()); - Tensor crops_tensor = - makeInputTensor(crops_shape, crops_data, memory_manager.get()); - Tensor output_tensor = makeOutputTensor(element_type); + MemoryManager memory_manager{}; + RuntimeModule runtime_module{}; + bool dealloc_input = true; - BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor); - kernel.configure(); - memory_manager->allocate_memory(output_tensor); - kernel.execute(); + // Load model with single op + auto *model_data_raw = reinterpret_cast(test_data_base->get_model_ptr()); + ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input); - EXPECT_THAT(extractTensorData(output_tensor), ::testing::ElementsAreArray(output_data)); - EXPECT_THAT(extractTensorShape(output_tensor), output_shape); -} + auto *main_runtime_graph = runtime_module.getMainGraph(); + assert(main_runtime_graph->getNumOfInputTensors() == 1); -template class BatchToSpaceNDTest : public ::testing::Test -{ -}; + // Set input data + { + auto *input_tensor_data = reinterpret_cast(main_runtime_graph->configureGraphInput(0)); + std::copy(test_data_base->get_input_data_by_index(0).begin(), + test_data_base->get_input_data_by_index(0).end(), input_tensor_data); + } -using DataTypes = ::testing::Types; -TYPED_TEST_SUITE(BatchToSpaceNDTest, DataTypes); + runtime_module.execute(); -TYPED_TEST(BatchToSpaceNDTest, Simple) -{ - Check(/*input_shape=*/{4, 2, 2, 1}, /*block_shape_shape=*/{2}, /*crops_shape=*/{2, 2}, - /*output_shape=*/{1, 4, 4, 1}, - /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, - /*block_shape_data=*/{2, 2}, /*crops_data=*/{0, 0, 0, 0}, - /*output_data=*/{1, 5, 2, 6, 9, 13, 10, 14, 3, 7, 4, 8, 11, 15, 12, 16}); + assert(main_runtime_graph->getNumOfOutputTensors() == 1); + + T *output_data = reinterpret_cast(main_runtime_graph->getOutputDataByIndex(0)); + const size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T)); + std::vector output_data_vector(output_data, output_data + num_elements); + return output_data_vector; } -TEST(BatchToSpaceNDTest, Invalid_Shape_NEG) +TEST_F(BatchToSpaceNDTest, Float_P) { - std::unique_ptr memory_manager = std::make_unique(); - Tensor input_tensor = makeInputTensor( - {3, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, memory_manager.get()); - Tensor block_shape_tensor = makeInputTensor({2}, {2, 2}, memory_manager.get()); - Tensor crops_tensor = makeInputTensor({2, 2}, {0, 0, 0, 0}, memory_manager.get()); - Tensor output_tensor = makeOutputTensor(DataType::FLOAT32); - - BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor); - EXPECT_ANY_THROW(kernel.configure()); + test_kernel::TestDataFloatBatchToSpaceND test_data_kernel; + std::vector output_data_vector = checkBatchToSpaceNDKernel(&test_data_kernel); + EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear( + test_data_kernel.get_output_data_by_index(0), 0.0001f)); } -TEST(BatchToSpaceNDTest, Invalid_Crops_NEG) +TEST_F(BatchToSpaceNDTest, Input_output_type_mismatch_NEG) { - std::unique_ptr memory_manager = std::make_unique(); - Tensor input_tensor = makeInputTensor( - {4, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, memory_manager.get()); - Tensor block_shape_tensor = makeInputTensor({2}, {2, 2}, memory_manager.get()); - Tensor crops_tensor = makeInputTensor({2, 2}, {0, 0, -1, 0}, memory_manager.get()); - Tensor output_tensor = makeOutputTensor(DataType::FLOAT32); - - BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor); - EXPECT_ANY_THROW(kernel.configure()); + test_kernel::NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel test_data_kernel; + MemoryManager memory_manager{}; + RuntimeModule runtime_module{}; + bool dealloc_input = true; + // Load model with single op + auto *model_data_raw = reinterpret_cast(test_data_kernel.get_model_ptr()); + EXPECT_DEATH(ModuleLoader::load(&runtime_module, &memory_manager, model_data_raw, dealloc_input), + ""); } } // namespace -} // namespace kernels } // namespace luci_interpreter