Imported Upstream version 1.7.0
[platform/core/ml/nnfw.git] / compiler / luci / logex / src / FormattedGraph.cpp
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 "luci/FormattedGraph.h"
18
19 #include <luci/IR/CircleDialect.h>
20 #include <luci/IR/CircleNodes.h>
21
22 #include <pepper/str.h>
23
24 #include <cassert>
25 #include <sstream>
26 #include <vector>
27
28 /**
29  * @brief dump std::vector<int64_t> values to stream
30  */
31 std::ostream &operator<<(std::ostream &os, const std::vector<int64_t> &vi64)
32 {
33   for (auto vi : vi64)
34   {
35     os << vi << " ";
36   }
37   return os;
38 }
39
40 // For TF lite
41 namespace
42 {
43
44 const char *to_str(loco::DataType type)
45 {
46   switch (type)
47   {
48     case loco::DataType::U8:
49       return "UINT8";
50     case loco::DataType::U16:
51       return "UINT16";
52     case loco::DataType::U32:
53       return "UINT32";
54     case loco::DataType::U64:
55       return "UINT64";
56
57     case loco::DataType::S8:
58       return "INT8";
59     case loco::DataType::S16:
60       return "INT16";
61     case loco::DataType::S32:
62       return "INT32";
63     case loco::DataType::S64:
64       return "INT64";
65
66     case loco::DataType::FLOAT16:
67       return "FLOAT16";
68     case loco::DataType::FLOAT32:
69       return "FLOAT32";
70     case loco::DataType::FLOAT64:
71       return "FLOAT64";
72
73     case loco::DataType::BOOL:
74       return "BOOL";
75
76     default:
77       return "Error";
78   }
79 }
80
81 const char *to_str(bool value) { return value ? "true" : "false"; }
82
83 const char *to_str(luci::FusedActFunc fused)
84 {
85   switch (fused)
86   {
87     case luci::FusedActFunc::NONE:
88       return "NONE";
89     case luci::FusedActFunc::RELU:
90       return "RELU";
91     case luci::FusedActFunc::RELU_N1_TO_1:
92       return "RELU_N1_TO_1";
93     case luci::FusedActFunc::RELU6:
94       return "RELU6";
95     default:
96       return "Error";
97   }
98 }
99
100 const char *to_str(luci::Padding padding)
101 {
102   switch (padding)
103   {
104     case luci::Padding::SAME:
105       return "SAME";
106     case luci::Padding::VALID:
107       return "VALID";
108     default:
109       return "Error";
110   }
111 }
112
113 const char *to_str(luci::MirrorPadMode mode)
114 {
115   switch (mode)
116   {
117     case luci::MirrorPadMode::REFLECT:
118       return "REFLECT";
119     case luci::MirrorPadMode::SYMMETRIC:
120       return "SYMMETRIC";
121     default:
122       return "Error";
123   }
124 }
125
126 std::string to_str(const luci::Stride *stride)
127 {
128   return pepper::str(stride->h(), ",", stride->w());
129 }
130
131 std::string to_str(const luci::Filter *filter)
132 {
133   return pepper::str(filter->h(), ",", filter->w());
134 }
135
136 std::string circle_opname(uint32_t opnum)
137 {
138   static const std::string prefix{"circle."};
139
140   switch (static_cast<luci::CircleOpcode>(opnum))
141   {
142 #define CIRCLE_NODE(OPCODE, CLASS) \
143   case luci::CircleOpcode::OPCODE: \
144     return prefix + #OPCODE;
145 #include <luci/IR/CircleNodes.lst>
146 #undef CIRCLE_NODE
147     default:
148       break;
149   };
150
151   return prefix + "Invalid";
152 }
153
154 // CircleNodeSummaryBuilder with default implementation
155 class CircleNodeSummaryBuilderBase : public locop::NodeSummaryBuilder
156 {
157 public:
158   CircleNodeSummaryBuilderBase(const locop::SymbolTable *tbl) : _tbl{tbl}
159   {
160     // DO NOTHING
161   }
162
163 public:
164   bool build(const loco::Node *, locop::NodeSummary &s) const final;
165
166 protected:
167 #define CIRCLE_NODE(OPCODE, CLASS)                                      \
168   virtual bool summary(const CLASS *, locop::NodeSummary &s) const      \
169   {                                                                     \
170     s.comments().append("Emitted by Default CircleNodeSummaryBuilder"); \
171     s.state(locop::NodeSummary::State::PartiallyKnown);                 \
172     return true;                                                        \
173   }
174 #include <luci/IR/CircleNodes.lst>
175 #undef CIRCLE_NODE
176
177 protected:
178   const locop::SymbolTable *tbl(void) const { return _tbl; }
179
180   // Please do not use _tbl directly and use tbl().
181   // This will be changed to private in near future.
182 protected:
183   const locop::SymbolTable *_tbl;
184 };
185
186 class CircleNodeSummaryBuilder final : public CircleNodeSummaryBuilderBase
187 {
188 public:
189   CircleNodeSummaryBuilder(const locop::SymbolTable *tbl) : CircleNodeSummaryBuilderBase(tbl)
190   {
191     // DO NOTHING
192   }
193
194 private:
195 #define IMPLEMENT(CLASS) bool summary(const CLASS *, locop::NodeSummary &) const final;
196   IMPLEMENT(luci::CircleAbs)
197   IMPLEMENT(luci::CircleAdd)
198   IMPLEMENT(luci::CircleAddN)
199   IMPLEMENT(luci::CircleArgMax)
200   IMPLEMENT(luci::CircleArgMin)
201   IMPLEMENT(luci::CircleAveragePool2D)
202   IMPLEMENT(luci::CircleBatchMatMul)
203   IMPLEMENT(luci::CircleBatchToSpaceND)
204   IMPLEMENT(luci::CircleCast)
205   IMPLEMENT(luci::CircleCeil)
206   IMPLEMENT(luci::CircleConcatenation)
207   IMPLEMENT(luci::CircleConst)
208   IMPLEMENT(luci::CircleConv2D)
209   IMPLEMENT(luci::CircleCos)
210   IMPLEMENT(luci::CircleCustom)
211   IMPLEMENT(luci::CircleDepthToSpace)
212   IMPLEMENT(luci::CircleDepthwiseConv2D)
213   IMPLEMENT(luci::CircleDiv)
214   IMPLEMENT(luci::CircleElu)
215   IMPLEMENT(luci::CircleExp)
216   IMPLEMENT(luci::CircleExpandDims)
217   IMPLEMENT(luci::CircleFill)
218   IMPLEMENT(luci::CircleFloor)
219   IMPLEMENT(luci::CircleFloorDiv)
220   IMPLEMENT(luci::CircleFloorMod)
221   IMPLEMENT(luci::CircleFullyConnected)
222   IMPLEMENT(luci::CircleGather)
223   IMPLEMENT(luci::CircleGatherNd)
224   IMPLEMENT(luci::CircleGreater)
225   IMPLEMENT(luci::CircleGreaterEqual)
226   IMPLEMENT(luci::CircleIf)
227   IMPLEMENT(luci::CircleL2Normalize)
228   IMPLEMENT(luci::CircleLeakyRelu)
229   IMPLEMENT(luci::CircleLess)
230   IMPLEMENT(luci::CircleLessEqual)
231   IMPLEMENT(luci::CircleLocalResponseNormalization)
232   IMPLEMENT(luci::CircleLog)
233   IMPLEMENT(luci::CircleLogicalAnd)
234   IMPLEMENT(luci::CircleLogicalNot)
235   IMPLEMENT(luci::CircleLogicalOr)
236   IMPLEMENT(luci::CircleLogistic)
237   IMPLEMENT(luci::CircleLogSoftmax)
238   IMPLEMENT(luci::CircleMatrixDiag)
239   IMPLEMENT(luci::CircleMatrixSetDiag)
240   IMPLEMENT(luci::CircleMaximum)
241   IMPLEMENT(luci::CircleMaxPool2D)
242   IMPLEMENT(luci::CircleMean)
243   IMPLEMENT(luci::CircleMinimum)
244   IMPLEMENT(luci::CircleMirrorPad)
245   IMPLEMENT(luci::CircleMul)
246   IMPLEMENT(luci::CircleNeg)
247   IMPLEMENT(luci::CircleNotEqual)
248   IMPLEMENT(luci::CircleOneHot)
249   IMPLEMENT(luci::CirclePack)
250   IMPLEMENT(luci::CirclePad)
251   IMPLEMENT(luci::CirclePow)
252   IMPLEMENT(luci::CirclePRelu)
253   IMPLEMENT(luci::CircleRange)
254   IMPLEMENT(luci::CircleRank)
255   IMPLEMENT(luci::CircleReduceAny)
256   IMPLEMENT(luci::CircleReduceMax)
257   IMPLEMENT(luci::CircleReduceMin)
258   IMPLEMENT(luci::CircleReduceProd)
259   IMPLEMENT(luci::CircleRelu)
260   IMPLEMENT(luci::CircleRelu6)
261   IMPLEMENT(luci::CircleReluN1To1)
262   IMPLEMENT(luci::CircleReshape)
263   IMPLEMENT(luci::CircleResizeBilinear)
264   IMPLEMENT(luci::CircleResizeNearestNeighbor)
265   IMPLEMENT(luci::CircleReverseSequence)
266   IMPLEMENT(luci::CircleReverseV2)
267   IMPLEMENT(luci::CircleRound)
268   IMPLEMENT(luci::CircleRsqrt)
269   IMPLEMENT(luci::CircleScatterNd)
270   IMPLEMENT(luci::CircleSegmentSum)
271   IMPLEMENT(luci::CircleSelect)
272   IMPLEMENT(luci::CircleSelectV2)
273   IMPLEMENT(luci::CircleShape)
274   IMPLEMENT(luci::CircleSin)
275   IMPLEMENT(luci::CircleSlice)
276   IMPLEMENT(luci::CircleSoftmax)
277   IMPLEMENT(luci::CircleSpaceToBatchND)
278   IMPLEMENT(luci::CircleSpaceToDepth)
279   IMPLEMENT(luci::CircleSparseToDense)
280   IMPLEMENT(luci::CircleSplit)
281   IMPLEMENT(luci::CircleSplitV)
282   IMPLEMENT(luci::CircleSqrt)
283   IMPLEMENT(luci::CircleSquare)
284   IMPLEMENT(luci::CircleSquaredDifference)
285   IMPLEMENT(luci::CircleSqueeze)
286   IMPLEMENT(luci::CircleStridedSlice)
287   IMPLEMENT(luci::CircleSub)
288   IMPLEMENT(luci::CircleSum)
289   IMPLEMENT(luci::CircleTanh)
290   IMPLEMENT(luci::CircleTile)
291   IMPLEMENT(luci::CircleTopKV2)
292   IMPLEMENT(luci::CircleTranspose)
293   IMPLEMENT(luci::CircleTransposeConv)
294   IMPLEMENT(luci::CircleUnpack)
295   IMPLEMENT(luci::CircleWhere)
296   IMPLEMENT(luci::CircleWhile)
297   IMPLEMENT(luci::CircleZerosLike)
298   // Circle Only
299   IMPLEMENT(luci::CircleBCQFullyConnected)
300   IMPLEMENT(luci::CircleBCQGather)
301   IMPLEMENT(luci::CircleInstanceNorm)
302   // Virtual nodes
303   IMPLEMENT(luci::CircleInput)
304   IMPLEMENT(luci::CircleOutput)
305   IMPLEMENT(luci::CircleIfOut)
306   IMPLEMENT(luci::CircleSplitOut)
307   IMPLEMENT(luci::CircleSplitVOut)
308   IMPLEMENT(luci::CircleTopKV2Out)
309   IMPLEMENT(luci::CircleUnpackOut)
310   IMPLEMENT(luci::CircleWhileOut)
311 #undef IMPLEMENT
312 };
313
314 template <class CIRCLENODE>
315 bool use_x(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
316 {
317   s.args().append("x", tbl->lookup(node->x()));
318   s.state(locop::NodeSummary::State::Complete);
319   return true;
320 }
321
322 template <class CIRCLENODE>
323 bool use_input(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
324 {
325   s.args().append("input", tbl->lookup(node->input()));
326   s.state(locop::NodeSummary::State::Complete);
327   return true;
328 }
329
330 template <class CIRCLENODE>
331 bool use_features(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
332 {
333   s.args().append("features", tbl->lookup(node->features()));
334   s.state(locop::NodeSummary::State::Complete);
335   return true;
336 }
337
338 template <class CIRCLENODE>
339 bool use_xy(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
340 {
341   s.args().append("x", tbl->lookup(node->x()));
342   s.args().append("y", tbl->lookup(node->y()));
343   s.state(locop::NodeSummary::State::Complete);
344   return true;
345 }
346
347 template <class CIRCLENODE>
348 bool use_xy_act(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
349 {
350   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
351
352   s.args().append("x", tbl->lookup(node->x()));
353   s.args().append("y", tbl->lookup(node->y()));
354   s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
355   s.state(locop::NodeSummary::State::Complete);
356   return true;
357 }
358
359 template <class CIRCLENODE>
360 bool use_reducer(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
361 {
362   s.args().append("input", tbl->lookup(node->input()));
363   s.args().append("reduction_indices", tbl->lookup(node->reduction_indices()));
364   s.args().append("keep_dims", node->keep_dims() ? "true" : "false");
365   s.state(locop::NodeSummary::State::Complete);
366   return true;
367 }
368
369 template <class CIRCLENODE>
370 bool use_ido(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
371 {
372   s.args().append("input", tbl->lookup(node->input()));
373   s.args().append("dimension", tbl->lookup(node->dimension()));
374   s.args().append("output_type", to_str(node->output_type()));
375   s.state(locop::NodeSummary::State::Complete);
376   return true;
377 }
378
379 bool CircleNodeSummaryBuilderBase::build(const loco::Node *node, locop::NodeSummary &s) const
380 {
381   if (node->dialect() != luci::CircleDialect::get())
382     return false;
383
384 #define CIRCLE_NODE(OPCODE, CLASS)                        \
385   if (dynamic_cast<const CLASS *>(node))                  \
386   {                                                       \
387     s.opname(circle_opname(node->opnum()));               \
388     return summary(dynamic_cast<const CLASS *>(node), s); \
389   }
390 #include <luci/IR/CircleNodes.lst>
391 #undef CIRCLE_NODE
392
393   return false;
394 }
395
396 bool CircleNodeSummaryBuilder::summary(const luci::CircleAbs *node, locop::NodeSummary &s) const
397 {
398   return use_x(tbl(), node, s);
399 }
400
401 bool CircleNodeSummaryBuilder::summary(const luci::CircleAdd *node, locop::NodeSummary &s) const
402 {
403   return use_xy_act(tbl(), node, s);
404 }
405
406 bool CircleNodeSummaryBuilder::summary(const luci::CircleAddN *node, locop::NodeSummary &s) const
407 {
408   for (uint32_t i = 0; i < node->arity(); ++i)
409     s.args().append("inputs", tbl()->lookup(node->inputs(i)));
410
411   s.state(locop::NodeSummary::State::Complete);
412   return true;
413 }
414
415 bool CircleNodeSummaryBuilder::summary(const luci::CircleArgMax *node, locop::NodeSummary &s) const
416 {
417   return use_ido(tbl(), node, s);
418 }
419
420 bool CircleNodeSummaryBuilder::summary(const luci::CircleArgMin *node, locop::NodeSummary &s) const
421 {
422   return use_ido(tbl(), node, s);
423 }
424
425 bool CircleNodeSummaryBuilder::summary(const luci::CircleAveragePool2D *node,
426                                        locop::NodeSummary &s) const
427 {
428   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
429
430   s.args().append("value", tbl()->lookup(node->value()));
431   s.args().append("filter(h,w)", to_str(node->filter()));
432   s.args().append("stride(h,w)", to_str(node->stride()));
433   s.args().append("padding", to_str(node->padding()));
434   s.args().append("fused", to_str(node->fusedActivationFunction()));
435
436   s.state(locop::NodeSummary::State::Complete);
437
438   return true;
439 }
440
441 bool CircleNodeSummaryBuilder::summary(const luci::CircleBatchMatMul *node,
442                                        locop::NodeSummary &s) const
443 {
444   s.args().append("x", tbl()->lookup(node->x()));
445   s.args().append("y", tbl()->lookup(node->y()));
446   s.args().append("adj_x", to_str(node->adj_x()));
447   s.args().append("adj_y", to_str(node->adj_y()));
448   s.state(locop::NodeSummary::State::Complete);
449   return true;
450 }
451
452 bool CircleNodeSummaryBuilder::summary(const luci::CircleBatchToSpaceND *node,
453                                        locop::NodeSummary &s) const
454 {
455   s.args().append("input", tbl()->lookup(node->input()));
456   s.args().append("block_shape", tbl()->lookup(node->block_shape()));
457   s.args().append("crops", tbl()->lookup(node->crops()));
458
459   s.state(locop::NodeSummary::State::Complete);
460
461   return true;
462 }
463
464 bool CircleNodeSummaryBuilder::summary(const luci::CircleCast *node, locop::NodeSummary &s) const
465 {
466   s.args().append("x", tbl()->lookup(node->x()));
467   s.args().append("in_data_type", to_str(node->in_data_type()));
468   s.args().append("out_data_type", to_str(node->out_data_type()));
469   s.state(locop::NodeSummary::State::Complete);
470   return true;
471 }
472
473 bool CircleNodeSummaryBuilder::summary(const luci::CircleCeil *node, locop::NodeSummary &s) const
474 {
475   return use_x(tbl(), node, s);
476 }
477
478 bool CircleNodeSummaryBuilder::summary(const luci::CircleConcatenation *node,
479                                        locop::NodeSummary &s) const
480 {
481   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
482
483   for (uint32_t i = 0; i < node->numValues(); ++i)
484     s.args().append("values", tbl()->lookup(node->values(i)));
485   s.args().append("axis", pepper::str(node->axis()));
486   s.args().append("fused", to_str(node->fusedActivationFunction()));
487   s.state(locop::NodeSummary::State::Complete);
488   return true;
489 }
490
491 bool CircleNodeSummaryBuilder::summary(const luci::CircleConst *, locop::NodeSummary &s) const
492 {
493   s.state(locop::NodeSummary::State::PartiallyKnown);
494   return true;
495 }
496
497 bool CircleNodeSummaryBuilder::summary(const luci::CircleConv2D *node, locop::NodeSummary &s) const
498 {
499   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
500   assert(node->padding() != luci::Padding::UNDEFINED);
501
502   s.args().append("input", tbl()->lookup(node->input()));
503   s.args().append("filter", tbl()->lookup(node->filter()));
504   s.args().append("bias", tbl()->lookup(node->bias()));
505
506   s.args().append("stride(h,w)", to_str(node->stride()));
507   s.args().append("dilation(h,w)", to_str(node->dilation()));
508
509   s.args().append("padding", to_str(node->padding()));
510   s.args().append("fused", to_str(node->fusedActivationFunction()));
511
512   s.state(locop::NodeSummary::State::Complete);
513
514   return true;
515 }
516
517 bool CircleNodeSummaryBuilder::summary(const luci::CircleCos *node, locop::NodeSummary &s) const
518 {
519   return use_x(tbl(), node, s);
520 }
521
522 bool CircleNodeSummaryBuilder::summary(const luci::CircleCustom *node, locop::NodeSummary &s) const
523 {
524   for (uint32_t i = 0; i < node->numInputs(); i++)
525   {
526     s.args().append("input" + std::to_string(i), tbl()->lookup(node->inputs(i)));
527   }
528   s.args().append("custom_code", node->custom_code());
529   s.state(locop::NodeSummary::State::Complete);
530   return true;
531 }
532
533 bool CircleNodeSummaryBuilder::summary(const luci::CircleDepthToSpace *node,
534                                        locop::NodeSummary &s) const
535 {
536   s.args().append("input", tbl()->lookup(node->input()));
537   s.args().append("block_size", std::to_string(node->block_size()));
538
539   s.state(locop::NodeSummary::State::Complete);
540
541   return true;
542 }
543
544 bool CircleNodeSummaryBuilder::summary(const luci::CircleDepthwiseConv2D *node,
545                                        locop::NodeSummary &s) const
546 {
547   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
548   assert(node->padding() != luci::Padding::UNDEFINED);
549
550   s.args().append("input", tbl()->lookup(node->input()));
551   s.args().append("filter", tbl()->lookup(node->filter()));
552   s.args().append("bias", tbl()->lookup(node->bias()));
553
554   s.args().append("stride(h,w)", to_str(node->stride()));
555   s.args().append("dilation(h,w)", to_str(node->dilation()));
556   s.args().append("padding", to_str(node->padding()));
557   s.args().append("depthMultiplier", std::to_string(node->depthMultiplier()));
558   s.args().append("fused", to_str(node->fusedActivationFunction()));
559
560   s.state(locop::NodeSummary::State::Complete);
561
562   return true;
563 }
564
565 bool CircleNodeSummaryBuilder::summary(const luci::CircleDiv *node, locop::NodeSummary &s) const
566 {
567   return use_xy(tbl(), node, s);
568 }
569
570 bool CircleNodeSummaryBuilder::summary(const luci::CircleElu *node, locop::NodeSummary &s) const
571 {
572   return use_features(tbl(), node, s);
573 }
574
575 bool CircleNodeSummaryBuilder::summary(const luci::CircleExp *node, locop::NodeSummary &s) const
576 {
577   return use_x(tbl(), node, s);
578 }
579
580 bool CircleNodeSummaryBuilder::summary(const luci::CircleExpandDims *node,
581                                        locop::NodeSummary &s) const
582 {
583   s.args().append("input", tbl()->lookup(node->input()));
584   s.args().append("axis", tbl()->lookup(node->axis()));
585   s.state(locop::NodeSummary::State::Complete);
586   return true;
587 }
588
589 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloor *node, locop::NodeSummary &s) const
590 {
591   return use_x(tbl(), node, s);
592 }
593
594 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloorDiv *node,
595                                        locop::NodeSummary &s) const
596 {
597   return use_xy(tbl(), node, s);
598 }
599
600 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloorMod *node,
601                                        locop::NodeSummary &s) const
602 {
603   return use_xy(tbl(), node, s);
604 }
605
606 bool CircleNodeSummaryBuilder::summary(const luci::CircleFill *node, locop::NodeSummary &s) const
607 {
608   s.args().append("dims", tbl()->lookup(node->dims()));
609   s.args().append("value", tbl()->lookup(node->value()));
610   s.state(locop::NodeSummary::State::Complete);
611   return true;
612 }
613
614 bool CircleNodeSummaryBuilder::summary(const luci::CircleFullyConnected *node,
615                                        locop::NodeSummary &s) const
616 {
617   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
618
619   s.args().append("input", tbl()->lookup(node->input()));
620   s.args().append("weights", tbl()->lookup(node->weights()));
621   s.args().append("bias", tbl()->lookup(node->bias()));
622   s.args().append("fused", to_str(node->fusedActivationFunction()));
623
624   s.state(locop::NodeSummary::State::Complete);
625
626   return true;
627 }
628
629 bool CircleNodeSummaryBuilder::summary(const luci::CircleGather *node, locop::NodeSummary &s) const
630 {
631   s.args().append("params", tbl()->lookup(node->params()));
632   s.args().append("indices", tbl()->lookup(node->indices()));
633   s.args().append("axis", pepper::str(node->axis()));
634
635   s.state(locop::NodeSummary::State::Complete);
636   return true;
637 }
638
639 bool CircleNodeSummaryBuilder::summary(const luci::CircleGatherNd *node,
640                                        locop::NodeSummary &s) const
641 {
642   s.args().append("params", tbl()->lookup(node->params()));
643   s.args().append("indices", tbl()->lookup(node->indices()));
644   s.state(locop::NodeSummary::State::Complete);
645   return true;
646 }
647
648 bool CircleNodeSummaryBuilder::summary(const luci::CircleGreater *node, locop::NodeSummary &s) const
649 {
650   return use_xy(tbl(), node, s);
651 }
652
653 bool CircleNodeSummaryBuilder::summary(const luci::CircleGreaterEqual *node,
654                                        locop::NodeSummary &s) const
655 {
656   return use_xy(tbl(), node, s);
657 }
658
659 bool CircleNodeSummaryBuilder::summary(const luci::CircleIf *node, locop::NodeSummary &s) const
660 {
661   s.args().append("cond", tbl()->lookup(node->cond()));
662   for (uint32_t i = 0; i < node->input_count(); ++i)
663     s.args().append("input", tbl()->lookup(node->input(i)));
664
665   if (node->then_graph() != nullptr)
666     s.args().append("then_graph", node->then_graph()->name());
667   else
668     s.args().append("then_branch", pepper::str(node->then_branch()));
669
670   if (node->else_graph() != nullptr)
671     s.args().append("else_graph", node->else_graph()->name());
672   else
673     s.args().append("else_branch", pepper::str(node->else_branch()));
674
675   s.state(locop::NodeSummary::State::Complete);
676
677   return true;
678 }
679
680 bool CircleNodeSummaryBuilder::summary(const luci::CircleL2Normalize *node,
681                                        locop::NodeSummary &s) const
682 {
683   s.args().append("x", tbl()->lookup(node->x()));
684   s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
685   s.state(locop::NodeSummary::State::Complete);
686   return true;
687 }
688
689 bool CircleNodeSummaryBuilder::summary(const luci::CircleLess *node, locop::NodeSummary &s) const
690 {
691   return use_xy(tbl(), node, s);
692 }
693
694 bool CircleNodeSummaryBuilder::summary(const luci::CircleLessEqual *node,
695                                        locop::NodeSummary &s) const
696 {
697   return use_xy(tbl(), node, s);
698 }
699
700 bool CircleNodeSummaryBuilder::summary(const luci::CircleLeakyRelu *node,
701                                        locop::NodeSummary &s) const
702 {
703   s.args().append("features", tbl()->lookup(node->features()));
704   s.args().append("alpha", std::to_string(node->alpha()));
705   s.state(locop::NodeSummary::State::Complete);
706   return true;
707 }
708
709 bool CircleNodeSummaryBuilder::summary(const luci::CircleLocalResponseNormalization *node,
710                                        locop::NodeSummary &s) const
711 {
712   s.args().append("input", tbl()->lookup(node->input()));
713   s.args().append("radius", pepper::str(node->radius()));
714   s.args().append("bias", pepper::str(node->bias()));
715   s.args().append("alpha", pepper::str(node->alpha()));
716   s.args().append("beta", pepper::str(node->beta()));
717   s.state(locop::NodeSummary::State::Complete);
718   return true;
719 }
720
721 bool CircleNodeSummaryBuilder::summary(const luci::CircleLog *node, locop::NodeSummary &s) const
722 {
723   return use_x(tbl(), node, s);
724 }
725
726 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalAnd *node,
727                                        locop::NodeSummary &s) const
728 {
729   return use_xy(tbl(), node, s);
730 }
731
732 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalNot *node,
733                                        locop::NodeSummary &s) const
734 {
735   return use_x(tbl(), node, s);
736 }
737
738 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalOr *node,
739                                        locop::NodeSummary &s) const
740 {
741   return use_xy(tbl(), node, s);
742 }
743
744 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogistic *node,
745                                        locop::NodeSummary &s) const
746 {
747   return use_x(tbl(), node, s);
748 }
749
750 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogSoftmax *node,
751                                        locop::NodeSummary &s) const
752 {
753   s.args().append("logits", tbl()->lookup(node->logits()));
754   s.state(locop::NodeSummary::State::Complete);
755   return true;
756 }
757
758 bool CircleNodeSummaryBuilder::summary(const luci::CircleMatrixDiag *node,
759                                        locop::NodeSummary &s) const
760 {
761   s.args().append("diagonal", tbl()->lookup(node->diagonal()));
762   s.state(locop::NodeSummary::State::Complete);
763   return true;
764 }
765
766 bool CircleNodeSummaryBuilder::summary(const luci::CircleMatrixSetDiag *node,
767                                        locop::NodeSummary &s) const
768 {
769   s.args().append("input", tbl()->lookup(node->input()));
770   s.args().append("diagonal", tbl()->lookup(node->diagonal()));
771   s.state(locop::NodeSummary::State::Complete);
772   return true;
773 }
774
775 bool CircleNodeSummaryBuilder::summary(const luci::CircleMaximum *node, locop::NodeSummary &s) const
776 {
777   return use_xy(tbl(), node, s);
778 }
779
780 bool CircleNodeSummaryBuilder::summary(const luci::CircleMaxPool2D *node,
781                                        locop::NodeSummary &s) const
782 {
783   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
784
785   s.args().append("value", tbl()->lookup(node->value()));
786   s.args().append("filter(h,w)", to_str(node->filter()));
787   s.args().append("stride(h,w)", to_str(node->stride()));
788   s.args().append("padding", to_str(node->padding()));
789   s.args().append("fused", to_str(node->fusedActivationFunction()));
790
791   s.state(locop::NodeSummary::State::Complete);
792
793   return true;
794 }
795
796 bool CircleNodeSummaryBuilder::summary(const luci::CircleMean *node, locop::NodeSummary &s) const
797 {
798   return use_reducer(tbl(), node, s);
799 }
800
801 bool CircleNodeSummaryBuilder::summary(const luci::CircleMinimum *node, locop::NodeSummary &s) const
802 {
803   return use_xy(tbl(), node, s);
804 }
805
806 bool CircleNodeSummaryBuilder::summary(const luci::CircleMirrorPad *node,
807                                        locop::NodeSummary &s) const
808 {
809   s.args().append("input", tbl()->lookup(node->input()));
810   s.args().append("paddings", tbl()->lookup(node->paddings()));
811   s.args().append("mode", to_str(node->mode()));
812   s.state(locop::NodeSummary::State::Complete);
813   return true;
814 }
815
816 bool CircleNodeSummaryBuilder::summary(const luci::CircleMul *node, locop::NodeSummary &s) const
817 {
818   return use_xy_act(tbl(), node, s);
819 }
820
821 bool CircleNodeSummaryBuilder::summary(const luci::CircleNeg *node, locop::NodeSummary &s) const
822 {
823   return use_x(tbl(), node, s);
824 }
825
826 bool CircleNodeSummaryBuilder::summary(const luci::CircleNotEqual *node,
827                                        locop::NodeSummary &s) const
828 {
829   return use_xy(tbl(), node, s);
830 }
831
832 bool CircleNodeSummaryBuilder::summary(const luci::CircleOneHot *node, locop::NodeSummary &s) const
833 {
834   s.args().append("indices", tbl()->lookup(node->indices()));
835   s.args().append("depth", tbl()->lookup(node->depth()));
836   s.args().append("on_value", tbl()->lookup(node->on_value()));
837   s.args().append("off_value", tbl()->lookup(node->off_value()));
838   s.args().append("axis", pepper::str(node->axis()));
839
840   s.state(locop::NodeSummary::State::Complete);
841   return true;
842 }
843
844 bool CircleNodeSummaryBuilder::summary(const luci::CirclePack *node, locop::NodeSummary &s) const
845 {
846   for (uint32_t i = 0; i < node->values_count(); ++i)
847     s.args().append("values", tbl()->lookup(node->values(i)));
848   s.args().append("values_count", pepper::str(node->values_count()));
849   s.args().append("axis", pepper::str(node->axis()));
850   s.state(locop::NodeSummary::State::Complete);
851   return true;
852 }
853
854 bool CircleNodeSummaryBuilder::summary(const luci::CirclePad *node, locop::NodeSummary &s) const
855 {
856   s.args().append("input", tbl()->lookup(node->input()));
857   s.args().append("paddings", tbl()->lookup(node->paddings()));
858   s.state(locop::NodeSummary::State::Complete);
859   return true;
860 }
861
862 bool CircleNodeSummaryBuilder::summary(const luci::CirclePow *node, locop::NodeSummary &s) const
863 {
864   return use_xy(tbl(), node, s);
865 }
866
867 bool CircleNodeSummaryBuilder::summary(const luci::CirclePRelu *node, locop::NodeSummary &s) const
868 {
869   s.args().append("input", tbl()->lookup(node->input()));
870   s.args().append("alpha", tbl()->lookup(node->alpha()));
871   s.state(locop::NodeSummary::State::Complete);
872   return true;
873 }
874
875 bool CircleNodeSummaryBuilder::summary(const luci::CircleRange *node, locop::NodeSummary &s) const
876 {
877   s.args().append("start", tbl()->lookup(node->start()));
878   s.args().append("limit", tbl()->lookup(node->limit()));
879   s.args().append("delta", tbl()->lookup(node->delta()));
880
881   s.state(locop::NodeSummary::State::Complete);
882   return true;
883 }
884
885 bool CircleNodeSummaryBuilder::summary(const luci::CircleRank *node, locop::NodeSummary &s) const
886 {
887   return use_input(tbl(), node, s);
888 }
889
890 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceAny *node,
891                                        locop::NodeSummary &s) const
892 {
893   return use_reducer(tbl(), node, s);
894 }
895
896 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceMax *node,
897                                        locop::NodeSummary &s) const
898 {
899   return use_reducer(tbl(), node, s);
900 }
901
902 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceMin *node,
903                                        locop::NodeSummary &s) const
904 {
905   return use_reducer(tbl(), node, s);
906 }
907
908 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceProd *node,
909                                        locop::NodeSummary &s) const
910 {
911   return use_reducer(tbl(), node, s);
912 }
913
914 bool CircleNodeSummaryBuilder::summary(const luci::CircleRelu *node, locop::NodeSummary &s) const
915 {
916   return use_features(tbl(), node, s);
917 }
918
919 bool CircleNodeSummaryBuilder::summary(const luci::CircleRelu6 *node, locop::NodeSummary &s) const
920 {
921   return use_features(tbl(), node, s);
922 }
923
924 bool CircleNodeSummaryBuilder::summary(const luci::CircleReluN1To1 *node,
925                                        locop::NodeSummary &s) const
926 {
927   return use_features(tbl(), node, s);
928 }
929
930 bool CircleNodeSummaryBuilder::summary(const luci::CircleReshape *node, locop::NodeSummary &s) const
931 {
932   s.args().append("tensor", tbl()->lookup(node->tensor()));
933   s.args().append("shape", tbl()->lookup(node->shape()));
934   // TODO Show newShape info
935   s.state(locop::NodeSummary::State::PartiallyKnown);
936   return true;
937 }
938
939 bool CircleNodeSummaryBuilder::summary(const luci::CircleResizeBilinear *node,
940                                        locop::NodeSummary &s) const
941 {
942   s.args().append("input", tbl()->lookup(node->input()));
943   s.args().append("size", tbl()->lookup(node->size()));
944   s.args().append("align_corners", node->align_corners() ? "true" : "false");
945   s.args().append("half_pixel_centers", node->half_pixel_centers() ? "true" : "false");
946   s.state(locop::NodeSummary::State::Complete);
947   return true;
948 }
949
950 bool CircleNodeSummaryBuilder::summary(const luci::CircleResizeNearestNeighbor *node,
951                                        locop::NodeSummary &s) const
952 {
953   s.args().append("input", tbl()->lookup(node->input()));
954   s.args().append("size", tbl()->lookup(node->size()));
955   s.args().append("align_corners", node->align_corners() ? "true" : "false");
956   s.state(locop::NodeSummary::State::Complete);
957   return true;
958 }
959
960 bool CircleNodeSummaryBuilder::summary(const luci::CircleReverseSequence *node,
961                                        locop::NodeSummary &s) const
962 {
963   s.args().append("input", tbl()->lookup(node->input()));
964   s.args().append("seq_lengths", tbl()->lookup(node->seq_lengths()));
965   s.args().append("seq_axis", std::to_string(node->seq_axis()));
966   s.args().append("batch_axis", std::to_string(node->batch_axis()));
967   s.state(locop::NodeSummary::State::Complete);
968   return true;
969 }
970
971 bool CircleNodeSummaryBuilder::summary(const luci::CircleReverseV2 *node,
972                                        locop::NodeSummary &s) const
973 {
974   s.args().append("tensor", tbl()->lookup(node->tensor()));
975   s.args().append("axis", tbl()->lookup(node->axis()));
976   s.state(locop::NodeSummary::State::Complete);
977   return true;
978 }
979
980 bool CircleNodeSummaryBuilder::summary(const luci::CircleRound *node, locop::NodeSummary &s) const
981 {
982   return use_x(tbl(), node, s);
983 }
984
985 bool CircleNodeSummaryBuilder::summary(const luci::CircleRsqrt *node, locop::NodeSummary &s) const
986 {
987   return use_x(tbl(), node, s);
988 }
989
990 bool CircleNodeSummaryBuilder::summary(const luci::CircleScatterNd *node,
991                                        locop::NodeSummary &s) const
992 {
993   s.args().append("indices", tbl()->lookup(node->indices()));
994   s.args().append("updates", tbl()->lookup(node->updates()));
995   s.args().append("shape", tbl()->lookup(node->shape()));
996   s.state(locop::NodeSummary::State::Complete);
997   return true;
998 }
999
1000 bool CircleNodeSummaryBuilder::summary(const luci::CircleSegmentSum *node,
1001                                        locop::NodeSummary &s) const
1002 {
1003   s.args().append("input", tbl()->lookup(node->input()));
1004   s.args().append("segment_ids", tbl()->lookup(node->segment_ids()));
1005   s.state(locop::NodeSummary::State::Complete);
1006   return true;
1007 }
1008
1009 bool CircleNodeSummaryBuilder::summary(const luci::CircleSelect *node, locop::NodeSummary &s) const
1010 {
1011   s.args().append("condition", tbl()->lookup(node->condition()));
1012   s.args().append("t", tbl()->lookup(node->t()));
1013   s.args().append("e", tbl()->lookup(node->e()));
1014   s.state(locop::NodeSummary::State::Complete);
1015   return true;
1016 }
1017
1018 bool CircleNodeSummaryBuilder::summary(const luci::CircleSelectV2 *node,
1019                                        locop::NodeSummary &s) const
1020 {
1021   s.args().append("condition", tbl()->lookup(node->condition()));
1022   s.args().append("t", tbl()->lookup(node->t()));
1023   s.args().append("e", tbl()->lookup(node->e()));
1024   s.state(locop::NodeSummary::State::Complete);
1025   return true;
1026 }
1027
1028 bool CircleNodeSummaryBuilder::summary(const luci::CircleShape *node, locop::NodeSummary &s) const
1029 {
1030   s.args().append("input", tbl()->lookup(node->input()));
1031   s.args().append("out_type", to_str(node->out_type()));
1032   s.state(locop::NodeSummary::State::Complete);
1033   return true;
1034 }
1035
1036 bool CircleNodeSummaryBuilder::summary(const luci::CircleSin *node, locop::NodeSummary &s) const
1037 {
1038   return use_x(tbl(), node, s);
1039 }
1040
1041 bool CircleNodeSummaryBuilder::summary(const luci::CircleSlice *node, locop::NodeSummary &s) const
1042 {
1043   s.args().append("input", tbl()->lookup(node->input()));
1044   s.args().append("begin", tbl()->lookup(node->begin()));
1045   s.args().append("size", tbl()->lookup(node->size()));
1046   s.state(locop::NodeSummary::State::Complete);
1047   return true;
1048 }
1049
1050 bool CircleNodeSummaryBuilder::summary(const luci::CircleSoftmax *node, locop::NodeSummary &s) const
1051 {
1052   s.args().append("logits", tbl()->lookup(node->logits()));
1053   s.args().append("beta", pepper::str(node->beta()));
1054   s.state(locop::NodeSummary::State::Complete);
1055   return true;
1056 }
1057
1058 bool CircleNodeSummaryBuilder::summary(const luci::CircleSpaceToBatchND *node,
1059                                        locop::NodeSummary &s) const
1060 {
1061   s.args().append("input", tbl()->lookup(node->input()));
1062   s.args().append("block_shape", tbl()->lookup(node->block_shape()));
1063   s.args().append("paddings", tbl()->lookup(node->paddings()));
1064
1065   s.state(locop::NodeSummary::State::Complete);
1066
1067   return true;
1068 }
1069
1070 bool CircleNodeSummaryBuilder::summary(const luci::CircleSpaceToDepth *node,
1071                                        locop::NodeSummary &s) const
1072 {
1073   s.args().append("input", tbl()->lookup(node->input()));
1074   s.args().append("block_size", pepper::str(node->block_size()));
1075
1076   s.state(locop::NodeSummary::State::Complete);
1077
1078   return true;
1079 }
1080
1081 bool CircleNodeSummaryBuilder::summary(const luci::CircleSparseToDense *node,
1082                                        locop::NodeSummary &s) const
1083 {
1084   s.args().append("indices", tbl()->lookup(node->indices()));
1085   s.args().append("output_shape", tbl()->lookup(node->output_shape()));
1086   s.args().append("values", tbl()->lookup(node->values()));
1087   s.args().append("default_value", tbl()->lookup(node->default_value()));
1088
1089   s.args().append("Validate_indices", pepper::str(node->validate_indices()));
1090
1091   s.state(locop::NodeSummary::State::Complete);
1092
1093   return true;
1094 }
1095
1096 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplit *node, locop::NodeSummary &s) const
1097 {
1098   s.args().append("split_dim", tbl()->lookup(node->split_dim()));
1099   s.args().append("input", tbl()->lookup(node->input()));
1100
1101   s.args().append("num_split", pepper::str(node->num_split()));
1102
1103   s.state(locop::NodeSummary::State::Complete);
1104
1105   return true;
1106 }
1107
1108 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitV *node, locop::NodeSummary &s) const
1109 {
1110   s.args().append("input", tbl()->lookup(node->input()));
1111   s.args().append("size_splits", tbl()->lookup(node->size_splits()));
1112   s.args().append("split_dim", tbl()->lookup(node->split_dim()));
1113
1114   s.args().append("num_split", pepper::str(node->num_split()));
1115
1116   s.state(locop::NodeSummary::State::Complete);
1117
1118   return true;
1119 }
1120
1121 bool CircleNodeSummaryBuilder::summary(const luci::CircleSqrt *node, locop::NodeSummary &s) const
1122 {
1123   return use_x(tbl(), node, s);
1124 }
1125
1126 bool CircleNodeSummaryBuilder::summary(const luci::CircleSquare *node, locop::NodeSummary &s) const
1127 {
1128   return use_x(tbl(), node, s);
1129 }
1130
1131 bool CircleNodeSummaryBuilder::summary(const luci::CircleSquaredDifference *node,
1132                                        locop::NodeSummary &s) const
1133 {
1134   return use_xy(tbl(), node, s);
1135 }
1136
1137 bool CircleNodeSummaryBuilder::summary(const luci::CircleSqueeze *node, locop::NodeSummary &s) const
1138 {
1139   s.args().append("input", tbl()->lookup(node->input()));
1140
1141   std::stringstream ss{"("};
1142   for (size_t i = 0; i < node->squeeze_dims().size(); ++i)
1143   {
1144     if (i != 0)
1145       ss << ", ";
1146     ss << node->squeeze_dims()[i];
1147   }
1148   ss << ")";
1149
1150   s.args().append("squeeze_dims", ss.str());
1151   s.state(locop::NodeSummary::State::Complete);
1152   return true;
1153 }
1154
1155 bool CircleNodeSummaryBuilder::summary(const luci::CircleStridedSlice *node,
1156                                        locop::NodeSummary &s) const
1157 {
1158   s.args().append("input", tbl()->lookup(node->input()));
1159   s.args().append("begin", tbl()->lookup(node->begin()));
1160   s.args().append("end", tbl()->lookup(node->end()));
1161   s.args().append("strides", tbl()->lookup(node->strides()));
1162
1163   s.args().append("begin_mask", pepper::str(node->begin_mask()));
1164   s.args().append("end_mask", pepper::str(node->end_mask()));
1165   s.args().append("ellipsis_mask", pepper::str(node->ellipsis_mask()));
1166   s.args().append("new_axis_mask", pepper::str(node->new_axis_mask()));
1167   s.args().append("shrink_axis_mask", pepper::str(node->shrink_axis_mask()));
1168
1169   s.state(locop::NodeSummary::State::Complete);
1170   return true;
1171 }
1172
1173 bool CircleNodeSummaryBuilder::summary(const luci::CircleSub *node, locop::NodeSummary &s) const
1174 {
1175   return use_xy(tbl(), node, s);
1176 }
1177
1178 bool CircleNodeSummaryBuilder::summary(const luci::CircleSum *node, locop::NodeSummary &s) const
1179 {
1180   return use_reducer(tbl(), node, s);
1181 }
1182
1183 bool CircleNodeSummaryBuilder::summary(const luci::CircleTanh *node, locop::NodeSummary &s) const
1184 {
1185   return use_x(tbl(), node, s);
1186 }
1187
1188 bool CircleNodeSummaryBuilder::summary(const luci::CircleTile *node, locop::NodeSummary &s) const
1189 {
1190   s.args().append("input", tbl()->lookup(node->input()));
1191   s.args().append("multiples", tbl()->lookup(node->multiples()));
1192   s.state(locop::NodeSummary::State::Complete);
1193   return true;
1194 }
1195
1196 bool CircleNodeSummaryBuilder::summary(const luci::CircleTopKV2 *node, locop::NodeSummary &s) const
1197 {
1198   s.args().append("input", tbl()->lookup(node->input()));
1199   s.args().append("k", tbl()->lookup(node->k()));
1200   s.state(locop::NodeSummary::State::Complete);
1201   return true;
1202 }
1203
1204 bool CircleNodeSummaryBuilder::summary(const luci::CircleTranspose *node,
1205                                        locop::NodeSummary &s) const
1206 {
1207   s.args().append("a", tbl()->lookup(node->a()));
1208   s.args().append("perm", tbl()->lookup(node->perm()));
1209   s.state(locop::NodeSummary::State::Complete);
1210   return true;
1211 }
1212
1213 bool CircleNodeSummaryBuilder::summary(const luci::CircleTransposeConv *node,
1214                                        locop::NodeSummary &s) const
1215 {
1216   assert(node->padding() != luci::Padding::UNDEFINED);
1217
1218   s.args().append("inputSizes", tbl()->lookup(node->inputSizes()));
1219   s.args().append("filter", tbl()->lookup(node->filter()));
1220   s.args().append("outBackprop", tbl()->lookup(node->outBackprop()));
1221
1222   s.args().append("stride(h,w)", to_str(node->stride()));
1223   s.args().append("padding", to_str(node->padding()));
1224
1225   s.state(locop::NodeSummary::State::Complete);
1226
1227   return true;
1228 }
1229
1230 bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpack *node, locop::NodeSummary &s) const
1231 {
1232   s.args().append("value", tbl()->lookup(node->value()));
1233
1234   s.args().append("num", pepper::str(node->num()));
1235   s.args().append("axis", pepper::str(node->axis()));
1236
1237   s.state(locop::NodeSummary::State::Complete);
1238
1239   return true;
1240 }
1241
1242 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhere *node, locop::NodeSummary &s) const
1243 {
1244   s.args().append("condition", tbl()->lookup(node->condition()));
1245   s.state(locop::NodeSummary::State::Complete);
1246
1247   return true;
1248 }
1249
1250 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhile *node, locop::NodeSummary &s) const
1251 {
1252   for (uint32_t i = 0; i < node->input_count(); ++i)
1253     s.args().append("input", tbl()->lookup(node->input(i)));
1254
1255   if (node->cond_graph() != nullptr)
1256     s.args().append("cond_graph", node->cond_graph()->name());
1257   else
1258     s.args().append("cond_branch", pepper::str(node->cond_branch()));
1259
1260   if (node->body_graph() != nullptr)
1261     s.args().append("body_graph", node->body_graph()->name());
1262   else
1263     s.args().append("body_branch", pepper::str(node->body_branch()));
1264
1265   s.state(locop::NodeSummary::State::Complete);
1266
1267   return true;
1268 }
1269
1270 bool CircleNodeSummaryBuilder::summary(const luci::CircleZerosLike *node,
1271                                        locop::NodeSummary &s) const
1272 {
1273   return use_input(tbl(), node, s);
1274 }
1275
1276 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitOut *node,
1277                                        locop::NodeSummary &s) const
1278 {
1279   return use_input(tbl(), node, s);
1280 }
1281
1282 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitVOut *node,
1283                                        locop::NodeSummary &s) const
1284 {
1285   return use_input(tbl(), node, s);
1286 }
1287
1288 bool CircleNodeSummaryBuilder::summary(const luci::CircleTopKV2Out *node,
1289                                        locop::NodeSummary &s) const
1290 {
1291   s.args().append("topkv2", tbl()->lookup(node->input()));
1292   s.state(locop::NodeSummary::State::Complete);
1293   return true;
1294 }
1295
1296 bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpackOut *node,
1297                                        locop::NodeSummary &s) const
1298 {
1299   s.args().append("unpack", tbl()->lookup(node->input()));
1300
1301   s.state(locop::NodeSummary::State::Complete);
1302
1303   return true;
1304 }
1305
1306 bool CircleNodeSummaryBuilder::summary(const luci::CircleIfOut *node, locop::NodeSummary &s) const
1307 {
1308   return use_input(tbl(), node, s);
1309 }
1310
1311 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhileOut *node,
1312                                        locop::NodeSummary &s) const
1313 {
1314   s.args().append("while", tbl()->lookup(node->input()));
1315
1316   s.state(locop::NodeSummary::State::Complete);
1317
1318   return true;
1319 }
1320
1321 bool CircleNodeSummaryBuilder::summary(const luci::CircleInput *, locop::NodeSummary &s) const
1322 {
1323   s.state(locop::NodeSummary::State::Complete);
1324   return true;
1325 }
1326
1327 bool CircleNodeSummaryBuilder::summary(const luci::CircleOutput *node, locop::NodeSummary &s) const
1328 {
1329   s.args().append("from", tbl()->lookup(node->from()));
1330
1331   s.state(locop::NodeSummary::State::Complete);
1332   return true;
1333 }
1334
1335 bool CircleNodeSummaryBuilder::summary(const luci::CircleBCQFullyConnected *node,
1336                                        locop::NodeSummary &s) const
1337 {
1338   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
1339
1340   s.args().append("input", tbl()->lookup(node->input()));
1341   s.args().append("weights_scales", tbl()->lookup(node->weights_scales()));
1342   s.args().append("weights_binary", tbl()->lookup(node->weights_binary()));
1343   s.args().append("bias", tbl()->lookup(node->bias()));
1344   s.args().append("weights_clusters", tbl()->lookup(node->weights_clusters()));
1345
1346   s.args().append("fused", to_str(node->fusedActivationFunction()));
1347   s.args().append("weights_hidden_size", pepper::str(node->weights_hidden_size()));
1348
1349   s.state(locop::NodeSummary::State::Complete);
1350
1351   return true;
1352 }
1353
1354 bool CircleNodeSummaryBuilder::summary(const luci::CircleBCQGather *node,
1355                                        locop::NodeSummary &s) const
1356 {
1357   s.args().append("input_scales", tbl()->lookup(node->input_scales()));
1358   s.args().append("input_binary", tbl()->lookup(node->input_binary()));
1359   s.args().append("indices", tbl()->lookup(node->indices()));
1360   s.args().append("input_clusters", tbl()->lookup(node->input_clusters()));
1361
1362   s.args().append("axis", pepper::str(node->axis()));
1363   s.args().append("input_hidden_size", pepper::str(node->input_hidden_size()));
1364
1365   s.state(locop::NodeSummary::State::Complete);
1366   return true;
1367 }
1368
1369 bool CircleNodeSummaryBuilder::summary(const luci::CircleInstanceNorm *node,
1370                                        locop::NodeSummary &s) const
1371 {
1372   auto fused = node->fusedActivationFunction();
1373   assert(fused != luci::FusedActFunc::UNDEFINED);
1374
1375   s.args().append("input", tbl()->lookup(node->input()));
1376   s.args().append("gamma", tbl()->lookup(node->gamma()));
1377   s.args().append("beta", tbl()->lookup(node->beta()));
1378   s.args().append("epsilon", pepper::str(node->epsilon()));
1379   s.args().append("fused_activation_function", to_str(fused));
1380
1381   s.state(locop::NodeSummary::State::Complete);
1382
1383   return true;
1384 }
1385
1386 } // namespace
1387
1388 namespace luci
1389 {
1390
1391 bool NodeSummaryBuilder::build(const loco::Node *node, locop::NodeSummary &s) const
1392 {
1393   if (locop::CanonicalNodeSummaryBuilder(_tbl).build(node, s))
1394   {
1395     return true;
1396   }
1397
1398   if (CircleNodeSummaryBuilder(_tbl).build(node, s))
1399   {
1400     return true;
1401   }
1402
1403   return false;
1404 }
1405
1406 } // namespace luci