42f11be1e41fc3099705834974a2c682f5e66ed0
[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 std::vector<std::string> CircleIfSummaryBuilder::get_input_names(const luci::CircleNode *node)
543 {
544   auto circle_if = loco::must_cast<const luci::CircleIf *>(node);
545
546   auto input_names = std::vector<std::string>();
547   input_names.push_back("cond");
548   for (uint32_t i = 0; i < circle_if->input_count(); ++i)
549     input_names.push_back("input");
550
551   return input_names;
552 }
553
554 void CircleIfSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
555 {
556   auto circle_if = loco::must_cast<const luci::CircleIf *>(node);
557
558   if (circle_if->then_graph() != nullptr)
559     s.args().append("then_graph", circle_if->then_graph()->name());
560   else
561     s.args().append("then_branch", std::to_string(circle_if->then_branch()));
562
563   if (circle_if->else_graph() != nullptr)
564     s.args().append("else_graph", circle_if->else_graph()->name());
565   else
566     s.args().append("else_branch", std::to_string(circle_if->else_branch()));
567 }
568
569 bool CircleInstanceNormSummaryBuilder::validate(const luci::CircleNode *node)
570 {
571   auto instnorm = loco::must_cast<const luci::CircleInstanceNorm *>(node);
572   if (instnorm->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
573     return false;
574
575   return true;
576 }
577
578 std::vector<std::string> CircleInstanceNormSummaryBuilder::get_input_names(const luci::CircleNode *)
579 {
580   return {"input", "gamma", "beta"};
581 }
582
583 void CircleInstanceNormSummaryBuilder::build_attributes(const luci::CircleNode *node,
584                                                         locop::NodeSummary &s)
585 {
586   auto instnorm = loco::must_cast<const luci::CircleInstanceNorm *>(node);
587   s.args().append("epsilon", std::to_string(instnorm->epsilon()));
588   s.args().append("fused_activation_function", to_str(instnorm->fusedActivationFunction()));
589 }
590
591 bool CircleL2NormalizeSummaryBuilder::validate(const luci::CircleNode *node)
592 {
593   auto l2norm = loco::must_cast<const luci::CircleL2Normalize *>(node);
594   if (l2norm->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
595     return false;
596
597   return true;
598 }
599
600 std::vector<std::string> CircleL2NormalizeSummaryBuilder::get_input_names(const luci::CircleNode *)
601 {
602   return {"x"};
603 }
604
605 void CircleL2NormalizeSummaryBuilder::build_attributes(const luci::CircleNode *node,
606                                                        locop::NodeSummary &s)
607 {
608   auto l2norm = loco::must_cast<const luci::CircleL2Normalize *>(node);
609   s.args().append("fused_activation_function", to_str(l2norm->fusedActivationFunction()));
610 }
611
612 bool CircleL2Pool2DSummaryBuilder::validate(const luci::CircleNode *node)
613 {
614   auto l2pool = loco::must_cast<const luci::CircleL2Pool2D *>(node);
615   if (l2pool->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
616     return false;
617   if (l2pool->padding() == luci::Padding::UNDEFINED)
618     return false;
619
620   return true;
621 }
622
623 std::vector<std::string> CircleL2Pool2DSummaryBuilder::get_input_names(const luci::CircleNode *)
624 {
625   return {"value"};
626 }
627
628 void CircleL2Pool2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
629                                                     locop::NodeSummary &s)
630 {
631   auto l2pool = loco::must_cast<const luci::CircleL2Pool2D *>(node);
632   s.args().append("filter(h,w)", to_str(l2pool->filter()));
633   s.args().append("stride(h,w)", to_str(l2pool->stride()));
634   s.args().append("padding", to_str(l2pool->padding()));
635   s.args().append("fused_activation_function", to_str(l2pool->fusedActivationFunction()));
636 }
637
638 void CircleLeakyReluSummaryBuilder::build_attributes(const luci::CircleNode *node,
639                                                      locop::NodeSummary &s)
640 {
641   auto leaky_relu = loco::must_cast<const luci::CircleLeakyRelu *>(node);
642   s.args().append("alpha", std::to_string(leaky_relu->alpha()));
643 }
644
645 void CircleLocalResponseNormalizationSummaryBuilder::build_attributes(const luci::CircleNode *node,
646                                                                       locop::NodeSummary &s)
647 {
648   auto lrn = loco::must_cast<const luci::CircleLocalResponseNormalization *>(node);
649   s.args().append("radius", std::to_string(lrn->radius()));
650   s.args().append("bias", std::to_string(lrn->bias()));
651   s.args().append("alpha", std::to_string(lrn->alpha()));
652   s.args().append("beta", std::to_string(lrn->beta()));
653 }
654
655 std::vector<std::string> CircleLogSoftmaxSummaryBuilder::get_input_names(const luci::CircleNode *)
656 {
657   return {"logits"};
658 }
659
660 std::vector<std::string> CircleMatrixDiagSummaryBuilder::get_input_names(const luci::CircleNode *)
661 {
662   return {"diagonal"};
663 }
664
665 std::vector<std::string>
666 CircleMatrixSetDiagSummaryBuilder::get_input_names(const luci::CircleNode *)
667 {
668   return {"input", "diagonal"};
669 }
670
671 bool CircleMaxPool2DSummaryBuilder::validate(const luci::CircleNode *node)
672 {
673   auto maxpool = loco::must_cast<const luci::CircleMaxPool2D *>(node);
674   if (maxpool->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
675     return false;
676   if (maxpool->padding() == luci::Padding::UNDEFINED)
677     return false;
678
679   return true;
680 }
681
682 std::vector<std::string> CircleMaxPool2DSummaryBuilder::get_input_names(const luci::CircleNode *)
683 {
684   return {"value"};
685 }
686
687 void CircleMaxPool2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
688                                                      locop::NodeSummary &s)
689 {
690   auto maxpool = loco::must_cast<const luci::CircleMaxPool2D *>(node);
691   s.args().append("filter(h,w)", to_str(maxpool->filter()));
692   s.args().append("stride(h,w)", to_str(maxpool->stride()));
693   s.args().append("padding", to_str(maxpool->padding()));
694   s.args().append("fused_activation_function", to_str(maxpool->fusedActivationFunction()));
695 }
696
697 bool CircleMirrorPadSummaryBuilder::validate(const luci::CircleNode *node)
698 {
699   auto mirror_pad = loco::must_cast<const luci::CircleMirrorPad *>(node);
700   if (mirror_pad->mode() == luci::MirrorPadMode::UNDEFINED)
701     return false;
702
703   return true;
704 }
705
706 std::vector<std::string> CircleMirrorPadSummaryBuilder::get_input_names(const luci::CircleNode *)
707 {
708   return {"input", "paddings"};
709 }
710
711 void CircleMirrorPadSummaryBuilder::build_attributes(const luci::CircleNode *node,
712                                                      locop::NodeSummary &s)
713 {
714   auto mirror_pad = loco::must_cast<const luci::CircleMirrorPad *>(node);
715   s.args().append("mode", to_str(mirror_pad->mode()));
716 }
717
718 bool CircleMulSummaryBuilder::validate(const luci::CircleNode *node)
719 {
720   auto mul = loco::must_cast<const luci::CircleMul *>(node);
721   if (mul->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
722     return false;
723
724   return true;
725 }
726
727 void CircleMulSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
728 {
729   auto mul = loco::must_cast<const luci::CircleMul *>(node);
730   s.args().append("fused_activation_function", to_str(mul->fusedActivationFunction()));
731 }
732
733 std::vector<std::string>
734 CircleNonMaxSuppressionV4SummaryBuilder::get_input_names(const luci::CircleNode *)
735 {
736   return {"boxes", "scores", "max_output_size", "iou_threshold", "score_threshold"};
737 }
738
739 std::vector<std::string>
740 CircleNonMaxSuppressionV5SummaryBuilder::get_input_names(const luci::CircleNode *)
741 {
742   return {"boxes",         "scores",          "max_output_size",
743           "iou_threshold", "score_threshold", "soft_nms_sigma"};
744 }
745
746 std::vector<std::string> CircleOneHotSummaryBuilder::get_input_names(const luci::CircleNode *)
747 {
748   return {"indices", "depth", "on_value", "off_value"};
749 }
750
751 void CircleOneHotSummaryBuilder::build_attributes(const luci::CircleNode *node,
752                                                   locop::NodeSummary &s)
753 {
754   auto onehot = loco::must_cast<const luci::CircleOneHot *>(node);
755   s.args().append("axis", std::to_string(onehot->axis()));
756 }
757
758 std::vector<std::string> CirclePackSummaryBuilder::get_input_names(const luci::CircleNode *node)
759 {
760   return std::vector<std::string>(node->arity(), "values");
761 }
762
763 void CirclePackSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
764 {
765   auto pack = loco::must_cast<const luci::CirclePack *>(node);
766   s.args().append("values_count", std::to_string(pack->values_count()));
767   s.args().append("axis", std::to_string(pack->axis()));
768 }
769
770 std::vector<std::string> CirclePadSummaryBuilder::get_input_names(const luci::CircleNode *)
771 {
772   return {"input", "paddings"};
773 }
774
775 std::vector<std::string> CirclePadV2SummaryBuilder::get_input_names(const luci::CircleNode *)
776 {
777   return {"input", "paddings", "constant_values"};
778 }
779
780 std::vector<std::string> CirclePReluSummaryBuilder::get_input_names(const luci::CircleNode *)
781 {
782   return {"input", "alpha"};
783 }
784
785 std::vector<std::string> CircleRangeSummaryBuilder::get_input_names(const luci::CircleNode *)
786 {
787   return {"start", "limit", "delta"};
788 }
789
790 std::vector<std::string> CircleReshapeSummaryBuilder::get_input_names(const luci::CircleNode *)
791 {
792   return {"tensor", "shape"};
793 }
794
795 void CircleReshapeSummaryBuilder::update_status(locop::NodeSummary &s)
796 {
797   s.state(locop::NodeDesc::State::PartiallyKnown);
798 }
799
800 std::vector<std::string>
801 CircleResizeBilinearSummaryBuilder::get_input_names(const luci::CircleNode *)
802 {
803   return {"input", "size"};
804 }
805
806 void CircleResizeBilinearSummaryBuilder::build_attributes(const luci::CircleNode *node,
807                                                           locop::NodeSummary &s)
808 {
809   auto resize_bilinear = loco::must_cast<const luci::CircleResizeBilinear *>(node);
810   s.args().append("align_corners", to_str(resize_bilinear->align_corners()));
811   s.args().append("half_pixel_centers", to_str(resize_bilinear->half_pixel_centers()));
812 }
813
814 std::vector<std::string>
815 CircleResizeNearestNeighborSummaryBuilder::get_input_names(const luci::CircleNode *)
816 {
817   return {"input", "size"};
818 }
819
820 void CircleResizeNearestNeighborSummaryBuilder::build_attributes(const luci::CircleNode *node,
821                                                                  locop::NodeSummary &s)
822 {
823   auto resize_nn = loco::must_cast<const luci::CircleResizeNearestNeighbor *>(node);
824   s.args().append("align_corners", to_str(resize_nn->align_corners()));
825 }
826
827 std::vector<std::string>
828 CircleReverseSequenceSummaryBuilder::get_input_names(const luci::CircleNode *)
829 {
830   return {"input", "seq_lengths"};
831 }
832
833 void CircleReverseSequenceSummaryBuilder::build_attributes(const luci::CircleNode *node,
834                                                            locop::NodeSummary &s)
835 {
836   auto reverse_seq = loco::must_cast<const luci::CircleReverseSequence *>(node);
837   s.args().append("seq_axis", std::to_string(reverse_seq->seq_axis()));
838   s.args().append("batch_axis", std::to_string(reverse_seq->batch_axis()));
839 }
840
841 std::vector<std::string> CircleReverseV2SummaryBuilder::get_input_names(const luci::CircleNode *)
842 {
843   return {"tensor", "axis"};
844 }
845
846 std::vector<std::string> CircleScatterNdSummaryBuilder::get_input_names(const luci::CircleNode *)
847 {
848   return {"indices", "updates", "shape"};
849 }
850
851 std::vector<std::string> CircleSegmentSumSummaryBuilder::get_input_names(const luci::CircleNode *)
852 {
853   return {"input", "segment_ids"};
854 }
855
856 std::vector<std::string> CircleSelectSummaryBuilder::get_input_names(const luci::CircleNode *)
857 {
858   return {"condition", "t", "e"};
859 }
860
861 std::vector<std::string> CircleSelectV2SummaryBuilder::get_input_names(const luci::CircleNode *)
862 {
863   return {"condition", "t", "e"};
864 }
865
866 void CircleShapeSummaryBuilder::build_attributes(const luci::CircleNode *node,
867                                                  locop::NodeSummary &s)
868 {
869   auto shape = loco::must_cast<const luci::CircleShape *>(node);
870   s.args().append("out_type", to_str(shape->out_type()));
871 }
872
873 std::vector<std::string> CircleSliceSummaryBuilder::get_input_names(const luci::CircleNode *)
874 {
875   return {"input", "begin", "size"};
876 }
877
878 std::vector<std::string> CircleSoftmaxSummaryBuilder::get_input_names(const luci::CircleNode *)
879 {
880   return {"logits"};
881 }
882
883 void CircleSoftmaxSummaryBuilder::build_attributes(const luci::CircleNode *node,
884                                                    locop::NodeSummary &s)
885 {
886   auto softmax = loco::must_cast<const luci::CircleSoftmax *>(node);
887   s.args().append("beta", to_str(softmax->beta()));
888 }
889
890 std::vector<std::string>
891 CircleSpaceToBatchNDSummaryBuilder::get_input_names(const luci::CircleNode *)
892 {
893   return {"input", "block_shape", "paddings"};
894 }
895
896 void CircleSpaceToDepthSummaryBuilder::build_attributes(const luci::CircleNode *node,
897                                                         locop::NodeSummary &s)
898 {
899   auto space_to_depth = loco::must_cast<const luci::CircleSpaceToDepth *>(node);
900   s.args().append("block_size", to_str(space_to_depth->block_size()));
901 }
902
903 std::vector<std::string>
904 CircleSparseToDenseSummaryBuilder::get_input_names(const luci::CircleNode *)
905 {
906   return {"indices", "output_shape", "values", "default_value"};
907 }
908
909 void CircleSparseToDenseSummaryBuilder::build_attributes(const luci::CircleNode *node,
910                                                          locop::NodeSummary &s)
911 {
912   auto sparse_to_dense = loco::must_cast<const luci::CircleSparseToDense *>(node);
913   s.args().append("validate_indices", to_str(sparse_to_dense->validate_indices()));
914 }
915
916 std::vector<std::string> CircleSplitSummaryBuilder::get_input_names(const luci::CircleNode *)
917 {
918   return {"split_dim", "input"};
919 }
920
921 void CircleSplitSummaryBuilder::build_attributes(const luci::CircleNode *node,
922                                                  locop::NodeSummary &s)
923 {
924   auto split = loco::must_cast<const luci::CircleSplit *>(node);
925   s.args().append("num_split", std::to_string(split->num_split()));
926 }
927
928 std::vector<std::string> CircleSplitVSummaryBuilder::get_input_names(const luci::CircleNode *)
929 {
930   return {"input", "size_splits", "split_dim"};
931 }
932
933 void CircleSplitVSummaryBuilder::build_attributes(const luci::CircleNode *node,
934                                                   locop::NodeSummary &s)
935 {
936   auto split_v = loco::must_cast<const luci::CircleSplitV *>(node);
937   s.args().append("num_split", std::to_string(split_v->num_split()));
938 }
939
940 void CircleSqueezeSummaryBuilder::build_attributes(const luci::CircleNode *node,
941                                                    locop::NodeSummary &s)
942 {
943   auto squeeze = loco::must_cast<const luci::CircleSqueeze *>(node);
944
945   std::string squeeze_dims = "(";
946   for (size_t i = 0; i < squeeze->squeeze_dims().size(); ++i)
947   {
948     if (i != 0)
949       squeeze_dims += ", ";
950     squeeze_dims += std::to_string(squeeze->squeeze_dims().at(i));
951   }
952   squeeze_dims += ")";
953
954   s.args().append("squeeze_dims", squeeze_dims);
955 }
956
957 std::vector<std::string> CircleStridedSliceSummaryBuilder::get_input_names(const luci::CircleNode *)
958 {
959   return {"input", "begin", "end", "strides"};
960 }
961
962 void CircleStridedSliceSummaryBuilder::build_attributes(const luci::CircleNode *node,
963                                                         locop::NodeSummary &s)
964 {
965   auto strided_slice = loco::must_cast<const luci::CircleStridedSlice *>(node);
966   s.args().append("begin_mask", std::to_string(strided_slice->begin_mask()));
967   s.args().append("end_mask", std::to_string(strided_slice->end_mask()));
968   s.args().append("ellipsis_mask", std::to_string(strided_slice->ellipsis_mask()));
969   s.args().append("new_axis_mask", std::to_string(strided_slice->new_axis_mask()));
970   s.args().append("shrink_axis_mask", std::to_string(strided_slice->shrink_axis_mask()));
971 }
972
973 bool CircleSVDFSummaryBuilder::validate(const luci::CircleNode *node)
974 {
975   auto svdf = loco::must_cast<const luci::CircleSVDF *>(node);
976   if (svdf->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
977     return false;
978
979   return true;
980 }
981
982 std::vector<std::string> CircleSVDFSummaryBuilder::get_input_names(const luci::CircleNode *)
983 {
984   return {"input", "weight_feature", "weight_time", "bias", "State"};
985 }
986
987 void CircleSVDFSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
988 {
989   auto svdf = loco::must_cast<const luci::CircleSVDF *>(node);
990   s.args().append("rank", to_str(svdf->svdf_rank()));
991   s.args().append("asymmetric_quantize_inputs", to_str(svdf->asymmetric_quantize_inputs()));
992   s.args().append("fused_activation_function", to_str(svdf->fusedActivationFunction()));
993 }
994
995 std::vector<std::string> CircleTileSummaryBuilder::get_input_names(const luci::CircleNode *)
996 {
997   return {"input", "multiples"};
998 }
999
1000 std::vector<std::string> CircleTopKV2SummaryBuilder::get_input_names(const luci::CircleNode *)
1001 {
1002   return {"input", "k"};
1003 }
1004
1005 std::vector<std::string> CircleTransposeSummaryBuilder::get_input_names(const luci::CircleNode *)
1006 {
1007   return {"a", "perm"};
1008 }
1009
1010 bool CircleTransposeConvSummaryBuilder::validate(const luci::CircleNode *node)
1011 {
1012   auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
1013   if (transpose_conv->padding() == luci::Padding::UNDEFINED)
1014     return false;
1015
1016   return true;
1017 }
1018
1019 std::vector<std::string>
1020 CircleTransposeConvSummaryBuilder::get_input_names(const luci::CircleNode *)
1021 {
1022   return {"inputSizes", "filter", "outBackProp", "bias"};
1023 }
1024
1025 void CircleTransposeConvSummaryBuilder::build_attributes(const luci::CircleNode *node,
1026                                                          locop::NodeSummary &s)
1027 {
1028   auto transpose_conv = loco::must_cast<const luci::CircleTransposeConv *>(node);
1029   s.args().append("stride(h,w)", to_str(transpose_conv->stride()));
1030   s.args().append("padding", to_str(transpose_conv->padding()));
1031 }
1032
1033 std::vector<std::string>
1034 CircleUnidirectionalSequenceLSTMSummaryBuilder::get_input_names(const luci::CircleNode *)
1035 {
1036   return {"input",
1037           "input_to_input_weights",
1038           "input_to_forget_weights",
1039           "input_to_cell_weights",
1040           "input_to_output_weights",
1041           "recurrent_to_input_weights",
1042           "recurrent_to_forget_weights",
1043           "recurrent_to_cell_weights",
1044           "recurrent_to_output_weights",
1045           "cell_to_input_weights",
1046           "cell_to_forget_weights",
1047           "cell_to_output_weights",
1048           "input_gate_bias",
1049           "forget_gate_bias",
1050           "cell_gate_bias",
1051           "output_gate_bias",
1052           "projection_weights",
1053           "projection_bias",
1054           "output_state",
1055           "cell_state",
1056           "input_layer_norm_coefficients",
1057           "forget_layer_norm_coefficients",
1058           "cell_layer_norm_coefficients",
1059           "output_layer_norm_coefficients"};
1060 }
1061
1062 void CircleUnidirectionalSequenceLSTMSummaryBuilder::build_attributes(const luci::CircleNode *node,
1063                                                                       locop::NodeSummary &s)
1064 {
1065   auto lstm = loco::must_cast<const luci::CircleUnidirectionalSequenceLSTM *>(node);
1066   s.args().append("cell_clip", to_str(lstm->cell_clip()));
1067   s.args().append("proj_clip", to_str(lstm->proj_clip()));
1068   s.args().append("time_major", to_str(lstm->time_major()));
1069   s.args().append("asymmetric_quantize_inputs", to_str(lstm->asymmetric_quantize_inputs()));
1070 }
1071
1072 void CircleUniqueSummaryBuilder::build_attributes(const luci::CircleNode *node,
1073                                                   locop::NodeSummary &s)
1074 {
1075   auto unique = loco::must_cast<const luci::CircleUnique *>(node);
1076   s.args().append("idx_out_type", to_str(unique->idx_out_type()));
1077 }
1078
1079 std::vector<std::string> CircleUnpackSummaryBuilder::get_input_names(const luci::CircleNode *)
1080 {
1081   return {"value"};
1082 }
1083
1084 void CircleUnpackSummaryBuilder::build_attributes(const luci::CircleNode *node,
1085                                                   locop::NodeSummary &s)
1086 {
1087   auto unpack = loco::must_cast<const luci::CircleUnpack *>(node);
1088   s.args().append("num", std::to_string(unpack->num()));
1089   s.args().append("axis", std::to_string(unpack->axis()));
1090 }
1091 std::vector<std::string> CircleWhereSummaryBuilder::get_input_names(const luci::CircleNode *)
1092 {
1093   return {"condition"};
1094 }
1095
1096 std::vector<std::string> CircleWhileSummaryBuilder::get_input_names(const luci::CircleNode *node)
1097 {
1098   auto circle_while = loco::must_cast<const luci::CircleWhile *>(node);
1099
1100   auto input_names = std::vector<std::string>();
1101   for (uint32_t i = 0; i < circle_while->input_count(); ++i)
1102     input_names.push_back("input");
1103
1104   return input_names;
1105 }
1106
1107 void CircleWhileSummaryBuilder::build_attributes(const luci::CircleNode *node,
1108                                                  locop::NodeSummary &s)
1109 {
1110   auto circle_while = loco::must_cast<const luci::CircleWhile *>(node);
1111
1112   if (circle_while->cond_graph() != nullptr)
1113     s.args().append("then_graph", circle_while->cond_graph()->name());
1114   else
1115     s.args().append("then_branch", std::to_string(circle_while->cond_branch()));
1116
1117   if (circle_while->body_graph() != nullptr)
1118     s.args().append("else_graph", circle_while->body_graph()->name());
1119   else
1120     s.args().append("else_branch", std::to_string(circle_while->body_branch()));
1121 }
1122
1123 std::vector<std::string> CircleOutputSummaryBuilder::get_input_names(const luci::CircleNode *)
1124 {
1125   return {"from"};
1126 }
1127
1128 std::vector<std::string> CircleTopKV2OutSummaryBuilder::get_input_names(const luci::CircleNode *)
1129 {
1130   return {"topkv2"};
1131 }
1132
1133 std::vector<std::string> CircleUniqueOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1134 {
1135   return {"unique"};
1136 }
1137
1138 std::vector<std::string> CircleUnpackOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1139 {
1140   return {"unpack"};
1141 }
1142
1143 std::vector<std::string> CircleWhileOutSummaryBuilder::get_input_names(const luci::CircleNode *)
1144 {
1145   return {"while"};
1146 }
1147
1148 } // namespace luci