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_SOURCE_H__
18 #define __ONERT_EXEC_SOURCE_H__
20 #include "feature/IndexIterator.h"
21 #include "feature/nchw/Reader.h"
22 #include "feature/nchw/View.h"
23 #include "feature/nhwc/Reader.h"
24 #include "feature/nhwc/View.h"
28 #include "util/Utils.h"
29 #include <ir/Layout.h>
39 virtual ~ISource() = default;
41 virtual void push(::onert::backend::ITensor &tensor) const = 0;
44 // Create second lever inheritance: the first lever is used as a reference type in use-case places
45 template <typename T> class ITemplSource : public ISource
48 ITemplSource(const void *input_buffer, const size_t &input_size, const ir::Shape &shape,
49 const bool copy, ir::Layout io_layout)
50 : _input_buffer{reinterpret_cast<const T *>(input_buffer)}, _input_size{input_size},
51 _shape{shape}, _copy(copy), _io_layout{io_layout}
55 virtual void push(::onert::backend::ITensor &tensor) const = 0;
58 void pushUnif(onert::backend::ITensor &tensor) const
60 assert(((_io_layout == ir::Layout::NHWC && tensor.layout() == ir::Layout::NCHW) ||
61 (_io_layout == ir::Layout::NCHW && tensor.layout() == ir::Layout::NHWC)) ||
63 auto output_buffer = tensor.buffer();
64 auto rank = _shape.rank();
66 if (!tensor.has_padding() && rank < 4 + _copy)
68 memcpy(output_buffer, _input_buffer, _input_size);
77 memcpy(output_buffer, _input_buffer, _input_size);
82 const int32_t copy_len = _shape.dim(1);
84 for (auto i = 0; i < _shape.dim(0); ++i)
86 ir::Coordinates coords{i, 0};
87 memcpy(output_buffer + tensor.calcOffset(coords), _input_buffer + i * copy_len,
88 copy_len * sizeof(T));
94 const int32_t dim1 = _shape.dim(1);
95 const int32_t dim2 = _shape.dim(2);
97 for (auto i = 0; i < _shape.dim(0); ++i)
99 for (auto j = 0; j < _shape.dim(1); ++j)
101 ir::Coordinates coords{i, j, 0};
102 memcpy(output_buffer + tensor.calcOffset(coords),
103 _input_buffer + i * dim1 * dim2 + j * dim2, dim2 * sizeof(T));
112 const int32_t dim1 = _shape.dim(1);
113 const int32_t dim2 = _shape.dim(2);
114 const int32_t dim3 = _shape.dim(3);
115 for (auto i = 0; i < _shape.dim(0); ++i)
117 for (auto j = 0; j < _shape.dim(1); ++j)
119 for (auto k = 0; k < _shape.dim(2); ++k)
121 ir::Coordinates coords{i, j, k, 0};
122 memcpy(output_buffer + tensor.calcOffset(coords),
123 _input_buffer + i * dim1 * dim2 * dim3 + j * dim2 * dim3 + k * dim3,
131 const auto shape = _shape.asFeature(_io_layout);
133 if (_io_layout == ir::Layout::NCHW)
135 const exec::feature::nchw::Reader<T> from(shape, _input_buffer, _input_size);
136 exec::feature::nhwc::View<T> into(&tensor);
137 feature::iterate(shape)
138 << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
139 const auto value = from.at(batch, ch, row, col);
140 into.at(batch, row, col, ch) = value;
143 else if (_io_layout == ir::Layout::NHWC)
145 const exec::feature::nhwc::Reader<T> from(shape, _input_buffer, _input_size);
146 exec::feature::nchw::View<T> into(&tensor);
147 feature::iterate(shape)
148 << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
149 const auto value = from.at(batch, row, col, ch);
150 into.at(batch, ch, row, col) = value;
155 throw std::runtime_error("Wrong Layout");
162 throw std::runtime_error("NYI: rank > 4");
168 const T *_input_buffer;
169 const size_t _input_size;
170 const ir::Shape _shape;
172 const ir::Layout _io_layout;
175 template <typename T> class PermutateSource final : public ITemplSource<T>
178 PermutateSource(const void *input_buffer, const size_t &input_size, const ir::Shape &shape,
179 ir::Layout io_layout)
180 : ITemplSource<T>(input_buffer, input_size, shape, false, io_layout)
185 void push(onert::backend::ITensor &tensor) const override
187 // do NHWC_TO_NCHW or NCHW_TO_NHWC permutation
188 ITemplSource<T>::pushUnif(tensor);
192 template <typename T> class CopySource final : public ITemplSource<T>
195 CopySource(const void *input_buffer, const size_t &input_size, const ir::Shape &shape,
196 ir::Layout io_layout = ir::Layout::UNKNOWN)
197 : ITemplSource<T>(input_buffer, input_size, shape, true, io_layout)
202 void push(onert::backend::ITensor &tensor) const override { ITemplSource<T>::pushUnif(tensor); }
208 #endif // __ONERT_EXEC_SOURCE_H__