Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / compiler / luci / logex / src / CircleNodeSummaryBuilders.cpp
1 /*
2  * Copyright (c) 2022 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 "CircleNodeSummaryBuilders.h"
18
19 #include <luci/IR/CircleNode.h>
20 #include <luci/IR/CircleNodes.h>
21 #include <loco/IR/Node.h>
22
23 #include <string>
24 #include <vector>
25
26 namespace
27 {
28
29 std::string to_str(loco::DataType type)
30 {
31   switch (type)
32   {
33     case loco::DataType::U8:
34       return "UINT8";
35     case loco::DataType::U16:
36       return "UINT16";
37     case loco::DataType::U32:
38       return "UINT32";
39     case loco::DataType::U64:
40       return "UINT64";
41
42     case loco::DataType::S8:
43       return "INT8";
44     case loco::DataType::S16:
45       return "INT16";
46     case loco::DataType::S32:
47       return "INT32";
48     case loco::DataType::S64:
49       return "INT64";
50
51     case loco::DataType::FLOAT16:
52       return "FLOAT16";
53     case loco::DataType::FLOAT32:
54       return "FLOAT32";
55     case loco::DataType::FLOAT64:
56       return "FLOAT64";
57
58     case loco::DataType::BOOL:
59       return "BOOL";
60
61     default:
62       return "Error";
63   }
64 }
65
66 std::string to_str(float value) { return std::to_string(value); }
67
68 std::string to_str(int32_t value) { return std::to_string(value); }
69
70 std::string to_str(bool value) { return value ? "true" : "false"; }
71
72 std::string to_str(luci::FusedActFunc fused)
73 {
74   switch (fused)
75   {
76     case luci::FusedActFunc::NONE:
77       return "NONE";
78     case luci::FusedActFunc::RELU:
79       return "RELU";
80     case luci::FusedActFunc::RELU_N1_TO_1:
81       return "RELU_N1_TO_1";
82     case luci::FusedActFunc::RELU6:
83       return "RELU6";
84     case luci::FusedActFunc::TANH:
85       return "TANH";
86     case luci::FusedActFunc::SIGN_BIT:
87       return "SIGN_BIT";
88     default:
89       return "Error";
90   }
91 }
92
93 std::string to_str(luci::Padding padding)
94 {
95   switch (padding)
96   {
97     case luci::Padding::SAME:
98       return "SAME";
99     case luci::Padding::VALID:
100       return "VALID";
101     default:
102       return "Error";
103   }
104 }
105
106 std::string to_str(const luci::Stride *stride)
107 {
108   return std::to_string(stride->h()) + "," + std::to_string(stride->w());
109 }
110
111 std::string to_str(const luci::Filter *filter)
112 {
113   return std::to_string(filter->h()) + "," + std::to_string(filter->w());
114 }
115
116 std::string to_str(luci::MirrorPadMode mode)
117 {
118   switch (mode)
119   {
120     case luci::MirrorPadMode::REFLECT:
121       return "REFLECT";
122     case luci::MirrorPadMode::SYMMETRIC:
123       return "SYMMETRIC";
124     default:
125       return "Error";
126   }
127 }
128
129 } // namespace
130
131 namespace luci
132 {
133
134 std::vector<std::string> CircleNodeWithXSummaryBuilder::get_input_names(const luci::CircleNode *)
135 {
136   return {"x"};
137 }
138
139 std::vector<std::string>
140 CircleNodeWithINPUTSummaryBuilder::get_input_names(const luci::CircleNode *)
141 {
142   return {"input"};
143 }
144
145 std::vector<std::string> CircleNodeWithXYSummaryBuilder::get_input_names(const luci::CircleNode *)
146 {
147   return {"x", "y"};
148 }
149
150 std::vector<std::string>
151 CircleNodeWithFEATURESSummaryBuilder::get_input_names(const luci::CircleNode *)
152 {
153   return {"features"};
154 }
155
156 } // namespace luci
157
158 namespace luci
159 {
160
161 bool CircleAddSummaryBuilder::validate(const luci::CircleNode *node)
162 {
163   auto add = loco::must_cast<const luci::CircleAdd *>(node);
164   if (add->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
165     return false;
166
167   return true;
168 }
169
170 void CircleAddSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
171 {
172   auto add = loco::must_cast<const luci::CircleAdd *>(node);
173   s.args().append("fused_activation_function", to_str(add->fusedActivationFunction()));
174 }
175
176 std::vector<std::string> CircleAddNSummaryBuilder::get_input_names(const luci::CircleNode *node)
177 {
178   return std::vector<std::string>(node->arity(), "inputs");
179 }
180
181 std::vector<std::string> CircleArgMaxSummaryBuilder::get_input_names(const luci::CircleNode *)
182 {
183   return {"input", "dimension"};
184 }
185
186 void CircleArgMaxSummaryBuilder::build_attributes(const luci::CircleNode *node,
187                                                   locop::NodeSummary &s)
188 {
189   auto argmax = loco::must_cast<const luci::CircleArgMax *>(node);
190   s.args().append("output_type", to_str(argmax->output_type()));
191 }
192
193 std::vector<std::string> CircleArgMinSummaryBuilder::get_input_names(const luci::CircleNode *)
194 {
195   return {"input", "dimension"};
196 }
197
198 void CircleArgMinSummaryBuilder::build_attributes(const luci::CircleNode *node,
199                                                   locop::NodeSummary &s)
200 {
201   auto argmin = loco::must_cast<const luci::CircleArgMin *>(node);
202   s.args().append("output_type", to_str(argmin->output_type()));
203 }
204
205 bool CircleAveragePool2DSummaryBuilder::validate(const luci::CircleNode *node)
206 {
207   auto avgpool = loco::must_cast<const luci::CircleAveragePool2D *>(node);
208   if (avgpool->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
209     return false;
210   if (avgpool->padding() == luci::Padding::UNDEFINED)
211     return false;
212
213   return true;
214 }
215
216 std::vector<std::string>
217 CircleAveragePool2DSummaryBuilder::get_input_names(const luci::CircleNode *)
218 {
219   return {"value"};
220 }
221
222 void CircleAveragePool2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
223                                                          locop::NodeSummary &s)
224 {
225   auto avgpool = loco::must_cast<const luci::CircleAveragePool2D *>(node);
226   s.args().append("filter(h,w)", to_str(avgpool->filter()));
227   s.args().append("stride(h,w)", to_str(avgpool->stride()));
228   s.args().append("padding", to_str(avgpool->padding()));
229   s.args().append("fused_activation_function", to_str(avgpool->fusedActivationFunction()));
230 }
231
232 void CircleBatchMatMulSummaryBuilder::build_attributes(const luci::CircleNode *node,
233                                                        locop::NodeSummary &s)
234 {
235   auto batchmatmul = loco::must_cast<const luci::CircleBatchMatMul *>(node);
236   s.args().append("adj_x", to_str(batchmatmul->adj_x()));
237   s.args().append("adj_y", to_str(batchmatmul->adj_y()));
238 }
239
240 std::vector<std::string>
241 CircleBatchToSpaceNDSummaryBuilder::get_input_names(const luci::CircleNode *)
242 {
243   return {"input", "block_shape", "crops"};
244 }
245
246 bool CircleBCQFullyConnectedSummaryBuilder::validate(const luci::CircleNode *node)
247 {
248   auto bcq_fc = loco::must_cast<const luci::CircleBCQFullyConnected *>(node);
249   if (bcq_fc->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
250     return false;
251
252   return true;
253 }
254
255 std::vector<std::string>
256 CircleBCQFullyConnectedSummaryBuilder::get_input_names(const luci::CircleNode *)
257 {
258   return {"input", "weights_scales", "weights_binary", "bias", "weights_clusters"};
259 }
260
261 void CircleBCQFullyConnectedSummaryBuilder::build_attributes(const luci::CircleNode *node,
262                                                              locop::NodeSummary &s)
263 {
264   auto bcq_fc = loco::must_cast<const luci::CircleBCQFullyConnected *>(node);
265   s.args().append("fused_activation_function", to_str(bcq_fc->fusedActivationFunction()));
266   s.args().append("weights_hidden_size", std::to_string(bcq_fc->weights_hidden_size()));
267 }
268
269 std::vector<std::string> CircleBCQGatherSummaryBuilder::get_input_names(const luci::CircleNode *)
270 {
271   return {"input_scales", "input_binary", "indices", "input_clusters"};
272 }
273
274 void CircleBCQGatherSummaryBuilder::build_attributes(const luci::CircleNode *node,
275                                                      locop::NodeSummary &s)
276 {
277   auto bcq_gather = loco::must_cast<const luci::CircleBCQGather *>(node);
278   s.args().append("axis", std::to_string(bcq_gather->axis()));
279   s.args().append("input_hidden_size", std::to_string(bcq_gather->input_hidden_size()));
280 }
281
282 std::vector<std::string>
283 CircleBidirectionalSequenceLSTMSummaryBuilder::get_input_names(const luci::CircleNode *)
284 {
285   return {"input",
286           "fw_input_to_input_weights",
287           "fw_input_to_forget_weights",
288           "fw_input_to_cell_weights",
289           "fw_input_to_output_weights",
290           "fw_recurrent_to_input_weights",
291           "fw_recurrent_to_forget_weights",
292           "fw_recurrent_to_cell_weights",
293           "fw_recurrent_to_output_weights",
294           "fw_cell_to_input_weights",
295           "fw_cell_to_forget_weights",
296           "fw_cell_to_output_weights",
297           "fw_input_gate_bias",
298           "fw_forget_gate_bias",
299           "fw_cell_gate_bias",
300           "fw_output_gate_bias",
301           "fw_projection_weights",
302           "fw_projection_bias",
303           "bw_input_to_input_weights",
304           "bw_input_to_forget_weights",
305           "bw_input_to_cell_weights",
306           "bw_input_to_output_weights",
307           "bw_recurrent_to_input_weights",
308           "bw_recurrent_to_forget_weights",
309           "bw_recurrent_to_cell_weights",
310           "bw_recurrent_to_output_weights",
311           "bw_cell_to_input_weights",
312           "bw_cell_to_forget_weights",
313           "bw_cell_to_output_weights",
314           "bw_input_gate_bias",
315           "bw_forget_gate_bias",
316           "bw_cell_gate_bias",
317           "bw_output_gate_bias",
318           "bw_projection_weights",
319           "bw_projection_bias",
320           "fw_activation_state",
321           "fw_cell_state",
322           "bw_activation_state",
323           "bw_cell_state",
324           "auxillary_input",
325           "fw_auxillary_input_to_input_weights",
326           "fw_auxillary_input_to_forget_weights",
327           "fw_auxillary_input_to_cell_weights",
328           "fw_auxillary_input_to_output_weights",
329           "bw_auxillary_input_to_input_weights",
330           "bw_auxillary_input_to_forget_weights",
331           "bw_auxillary_input_to_cell_weights",
332           "bw_auxillary_input_to_output_weights"};
333 }
334
335 void CircleBidirectionalSequenceLSTMSummaryBuilder::build_attributes(const luci::CircleNode *node,
336                                                                      locop::NodeSummary &s)
337 {
338   auto lstm = loco::must_cast<const luci::CircleBidirectionalSequenceLSTM *>(node);
339   s.args().append("cell_clip", to_str(lstm->cell_clip()));
340   s.args().append("proj_clip", to_str(lstm->proj_clip()));
341   s.args().append("merge_outputs", to_str(lstm->merge_outputs()));
342   s.args().append("time_major", to_str(lstm->time_major()));
343   s.args().append("asymmetric_quantize_inputs", to_str(lstm->asymmetric_quantize_inputs()));
344 }
345
346 std::vector<std::string> CircleCastSummaryBuilder::get_input_names(const luci::CircleNode *)
347 {
348   return {"x"};
349 }
350
351 void CircleCastSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
352 {
353   auto cast = loco::must_cast<const luci::CircleCast *>(node);
354   s.args().append("in_data_type", to_str(cast->in_data_type()));
355   s.args().append("out_data_type", to_str(cast->out_data_type()));
356 }
357
358 bool CircleConcatenationSummaryBuilder::validate(const luci::CircleNode *node)
359 {
360   auto concat = loco::must_cast<const luci::CircleConcatenation *>(node);
361   if (concat->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
362     return false;
363
364   return true;
365 }
366
367 std::vector<std::string>
368 CircleConcatenationSummaryBuilder::get_input_names(const luci::CircleNode *node)
369 {
370   return std::vector<std::string>(node->arity(), "values");
371 }
372
373 void CircleConcatenationSummaryBuilder::build_attributes(const luci::CircleNode *node,
374                                                          locop::NodeSummary &s)
375 {
376   auto concat = loco::must_cast<const luci::CircleConcatenation *>(node);
377   s.args().append("axis", std::to_string(concat->axis()));
378   s.args().append("fused_activation_function", to_str(concat->fusedActivationFunction()));
379 }
380
381 void CircleConstSummaryBuilder::build_attributes(const luci::CircleNode *node,
382                                                  locop::NodeSummary &s)
383 {
384   auto circonst = loco::must_cast<const luci::CircleConst *>(node);
385   s.args().append("dtype", to_str(circonst->dtype()));
386   s.args().append("rank", std::to_string(circonst->rank()));
387   std::string shape;
388   for (uint32_t r = 0; r < circonst->rank(); ++r)
389   {
390     if (!shape.empty())
391       shape += " ";
392     shape += std::to_string(circonst->dim(r).value());
393   }
394   s.args().append("shape", "[" + shape + "]");
395 }
396
397 void CircleConstSummaryBuilder::update_status(locop::NodeSummary &s)
398 {
399   s.state(locop::NodeDesc::State::PartiallyKnown);
400 }
401
402 bool CircleConv2DSummaryBuilder::validate(const luci::CircleNode *node)
403 {
404   auto conv2d = loco::must_cast<const luci::CircleConv2D *>(node);
405   if (conv2d->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
406     return false;
407   if (conv2d->padding() == luci::Padding::UNDEFINED)
408     return false;
409
410   return true;
411 }
412
413 std::vector<std::string> CircleConv2DSummaryBuilder::get_input_names(const luci::CircleNode *)
414 {
415   return {"input", "filter", "bias"};
416 }
417
418 void CircleConv2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
419                                                   locop::NodeSummary &s)
420 {
421   auto conv2d = loco::must_cast<const luci::CircleConv2D *>(node);
422   s.args().append("stride(h,w)", to_str(conv2d->stride()));
423   s.args().append("dilation(h,w)", to_str(conv2d->dilation()));
424   s.args().append("padding", to_str(conv2d->padding()));
425   s.args().append("fused_activation_function", to_str(conv2d->fusedActivationFunction()));
426 }
427
428 std::vector<std::string> CircleCustomSummaryBuilder::get_input_names(const luci::CircleNode *node)
429 {
430   auto input_names = std::vector<std::string>();
431   for (uint32_t i = 0; i < node->arity(); ++i)
432     input_names.push_back("input" + std::to_string(i));
433   return input_names;
434 }
435
436 void CircleCustomSummaryBuilder::build_attributes(const luci::CircleNode *node,
437                                                   locop::NodeSummary &s)
438 {
439   auto custom = loco::must_cast<const luci::CircleCustom *>(node);
440   s.args().append("custom_code", custom->custom_code());
441 }
442
443 void CircleDepthToSpaceSummaryBuilder::build_attributes(const luci::CircleNode *node,
444                                                         locop::NodeSummary &s)
445 {
446   auto depth_to_space = loco::must_cast<const luci::CircleDepthToSpace *>(node);
447   s.args().append("block_size", std::to_string(depth_to_space->block_size()));
448 }
449
450 bool CircleDepthwiseConv2DSummaryBuilder::validate(const luci::CircleNode *node)
451 {
452   auto dw_conv2d = loco::must_cast<const luci::CircleDepthwiseConv2D *>(node);
453   if (dw_conv2d->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
454     return false;
455   if (dw_conv2d->padding() == luci::Padding::UNDEFINED)
456     return false;
457
458   return true;
459 }
460
461 std::vector<std::string>
462 CircleDepthwiseConv2DSummaryBuilder::get_input_names(const luci::CircleNode *)
463 {
464   return {"input", "filter", "bias"};
465 }
466
467 void CircleDepthwiseConv2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
468                                                            locop::NodeSummary &s)
469 {
470   auto dw_conv2d = loco::must_cast<const luci::CircleDepthwiseConv2D *>(node);
471   s.args().append("stride(h,w)", to_str(dw_conv2d->stride()));
472   s.args().append("dilation(h,w)", to_str(dw_conv2d->dilation()));
473   s.args().append("padding", to_str(dw_conv2d->padding()));
474   s.args().append("depthMultiplier", std::to_string(dw_conv2d->depthMultiplier()));
475   s.args().append("fused_activation_function", to_str(dw_conv2d->fusedActivationFunction()));
476 }
477
478 std::vector<std::string> CircleExpandDimsSummaryBuilder::get_input_names(const luci::CircleNode *)
479 {
480   return {"input", "axis"};
481 }
482
483 std::vector<std::string> CircleFakeQuantSummaryBuilder::get_input_names(const luci::CircleNode *)
484 {
485   return {"inputs"};
486 }
487
488 void CircleFakeQuantSummaryBuilder::build_attributes(const luci::CircleNode *node,
489                                                      locop::NodeSummary &s)
490 {
491   auto fake_quant = loco::must_cast<const luci::CircleFakeQuant *>(node);
492   s.args().append("min", std::to_string(fake_quant->min()));
493   s.args().append("max", std::to_string(fake_quant->max()));
494   s.args().append("num_bits", std::to_string(fake_quant->num_bits()));
495   s.args().append("narrow_range", to_str(fake_quant->narrow_range()));
496 }
497
498 std::vector<std::string> CircleFillSummaryBuilder::get_input_names(const luci::CircleNode *)
499 {
500   return {"dims", "value"};
501 }
502
503 bool CircleFullyConnectedSummaryBuilder::validate(const luci::CircleNode *node)
504 {
505   auto fc = loco::must_cast<const luci::CircleFullyConnected *>(node);
506   if (fc->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
507     return false;
508
509   return true;
510 }
511
512 std::vector<std::string>
513 CircleFullyConnectedSummaryBuilder::get_input_names(const luci::CircleNode *)
514 {
515   return {"input", "weights", "bias"};
516 }
517
518 void CircleFullyConnectedSummaryBuilder::build_attributes(const luci::CircleNode *node,
519                                                           locop::NodeSummary &s)
520 {
521   auto fc = loco::must_cast<const luci::CircleFullyConnected *>(node);
522   s.args().append("fused_activation_function", to_str(fc->fusedActivationFunction()));
523 }
524
525 std::vector<std::string> CircleGatherSummaryBuilder::get_input_names(const luci::CircleNode *)
526 {
527   return {"params", "indices"};
528 }
529
530 void CircleGatherSummaryBuilder::build_attributes(const luci::CircleNode *node,
531                                                   locop::NodeSummary &s)
532 {
533   auto gather = loco::must_cast<const luci::CircleGather *>(node);
534   s.args().append("axis", std::to_string(gather->axis()));
535 }
536
537 std::vector<std::string> CircleGatherNdSummaryBuilder::get_input_names(const luci::CircleNode *)
538 {
539   return {"params", "indices"};
540 }
541
542 void CircleGeluSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
543 {
544   auto gelu = loco::must_cast<const luci::CircleGelu *>(node);
545   s.args().append("approximate", to_str(gelu->approximate()));
546 }
547
548 std::vector<std::string> CircleIfSummaryBuilder::get_input_names(const luci::CircleNode *node)
549 {
550   auto circle_if = loco::must_cast<const luci::CircleIf *>(node);
551
552   auto input_names = std::vector<std::string>();
553   input_names.push_back("cond");
554   for (uint32_t i = 0; i < circle_if->input_count(); ++i)
555     input_names.push_back("input");
556
557   return input_names;
558 }
559
560 void CircleIfSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
561 {
562   auto circle_if = loco::must_cast<const luci::CircleIf *>(node);
563
564   if (circle_if->then_graph() != nullptr)
565     s.args().append("then_graph", circle_if->then_graph()->name());
566   else
567     s.args().append("then_branch", std::to_string(circle_if->then_branch()));
568
569   if (circle_if->else_graph() != nullptr)
570     s.args().append("else_graph", circle_if->else_graph()->name());
571   else
572     s.args().append("else_branch", std::to_string(circle_if->else_branch()));
573 }
574
575 bool CircleInstanceNormSummaryBuilder::validate(const luci::CircleNode *node)
576 {
577   auto instnorm = loco::must_cast<const luci::CircleInstanceNorm *>(node);
578   if (instnorm->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
579     return false;
580
581   return true;
582 }
583
584 std::vector<std::string> CircleInstanceNormSummaryBuilder::get_input_names(const luci::CircleNode *)
585 {
586   return {"input", "gamma", "beta"};
587 }
588
589 void CircleInstanceNormSummaryBuilder::build_attributes(const luci::CircleNode *node,
590                                                         locop::NodeSummary &s)
591 {
592   auto instnorm = loco::must_cast<const luci::CircleInstanceNorm *>(node);
593   s.args().append("epsilon", std::to_string(instnorm->epsilon()));
594   s.args().append("fused_activation_function", to_str(instnorm->fusedActivationFunction()));
595 }
596
597 bool CircleL2NormalizeSummaryBuilder::validate(const luci::CircleNode *node)
598 {
599   auto l2norm = loco::must_cast<const luci::CircleL2Normalize *>(node);
600   if (l2norm->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
601     return false;
602
603   return true;
604 }
605
606 std::vector<std::string> CircleL2NormalizeSummaryBuilder::get_input_names(const luci::CircleNode *)
607 {
608   return {"x"};
609 }
610
611 void CircleL2NormalizeSummaryBuilder::build_attributes(const luci::CircleNode *node,
612                                                        locop::NodeSummary &s)
613 {
614   auto l2norm = loco::must_cast<const luci::CircleL2Normalize *>(node);
615   s.args().append("fused_activation_function", to_str(l2norm->fusedActivationFunction()));
616 }
617
618 bool CircleL2Pool2DSummaryBuilder::validate(const luci::CircleNode *node)
619 {
620   auto l2pool = loco::must_cast<const luci::CircleL2Pool2D *>(node);
621   if (l2pool->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
622     return false;
623   if (l2pool->padding() == luci::Padding::UNDEFINED)
624     return false;
625
626   return true;
627 }
628
629 std::vector<std::string> CircleL2Pool2DSummaryBuilder::get_input_names(const luci::CircleNode *)
630 {
631   return {"value"};
632 }
633
634 void CircleL2Pool2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
635                                                     locop::NodeSummary &s)
636 {
637   auto l2pool = loco::must_cast<const luci::CircleL2Pool2D *>(node);
638   s.args().append("filter(h,w)", to_str(l2pool->filter()));
639   s.args().append("stride(h,w)", to_str(l2pool->stride()));
640   s.args().append("padding", to_str(l2pool->padding()));
641   s.args().append("fused_activation_function", to_str(l2pool->fusedActivationFunction()));
642 }
643
644 void CircleLeakyReluSummaryBuilder::build_attributes(const luci::CircleNode *node,
645                                                      locop::NodeSummary &s)
646 {
647   auto leaky_relu = loco::must_cast<const luci::CircleLeakyRelu *>(node);
648   s.args().append("alpha", std::to_string(leaky_relu->alpha()));
649 }
650
651 void CircleLocalResponseNormalizationSummaryBuilder::build_attributes(const luci::CircleNode *node,
652                                                                       locop::NodeSummary &s)
653 {
654   auto lrn = loco::must_cast<const luci::CircleLocalResponseNormalization *>(node);
655   s.args().append("radius", std::to_string(lrn->radius()));
656   s.args().append("bias", std::to_string(lrn->bias()));
657   s.args().append("alpha", std::to_string(lrn->alpha()));
658   s.args().append("beta", std::to_string(lrn->beta()));
659 }
660
661 std::vector<std::string> CircleLogSoftmaxSummaryBuilder::get_input_names(const luci::CircleNode *)
662 {
663   return {"logits"};
664 }
665
666 std::vector<std::string> CircleMatrixDiagSummaryBuilder::get_input_names(const luci::CircleNode *)
667 {
668   return {"diagonal"};
669 }
670
671 std::vector<std::string>
672 CircleMatrixSetDiagSummaryBuilder::get_input_names(const luci::CircleNode *)
673 {
674   return {"input", "diagonal"};
675 }
676
677 bool CircleMaxPool2DSummaryBuilder::validate(const luci::CircleNode *node)
678 {
679   auto maxpool = loco::must_cast<const luci::CircleMaxPool2D *>(node);
680   if (maxpool->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
681     return false;
682   if (maxpool->padding() == luci::Padding::UNDEFINED)
683     return false;
684
685   return true;
686 }
687
688 std::vector<std::string> CircleMaxPool2DSummaryBuilder::get_input_names(const luci::CircleNode *)
689 {
690   return {"value"};
691 }
692
693 void CircleMaxPool2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
694                                                      locop::NodeSummary &s)
695 {
696   auto maxpool = loco::must_cast<const luci::CircleMaxPool2D *>(node);
697   s.args().append("filter(h,w)", to_str(maxpool->filter()));
698   s.args().append("stride(h,w)", to_str(maxpool->stride()));
699   s.args().append("padding", to_str(maxpool->padding()));
700   s.args().append("fused_activation_function", to_str(maxpool->fusedActivationFunction()));
701 }
702
703 bool CircleMirrorPadSummaryBuilder::validate(const luci::CircleNode *node)
704 {
705   auto mirror_pad = loco::must_cast<const luci::CircleMirrorPad *>(node);
706   if (mirror_pad->mode() == luci::MirrorPadMode::UNDEFINED)
707     return false;
708
709   return true;
710 }
711
712 std::vector<std::string> CircleMirrorPadSummaryBuilder::get_input_names(const luci::CircleNode *)
713 {
714   return {"input", "paddings"};
715 }
716
717 void CircleMirrorPadSummaryBuilder::build_attributes(const luci::CircleNode *node,
718                                                      locop::NodeSummary &s)
719 {
720   auto mirror_pad = loco::must_cast<const luci::CircleMirrorPad *>(node);
721   s.args().append("mode", to_str(mirror_pad->mode()));
722 }
723
724 bool CircleMulSummaryBuilder::validate(const luci::CircleNode *node)
725 {
726   auto mul = loco::must_cast<const luci::CircleMul *>(node);
727   if (mul->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
728     return false;
729
730   return true;
731 }
732
733 void CircleMulSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
734 {
735   auto mul = loco::must_cast<const luci::CircleMul *>(node);
736   s.args().append("fused_activation_function", to_str(mul->fusedActivationFunction()));
737 }
738
739 std::vector<std::string>
740 CircleNonMaxSuppressionV4SummaryBuilder::get_input_names(const luci::CircleNode *)
741 {
742   return {"boxes", "scores", "max_output_size", "iou_threshold", "score_threshold"};
743 }
744
745 std::vector<std::string>
746 CircleNonMaxSuppressionV5SummaryBuilder::get_input_names(const luci::CircleNode *)
747 {
748   return {"boxes",         "scores",          "max_output_size",
749           "iou_threshold", "score_threshold", "soft_nms_sigma"};
750 }
751
752 std::vector<std::string> CircleOneHotSummaryBuilder::get_input_names(const luci::CircleNode *)
753 {
754   return {"indices", "depth", "on_value", "off_value"};
755 }
756
757 void CircleOneHotSummaryBuilder::build_attributes(const luci::CircleNode *node,
758                                                   locop::NodeSummary &s)
759 {
760   auto onehot = loco::must_cast<const luci::CircleOneHot *>(node);
761   s.args().append("axis", std::to_string(onehot->axis()));
762 }
763
764 std::vector<std::string> CirclePackSummaryBuilder::get_input_names(const luci::CircleNode *node)
765 {
766   return std::vector<std::string>(node->arity(), "values");
767 }
768
769 void CirclePackSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
770 {
771   auto pack = loco::must_cast<const luci::CirclePack *>(node);
772   s.args().append("values_count", std::to_string(pack->values_count()));
773   s.args().append("axis", std::to_string(pack->axis()));
774 }
775
776 std::vector<std::string> CirclePadSummaryBuilder::get_input_names(const luci::CircleNode *)
777 {
778   return {"input", "paddings"};
779 }
780
781 std::vector<std::string> CirclePadV2SummaryBuilder::get_input_names(const luci::CircleNode *)
782 {
783   return {"input", "paddings", "constant_values"};
784 }
785
786 std::vector<std::string> CirclePReluSummaryBuilder::get_input_names(const luci::CircleNode *)
787 {
788   return {"input", "alpha"};
789 }
790
791 std::vector<std::string> CircleRangeSummaryBuilder::get_input_names(const luci::CircleNode *)
792 {
793   return {"start", "limit", "delta"};
794 }
795
796 std::vector<std::string> CircleReshapeSummaryBuilder::get_input_names(const luci::CircleNode *)
797 {
798   return {"tensor", "shape"};
799 }
800
801 void CircleReshapeSummaryBuilder::update_status(locop::NodeSummary &s)
802 {
803   s.state(locop::NodeDesc::State::PartiallyKnown);
804 }
805
806 std::vector<std::string>
807 CircleResizeBilinearSummaryBuilder::get_input_names(const luci::CircleNode *)
808 {
809   return {"input", "size"};
810 }
811
812 void CircleResizeBilinearSummaryBuilder::build_attributes(const luci::CircleNode *node,
813                                                           locop::NodeSummary &s)
814 {
815   auto resize_bilinear = loco::must_cast<const luci::CircleResizeBilinear *>(node);
816   s.args().append("align_corners", to_str(resize_bilinear->align_corners()));
817   s.args().append("half_pixel_centers", to_str(resize_bilinear->half_pixel_centers()));
818 }
819
820 std::vector<std::string>
821 CircleResizeNearestNeighborSummaryBuilder::get_input_names(const luci::CircleNode *)
822 {
823   return {"input", "size"};
824 }
825
826 void CircleResizeNearestNeighborSummaryBuilder::build_attributes(const luci::CircleNode *node,
827                                                                  locop::NodeSummary &s)
828 {
829   auto resize_nn = loco::must_cast<const luci::CircleResizeNearestNeighbor *>(node);
830   s.args().append("align_corners", to_str(resize_nn->align_corners()));
831 }
832
833 std::vector<std::string>
834 CircleReverseSequenceSummaryBuilder::get_input_names(const luci::CircleNode *)
835 {
836   return {"input", "seq_lengths"};
837 }
838
839 void CircleReverseSequenceSummaryBuilder::build_attributes(const luci::CircleNode *node,
840                                                            locop::NodeSummary &s)
841 {
842   auto reverse_seq = loco::must_cast<const luci::CircleReverseSequence *>(node);
843   s.args().append("seq_axis", std::to_string(reverse_seq->seq_axis()));
844   s.args().append("batch_axis", std::to_string(reverse_seq->batch_axis()));
845 }
846
847 std::vector<std::string> CircleReverseV2SummaryBuilder::get_input_names(const luci::CircleNode *)
848 {
849   return {"tensor", "axis"};
850 }
851
852 std::vector<std::string> CircleScatterNdSummaryBuilder::get_input_names(const luci::CircleNode *)
853 {
854   return {"indices", "updates", "shape"};
855 }
856
857 std::vector<std::string> CircleSegmentSumSummaryBuilder::get_input_names(const luci::CircleNode *)
858 {
859   return {"input", "segment_ids"};
860 }
861
862 std::vector<std::string> CircleSelectSummaryBuilder::get_input_names(const luci::CircleNode *)
863 {
864   return {"condition", "t", "e"};
865 }
866
867 std::vector<std::string> CircleSelectV2SummaryBuilder::get_input_names(const luci::CircleNode *)
868 {
869   return {"condition", "t", "e"};
870 }
871
872 void CircleShapeSummaryBuilder::build_attributes(const luci::CircleNode *node,
873                                                  locop::NodeSummary &s)
874 {
875   auto shape = loco::must_cast<const luci::CircleShape *>(node);
876   s.args().append("out_type", to_str(shape->out_type()));
877 }
878
879 std::vector<std::string> CircleSliceSummaryBuilder::get_input_names(const luci::CircleNode *)
880 {
881   return {"input", "begin", "size"};
882 }
883
884 std::vector<std::string> CircleSoftmaxSummaryBuilder::get_input_names(const luci::CircleNode *)
885 {
886   return {"logits"};
887 }
888
889 void CircleSoftmaxSummaryBuilder::build_attributes(const luci::CircleNode *node,
890                                                    locop::NodeSummary &s)
891 {
892   auto softmax = loco::must_cast<const luci::CircleSoftmax *>(node);
893   s.args().append("beta", to_str(softmax->beta()));
894 }
895
896 std::vector<std::string>
897 CircleSpaceToBatchNDSummaryBuilder::get_input_names(const luci::CircleNode *)
898 {
899   return {"input", "block_shape", "paddings"};
900 }
901
902 void CircleSpaceToDepthSummaryBuilder::build_attributes(const luci::CircleNode *node,
903                                                         locop::NodeSummary &s)
904 {
905   auto space_to_depth = loco::must_cast<const luci::CircleSpaceToDepth *>(node);
906   s.args().append("block_size", to_str(space_to_depth->block_size()));
907 }
908
909 std::vector<std::string>
910 CircleSparseToDenseSummaryBuilder::get_input_names(const luci::CircleNode *)
911 {
912   return {"indices", "output_shape", "values", "default_value"};
913 }
914
915 void CircleSparseToDenseSummaryBuilder::build_attributes(const luci::CircleNode *node,
916                                                          locop::NodeSummary &s)
917 {
918   auto sparse_to_dense = loco::must_cast<const luci::CircleSparseToDense *>(node);
919   s.args().append("validate_indices", to_str(sparse_to_dense->validate_indices()));
920 }
921
922 std::vector<std::string> CircleSplitSummaryBuilder::get_input_names(const luci::CircleNode *)
923 {
924   return {"split_dim", "input"};
925 }
926
927 void CircleSplitSummaryBuilder::build_attributes(const luci::CircleNode *node,
928                                                  locop::NodeSummary &s)
929 {
930   auto split = loco::must_cast<const luci::CircleSplit *>(node);
931   s.args().append("num_split", std::to_string(split->num_split()));
932 }
933
934 std::vector<std::string> CircleSplitVSummaryBuilder::get_input_names(const luci::CircleNode *)
935 {
936   return {"input", "size_splits", "split_dim"};
937 }
938
939 void CircleSplitVSummaryBuilder::build_attributes(const luci::CircleNode *node,
940                                                   locop::NodeSummary &s)
941 {
942   auto split_v = loco::must_cast<const luci::CircleSplitV *>(node);
943   s.args().append("num_split", std::to_string(split_v->num_split()));
944 }
945
946 void CircleSqueezeSummaryBuilder::build_attributes(const luci::CircleNode *node,
947                                                    locop::NodeSummary &s)
948 {
949   auto squeeze = loco::must_cast<const luci::CircleSqueeze *>(node);
950
951   std::string squeeze_dims = "(";
952   for (size_t i = 0; i < squeeze->squeeze_dims().size(); ++i)
953   {
954     if (i != 0)
955       squeeze_dims += ", ";
956     squeeze_dims += std::to_string(squeeze->squeeze_dims().at(i));
957   }
958   squeeze_dims += ")";
959
960   s.args().append("squeeze_dims", squeeze_dims);
961 }
962
963 std::vector<std::string> CircleStridedSliceSummaryBuilder::get_input_names(const luci::CircleNode *)
964 {
965   return {"input", "begin", "end", "strides"};
966 }
967
968 void CircleStridedSliceSummaryBuilder::build_attributes(const luci::CircleNode *node,
969                                                         locop::NodeSummary &s)
970 {
971   auto strided_slice = loco::must_cast<const luci::CircleStridedSlice *>(node);
972   s.args().append("begin_mask", std::to_string(strided_slice->begin_mask()));
973   s.args().append("end_mask", std::to_string(strided_slice->end_mask()));
974   s.args().append("ellipsis_mask", std::to_string(strided_slice->ellipsis_mask()));
975   s.args().append("new_axis_mask", std::to_string(strided_slice->new_axis_mask()));
976   s.args().append("shrink_axis_mask", std::to_string(strided_slice->shrink_axis_mask()));
977 }
978
979 bool CircleSVDFSummaryBuilder::validate(const luci::CircleNode *node)
980 {
981   auto svdf = loco::must_cast<const luci::CircleSVDF *>(node);
982   if (svdf->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
983     return false;
984
985   return true;
986 }
987
988 std::vector<std::string> CircleSVDFSummaryBuilder::get_input_names(const luci::CircleNode *)
989 {
990   return {"input", "weight_feature", "weight_time", "bias", "State"};
991 }
992
993 void CircleSVDFSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
994 {
995   auto svdf = loco::must_cast<const luci::CircleSVDF *>(node);
996   s.args().append("rank", to_str(svdf->svdf_rank()));
997   s.args().append("asymmetric_quantize_inputs", to_str(svdf->asymmetric_quantize_inputs()));
998   s.args().append("fused_activation_function", to_str(svdf->fusedActivationFunction()));
999 }
1000
1001 std::vector<std::string> CircleTileSummaryBuilder::get_input_names(const luci::CircleNode *)
1002 {
1003   return {"input", "multiples"};
1004 }
1005
1006 std::vector<std::string> CircleTopKV2SummaryBuilder::get_input_names(const luci::CircleNode *)
1007 {
1008   return {"input", "k"};
1009 }
1010
1011 std::vector<std::string> CircleTransposeSummaryBuilder::get_input_names(const luci::CircleNode *)
1012 {
1013   return {"a", "perm"};
1014 }
1015
1016 bool CircleTransposeConvSummaryBuilder::validate(const luci::CircleNode *node)
1017 {
1018   auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
1019   if (transpose_conv->padding() == luci::Padding::UNDEFINED)
1020     return false;
1021   if (transpose_conv->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
1022     return false;
1023
1024   return true;
1025 }
1026
1027 std::vector<std::string>
1028 CircleTransposeConvSummaryBuilder::get_input_names(const luci::CircleNode *)
1029 {
1030   return {"inputSizes", "filter", "outBackProp", "bias"};
1031 }
1032
1033 void CircleTransposeConvSummaryBuilder::build_attributes(const luci::CircleNode *node,
1034                                                          locop::NodeSummary &s)
1035 {
1036   auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
1037   s.args().append("stride(h,w)", to_str(transpose_conv->stride()));
1038   s.args().append("padding", to_str(transpose_conv->padding()));
1039   s.args().append("fused_activation_function", to_str(transpose_conv->fusedActivationFunction()));
1040 }
1041
1042 std::vector<std::string>
1043 CircleUnidirectionalSequenceLSTMSummaryBuilder::get_input_names(const luci::CircleNode *)
1044 {
1045   return {"input",
1046           "input_to_input_weights",
1047           "input_to_forget_weights",
1048           "input_to_cell_weights",
1049           "input_to_output_weights",
1050           "recurrent_to_input_weights",
1051           "recurrent_to_forget_weights",
1052           "recurrent_to_cell_weights",
1053           "recurrent_to_output_weights",
1054           "cell_to_input_weights",
1055           "cell_to_forget_weights",
1056           "cell_to_output_weights",
1057           "input_gate_bias",
1058           "forget_gate_bias",
1059           "cell_gate_bias",
1060           "output_gate_bias",
1061           "projection_weights",
1062           "projection_bias",
1063           "output_state",
1064           "cell_state",
1065           "input_layer_norm_coefficients",
1066           "forget_layer_norm_coefficients",
1067           "cell_layer_norm_coefficients",
1068           "output_layer_norm_coefficients"};
1069 }
1070
1071 void CircleUnidirectionalSequenceLSTMSummaryBuilder::build_attributes(const luci::CircleNode *node,
1072                                                                       locop::NodeSummary &s)
1073 {
1074   auto lstm = loco::must_cast<const luci::CircleUnidirectionalSequenceLSTM *>(node);
1075   s.args().append("cell_clip", to_str(lstm->cell_clip()));
1076   s.args().append("proj_clip", to_str(lstm->proj_clip()));
1077   s.args().append("time_major", to_str(lstm->time_major()));
1078   s.args().append("asymmetric_quantize_inputs", to_str(lstm->asymmetric_quantize_inputs()));
1079 }
1080
1081 void CircleUniqueSummaryBuilder::build_attributes(const luci::CircleNode *node,
1082                                                   locop::NodeSummary &s)
1083 {
1084   auto unique = loco::must_cast<const luci::CircleUnique *>(node);
1085   s.args().append("idx_out_type", to_str(unique->idx_out_type()));
1086 }
1087
1088 std::vector<std::string> CircleUnpackSummaryBuilder::get_input_names(const luci::CircleNode *)
1089 {
1090   return {"value"};
1091 }
1092
1093 void CircleUnpackSummaryBuilder::build_attributes(const luci::CircleNode *node,
1094                                                   locop::NodeSummary &s)
1095 {
1096   auto unpack = loco::must_cast<const luci::CircleUnpack *>(node);
1097   s.args().append("num", std::to_string(unpack->num()));
1098   s.args().append("axis", std::to_string(unpack->axis()));
1099 }
1100 std::vector<std::string> CircleWhereSummaryBuilder::get_input_names(const luci::CircleNode *)
1101 {
1102   return {"condition"};
1103 }
1104
1105 std::vector<std::string> CircleWhileSummaryBuilder::get_input_names(const luci::CircleNode *node)
1106 {
1107   auto circle_while = loco::must_cast<const luci::CircleWhile *>(node);
1108
1109   auto input_names = std::vector<std::string>();
1110   for (uint32_t i = 0; i < circle_while->input_count(); ++i)
1111     input_names.push_back("input");
1112
1113   return input_names;
1114 }
1115
1116 void CircleWhileSummaryBuilder::build_attributes(const luci::CircleNode *node,
1117                                                  locop::NodeSummary &s)
1118 {
1119   auto circle_while = loco::must_cast<const luci::CircleWhile *>(node);
1120
1121   if (circle_while->cond_graph() != nullptr)
1122     s.args().append("then_graph", circle_while->cond_graph()->name());
1123   else
1124     s.args().append("then_branch", std::to_string(circle_while->cond_branch()));
1125
1126   if (circle_while->body_graph() != nullptr)
1127     s.args().append("else_graph", circle_while->body_graph()->name());
1128   else
1129     s.args().append("else_branch", std::to_string(circle_while->body_branch()));
1130 }
1131
1132 std::vector<std::string> CircleOutputSummaryBuilder::get_input_names(const luci::CircleNode *)
1133 {
1134   return {"from"};
1135 }
1136
1137 std::vector<std::string> CircleTopKV2OutSummaryBuilder::get_input_names(const luci::CircleNode *)
1138 {
1139   return {"topkv2"};
1140 }
1141
1142 std::vector<std::string> CircleUniqueOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1143 {
1144   return {"unique"};
1145 }
1146
1147 std::vector<std::string> CircleUnpackOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1148 {
1149   return {"unpack"};
1150 }
1151
1152 std::vector<std::string> CircleWhileOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1153 {
1154   return {"while"};
1155 }
1156
1157 } // namespace luci