Imported Upstream version 1.18.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::addOperatorL2Normalization(const OperatorParams &params)
273 {
274   auto options = circle::CreateL2NormOptions(_fbb).Union();
275   return addOperatorWithOptions(params, circle::BuiltinOperator_L2_NORMALIZATION,
276                                 circle::BuiltinOptions_L2NormOptions, options);
277 }
278
279 uint32_t CircleGen::addOperatorLess(const OperatorParams &params)
280 {
281   auto options = circle::CreateLessOptions(_fbb).Union();
282   return addOperatorWithOptions(params, circle::BuiltinOperator_LESS,
283                                 circle::BuiltinOptions_LessOptions, options);
284 }
285
286 uint32_t CircleGen::addOperatorLeakyRelu(const OperatorParams &params, float alpha)
287 {
288   auto options = circle::CreateLeakyReluOptions(_fbb, alpha).Union();
289   return addOperatorWithOptions(params, circle::BuiltinOperator_LEAKY_RELU,
290                                 circle::BuiltinOptions_LeakyReluOptions, options);
291 }
292
293 uint32_t CircleGen::addOperatorLogSoftmax(const OperatorParams &params)
294 {
295   auto options = circle::CreateLogSoftmaxOptions(_fbb).Union();
296   return addOperatorWithOptions(params, circle::BuiltinOperator_LOG_SOFTMAX,
297                                 circle::BuiltinOptions_LogSoftmaxOptions, options);
298 }
299
300 uint32_t CircleGen::addOperatorMean(const OperatorParams &params, bool keep_dims)
301 {
302   auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
303   return addOperatorWithOptions(params, circle::BuiltinOperator_MEAN,
304                                 circle::BuiltinOptions_ReducerOptions, options);
305 }
306
307 uint32_t CircleGen::addOperatorMul(const OperatorParams &params,
308                                    circle::ActivationFunctionType actfn)
309 {
310   auto options = circle::CreateMulOptions(_fbb, actfn).Union();
311   return addOperatorWithOptions(params, circle::BuiltinOperator_MUL,
312                                 circle::BuiltinOptions_MulOptions, options);
313 }
314
315 uint32_t CircleGen::addOperatorNeg(const OperatorParams &params)
316 {
317   auto options = circle::CreatePadOptions(_fbb).Union();
318   return addOperatorWithOptions(params, circle::BuiltinOperator_NEG,
319                                 circle::BuiltinOptions_NegOptions, options);
320 }
321
322 uint32_t CircleGen::addOperatorOneHot(const OperatorParams &params, int32_t axis)
323 {
324   auto options = circle::CreateOneHotOptions(_fbb, axis).Union();
325   return addOperatorWithOptions(params, circle::BuiltinOperator_ONE_HOT,
326                                 circle::BuiltinOptions_OneHotOptions, options);
327 }
328
329 uint32_t CircleGen::addOperatorPad(const OperatorParams &params)
330 {
331   auto options = circle::CreatePadOptions(_fbb).Union();
332   return addOperatorWithOptions(params, circle::BuiltinOperator_PAD,
333                                 circle::BuiltinOptions_PadOptions, options);
334 }
335
336 uint32_t CircleGen::addOperatorPadV2(const OperatorParams &params)
337 {
338   auto options = circle::CreatePadOptions(_fbb).Union();
339   return addOperatorWithOptions(params, circle::BuiltinOperator_PADV2,
340                                 circle::BuiltinOptions_PadV2Options, options);
341 }
342
343 uint32_t CircleGen::addOperatorQuantize(const OperatorParams &params)
344 {
345   auto options = circle::CreateQuantizeOptions(_fbb).Union();
346   return addOperatorWithOptions(params, circle::BuiltinOperator_QUANTIZE,
347                                 circle::BuiltinOptions_QuantizeOptions, options);
348 }
349
350 uint32_t CircleGen::addOperatorRank(const OperatorParams &params)
351 {
352   auto options = circle::CreateRankOptions(_fbb).Union();
353   return addOperatorWithOptions(params, circle::BuiltinOperator_RANK,
354                                 circle::BuiltinOptions_RankOptions, options);
355 }
356
357 uint32_t CircleGen::addOperatorReduce(const OperatorParams &params,
358                                       circle::BuiltinOperator reduce_op, bool keep_dims)
359 {
360   switch (reduce_op)
361   {
362     case circle::BuiltinOperator_REDUCE_ANY:
363     case circle::BuiltinOperator_REDUCE_MIN:
364     case circle::BuiltinOperator_REDUCE_MAX:
365     case circle::BuiltinOperator_REDUCE_PROD:
366       break;
367     default:
368       throw std::runtime_error{"Wrong reduce op"};
369   }
370   auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
371   return addOperatorWithOptions(params, reduce_op, circle::BuiltinOptions_ReducerOptions, options);
372 }
373
374 uint32_t CircleGen::addOperatorRelu(const OperatorParams &params)
375 {
376   return addOperatorWithOptions(params, circle::BuiltinOperator_RELU, circle::BuiltinOptions_NONE,
377                                 0);
378 }
379
380 uint32_t CircleGen::addOperatorRelu6(const OperatorParams &params)
381 {
382   return addOperatorWithOptions(params, circle::BuiltinOperator_RELU6, circle::BuiltinOptions_NONE,
383                                 0);
384 }
385
386 uint32_t CircleGen::addOperatorReshape(const OperatorParams &params, const Shape *new_shape)
387 {
388   auto options = circle::CreateReshapeOptionsDirect(_fbb, new_shape).Union();
389   return addOperatorWithOptions(params, circle::BuiltinOperator_RESHAPE,
390                                 circle::BuiltinOptions_ReshapeOptions, options);
391 }
392
393 uint32_t CircleGen::addOperatorResizeBilinear(const OperatorParams &params, bool align_corners,
394                                               bool half_pixel_centers)
395 {
396   auto options =
397     circle::CreateResizeBilinearOptions(_fbb, align_corners, half_pixel_centers).Union();
398   return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_BILINEAR,
399                                 circle::BuiltinOptions_ResizeBilinearOptions, options);
400 }
401
402 uint32_t CircleGen::addOperatorResizeNearestNeighbor(const OperatorParams &params)
403 {
404   auto options = circle::CreateResizeNearestNeighborOptions(_fbb).Union();
405   return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
406                                 circle::BuiltinOptions_ResizeNearestNeighborOptions, options);
407 }
408
409 uint32_t CircleGen::addOperatorReverseV2(const OperatorParams &params)
410 {
411   auto options = circle::CreateReverseV2Options(_fbb).Union();
412   return addOperatorWithOptions(params, circle::BuiltinOperator_REVERSE_V2,
413                                 circle::BuiltinOptions_ReverseV2Options, options);
414 }
415
416 uint32_t CircleGen::addOperatorShape(const OperatorParams &params, circle::TensorType type)
417 {
418   auto options = circle::CreateShapeOptions(_fbb, type).Union();
419   return addOperatorWithOptions(params, circle::BuiltinOperator_SHAPE,
420                                 circle::BuiltinOptions_RankOptions, options);
421 }
422
423 uint32_t CircleGen::addOperatorSelect(const OperatorParams &params)
424 {
425   auto options = circle::CreateSelectOptions(_fbb).Union();
426   return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT,
427                                 circle::BuiltinOptions_SelectOptions, options);
428 }
429
430 uint32_t CircleGen::addOperatorSelectV2(const OperatorParams &params)
431 {
432   auto options = circle::CreateSelectV2Options(_fbb).Union();
433   return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT_V2,
434                                 circle::BuiltinOptions_SelectV2Options, options);
435 }
436
437 uint32_t CircleGen::addOperatorSlice(const OperatorParams &params)
438 {
439   auto options = circle::CreateSliceOptions(_fbb).Union();
440   return addOperatorWithOptions(params, circle::BuiltinOperator_SLICE,
441                                 circle::BuiltinOptions_SliceOptions, options);
442 }
443
444 uint32_t CircleGen::addOperatorSoftmax(const OperatorParams &params, float beta)
445 {
446   auto options = circle::CreateSoftmaxOptions(_fbb, beta).Union();
447   return addOperatorWithOptions(params, circle::BuiltinOperator_SOFTMAX,
448                                 circle::BuiltinOptions_SoftmaxOptions, options);
449 }
450
451 uint32_t CircleGen::addOperatorSplit(const OperatorParams &params, int32_t num_split)
452 {
453   auto options = circle::CreateSplitOptions(_fbb, num_split).Union();
454   return addOperatorWithOptions(params, circle::BuiltinOperator_SPLIT,
455                                 circle::BuiltinOptions_SplitOptions, options);
456 }
457
458 uint32_t CircleGen::addOperatorStridedSlice(const OperatorParams &params, int32_t begin_mask,
459                                             int32_t end_mask, int32_t ellipsis_mask,
460                                             int32_t new_axis_mask, int32_t shrink_axis_mask)
461 {
462   auto options = circle::CreateStridedSliceOptions(_fbb, begin_mask, end_mask, ellipsis_mask,
463                                                    new_axis_mask, shrink_axis_mask)
464                    .Union();
465   return addOperatorWithOptions(params, circle::BuiltinOperator_STRIDED_SLICE,
466                                 circle::BuiltinOptions_StridedSliceOptions, options);
467 }
468
469 uint32_t CircleGen::addOperatorSub(const OperatorParams &params,
470                                    circle::ActivationFunctionType actfn)
471 {
472   auto options = circle::CreateSubOptions(_fbb, actfn).Union();
473   return addOperatorWithOptions(params, circle::BuiltinOperator_SUB,
474                                 circle::BuiltinOptions_SubOptions, options);
475 }
476
477 uint32_t CircleGen::addOperatorTile(const OperatorParams &params)
478 {
479   auto options = circle::CreateTileOptions(_fbb).Union();
480   return addOperatorWithOptions(params, circle::BuiltinOperator_TILE,
481                                 circle::BuiltinOptions_TileOptions, options);
482 }
483
484 uint32_t CircleGen::addOperatorWhile(const OperatorParams &params, uint32_t cond_subg,
485                                      uint32_t body_subg)
486 {
487   auto options = circle::CreateWhileOptions(_fbb, cond_subg, body_subg).Union();
488   return addOperatorWithOptions(params, circle::BuiltinOperator_WHILE,
489                                 circle::BuiltinOptions_WhileOptions, options);
490 }
491
492 uint32_t CircleGen::addOperatorIf(const OperatorParams &params, uint32_t then_subg,
493                                   uint32_t else_subg)
494 {
495   auto options = circle::CreateIfOptions(_fbb, then_subg, else_subg).Union();
496   return addOperatorWithOptions(params, circle::BuiltinOperator_IF,
497                                 circle::BuiltinOptions_IfOptions, options);
498 }
499
500 uint32_t CircleGen::addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
501                                             circle::ActivationFunctionType actfn)
502 {
503   auto options = circle::CreateInstanceNormOptions(_fbb, epsilon, actfn).Union();
504   return addOperatorWithOptions(params, circle::BuiltinOperator_INSTANCE_NORM,
505                                 circle::BuiltinOptions_InstanceNormOptions, options);
506 }
507
508 uint32_t CircleGen::addOperatorTranspose(const OperatorParams &params)
509 {
510   auto options = circle::CreateTransposeOptions(_fbb).Union();
511   return addOperatorWithOptions(params, circle::BuiltinOperator_TRANSPOSE,
512                                 circle::BuiltinOptions_TransposeOptions, options);
513 }
514
515 uint32_t CircleGen::addOperatorSqrt(const OperatorParams &params)
516 {
517   return addOperatorWithOptions(params, circle::BuiltinOperator_SQRT, circle::BuiltinOptions_NONE,
518                                 0);
519 }
520
521 uint32_t CircleGen::addOperatorSquare(const OperatorParams &params)
522 {
523   auto options = circle::CreateSquareOptions(_fbb).Union();
524   return addOperatorWithOptions(params, circle::BuiltinOperator_SQUARE,
525                                 circle::BuiltinOptions_SquareOptions, options);
526 }
527
528 // NOTE Please add addOperator functions ABOVE this lie
529 //
530 // %  How to add a new addOperatorXXX fuction
531 // 0. Copy code from one of the existing addOperatorXXX function
532 // 1. Change the function signature (need BuiltinOperator params)
533 // 2. Change enum BuiltinOperator
534 // 3. Change enum BuiltinOptions
535 // 4. Change CreateXXXOptions accordingly
536 //
537 // If operator don't have option table, remove CreateXXXOptions call,
538 // call addOperatorWithOptions with options_type = circle::BuiltinOptions_NONE and options = 0
539
540 // ===== Add Operator methods end =====
541
542 uint32_t CircleGen::addOperatorWithOptions(const OperatorParams &params,
543                                            circle::BuiltinOperator opcode,
544                                            circle::BuiltinOptions options_type,
545                                            flatbuffers::Offset<void> options)
546 {
547   uint32_t opcode_ind = addOperatorCode(opcode);
548   auto op = circle::CreateOperatorDirect(_fbb, opcode_ind, &params.inputs, &params.outputs,
549                                          options_type, options);
550
551   uint32_t ind = curSubgCtx().operators.size();
552   curSubgCtx().operators.emplace_back(op);
553   return ind;
554 }
555
556 uint32_t CircleGen::addCustomOperatorWithOptions(
557   const OperatorParams &params, std::string custom_code, circle::BuiltinOptions options_type,
558   flatbuffers::Offset<void> options, const std::vector<uint8_t> *custom_options,
559   circle::CustomOptionsFormat custom_options_format,
560   const std::vector<uint8_t> *mutating_variable_inputs, const std::vector<int32_t> *intermediates)
561
562 {
563   uint32_t opcode_ind = addCustomOperatorCode(custom_code);
564   auto op = circle::CreateOperatorDirect(
565     _fbb, opcode_ind, &params.inputs, &params.outputs, options_type, options, custom_options,
566     custom_options_format, mutating_variable_inputs, intermediates);
567
568   uint32_t ind = curSubgCtx().operators.size();
569   curSubgCtx().operators.emplace_back(op);
570   return ind;
571 }
572
573 uint32_t CircleGen::addOperatorCode(circle::BuiltinOperator opcode)
574 {
575   // TODO If the same OperatorCode is registered already, just return it
576   uint32_t ind = _opcodes.size();
577   _opcodes.emplace_back(circle::CreateOperatorCode(_fbb, opcode));
578   return ind;
579 }
580
581 uint32_t CircleGen::addCustomOperatorCode(std::string custom_code)
582 {
583   // TODO If the same OperatorCode is registered already, just return it
584   uint32_t ind = _opcodes.size();
585   _opcodes.emplace_back(
586     circle::CreateOperatorCodeDirect(_fbb, circle::BuiltinOperator_CUSTOM, custom_code.c_str()));
587   return ind;
588 }
589
590 flatbuffers::Offset<circle::Buffer> CircleGen::buildBuffer(const uint8_t *buf, size_t size)
591 {
592   if (buf == nullptr && size == 0)
593     return circle::CreateBuffer(_fbb);
594   auto buffer = _fbb.CreateVector(buf, size);
595   return circle::CreateBuffer(_fbb, buffer);
596 }
597
598 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params)
599 {
600   auto shape = _fbb.CreateVector(params.shape);
601   auto name = _fbb.CreateString(params.name);
602   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
603                               0 /* QuantParam */, false /* is_variable */, 0 /* sparsity */,
604                               0 /* shape_signature */);
605 }
606
607 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params, float scale,
608                                                            int64_t zero_point)
609 {
610   auto shape = _fbb.CreateVector(params.shape);
611   auto name = _fbb.CreateString(params.name);
612   std::vector<float> scale_vector = {scale};
613   std::vector<int64_t> zero_point_vector = {zero_point};
614   auto quantization = circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr,
615                                                                  &scale_vector, &zero_point_vector);
616   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
617                               false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
618 }
619
620 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
621                                                            std::vector<float> &scales,
622                                                            std::vector<int64_t> &zero_points)
623 {
624   auto shape = _fbb.CreateVector(params.shape);
625   auto name = _fbb.CreateString(params.name);
626   auto quantization =
627     circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr, &scales, &zero_points);
628   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
629                               false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
630 }
631
632 flatbuffers::Offset<circle::SparsityParameters>
633 CircleGen::buildSparsityParameters(const SparsityParams &sp)
634 {
635   flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order;
636   flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map;
637   flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
638     dim_metadata;
639
640   traversal_order = _fbb.CreateVector(sp.traversal_order);
641   block_map = _fbb.CreateVector(sp.block_map);
642
643   std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
644   for (auto &it : sp.dim_metadata)
645   {
646     auto fb_array_segments = circle::CreateUint16VectorDirect(_fbb, &it._array_segments.u16);
647     auto fb_array_indices = circle::CreateUint16VectorDirect(_fbb, &it._array_indices.u16);
648     auto dim_metadata = circle::CreateDimensionMetadata(
649       _fbb, it._format, it._dense_size, it._array_segments_type, fb_array_segments.Union(),
650       it._array_indices_type, fb_array_indices.Union());
651     dim_metadata_vec.emplace_back(dim_metadata);
652   }
653   dim_metadata = _fbb.CreateVector(dim_metadata_vec);
654
655   return circle::CreateSparsityParameters(_fbb, traversal_order, block_map, dim_metadata);
656 }
657
658 flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
659                                                            const SparsityParams &sp)
660 {
661   auto shape = _fbb.CreateVector(params.shape);
662   auto name = _fbb.CreateString(params.name);
663   auto sparsity = buildSparsityParameters(sp);
664   return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
665                               0 /* QuantParam */, false /* is_variable */, sparsity,
666                               0 /* shape_signature */);
667 }
668
669 flatbuffers::Offset<circle::SubGraph> CircleGen::buildSubGraph(const SubgraphContext &ctx)
670 {
671   return circle::CreateSubGraphDirect(_fbb, &ctx.tensors, &ctx.inputs, &ctx.outputs, &ctx.operators,
672                                       nullptr);
673 }