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 #include "circle_loader.h"
18 #include "base_loader.h"
19 #include "circle_schema_generated.h"
23 namespace circle_loader
29 ir::Layout convertDataFormat(circle::DataFormat data_format)
33 case circle::DataFormat::DataFormat_CHANNELS_FIRST:
34 return ir::Layout::NCHW;
35 case circle::DataFormat::DataFormat_CHANNELS_LAST:
36 return ir::Layout::NHWC;
38 throw std::runtime_error("Unsupported DataFormat");
44 using Verifier = flatbuffers::Verifier;
45 using ActivationFunctionType = circle::ActivationFunctionType;
46 using Buffer = circle::Buffer;
47 using BuiltinOperator = circle::BuiltinOperator;
48 using CustomOptionsFormat = circle::CustomOptionsFormat;
49 using Model = circle::Model;
50 using Operator = circle::Operator;
51 using Padding = circle::Padding;
52 using Pool2DOptions = circle::Pool2DOptions;
53 using Tensor = circle::Tensor;
54 using TensorType = circle::TensorType;
55 using SubGraph = circle::SubGraph;
56 using DimensionType = circle::DimensionType;
57 using SparseIndexVector = circle::SparseIndexVector;
59 static const char *EnumNameBuiltinOperator(BuiltinOperator e)
61 return circle::EnumNameBuiltinOperator(e);
63 static const char *EnumNameActivationFunctionType(ActivationFunctionType e)
65 return circle::EnumNameActivationFunctionType(e);
67 static const char *EnumNameTensorType(TensorType e) { return circle::EnumNameTensorType(e); }
68 static const Model *GetModel(const void *buf) { return circle::GetModel(buf); }
69 static bool VerifyModelBuffer(Verifier &verifier) { return circle::VerifyModelBuffer(verifier); }
72 class CircleLoader final : public base_loader::BaseLoader<LoaderDomain>
75 void loadInstanceNorm(const Operator *op, ir::Graph &subg);
76 void loadBCQFullyConnected(const Operator *op, ir::Graph &subg);
77 void loadBCQGather(const Operator *op, ir::Graph &subg);
80 using BaseLoader::BaseLoader;
82 bool allowOptionalInputTensor(BuiltinOperator op) override
86 case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
87 case BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
88 case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
96 std::unique_ptr<ir::Graph> loadSubgraph(const circle::SubGraph *circle_subg) override
98 auto subg = std::make_unique<ir::Graph>();
100 _tensor_to_operand.resize(circle_subg->tensors()->size());
101 for (flatbuffers::uoffset_t i = 0; i < circle_subg->tensors()->size(); ++i)
103 _tensor_to_operand[i] = loadOperand(circle_subg->tensors()->Get(i), *subg);
106 for (const std::int32_t input_ind : *circle_subg->inputs())
108 subg->addInput(tensorIdxToOperandIdx(input_ind),
109 _tensor_names.at(_tensor_to_operand[input_ind]));
112 for (const std::int32_t output_ind : *circle_subg->outputs())
114 subg->addOutput(tensorIdxToOperandIdx(output_ind),
115 _tensor_names.at(_tensor_to_operand[output_ind]));
118 for (const auto *op : *circle_subg->operators())
120 CircleLoader::loadOperation(op, *subg);
123 subg->setLayout(convertDataFormat(circle_subg->data_format()));
125 subg->finishBuilding();
130 void loadOperation(const circle::Operator *op, ir::Graph &subg)
132 const auto builtin_op = _model->operator_codes()->Get(op->opcode_index())->builtin_code();
136 case circle::BuiltinOperator::BuiltinOperator_INSTANCE_NORM:
137 loadInstanceNorm(op, subg);
139 case circle::BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
140 loadBCQFullyConnected(op, subg);
142 case circle::BuiltinOperator::BuiltinOperator_BCQ_GATHER:
143 loadBCQGather(op, subg);
146 BaseLoader::loadOperation(op, subg);
152 void CircleLoader::loadInstanceNorm(const Operator *op, ir::Graph &subg)
154 ir::OperandIndexSequence inputs;
155 ir::OperandIndexSequence outputs;
157 loadOperationIO(op, inputs, outputs);
159 ir::operation::InstanceNorm::Param param;
160 const auto *options = op->builtin_options_as_InstanceNormOptions();
162 param.activation = convertActivation(options->fused_activation_function());
163 // Use default value 1e-5 if value of epsilon is zero
164 param.epsilon = options->epsilon() == 0.f ? 1e-5 : options->epsilon();
166 std::unique_ptr<ir::Operation> new_op(new ir::operation::InstanceNorm(inputs, outputs, param));
167 subg.addOperation(std::move(new_op));
170 void CircleLoader::loadBCQGather(const Operator *op, ir::Graph &subg)
172 ir::OperandIndexSequence inputs;
173 ir::OperandIndexSequence outputs;
175 loadOperationIO(op, inputs, outputs);
177 ir::operation::BCQGather::Param param;
178 const auto *options = op->builtin_options_as_BCQGatherOptions();
179 param.input_hidden_size = options->input_hidden_size();
180 param.axis = options->axis();
182 std::unique_ptr<ir::Operation> new_op(new ir::operation::BCQGather(inputs, outputs, param));
183 subg.addOperation(std::move(new_op));
186 void CircleLoader::loadBCQFullyConnected(const Operator *op, ir::Graph &subg)
188 ir::OperandIndexSequence inputs;
189 ir::OperandIndexSequence outputs;
191 loadOperationIO(op, inputs, outputs);
193 ir::operation::BCQFullyConnected::Param param;
194 const auto *options = op->builtin_options_as_BCQFullyConnectedOptions();
195 param.weights_hidden_size = options->weights_hidden_size();
196 param.activation = convertActivation(options->fused_activation_function());
198 std::unique_ptr<ir::Operation> new_op(
199 new ir::operation::BCQFullyConnected(inputs, outputs, param));
200 subg.addOperation(std::move(new_op));
205 std::unique_ptr<ir::Subgraphs> loadModel(const char *filename)
207 auto subgraphs = std::make_unique<ir::Subgraphs>();
208 CircleLoader loader(subgraphs);
209 loader.loadFromFile(filename);
213 std::unique_ptr<ir::Subgraphs> loadModel(uint8_t *buffer, size_t size)
215 auto subgraphs = std::make_unique<ir::Subgraphs>();
216 CircleLoader loader(subgraphs);
217 loader.loadFromBuffer(buffer, size);
221 } // namespace circle_loader