summaryrefslogtreecommitdiff
path: root/runtime/onert/backend/cpu/kernel
diff options
context:
space:
mode:
authorChunseok Lee <chunseok.lee@samsung.com>2020-04-23 14:45:49 +0900
committerChunseok Lee <chunseok.lee@samsung.com>2020-04-23 14:45:49 +0900
commite2ef8438a24f7c56a0744eb579a6e293ee2fbf8e (patch)
tree44a1a7951d168dd4370e13593ed03f4bc6d920c5 /runtime/onert/backend/cpu/kernel
parent302e6564a7a76109e1178207e44e45a58631c477 (diff)
downloadnnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.tar.gz
nnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.tar.bz2
nnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.zip
Imported Upstream version 1.4.0upstream/1.4.0submit/tizen/20200423.054851
Diffstat (limited to 'runtime/onert/backend/cpu/kernel')
-rw-r--r--runtime/onert/backend/cpu/kernel/AbsLayer.cc67
-rw-r--r--runtime/onert/backend/cpu/kernel/AbsLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/AddLayer.cc96
-rw-r--r--runtime/onert/backend/cpu/kernel/AddLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc116
-rw-r--r--runtime/onert/backend/cpu/kernel/AvgPoolLayer.h81
-rw-r--r--runtime/onert/backend/cpu/kernel/CastLayer.cc108
-rw-r--r--runtime/onert/backend/cpu/kernel/CastLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/CompareLayer.cc180
-rw-r--r--runtime/onert/backend/cpu/kernel/CompareLayer.h65
-rw-r--r--runtime/onert/backend/cpu/kernel/ConcatLayer.cc134
-rw-r--r--runtime/onert/backend/cpu/kernel/ConcatLayer.h65
-rw-r--r--runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc159
-rw-r--r--runtime/onert/backend/cpu/kernel/ConvolutionLayer.h96
-rw-r--r--runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc136
-rw-r--r--runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h83
-rw-r--r--runtime/onert/backend/cpu/kernel/DivLayer.cc92
-rw-r--r--runtime/onert/backend/cpu/kernel/DivLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/ExpLayer.cc71
-rw-r--r--runtime/onert/backend/cpu/kernel/ExpLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc141
-rw-r--r--runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h81
-rw-r--r--runtime/onert/backend/cpu/kernel/GatherLayer.cc77
-rw-r--r--runtime/onert/backend/cpu/kernel/GatherLayer.h66
-rw-r--r--runtime/onert/backend/cpu/kernel/LogisticLayer.cc71
-rw-r--r--runtime/onert/backend/cpu/kernel/LogisticLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/MaxLayer.cc78
-rw-r--r--runtime/onert/backend/cpu/kernel/MaxLayer.h67
-rw-r--r--runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc113
-rw-r--r--runtime/onert/backend/cpu/kernel/MaxPoolLayer.h81
-rw-r--r--runtime/onert/backend/cpu/kernel/MinLayer.cc78
-rw-r--r--runtime/onert/backend/cpu/kernel/MinLayer.h67
-rw-r--r--runtime/onert/backend/cpu/kernel/MulLayer.cc92
-rw-r--r--runtime/onert/backend/cpu/kernel/MulLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/OneHotLayer.cc70
-rw-r--r--runtime/onert/backend/cpu/kernel/OneHotLayer.h73
-rw-r--r--runtime/onert/backend/cpu/kernel/OperationUtils.cc269
-rw-r--r--runtime/onert/backend/cpu/kernel/OperationUtils.h162
-rw-r--r--runtime/onert/backend/cpu/kernel/PackLayer.cc98
-rw-r--r--runtime/onert/backend/cpu/kernel/PackLayer.h65
-rw-r--r--runtime/onert/backend/cpu/kernel/PadLayer.cc70
-rw-r--r--runtime/onert/backend/cpu/kernel/PadLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/PermuteLayer.cc71
-rw-r--r--runtime/onert/backend/cpu/kernel/PermuteLayer.h209
-rw-r--r--runtime/onert/backend/cpu/kernel/ReduceLayer.cc137
-rw-r--r--runtime/onert/backend/cpu/kernel/ReduceLayer.h84
-rw-r--r--runtime/onert/backend/cpu/kernel/ReshapeLayer.cc55
-rw-r--r--runtime/onert/backend/cpu/kernel/ReshapeLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/RsqrtLayer.cc70
-rw-r--r--runtime/onert/backend/cpu/kernel/RsqrtLayer.h59
-rw-r--r--runtime/onert/backend/cpu/kernel/ShapeLayer.cc81
-rw-r--r--runtime/onert/backend/cpu/kernel/ShapeLayer.h61
-rw-r--r--runtime/onert/backend/cpu/kernel/SinLayer.cc69
-rw-r--r--runtime/onert/backend/cpu/kernel/SinLayer.h60
-rw-r--r--runtime/onert/backend/cpu/kernel/SliceLayer.cc111
-rw-r--r--runtime/onert/backend/cpu/kernel/SliceLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc173
-rw-r--r--runtime/onert/backend/cpu/kernel/SoftMaxLayer.h65
-rw-r--r--runtime/onert/backend/cpu/kernel/SplitLayer.cc98
-rw-r--r--runtime/onert/backend/cpu/kernel/SplitLayer.h66
-rw-r--r--runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc96
-rw-r--r--runtime/onert/backend/cpu/kernel/StridedSliceLayer.h78
-rw-r--r--runtime/onert/backend/cpu/kernel/SubLayer.cc92
-rw-r--r--runtime/onert/backend/cpu/kernel/SubLayer.h71
-rw-r--r--runtime/onert/backend/cpu/kernel/TanhLayer.cc71
-rw-r--r--runtime/onert/backend/cpu/kernel/TanhLayer.h63
-rw-r--r--runtime/onert/backend/cpu/kernel/TransposeLayer.cc81
-rw-r--r--runtime/onert/backend/cpu/kernel/TransposeLayer.h61
-rw-r--r--runtime/onert/backend/cpu/kernel/UnpackLayer.cc104
-rw-r--r--runtime/onert/backend/cpu/kernel/UnpackLayer.h66
70 files changed, 6290 insertions, 0 deletions
diff --git a/runtime/onert/backend/cpu/kernel/AbsLayer.cc b/runtime/onert/backend/cpu/kernel/AbsLayer.cc
new file mode 100644
index 000000000..770386826
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AbsLayer.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 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 "AbsLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Elementwise.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+AbsLayer::AbsLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void AbsLayer::absFloat32()
+{
+ nnfw::cker::Abs(convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void AbsLayer::absQuant8() { throw std::runtime_error{"NYI"}; }
+
+void AbsLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void AbsLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ absFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ absQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/AbsLayer.h b/runtime/onert/backend/cpu/kernel/AbsLayer.h
new file mode 100644
index 000000000..551782a45
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AbsLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 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 riting, 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_BACKEND_CPU_KERNEL_ABSLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_ABSLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class AbsLayer : public ::onert::exec::IFunction
+{
+public:
+ AbsLayer();
+
+public:
+ void absFloat32();
+
+ void absQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_ABSLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/AddLayer.cc b/runtime/onert/backend/cpu/kernel/AddLayer.cc
new file mode 100644
index 000000000..51320907d
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AddLayer.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019 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 "AddLayer.h"
+
+#include <cker/operation/BinaryArithmeticOps.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void AddLayer::addFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ nnfw::cker::BinaryArithmeticOpParam op_params;
+ op_params.type = nnfw::cker::BinaryArithmeticOpType::ADD;
+ op_params.float_activation_max = output_activation_max;
+ op_params.float_activation_min = output_activation_min;
+
+ if (!HaveSameShapes(_lhs, _rhs))
+ {
+ nnfw::cker::BroadcastBinaryArithmeticOpSlow(
+ op_params, convertToExtendedCkerShape(_lhs),
+ reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs),
+ reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ return;
+ }
+
+ nnfw::cker::BinaryArithmeticOp(
+ op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void AddLayer::addQuant8()
+{
+ int32_t output_activation_min, output_activation_max;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ // nnfw::cker::BinaryArithmeticOpParam op_params;
+ // op_params.quantized_activation_max = output_activation_max;
+ // op_params.quantized_activation_min = output_activation_min;
+
+ // cker quant8 add is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void AddLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ assert(lhs != nullptr);
+ assert(rhs != nullptr);
+ assert(output != nullptr);
+
+ _lhs = lhs;
+ _rhs = rhs;
+ _activation = activation;
+ _output = output;
+}
+
+void AddLayer::run()
+{
+ if (_lhs->data_type() == OperandType::FLOAT32)
+ {
+ addFloat32();
+ }
+ else if (_lhs->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ addQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/AddLayer.h b/runtime/onert/backend/cpu/kernel/AddLayer.h
new file mode 100644
index 000000000..657decc72
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AddLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_ADDLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_ADDLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class AddLayer : public ::onert::exec::IFunction
+{
+public:
+ AddLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void addFloat32();
+
+ void addQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+
+ ir::Activation _activation{ir::Activation::NONE};
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_ADDLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc
new file mode 100644
index 000000000..ba11b7cde
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2018 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 "AvgPoolLayer.h"
+
+#include <cker/operation/AveragePool.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+#define AVGPOOLING_PARAMETERS \
+ nnfw::cker::PoolParams op_params; \
+ op_params.stride_height = _strideHeight; \
+ op_params.stride_width = _strideWidth; \
+ op_params.filter_height = _kernelHeight; \
+ op_params.filter_width = _kernelWidth; \
+ op_params.padding_values.height = (int8_t)_paddingTop; \
+ op_params.padding_values.width = (int8_t)_paddingLeft;
+
+AvgPoolLayer::AvgPoolLayer()
+ : _input(nullptr), _output(nullptr), _paddingLeft(0), _paddingTop(0), _paddingRight(0),
+ _paddingBottom(0), _strideWidth(0), _strideHeight(0), _kernelWidth(0), _kernelHeight(0),
+ _activation(ir::Activation::NONE)
+{
+ // DO NOTHING
+}
+
+void AvgPoolLayer::averagePoolFloat32()
+{
+ AVGPOOLING_PARAMETERS
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::AveragePool(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+void AvgPoolLayer::averagePoolQuant8()
+{
+ AVGPOOLING_PARAMETERS
+ int32_t output_activation_min = 0;
+ int32_t output_activation_max = 0;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ op_params.quantized_activation_min = output_activation_min;
+ op_params.quantized_activation_max = output_activation_max;
+
+ nnfw::cker::AveragePool(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void AvgPoolLayer::configure(const operand::Tensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ operand::Tensor *output)
+{
+ assert(input != nullptr);
+ assert(output != nullptr);
+
+ _input = input;
+ _paddingLeft = paddingLeft;
+ _paddingRight = paddingRight;
+ _paddingTop = paddingTop;
+ _paddingBottom = paddingBottom;
+ _strideWidth = strideWidth;
+ _strideHeight = strideHeight;
+ _kernelWidth = kernelWidth;
+ _kernelHeight = kernelHeight;
+ _activation = activation;
+ _output = output;
+}
+
+void AvgPoolLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ averagePoolFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ averagePoolQuant8();
+ }
+}
+
+#undef AVGPOOLING_PARAMETERS
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h
new file mode 100644
index 000000000..7d7ef980d
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class AvgPoolLayer : public ::onert::exec::IFunction
+{
+public:
+ AvgPoolLayer();
+
+public:
+ void averagePoolFloat32();
+
+ void averagePoolQuant8();
+
+ void configure(const operand::Tensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+
+ uint32_t _paddingLeft;
+ uint32_t _paddingTop;
+ uint32_t _paddingRight;
+ uint32_t _paddingBottom;
+
+ uint32_t _strideWidth;
+ uint32_t _strideHeight;
+ uint32_t _kernelWidth;
+ uint32_t _kernelHeight;
+
+ ir::Activation _activation;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/CastLayer.cc b/runtime/onert/backend/cpu/kernel/CastLayer.cc
new file mode 100644
index 000000000..e485e04c7
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/CastLayer.cc
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2020 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 "CastLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+CastLayer::CastLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void CastLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+template <typename FromT, typename ToT> void CastLayer::castTensor(const FromT *in, ToT *out)
+{
+ auto input_shape = convertTensorToCkerShape(_input);
+ auto output_shape = convertTensorToCkerShape(_output);
+ const auto num_elements = MatchingFlatSize(input_shape, output_shape);
+
+ std::transform(in, in + num_elements, out, [](FromT a) { return static_cast<ToT>(a); });
+}
+
+template <typename FromT> void CastLayer::castPtr(const FromT *in, DataPtr out)
+{
+ switch (_output->data_type())
+ {
+ case ir::DataType::FLOAT32:
+ castTensor(in, out.f);
+ return;
+ case ir::DataType::INT32:
+ castTensor(in, out.i32);
+ return;
+ case ir::DataType::UINT32:
+ castTensor(in, out.u32);
+ return;
+ case ir::DataType::UINT8:
+ castTensor(in, out.u8);
+ return;
+ case ir::DataType::BOOL8:
+ castTensor(in, out.b);
+ return;
+ case ir::DataType::QUANT8_ASYMM:
+ case ir::DataType::QUANT8_SYMM:
+ throw std::runtime_error("Not supported output type" +
+ std::to_string((int)_output->data_type()));
+ }
+}
+
+void CastLayer::run()
+{
+ auto input_buf = _input->buffer();
+ auto output_buf = _output->buffer();
+ const auto in = *reinterpret_cast<const DataPtr *>(&input_buf);
+ auto out = *reinterpret_cast<DataPtr *>(&output_buf);
+
+ switch (_input->data_type())
+ {
+ case ir::DataType::FLOAT32:
+ castPtr(in.f, out);
+ return;
+ case ir::DataType::INT32:
+ castPtr(in.i32, out);
+ return;
+ case ir::DataType::UINT32:
+ castPtr(in.u32, out);
+ return;
+ case ir::DataType::UINT8:
+ castPtr(in.u8, out);
+ return;
+ case ir::DataType::BOOL8:
+ castPtr(in.b, out);
+ return;
+ case ir::DataType::QUANT8_ASYMM:
+ case ir::DataType::QUANT8_SYMM:
+ throw std::runtime_error("Not supported input type" +
+ std::to_string((int)_input->data_type()));
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/CastLayer.h b/runtime/onert/backend/cpu/kernel/CastLayer.h
new file mode 100644
index 000000000..4690e1007
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/CastLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_CASTLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_CASTLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class CastLayer : public ::onert::exec::IFunction
+{
+public:
+ CastLayer();
+
+public:
+ template <typename FromT, typename ToT> void castTensor(const FromT *in, ToT *out);
+ template <typename FromT> void castPtr(const FromT *in, DataPtr out);
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_CASTLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/CompareLayer.cc b/runtime/onert/backend/cpu/kernel/CompareLayer.cc
new file mode 100644
index 000000000..c8ee683b1
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/CompareLayer.cc
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2020 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 "CompareLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Comparison.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+namespace
+{
+
+using OpType = onert::ir::operation::Comparison::ComparisonType;
+using namespace onert::backend::cpu;
+
+template <typename T>
+void compareScalar(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output,
+ OpType op_type)
+{
+ bool requires_broadcast = !HaveSameShapes(lhs, rhs);
+
+ if (requires_broadcast)
+ {
+ switch (op_type)
+ {
+ case OpType::Equal:
+ Broadcast4DSlowEqual(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::NotEqual:
+ Broadcast4DSlowNotEqual(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::Greater:
+ Broadcast4DSlowGreater(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::GreaterEqual:
+ Broadcast4DSlowGreaterEqual(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::Less:
+ Broadcast4DSlowLess(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::LessEqual:
+ Broadcast4DSlowLessEqual(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ default:
+ throw std::runtime_error{"Invalid OpType for CompareLayer"};
+ }
+ }
+ else // if (requires_broadcast == false)
+ {
+ switch (op_type)
+ {
+ case OpType::Equal:
+ EqualNoScaling(convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output),
+ reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::NotEqual:
+ NotEqualNoScaling(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::Greater:
+ GreaterNoScaling(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::GreaterEqual:
+ GreaterEqualNoScaling(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::Less:
+ LessNoScaling(convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output),
+ reinterpret_cast<bool *>(output->buffer()));
+ break;
+ case OpType::LessEqual:
+ LessEqualNoScaling(
+ convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
+ convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
+ convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer()));
+ break;
+ default:
+ throw std::runtime_error{"Invalid OpType for CompareLayer"};
+ }
+ }
+ return;
+}
+} // namespace
+
+CompareLayer::CompareLayer()
+ : _lhs(nullptr), _rhs(nullptr), _output(nullptr),
+ _op_type(ir::operation::Comparison::ComparisonType::Equal)
+{
+ // DO NOTHING
+}
+
+void CompareLayer::compareQuant8() { throw std::runtime_error{"Compare NYI for quantized"}; }
+
+void CompareLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const OpType op_type, operand::Tensor *output)
+{
+ _lhs = lhs;
+ _rhs = rhs;
+ _op_type = op_type;
+ _output = output;
+}
+
+void CompareLayer::run()
+{
+ if (_lhs->data_type() == OperandType::FLOAT32)
+ {
+ compareScalar<float>(_lhs, _rhs, _output, _op_type);
+ }
+ else if (_lhs->data_type() == OperandType::INT32)
+ {
+ compareScalar<int32_t>(_lhs, _rhs, _output, _op_type);
+ }
+ else if (_lhs->data_type() == OperandType::BOOL8)
+ {
+ compareScalar<uint8_t>(_lhs, _rhs, _output, _op_type);
+ }
+ else if (_lhs->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ compareQuant8();
+ }
+ else
+ {
+ throw std::runtime_error{"Compare: unsupported data type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/CompareLayer.h b/runtime/onert/backend/cpu/kernel/CompareLayer.h
new file mode 100644
index 000000000..b62e5a2e4
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/CompareLayer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_COMPARELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_COMPARELAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+#include <ir/operation/Comparison.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class CompareLayer : public ::onert::exec::IFunction
+{
+public:
+ CompareLayer();
+
+public:
+ void compareQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::operation::Comparison::ComparisonType op_type, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+ ir::operation::Comparison::ComparisonType _op_type;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_COMPARELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ConcatLayer.cc b/runtime/onert/backend/cpu/kernel/ConcatLayer.cc
new file mode 100644
index 000000000..80a29e8ce
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ConcatLayer.cc
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2018 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 "ConcatLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Concatenation.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+ConcatLayer::ConcatLayer() : _inputs(), _output(nullptr), _axis(0)
+{
+ // DO NOTHING
+}
+
+void ConcatLayer::concatenationFloat32()
+{
+ uint32_t num_inputs = _inputs.size();
+
+ nnfw::cker::ConcatenationParams op_params;
+ op_params.axis = _axis;
+ op_params.inputs_count = num_inputs;
+
+ std::vector<nnfw::cker::Shape *> inputDimsPtr;
+ std::vector<nnfw::cker::Shape> inputDims;
+ inputDimsPtr.reserve(num_inputs);
+ inputDims.reserve(num_inputs);
+
+ for (uint32_t i = 0; i < num_inputs; i++)
+ {
+ inputDims.push_back(convertTensorToCkerShape(_inputs[i]));
+ inputDimsPtr.push_back(&inputDims[i]);
+ }
+
+ std::vector<const float *> inputFloatPtrs;
+
+ for (const auto input : _inputs)
+ {
+ inputFloatPtrs.emplace_back(reinterpret_cast<const float *>(input->buffer()));
+ }
+
+ nnfw::cker::Concatenation<float>(op_params, inputDimsPtr.data(), inputFloatPtrs.data(),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+void ConcatLayer::concatenationQuant8()
+{
+ uint32_t num_inputs = _inputs.size();
+
+ std::vector<int32_t> input_zeropoints(num_inputs);
+ std::vector<float> input_scales(num_inputs);
+ for (uint32_t i = 0; i < num_inputs; i++)
+ {
+ input_zeropoints[i] = _inputs[i]->offset();
+ input_scales[i] = _inputs[i]->scale();
+ }
+
+ nnfw::cker::ConcatenationParams op_params;
+ op_params.axis = _axis;
+ op_params.inputs_count = num_inputs;
+ op_params.input_zeropoint = input_zeropoints.data();
+ op_params.input_scale = input_scales.data();
+ op_params.output_zeropoint = _output->offset();
+ op_params.output_scale = _output->scale();
+
+ std::vector<nnfw::cker::Shape *> inputDimsPtr;
+ std::vector<nnfw::cker::Shape> inputDims;
+ inputDimsPtr.reserve(num_inputs);
+ inputDims.reserve(num_inputs);
+ for (uint32_t i = 0; i < num_inputs; i++)
+ {
+ inputDims.push_back(convertTensorToCkerShape(_inputs[i]));
+ inputDimsPtr.push_back(&inputDims[i]);
+ }
+
+ std::vector<const uint8_t *> inputDataPtrs;
+ for (const auto input : _inputs)
+ {
+ inputDataPtrs.emplace_back(reinterpret_cast<const uint8_t *>(input->buffer()));
+ }
+
+ nnfw::cker::ConcatenationWithScaling(op_params, inputDimsPtr.data(), inputDataPtrs.data(),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void ConcatLayer::configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis,
+ operand::Tensor *output)
+{
+ assert(inputs.size() > 0);
+ assert(output != nullptr);
+
+ _inputs = inputs;
+ _axis = axis;
+ _output = output;
+}
+
+void ConcatLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ concatenationFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ concatenationQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ConcatLayer.h b/runtime/onert/backend/cpu/kernel/ConcatLayer.h
new file mode 100644
index 000000000..1ac1604cf
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ConcatLayer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_CONCATLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_CONCATLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class ConcatLayer : public ::onert::exec::IFunction
+{
+public:
+ ConcatLayer();
+
+public:
+ void concatenationFloat32();
+
+ void concatenationQuant8();
+
+ void configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ std::vector<const operand::Tensor *> _inputs;
+ operand::Tensor *_output;
+ int32_t _axis;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_CONCATLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc
new file mode 100644
index 000000000..398054527
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018 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 "ConvolutionLayer.h"
+
+#include <cker/operation/Conv.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+ConvolutionLayer::ConvolutionLayer()
+ : _input(nullptr), _kernel(nullptr), _bias(nullptr), _output(nullptr),
+ _paddingType(ir::PaddingType::EXPLICIT), _paddingLeft(0), _paddingTop(0), _paddingRight(0),
+ _paddingBottom(0), _strideWidth(0), _strideHeight(0), _activation(ir::Activation::NONE),
+ _conv_kernel(new nnfw::cker::Conv()), _prepare(false)
+{
+ // DO NOTHING
+}
+
+ConvolutionLayer::~ConvolutionLayer() = default;
+
+void ConvolutionLayer::convFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+
+ nnfw::cker::ConvParams op_params;
+ op_params.padding_type = getPaddingType(_paddingType);
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = 1;
+ op_params.dilation_height_factor = 1;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::Conv &kernel = *_conv_kernel;
+ if (!_prepare)
+ {
+ bool is_replaced_weights = false;
+ kernel.prepare(convertTensorToCkerShape(_kernel),
+ reinterpret_cast<const float *>(_kernel->buffer()), op_params.padding_type,
+ is_replaced_weights);
+
+ if (is_replaced_weights)
+ {
+ // TODO Remove const_cast
+ const_cast<operand::Tensor *>(_kernel)->decrease_ref();
+ }
+ _prepare = true;
+ }
+ kernel(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_kernel),
+ reinterpret_cast<const float *>(_kernel->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void ConvolutionLayer::convQuant8()
+{
+ int32_t output_activation_min = 0;
+ int32_t output_activation_max = 0;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+
+ double real_multiplier = 0.0;
+ int32_t output_multiplier = 0;
+ int32_t output_shift = 0;
+ GetQuantizedConvolutionMultiplier(_input, _kernel, _bias, _output, &real_multiplier);
+ QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+
+ nnfw::cker::ConvParams op_params;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = 1;
+ op_params.dilation_height_factor = 1;
+ op_params.padding_type = getPaddingType(_paddingType);
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.input_offset = -_input->offset();
+ op_params.weights_offset = -_kernel->offset();
+ op_params.output_offset = _output->offset();
+ op_params.output_multiplier = output_multiplier;
+ op_params.output_shift = output_shift;
+ op_params.quantized_activation_min = output_activation_min;
+ op_params.quantized_activation_max = output_activation_max;
+
+ nnfw::cker::Conv &kernel = *_conv_kernel;
+ if (!_prepare)
+ {
+ kernel.prepareQuant(convertTensorToCkerShape(_input), convertTensorToCkerShape(_kernel),
+ convertTensorToCkerShape(_output), _strideWidth, _strideHeight);
+ _prepare = true;
+ }
+ kernel(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_kernel),
+ reinterpret_cast<const uint8_t *>(_kernel->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void ConvolutionLayer::configure(const operand::Tensor *input, const operand::Tensor *kernel,
+ const operand::Tensor *bias, const ir::PaddingType paddingType,
+ const uint32_t paddingLeft, const uint32_t paddingRight,
+ const uint32_t paddingTop, const uint32_t paddingBottom,
+ const uint32_t strideWidth, const uint32_t strideHeight,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ _input = input;
+ _kernel = kernel;
+ _bias = bias;
+ _paddingType = paddingType;
+ _paddingLeft = paddingLeft;
+ _paddingRight = paddingRight;
+ _paddingTop = paddingTop;
+ _paddingBottom = paddingBottom;
+ _strideWidth = strideWidth;
+ _strideHeight = strideHeight;
+ _activation = activation;
+ _output = output;
+}
+
+void ConvolutionLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ convFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ convQuant8();
+ }
+}
+
+#undef ANDROID_NN_CONV_PARAMETERS
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h
new file mode 100644
index 000000000..70af098c4
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+#include <functional>
+#include <memory>
+
+namespace nnfw
+{
+namespace cker
+{
+class Conv;
+}
+} // namespace nnfw
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class ConvolutionLayer : public ::onert::exec::IFunction
+{
+public:
+ ConvolutionLayer();
+ ~ConvolutionLayer();
+
+public:
+ void convFloat32();
+
+ void convQuant8();
+
+ void configure(const operand::Tensor *input, const operand::Tensor *kernel,
+ const operand::Tensor *bias, const ir::PaddingType paddingType,
+ const uint32_t paddingLeft, const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideW, const uint32_t strideH,
+ const ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_kernel;
+ const operand::Tensor *_bias;
+ operand::Tensor *_output;
+
+ ir::PaddingType _paddingType;
+ uint32_t _paddingLeft;
+ uint32_t _paddingTop;
+ uint32_t _paddingRight;
+ uint32_t _paddingBottom;
+
+ uint32_t _strideWidth;
+ uint32_t _strideHeight;
+
+ ir::Activation _activation;
+
+ std::unique_ptr<nnfw::cker::Conv> _conv_kernel;
+
+ bool _prepare;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc
new file mode 100644
index 000000000..a1efe9fed
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019 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 "DepthwiseConvolutionLayer.h"
+
+#include <cker/operation/DepthwiseConv.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+DepthwiseConvolutionLayer::DepthwiseConvolutionLayer()
+ : _input(nullptr), _kernel(nullptr), _bias(nullptr), _output(nullptr), _paddingLeft(0),
+ _paddingTop(0), _paddingRight(0), _paddingBottom(0), _strideWidth(0), _strideHeight(0),
+ _multiplier(0), _activation(ir::Activation::NONE)
+{
+ // DO NOTHING
+}
+
+void DepthwiseConvolutionLayer::convFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+
+ nnfw::cker::DepthwiseConvParams op_params;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = 1;
+ op_params.dilation_height_factor = 1;
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.depth_multiplier = _multiplier;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::DepthwiseConv(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_kernel),
+ reinterpret_cast<const float *>(_kernel->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void DepthwiseConvolutionLayer::convQuant8()
+{
+ int32_t output_activation_min = 0;
+ int32_t output_activation_max = 0;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+
+ double real_multiplier = 0.0;
+ int32_t output_multiplier = 0;
+ int32_t output_shift = 0;
+ GetQuantizedConvolutionMultiplier(_input, _kernel, _bias, _output, &real_multiplier);
+ QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+
+ nnfw::cker::DepthwiseConvParams op_params;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = 1;
+ op_params.dilation_height_factor = 1;
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.depth_multiplier = _multiplier;
+ op_params.input_offset = -_input->offset();
+ op_params.weights_offset = -_kernel->offset();
+ op_params.output_offset = _output->offset();
+ op_params.output_multiplier = output_multiplier;
+ op_params.output_shift = output_shift;
+ op_params.quantized_activation_min = output_activation_min;
+ op_params.quantized_activation_max = output_activation_max;
+
+ nnfw::cker::DepthwiseConv(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_kernel),
+ reinterpret_cast<const uint8_t *>(_kernel->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void DepthwiseConvolutionLayer::configure(const operand::Tensor *input,
+ const operand::Tensor *kernel,
+ const operand::Tensor *bias, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t multiplier,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ _input = input;
+ _kernel = kernel;
+ _bias = bias;
+ _paddingLeft = paddingLeft;
+ _paddingRight = paddingRight;
+ _paddingTop = paddingTop;
+ _paddingBottom = paddingBottom;
+ _strideWidth = strideWidth;
+ _strideHeight = strideHeight;
+ _multiplier = multiplier;
+ _activation = activation;
+ _output = output;
+}
+
+void DepthwiseConvolutionLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ convFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ convQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h
new file mode 100644
index 000000000..dcc3762cc
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 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_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__
+#define __ONERT_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class DepthwiseConvolutionLayer : public ::onert::exec::IFunction
+{
+public:
+ DepthwiseConvolutionLayer();
+
+public:
+ void convFloat32();
+
+ void convQuant8();
+
+ void configure(const operand::Tensor *input, const operand::Tensor *kernel,
+ const operand::Tensor *bias, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideW, const uint32_t strideH,
+ const uint32_t multiplier, const ir::Activation activation,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_kernel;
+ const operand::Tensor *_bias;
+ operand::Tensor *_output;
+
+ uint32_t _paddingLeft;
+ uint32_t _paddingTop;
+ uint32_t _paddingRight;
+ uint32_t _paddingBottom;
+
+ uint32_t _strideWidth;
+ uint32_t _strideHeight;
+
+ uint32_t _multiplier;
+
+ ir::Activation _activation;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/DivLayer.cc b/runtime/onert/backend/cpu/kernel/DivLayer.cc
new file mode 100644
index 000000000..ec9daae9b
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/DivLayer.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019 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 "DivLayer.h"
+
+#include <cker/operation/BinaryArithmeticOps.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void DivLayer::divFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ nnfw::cker::BinaryArithmeticOpParam op_params;
+ op_params.type = nnfw::cker::BinaryArithmeticOpType::DIV;
+ op_params.float_activation_max = output_activation_max;
+ op_params.float_activation_min = output_activation_min;
+
+ if (!HaveSameShapes(_lhs, _rhs))
+ {
+ nnfw::cker::BroadcastBinaryArithmeticOpSlow(
+ op_params, convertToExtendedCkerShape(_lhs),
+ reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs),
+ reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ return;
+ }
+
+ nnfw::cker::BinaryArithmeticOp(
+ op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void DivLayer::divQuant8()
+{
+ int32_t output_activation_min, output_activation_max;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ // nnfw::cker::BinaryArithmeticOpParam op_params;
+ // op_params.quantized_activation_max = output_activation_max;
+ // op_params.quantized_activation_min = output_activation_min;
+
+ // cker quant8 div is not implemented yet
+ throw std::runtime_error{"Div NYI for quantized"};
+}
+
+void DivLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ _lhs = lhs;
+ _rhs = rhs;
+ _activation = activation;
+ _output = output;
+}
+
+void DivLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ divFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ divQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/DivLayer.h b/runtime/onert/backend/cpu/kernel/DivLayer.h
new file mode 100644
index 000000000..3e14d9c19
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/DivLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_DIVLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_DIVLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class DivLayer : public ::onert::exec::IFunction
+{
+public:
+ DivLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void divFloat32();
+
+ void divQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+
+ ir::Activation _activation{ir::Activation::NONE};
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_DIVLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ExpLayer.cc b/runtime/onert/backend/cpu/kernel/ExpLayer.cc
new file mode 100644
index 000000000..335a789b2
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ExpLayer.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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 "ExpLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Exp.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+ExpLayer::ExpLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void ExpLayer::expFloat32()
+{
+ nnfw::cker::Exp(convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void ExpLayer::expQuant8()
+{
+ // cker quant8 exp is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void ExpLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void ExpLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ expFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ expQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ExpLayer.h b/runtime/onert/backend/cpu/kernel/ExpLayer.h
new file mode 100644
index 000000000..5a7222fad
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ExpLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_EXPLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_EXPLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class ExpLayer : public ::onert::exec::IFunction
+{
+public:
+ ExpLayer();
+
+public:
+ void expFloat32();
+
+ void expQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_EXPLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc
new file mode 100644
index 000000000..636df8941
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018 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 "FullyConnectedLayer.h"
+
+#include <cker/operation/FullyConnected.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+FullyConnectedLayer::FullyConnectedLayer()
+ : _input(nullptr), _weights(nullptr), _bias(nullptr), _output(nullptr),
+ _activation(ir::Activation::NONE), _temp_arena(new nnfw::cker::FCTempArena())
+{
+ // DO NOTHING
+}
+
+FullyConnectedLayer::~FullyConnectedLayer() = default;
+
+void FullyConnectedLayer::fullyConnectedFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+
+ nnfw::cker::FullyConnectedParams op_params;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+ op_params.activation = convertActivationType(_activation);
+
+ nnfw::cker::FullyConnected(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_weights),
+ reinterpret_cast<const float *>(_weights->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+// executionMutex is used to protect concurrent access of non-threadsafe resources
+// like gemmlowp::GemmContext.
+void FullyConnectedLayer::fullyConnectedQuant8()
+{
+ double real_multiplier = 0.0;
+ int32_t output_multiplier = 0;
+ int32_t output_shift = 0;
+ int32_t output_activation_min = 0;
+ int32_t output_activation_max = 0;
+ GetQuantizedConvolutionMultiplier(_input, _weights, _bias, _output, &real_multiplier);
+ QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+
+ nnfw::cker::FullyConnectedParams op_params;
+ op_params.input_offset = -_input->offset();
+ op_params.weights_offset = -_weights->offset();
+ op_params.output_offset = _output->offset();
+ op_params.output_multiplier = output_multiplier;
+ op_params.output_shift = output_shift;
+ op_params.quantized_activation_min = output_activation_min;
+ op_params.quantized_activation_max = output_activation_max;
+
+ nnfw::cker::FullyConnected(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_weights),
+ reinterpret_cast<const uint8_t *>(_weights->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void FullyConnectedLayer::fullyConnectedHybrid()
+{
+ nnfw::cker::FCTempArena &temp_arena = *_temp_arena;
+ if (!temp_arena.prepared)
+ {
+ temp_arena.prepare(convertTensorToCkerShape(_input), convertTensorToCkerShape(_weights));
+ }
+
+ nnfw::cker::FullyConnectedParams op_params;
+ op_params.activation = convertActivationType(_activation);
+ op_params.weights_scale = _weights->scale();
+
+ nnfw::cker::FullyConnectedHybrid(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_weights),
+ reinterpret_cast<const int8_t *>(_weights->buffer()), convertTensorToCkerShape(_bias),
+ reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()), temp_arena);
+}
+
+void FullyConnectedLayer::configure(const operand::Tensor *input, const operand::Tensor *weights,
+ const operand::Tensor *bias, ir::Activation activation,
+ operand::Tensor *output)
+{
+ _input = input;
+ _weights = weights;
+ _bias = bias;
+ _activation = activation;
+ _output = output;
+}
+
+void FullyConnectedLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ if (_weights->data_type() == OperandType::QUANT8_SYMM)
+ {
+ fullyConnectedHybrid();
+ }
+ else
+ {
+ fullyConnectedFloat32();
+ }
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ fullyConnectedQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h
new file mode 100644
index 000000000..616124bac
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace nnfw
+{
+namespace cker
+{
+class FCTempArena;
+}
+} // namespace nnfw
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class FullyConnectedLayer : public ::onert::exec::IFunction
+{
+public:
+ FullyConnectedLayer();
+ ~FullyConnectedLayer();
+
+public:
+ void fullyConnectedFloat32();
+
+ void fullyConnectedQuant8();
+
+ void fullyConnectedHybrid();
+
+ void configure(const operand::Tensor *input, const operand::Tensor *weights,
+ const operand::Tensor *bias, ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_weights;
+ const operand::Tensor *_bias;
+ operand::Tensor *_output;
+
+ ir::Activation _activation;
+ std::unique_ptr<nnfw::cker::FCTempArena> _temp_arena;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/GatherLayer.cc b/runtime/onert/backend/cpu/kernel/GatherLayer.cc
new file mode 100644
index 000000000..07f30136c
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/GatherLayer.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 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 "GatherLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Gather.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void GatherLayer::configure(const operand::Tensor *input, const operand::Tensor *indices,
+ operand::Tensor *output, int32_t axis)
+{
+ _input = input;
+ _indices = indices;
+ _axis = axis;
+ _output = output;
+}
+
+void GatherLayer::run()
+{
+ nnfw::cker::GatherParams op_params;
+ op_params.axis = _axis;
+
+ switch (_input->data_type())
+ {
+ case OperandType::FLOAT32:
+ nnfw::cker::Gather<float>(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_indices),
+ reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ break;
+ case OperandType::QUANT8_ASYMM:
+ nnfw::cker::Gather<uint8_t>(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_indices),
+ reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+ break;
+ case OperandType::INT32:
+ nnfw::cker::Gather<int32_t>(
+ op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const int32_t *>(_input->buffer()), convertTensorToCkerShape(_indices),
+ reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<int32_t *>(_output->buffer()));
+ break;
+ default:
+ throw std::runtime_error("Gather NYI for this operand type!");
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/GatherLayer.h b/runtime/onert/backend/cpu/kernel/GatherLayer.h
new file mode 100644
index 000000000..2ff3605a2
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/GatherLayer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_GATHERLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_GATHERLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class GatherLayer : public ::onert::exec::IFunction
+{
+public:
+ GatherLayer() : _input{nullptr}, _indices{nullptr}, _output{nullptr}, _axis{-1}
+ {
+ // DO NOTHING
+ }
+
+public:
+ void configure(const operand::Tensor *input, const operand::Tensor *indices,
+ operand::Tensor *output, int32_t axis);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_indices;
+ operand::Tensor *_output;
+
+ int32_t _axis;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_GATHERLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/LogisticLayer.cc b/runtime/onert/backend/cpu/kernel/LogisticLayer.cc
new file mode 100644
index 000000000..07f434048
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/LogisticLayer.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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 "LogisticLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Logistic.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+LogisticLayer::LogisticLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void LogisticLayer::logisticFloat32()
+{
+ nnfw::cker::Logistic(
+ convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void LogisticLayer::logisticQuant8()
+{
+ // cker quant8 logistic is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void LogisticLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void LogisticLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ logisticFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ logisticQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/LogisticLayer.h b/runtime/onert/backend/cpu/kernel/LogisticLayer.h
new file mode 100644
index 000000000..76ee1600f
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/LogisticLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class LogisticLayer : public ::onert::exec::IFunction
+{
+public:
+ LogisticLayer();
+
+public:
+ void logisticFloat32();
+
+ void logisticQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/MaxLayer.cc b/runtime/onert/backend/cpu/kernel/MaxLayer.cc
new file mode 100644
index 000000000..701d73a35
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MaxLayer.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020 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 "MaxLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/MaxMin.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void MaxLayer::maxFloat32()
+{
+ nnfw::cker::Max<float>(
+ convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void MaxLayer::maxQuant8()
+{
+ // TODO Check whether cker for quant8 max produces correct results
+ // nnfw::cker::Max<uint8_t>(
+ // convertTensorToCkerShape(_lhs), reinterpret_cast<const uint8_t*>(_lhs->buffer()),
+ // convertTensorToCkerShape(_rhs), reinterpret_cast<const uint8_t*>(_rhs->buffer()),
+ // convertTensorToCkerShape(_output), reinterpret_cast<uint8_t*>(_output->buffer()));
+
+ throw std::runtime_error("Max NYI for quantized");
+}
+
+void MaxLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ operand::Tensor *output)
+{
+ assert(lhs != nullptr);
+ assert(rhs != nullptr);
+ assert(output != nullptr);
+
+ _lhs = lhs;
+ _rhs = rhs;
+ _output = output;
+}
+
+void MaxLayer::run()
+{
+ if (_lhs->data_type() == OperandType::FLOAT32)
+ {
+ maxFloat32();
+ }
+ else if (_lhs->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ maxQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/MaxLayer.h b/runtime/onert/backend/cpu/kernel/MaxLayer.h
new file mode 100644
index 000000000..2cccf26ae
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MaxLayer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_MAXLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_MAXLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class MaxLayer : public ::onert::exec::IFunction
+{
+public:
+ MaxLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void maxFloat32();
+
+ void maxQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_MAXLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc
new file mode 100644
index 000000000..e35d5e92a
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018 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 "MaxPoolLayer.h"
+
+#include <cker/operation/MaxPool.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+#define MAXPOOLING_PARAMETERS \
+ nnfw::cker::PoolParams op_params; \
+ op_params.stride_height = _strideHeight; \
+ op_params.stride_width = _strideWidth; \
+ op_params.filter_height = _kernelHeight; \
+ op_params.filter_width = _kernelWidth; \
+ op_params.padding_values.height = (int8_t)_paddingTop; \
+ op_params.padding_values.width = (int8_t)_paddingLeft;
+
+MaxPoolLayer::MaxPoolLayer()
+ : _input(nullptr), _output(nullptr), _paddingLeft(0), _paddingTop(0), _paddingRight(0),
+ _paddingBottom(0), _strideWidth(0), _strideHeight(0), _kernelWidth(0), _kernelHeight(0),
+ _activation(ir::Activation::NONE)
+{
+ // DO NOTHING
+}
+
+void MaxPoolLayer::maxPoolFloat32()
+{
+ MAXPOOLING_PARAMETERS
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::MaxPool(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+void MaxPoolLayer::maxPoolQuant8()
+{
+ MAXPOOLING_PARAMETERS
+ int32_t output_activation_min = 0;
+ int32_t output_activation_max = 0;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ op_params.quantized_activation_min = output_activation_min;
+ op_params.quantized_activation_max = output_activation_max;
+
+ nnfw::cker::MaxPool(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const uint8_t *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void MaxPoolLayer::configure(const operand::Tensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ operand::Tensor *output)
+{
+ _input = input;
+ _paddingLeft = paddingLeft;
+ _paddingRight = paddingRight;
+ _paddingTop = paddingTop;
+ _paddingBottom = paddingBottom;
+ _strideWidth = strideWidth;
+ _strideHeight = strideHeight;
+ _kernelWidth = kernelWidth;
+ _kernelHeight = kernelHeight;
+ _activation = activation;
+ _output = output;
+}
+
+void MaxPoolLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ maxPoolFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ maxPoolQuant8();
+ }
+}
+
+#undef MAXPOOLING_PARAMETERS
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h
new file mode 100644
index 000000000..a29e09e1b
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class MaxPoolLayer : public ::onert::exec::IFunction
+{
+public:
+ MaxPoolLayer();
+
+public:
+ void maxPoolFloat32();
+
+ void maxPoolQuant8();
+
+ void configure(const operand::Tensor *input, const uint32_t paddingLeft,
+ const uint32_t paddingRight, const uint32_t paddingTop,
+ const uint32_t paddingBottom, const uint32_t strideWidth,
+ const uint32_t strideHeight, const uint32_t kernelWidth,
+ const uint32_t kernelHeight, const ir::Activation activation,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+
+ uint32_t _paddingLeft;
+ uint32_t _paddingTop;
+ uint32_t _paddingRight;
+ uint32_t _paddingBottom;
+
+ uint32_t _strideWidth;
+ uint32_t _strideHeight;
+ uint32_t _kernelWidth;
+ uint32_t _kernelHeight;
+
+ ir::Activation _activation;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/MinLayer.cc b/runtime/onert/backend/cpu/kernel/MinLayer.cc
new file mode 100644
index 000000000..07cb8ab91
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MinLayer.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020 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 "MinLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/MaxMin.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void MinLayer::minFloat32()
+{
+ nnfw::cker::Min<float>(
+ convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void MinLayer::minQuant8()
+{
+ // TODO Check whether cker for quant8 min produces correct results
+ // nnfw::cker::Min<uint8_t>(
+ // convertTensorToCkerShape(_lhs), reinterpret_cast<const uint8_t*>(_lhs->buffer()),
+ // convertTensorToCkerShape(_rhs), reinterpret_cast<const uint8_t*>(_rhs->buffer()),
+ // convertTensorToCkerShape(_output), reinterpret_cast<uint8_t*>(_output->buffer()));
+
+ throw std::runtime_error("Min NYI for quantized");
+}
+
+void MinLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ operand::Tensor *output)
+{
+ assert(lhs != nullptr);
+ assert(rhs != nullptr);
+ assert(output != nullptr);
+
+ _lhs = lhs;
+ _rhs = rhs;
+ _output = output;
+}
+
+void MinLayer::run()
+{
+ if (_lhs->data_type() == OperandType::FLOAT32)
+ {
+ minFloat32();
+ }
+ else if (_lhs->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ minQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/MinLayer.h b/runtime/onert/backend/cpu/kernel/MinLayer.h
new file mode 100644
index 000000000..5beb6444a
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MinLayer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_MINLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_MINLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class MinLayer : public ::onert::exec::IFunction
+{
+public:
+ MinLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void minFloat32();
+
+ void minQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_MINLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/MulLayer.cc b/runtime/onert/backend/cpu/kernel/MulLayer.cc
new file mode 100644
index 000000000..df7d71eec
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MulLayer.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019 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 "MulLayer.h"
+
+#include <cker/operation/BinaryArithmeticOps.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void MulLayer::mulFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ nnfw::cker::BinaryArithmeticOpParam op_params;
+ op_params.type = nnfw::cker::BinaryArithmeticOpType::MUL;
+ op_params.float_activation_max = output_activation_max;
+ op_params.float_activation_min = output_activation_min;
+
+ if (!HaveSameShapes(_lhs, _rhs))
+ {
+ nnfw::cker::BroadcastBinaryArithmeticOpSlow(
+ op_params, convertToExtendedCkerShape(_lhs),
+ reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs),
+ reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ return;
+ }
+
+ nnfw::cker::BinaryArithmeticOp(
+ op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void MulLayer::mulQuant8()
+{
+ int32_t output_activation_min, output_activation_max;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ // nnfw::cker::BinaryArithmeticOpParam op_params;
+ // op_params.quantized_activation_max = output_activation_max;
+ // op_params.quantized_activation_min = output_activation_min;
+
+ // cker quant8 mul is not implemented yet
+ throw std::runtime_error{"Mull NYI for quantized"};
+}
+
+void MulLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ _lhs = lhs;
+ _rhs = rhs;
+ _activation = activation;
+ _output = output;
+}
+
+void MulLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ mulFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ mulQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/MulLayer.h b/runtime/onert/backend/cpu/kernel/MulLayer.h
new file mode 100644
index 000000000..a5cf25f0f
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/MulLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_MULLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_MULLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class MulLayer : public ::onert::exec::IFunction
+{
+public:
+ MulLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void mulFloat32();
+
+ void mulQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+
+ ir::Activation _activation{ir::Activation::NONE};
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_MULLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/OneHotLayer.cc b/runtime/onert/backend/cpu/kernel/OneHotLayer.cc
new file mode 100644
index 000000000..fd2c1b795
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/OneHotLayer.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020 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 "OneHotLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/OneHot.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void OneHotLayer::oneHotFloat32()
+{
+ nnfw::cker::OneHot<float, int32_t>(
+ _depth, _on_value, _off_value, _axis, convertTensorToCkerShape(_indices),
+ reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void OneHotLayer::oneHotQuant8() { throw std::runtime_error{"OneHot NYI for quantized"}; }
+
+void OneHotLayer::configure(const operand::Tensor *indices, operand::Tensor *output, int32_t depth,
+ float on_value, float off_value, int32_t axis)
+{
+ _indices = indices;
+ _output = output;
+ _depth = depth;
+ _on_value = on_value;
+ _off_value = off_value;
+ _axis = axis;
+ if (_axis == -1)
+ _axis = _indices->num_dimensions();
+}
+
+void OneHotLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ oneHotFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ oneHotQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/OneHotLayer.h b/runtime/onert/backend/cpu/kernel/OneHotLayer.h
new file mode 100644
index 000000000..5f23481ba
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/OneHotLayer.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class OneHotLayer : public ::onert::exec::IFunction
+{
+public:
+ OneHotLayer()
+ : _indices(nullptr), _output(nullptr), _depth(0), _on_value(1), _off_value(0), _axis(-1)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void oneHotFloat32();
+
+ void oneHotQuant8();
+
+ void configure(const operand::Tensor *indices, operand::Tensor *output, int32_t depth,
+ float on_value, float off_value, int32_t axis);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_indices;
+ operand::Tensor *_output;
+
+ int32_t _depth;
+ float _on_value;
+ float _off_value;
+ int32_t _axis;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/OperationUtils.cc b/runtime/onert/backend/cpu/kernel/OperationUtils.cc
new file mode 100644
index 000000000..178aac833
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/OperationUtils.cc
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2018 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 "OperationUtils.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+uint32_t getNumberOfDimensions(const operand::Tensor *tensor)
+{
+ assert(tensor);
+ return tensor->num_dimensions();
+}
+
+uint32_t getNumberOfElements(const operand::Tensor *tensor)
+{
+ assert(tensor);
+ uint32_t count = 1;
+ for (size_t i = 0; i < tensor->num_dimensions(); i++)
+ {
+ count *= tensor->dimension(i);
+ }
+ return count;
+}
+
+uint32_t getSizeOfDimension(const operand::Tensor *tensor, uint32_t dimensionIdx)
+{
+ assert(tensor);
+ if (dimensionIdx >= tensor->num_dimensions())
+ {
+ // TODO, log the error
+ return 0;
+ }
+ return tensor->dimension(dimensionIdx);
+}
+
+void QuantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift)
+{
+ if (double_multiplier == 0.)
+ {
+ *quantized_multiplier = 0;
+ *shift = 0;
+ return;
+ }
+ const double q = std::frexp(double_multiplier, shift);
+ auto q_fixed = static_cast<int64_t>(std::round(q * (1ll << 31)));
+
+ assert(q_fixed <= (1ll << 31));
+ if (q_fixed == (1ll << 31))
+ {
+ q_fixed /= 2;
+ ++*shift;
+ }
+ assert(q_fixed <= std::numeric_limits<int32_t>::max());
+ *quantized_multiplier = static_cast<int32_t>(q_fixed);
+}
+
+void GetQuantizedConvolutionMultiplier(const operand::Tensor *input, const operand::Tensor *filter,
+ const operand::Tensor *bias, const operand::Tensor *output,
+ double *multiplier)
+{
+ const double input_product_scale = input->scale() * filter->scale();
+ const double bias_scale = bias->scale();
+ const double output_scale = output->scale();
+ // The following conditions must be guaranteed by the training pipeline.
+ UNUSED_RELEASE(bias_scale);
+ assert(std::abs(input_product_scale - bias_scale) <=
+ 1e-6 * std::min(input_product_scale, bias_scale));
+ assert(input_product_scale >= 0);
+ assert(input_product_scale < output_scale);
+ *multiplier = input_product_scale / output_scale;
+}
+
+void QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier,
+ int *left_shift)
+{
+ assert(double_multiplier > 1.);
+ const double q = std::frexp(double_multiplier, left_shift);
+ int64_t q_fixed = static_cast<int64_t>(std::round(q * (1ll << 31)));
+ assert(q_fixed <= (1ll << 31));
+ if (q_fixed == (1ll << 31))
+ {
+ q_fixed /= 2;
+ ++*left_shift;
+ }
+ assert(*left_shift >= 0);
+ assert(q_fixed <= std::numeric_limits<int32_t>::max());
+ *quantized_multiplier = static_cast<int32_t>(q_fixed);
+}
+
+void CalculateActivationRangeFloat(ir::Activation activation, float *activation_min,
+ float *activation_max)
+{
+ if (activation == ir::Activation::RELU)
+ {
+ *activation_min = 0.f;
+ *activation_max = std::numeric_limits<float>::max();
+ }
+ else if (activation == ir::Activation::RELU6)
+ {
+ *activation_min = 0.f;
+ *activation_max = 6.f;
+ }
+ else if (activation == ir::Activation::RELU1)
+ {
+ *activation_min = -1.f;
+ *activation_max = 1.f;
+ }
+ else if (activation == ir::Activation::SIGMOID)
+ {
+ *activation_min = 0.f;
+ *activation_max = 1.f;
+ }
+ else if (activation == ir::Activation::NONE)
+ {
+ *activation_min = std::numeric_limits<float>::lowest();
+ *activation_max = std::numeric_limits<float>::max();
+ }
+ else
+ {
+ std::cout << "Unsupported fused activation function." << std::endl;
+ }
+}
+
+void CalculateActivationRangeUint8(ir::Activation activation, const operand::Tensor *output,
+ int32_t *act_min, int32_t *act_max)
+{
+ const int32_t qmin = std::numeric_limits<uint8_t>::min();
+ const int32_t qmax = std::numeric_limits<uint8_t>::max();
+ const auto scale = output->scale();
+ const auto zero_point = output->offset();
+ auto quantize = [scale, zero_point](float f) {
+ return zero_point + static_cast<int32_t>(std::round(f / scale));
+ };
+ if (activation == ir::Activation::RELU)
+ {
+ *act_min = std::max(qmin, quantize(0.0));
+ *act_max = qmax;
+ }
+ else if (activation == ir::Activation::RELU6)
+ {
+ *act_min = std::max(qmin, quantize(0.0));
+ *act_max = std::min(qmax, quantize(6.0));
+ }
+ else if (activation == ir::Activation::RELU1)
+ {
+ *act_min = std::max(qmin, quantize(-1.0));
+ *act_max = std::min(qmax, quantize(1.0));
+ }
+ else if (activation == ir::Activation::SIGMOID)
+ {
+ *act_min = std::max(qmin, quantize(0.0));
+ *act_max = std::min(qmax, quantize(1.0));
+ }
+ else if (activation == ir::Activation::NONE)
+ {
+ *act_min = qmin;
+ *act_max = qmax;
+ }
+ else
+ {
+ std::cout << "Unsupported fused activation function." << std::endl;
+ }
+}
+
+bool HaveSameShapes(const operand::Tensor *input1, const operand::Tensor *input2)
+{
+ if (input1 == input2)
+ return true;
+ if (input2 == NULL || input2 == NULL)
+ return false;
+
+ if (input1 == NULL)
+ {
+ return (getNumberOfDimensions(input2) == 0);
+ }
+
+ if (getNumberOfDimensions(input1) != getNumberOfDimensions(input2))
+ return false;
+
+ for (uint32_t i = 0; i < getNumberOfDimensions(input1); i++)
+ if (input1->dimension(i) != input2->dimension(i))
+ return false;
+
+ return true;
+}
+
+int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift)
+{
+ const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
+ (1ll << (31 - input_integer_bits)) / (1ll << input_left_shift);
+ // Tighten bound using floor. Suppose that we could use the exact value.
+ // After scaling the difference, the result would be at the maximum. Thus we
+ // must ensure that our value has lower magnitude.
+ return static_cast<int32_t>(std::floor(max_input_rescaled));
+}
+
+uint32_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions)
+{
+ uint32_t size = 4;
+
+ switch (type)
+ {
+ case OperandType::FLOAT32:
+ case OperandType::INT32:
+ case OperandType::UINT32:
+ size = 4;
+ break;
+ case OperandType::BOOL8:
+ case OperandType::QUANT8_ASYMM:
+ case OperandType::QUANT8_SYMM:
+ size = 1;
+ break;
+ default:
+ throw std::runtime_error("Not supported operand type.");
+ break;
+ }
+
+ for (auto d : dimensions)
+ {
+ size *= d;
+ }
+
+ return size;
+}
+
+nnfw::cker::PaddingType getPaddingType(ir::PaddingType ir_padding_type)
+{
+ switch (ir_padding_type)
+ {
+ case ir::PaddingType::EXPLICIT:
+ return nnfw::cker::PaddingType::kNone;
+ case ir::PaddingType::SAME:
+ return nnfw::cker::PaddingType::kSame;
+ case ir::PaddingType::VALID:
+ return nnfw::cker::PaddingType::kValid;
+ default:
+ throw std::runtime_error("Wrong padding type.");
+ break;
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/OperationUtils.h b/runtime/onert/backend/cpu/kernel/OperationUtils.h
new file mode 100644
index 000000000..be9b24f36
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/OperationUtils.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 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 __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__
+#define __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__
+
+#include "../operand/Tensor.h"
+
+#include <cker/Shape.h>
+#include <cker/Types.h>
+#include <iostream>
+#include <ir/DataType.h>
+#include <ir/InternalType.h>
+#include <ir/Operand.h>
+#include <ir/Padding.h>
+
+#include <limits>
+#include <vector>
+
+using OperandType = onert::ir::DataType;
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+union DataPtr {
+ uint8_t *u8;
+ int8_t *i8;
+ uint32_t *u32;
+ int32_t *i32;
+ bool *b;
+ float *f;
+ void *v;
+};
+
+uint32_t getNumberOfDimensions(const operand::Tensor *tensor);
+
+uint32_t getNumberOfElements(const operand::Tensor *tensor);
+
+uint32_t getSizeOfDimension(const operand::Tensor *tensor, uint32_t dimensionIdx);
+
+inline nnfw::cker::Shape convertToExtendedCkerShape(const operand::Tensor *tensor)
+{
+ assert(tensor);
+ std::vector<int32_t> raw_shape;
+ raw_shape.resize(4);
+
+ uint32_t src = 4 - tensor->num_dimensions();
+ for (uint32_t i = 0; i < 4; ++i)
+ {
+ if (i < src)
+ {
+ raw_shape[i] = 1;
+ }
+ else
+ {
+ raw_shape[i] = tensor->dimension(i - src);
+ }
+ }
+
+ return nnfw::cker::GetShape(raw_shape);
+}
+
+inline nnfw::cker::Shape convertTensorToCkerShape(const operand::Tensor *tensor)
+{
+ assert(tensor);
+ assert(tensor->layout() == ir::Layout::NHWC);
+ std::vector<int32_t> raw_shape;
+ raw_shape.resize(tensor->num_dimensions());
+ for (uint32_t i = 0; i < tensor->num_dimensions(); ++i)
+ {
+ raw_shape[i] = tensor->dimension(i);
+ }
+
+ return nnfw::cker::GetShape(raw_shape);
+}
+
+inline nnfw::cker::FusedActivationFunctionType
+convertActivationType(const ir::Activation activation)
+{
+ switch (activation)
+ {
+ case ir::Activation::NONE:
+ return nnfw::cker::FusedActivationFunctionType::kNone;
+ case ir::Activation::RELU:
+ return nnfw::cker::FusedActivationFunctionType::kRelu;
+ case ir::Activation::RELU1:
+ return nnfw::cker::FusedActivationFunctionType::kRelu1;
+ case ir::Activation::RELU6:
+ return nnfw::cker::FusedActivationFunctionType::kRelu6;
+ default:
+ throw std::runtime_error{"CPU backend: Cannot convert activation type"};
+ }
+}
+
+inline int32_t getAxis(uint32_t rank, int32_t axis, ir::Layout frontend_layout)
+{
+ auto ret = axis;
+
+ if (axis < 0)
+ {
+ ret += rank;
+ }
+
+ // NCHW -> NHWC
+ if (frontend_layout == ir::Layout::NCHW)
+ {
+ int32_t permutation[4] = {0, 3, 1, 2};
+ ret = permutation[ret];
+ }
+
+ return ret;
+}
+
+void QuantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift);
+
+void GetQuantizedConvolutionMultiplier(const operand::Tensor *inputDescr,
+ const operand::Tensor *filterDescr,
+ const operand::Tensor *biasDescr,
+ const operand::Tensor *outputDescr, double *multiplier);
+
+void QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier,
+ int *left_shift);
+
+void CalculateActivationRangeFloat(ir::Activation activation, float *activation_min,
+ float *activation_max);
+
+void CalculateActivationRangeUint8(ir::Activation activation, const operand::Tensor *output,
+ int32_t *act_min, int32_t *act_max);
+
+bool HaveSameShapes(const operand::Tensor *input1, const operand::Tensor *input2);
+
+int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift);
+
+uint32_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions);
+
+nnfw::cker::PaddingType getPaddingType(ir::PaddingType ir_padding_type);
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__
diff --git a/runtime/onert/backend/cpu/kernel/PackLayer.cc b/runtime/onert/backend/cpu/kernel/PackLayer.cc
new file mode 100644
index 000000000..01e69ff1d
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PackLayer.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2020 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 "PackLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Pack.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+PackLayer::PackLayer() : _inputs(), _output(nullptr), _axis(0)
+{
+ // DO NOTHING
+}
+
+void PackLayer::packFloat32()
+{
+ uint32_t num_inputs = _inputs.size();
+ nnfw::cker::PackParams op_params;
+ op_params.axis = _axis;
+ op_params.inputs_count = num_inputs;
+
+ std::vector<nnfw::cker::Shape *> inputDimsPtr;
+ std::vector<nnfw::cker::Shape> inputDims;
+ inputDimsPtr.reserve(num_inputs);
+ inputDims.reserve(num_inputs);
+
+ for (uint32_t i = 0; i < num_inputs; i++)
+ {
+ inputDims.push_back(convertTensorToCkerShape(_inputs[i]));
+ inputDimsPtr.push_back(&inputDims[i]);
+ }
+
+ std::vector<const float *> inputFloatPtrs;
+
+ for (const auto input : _inputs)
+ {
+ inputFloatPtrs.emplace_back(reinterpret_cast<const float *>(input->buffer()));
+ }
+
+ nnfw::cker::Pack<float>(op_params, inputFloatPtrs.data(), convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void PackLayer::packQuant8()
+{
+ // cker quant8 pack is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void PackLayer::configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis,
+ operand::Tensor *output)
+{
+ assert(inputs.size() > 0);
+ assert(output != nullptr);
+
+ _inputs = inputs;
+ _axis = axis;
+ _output = output;
+}
+
+void PackLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ packFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ packQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/PackLayer.h b/runtime/onert/backend/cpu/kernel/PackLayer.h
new file mode 100644
index 000000000..5c87382be
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PackLayer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_PACKLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_PACKLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class PackLayer : public ::onert::exec::IFunction
+{
+public:
+ PackLayer();
+
+public:
+ void packFloat32();
+
+ void packQuant8();
+
+ void configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ std::vector<const operand::Tensor *> _inputs;
+ operand::Tensor *_output;
+ int32_t _axis;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_PACKLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/PadLayer.cc b/runtime/onert/backend/cpu/kernel/PadLayer.cc
new file mode 100644
index 000000000..393856178
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PadLayer.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2019 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 "PadLayer.h"
+
+#include <cker/operation/Pad.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+PadLayer::PadLayer()
+ : _input(nullptr), _output(nullptr), _padData(), _padRank(), _constantValueData()
+{
+ // DO NOTHING
+}
+
+void PadLayer::padFloat32()
+{
+ nnfw::cker::Pad(_padData, _padRank, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()),
+ _constantValueData.f);
+}
+void PadLayer::padQuant8() { throw std::runtime_error("Quantized Pad isn't supported NYI"); }
+
+void PadLayer::configure(const operand::Tensor *input, operand::Tensor *output,
+ const int32_t *padData, int32_t padRank, uint8_t *constantValueData)
+{
+ _input = input;
+ _output = output;
+ _padData = padData;
+ _padRank = padRank;
+ _constantValueData.u8 = constantValueData;
+}
+
+void PadLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ padFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ padQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/PadLayer.h b/runtime/onert/backend/cpu/kernel/PadLayer.h
new file mode 100644
index 000000000..fc14ae033
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PadLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_PADLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_PADLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+// Note, this is pad with mode=`CONSTANT`: it doesn't support `REFLECT` and
+// `SYMMETRIC`
+class PadLayer : public ::onert::exec::IFunction
+{
+public:
+ PadLayer();
+
+public:
+ void padFloat32();
+
+ void padQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output, const int32_t *padData,
+ int32_t padRank, uint8_t *constantValueData = nullptr);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+
+ const int32_t *_padData;
+ int32_t _padRank;
+ DataPtr _constantValueData;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_PADLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/PermuteLayer.cc b/runtime/onert/backend/cpu/kernel/PermuteLayer.cc
new file mode 100644
index 000000000..a3e828255
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PermuteLayer.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 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 "PermuteLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+using Type = ir::operation::Permute::Type;
+
+void PermuteLayer::configure(std::shared_ptr<backend::ITensor> input,
+ std::shared_ptr<backend::ITensor> output,
+ const ir::Shape &output_shape, Type type, ir::DataType dataType)
+{
+ _input = input;
+ _output = output;
+ _output_shape = output_shape;
+ _type = type;
+ _dataType = dataType;
+}
+
+void PermuteLayer::run()
+{
+ using ir::DataType;
+ switch (_dataType)
+ {
+ case DataType::FLOAT32:
+ runTempl<float>();
+ break;
+ case DataType::INT32:
+ runTempl<int32_t>();
+ break;
+ case DataType::UINT32:
+ runTempl<uint32_t>();
+ break;
+ case DataType::BOOL8:
+ case DataType::QUANT8_ASYMM:
+ runTempl<uint8_t>();
+ break;
+ case DataType::QUANT8_SYMM:
+ runTempl<int8_t>();
+ break;
+ default:
+ throw std::runtime_error("NYI");
+ break;
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/PermuteLayer.h b/runtime/onert/backend/cpu/kernel/PermuteLayer.h
new file mode 100644
index 000000000..52b96caba
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/PermuteLayer.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__
+
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+#include <ir/Coordinates.h>
+#include <ir/operation/Permute.h>
+#include <misc/feature/IndexIterator.h>
+#include <util/feature/nchw/View.h>
+#include <util/feature/nhwc/Reader.h>
+#include <util/feature/nhwc/View.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class PermuteLayer : public ::onert::exec::IFunction
+{
+public:
+ PermuteLayer() = default;
+
+public:
+ void configure(std::shared_ptr<backend::ITensor> input, std::shared_ptr<backend::ITensor> output,
+ const ir::Shape &output_shape, ir::operation::Permute::Type type,
+ ir::DataType dataType);
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ template <class T> void runTempl()
+ {
+ auto rank = _output_shape.rank();
+ auto fn = [&](ITensor &in_tensor) {
+ _output->access([&](ITensor &out_tensor) {
+ auto input_buffer = in_tensor.buffer();
+ auto input_size = in_tensor.total_size();
+ auto output_buffer = out_tensor.buffer();
+ if (_type == ir::operation::Permute::Type::COPY)
+ {
+ assert(in_tensor.layout() == out_tensor.layout());
+ if (!in_tensor.has_padding() && !out_tensor.has_padding())
+ {
+ assert(input_size == out_tensor.total_size());
+ memcpy(output_buffer, input_buffer, input_size);
+ return;
+ }
+ }
+ switch (rank)
+ {
+ case 0:
+ case 1:
+ {
+ const int32_t copy_len = _output_shape.dim(0);
+
+ memcpy(output_buffer, input_buffer, copy_len);
+ break;
+ }
+ case 2:
+ {
+ const int32_t copy_len = _output_shape.dim(1);
+
+ for (auto i = 0; i < _output_shape.dim(0); ++i)
+ {
+ ir::Coordinates coords{i, 0};
+ memcpy(output_buffer + out_tensor.calcOffset(coords),
+ input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T));
+ }
+ break;
+ }
+ case 3:
+ {
+ const int32_t copy_len = _output_shape.dim(2);
+
+ for (auto i = 0; i < _output_shape.dim(0); ++i)
+ {
+ for (auto j = 0; j < _output_shape.dim(1); ++j)
+ {
+ ir::Coordinates coords{i, j, 0};
+ memcpy(output_buffer + out_tensor.calcOffset(coords),
+ input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T));
+ }
+ }
+ break;
+ }
+ case 4:
+ {
+ // TODO Unify permute type and remove switch case
+ switch (_type)
+ {
+ case ir::operation::Permute::Type::NHWC_TO_NCHW:
+ {
+ for (auto n = 0; n < _output_shape.dim(0); ++n)
+ {
+ for (auto c = 0; c < _output_shape.dim(1); ++c)
+ {
+ for (auto h = 0; h < _output_shape.dim(2); ++h)
+ {
+ for (auto w = 0; w < _output_shape.dim(3); ++w)
+ {
+ const ir::Coordinates in_coords{n, h, w, c};
+ const auto out_coords =
+ convertCoordinates(in_coords, in_tensor.layout(), out_tensor.layout());
+ const auto value =
+ *reinterpret_cast<T *>(input_buffer + in_tensor.calcOffset(in_coords));
+ *reinterpret_cast<T *>(output_buffer + out_tensor.calcOffset(out_coords)) =
+ value;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ir::operation::Permute::Type::NCHW_TO_NHWC:
+ {
+ for (auto n = 0; n < _output_shape.dim(0); ++n)
+ {
+ for (auto h = 0; h < _output_shape.dim(1); ++h)
+ {
+ for (auto w = 0; w < _output_shape.dim(2); ++w)
+ {
+ for (auto c = 0; c < _output_shape.dim(3); ++c)
+ {
+ const ir::Coordinates in_coords{n, c, h, w};
+ const auto out_coords =
+ convertCoordinates(in_coords, in_tensor.layout(), out_tensor.layout());
+ const auto value =
+ *reinterpret_cast<T *>(input_buffer + in_tensor.calcOffset(in_coords));
+ *reinterpret_cast<T *>(output_buffer + out_tensor.calcOffset(out_coords)) =
+ value;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ir::operation::Permute::Type::COPY:
+ {
+ const int32_t copy_len = _output_shape.dim(3);
+
+ for (auto i = 0; i < _output_shape.dim(0); ++i)
+ {
+ for (auto j = 0; j < _output_shape.dim(1); ++j)
+ {
+ for (auto k = 0; k < _output_shape.dim(2); ++k)
+ {
+ ir::Coordinates coords{i, j, k, 0};
+ memcpy(output_buffer + out_tensor.calcOffset(coords),
+ input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T));
+ }
+ }
+ }
+ break;
+ }
+ default:
+ throw std::runtime_error("NYI");
+ break;
+ }
+ break;
+ }
+ default:
+ throw std::runtime_error("NYI");
+ break;
+ }
+ });
+ };
+ _input->access(fn);
+ }
+
+private:
+ std::shared_ptr<backend::ITensor> _input{nullptr};
+ std::shared_ptr<backend::ITensor> _output{nullptr};
+ ir::Shape _output_shape{};
+ ir::operation::Permute::Type _type{ir::operation::Permute::Type::COPY};
+ ir::DataType _dataType{ir::DataType::FLOAT32};
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ReduceLayer.cc b/runtime/onert/backend/cpu/kernel/ReduceLayer.cc
new file mode 100644
index 000000000..78c82f1cc
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ReduceLayer.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2020 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 "ReduceLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Reduce.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+namespace
+{
+
+template <typename T>
+void evalLogic(const operand::Tensor *input, operand::Tensor *output, const std::vector<int> &axes,
+ bool keep_dims, T init_value, nnfw::cker::Reduce &reduce_kernel,
+ T reducer(const T current, const T in))
+{
+ reduce_kernel.prepare(input->num_dimensions(), axes.size());
+ bool result = reduce_kernel.ReduceGeneric<T>(
+ convertTensorToCkerShape(input), reinterpret_cast<const T *>(input->buffer()),
+ convertTensorToCkerShape(output), reinterpret_cast<T *>(output->buffer()), axes, keep_dims,
+ init_value, reducer);
+
+ if (!result)
+ {
+ throw std::runtime_error{"Reduce: Fail to run"};
+ }
+}
+
+template <typename T>
+void evalType(const operand::Tensor *input, operand::Tensor *output, const std::vector<int> &axes,
+ bool keep_dims, nnfw::cker::Reduce &reduce_kernel, ReduceType reduce_type)
+{
+ switch (reduce_type)
+ {
+ case ReduceType::kSum:
+ return evalLogic<T>(input, output, axes, keep_dims, static_cast<T>(0), reduce_kernel,
+ [](const T current, const T in) -> T { return in + current; });
+ break;
+ case ReduceType::kProd:
+ return evalLogic<T>(input, output, axes, keep_dims, static_cast<T>(1), reduce_kernel,
+ [](const T current, const T in) -> T { return in * current; });
+ break;
+ case ReduceType::kMax:
+ return evalLogic<T>(
+ input, output, axes, keep_dims, std::numeric_limits<T>::lowest(), reduce_kernel,
+ [](const T current, const T in) -> T { return (in > current) ? in : current; });
+ break;
+ case ReduceType::kMin:
+ return evalLogic<T>(
+ input, output, axes, keep_dims, std::numeric_limits<T>::max(), reduce_kernel,
+ [](const T current, const T in) -> T { return (in < current) ? in : current; });
+ break;
+ default:
+ throw std::runtime_error{"Reduce: Unsupported reduce type"};
+ }
+}
+
+template <ReduceType reduce_type>
+void evalGeneric(const operand::Tensor *input, operand::Tensor *output,
+ const std::vector<int> &axes, bool keep_dims, nnfw::cker::Reduce &reduce_kernel)
+{
+ switch (input->data_type())
+ {
+ case OperandType::FLOAT32:
+ return evalType<float>(input, output, axes, keep_dims, reduce_kernel, reduce_type);
+ case OperandType::INT32:
+ return evalType<int32_t>(input, output, axes, keep_dims, reduce_kernel, reduce_type);
+ default:
+ throw std::runtime_error{"Reduce(generic): Unsupported input type"};
+ }
+}
+} // namespace
+
+ReduceLayer::ReduceLayer()
+ : _input(nullptr), _output(nullptr), _reduceType(ReduceType::kAny), _axes(), _keep_dims(false),
+ _reduce_kernel(new nnfw::cker::Reduce())
+{
+ // DO NOTHING
+}
+
+ReduceLayer::~ReduceLayer() = default;
+
+void ReduceLayer::configure(const operand::Tensor *input, operand::Tensor *output,
+ ReduceType reduceType, const std::vector<int> &axes, bool keep_dims)
+{
+ _input = input;
+ _output = output;
+ _reduceType = reduceType;
+ _axes = axes;
+ _keep_dims = keep_dims;
+}
+
+void ReduceLayer::run()
+{
+ switch (_reduceType)
+ {
+ case ReduceType::kSum:
+ evalGeneric<ReduceType::kSum>(_input, _output, _axes, _keep_dims, *_reduce_kernel);
+ break;
+ case ReduceType::kMax:
+ evalGeneric<ReduceType::kMax>(_input, _output, _axes, _keep_dims, *_reduce_kernel);
+ break;
+ case ReduceType::kMin:
+ evalGeneric<ReduceType::kMin>(_input, _output, _axes, _keep_dims, *_reduce_kernel);
+ break;
+ default:
+ throw std::runtime_error{"ReduceSum: Unsupported reduce type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ReduceLayer.h b/runtime/onert/backend/cpu/kernel/ReduceLayer.h
new file mode 100644
index 000000000..9310882c9
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ReduceLayer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+#include <memory>
+
+namespace nnfw
+{
+namespace cker
+{
+class Reduce;
+}
+} // namespace nnfw
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+enum class ReduceType
+{
+ kSum,
+ kProd,
+ kMax,
+ kMin,
+ kAny,
+};
+
+class ReduceLayer : public ::onert::exec::IFunction
+{
+public:
+ ReduceLayer();
+ ~ReduceLayer();
+
+public:
+ void configure(const operand::Tensor *input, operand::Tensor *output, ReduceType reduceType,
+ const std::vector<int> &axes, bool keep_dims);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+ ReduceType _reduceType;
+ std::vector<int> _axes;
+ bool _keep_dims;
+
+ std::unique_ptr<nnfw::cker::Reduce> _reduce_kernel;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc b/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc
new file mode 100644
index 000000000..b8bd5a45c
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 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 "ReshapeLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+ReshapeLayer::ReshapeLayer() : _input(nullptr), _shape(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void ReshapeLayer::reshapeGeneric()
+{
+ // TODO use _shape to calculate shape of output when _shape is not nullptr && not constant
+
+ size_t count = _input->total_size();
+ memcpy(_output->buffer(), _input->buffer(), count);
+}
+
+void ReshapeLayer::configure(const operand::Tensor *input, const operand::Tensor *shape,
+ operand::Tensor *output)
+{
+ _input = input;
+ /* note : shape is optional. If not provided from model, _shape is nullptr. */
+ _shape = shape;
+ _output = output;
+}
+
+void ReshapeLayer::run() { reshapeGeneric(); }
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ReshapeLayer.h b/runtime/onert/backend/cpu/kernel/ReshapeLayer.h
new file mode 100644
index 000000000..7a95b6d35
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ReshapeLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_RESHAPELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_RESHAPELAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class ReshapeLayer : public ::onert::exec::IFunction
+{
+public:
+ ReshapeLayer();
+
+public:
+ void reshapeGeneric();
+
+ void configure(const operand::Tensor *input, const operand::Tensor *shape,
+ operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_shape;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_RESHAPELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc b/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc
new file mode 100644
index 000000000..d94ff8751
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020 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 "RsqrtLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Elementwise.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+RsqrtLayer::RsqrtLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void RsqrtLayer::rsqrtFloat32()
+{
+ nnfw::cker::Rsqrt(
+ convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void RsqrtLayer::rsqrtQuant8() { throw std::runtime_error{"NYI : QASYMM8 not supported"}; }
+
+void RsqrtLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void RsqrtLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ rsqrtFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ rsqrtQuant8();
+ }
+ else
+ {
+ throw std::runtime_error{"Rsqrt: unsupported data type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/RsqrtLayer.h b/runtime/onert/backend/cpu/kernel/RsqrtLayer.h
new file mode 100644
index 000000000..188d53160
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/RsqrtLayer.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020 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 riting, 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_BACKEND_CPU_KERNEL_RSQRTLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_RSQRTLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+class RsqrtLayer : public ::onert::exec::IFunction
+{
+public:
+ RsqrtLayer();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this rsqrttract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ void rsqrtFloat32();
+ void rsqrtQuant8();
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_RSQRTLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/ShapeLayer.cc b/runtime/onert/backend/cpu/kernel/ShapeLayer.cc
new file mode 100644
index 000000000..1cd183331
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ShapeLayer.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 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 "ShapeLayer.h"
+
+#include "OperationUtils.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+ShapeLayer::ShapeLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+template <typename T> void GetRawShape(const operand::Tensor *input, T *output_data)
+{
+ for (uint32_t i = 0; i < input->num_dimensions(); ++i)
+ {
+ output_data[i] = static_cast<T>(input->dimension(i));
+ }
+}
+
+void ShapeLayer::shape()
+{
+ if (_output->data_type() == OperandType::UINT32)
+ {
+ GetRawShape(_input, reinterpret_cast<uint32_t *>(_output->buffer()));
+ }
+ else if (_output->data_type() == OperandType::INT32)
+ {
+ GetRawShape(_input, reinterpret_cast<int32_t *>(_output->buffer()));
+ }
+ else
+ {
+ throw std::runtime_error{"NYI : not supported output type for ShapeLayer"};
+ }
+}
+
+void ShapeLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void ShapeLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32 ||
+ _input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ shape();
+ }
+ else
+ {
+ throw std::runtime_error{"NYI : not supported input type for ShapeLayer"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/ShapeLayer.h b/runtime/onert/backend/cpu/kernel/ShapeLayer.h
new file mode 100644
index 000000000..cb4acedb8
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/ShapeLayer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020 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 riting, 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_BACKEND_CPU_KERNEL_SHAPELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SHAPELAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class ShapeLayer : public ::onert::exec::IFunction
+{
+public:
+ ShapeLayer();
+
+public:
+ void shape();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SHAPELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/SinLayer.cc b/runtime/onert/backend/cpu/kernel/SinLayer.cc
new file mode 100644
index 000000000..db8186ac6
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SinLayer.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2020 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 "SinLayer.h"
+#include "OperationUtils.h"
+
+#include <cker/operation/Elementwise.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+SinLayer::SinLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void SinLayer::sinFloat32()
+{
+ nnfw::cker::Sin(convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void SinLayer::sinQuant8() { throw std::runtime_error{"NYI"}; }
+
+void SinLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void SinLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ sinFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ sinQuant8();
+ }
+ else
+ {
+ throw std::runtime_error{"Sin: unsupported data type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/SinLayer.h b/runtime/onert/backend/cpu/kernel/SinLayer.h
new file mode 100644
index 000000000..7898cf050
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SinLayer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 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 riting, 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_BACKEND_CPU_KERNEL_SINLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SINLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+class SinLayer : public ::onert::exec::IFunction
+{
+public:
+ SinLayer();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ void sinFloat32();
+ void sinQuant8();
+
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SINLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/SliceLayer.cc b/runtime/onert/backend/cpu/kernel/SliceLayer.cc
new file mode 100644
index 000000000..1ade5fb44
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SliceLayer.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020 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 "SliceLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Slice.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+SliceLayer::SliceLayer() : _input(nullptr), _begin(nullptr), _size(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+template <typename T>
+void SliceLayer::GetBeginAndSizeVectors(int dimensions, const operand::Tensor *begin,
+ const operand::Tensor *size, std::vector<int> *begins,
+ std::vector<int> *sizes)
+{
+ for (int idx = dimensions - 1; idx >= 0; --idx)
+ {
+ begins->push_back(reinterpret_cast<T *>(begin->buffer())[idx]);
+ sizes->push_back(reinterpret_cast<T *>(size->buffer())[idx]);
+ }
+}
+
+void SliceLayer::sliceFloat32()
+{
+ const int kMaxDim = nnfw::cker::Shape::kMaxSmallSize;
+
+ std::vector<int> begins;
+ std::vector<int> sizes;
+ begins.reserve(kMaxDim);
+ sizes.reserve(kMaxDim);
+
+ GetBeginAndSizeVectors<int32_t>(_input->num_dimensions(), _begin, _size, &begins, &sizes);
+
+ // begins : 0-based, sizes : 1-based
+ for (int i = _input->num_dimensions(); i < kMaxDim; ++i)
+ {
+ begins.push_back(0);
+ sizes.push_back(1);
+ }
+
+ nnfw::cker::SliceParams op_params;
+ op_params.begin_count = 4;
+ op_params.size_count = 4;
+ for (int i = 0; i < 4; ++i)
+ {
+ op_params.begin[i] = begins[3 - i];
+ op_params.size[i] = sizes[3 - i];
+ }
+
+ nnfw::cker::Slice(op_params, convertToExtendedCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void SliceLayer::sliceQuant8()
+{
+ // cker quant8 slice is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void SliceLayer::configure(const operand::Tensor *input, const operand::Tensor *begin,
+ const operand::Tensor *size, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+ _begin = begin;
+ _size = size;
+}
+
+void SliceLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ sliceFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ sliceQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/SliceLayer.h b/runtime/onert/backend/cpu/kernel/SliceLayer.h
new file mode 100644
index 000000000..bb18c890c
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SliceLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_SLICELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SLICELAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class SliceLayer : public ::onert::exec::IFunction
+{
+public:
+ SliceLayer();
+
+public:
+ void configure(const operand::Tensor *input, const operand::Tensor *begin,
+ const operand::Tensor *size, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ void sliceFloat32();
+ void sliceQuant8();
+
+ template <typename T>
+ void GetBeginAndSizeVectors(int dimensions, const operand::Tensor *begin,
+ const operand::Tensor *size, std::vector<int> *begins,
+ std::vector<int> *sizes);
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_begin;
+ const operand::Tensor *_size;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SLICELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc
new file mode 100644
index 000000000..7a1ba48aa
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018 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 "SoftMaxLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/SoftMax.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+SoftMaxLayer::SoftMaxLayer() : _input(nullptr), _output(nullptr), _beta(0.0)
+{
+ // DO NOTHING
+}
+
+// Performs softmax along the input of size (input_size * batch_size).
+void Softmax(const float *in, const int input_size, const int batch_size, const float beta,
+ float *out)
+{
+ assert(input_size > 0);
+
+ // For each batch
+ for (int b = 0; b < batch_size; b++)
+ {
+ // Find the max coeff.
+ float max_coeff = in[0];
+ for (int i = 1; i < input_size; i++)
+ {
+ if (in[i] > max_coeff)
+ max_coeff = in[i];
+ }
+
+ // Compute the normalized sum of exps.
+ float exp_sum = 0.0;
+ for (int i = 0; i < input_size; i++)
+ {
+ out[i] = std::exp((in[i] - max_coeff) * beta);
+ exp_sum += out[i];
+ }
+
+ // Divide by the sum of exps.
+ float reciprocal_sum_exp = 1.f / exp_sum;
+ for (int i = 0; i < input_size; i++)
+ {
+ out[i] *= reciprocal_sum_exp;
+ }
+
+ // Advance in and out pointers for the next batch.
+ in += input_size;
+ out += input_size;
+ }
+}
+
+void SoftMaxLayer::softmaxFloat32()
+{
+ if (getNumberOfDimensions(_input) == 2)
+ {
+ uint32_t batch_size = getSizeOfDimension(_input, 0);
+ if (batch_size == 0)
+ throw std::runtime_error("batch_size should not be 0");
+
+ uint32_t input_size = getNumberOfElements(_input) / batch_size;
+ Softmax(reinterpret_cast<const float *>(_input->buffer()), input_size, batch_size, _beta,
+ reinterpret_cast<float *>(_output->buffer()));
+ }
+ else if (getNumberOfDimensions(_input) == 4)
+ {
+ nnfw::cker::SoftmaxParams op_params;
+ op_params.beta = _beta;
+ nnfw::cker::Softmax(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ }
+ else
+ {
+ throw std::runtime_error{"only 2D and 4D tensors supported"};
+ }
+}
+
+void SoftMaxLayer::softmaxQuant8()
+{
+ nnfw::cker::Shape descrIn4D(4);
+
+ if (getNumberOfDimensions(_input) == 2)
+ {
+ auto batch_size = getSizeOfDimension(_input, 0);
+ if (batch_size == 0)
+ throw std::runtime_error("batch_size should not be 0");
+
+ auto input_size = getNumberOfElements(_input) / batch_size;
+ descrIn4D.SetDim(0, batch_size);
+ descrIn4D.SetDim(1, 1);
+ descrIn4D.SetDim(2, 1);
+ descrIn4D.SetDim(3, input_size);
+ }
+ else if (getNumberOfDimensions(_input) == 4)
+ {
+ descrIn4D.SetDim(0, _input->dimension(0));
+ descrIn4D.SetDim(1, _input->dimension(1));
+ descrIn4D.SetDim(2, _input->dimension(2));
+ descrIn4D.SetDim(3, _input->dimension(3));
+ }
+ else
+ {
+ throw std::runtime_error{"only 2D and 4D tensors supported"};
+ }
+ if (_output->offset() != 0 || _output->scale() != 1.f / 256)
+ {
+ throw std::runtime_error{"incorrect scale / offset for output"};
+ }
+ static const int32_t kScaledDiffIntegerBits = 5;
+ const double input_beta_real_multiplier = std::min(
+ 1.0 * _beta * _input->scale() * (1 << (31 - kScaledDiffIntegerBits)), (1ll << 31) - 1.0);
+ int32_t input_multiplier = 0;
+ int32_t input_left_shift = 0;
+ QuantizeMultiplierGreaterThanOne(input_beta_real_multiplier, &input_multiplier,
+ &input_left_shift);
+ float diff_min = -1.0f * CalculateInputRadius(kScaledDiffIntegerBits, input_left_shift);
+
+ nnfw::cker::SoftmaxParams op_params;
+ op_params.input_multiplier = input_multiplier;
+ op_params.input_left_shift = input_left_shift;
+ op_params.diff_min = diff_min;
+ nnfw::cker::Softmax(op_params, descrIn4D, reinterpret_cast<const uint8_t *>(_input->buffer()),
+ descrIn4D, reinterpret_cast<uint8_t *>(_output->buffer()));
+}
+
+void SoftMaxLayer::configure(const operand::Tensor *input, const float beta,
+ operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+ _beta = beta;
+}
+
+void SoftMaxLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ softmaxFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ softmaxQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h
new file mode 100644
index 000000000..bb29b4fda
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 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_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class SoftMaxLayer : public ::onert::exec::IFunction
+{
+public:
+ SoftMaxLayer();
+
+public:
+ void softmaxFloat32();
+
+ void softmaxQuant8();
+
+ void configure(const operand::Tensor *input, const float beta, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+
+ float _beta;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/SplitLayer.cc b/runtime/onert/backend/cpu/kernel/SplitLayer.cc
new file mode 100644
index 000000000..e4c5ef3a0
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SplitLayer.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2020 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 "SplitLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Split.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+SplitLayer::SplitLayer() : _input(nullptr), _num_splits(0), _axis(0), _outputs()
+{
+ // DO NOTHING
+}
+
+void SplitLayer::splitFloat32()
+{
+ nnfw::cker::SplitParams op_params;
+ op_params.axis = _axis;
+ op_params.num_split = _num_splits;
+
+ std::vector<nnfw::cker::Shape *> outputDimsPtr;
+ std::vector<nnfw::cker::Shape> outputDims;
+ outputDimsPtr.reserve(_num_splits);
+ outputDims.reserve(_num_splits);
+
+ for (uint32_t i = 0; i < _num_splits; i++)
+ {
+ outputDims.push_back(convertTensorToCkerShape(_outputs[i]));
+ outputDimsPtr.push_back(&outputDims[i]);
+ }
+
+ std::vector<float *> outputFloatPtrs;
+
+ for (const auto output : _outputs)
+ {
+ outputFloatPtrs.emplace_back(reinterpret_cast<float *>(output->buffer()));
+ }
+
+ nnfw::cker::Split<float>(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<float *>(_input->buffer()),
+ convertTensorToCkerShape(_outputs[0]), outputFloatPtrs.data());
+}
+
+void SplitLayer::splitQuant8() { throw std::runtime_error{"Split: NYI quant8 type"}; }
+
+void SplitLayer::configure(const operand::Tensor *input, uint16_t num_splits, int16_t axis,
+ std::vector<operand::Tensor *> &outputs)
+{
+ assert(input != nullptr);
+
+ _num_splits = num_splits;
+ _input = input;
+ _axis = axis;
+ _outputs = outputs;
+}
+
+void SplitLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ splitFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ splitQuant8();
+ }
+ else
+ {
+ throw std::runtime_error{"Split: Unsupported input type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/SplitLayer.h b/runtime/onert/backend/cpu/kernel/SplitLayer.h
new file mode 100644
index 000000000..9f236f0af
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SplitLayer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_SPLITLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SPLITLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class SplitLayer : public ::onert::exec::IFunction
+{
+public:
+ SplitLayer();
+
+public:
+ void splitFloat32();
+
+ void splitQuant8();
+
+ void configure(const operand::Tensor *input, uint16_t num_splits, int16_t axis,
+ std::vector<operand::Tensor *> &outputs);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ uint16_t _num_splits;
+ int16_t _axis;
+ std::vector<operand::Tensor *> _outputs;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SPLITLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc
new file mode 100644
index 000000000..22315c7c6
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2020 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 "StridedSliceLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/StridedSlice.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+StridedSliceLayer::StridedSliceLayer()
+ : _input(nullptr), _begin(nullptr), _end(nullptr), _strides(nullptr), _output(nullptr),
+ _begin_mask(0), _ellipsis_mask(0), _end_mask(0), _new_axis_mask(0), _shrink_axis_mask(0),
+ _rank(0)
+{
+}
+
+void StridedSliceLayer::stridedSliceFloat32()
+{
+ auto op_params = nnfw::cker::buildStridedSliceParams(
+ reinterpret_cast<uint32_t *>(_begin->buffer()), reinterpret_cast<uint32_t *>(_end->buffer()),
+ reinterpret_cast<uint32_t *>(_strides->buffer()), _begin_mask, _end_mask, _shrink_axis_mask,
+ _rank);
+
+ nnfw::cker::checkOutputSize(op_params, convertTensorToCkerShape(_input),
+ convertTensorToCkerShape(_output), _rank);
+
+ nnfw::cker::StridedSlice(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+}
+
+void StridedSliceLayer::stridedSliceQuant8()
+{
+ // cker quant8 stridedSlice is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void StridedSliceLayer::configure(const operand::Tensor *input, const operand::Tensor *begin,
+ const operand::Tensor *end, const operand::Tensor *strides,
+ operand::Tensor *output, const int32_t begin_mask,
+ const int32_t end_mask, const int32_t shrink_axis_mask,
+ const int32_t rank)
+{
+ _input = input;
+ _begin = begin;
+ _end = end;
+ _strides = strides;
+ _output = output;
+
+ _rank = rank;
+ _begin_mask = begin_mask;
+ _ellipsis_mask = 0;
+ _end_mask = end_mask;
+ _new_axis_mask = 0;
+ _shrink_axis_mask = shrink_axis_mask;
+}
+
+void StridedSliceLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ stridedSliceFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ stridedSliceQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h
new file mode 100644
index 000000000..7888eff3c
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class StridedSliceLayer : public ::onert::exec::IFunction
+{
+public:
+ StridedSliceLayer();
+
+public:
+ void configure(const operand::Tensor *input, const operand::Tensor *begin,
+ const operand::Tensor *end, const operand::Tensor *strides,
+ operand::Tensor *output, const int32_t begin_mask, const int32_t end_mask,
+ const int32_t shrink_axis_mask, const int32_t rank);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ void stridedSliceFloat32();
+ void stridedSliceQuant8();
+
+private:
+ const operand::Tensor *_input;
+ const operand::Tensor *_begin;
+ const operand::Tensor *_end;
+ const operand::Tensor *_strides;
+ operand::Tensor *_output;
+
+ int32_t _begin_mask;
+ int32_t _ellipsis_mask;
+ int32_t _end_mask;
+ int32_t _new_axis_mask;
+ int32_t _shrink_axis_mask;
+
+ int32_t _rank;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/SubLayer.cc b/runtime/onert/backend/cpu/kernel/SubLayer.cc
new file mode 100644
index 000000000..15aa43835
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SubLayer.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019 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 "SubLayer.h"
+
+#include <cker/operation/BinaryArithmeticOps.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+void SubLayer::subFloat32()
+{
+ float output_activation_min, output_activation_max;
+ CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max);
+ nnfw::cker::BinaryArithmeticOpParam op_params;
+ op_params.type = nnfw::cker::BinaryArithmeticOpType::SUB;
+ op_params.float_activation_max = output_activation_max;
+ op_params.float_activation_min = output_activation_min;
+
+ if (!HaveSameShapes(_lhs, _rhs))
+ {
+ nnfw::cker::BroadcastBinaryArithmeticOpSlow(
+ op_params, convertToExtendedCkerShape(_lhs),
+ reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs),
+ reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output),
+ reinterpret_cast<float *>(_output->buffer()));
+ return;
+ }
+
+ nnfw::cker::BinaryArithmeticOp(
+ op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()),
+ convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void SubLayer::subQuant8()
+{
+ int32_t output_activation_min, output_activation_max;
+ CalculateActivationRangeUint8(_activation, _output, &output_activation_min,
+ &output_activation_max);
+ // nnfw::cker::SubParam op_params;
+ // op_params.quantized_activation_max = output_activation_max;
+ // op_params.quantized_activation_min = output_activation_min;
+
+ // cker quant8 sub is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void SubLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output)
+{
+ _lhs = lhs;
+ _rhs = rhs;
+ _activation = activation;
+ _output = output;
+}
+
+void SubLayer::run()
+{
+ if (_output->data_type() == OperandType::FLOAT32)
+ {
+ subFloat32();
+ }
+ else if (_output->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ subQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/SubLayer.h b/runtime/onert/backend/cpu/kernel/SubLayer.h
new file mode 100644
index 000000000..48fa97669
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/SubLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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_BACKEND_CPU_KERNEL_SUBLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_SUBLAYER_H__
+
+#include "../operand/Tensor.h"
+#include "OperationUtils.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class SubLayer : public ::onert::exec::IFunction
+{
+public:
+ SubLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr)
+ {
+ // DO NOTHING
+ }
+
+public:
+ void subFloat32();
+
+ void subQuant8();
+
+ void configure(const operand::Tensor *lhs, const operand::Tensor *rhs,
+ const ir::Activation activation, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_lhs;
+ const operand::Tensor *_rhs;
+ operand::Tensor *_output;
+
+ ir::Activation _activation{ir::Activation::NONE};
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_SUBLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/TanhLayer.cc b/runtime/onert/backend/cpu/kernel/TanhLayer.cc
new file mode 100644
index 000000000..6a9274f7a
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/TanhLayer.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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 "TanhLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Tanh.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+TanhLayer::TanhLayer() : _input(nullptr), _output(nullptr)
+{
+ // DO NOTHING
+}
+
+void TanhLayer::tanhFloat32()
+{
+ nnfw::cker::Tanh(convertTensorToCkerShape(_input),
+ reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void TanhLayer::tanhQuant8()
+{
+ // cker quant8 tanh is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void TanhLayer::configure(const operand::Tensor *input, operand::Tensor *output)
+{
+ _input = input;
+ _output = output;
+}
+
+void TanhLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ tanhFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ tanhQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/TanhLayer.h b/runtime/onert/backend/cpu/kernel/TanhLayer.h
new file mode 100644
index 000000000..8fb621cdb
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/TanhLayer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_TANHLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_TANHLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class TanhLayer : public ::onert::exec::IFunction
+{
+public:
+ TanhLayer();
+
+public:
+ void tanhFloat32();
+
+ void tanhQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_TANHLAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/TransposeLayer.cc b/runtime/onert/backend/cpu/kernel/TransposeLayer.cc
new file mode 100644
index 000000000..31b1dd12d
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/TransposeLayer.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 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 "TransposeLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Transpose.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+TransposeLayer::TransposeLayer() : _input(nullptr), _output(nullptr), _perm(), _rank(0)
+{
+ // DO NOTHING
+}
+
+void TransposeLayer::transposeFloat32()
+{
+ nnfw::cker::TransposeParams param;
+ param.perm_count = _rank;
+ for (int32_t i = 0; i < _rank; i++)
+ {
+ param.perm[i] = _perm[i];
+ }
+
+ nnfw::cker::Transpose(
+ param, convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()),
+ convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()));
+}
+
+void TransposeLayer::transposeQuant8()
+{
+ // cker quant8 tanh is not implemented yet
+ throw std::runtime_error{"NYI"};
+}
+
+void TransposeLayer::configure(const operand::Tensor *input, operand::Tensor *output,
+ const std::vector<int> &perm, int32_t rank)
+{
+ _input = input;
+ _rank = rank;
+ _perm = perm;
+ _output = output;
+}
+
+void TransposeLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ transposeFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ transposeQuant8();
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/TransposeLayer.h b/runtime/onert/backend/cpu/kernel/TransposeLayer.h
new file mode 100644
index 000000000..ffe7c2ae5
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/TransposeLayer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class TransposeLayer : public ::onert::exec::IFunction
+{
+public:
+ TransposeLayer();
+
+public:
+ void transposeFloat32();
+
+ void transposeQuant8();
+
+ void configure(const operand::Tensor *input, operand::Tensor *output,
+ const std::vector<int> &perm, int32_t rank);
+
+ void run();
+ void runSync() { run(); }
+
+private:
+ const operand::Tensor *_input;
+ operand::Tensor *_output;
+ std::vector<int> _perm;
+ int32_t _rank;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__
diff --git a/runtime/onert/backend/cpu/kernel/UnpackLayer.cc b/runtime/onert/backend/cpu/kernel/UnpackLayer.cc
new file mode 100644
index 000000000..fe07e3e19
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/UnpackLayer.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2020 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 "UnpackLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/Unpack.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+UnpackLayer::UnpackLayer() : _input(nullptr), _outputs(), _axis(0), _num_output(0)
+{
+ // DO NOTHING
+}
+
+void UnpackLayer::unpackFloat32()
+{
+ nnfw::cker::UnpackParams op_params;
+ op_params.axis = _axis;
+ op_params.num_split = _num_output;
+
+ std::vector<nnfw::cker::Shape *> outputDimsPtr;
+ std::vector<nnfw::cker::Shape> outputDims;
+ outputDimsPtr.reserve(_num_output);
+ outputDims.reserve(_num_output);
+
+ for (int32_t i = 0; i < _num_output; i++)
+ {
+ outputDims.push_back(convertTensorToCkerShape(_outputs[i]));
+ outputDimsPtr.push_back(&outputDims[i]);
+ }
+
+ std::vector<float *> outputFloatPtrs;
+
+ for (const auto output : _outputs)
+ {
+ outputFloatPtrs.emplace_back(reinterpret_cast<float *>(output->buffer()));
+ }
+
+ nnfw::cker::Unpack<float>(op_params, convertTensorToCkerShape(_input),
+ reinterpret_cast<float *>(_input->buffer()),
+ convertTensorToCkerShape(_outputs[0]), outputFloatPtrs.data());
+}
+
+void UnpackLayer::unpackQuant8()
+{
+ // cker quant8 pack is not implemented yet
+ throw std::runtime_error{"Unpack: NYI quant8 type"};
+}
+
+void UnpackLayer::configure(const operand::Tensor *input, uint32_t axis, int32_t num,
+ std::vector<operand::Tensor *> &outputs)
+{
+ assert(input != nullptr);
+ assert(outputs.size() > 0);
+ assert(outputs.size() == (size_t)num);
+
+ _input = input;
+ _axis = axis;
+ _num_output = num;
+ _outputs = outputs;
+}
+
+void UnpackLayer::run()
+{
+ if (_input->data_type() == OperandType::FLOAT32)
+ {
+ unpackFloat32();
+ }
+ else if (_input->data_type() == OperandType::QUANT8_ASYMM)
+ {
+ unpackQuant8();
+ }
+ else
+ {
+ throw std::runtime_error{"Unpack: Unsupported input type"};
+ }
+}
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/cpu/kernel/UnpackLayer.h b/runtime/onert/backend/cpu/kernel/UnpackLayer.h
new file mode 100644
index 000000000..23d064db2
--- /dev/null
+++ b/runtime/onert/backend/cpu/kernel/UnpackLayer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 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_BACKEND_CPU_KERNEL_UNPACKLAYER_H__
+#define __ONERT_BACKEND_CPU_KERNEL_UNPACKLAYER_H__
+
+#include "../operand/Tensor.h"
+
+#include <exec/IFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace cpu
+{
+namespace kernel
+{
+
+class UnpackLayer : public ::onert::exec::IFunction
+{
+public:
+ UnpackLayer();
+
+public:
+ void unpackFloat32();
+
+ void unpackQuant8();
+
+ void configure(const operand::Tensor *input, uint32_t axis, int32_t num_output,
+ std::vector<operand::Tensor *> &output);
+
+ void run();
+ void runSync()
+ {
+ // this abstract method is used just for profiling and called for
+ // backend::acl_common::AclFunction
+ run();
+ }
+
+private:
+ const operand::Tensor *_input;
+ std::vector<operand::Tensor *> _outputs;
+ uint32_t _axis;
+ int32_t _num_output;
+};
+
+} // namespace kernel
+} // namespace cpu
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_CPU_KERNEL_UNPACKLAYER_H__