summaryrefslogtreecommitdiff
path: root/libs/kernel/acl/src/IO_accessor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/kernel/acl/src/IO_accessor.cpp')
-rw-r--r--libs/kernel/acl/src/IO_accessor.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/libs/kernel/acl/src/IO_accessor.cpp b/libs/kernel/acl/src/IO_accessor.cpp
new file mode 100644
index 000000000..410fb8ea5
--- /dev/null
+++ b/libs/kernel/acl/src/IO_accessor.cpp
@@ -0,0 +1,310 @@
+/*
+ * 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 "IO_accessor.h"
+
+#include <cassert>
+
+namespace nnfw {
+namespace kernel {
+namespace acl {
+
+InputAccessor::InputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape)
+ : _inputData(inputData)
+ , _inputShape(inputShape)
+{
+}
+
+MatrixInputAccessor::MatrixInputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape)
+ : _inputData(inputData)
+ , _inputShape(inputShape)
+{
+}
+
+VectorInputAccessor::VectorInputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape)
+ : _inputData(inputData)
+ , _inputShape(inputShape)
+{
+}
+
+WeightAccessor::WeightAccessor(const float* filterData, const nnfw::rt::Shape& filterShape)
+ : _filterData(filterData)
+ , _filterShape(filterShape)
+{
+}
+
+MatrixWeightAccessor::MatrixWeightAccessor(const float* filterData, const nnfw::rt::Shape& filterShape)
+ : _filterData(filterData)
+ , _filterShape(filterShape)
+{
+}
+
+BiasAccessor::BiasAccessor(const float* biasData, const nnfw::rt::Shape& biasShape)
+ : _biasData(biasData)
+ , _biasShape(biasShape)
+{
+}
+
+OutputAccessor::OutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape)
+ : _outputData(outputData)
+ , _outputShape(outputShape)
+{
+}
+
+MatrixOutputAccessor::MatrixOutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape)
+ : _outputData(outputData)
+ , _outputShape(outputShape)
+{
+}
+
+VectorOutputAccessor::VectorOutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape)
+ : _outputData(outputData)
+ , _outputShape(outputShape)
+{
+}
+
+static uint32_t getOffsetNCHW(const nnfw::rt::Shape& shape, const arm_compute::Coordinates& id)
+{
+ // get offset for ACL(NCHW) from data of NNAPI(NHWC)
+ uint32_t num = getSizeOfDimension(shape, 0);
+ uint32_t height = getSizeOfDimension(shape, 1);
+ uint32_t width = getSizeOfDimension(shape, 2);
+ uint32_t chann = getSizeOfDimension(shape, 3);
+ uint32_t stride = 1;
+ uint32_t offset = 0;
+ uint32_t numdim = id.num_dimensions();
+ offset += numdim > 0 ? id[0] * stride : 0; stride *= width;
+ offset += numdim > 1 ? id[1] * stride : 0; stride *= height;
+ offset += numdim > 2 ? id[2] * stride : 0; stride *= chann;
+ offset += numdim > 3 ? id[3] * stride : 0; stride *= num;
+ return offset;
+}
+
+static uint32_t getElementOffset(const nnfw::rt::Shape& shape,
+ uint32_t ch, uint32_t row, uint32_t col)
+{
+ assert(getSizeOfDimension(shape, 0) == 1);
+ assert(shape.dimensions.size() == 4);
+
+ // TODO Optimize this!
+ const uint32_t W = getSizeOfDimension(shape, 2);
+ const uint32_t C = getSizeOfDimension(shape, 3);
+
+ int offset = 0;
+
+ // NNAPI uses NHWC ordering
+ offset += row * W * C;
+ offset += col * C;
+ offset += ch;
+
+ return offset;
+}
+
+static uint32_t getElementOffset(const nnfw::rt::Shape& shape,
+ uint32_t nth, uint32_t ch, uint32_t row, uint32_t col)
+{
+ assert(shape.dimensions.size() == 4);
+
+ // TODO Optimize this!
+ const uint32_t H = getSizeOfDimension(shape, 1);
+ const uint32_t W = getSizeOfDimension(shape, 2);
+ const uint32_t C = getSizeOfDimension(shape, 3);
+
+ int offset = 0;
+
+ // NNAPI uses NHWC ordering
+ offset += nth * H * W * C;
+ offset += row * W * C;
+ offset += col * C;
+ offset += ch;
+
+ return offset;
+}
+
+bool InputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const uint32_t ch = id[2];
+ const uint32_t row = id[1];
+ const uint32_t col = id[0];
+
+ uint32_t offset = getElementOffset(_inputShape, ch, row, col);
+
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_inputData + offset);
+ });
+ return true;
+}
+
+bool MatrixInputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ assert(tensor.info()->tensor_shape().num_dimensions() <= 2);
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const auto row = id[1];
+ const auto col = id[0];
+ const auto W = tensor.info()->tensor_shape().x();
+
+ const auto offset = row * W + col;
+
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_inputData + offset);
+ });
+ return true;
+}
+
+bool VectorInputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ assert(tensor.info()->tensor_shape().num_dimensions() == 1);
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ uint32_t offset = id[0];
+
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_inputData + offset);
+ });
+ return true;
+}
+
+bool WeightAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const uint32_t nth = id[3];
+ const uint32_t ch = id[2];
+ const uint32_t row = id[1];
+ const uint32_t col = id[0];
+
+ uint32_t offset = getElementOffset(_filterShape, nth, ch, row, col);
+
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_filterData + offset);
+ });
+ return true;
+}
+
+bool MatrixWeightAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ assert(tensor.info()->tensor_shape().num_dimensions() <= 2);
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const auto row = id[1];
+ const auto col = id[0];
+ const auto W = tensor.info()->tensor_shape().x();
+
+ uint32_t offset = row * W + col;
+
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_filterData + offset);
+ });
+ return true;
+}
+
+bool BiasAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ uint32_t offset = getOffsetNCHW(_biasShape, id);
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id)) =
+ *(_biasData + offset);
+ });
+ return true;
+}
+
+bool OutputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const uint32_t ch = id[2];
+ const uint32_t row = id[1];
+ const uint32_t col = id[0];
+
+ uint32_t offset = getElementOffset(_outputShape, ch, row, col);
+
+ *(_outputData + offset) =
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id));
+ });
+ return false; // end the network
+}
+
+bool VectorOutputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ assert(tensor.info()->tensor_shape().num_dimensions() == 1);
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const uint32_t x = id[0];
+
+ uint32_t offset = x;
+
+ *(_outputData + offset) =
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id));
+ });
+ return false; // end the network
+}
+
+bool MatrixOutputAccessor::access_tensor(arm_compute::ITensor &tensor)
+{
+ arm_compute::Window window;
+ window.use_tensor_dimensions(tensor.info()->tensor_shape());
+
+ assert(tensor.info()->tensor_shape().num_dimensions() <= 2);
+
+ execute_window_loop(window, [&](const arm_compute::Coordinates& id)
+ {
+ const auto row = id[1];
+ const auto col = id[0];
+ const auto W = tensor.info()->tensor_shape().x();
+
+ const auto offset = row * W + col;
+
+ *(_outputData + offset) =
+ *reinterpret_cast<float *>(tensor.ptr_to_element(id));
+ });
+ return false; // end the network
+}
+
+} // namespace acl
+} // namespace kernel
+} // namespace nnfw