2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef __ONERT_EXEC_SINK_H__
18 #define __ONERT_EXEC_SINK_H__
20 #include "feature/nchw/Reader.h"
21 #include "feature/nchw/View.h"
22 #include "feature/nhwc/Reader.h"
23 #include "feature/nhwc/View.h"
27 #include "util/Utils.h"
28 #include <misc/feature/IndexIterator.h>
36 virtual ~ISink() = default;
38 virtual void pull(::onert::backend::ITensor &tensor) const = 0;
41 // Create second lever inheritance: the first lever is used as a reference type in use-case places
42 template <typename T> class ITemplSink : public ISink
45 ITemplSink(void *output_buffer, const size_t &output_size, const ir::Shape &shape,
46 const bool copy, ir::Layout io_layout)
47 : _output_buffer{reinterpret_cast<T *>(output_buffer)}, _output_size{output_size},
48 _shape{shape}, _copy{copy}, _io_layout{io_layout}
53 void pullUnif(onert::backend::ITensor &tensor) const
55 assert(((_io_layout == ir::Layout::NHWC && tensor.layout() == ir::Layout::NCHW) ||
56 (_io_layout == ir::Layout::NCHW && tensor.layout() == ir::Layout::NHWC)) ||
58 auto input_buffer = tensor.buffer();
59 auto rank = _shape.rank();
61 if (!tensor.has_padding() && rank < 4 + _copy)
63 memcpy(_output_buffer, input_buffer, _output_size);
72 memcpy(_output_buffer, input_buffer, _output_size);
77 const int32_t copy_len = _shape.dim(1);
79 for (auto i = 0; i < _shape.dim(0); ++i)
81 ir::Coordinates coords{i, 0};
82 memcpy(_output_buffer + i * copy_len, input_buffer + tensor.calcOffset(coords),
83 copy_len * sizeof(T));
89 const int32_t dim1 = _shape.dim(1);
90 const int32_t dim2 = _shape.dim(2);
92 for (auto i = 0; i < _shape.dim(0); ++i)
94 for (auto j = 0; j < _shape.dim(1); ++j)
96 ir::Coordinates coords{i, j, 0};
97 memcpy(_output_buffer + i * dim1 * dim2 + j * dim2,
98 input_buffer + tensor.calcOffset(coords), dim2 * sizeof(T));
107 const int32_t dim1 = _shape.dim(1);
108 const int32_t dim2 = _shape.dim(2);
109 const int32_t dim3 = _shape.dim(3);
111 for (auto i = 0; i < _shape.dim(0); ++i)
113 for (auto j = 0; j < _shape.dim(1); ++j)
115 for (auto k = 0; k < _shape.dim(2); ++k)
117 ir::Coordinates coords{i, j, k, 0};
118 memcpy(_output_buffer + i * dim1 * dim2 * dim3 + j * dim2 * dim3 + k * dim3,
119 input_buffer + tensor.calcOffset(coords), dim3 * sizeof(T));
126 const auto shape = _shape.asFeature(_io_layout);
128 if (_io_layout == ir::Layout::NHWC)
130 const exec::feature::nchw::Reader<T> from(&tensor);
131 exec::feature::nhwc::View<T> into(shape, _output_buffer, _output_size);
132 feature::iterate(shape)
133 << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
134 const auto value = from.at(batch, ch, row, col);
135 into.at(batch, row, col, ch) = value;
138 else if (_io_layout == ir::Layout::NCHW)
140 const exec::feature::nhwc::Reader<T> from(&tensor);
141 exec::feature::nchw::View<T> into(shape, _output_buffer, _output_size);
142 feature::iterate(shape)
143 << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
144 const auto value = from.at(batch, row, col, ch);
145 into.at(batch, ch, row, col) = value;
150 throw std::runtime_error("Wrong Layout");
156 throw std::runtime_error("NYI: rank > 4");
163 const size_t _output_size;
164 const ir::Shape _shape;
166 const ir::Layout _io_layout;
169 template <typename T> class PermutateSink final : public ITemplSink<T>
172 PermutateSink(void *output_buffer, const size_t &output_size, const ir::Shape &shape,
173 ir::Layout io_layout)
174 : ITemplSink<T>(output_buffer, output_size, shape, false, io_layout)
179 void pull(onert::backend::ITensor &tensor) const override { ITemplSink<T>::pullUnif(tensor); }
182 // Only supports NHWC format front-end(NNAPI) now
183 template <typename T> class CopySink final : public ITemplSink<T>
186 CopySink(void *output_buffer, const size_t &output_size, const ir::Shape &shape,
187 ir::Layout io_layout = ir::Layout::UNKNOWN)
188 : ITemplSink<T>(output_buffer, output_size, shape, true, io_layout)
193 void pull(onert::backend::ITensor &tensor) const override { ITemplSink<T>::pullUnif(tensor); }
199 #endif // __ONERT_EXEC_SINK_H__