Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / tests / nnfw_api / src / CircleGen.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "CircleGen.h"
18 #include "flatbuffers/flexbuffers.h"
19
20 CircleGen::CircleGen() : _subgraph_contexts(1) // Create primary subgraph
21 {
22   // 0th buffer is always the empty buffer for non-const tensors
23   addBuffer(nullptr, 0);
24 }
25
26 template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
27 {
28   auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
29   auto size = buf_vec.size() * sizeof(T);
30   return addBuffer(buf, size);
31 }
32
33 uint32_t CircleGen::addBuffer(const uint8_t *buf, size_t size)
34 {
35   uint32_t ind = _buffers.size();
36   _buffers.emplace_back(buildBuffer(buf, size));
37   return ind;
38 }
39
40 uint32_t CircleGen::addTensor(const TensorParams &params)
41 {
42   uint32_t ind = curSubgCtx().tensors.size();
43   curSubgCtx().tensors.emplace_back(buildTensor(params));
44   return ind;
45 }
46
47 uint32_t CircleGen::addTensor(const TensorParams &params, float scale, int64_t zero_point)
48 {
49   // TensorType_INT8: scale >= 0, zero_point: [-128, 127]
50   // TensorType_UINT8: scale >= 0, zero_point: [0, 255]
51   uint32_t ind = curSubgCtx().tensors.size();
52   curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
53   return ind;
54 }
55
56 uint32_t CircleGen::addTensor(const TensorParams &params, std::vector<float> &scale,
57                               std::vector<int64_t> &zero_point)
58 {
59   uint32_t ind = curSubgCtx().tensors.size();
60   curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
61   return ind;
62 }
63
64 uint32_t CircleGen::addTensor(const TensorParams &params, const SparsityParams &sp)
65 {
66   uint32_t ind = curSubgCtx().tensors.size();
67   curSubgCtx().tensors.emplace_back(buildTensor(params, sp));
68   return ind;
69 }
70
71 void CircleGen::setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs)
72 {
73   curSubgCtx().inputs = inputs;
74   curSubgCtx().outputs = outputs;
75 }
76
77 uint32_t CircleGen::nextSubgraph()
78 {
79   uint32_t ind = _subgraph_contexts.size();
80   _subgraph_contexts.push_back({});
81   return ind;
82 }
83
84 CircleBuffer CircleGen::finish()
85 {
86   std::vector<flatbuffers::Offset<circle::SubGraph>> subgraphs;
87   for (auto &ctx : _subgraph_contexts)
88     subgraphs.push_back(buildSubGraph(ctx));
89   auto model =
90     circle::CreateModelDirect(_fbb, 3, &_opcodes, &subgraphs, "CircleGen generated", &_buffers);
91   _fbb.Finish(model);
92   return CircleBuffer{std::move(_fbb)};
93 }
94
95 // ===== Add Operator methods begin =====
96
97 uint32_t CircleGen::addOperatorAdd(const OperatorParams &params,
98                                    circle::ActivationFunctionType actfn)
99 {
100   auto options = circle::CreateAddOptions(_fbb, actfn).Union();
101   return addOperatorWithOptions(params, circle::BuiltinOperator_ADD,
102                                 circle::BuiltinOptions_AddOptions, options);
103 }
104
105 uint32_t CircleGen::addOperatorAddN(const OperatorParams &params)
106 {
107   auto options = circle::CreateAddNOptions(_fbb).Union();
108   return addOperatorWithOptions(params, circle::BuiltinOperator_ADD_N,
109                                 circle::BuiltinOptions_AddNOptions, options);
110 }
111
112 uint32_t CircleGen::addOperatorArgMax(const OperatorParams &params, circle::TensorType output_type)
113 {
114   auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
115   return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MAX,
116                                 circle::BuiltinOptions_ArgMaxOptions, options);
117 }
118
119 uint32_t CircleGen::addOperatorArgMin(const OperatorParams &params, circle::TensorType output_type)
120 {
121   auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
122   return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MIN,
123                                 circle::BuiltinOptions_ArgMinOptions, options);
124 }
125
126 uint32_t CircleGen::addOperatorAveragePool2D(const OperatorParams &params, circle::Padding padding,
127                                              int stride_w, int stride_h, int filter_w, int filter_h,
128                                              circle::ActivationFunctionType actfn)
129 {
130   auto options =
131     circle::CreatePool2DOptions(_fbb, padding, stride_w, stride_h, filter_w, filter_h, actfn)
132       .Union();
133   return addOperatorWithOptions(params, circle::BuiltinOperator_AVERAGE_POOL_2D,
134                                 circle::BuiltinOptions_Pool2DOptions, options);
135 }
136
137 uint32_t CircleGen::addOperatorCast(const OperatorParams &params, circle::TensorType input_type,
138                                     circle::TensorType output_type)
139 {
140   auto options = circle::CreateCastOptions(_fbb, input_type, output_type).Union();
141   return addOperatorWithOptions(params, circle::BuiltinOperator_CAST,
142                                 circle::BuiltinOptions_AddOptions, options);
143 }
144
145 uint32_t CircleGen::addOperatorConcatenation(const OperatorParams &params, int axis,
146                                              circle::ActivationFunctionType actfn)
147 {
148   auto options = circle::CreateConcatenationOptions(_fbb, axis, actfn).Union();
149   return addOperatorWithOptions(params, circle::BuiltinOperator_CONCATENATION,
150                                 circle::BuiltinOptions_ConcatenationOptions, options);
151 }
152
153 uint32_t CircleGen::addOperatorConv2D(const OperatorParams &params, circle::Padding padding,
154                                       int stride_w, int stride_h,
155                                       circle::ActivationFunctionType actfn, int dilation_w,
156                                       int dilation_h)
157 {
158   auto options =
159     circle::CreateConv2DOptions(_fbb, padding, stride_w, stride_h, actfn, dilation_w, dilation_h)
160       .Union();
161   return addOperatorWithOptions(params, circle::BuiltinOperator_CONV_2D,
162                                 circle::BuiltinOptions_Conv2DOptions, options);
163 }
164
165 uint32_t CircleGen::addOperatorCos(const OperatorParams &params)
166 {
167   auto options = circle::CreateCosOptions(_fbb).Union();
168   return addOperatorWithOptions(params, circle::BuiltinOperator_COS,
169                                 circle::BuiltinOptions_CosOptions, options);
170 }
171
172 uint32_t CircleGen::addOperatorDepthToSpace(const OperatorParams &params, int32_t block_size)
173 {
174   auto options = circle::CreateDepthToSpaceOptions(_fbb, block_size).Union();
175   return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTH_TO_SPACE,
176                                 circle::BuiltinOptions_DepthToSpaceOptions, options);
177 }
178
179 uint32_t CircleGen::addOperatorDepthwiseConv2D(const OperatorParams &params,
180                                                circle::Padding padding, int stride_w, int stride_h,
181                                                int depth_multiplier,
182                                                circle::ActivationFunctionType actfn, int dilation_w,
183                                                int dilation_h)
184 {
185   auto options =
186     circle::CreateDepthwiseConv2DOptions(_fbb, padding, stride_w, stride_h, depth_multiplier, actfn,
187                                          dilation_w, dilation_h)
188       .Union();
189   return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTHWISE_CONV_2D,
190                                 circle::BuiltinOptions_DepthwiseConv2DOptions, options);
191 }
192
193 uint32_t CircleGen::addOperatorDetectionPostProcess(const OperatorParams &params, int num_classes,
194                                                     float y_scale, float x_scale, float h_scale,
195                                                     float w_scale, float nms_score_threshold,
196                                                     float nms_iou_threshold, int max_detections,
197                                                     int max_classes_per_detection,
198                                                     int detections_per_class)
199 {
200   // flexbuffer custom_option
201   auto flex_buffers = std::make_unique<flexbuffers::Builder>();
202   size_t map_start = flex_buffers->StartMap();
203   flex_buffers->Int("num_classes", num_classes);
204   flex_buffers->Float("y_scale", y_scale);
205   flex_buffers->Float("x_scale", x_scale);
206   flex_buffers->Float("h_scale", h_scale);
207   flex_buffers->Float("w_scale", w_scale);
208   flex_buffers->Float("nms_iou_threshold", nms_iou_threshold);
209   flex_buffers->Float("nms_score_threshold", nms_score_threshold);
210   flex_buffers->Int("max_detections", max_detections);
211   flex_buffers->Int("max_classes_per_detection", max_classes_per_detection);
212   flex_buffers->Int("detections_per_class", detections_per_class);
213   flex_buffers->EndMap(map_start);
214   flex_buffers->Finish();
215
216   return addCustomOperatorWithOptions(params, "TFLite_Detection_PostProcess",
217                                       circle::BuiltinOptions_NONE, 0, &flex_buffers->GetBuffer(),
218                                       circle::CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS,
219                                       nullptr, nullptr);
220 }
221
222 uint32_t CircleGen::addOperatorElu(const OperatorParams &params)
223 {
224   return addOperatorWithOptions(params, circle::BuiltinOperator_ELU, circle::BuiltinOptions_NONE,
225                                 0);
226 }
227
228 uint32_t CircleGen::addOperatorEqual(const OperatorParams &params)
229 {
230   auto options = circle::CreateEqualOptions(_fbb).Union();
231   return addOperatorWithOptions(params, circle::BuiltinOperator_EQUAL,
232                                 circle::BuiltinOptions_EqualOptions, options);
233 }
234
235 uint32_t CircleGen::addOperatorExpandDims(const OperatorParams &params)
236 {
237   auto options = circle::CreateEqualOptions(_fbb).Union();
238   return addOperatorWithOptions(params, circle::BuiltinOperator_EXPAND_DIMS,
239                                 circle::BuiltinOptions_ExpandDimsOptions, options);
240 }
241
242 uint32_t
243 CircleGen::addOperatorFullyConnected(const OperatorParams &params,
244                                      circle::FullyConnectedOptionsWeightsFormat weights_format)
245 {
246   auto options =
247     circle::CreateFullyConnectedOptions(_fbb, circle::ActivationFunctionType_NONE, weights_format)
248       .Union();
249   return addOperatorWithOptions(params, circle::BuiltinOperator_FULLY_CONNECTED,
250                                 circle::BuiltinOptions_FullyConnectedOptions, options);
251 }
252
253 uint32_t CircleGen::addOperatorFill(const OperatorParams &params)
254 {
255   auto options = circle::CreateFillOptions(_fbb).Union();
256   return addOperatorWithOptions(params, circle::BuiltinOperator_FILL,
257                                 circle::BuiltinOptions_FillOptions, options);
258 }
259
260 uint32_t CircleGen::addOperatorFloor(const OperatorParams &params)
261 {
262   return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR, circle::BuiltinOptions_NONE,
263                                 0);
264 }
265
266 uint32_t CircleGen::addOperatorFloorDiv(const OperatorParams &params)
267 {
268   return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR_DIV,
269                                 circle::BuiltinOptions_NONE, 0);
270 }
271
272 uint32_t CircleGen::addOperatorGreater(const OperatorParams &params)
273 {
274   auto options = circle::CreateLessOptions(_fbb).Union();
275   return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER,
276                                 circle::BuiltinOptions_GreaterOptions, options);
277 }
278
279 uint32_t CircleGen::addOperatorGreaterEqual(const OperatorParams &params)
280 {
281   auto options = circle::CreateGreaterOptions(_fbb).Union();
282   return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER_EQUAL,
283                                 circle::BuiltinOptions_GreaterEqualOptions, options);
284 }
285
286 uint32_t CircleGen::addOperatorL2Normalization(const OperatorParams &params)
287 {
288   auto options = circle::CreateL2NormOptions(_fbb).Union();
289   return addOperatorWithOptions(params, circle::BuiltinOperator_L2_NORMALIZATION,
290                                 circle::BuiltinOptions_L2NormOptions, options);
291 }
292
293 uint32_t CircleGen::addOperatorLess(const OperatorParams &params)
294 {
295   auto options = circle::CreateLessOptions(_fbb).Union();
296   return addOperatorWithOptions(params, circle::BuiltinOperator_LESS,
297                                 circle::BuiltinOptions_LessOptions, options);
298 }
299
300 uint32_t CircleGen::addOperatorLessEqual(const OperatorParams &params)
301 {
302   auto options = circle::CreateLessOptions(_fbb).Union();
303   return addOperatorWithOptions(params, circle::BuiltinOperator_LESS_EQUAL,
304                                 circle::BuiltinOptions_LessEqualOptions, options);
305 }
306
307 uint32_t CircleGen::addOperatorLeakyRelu(const OperatorParams &params, float alpha)
308 {
309   auto options = circle::CreateLeakyReluOptions(_fbb, alpha).Union();
310   return addOperatorWithOptions(params, circle::BuiltinOperator_LEAKY_RELU,
311                                 circle::BuiltinOptions_LeakyReluOptions, options);
312 }
313
314 uint32_t CircleGen::addOperatorLogSoftmax(const OperatorParams &params)
315 {
316   auto options = circle::CreateLogSoftmaxOptions(_fbb).Union();
317   return addOperatorWithOptions(params, circle::BuiltinOperator_LOG_SOFTMAX,
318                                 circle::BuiltinOptions_LogSoftmaxOptions, options);
319 }
320
321 uint32_t CircleGen::addOperatorMean(const OperatorParams &params, bool keep_dims)
322 {
323   auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
324   return addOperatorWithOptions(params, circle::BuiltinOperator_MEAN,
325                                 circle::BuiltinOptions_ReducerOptions, options);
326 }
327
328 uint32_t CircleGen::addOperatorMul(const OperatorParams &params,
329                                    circle::ActivationFunctionType actfn)
330 {
331   auto options = circle::CreateMulOptions(_fbb, actfn).Union();
332   return addOperatorWithOptions(params, circle::BuiltinOperator_MUL,
333                                 circle::BuiltinOptions_MulOptions, options);
334 }
335
336 uint32_t CircleGen::addOperatorNeg(const OperatorParams &params)
337 {
338   auto options = circle::CreatePadOptions(_fbb).Union();
339   return addOperatorWithOptions(params, circle::BuiltinOperator_NEG,
340                                 circle::BuiltinOptions_NegOptions, options);
341 }
342
343 uint32_t CircleGen::addOperatorNotEqual(const OperatorParams &params)
344 {
345   auto options = circle::CreateEqualOptions(_fbb).Union();
346   return addOperatorWithOptions(params, circle::BuiltinOperator_NOT_EQUAL,
347                                 circle::BuiltinOptions_NotEqualOptions, options);
348 }
349
350 uint32_t CircleGen::addOperatorOneHot(const OperatorParams &params, int32_t axis)
351 {
352   auto options = circle::CreateOneHotOptions(_fbb, axis).Union();
353   return addOperatorWithOptions(params, circle::BuiltinOperator_ONE_HOT,
354                                 circle::BuiltinOptions_OneHotOptions, options);
355 }
356
357 uint32_t CircleGen::addOperatorPad(const OperatorParams &params)
358 {
359   auto options = circle::CreatePadOptions(_fbb).Union();
360   return addOperatorWithOptions(params, circle::BuiltinOperator_PAD,
361                                 circle::BuiltinOptions_PadOptions, options);
362 }
363
364 uint32_t CircleGen::addOperatorPadV2(const OperatorParams &params)
365 {
366   auto options = circle::CreatePadOptions(_fbb).Union();
367   return addOperatorWithOptions(params, circle::BuiltinOperator_PADV2,
368                                 circle::BuiltinOptions_PadV2Options, options);
369 }
370
371 uint32_t CircleGen::addOperatorQuantize(const OperatorParams &params)
372 {
373   auto options = circle::CreateQuantizeOptions(_fbb).Union();
374   return addOperatorWithOptions(params, circle::BuiltinOperator_QUANTIZE,
375                                 circle::BuiltinOptions_QuantizeOptions, options);
376 }
377
378 uint32_t CircleGen::addOperatorRank(const OperatorParams &params)
379 {
380   auto options = circle::CreateRankOptions(_fbb).Union();
381   return addOperatorWithOptions(params, circle::BuiltinOperator_RANK,
382                                 circle::BuiltinOptions_RankOptions, options);
383 }
384
385 uint32_t CircleGen::addOperatorReduce(const OperatorParams &params,
386                                       circle::BuiltinOperator reduce_op, bool keep_dims)
387 {
388   switch (reduce_op)
389   {
390     case circle::BuiltinOperator_REDUCE_ANY:
391     case circle::BuiltinOperator_REDUCE_MIN:
392     case circle::BuiltinOperator_REDUCE_MAX:
393     case circle::BuiltinOperator_REDUCE_PROD:
394       break;
395     default:
396       throw std::runtime_error{"Wrong reduce op"};
397   }
398   auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
399   return addOperatorWithOptions(params, reduce_op, circle::BuiltinOptions_ReducerOptions, options);
400 }
401
402 uint32_t CircleGen::addOperatorRelu(const OperatorParams &params)
403 {
404   return addOperatorWithOptions(params, circle::BuiltinOperator_RELU, circle::BuiltinOptions_NONE,
405                                 0);
406 }
407
408 uint32_t CircleGen::addOperatorRelu6(const OperatorParams &params)
409 {
410   return addOperatorWithOptions(params, circle::BuiltinOperator_RELU6, circle::BuiltinOptions_NONE,
411                                 0);
412 }
413
414 uint32_t CircleGen::addOperatorReshape(const OperatorParams &params, const Shape *new_shape)
415 {
416   auto options = circle::CreateReshapeOptionsDirect(_fbb, new_shape).Union();
417   return addOperatorWithOptions(params, circle::BuiltinOperator_RESHAPE,
418                                 circle::BuiltinOptions_ReshapeOptions, options);
419 }
420
421 uint32_t CircleGen::addOperatorResizeBilinear(const OperatorParams &params, bool align_corners,
422                                               bool half_pixel_centers)
423 {
424   auto options =
425     circle::CreateResizeBilinearOptions(_fbb, align_corners, half_pixel_centers).Union();
426   return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_BILINEAR,
427                                 circle::BuiltinOptions_ResizeBilinearOptions, options);
428 }
429
430 uint32_t CircleGen::addOperatorResizeNearestNeighbor(const OperatorParams &params)
431 {
432   auto options = circle::CreateResizeNearestNeighborOptions(_fbb).Union();
433   return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
434                                 circle::BuiltinOptions_ResizeNearestNeighborOptions, options);
435 }
436
437 uint32_t CircleGen::addOperatorReverseV2(const OperatorParams &params)
438 {
439   auto options = circle::CreateReverseV2Options(_fbb).Union();
440   return addOperatorWithOptions(params, circle::BuiltinOperator_REVERSE_V2,
441                                 circle::BuiltinOptions_ReverseV2Options, options);
442 }
443
444 uint32_t CircleGen::addOperatorShape(const OperatorParams &params, circle::TensorType type)
445 {
446   auto options = circle::CreateShapeOptions(_fbb, type).Union();
447   return addOperatorWithOptions(params, circle::BuiltinOperator_SHAPE,
448                                 circle::BuiltinOptions_RankOptions, options);
449 }
450
451 uint32_t CircleGen::addOperatorSelect(const OperatorParams &params)
452 {
453   auto options = circle::CreateSelectOptions(_fbb).Union();
454   return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT,
455                                 circle::BuiltinOptions_SelectOptions, options);
456 }
457
458 uint32_t CircleGen::addOperatorSelectV2(const OperatorParams &params)
459 {
460   auto options = circle::CreateSelectV2Options(_fbb).Union();
461   return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT_V2,
462                                 circle::BuiltinOptions_SelectV2Options, options);
463 }
464
465 uint32_t CircleGen::addOperatorSlice(const OperatorParams &params)
466 {
467   auto options = circle::CreateSliceOptions(_fbb).Union();
468   return addOperatorWithOptions(params, circle::BuiltinOperator_SLICE,
469                                 circle::BuiltinOptions_SliceOptions, options);
470 }
471
472 uint32_t CircleGen::addOperatorSoftmax(const OperatorParams &params, float beta)
473 {
474   auto options = circle::CreateSoftmaxOptions(_fbb, beta).Union();
475   return addOperatorWithOptions(params, circle::BuiltinOperator_SOFTMAX,
476                                 circle::BuiltinOptions_SoftmaxOptions, options);
477 }
478
479 uint32_t CircleGen::addOperatorSplit(const OperatorParams &params, int32_t num_split)
480 {
481   auto options = circle::CreateSplitOptions(_fbb, num_split).Union();
482   return addOperatorWithOptions(params, circle::BuiltinOperator_SPLIT,
483                                 circle::BuiltinOptions_SplitOptions, options);
484 }
485
486 uint32_t CircleGen::addOperatorStridedSlice(const OperatorParams &params, int32_t begin_mask,
487                                             int32_t end_mask, int32_t ellipsis_mask,
488                                             int32_t new_axis_mask, int32_t shrink_axis_mask)
489 {
490   auto options = circle::CreateStridedSliceOptions(_fbb, begin_mask, end_mask, ellipsis_mask,
491                                                    new_axis_mask, shrink_axis_mask)
492                    .Union();
493   return addOperatorWithOptions(params, circle::BuiltinOperator_STRIDED_SLICE,
494                                 circle::BuiltinOptions_StridedSliceOptions, options);
495 }
496
497 uint32_t CircleGen::addOperatorSub(const OperatorParams &params,
498                                    circle::ActivationFunctionType actfn)
499 {
500   auto options = circle::CreateSubOptions(_fbb, actfn).Union();
501   return addOperatorWithOptions(params, circle::BuiltinOperator_SUB,
502                                 circle::BuiltinOptions_SubOptions, options);
503 }
504
505 uint32_t CircleGen::addOperatorTile(const OperatorParams &params)
506 {
507   auto options = circle::CreateTileOptions(_fbb).Union();
508   return addOperatorWithOptions(params, circle::BuiltinOperator_TILE,
509                                 circle::BuiltinOptions_TileOptions, options);
510 }
511
512 uint32_t CircleGen::addOperatorWhile(const OperatorParams &params, uint32_t cond_subg,
513                                      uint32_t body_subg)
514 {
515   auto options = circle::CreateWhileOptions(_fbb, cond_subg, body_subg).Union();
516   return addOperatorWithOptions(params, circle::BuiltinOperator_WHILE,
517                                 circle::BuiltinOptions_WhileOptions, options);
518 }
519
520 uint32_t CircleGen::addOperatorIf(const OperatorParams &params, uint32_t then_subg,
521                                   uint32_t else_subg)
522 {
523   auto options = circle::CreateIfOptions(_fbb, then_subg, else_subg).Union();
524   return addOperatorWithOptions(params, circle::BuiltinOperator_IF,
525                                 circle::BuiltinOptions_IfOptions, options);
526 }
527
528 uint32_t CircleGen::addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
529                                             circle::ActivationFunctionType actfn)
530 {
531   auto options = circle::CreateInstanceNormOptions(_fbb, epsilon, actfn).Union();
532   return addOperatorWithOptions(params, circle::BuiltinOperator_INSTANCE_NORM,
533                                 circle::BuiltinOptions_InstanceNormOptions, options);
534 }
535
536 uint32_t CircleGen::addOperatorTranspose(const OperatorParams &params)
537 {
538   auto options = circle::CreateTransposeOptions(_fbb).Union();
539   return addOperatorWithOptions(params, circle::BuiltinOperator_TRANSPOSE,
540                                 circle::BuiltinOptions_TransposeOptions, options);
541 }
542
543 uint32_t CircleGen::addOperatorSqrt(const OperatorParams &params)
544 {
545   return addOperatorWithOptions(params, circle::BuiltinOperator_SQRT, circle::BuiltinOptions_NONE,
546                                 0);
547 }
548
549 uint32_t CircleGen::addOperatorSquare(const OperatorParams &params)
550 {
551   auto options = circle::CreateSquareOptions(_fbb).Union();
552   return addOperatorWithOptions(params, circle::BuiltinOperator_SQUARE,
553                                 circle::BuiltinOptions_SquareOptions, options);
554 }
555
556 uint32_t CircleGen::addOperatorBatchToSpaceND(const OperatorParams &params)
557 {
558   auto options = circle::CreateBatchToSpaceNDOptions(_fbb).Union();
559   return addOperatorWithOptions(params, circle::BuiltinOperator_BATCH_TO_SPACE_ND,
560                                 circle::BuiltinOptions_BatchToSpaceNDOptions, options);
561 }
562
563 // NOTE Please add addOperator functions ABOVE this lie
564 //
565 // %  How to add a new addOperatorXXX fuction
566 // 0. Copy code from one of the existing addOperatorXXX function
567 // 1. Change the function signature (need BuiltinOperator params)
568 // 2. Change enum BuiltinOperator
569 // 3. Change enum BuiltinOptions
570 // 4. Change CreateXXXOptions accordingly
571 //
572 // If operator don't have option table, remove CreateXXXOptions call,
573 // call addOperatorWithOptions with options_type = circle::BuiltinOptions_NONE and options = 0
574
575 // ===== Add Operator methods end =====
576
577 uint32_t CircleGen::addOperatorWithOptions(const OperatorParams &params,
578                                            circle::BuiltinOperator opcode,
579                                            circle::BuiltinOptions options_type,
580                                            flatbuffers::Offset<void> options)
581 {
582   uint32_t opcode_ind = addOperatorCode(opcode);
583   auto op = circle::CreateOperatorDirect(_fbb, opcode_ind, &params.inputs, &params.outputs,
584                                          options_type, options);
585
586   uint32_t ind = curSubgCtx().operators.size();
587   curSubgCtx().operators.emplace_back(op);
588   return ind;
589 }
590
591 uint32_t CircleGen::addCustomOperatorWithOptions(
592   const OperatorParams &params, std::string custom_code, circle::BuiltinOptions options_type,
593   flatbuffers::Offset<void> options, const std::vector<uint8_t> *custom_options,
594   circle::CustomOptionsFormat custom_options_format,
595   const std::vector<uint8_t> *mutating_variable_inputs, const std::vector<int32_t> *intermediates)
596
597 {
598   uint32_t opcode_ind = addCustomOperatorCode(custom_code);
599   auto op = circle::CreateOperatorDirect(
600     _fbb, opcode_ind, &params.inputs, &params.outputs, options_type, options, custom_options,
601     custom_options_format, mutating_variable_inputs, intermediates);
602
603   uint32_t ind = curSubgCtx().operators.size();
604   curSubgCtx().operators.emplace_back(op);
605   return ind;
606 }
607
608 uint32_t CircleGen::addOperatorCode(circle::BuiltinOperator opcode)
609 {
610   // TODO If the same OperatorCode is registered already, just return it
611   uint32_t ind = _opcodes.size();
612   _opcodes.emplace_back(circle::CreateOperatorCode(_fbb, opcode));
613   return ind;
614 }
615
616 uint32_t CircleGen::addCustomOperatorCode(std::string custom_code)
617 {
618   // TODO If the same OperatorCode is registered already, just return it
619   uint32_t ind = _opcodes.size();
620   _opcodes.emplace_back(
621     circle::CreateOperatorCodeDirect(_fbb, circle::BuiltinOperator_CUSTOM, custom_code.c_str()));
622   return ind;
623 }
624
625 flatbuffers::Offset<circle::Buffer> CircleGen::buildBuffer(const uint8_t *buf, size_t size)
626 {
627   if (buf == nullptr || size == 0)
628     return circle::CreateBuffer(_fbb);
629   auto buffer = _fbb.CreateVector(buf, size);
630   return circle::CreateBuffer(_fbb, buffer);
631 }
632
633 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params)
634 {
635   auto shape = _fbb.CreateVector(params.shape);
636   auto name = _fbb.CreateString(params.name);
637   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
638                               0 /* QuantParam */, false /* is_variable */, 0 /* sparsity */,
639                               0 /* shape_signature */);
640 }
641
642 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params, float scale,
643                                                            int64_t zero_point)
644 {
645   auto shape = _fbb.CreateVector(params.shape);
646   auto name = _fbb.CreateString(params.name);
647   std::vector<float> scale_vector = {scale};
648   std::vector<int64_t> zero_point_vector = {zero_point};
649   auto quantization = circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr,
650                                                                  &scale_vector, &zero_point_vector);
651   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
652                               false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
653 }
654
655 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
656                                                            std::vector<float> &scales,
657                                                            std::vector<int64_t> &zero_points)
658 {
659   auto shape = _fbb.CreateVector(params.shape);
660   auto name = _fbb.CreateString(params.name);
661   auto quantization =
662     circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr, &scales, &zero_points);
663   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
664                               false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
665 }
666
667 flatbuffers::Offset<circle::SparsityParameters>
668 CircleGen::buildSparsityParameters(const SparsityParams &sp)
669 {
670   flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order;
671   flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map;
672   flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
673     dim_metadata;
674
675   traversal_order = _fbb.CreateVector(sp.traversal_order);
676   block_map = _fbb.CreateVector(sp.block_map);
677
678   std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
679   for (auto &it : sp.dim_metadata)
680   {
681     auto fb_array_segments = circle::CreateUint16VectorDirect(_fbb, &it._array_segments.u16);
682     auto fb_array_indices = circle::CreateUint16VectorDirect(_fbb, &it._array_indices.u16);
683     auto dim_metadata = circle::CreateDimensionMetadata(
684       _fbb, it._format, it._dense_size, it._array_segments_type, fb_array_segments.Union(),
685       it._array_indices_type, fb_array_indices.Union());
686     dim_metadata_vec.emplace_back(dim_metadata);
687   }
688   dim_metadata = _fbb.CreateVector(dim_metadata_vec);
689
690   return circle::CreateSparsityParameters(_fbb, traversal_order, block_map, dim_metadata);
691 }
692
693 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
694                                                            const SparsityParams &sp)
695 {
696   auto shape = _fbb.CreateVector(params.shape);
697   auto name = _fbb.CreateString(params.name);
698   auto sparsity = buildSparsityParameters(sp);
699   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
700                               0 /* QuantParam */, false /* is_variable */, sparsity,
701                               0 /* shape_signature */);
702 }
703
704 flatbuffers::Offset<circle::SubGraph> CircleGen::buildSubGraph(const SubgraphContext &ctx)
705 {
706   return circle::CreateSubGraphDirect(_fbb, &ctx.tensors, &ctx.inputs, &ctx.outputs, &ctx.operators,
707                                       nullptr);
708 }