2 * Copyright (c) 2019 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 __BASE_LOADER_BASE_LOADER_H__
18 #define __BASE_LOADER_BASE_LOADER_H__
22 #include "ir/Operations.Include.h"
24 #include "flatbuffers/flexbuffers.h"
34 #include <util/logging.h>
41 template <typename LoaderDomain, typename SpecificLoader> class BaseLoader
44 using Verifier = typename LoaderDomain::Verifier;
45 using ActivationFunctionType = typename LoaderDomain::ActivationFunctionType;
46 using Buffer = typename LoaderDomain::Buffer;
47 using BuiltinOperator = typename LoaderDomain::BuiltinOperator;
48 using CustomOptionsFormat = typename LoaderDomain::CustomOptionsFormat;
49 using Model = typename LoaderDomain::Model;
50 using Operator = typename LoaderDomain::Operator;
51 using Padding = typename LoaderDomain::Padding;
52 using Pool2DOptions = typename LoaderDomain::Pool2DOptions;
53 using SubGraph = typename LoaderDomain::SubGraph;
54 using Tensor = typename LoaderDomain::Tensor;
55 using TensorType = typename LoaderDomain::TensorType;
56 using DimensionType = typename LoaderDomain::DimensionType;
57 using SparseIndexVector = typename LoaderDomain::SparseIndexVector;
60 bool isOptionalInputTensor(std::int32_t idx) { return idx == -1; }
61 virtual bool allowOptionalInputTensor(BuiltinOperator) = 0;
65 * @brief Construct a new Loader object
67 * @param graph reference on subgraphs
69 explicit BaseLoader(std::unique_ptr<ir::Subgraphs> &subgs)
70 : _base{nullptr}, _pagesize(getpagesize()), _fd(-1), _subgraphs(subgs), _model{nullptr}
75 * @brief Load a model from file
79 void loadFromFile(const char *file_path);
81 * @brief Load a model from a buffer
83 * @param buffer buffer pointer
84 * @param size buffer size
86 void loadFromBuffer(uint8_t *buffer, size_t size);
89 ~BaseLoader() = default;
93 ir::Activation convertActivation(ActivationFunctionType type);
94 ir::DataType tensorTypeToDataType(TensorType type);
95 ir::OperandIndex tensorIdxToOperandIdx(int32_t tensorIdx);
96 void deallocateMmappedArea(uint8_t *ptr, size_t size);
98 // Create operands form tflite::Tensor
99 ir::OperandIndex loadOperand(const Tensor *tensor, ir::Graph &subg);
100 void loadOperationIO(const Operator *op, ir::OperandIndexSequence &inputs,
101 ir::OperandIndexSequence &outputs);
102 // Create operations from Operator
103 void loadOperation(const Operator *op, ir::Graph &subg);
104 // Load Strides and Paddings from options to param
105 template <typename Param, typename OptionsType>
106 void loadStridesAndPaddings(Param ¶m, const OptionsType *options);
108 template <typename Param> void loadPool2D(Param ¶m, const Pool2DOptions *options);
111 void loadConv2D(const Operator *op, ir::Graph &subg);
112 void loadDepthwiseConv2D(const Operator *op, ir::Graph &subg);
113 void loadTransposeConv(const Operator *op, ir::Graph &subg);
114 void loadAvgPool2D(const Operator *op, ir::Graph &subg);
115 void loadReshape(const Operator *op, ir::Graph &subg);
116 void loadSoftmax(const Operator *op, ir::Graph &subg);
117 void loadMaxPool2D(const Operator *op, ir::Graph &subg);
118 void loadConcatenation(const Operator *op, ir::Graph &subg);
119 void loadFill(const Operator *op, ir::Graph &subg);
120 void loadFC(const Operator *op, ir::Graph &subg);
121 void loadAdd(const Operator *op, ir::Graph &subg);
122 void loadSub(const Operator *op, ir::Graph &subg);
123 void loadMul(const Operator *op, ir::Graph &subg);
124 void loadDiv(const Operator *op, ir::Graph &subg);
125 void loadPack(const Operator *op, ir::Graph &subg);
126 void loadRelu(const Operator *op, ir::Graph &subg);
127 void loadRelu6(const Operator *op, ir::Graph &subg);
128 void loadResizeBilinear(const Operator *op, ir::Graph &subg);
129 void loadRsqrt(const Operator *op, ir::Graph &subg);
130 void loadSelect(const Operator *op, ir::Graph &subg);
131 void loadSqrt(const Operator *op, ir::Graph &subg);
132 void loadSquaredDifference(const Operator *op, ir::Graph &subg);
133 void loadTanh(const Operator *op, ir::Graph &subg);
134 void loadTranspose(const Operator *op, ir::Graph &subg);
135 void loadReduce(const Operator *op, ir::Graph &subg,
136 ir::operation::Reduce::ReduceType reduce_type);
137 void loadReduceAll(const Operator *op, ir::Graph &subg);
138 void loadReverseV2(const Operator *op, ir::Graph &subg);
139 void loadPad(const Operator *op, ir::Graph &subg);
140 void loadLogistic(const Operator *op, ir::Graph &subg);
141 void loadExp(const Operator *op, ir::Graph &subg);
142 void loadExpandDims(const Operator *op, ir::Graph &subg);
143 void loadGather(const Operator *op, ir::Graph &subg);
144 void loadCustom(const Operator *op, ir::Graph &subg);
145 void loadSpaceToBatchND(const Operator *op, ir::Graph &subg);
146 void loadBatchMatMul(const Operator *op, ir::Graph &subg);
147 void loadBatchToSpaceND(const Operator *op, ir::Graph &subg);
148 void loadSqueeze(const Operator *op, ir::Graph &subg);
149 void loadPrelu(const Operator *op, ir::Graph &subg);
150 void loadSplit(const Operator *op, ir::Graph &subg);
151 void loadSplitV(const Operator *op, ir::Graph &subg);
152 void loadSlice(const Operator *op, ir::Graph &subg);
153 void loadStridedSlice(const Operator *op, ir::Graph &subg);
154 void loadUnpack(const Operator *op, ir::Graph &subg);
155 void loadMinimum(const Operator *op, ir::Graph &subg);
156 void loadMaximum(const Operator *op, ir::Graph &subg);
157 void loadCast(const Operator *op, ir::Graph &subg);
158 void loadComparison(const Operator *op, ir::Graph &subg);
159 void loadEinsum(const Operator *op, ir::Graph &subg);
160 void loadOneHot(const Operator *op, ir::Graph &subg);
161 void loadAbs(const Operator *op, ir::Graph &subg);
162 void loadCos(const Operator *op, ir::Graph &subg);
163 void loadSin(const Operator *op, ir::Graph &subg);
164 void loadShape(const Operator *op, ir::Graph &subg);
165 void loadIf(const Operator *op, ir::Graph &subg);
166 void loadWhile(const Operator *op, ir::Graph &subg);
167 void loadNeg(const Operator *op, ir::Graph &subg);
168 void loadLog(const Operator *op, ir::Graph &subg);
169 void loadArgMax(const Operator *op, ir::Graph &subg);
170 void loadRound(const Operator *op, ir::Graph &subg);
171 void loadPow(const Operator *op, ir::Graph &subg);
172 void loadLogicalNot(const Operator *op, ir::Graph &subg);
173 void loadZerosLike(const Operator *op, ir::Graph &subg);
174 void loadTile(const Operator *op, ir::Graph &subg);
175 void loadLogicalOr(const Operator *op, ir::Graph &subg);
176 void loadRange(const Operator *op, ir::Graph &subg);
177 void loadMatrixBandPart(const Operator *op, ir::Graph &subg);
178 void loadBroadcastTo(const Operator *op, ir::Graph &subg);
179 void loadFusedBatchNorm(const Operator *op, ir::Graph &subg);
180 void loadLogSoftmax(const Operator *op, ir::Graph &subg);
181 void loadQuantize(const Operator *op, ir::Graph &subg);
182 void loadSpaceToDepth(const Operator *op, ir::Graph &subg);
183 void loadStatelessRandomUniform(const Operator *op, ir::Graph &subg);
186 // Base address for mapped region for loading (if needed)
190 // loaded file description
192 // Reference on loadable subgraphs
193 std::unique_ptr<ir::Subgraphs> &_subgraphs;
195 // Maps Tensor indices to onert Operands.
196 std::vector<ir::OperandIndex> _tensor_to_operand;
198 std::unique_ptr<Verifier> _verifier;
201 template <typename LoaderDomain, typename SpecificLoader>
202 void BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::loadFromFile(const char *file_path)
204 _fd = open(file_path, O_RDONLY);
207 throw std::runtime_error("Failed to open file " + std::string(file_path));
210 struct stat file_stat;
211 if (fstat(_fd, &file_stat) != 0)
213 throw std::runtime_error("Fstat failed or file " + std::string(file_path) +
214 " is not a regular file");
216 int size = file_stat.st_size;
218 // Map model file into memory region
219 _base = static_cast<uint8_t *>(mmap(NULL, size, PROT_READ, MAP_PRIVATE, _fd, 0));
220 if (_base == MAP_FAILED)
223 throw std::runtime_error("mmap failed - " + std::string(strerror(errno)));
226 _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
233 template <typename LoaderDomain, typename SpecificLoader>
234 void BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::loadFromBuffer(uint8_t *buffer,
238 _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
242 template <typename LoaderDomain, typename SpecificLoader>
243 ir::Activation BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::convertActivation(
244 const ActivationFunctionType type)
248 case ActivationFunctionType::ActivationFunctionType_NONE:
249 return ir::Activation::NONE;
250 case ActivationFunctionType::ActivationFunctionType_RELU:
251 return ir::Activation::RELU;
252 case ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
253 return ir::Activation::RELU1;
254 case ActivationFunctionType::ActivationFunctionType_RELU6:
255 return ir::Activation::RELU6;
256 case ActivationFunctionType::ActivationFunctionType_TANH:
257 return ir::Activation::TANH;
259 throw std::runtime_error(std::string("Unsupported activation type: ")
260 .append(EnumNameActivationFunctionType(type)));
264 template <typename LoaderDomain, typename SpecificLoader>
266 BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::tensorTypeToDataType(const TensorType type)
270 case TensorType::TensorType_FLOAT32:
271 return ir::DataType::FLOAT32;
272 case TensorType::TensorType_INT32:
273 return ir::DataType::INT32;
274 case TensorType::TensorType_BOOL:
275 return ir::DataType::BOOL8;
276 case TensorType::TensorType_UINT8:
277 return ir::DataType::QUANT_UINT8_ASYMM;
278 case TensorType::TensorType_INT8:
279 return ir::DataType::QUANT_INT8_SYMM;
280 case TensorType::TensorType_INT64:
281 return ir::DataType::INT64;
283 throw std::runtime_error(
284 std::string("Unsupported tensor type: ").append(EnumNameTensorType(type)));
288 template <typename LoaderDomain, typename SpecificLoader>
290 BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::tensorIdxToOperandIdx(int32_t tensorIdx)
292 return isOptionalInputTensor(tensorIdx) ? ir::OperandIndex() : _tensor_to_operand[tensorIdx];
295 template <typename LoaderDomain, typename SpecificLoader>
296 void BaseLoader<LoaderDomain, SpecificLoader>::BaseLoader::deallocateMmappedArea(uint8_t *ptr,
299 // Calculate offset from base address of mapped region
300 ptrdiff_t unaligned_offset_start = ptr - _base;
301 ptrdiff_t unaligned_offset_end = unaligned_offset_start + size;
303 // Calculated aligned offset from base address of mapped region
304 // munmap accepts memory address which is a multiple of the pagesize
305 ptrdiff_t aligned_offset_start =
306 ((unaligned_offset_start + (_pagesize - 1)) / _pagesize) * _pagesize;
307 ptrdiff_t aligned_offset_end = (unaligned_offset_end / _pagesize) * _pagesize;
309 ptrdiff_t area_size = aligned_offset_end - aligned_offset_start;
312 // Unmap mapped region for CachedData
313 if (munmap(_base + aligned_offset_start, area_size) == -1)
315 VERBOSE(BASE_LOADER) << "munmap failed" << std::endl;
320 /* Copied from tensorflow lite. Need to append copyright */
321 template <typename T> bool Copy(const T *data_ptr, std::vector<uint16_t> &arr)
323 if (data_ptr->values() == nullptr)
328 int size = data_ptr->values()->size();
330 for (int i = 0; i < size; i++)
332 arr.emplace_back(static_cast<uint16_t>(data_ptr->values()->Get(i)));
337 template <typename LoaderDomain, typename SpecificLoader>
338 ir::OperandIndex BaseLoader<LoaderDomain, SpecificLoader>::loadOperand(const Tensor *tensor,
343 const auto *tensor_shape = tensor->shape();
344 if (tensor_shape != nullptr)
346 for (const auto &dim : *tensor_shape)
352 // Note for tensor->shape_signature()
353 // We don't handle shape signature
355 // If shape_signature[k] == -1, we will use tensor->shape()[k] == 1
356 // If app wants to change the input shape, call nnfw_apply_input_tensorinfo() can
360 ir::DataType data_type = tensorTypeToDataType(tensor->type());
362 auto q_params = tensor->quantization();
365 if (q_params != nullptr)
367 if (q_params->scale())
369 if (q_params->scale()->size() != 1)
371 throw std::runtime_error("Only 1 scale for a tensor is supported.");
373 scale = q_params->scale()->Get(0);
376 if (q_params->zero_point())
378 if (q_params->zero_point()->size() != 1)
380 throw std::runtime_error("Only 1 zero_point value for a tensor is supported.");
382 zero_point = q_params->zero_point()->Get(0);
383 // zero_point is long while TypeInfo.zero_point is defined as int32_t.
384 assert(zero_point >= std::numeric_limits<int32_t>::min());
385 assert(zero_point <= std::numeric_limits<int32_t>::max());
387 auto details = q_params->details_as_CustomQuantization();
388 if (details != nullptr)
389 throw std::runtime_error("Custom Quantization is not supported");
392 ir::TypeInfo type_info(data_type, scale, zero_point);
394 auto src_sparsity = tensor->sparsity();
395 if (src_sparsity != nullptr)
397 std::vector<uint16_t> w1_segments;
398 std::vector<uint16_t> w1_indices;
399 // ignore traversal_order, block_map
401 const size_t dim_metadata_size = src_sparsity->dim_metadata()->size();
402 if (dim_metadata_size != 2)
403 throw std::runtime_error("sparse tensor is supported only for 2D");
404 const auto *src_metadata = src_sparsity->dim_metadata()->Get(0);
405 if (src_metadata->format() != DimensionType::DimensionType_DENSE)
406 throw std::runtime_error("sparse tensor dim[0] is not DENSE");
407 src_metadata = src_sparsity->dim_metadata()->Get(1);
408 if (src_metadata->format() != DimensionType::DimensionType_SPARSE_CSR)
409 throw std::runtime_error("sparse tensor dim[0] is not SPARSE_CSR");
411 auto ParseSparseIndexVector = [src_metadata, &w1_segments, &w1_indices]() {
412 if (src_metadata->array_segments() == nullptr || src_metadata->array_indices() == nullptr)
415 switch (src_metadata->array_segments_type())
417 case SparseIndexVector::SparseIndexVector_Int32Vector:
418 status = Copy(src_metadata->array_segments_as_Int32Vector(), w1_segments);
420 case SparseIndexVector::SparseIndexVector_Uint16Vector:
421 status = Copy(src_metadata->array_segments_as_Uint16Vector(), w1_segments);
423 case SparseIndexVector::SparseIndexVector_Uint8Vector:
424 status = Copy(src_metadata->array_segments_as_Uint8Vector(), w1_segments);
431 switch (src_metadata->array_indices_type())
433 case SparseIndexVector::SparseIndexVector_Int32Vector:
434 return Copy(src_metadata->array_indices_as_Int32Vector(), w1_indices);
435 case SparseIndexVector::SparseIndexVector_Uint16Vector:
436 return Copy(src_metadata->array_indices_as_Uint16Vector(), w1_indices);
437 case SparseIndexVector::SparseIndexVector_Uint8Vector:
438 return Copy(src_metadata->array_indices_as_Uint8Vector(), w1_indices);
444 if (ParseSparseIndexVector() == false)
445 throw std::runtime_error("Error during parsing sparsity index information");
446 type_info.sparse2DMetadata(std::move(w1_segments), std::move(w1_indices));
449 const auto operand_index = subg.addOperand(shape, type_info);
451 // Constant tensors are indicated by non-empty data.
452 const auto *data = _model->buffers()->Get(tensor->buffer())->data();
455 using std::ptrdiff_t;
456 std::unique_ptr<ir::Data> data_obj;
457 if (_fd == -1) // Model is from memory
459 data_obj = std::make_unique<ir::ExternalData>(data->data(), data->size());
461 else // Model is loaded(mmap'd) from a file
463 data_obj = std::make_unique<ir::CachedData>(data->data(), data->size());
464 deallocateMmappedArea(const_cast<uint8_t *>(data->data()), data->size());
466 subg.setOperandValue(operand_index, std::move(data_obj));
470 // auto name = tensor->name();
472 if (tensor->is_variable())
473 throw std::runtime_error("Variable tensor not supported!");
475 return operand_index;
478 template <typename LoaderDomain, typename SpecificLoader>
479 void BaseLoader<LoaderDomain, SpecificLoader>::loadOperationIO(const Operator *op,
480 ir::OperandIndexSequence &inputs,
481 ir::OperandIndexSequence &outputs)
483 for (const std::int32_t idx : *op->inputs())
485 // Optional tensors are not supported yet except for FULLY_CONNECTED and BCQ_FULLY_CONNECTED
486 auto check_optional_input = [&]() {
487 auto builtin_code = _model->operator_codes()->Get(op->opcode_index())->builtin_code();
488 if (isOptionalInputTensor(idx) && !allowOptionalInputTensor(builtin_code))
489 throw std::runtime_error(
490 std::string("loader doesn't support optional input tensor yet for ")
491 .append(EnumNameBuiltinOperator(builtin_code)));
493 check_optional_input();
494 inputs.append(tensorIdxToOperandIdx(idx));
497 for (const std::int32_t idx : *op->outputs())
499 outputs.append(tensorIdxToOperandIdx(idx));
503 template <typename LoaderDomain, typename SpecificLoader>
504 template <typename Param, typename OptionsType>
505 void BaseLoader<LoaderDomain, SpecificLoader>::loadStridesAndPaddings(Param ¶m,
506 const OptionsType *options)
509 param.stride.vertical = options->stride_h();
510 param.stride.horizontal = options->stride_w();
512 if (options->padding() == Padding::Padding_SAME)
513 param.padding.type = ir::PaddingType::SAME;
514 if (options->padding() == Padding::Padding_VALID)
515 param.padding.type = ir::PaddingType::VALID;
516 // param paddings indexes unused
519 template <typename LoaderDomain, typename SpecificLoader>
520 template <typename Param>
521 void BaseLoader<LoaderDomain, SpecificLoader>::loadPool2D(Param ¶m,
522 const Pool2DOptions *options)
524 // Strides and Paddings
525 loadStridesAndPaddings(param, options);
526 // Filter width and height
528 param.kw = options->filter_width();
529 param.kh = options->filter_height();
531 param.activation = convertActivation(options->fused_activation_function());
534 template <typename LoaderDomain, typename SpecificLoader>
535 void BaseLoader<LoaderDomain, SpecificLoader>::loadConv2D(const Operator *op, ir::Graph &subg)
537 ir::OperandIndexSequence inputs;
538 ir::OperandIndexSequence outputs;
540 loadOperationIO(op, inputs, outputs);
542 ir::operation::Conv2D::Param param;
543 const auto *options = op->builtin_options_as_Conv2DOptions();
544 param.activation = convertActivation(options->fused_activation_function());
545 loadStridesAndPaddings(param, options);
546 // Dilation h/w factor unused
547 std::unique_ptr<ir::Operation> new_op(new ir::operation::Conv2D(inputs, outputs, param));
548 subg.addOperation(std::move(new_op));
551 template <typename LoaderDomain, typename SpecificLoader>
552 void BaseLoader<LoaderDomain, SpecificLoader>::loadDepthwiseConv2D(const Operator *op,
555 ir::OperandIndexSequence inputs;
556 ir::OperandIndexSequence outputs;
558 loadOperationIO(op, inputs, outputs);
560 ir::operation::DepthwiseConv2D::Param param;
561 const auto *options = op->builtin_options_as_DepthwiseConv2DOptions();
562 param.activation = convertActivation(options->fused_activation_function());
563 loadStridesAndPaddings(param, options);
565 param.multiplier = options->depth_multiplier();
566 // Dilation h/w factor unused
567 std::unique_ptr<ir::Operation> new_op(new ir::operation::DepthwiseConv2D(inputs, outputs, param));
568 subg.addOperation(std::move(new_op));
571 template <typename LoaderDomain, typename SpecificLoader>
572 void BaseLoader<LoaderDomain, SpecificLoader>::loadTransposeConv(const Operator *op,
575 ir::OperandIndexSequence inputs;
576 ir::OperandIndexSequence outputs;
578 loadOperationIO(op, inputs, outputs);
580 ir::operation::TransposeConv::Param param;
581 const auto *options = op->builtin_options_as_TransposeConvOptions();
582 loadStridesAndPaddings(param, options);
583 std::unique_ptr<ir::Operation> new_op(new ir::operation::TransposeConv(inputs, outputs, param));
584 subg.addOperation(std::move(new_op));
587 template <typename LoaderDomain, typename SpecificLoader>
588 void BaseLoader<LoaderDomain, SpecificLoader>::loadAvgPool2D(const Operator *op, ir::Graph &subg)
590 ir::OperandIndexSequence inputs;
591 ir::OperandIndexSequence outputs;
593 loadOperationIO(op, inputs, outputs);
595 ir::operation::AvgPool2D::Param param;
596 const auto *options = op->builtin_options_as_Pool2DOptions();
598 loadPool2D(param, options);
600 std::unique_ptr<ir::Operation> new_op(new ir::operation::AvgPool2D(inputs, outputs, param));
601 subg.addOperation(std::move(new_op));
604 template <typename LoaderDomain, typename SpecificLoader>
605 void BaseLoader<LoaderDomain, SpecificLoader>::loadReshape(const Operator *op, ir::Graph &subg)
607 ir::OperandIndexSequence inputs;
608 ir::OperandIndexSequence outputs;
610 loadOperationIO(op, inputs, outputs);
612 ir::operation::Reshape::Param param{};
613 const auto *options = op->builtin_options_as_ReshapeOptions();
614 if (options != nullptr)
616 const auto *new_shape = options->new_shape();
619 for (uint i = 0; i < new_shape->Length(); ++i)
621 param.new_shape.push_back(new_shape->Get(i));
626 std::unique_ptr<ir::Operation> new_op(new ir::operation::Reshape(inputs, outputs, param));
627 subg.addOperation(std::move(new_op));
630 template <typename LoaderDomain, typename SpecificLoader>
631 void BaseLoader<LoaderDomain, SpecificLoader>::loadSoftmax(const Operator *op, ir::Graph &subg)
633 ir::OperandIndexSequence inputs;
634 ir::OperandIndexSequence outputs;
636 loadOperationIO(op, inputs, outputs);
638 ir::operation::Softmax::Param param;
639 const auto *options = op->builtin_options_as_SoftmaxOptions();
641 param.beta = options->beta();
643 std::unique_ptr<ir::Operation> new_op(new ir::operation::Softmax(inputs, outputs, param));
644 subg.addOperation(std::move(new_op));
647 template <typename LoaderDomain, typename SpecificLoader>
648 void BaseLoader<LoaderDomain, SpecificLoader>::loadMaxPool2D(const Operator *op, ir::Graph &subg)
650 ir::OperandIndexSequence inputs;
651 ir::OperandIndexSequence outputs;
653 loadOperationIO(op, inputs, outputs);
655 ir::operation::MaxPool2D::Param param;
656 const auto *options = op->builtin_options_as_Pool2DOptions();
658 loadPool2D(param, options);
660 std::unique_ptr<ir::Operation> new_op(new ir::operation::MaxPool2D(inputs, outputs, param));
661 subg.addOperation(std::move(new_op));
664 template <typename LoaderDomain, typename SpecificLoader>
665 void BaseLoader<LoaderDomain, SpecificLoader>::loadConcatenation(const Operator *op,
668 ir::OperandIndexSequence inputs;
669 ir::OperandIndexSequence outputs;
671 loadOperationIO(op, inputs, outputs);
673 ir::operation::Concat::Param param;
674 const auto *options = op->builtin_options_as_ConcatenationOptions();
676 param.axis = options->axis();
679 std::unique_ptr<ir::Operation> new_op(new ir::operation::Concat(inputs, outputs, param));
680 subg.addOperation(std::move(new_op));
683 template <typename LoaderDomain, typename SpecificLoader>
684 void BaseLoader<LoaderDomain, SpecificLoader>::loadFill(const Operator *op, ir::Graph &subg)
686 ir::OperandIndexSequence inputs;
687 ir::OperandIndexSequence outputs;
689 loadOperationIO(op, inputs, outputs);
691 std::unique_ptr<ir::Operation> new_op(new ir::operation::Fill(inputs, outputs));
692 subg.addOperation(std::move(new_op));
695 template <typename LoaderDomain, typename SpecificLoader>
696 void BaseLoader<LoaderDomain, SpecificLoader>::loadFC(const Operator *op, ir::Graph &subg)
698 ir::OperandIndexSequence inputs;
699 ir::OperandIndexSequence outputs;
701 loadOperationIO(op, inputs, outputs);
703 const auto &input_operand = subg.operands().at(inputs.at(ir::operation::FullyConnected::INPUT));
704 auto &weights_operand = subg.operands().at(inputs.at(ir::operation::FullyConnected::WEIGHT));
705 if (input_operand.typeInfo().type() == ir::DataType::FLOAT32 &&
706 weights_operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM)
708 weights_operand.type(ir::DataType::QUANT_INT8_SYMM);
711 ir::operation::FullyConnected::Param param;
712 const auto *options = op->builtin_options_as_FullyConnectedOptions();
714 param.activation = convertActivation(options->fused_activation_function());
715 // weights_format unused
717 std::unique_ptr<ir::Operation> new_op(new ir::operation::FullyConnected(inputs, outputs, param));
718 subg.addOperation(std::move(new_op));
721 template <typename LoaderDomain, typename SpecificLoader>
722 void BaseLoader<LoaderDomain, SpecificLoader>::loadAdd(const Operator *op, ir::Graph &subg)
724 ir::OperandIndexSequence inputs;
725 ir::OperandIndexSequence outputs;
727 loadOperationIO(op, inputs, outputs);
729 ir::operation::Add::Param param;
730 const auto *options = op->builtin_options_as_AddOptions();
732 param.activation = convertActivation(options->fused_activation_function());
734 std::unique_ptr<ir::Operation> new_op(new ir::operation::Add(inputs, outputs, param));
735 subg.addOperation(std::move(new_op));
738 template <typename LoaderDomain, typename SpecificLoader>
739 void BaseLoader<LoaderDomain, SpecificLoader>::loadSub(const Operator *op, ir::Graph &subg)
741 ir::OperandIndexSequence inputs;
742 ir::OperandIndexSequence outputs;
744 loadOperationIO(op, inputs, outputs);
746 ir::operation::Sub::Param param;
747 const auto *options = op->builtin_options_as_SubOptions();
749 param.activation = convertActivation(options->fused_activation_function());
751 std::unique_ptr<ir::Operation> new_op(new ir::operation::Sub(inputs, outputs, param));
752 subg.addOperation(std::move(new_op));
755 template <typename LoaderDomain, typename SpecificLoader>
756 void BaseLoader<LoaderDomain, SpecificLoader>::loadMul(const Operator *op, ir::Graph &subg)
758 ir::OperandIndexSequence inputs;
759 ir::OperandIndexSequence outputs;
761 loadOperationIO(op, inputs, outputs);
763 ir::operation::Mul::Param param;
764 const auto *options = op->builtin_options_as_MulOptions();
766 param.activation = convertActivation(options->fused_activation_function());
768 std::unique_ptr<ir::Operation> new_op(new ir::operation::Mul(inputs, outputs, param));
769 subg.addOperation(std::move(new_op));
772 template <typename LoaderDomain, typename SpecificLoader>
773 void BaseLoader<LoaderDomain, SpecificLoader>::loadDiv(const Operator *op, ir::Graph &subg)
775 ir::OperandIndexSequence inputs;
776 ir::OperandIndexSequence outputs;
778 loadOperationIO(op, inputs, outputs);
780 ir::operation::Div::Param param;
781 const auto *options = op->builtin_options_as_DivOptions();
783 param.activation = convertActivation(options->fused_activation_function());
785 std::unique_ptr<ir::Operation> new_op(new ir::operation::Div(inputs, outputs, param));
786 subg.addOperation(std::move(new_op));
789 template <typename LoaderDomain, typename SpecificLoader>
790 void BaseLoader<LoaderDomain, SpecificLoader>::loadPack(const Operator *op, ir::Graph &subg)
792 // This runtime_error will be removed if the one of backend supports this operation
793 ir::OperandIndexSequence inputs;
794 ir::OperandIndexSequence outputs;
796 loadOperationIO(op, inputs, outputs);
798 ir::operation::Pack::Param param;
799 const auto *options = op->builtin_options_as_PackOptions();
800 param.num = options->values_count();
801 param.axis = options->axis();
803 std::unique_ptr<ir::Operation> new_op(new ir::operation::Pack(inputs, outputs, param));
804 subg.addOperation(std::move(new_op));
807 template <typename LoaderDomain, typename SpecificLoader>
808 void BaseLoader<LoaderDomain, SpecificLoader>::loadRelu(const Operator *op, ir::Graph &subg)
810 ir::OperandIndexSequence inputs;
811 ir::OperandIndexSequence outputs;
813 loadOperationIO(op, inputs, outputs);
815 std::unique_ptr<ir::Operation> new_op(new ir::operation::ReLU(inputs, outputs));
816 subg.addOperation(std::move(new_op));
819 template <typename LoaderDomain, typename SpecificLoader>
820 void BaseLoader<LoaderDomain, SpecificLoader>::loadRelu6(const Operator *op, ir::Graph &subg)
822 ir::OperandIndexSequence inputs;
823 ir::OperandIndexSequence outputs;
825 loadOperationIO(op, inputs, outputs);
827 std::unique_ptr<ir::Operation> new_op(new ir::operation::ReLU6(inputs, outputs));
828 subg.addOperation(std::move(new_op));
831 template <typename LoaderDomain, typename SpecificLoader>
832 void BaseLoader<LoaderDomain, SpecificLoader>::loadResizeBilinear(const Operator *op,
835 ir::OperandIndexSequence inputs;
836 ir::OperandIndexSequence outputs;
838 loadOperationIO(op, inputs, outputs);
839 auto input = inputs.at(0);
840 auto size = inputs.at(1);
842 // FIXME Handle ResizeBilinearOptions.
843 if (!subg.operands().at(size).isConstant())
844 throw std::runtime_error("ResizeBilinear: non-constant 'size' is not supported.");
846 std::vector<std::int32_t> size_v = subg.operands().at(size).template asVector<std::int32_t>();
848 ir::operation::ResizeBilinear::Param param;
849 param.height_out = size_v[0];
850 param.width_out = size_v[1];
851 param.align_corners = op->builtin_options_as_ResizeBilinearOptions()->align_corners();
852 param.half_pixel_centers = op->builtin_options_as_ResizeBilinearOptions()->half_pixel_centers();
854 std::unique_ptr<ir::Operation> new_op(new ir::operation::ResizeBilinear({input}, outputs, param));
855 subg.addOperation(std::move(new_op));
858 template <typename LoaderDomain, typename SpecificLoader>
859 void BaseLoader<LoaderDomain, SpecificLoader>::loadRsqrt(const Operator *op, ir::Graph &subg)
861 ir::OperandIndexSequence inputs;
862 ir::OperandIndexSequence outputs;
864 loadOperationIO(op, inputs, outputs);
866 std::unique_ptr<ir::Operation> new_op(new ir::operation::RSQRT(inputs, outputs));
867 subg.addOperation(std::move(new_op));
870 template <typename LoaderDomain, typename SpecificLoader>
871 void BaseLoader<LoaderDomain, SpecificLoader>::loadSelect(const Operator *op, ir::Graph &subg)
873 ir::OperandIndexSequence inputs;
874 ir::OperandIndexSequence outputs;
876 loadOperationIO(op, inputs, outputs);
878 std::unique_ptr<ir::Operation> new_op(new ir::operation::Select(inputs, outputs));
879 subg.addOperation(std::move(new_op));
882 template <typename LoaderDomain, typename SpecificLoader>
883 void BaseLoader<LoaderDomain, SpecificLoader>::loadSqrt(const Operator *op, ir::Graph &subg)
885 ir::OperandIndexSequence inputs;
886 ir::OperandIndexSequence outputs;
888 loadOperationIO(op, inputs, outputs);
890 std::unique_ptr<ir::Operation> new_op(new ir::operation::SQRT(inputs, outputs));
891 subg.addOperation(std::move(new_op));
894 template <typename LoaderDomain, typename SpecificLoader>
895 void BaseLoader<LoaderDomain, SpecificLoader>::loadSquaredDifference(const Operator *op,
898 ir::OperandIndexSequence inputs;
899 ir::OperandIndexSequence outputs;
901 loadOperationIO(op, inputs, outputs);
903 std::unique_ptr<ir::Operation> new_op(new ir::operation::SquaredDifference(inputs, outputs));
904 subg.addOperation(std::move(new_op));
907 template <typename LoaderDomain, typename SpecificLoader>
908 void BaseLoader<LoaderDomain, SpecificLoader>::loadTanh(const Operator *op, ir::Graph &subg)
910 ir::OperandIndexSequence inputs;
911 ir::OperandIndexSequence outputs;
913 loadOperationIO(op, inputs, outputs);
915 std::unique_ptr<ir::Operation> new_op(new ir::operation::Tanh(inputs, outputs));
916 subg.addOperation(std::move(new_op));
919 template <typename LoaderDomain, typename SpecificLoader>
920 void BaseLoader<LoaderDomain, SpecificLoader>::loadTranspose(const Operator *op, ir::Graph &subg)
922 ir::OperandIndexSequence inputs;
923 ir::OperandIndexSequence outputs;
925 loadOperationIO(op, inputs, outputs);
926 auto input = inputs.at(0);
927 auto perm = inputs.at(1);
929 if (!subg.operands().at(perm).isConstant())
930 throw std::runtime_error("Transpose: non-constant 'perm' is not supported.");
932 ir::operation::Transpose::Param param;
933 param.perm = subg.operands().at(perm).template asVector<int>();
935 std::unique_ptr<ir::Operation> new_op(new ir::operation::Transpose({input}, outputs, param));
936 subg.addOperation(std::move(new_op));
939 template <typename LoaderDomain, typename SpecificLoader>
940 void BaseLoader<LoaderDomain, SpecificLoader>::loadReduce(
941 const Operator *op, ir::Graph &subg, ir::operation::Reduce::ReduceType reduce_type)
943 ir::OperandIndexSequence inputs;
944 ir::OperandIndexSequence outputs;
946 loadOperationIO(op, inputs, outputs);
948 ir::operation::Reduce::Param param;
949 param.reduce_type = reduce_type;
950 param.keep_dims = op->builtin_options_as_ReducerOptions()->keep_dims();
952 std::unique_ptr<ir::Operation> new_op(new ir::operation::Reduce(inputs, outputs, param));
953 subg.addOperation(std::move(new_op));
956 template <typename LoaderDomain, typename SpecificLoader>
957 void BaseLoader<LoaderDomain, SpecificLoader>::loadReduceAll(const Operator *op, ir::Graph &subg)
959 ir::OperandIndexSequence inputs;
960 ir::OperandIndexSequence outputs;
962 loadOperationIO(op, inputs, outputs);
964 ir::operation::Reduce::Param param;
965 param.reduce_type = ir::operation::Reduce::ReduceType::ALL;
966 if (op->custom_options() == nullptr)
968 param.keep_dims = false;
972 size_t custom_op_data_size = op->custom_options()->size();
973 auto custom_op_data = op->custom_options()->Data();
974 auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
975 auto attr_map = data_root.AsMap();
976 param.keep_dims = attr_map["keep_dims"].AsBool();
979 std::unique_ptr<ir::Operation> new_op(new ir::operation::Reduce(inputs, outputs, param));
980 subg.addOperation(std::move(new_op));
983 template <typename LoaderDomain, typename SpecificLoader>
984 void BaseLoader<LoaderDomain, SpecificLoader>::loadReverseV2(const Operator *op, ir::Graph &subg)
986 ir::OperandIndexSequence inputs;
987 ir::OperandIndexSequence outputs;
989 loadOperationIO(op, inputs, outputs);
991 std::unique_ptr<ir::Operation> new_op(new ir::operation::Reverse(inputs, outputs));
992 subg.addOperation(std::move(new_op));
995 template <typename LoaderDomain, typename SpecificLoader>
996 void BaseLoader<LoaderDomain, SpecificLoader>::loadPad(const Operator *op, ir::Graph &subg)
998 ir::OperandIndexSequence inputs;
999 ir::OperandIndexSequence outputs;
1001 loadOperationIO(op, inputs, outputs);
1003 std::unique_ptr<ir::Operation> new_op(new ir::operation::Pad(inputs, outputs));
1004 subg.addOperation(std::move(new_op));
1007 template <typename LoaderDomain, typename SpecificLoader>
1008 void BaseLoader<LoaderDomain, SpecificLoader>::loadLogistic(const Operator *op, ir::Graph &subg)
1010 ir::OperandIndexSequence inputs;
1011 ir::OperandIndexSequence outputs;
1013 loadOperationIO(op, inputs, outputs);
1015 std::unique_ptr<ir::Operation> new_op(new ir::operation::Logistic(inputs, outputs));
1016 subg.addOperation(std::move(new_op));
1019 template <typename LoaderDomain, typename SpecificLoader>
1020 void BaseLoader<LoaderDomain, SpecificLoader>::loadExp(const Operator *op, ir::Graph &subg)
1022 ir::OperandIndexSequence inputs;
1023 ir::OperandIndexSequence outputs;
1025 loadOperationIO(op, inputs, outputs);
1027 std::unique_ptr<ir::Operation> new_op(new ir::operation::Exp(inputs, outputs));
1028 subg.addOperation(std::move(new_op));
1031 template <typename LoaderDomain, typename SpecificLoader>
1032 void BaseLoader<LoaderDomain, SpecificLoader>::loadExpandDims(const Operator *op, ir::Graph &subg)
1034 ir::OperandIndexSequence inputs;
1035 ir::OperandIndexSequence outputs;
1037 loadOperationIO(op, inputs, outputs);
1039 std::unique_ptr<ir::Operation> new_op(new ir::operation::ExpandDims(inputs, outputs));
1040 subg.addOperation(std::move(new_op));
1043 template <typename LoaderDomain, typename SpecificLoader>
1044 void BaseLoader<LoaderDomain, SpecificLoader>::loadGather(const Operator *op, ir::Graph &subg)
1046 ir::OperandIndexSequence inputs;
1047 ir::OperandIndexSequence outputs;
1049 loadOperationIO(op, inputs, outputs);
1050 ir::operation::Gather::Param param;
1051 param.axis = op->builtin_options_as_GatherOptions()->axis();
1053 std::unique_ptr<ir::Operation> new_op(new ir::operation::Gather(inputs, outputs, param));
1054 subg.addOperation(std::move(new_op));
1057 template <typename LoaderDomain, typename SpecificLoader>
1058 void BaseLoader<LoaderDomain, SpecificLoader>::loadSpaceToBatchND(const Operator *op,
1061 ir::OperandIndexSequence inputs;
1062 ir::OperandIndexSequence outputs;
1064 loadOperationIO(op, inputs, outputs);
1066 std::unique_ptr<ir::Operation> new_op{new ir::operation::SpaceToBatchND{inputs, outputs}};
1067 subg.addOperation(std::move(new_op));
1070 template <typename LoaderDomain, typename SpecificLoader>
1071 void BaseLoader<LoaderDomain, SpecificLoader>::loadBatchMatMul(const Operator *op, ir::Graph &subg)
1073 ir::OperandIndexSequence inputs;
1074 ir::OperandIndexSequence outputs;
1076 loadOperationIO(op, inputs, outputs);
1077 ir::operation::BatchMatMul::Param param;
1079 const auto builtin_op = _model->operator_codes()->Get(op->opcode_index())->builtin_code();
1083 case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
1084 param.adj_x = op->builtin_options_as_BatchMatMulOptions()->adjoint_lhs();
1085 param.adj_y = op->builtin_options_as_BatchMatMulOptions()->adjoint_rhs();
1087 case BuiltinOperator::BuiltinOperator_CUSTOM:
1088 if (op->custom_options() == nullptr)
1090 param.adj_x = false;
1091 param.adj_y = false;
1095 size_t custom_op_data_size = op->custom_options()->size();
1096 auto custom_op_data = op->custom_options()->Data();
1097 auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
1098 auto attr_map = data_root.AsMap();
1099 param.adj_x = attr_map["adj_x"].AsBool();
1100 param.adj_y = attr_map["adj_y"].AsBool();
1104 throw std::runtime_error(
1105 std::string("Wrong loaded operation: ").append(EnumNameBuiltinOperator(builtin_op)) +
1106 " as " + EnumNameBuiltinOperator(BuiltinOperator::BuiltinOperator_BATCH_MATMUL));
1109 std::unique_ptr<ir::Operation> new_op{new ir::operation::BatchMatMul{inputs, outputs, param}};
1110 subg.addOperation(std::move(new_op));
1113 template <typename LoaderDomain, typename SpecificLoader>
1114 void BaseLoader<LoaderDomain, SpecificLoader>::loadBatchToSpaceND(const Operator *op,
1117 ir::OperandIndexSequence inputs;
1118 ir::OperandIndexSequence outputs;
1120 loadOperationIO(op, inputs, outputs);
1122 std::unique_ptr<ir::Operation> new_op{new ir::operation::BatchToSpaceND{inputs, outputs}};
1123 subg.addOperation(std::move(new_op));
1126 template <typename LoaderDomain, typename SpecificLoader>
1127 void BaseLoader<LoaderDomain, SpecificLoader>::loadMatrixBandPart(const Operator *op,
1130 ir::OperandIndexSequence inputs;
1131 ir::OperandIndexSequence outputs;
1133 loadOperationIO(op, inputs, outputs);
1135 std::unique_ptr<ir::Operation> new_op(new ir::operation::MatrixBandPart(inputs, outputs));
1136 subg.addOperation(std::move(new_op));
1139 template <typename LoaderDomain, typename SpecificLoader>
1140 void BaseLoader<LoaderDomain, SpecificLoader>::loadBroadcastTo(const Operator *op, ir::Graph &subg)
1142 ir::OperandIndexSequence inputs;
1143 ir::OperandIndexSequence outputs;
1145 loadOperationIO(op, inputs, outputs);
1147 std::unique_ptr<ir::Operation> new_op(new ir::operation::BroadcastTo(inputs, outputs));
1148 subg.addOperation(std::move(new_op));
1150 template <typename LoaderDomain, typename SpecificLoader>
1151 void BaseLoader<LoaderDomain, SpecificLoader>::loadSpaceToDepth(const Operator *op, ir::Graph &subg)
1153 ir::OperandIndexSequence inputs;
1154 ir::OperandIndexSequence outputs;
1155 ir::operation::SpaceToDepth::Param param;
1157 const auto *options = op->builtin_options_as_SpaceToDepthOptions();
1159 param.block_size = options->block_size();
1161 loadOperationIO(op, inputs, outputs);
1163 std::unique_ptr<ir::Operation> new_op(new ir::operation::SpaceToDepth(inputs, outputs, param));
1164 subg.addOperation(std::move(new_op));
1167 template <typename LoaderDomain, typename SpecificLoader>
1168 void BaseLoader<LoaderDomain, SpecificLoader>::loadStatelessRandomUniform(const Operator *op,
1171 ir::OperandIndexSequence inputs;
1172 ir::OperandIndexSequence outputs;
1173 loadOperationIO(op, inputs, outputs);
1175 std::unique_ptr<ir::Operation> new_op(new ir::operation::StatelessRandomUniform(inputs, outputs));
1176 subg.addOperation(std::move(new_op));
1179 template <typename LoaderDomain, typename SpecificLoader>
1180 void BaseLoader<LoaderDomain, SpecificLoader>::loadCustom(const Operator *op, ir::Graph &subg)
1182 ir::OperandIndexSequence inputs;
1183 ir::OperandIndexSequence outputs;
1185 assert(op->custom_options_format() == CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS &&
1186 "Unsupported custom operation options format");
1188 auto *op_code = _model->operator_codes()->Get(op->opcode_index());
1189 auto custom_op_name = op_code->custom_code()->str();
1191 enum class BuiltinOP
1200 StatelessRandomUniform
1203 // Mapping from custom op name string to BuiltinOP enum
1204 std::map<std::string, BuiltinOP> builtin_map = {
1205 {"AddV2", BuiltinOP::AddV2},
1206 {"All", BuiltinOP::ReduceAll},
1207 {"MatrixBandPart", BuiltinOP::MatrixBandPart},
1208 {"BatchMatMulV2", BuiltinOP::BatchMatMul},
1209 {"Einsum", BuiltinOP::Einsum},
1210 {"FusedBatchNormV3", BuiltinOP::FusedBatchNorm},
1211 {"BroadcastTo", BuiltinOP::BroadcastTo},
1212 {"StatelessRandomUniform", BuiltinOP::StatelessRandomUniform},
1217 // Throw out_of_range if it is unknown custom op
1218 auto custom_op_id = builtin_map.at(custom_op_name);
1219 switch (custom_op_id)
1221 case BuiltinOP::AddV2:
1224 case BuiltinOP::ReduceAll:
1225 loadReduceAll(op, subg);
1227 case BuiltinOP::MatrixBandPart:
1228 loadMatrixBandPart(op, subg);
1230 case BuiltinOP::BatchMatMul:
1231 loadBatchMatMul(op, subg);
1233 case BuiltinOP::Einsum:
1234 loadEinsum(op, subg);
1236 case BuiltinOP::BroadcastTo:
1237 loadBroadcastTo(op, subg);
1239 case BuiltinOP::FusedBatchNorm:
1240 loadFusedBatchNorm(op, subg);
1242 case BuiltinOP::StatelessRandomUniform:
1243 loadStatelessRandomUniform(op, subg);
1246 throw std::runtime_error{
1247 "Loader: Custom OP map is defined but operation loader function is not defined"};
1254 loadOperationIO(op, inputs, outputs);
1256 auto constraint = ir::OperandConstraint::createExact(inputs.size());
1258 size_t custom_op_data_size = op->custom_options()->size();
1259 auto custom_op_data = new char[custom_op_data_size];
1260 std::copy(op->custom_options()->begin(), op->custom_options()->end(), custom_op_data);
1262 ir::operation::Custom::Userdata userdata{};
1263 userdata.data = custom_op_data;
1264 userdata.size = custom_op_data_size;
1266 auto new_op = std::make_unique<ir::operation::Custom>(constraint, inputs, outputs,
1267 custom_op_name, userdata);
1269 subg.addOperation(std::move(new_op));
1273 template <typename LoaderDomain, typename SpecificLoader>
1274 void BaseLoader<LoaderDomain, SpecificLoader>::loadSqueeze(const Operator *op, ir::Graph &subg)
1276 ir::OperandIndexSequence inputs;
1277 ir::OperandIndexSequence outputs;
1279 loadOperationIO(op, inputs, outputs);
1281 ir::operation::Squeeze::Param param{};
1282 const auto *options = op->builtin_options_as_SqueezeOptions();
1283 const auto *dims = options->squeeze_dims();
1286 if (dims->Length() > sizeof(param.dims) / sizeof(param.dims[0]))
1287 throw std::runtime_error("Squeeze: 'param.ndims' is out of range.");
1288 param.ndim = dims->Length();
1289 for (int i = 0; i < param.ndim; ++i)
1290 param.dims[i] = dims->Get(i);
1293 std::unique_ptr<ir::Operation> new_op(new ir::operation::Squeeze(inputs, outputs, param));
1294 subg.addOperation(std::move(new_op));
1297 template <typename LoaderDomain, typename SpecificLoader>
1298 void BaseLoader<LoaderDomain, SpecificLoader>::loadPrelu(const Operator *op, ir::Graph &subg)
1300 ir::OperandIndexSequence inputs;
1301 ir::OperandIndexSequence outputs;
1303 loadOperationIO(op, inputs, outputs);
1305 std::unique_ptr<ir::Operation> new_op(new ir::operation::PReLU(inputs, outputs));
1306 subg.addOperation(std::move(new_op));
1309 template <typename LoaderDomain, typename SpecificLoader>
1310 void BaseLoader<LoaderDomain, SpecificLoader>::loadSplit(const Operator *op, ir::Graph &subg)
1312 ir::OperandIndexSequence inputs;
1313 ir::OperandIndexSequence outputs;
1315 loadOperationIO(op, inputs, outputs);
1316 // Notice : input order is strange for tflite split
1317 auto input = inputs.at(1);
1318 auto axis = inputs.at(0);
1320 // FIXME Handle SplitOptions.
1321 if (!subg.operands().at(axis).isConstant())
1322 throw std::runtime_error("Split: non-constant 'axis' is not supported.");
1324 ir::operation::Split::Param param{};
1325 param.axis = subg.operands().at(axis).template asScalar<int>();
1326 const auto *options = op->builtin_options_as_SplitOptions();
1327 param.num_splits = options->num_splits();
1329 std::unique_ptr<ir::Operation> new_op(new ir::operation::Split({input}, outputs, param));
1330 subg.addOperation(std::move(new_op));
1333 template <typename LoaderDomain, typename SpecificLoader>
1334 void BaseLoader<LoaderDomain, SpecificLoader>::loadSplitV(const Operator *op, ir::Graph &subg)
1336 ir::OperandIndexSequence inputs;
1337 ir::OperandIndexSequence outputs;
1339 loadOperationIO(op, inputs, outputs);
1341 ir::operation::SplitV::Param param{};
1343 const auto *options = op->builtin_options_as_SplitVOptions();
1344 param.num_splits = options->num_splits();
1346 std::unique_ptr<ir::Operation> new_op(new ir::operation::SplitV(inputs, outputs, param));
1347 subg.addOperation(std::move(new_op));
1350 template <typename LoaderDomain, typename SpecificLoader>
1351 void BaseLoader<LoaderDomain, SpecificLoader>::loadSlice(const Operator *op, ir::Graph &subg)
1353 ir::OperandIndexSequence inputs;
1354 ir::OperandIndexSequence outputs;
1356 loadOperationIO(op, inputs, outputs);
1358 std::unique_ptr<ir::Operation> new_op{new ir::operation::Slice{inputs, outputs}};
1359 subg.addOperation(std::move(new_op));
1362 template <typename LoaderDomain, typename SpecificLoader>
1363 void BaseLoader<LoaderDomain, SpecificLoader>::loadStridedSlice(const Operator *op, ir::Graph &subg)
1365 ir::OperandIndexSequence inputs;
1366 ir::OperandIndexSequence outputs;
1368 loadOperationIO(op, inputs, outputs);
1370 ir::operation::StridedSlice::Param param;
1372 const auto *options = op->builtin_options_as_StridedSliceOptions();
1373 param.begin_mask = options->begin_mask();
1374 param.end_mask = options->end_mask();
1375 param.shrink_axis_mask = options->shrink_axis_mask();
1377 std::unique_ptr<ir::Operation> new_op{new ir::operation::StridedSlice{inputs, outputs, param}};
1378 subg.addOperation(std::move(new_op));
1381 template <typename LoaderDomain, typename SpecificLoader>
1382 void BaseLoader<LoaderDomain, SpecificLoader>::loadUnpack(const Operator *op, ir::Graph &subg)
1384 ir::OperandIndexSequence inputs;
1385 ir::OperandIndexSequence outputs;
1387 loadOperationIO(op, inputs, outputs);
1389 ir::operation::Unpack::Param param;
1390 const auto *options = op->builtin_options_as_UnpackOptions();
1391 param.num = options->num();
1392 param.axis = options->axis();
1394 std::unique_ptr<ir::Operation> new_op(new ir::operation::Unpack(inputs, outputs, param));
1395 subg.addOperation(std::move(new_op));
1398 template <typename LoaderDomain, typename SpecificLoader>
1399 void BaseLoader<LoaderDomain, SpecificLoader>::loadMinimum(const Operator *op, ir::Graph &subg)
1401 ir::OperandIndexSequence inputs;
1402 ir::OperandIndexSequence outputs;
1404 loadOperationIO(op, inputs, outputs);
1406 std::unique_ptr<ir::Operation> new_op(new ir::operation::Min(inputs, outputs));
1407 subg.addOperation(std::move(new_op));
1410 template <typename LoaderDomain, typename SpecificLoader>
1411 void BaseLoader<LoaderDomain, SpecificLoader>::loadMaximum(const Operator *op, ir::Graph &subg)
1413 ir::OperandIndexSequence inputs;
1414 ir::OperandIndexSequence outputs;
1416 loadOperationIO(op, inputs, outputs);
1418 std::unique_ptr<ir::Operation> new_op(new ir::operation::Max(inputs, outputs));
1419 subg.addOperation(std::move(new_op));
1422 template <typename LoaderDomain, typename SpecificLoader>
1423 void BaseLoader<LoaderDomain, SpecificLoader>::loadCast(const Operator *op, ir::Graph &subg)
1425 ir::OperandIndexSequence inputs;
1426 ir::OperandIndexSequence outputs;
1428 loadOperationIO(op, inputs, outputs);
1430 auto qasymm8ToUint8 = [](ir::Operand &operand) {
1431 if (operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM)
1433 operand.type(ir::DataType::UINT8);
1436 qasymm8ToUint8(subg.operands().at(inputs.at(ir::operation::Cast::Input::INPUT)));
1437 qasymm8ToUint8(subg.operands().at(outputs.at(0)));
1439 std::unique_ptr<ir::Operation> new_op(new ir::operation::Cast(inputs, outputs));
1440 subg.addOperation(std::move(new_op));
1443 template <typename LoaderDomain, typename SpecificLoader>
1444 void BaseLoader<LoaderDomain, SpecificLoader>::loadComparison(const Operator *op, ir::Graph &subg)
1446 ir::OperandIndexSequence inputs;
1447 ir::OperandIndexSequence outputs;
1449 loadOperationIO(op, inputs, outputs);
1451 ir::operation::Comparison::Param param;
1453 const auto builtin_op = _model->operator_codes()->Get(op->opcode_index())->builtin_code();
1457 case BuiltinOperator::BuiltinOperator_EQUAL:
1458 param.comparison_type = ir::operation::Comparison::ComparisonType::Equal;
1460 case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
1461 param.comparison_type = ir::operation::Comparison::ComparisonType::NotEqual;
1463 case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
1464 param.comparison_type = ir::operation::Comparison::ComparisonType::GreaterEqual;
1466 case BuiltinOperator::BuiltinOperator_GREATER:
1467 param.comparison_type = ir::operation::Comparison::ComparisonType::Greater;
1469 case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
1470 param.comparison_type = ir::operation::Comparison::ComparisonType::LessEqual;
1472 case BuiltinOperator::BuiltinOperator_LESS:
1473 param.comparison_type = ir::operation::Comparison::ComparisonType::Less;
1476 throw std::runtime_error(
1477 std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
1480 std::unique_ptr<ir::Operation> new_op(new ir::operation::Comparison(inputs, outputs, param));
1481 subg.addOperation(std::move(new_op));
1484 template <typename LoaderDomain, typename SpecificLoader>
1485 void BaseLoader<LoaderDomain, SpecificLoader>::loadEinsum(const Operator *op, ir::Graph &subg)
1487 ir::OperandIndexSequence inputs;
1488 ir::OperandIndexSequence outputs;
1490 loadOperationIO(op, inputs, outputs);
1491 ir::operation::Einsum::Param param;
1493 if (inputs.size() != 2)
1495 throw std::runtime_error{"Einsum: NYI input - only support two inputs"};
1498 if (op->custom_options() == nullptr)
1500 throw std::runtime_error{"Einsum: empty equation"};
1504 size_t custom_op_data_size = op->custom_options()->size();
1505 auto custom_op_data = op->custom_options()->Data();
1506 auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
1507 auto attr_map = data_root.AsMap();
1508 param.equation = attr_map["equation"].ToString();
1511 std::unique_ptr<ir::Operation> new_op{new ir::operation::Einsum{inputs, outputs, param}};
1512 subg.addOperation(std::move(new_op));
1514 template <typename LoaderDomain, typename SpecificLoader>
1515 void BaseLoader<LoaderDomain, SpecificLoader>::loadFusedBatchNorm(const Operator *op,
1518 ir::OperandIndexSequence inputs;
1519 ir::OperandIndexSequence outputs;
1521 loadOperationIO(op, inputs, outputs);
1522 ir::operation::FusedBatchNorm::Param param;
1524 if (inputs.size() != 5)
1526 throw std::runtime_error{"FusedBatchNorm: NYI input - only support five inputs"};
1529 if (op->custom_options() == nullptr)
1531 throw std::runtime_error{"FusedBatchNorm: empty option"};
1535 size_t custom_op_data_size = op->custom_options()->size();
1536 auto custom_op_data = op->custom_options()->Data();
1537 auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
1538 auto attr_map = data_root.AsMap();
1539 param.is_training = attr_map["is_training"].AsBool();
1540 param.epsilon = attr_map["epsilon"].AsFloat();
1541 param.data_format = attr_map["data_format"].ToString();
1544 std::unique_ptr<ir::Operation> new_op{new ir::operation::FusedBatchNorm{inputs, outputs, param}};
1545 subg.addOperation(std::move(new_op));
1548 template <typename LoaderDomain, typename SpecificLoader>
1549 void BaseLoader<LoaderDomain, SpecificLoader>::loadOneHot(const Operator *op, ir::Graph &subg)
1551 if (op->inputs()->size() != 4 || op->outputs()->size() != 1)
1552 throw std::runtime_error("OneHot Op has wrong number of input or output tensors.");
1554 // Set input and output tensors
1555 ir::OperandIndexSequence inputs, outputs;
1556 loadOperationIO(op, inputs, outputs);
1559 const auto axis = op->builtin_options_as_OneHotOptions()->axis();
1560 std::unique_ptr<ir::Operation> new_op(new ir::operation::OneHot(inputs, outputs, {axis}));
1561 subg.addOperation(std::move(new_op));
1564 template <typename LoaderDomain, typename SpecificLoader>
1565 void BaseLoader<LoaderDomain, SpecificLoader>::loadAbs(const Operator *op, ir::Graph &subg)
1567 ir::OperandIndexSequence inputs;
1568 ir::OperandIndexSequence outputs;
1570 loadOperationIO(op, inputs, outputs);
1572 std::unique_ptr<ir::Operation> new_op(new ir::operation::Abs(inputs, outputs));
1573 subg.addOperation(std::move(new_op));
1576 template <typename LoaderDomain, typename SpecificLoader>
1577 void BaseLoader<LoaderDomain, SpecificLoader>::loadCos(const Operator *op, ir::Graph &subg)
1579 ir::OperandIndexSequence inputs;
1580 ir::OperandIndexSequence outputs;
1582 loadOperationIO(op, inputs, outputs);
1584 std::unique_ptr<ir::Operation> new_op(new ir::operation::Cos(inputs, outputs));
1585 subg.addOperation(std::move(new_op));
1588 template <typename LoaderDomain, typename SpecificLoader>
1589 void BaseLoader<LoaderDomain, SpecificLoader>::loadSin(const Operator *op, ir::Graph &subg)
1591 ir::OperandIndexSequence inputs;
1592 ir::OperandIndexSequence outputs;
1594 loadOperationIO(op, inputs, outputs);
1596 std::unique_ptr<ir::Operation> new_op(new ir::operation::Sin(inputs, outputs));
1597 subg.addOperation(std::move(new_op));
1600 template <typename LoaderDomain, typename SpecificLoader>
1601 void BaseLoader<LoaderDomain, SpecificLoader>::loadShape(const Operator *op, ir::Graph &subg)
1603 ir::OperandIndexSequence inputs;
1604 ir::OperandIndexSequence outputs;
1606 loadOperationIO(op, inputs, outputs);
1608 // ir::operation::Shape::Param param;
1609 // const auto *options = op->builtin_options_as_ShapeOptions();
1610 // param.out_type = tensorTypeToDataType(options->out_type());
1612 std::unique_ptr<ir::Operation> new_op(new ir::operation::Shape(inputs, outputs /*, param*/));
1613 subg.addOperation(std::move(new_op));
1616 template <typename LoaderDomain, typename SpecificLoader>
1617 void BaseLoader<LoaderDomain, SpecificLoader>::loadIf(const Operator *op, ir::Graph &subg)
1619 ir::OperandIndexSequence inputs;
1620 ir::OperandIndexSequence outputs;
1622 loadOperationIO(op, inputs, outputs);
1624 ir::operation::If::Param param;
1625 const auto *options = op->builtin_options_as_IfOptions();
1626 const uint32_t then_index = options->then_subgraph_index();
1627 const uint32_t else_index = options->else_subgraph_index();
1628 param.then_subg_index = ir::SubgraphIndex{then_index};
1629 param.else_subg_index = ir::SubgraphIndex{else_index};
1631 std::unique_ptr<ir::Operation> new_op(new ir::operation::If(inputs, outputs, param));
1632 subg.addOperation(std::move(new_op));
1635 template <typename LoaderDomain, typename SpecificLoader>
1636 void BaseLoader<LoaderDomain, SpecificLoader>::loadWhile(const Operator *op, ir::Graph &subg)
1638 ir::OperandIndexSequence inputs;
1639 ir::OperandIndexSequence outputs;
1641 loadOperationIO(op, inputs, outputs);
1643 ir::operation::While::Param param;
1644 const auto *options = op->builtin_options_as_WhileOptions();
1645 const uint32_t cond_index = options->cond_subgraph_index();
1646 const uint32_t body_index = options->body_subgraph_index();
1647 param.cond_subg_index = ir::SubgraphIndex{cond_index};
1648 param.body_subg_index = ir::SubgraphIndex{body_index};
1650 std::unique_ptr<ir::Operation> new_op(new ir::operation::While(inputs, outputs, param));
1651 subg.addOperation(std::move(new_op));
1654 template <typename LoaderDomain, typename SpecificLoader>
1655 void BaseLoader<LoaderDomain, SpecificLoader>::loadNeg(const Operator *op, ir::Graph &subg)
1657 ir::OperandIndexSequence inputs;
1658 ir::OperandIndexSequence outputs;
1660 loadOperationIO(op, inputs, outputs);
1662 std::unique_ptr<ir::Operation> new_op(new ir::operation::Neg(inputs, outputs));
1663 subg.addOperation(std::move(new_op));
1666 template <typename LoaderDomain, typename SpecificLoader>
1667 void BaseLoader<LoaderDomain, SpecificLoader>::loadArgMax(const Operator *op, ir::Graph &subg)
1669 ir::OperandIndexSequence inputs;
1670 ir::OperandIndexSequence outputs;
1672 loadOperationIO(op, inputs, outputs);
1674 auto inputOperand = subg.operands().at(inputs.at(0));
1675 auto axisOperand = subg.operands().at(inputs.at(1));
1677 if (!axisOperand.isConstant())
1678 throw std::runtime_error("ArgMax: non-constant 'axis' is not supported.");
1679 if (!(axisOperand.operandSize() == 4 && (axisOperand.typeInfo().type() == ir::DataType::INT32 ||
1680 axisOperand.typeInfo().type() == ir::DataType::INT64)))
1681 throw std::runtime_error("ArgMax: `axis` with an int32 or int64 element is only supported.");
1683 ir::operation::ArgMax::Param param;
1684 param.axis = axisOperand.template asVector<int>()[0];
1685 const auto output_type = op->builtin_options_as_ArgMaxOptions()->output_type();
1686 switch (output_type)
1688 case TensorType::TensorType_INT32:
1689 case TensorType::TensorType_INT64:
1692 throw std::runtime_error("ArgMax: `output_type` must be either int32 or int64.");
1694 param.output_type = tensorTypeToDataType(output_type);
1695 std::unique_ptr<ir::Operation> new_op(new ir::operation::ArgMax(inputs, outputs, param));
1696 subg.addOperation(std::move(new_op));
1699 template <typename LoaderDomain, typename SpecificLoader>
1700 void BaseLoader<LoaderDomain, SpecificLoader>::loadLog(const Operator *op, ir::Graph &subg)
1702 ir::OperandIndexSequence inputs;
1703 ir::OperandIndexSequence outputs;
1705 loadOperationIO(op, inputs, outputs);
1707 std::unique_ptr<ir::Operation> new_op(new ir::operation::Log(inputs, outputs));
1708 subg.addOperation(std::move(new_op));
1711 template <typename LoaderDomain, typename SpecificLoader>
1712 void BaseLoader<LoaderDomain, SpecificLoader>::loadRound(const Operator *op, ir::Graph &subg)
1714 ir::OperandIndexSequence inputs;
1715 ir::OperandIndexSequence outputs;
1717 loadOperationIO(op, inputs, outputs);
1719 std::unique_ptr<ir::Operation> new_op(new ir::operation::Round(inputs, outputs));
1720 subg.addOperation(std::move(new_op));
1723 template <typename LoaderDomain, typename SpecificLoader>
1724 void BaseLoader<LoaderDomain, SpecificLoader>::loadPow(const Operator *op, ir::Graph &subg)
1726 ir::OperandIndexSequence inputs;
1727 ir::OperandIndexSequence outputs;
1729 loadOperationIO(op, inputs, outputs);
1731 std::unique_ptr<ir::Operation> new_op(new ir::operation::Pow(inputs, outputs));
1732 subg.addOperation(std::move(new_op));
1735 template <typename LoaderDomain, typename SpecificLoader>
1736 void BaseLoader<LoaderDomain, SpecificLoader>::loadLogicalNot(const Operator *op, ir::Graph &subg)
1738 ir::OperandIndexSequence inputs;
1739 ir::OperandIndexSequence outputs;
1741 loadOperationIO(op, inputs, outputs);
1743 std::unique_ptr<ir::Operation> new_op(new ir::operation::LogicalNot(inputs, outputs));
1744 subg.addOperation(std::move(new_op));
1747 template <typename LoaderDomain, typename SpecificLoader>
1748 void BaseLoader<LoaderDomain, SpecificLoader>::loadZerosLike(const Operator *op, ir::Graph &subg)
1750 ir::OperandIndexSequence inputs;
1751 ir::OperandIndexSequence outputs;
1753 loadOperationIO(op, inputs, outputs);
1755 std::unique_ptr<ir::Operation> new_op(new ir::operation::ZerosLike(inputs, outputs));
1757 subg.addOperation(std::move(new_op));
1760 template <typename LoaderDomain, typename SpecificLoader>
1761 void BaseLoader<LoaderDomain, SpecificLoader>::loadRange(const Operator *op, ir::Graph &subg)
1763 ir::OperandIndexSequence inputs;
1764 ir::OperandIndexSequence outputs;
1766 loadOperationIO(op, inputs, outputs);
1768 std::unique_ptr<ir::Operation> new_op(new ir::operation::Range(inputs, outputs));
1769 subg.addOperation(std::move(new_op));
1772 template <typename LoaderDomain, typename SpecificLoader>
1773 void BaseLoader<LoaderDomain, SpecificLoader>::loadTile(const Operator *op, ir::Graph &subg)
1775 ir::OperandIndexSequence inputs;
1776 ir::OperandIndexSequence outputs;
1778 loadOperationIO(op, inputs, outputs);
1780 auto multiples = inputs.at(ir::operation::Tile::MULTIPLES);
1782 if (!subg.operands().at(multiples).isConstant())
1783 throw std::runtime_error("Tile: non-constant 'multiples' is not supported.");
1785 std::unique_ptr<ir::Operation> new_op(new ir::operation::Tile(inputs, outputs));
1786 subg.addOperation(std::move(new_op));
1789 template <typename LoaderDomain, typename SpecificLoader>
1790 void BaseLoader<LoaderDomain, SpecificLoader>::loadLogicalOr(const Operator *op, ir::Graph &subg)
1792 ir::OperandIndexSequence inputs;
1793 ir::OperandIndexSequence outputs;
1795 loadOperationIO(op, inputs, outputs);
1797 std::unique_ptr<ir::Operation> new_op(new ir::operation::LogicalOr(inputs, outputs));
1798 subg.addOperation(std::move(new_op));
1801 template <typename LoaderDomain, typename SpecificLoader>
1802 void BaseLoader<LoaderDomain, SpecificLoader>::loadLogSoftmax(const Operator *op, ir::Graph &subg)
1804 ir::OperandIndexSequence inputs;
1805 ir::OperandIndexSequence outputs;
1807 loadOperationIO(op, inputs, outputs);
1809 ir::operation::LogSoftmax::Param param;
1811 // In tflite, beta is fixed to 1.0 and axis is fixed to -1.
1815 std::unique_ptr<ir::Operation> new_op(new ir::operation::LogSoftmax(inputs, outputs, param));
1816 subg.addOperation(std::move(new_op));
1819 template <typename LoaderDomain, typename SpecificLoader>
1820 void BaseLoader<LoaderDomain, SpecificLoader>::loadQuantize(const Operator *op, ir::Graph &subg)
1822 ir::OperandIndexSequence inputs;
1823 ir::OperandIndexSequence outputs;
1825 loadOperationIO(op, inputs, outputs);
1827 std::unique_ptr<ir::Operation> new_op(new ir::operation::Quantize(inputs, outputs));
1828 subg.addOperation(std::move(new_op));
1831 template <typename LoaderDomain, typename SpecificLoader>
1832 void BaseLoader<LoaderDomain, SpecificLoader>::loadOperation(const Operator *op, ir::Graph &subg)
1834 const auto builtin_op = _model->operator_codes()->Get(op->opcode_index())->builtin_code();
1838 case BuiltinOperator::BuiltinOperator_CONV_2D:
1839 loadConv2D(op, subg);
1841 case BuiltinOperator::BuiltinOperator_AVERAGE_POOL_2D:
1842 loadAvgPool2D(op, subg);
1844 case BuiltinOperator::BuiltinOperator_DEPTHWISE_CONV_2D:
1845 loadDepthwiseConv2D(op, subg);
1847 case BuiltinOperator::BuiltinOperator_TRANSPOSE_CONV:
1848 loadTransposeConv(op, subg);
1850 case BuiltinOperator::BuiltinOperator_RESHAPE:
1851 loadReshape(op, subg);
1853 case BuiltinOperator::BuiltinOperator_SOFTMAX:
1854 loadSoftmax(op, subg);
1856 case BuiltinOperator::BuiltinOperator_MAX_POOL_2D:
1857 loadMaxPool2D(op, subg);
1859 case BuiltinOperator::BuiltinOperator_CONCATENATION:
1860 loadConcatenation(op, subg);
1862 case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
1865 case BuiltinOperator::BuiltinOperator_ADD:
1868 case BuiltinOperator::BuiltinOperator_SUB:
1871 case BuiltinOperator::BuiltinOperator_MUL:
1874 case BuiltinOperator::BuiltinOperator_DIV:
1877 case BuiltinOperator::BuiltinOperator_PACK:
1880 case BuiltinOperator::BuiltinOperator_RELU:
1883 case BuiltinOperator::BuiltinOperator_RELU6:
1884 loadRelu6(op, subg);
1886 case BuiltinOperator::BuiltinOperator_RESIZE_BILINEAR:
1887 loadResizeBilinear(op, subg);
1889 case BuiltinOperator::BuiltinOperator_RSQRT:
1890 loadRsqrt(op, subg);
1892 case BuiltinOperator::BuiltinOperator_SELECT:
1893 loadSelect(op, subg);
1895 case BuiltinOperator::BuiltinOperator_SELECT_V2:
1896 // Use same loader with BuiltinOperator_SELECT
1897 loadSelect(op, subg);
1899 case BuiltinOperator::BuiltinOperator_SQRT:
1902 case BuiltinOperator::BuiltinOperator_SQUARED_DIFFERENCE:
1903 loadSquaredDifference(op, subg);
1905 case BuiltinOperator::BuiltinOperator_TANH:
1908 case BuiltinOperator::BuiltinOperator_TRANSPOSE:
1909 loadTranspose(op, subg);
1911 case BuiltinOperator::BuiltinOperator_MEAN:
1912 loadReduce(op, subg, ir::operation::Reduce::ReduceType::MEAN);
1914 case BuiltinOperator::BuiltinOperator_REDUCE_ANY:
1915 loadReduce(op, subg, ir::operation::Reduce::ReduceType::ANY);
1917 case BuiltinOperator::BuiltinOperator_REDUCE_MAX:
1918 loadReduce(op, subg, ir::operation::Reduce::ReduceType::MAX);
1920 case BuiltinOperator::BuiltinOperator_REVERSE_V2:
1921 loadReverseV2(op, subg);
1923 case BuiltinOperator::BuiltinOperator_PAD:
1926 case BuiltinOperator::BuiltinOperator_LOGISTIC:
1927 loadLogistic(op, subg);
1929 case BuiltinOperator::BuiltinOperator_EXP:
1932 case BuiltinOperator::BuiltinOperator_EXPAND_DIMS:
1933 loadExpandDims(op, subg);
1935 case BuiltinOperator::BuiltinOperator_GATHER:
1936 loadGather(op, subg);
1938 case BuiltinOperator::BuiltinOperator_SPACE_TO_BATCH_ND:
1939 loadSpaceToBatchND(op, subg);
1941 case BuiltinOperator::BuiltinOperator_BATCH_TO_SPACE_ND:
1942 loadBatchToSpaceND(op, subg);
1944 case BuiltinOperator::BuiltinOperator_SUM:
1945 loadReduce(op, subg, ir::operation::Reduce::ReduceType::SUM);
1947 case BuiltinOperator::BuiltinOperator_CUSTOM:
1948 loadCustom(op, subg);
1950 case BuiltinOperator::BuiltinOperator_SQUEEZE:
1951 loadSqueeze(op, subg);
1953 case BuiltinOperator::BuiltinOperator_PRELU:
1954 loadPrelu(op, subg);
1956 case BuiltinOperator::BuiltinOperator_SPLIT:
1957 loadSplit(op, subg);
1959 case BuiltinOperator::BuiltinOperator_SPLIT_V:
1960 loadSplitV(op, subg);
1962 case BuiltinOperator::BuiltinOperator_SLICE:
1963 loadSlice(op, subg);
1965 case BuiltinOperator::BuiltinOperator_STRIDED_SLICE:
1966 loadStridedSlice(op, subg);
1968 case BuiltinOperator::BuiltinOperator_UNPACK:
1969 loadUnpack(op, subg);
1971 case BuiltinOperator::BuiltinOperator_MINIMUM:
1972 loadMinimum(op, subg);
1974 case BuiltinOperator::BuiltinOperator_MAXIMUM:
1975 loadMaximum(op, subg);
1977 case BuiltinOperator::BuiltinOperator_CAST:
1980 case BuiltinOperator::BuiltinOperator_EQUAL:
1981 case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
1982 case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
1983 case BuiltinOperator::BuiltinOperator_GREATER:
1984 case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
1985 case BuiltinOperator::BuiltinOperator_LESS:
1986 loadComparison(op, subg);
1988 case BuiltinOperator::BuiltinOperator_ONE_HOT:
1989 loadOneHot(op, subg);
1991 case BuiltinOperator::BuiltinOperator_ABS:
1994 case BuiltinOperator::BuiltinOperator_COS:
1997 case BuiltinOperator::BuiltinOperator_SIN:
2000 case BuiltinOperator::BuiltinOperator_SHAPE:
2001 loadShape(op, subg);
2003 case BuiltinOperator::BuiltinOperator_REDUCE_PROD:
2004 loadReduce(op, subg, ir::operation::Reduce::ReduceType::PROD);
2006 case BuiltinOperator::BuiltinOperator_IF:
2009 case BuiltinOperator::BuiltinOperator_WHILE:
2010 loadWhile(op, subg);
2012 case BuiltinOperator::BuiltinOperator_NEG:
2015 case BuiltinOperator::BuiltinOperator_ARG_MAX:
2016 loadArgMax(op, subg);
2018 case BuiltinOperator::BuiltinOperator_LOG:
2021 case BuiltinOperator::BuiltinOperator_ROUND:
2022 loadRound(op, subg);
2024 case BuiltinOperator::BuiltinOperator_POW:
2027 case BuiltinOperator::BuiltinOperator_LOGICAL_NOT:
2028 loadLogicalNot(op, subg);
2030 case BuiltinOperator::BuiltinOperator_LOGICAL_OR:
2031 loadLogicalOr(op, subg);
2033 case BuiltinOperator::BuiltinOperator_FILL:
2036 case BuiltinOperator::BuiltinOperator_ZEROS_LIKE:
2037 loadZerosLike(op, subg);
2039 case BuiltinOperator::BuiltinOperator_TILE:
2042 case BuiltinOperator::BuiltinOperator_RANGE:
2043 loadRange(op, subg);
2045 case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
2046 loadBatchMatMul(op, subg);
2048 case BuiltinOperator::BuiltinOperator_LOG_SOFTMAX:
2049 loadLogSoftmax(op, subg);
2051 case BuiltinOperator::BuiltinOperator_QUANTIZE:
2052 loadQuantize(op, subg);
2054 case BuiltinOperator::BuiltinOperator_SPACE_TO_DEPTH:
2055 loadSpaceToDepth(op, subg);
2058 throw std::runtime_error(
2059 std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
2063 template <typename LoaderDomain, typename SpecificLoader>
2064 void BaseLoader<LoaderDomain, SpecificLoader>::loadModel()
2066 LoaderDomain::VerifyModelBuffer(*_verifier.get());
2067 _model = LoaderDomain::GetModel(_base);
2069 // const auto version = _model->version();
2070 // Description unused
2071 // const auto *description = _model->description();
2072 // Metabuffer unsued
2073 // const auto *metadata_buffer = _model->metadata_buffer();
2074 // Load subgraphs and map operations on subgraph
2075 const auto domain_subgraphs = _model->subgraphs();
2076 auto subgraphs = std::make_unique<ir::Subgraphs>();
2077 for (uint32_t subgraph_index = 0; subgraph_index < domain_subgraphs->size(); ++subgraph_index)
2080 static_cast<SpecificLoader *>(this)->loadSubgraph((*_model->subgraphs())[subgraph_index]);
2081 subgraphs->push(ir::SubgraphIndex{subgraph_index}, std::move(subg));
2083 _subgraphs = std::move(subgraphs);
2086 } // namespace base_loader
2087 } // namespace onert
2089 #endif //__BASE_LOADER_BASE_LOADER_H__