f04a418efad5ed916e23ec06e9f60206037bc478
[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::CircleNonMaxSuppressionV4)
248   IMPLEMENT(luci::CircleNotEqual)
249   IMPLEMENT(luci::CircleOneHot)
250   IMPLEMENT(luci::CirclePack)
251   IMPLEMENT(luci::CirclePad)
252   IMPLEMENT(luci::CirclePow)
253   IMPLEMENT(luci::CirclePRelu)
254   IMPLEMENT(luci::CircleRange)
255   IMPLEMENT(luci::CircleRank)
256   IMPLEMENT(luci::CircleReduceAny)
257   IMPLEMENT(luci::CircleReduceMax)
258   IMPLEMENT(luci::CircleReduceMin)
259   IMPLEMENT(luci::CircleReduceProd)
260   IMPLEMENT(luci::CircleRelu)
261   IMPLEMENT(luci::CircleRelu6)
262   IMPLEMENT(luci::CircleReluN1To1)
263   IMPLEMENT(luci::CircleReshape)
264   IMPLEMENT(luci::CircleResizeBilinear)
265   IMPLEMENT(luci::CircleResizeNearestNeighbor)
266   IMPLEMENT(luci::CircleReverseSequence)
267   IMPLEMENT(luci::CircleReverseV2)
268   IMPLEMENT(luci::CircleRound)
269   IMPLEMENT(luci::CircleRsqrt)
270   IMPLEMENT(luci::CircleScatterNd)
271   IMPLEMENT(luci::CircleSegmentSum)
272   IMPLEMENT(luci::CircleSelect)
273   IMPLEMENT(luci::CircleSelectV2)
274   IMPLEMENT(luci::CircleShape)
275   IMPLEMENT(luci::CircleSin)
276   IMPLEMENT(luci::CircleSlice)
277   IMPLEMENT(luci::CircleSoftmax)
278   IMPLEMENT(luci::CircleSpaceToBatchND)
279   IMPLEMENT(luci::CircleSpaceToDepth)
280   IMPLEMENT(luci::CircleSparseToDense)
281   IMPLEMENT(luci::CircleSplit)
282   IMPLEMENT(luci::CircleSplitV)
283   IMPLEMENT(luci::CircleSqrt)
284   IMPLEMENT(luci::CircleSquare)
285   IMPLEMENT(luci::CircleSquaredDifference)
286   IMPLEMENT(luci::CircleSqueeze)
287   IMPLEMENT(luci::CircleStridedSlice)
288   IMPLEMENT(luci::CircleSub)
289   IMPLEMENT(luci::CircleSum)
290   IMPLEMENT(luci::CircleTanh)
291   IMPLEMENT(luci::CircleTile)
292   IMPLEMENT(luci::CircleTopKV2)
293   IMPLEMENT(luci::CircleTranspose)
294   IMPLEMENT(luci::CircleTransposeConv)
295   IMPLEMENT(luci::CircleUnique)
296   IMPLEMENT(luci::CircleUnpack)
297   IMPLEMENT(luci::CircleWhere)
298   IMPLEMENT(luci::CircleWhile)
299   IMPLEMENT(luci::CircleZerosLike)
300   // Circle Only
301   IMPLEMENT(luci::CircleBCQFullyConnected)
302   IMPLEMENT(luci::CircleBCQGather)
303   IMPLEMENT(luci::CircleInstanceNorm)
304   // Virtual nodes
305   IMPLEMENT(luci::CircleInput)
306   IMPLEMENT(luci::CircleOutput)
307   IMPLEMENT(luci::CircleIfOut)
308   IMPLEMENT(luci::CircleNonMaxSuppressionV4Out)
309   IMPLEMENT(luci::CircleSplitOut)
310   IMPLEMENT(luci::CircleSplitVOut)
311   IMPLEMENT(luci::CircleTopKV2Out)
312   IMPLEMENT(luci::CircleUniqueOut)
313   IMPLEMENT(luci::CircleUnpackOut)
314   IMPLEMENT(luci::CircleWhileOut)
315 #undef IMPLEMENT
316 };
317
318 template <class CIRCLENODE>
319 bool use_x(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
320 {
321   s.args().append("x", tbl->lookup(node->x()));
322   s.state(locop::NodeSummary::State::Complete);
323   return true;
324 }
325
326 template <class CIRCLENODE>
327 bool use_input(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
328 {
329   s.args().append("input", tbl->lookup(node->input()));
330   s.state(locop::NodeSummary::State::Complete);
331   return true;
332 }
333
334 template <class CIRCLENODE>
335 bool use_features(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
336 {
337   s.args().append("features", tbl->lookup(node->features()));
338   s.state(locop::NodeSummary::State::Complete);
339   return true;
340 }
341
342 template <class CIRCLENODE>
343 bool use_xy(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
344 {
345   s.args().append("x", tbl->lookup(node->x()));
346   s.args().append("y", tbl->lookup(node->y()));
347   s.state(locop::NodeSummary::State::Complete);
348   return true;
349 }
350
351 template <class CIRCLENODE>
352 bool use_xy_act(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
353 {
354   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
355
356   s.args().append("x", tbl->lookup(node->x()));
357   s.args().append("y", tbl->lookup(node->y()));
358   s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
359   s.state(locop::NodeSummary::State::Complete);
360   return true;
361 }
362
363 template <class CIRCLENODE>
364 bool use_reducer(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
365 {
366   s.args().append("input", tbl->lookup(node->input()));
367   s.args().append("reduction_indices", tbl->lookup(node->reduction_indices()));
368   s.args().append("keep_dims", node->keep_dims() ? "true" : "false");
369   s.state(locop::NodeSummary::State::Complete);
370   return true;
371 }
372
373 template <class CIRCLENODE>
374 bool use_ido(const locop::SymbolTable *tbl, const CIRCLENODE *node, locop::NodeSummary &s)
375 {
376   s.args().append("input", tbl->lookup(node->input()));
377   s.args().append("dimension", tbl->lookup(node->dimension()));
378   s.args().append("output_type", to_str(node->output_type()));
379   s.state(locop::NodeSummary::State::Complete);
380   return true;
381 }
382
383 bool CircleNodeSummaryBuilderBase::build(const loco::Node *node, locop::NodeSummary &s) const
384 {
385   if (node->dialect() != luci::CircleDialect::get())
386     return false;
387
388 #define CIRCLE_NODE(OPCODE, CLASS)                        \
389   if (dynamic_cast<const CLASS *>(node))                  \
390   {                                                       \
391     s.opname(circle_opname(node->opnum()));               \
392     return summary(dynamic_cast<const CLASS *>(node), s); \
393   }
394 #include <luci/IR/CircleNodes.lst>
395 #undef CIRCLE_NODE
396
397   return false;
398 }
399
400 bool CircleNodeSummaryBuilder::summary(const luci::CircleAbs *node, locop::NodeSummary &s) const
401 {
402   return use_x(tbl(), node, s);
403 }
404
405 bool CircleNodeSummaryBuilder::summary(const luci::CircleAdd *node, locop::NodeSummary &s) const
406 {
407   return use_xy_act(tbl(), node, s);
408 }
409
410 bool CircleNodeSummaryBuilder::summary(const luci::CircleAddN *node, locop::NodeSummary &s) const
411 {
412   for (uint32_t i = 0; i < node->arity(); ++i)
413     s.args().append("inputs", tbl()->lookup(node->inputs(i)));
414
415   s.state(locop::NodeSummary::State::Complete);
416   return true;
417 }
418
419 bool CircleNodeSummaryBuilder::summary(const luci::CircleArgMax *node, locop::NodeSummary &s) const
420 {
421   return use_ido(tbl(), node, s);
422 }
423
424 bool CircleNodeSummaryBuilder::summary(const luci::CircleArgMin *node, locop::NodeSummary &s) const
425 {
426   return use_ido(tbl(), node, s);
427 }
428
429 bool CircleNodeSummaryBuilder::summary(const luci::CircleAveragePool2D *node,
430                                        locop::NodeSummary &s) const
431 {
432   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
433
434   s.args().append("value", tbl()->lookup(node->value()));
435   s.args().append("filter(h,w)", to_str(node->filter()));
436   s.args().append("stride(h,w)", to_str(node->stride()));
437   s.args().append("padding", to_str(node->padding()));
438   s.args().append("fused", to_str(node->fusedActivationFunction()));
439
440   s.state(locop::NodeSummary::State::Complete);
441
442   return true;
443 }
444
445 bool CircleNodeSummaryBuilder::summary(const luci::CircleBatchMatMul *node,
446                                        locop::NodeSummary &s) const
447 {
448   s.args().append("x", tbl()->lookup(node->x()));
449   s.args().append("y", tbl()->lookup(node->y()));
450   s.args().append("adj_x", to_str(node->adj_x()));
451   s.args().append("adj_y", to_str(node->adj_y()));
452   s.state(locop::NodeSummary::State::Complete);
453   return true;
454 }
455
456 bool CircleNodeSummaryBuilder::summary(const luci::CircleBatchToSpaceND *node,
457                                        locop::NodeSummary &s) const
458 {
459   s.args().append("input", tbl()->lookup(node->input()));
460   s.args().append("block_shape", tbl()->lookup(node->block_shape()));
461   s.args().append("crops", tbl()->lookup(node->crops()));
462
463   s.state(locop::NodeSummary::State::Complete);
464
465   return true;
466 }
467
468 bool CircleNodeSummaryBuilder::summary(const luci::CircleCast *node, locop::NodeSummary &s) const
469 {
470   s.args().append("x", tbl()->lookup(node->x()));
471   s.args().append("in_data_type", to_str(node->in_data_type()));
472   s.args().append("out_data_type", to_str(node->out_data_type()));
473   s.state(locop::NodeSummary::State::Complete);
474   return true;
475 }
476
477 bool CircleNodeSummaryBuilder::summary(const luci::CircleCeil *node, locop::NodeSummary &s) const
478 {
479   return use_x(tbl(), node, s);
480 }
481
482 bool CircleNodeSummaryBuilder::summary(const luci::CircleConcatenation *node,
483                                        locop::NodeSummary &s) const
484 {
485   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
486
487   for (uint32_t i = 0; i < node->numValues(); ++i)
488     s.args().append("values", tbl()->lookup(node->values(i)));
489   s.args().append("axis", pepper::str(node->axis()));
490   s.args().append("fused", to_str(node->fusedActivationFunction()));
491   s.state(locop::NodeSummary::State::Complete);
492   return true;
493 }
494
495 bool CircleNodeSummaryBuilder::summary(const luci::CircleConst *, locop::NodeSummary &s) const
496 {
497   s.state(locop::NodeSummary::State::PartiallyKnown);
498   return true;
499 }
500
501 bool CircleNodeSummaryBuilder::summary(const luci::CircleConv2D *node, locop::NodeSummary &s) const
502 {
503   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
504   assert(node->padding() != luci::Padding::UNDEFINED);
505
506   s.args().append("input", tbl()->lookup(node->input()));
507   s.args().append("filter", tbl()->lookup(node->filter()));
508   s.args().append("bias", tbl()->lookup(node->bias()));
509
510   s.args().append("stride(h,w)", to_str(node->stride()));
511   s.args().append("dilation(h,w)", to_str(node->dilation()));
512
513   s.args().append("padding", to_str(node->padding()));
514   s.args().append("fused", to_str(node->fusedActivationFunction()));
515
516   s.state(locop::NodeSummary::State::Complete);
517
518   return true;
519 }
520
521 bool CircleNodeSummaryBuilder::summary(const luci::CircleCos *node, locop::NodeSummary &s) const
522 {
523   return use_x(tbl(), node, s);
524 }
525
526 bool CircleNodeSummaryBuilder::summary(const luci::CircleCustom *node, locop::NodeSummary &s) const
527 {
528   for (uint32_t i = 0; i < node->numInputs(); i++)
529   {
530     s.args().append("input" + std::to_string(i), tbl()->lookup(node->inputs(i)));
531   }
532   s.args().append("custom_code", node->custom_code());
533   s.state(locop::NodeSummary::State::Complete);
534   return true;
535 }
536
537 bool CircleNodeSummaryBuilder::summary(const luci::CircleDepthToSpace *node,
538                                        locop::NodeSummary &s) const
539 {
540   s.args().append("input", tbl()->lookup(node->input()));
541   s.args().append("block_size", std::to_string(node->block_size()));
542
543   s.state(locop::NodeSummary::State::Complete);
544
545   return true;
546 }
547
548 bool CircleNodeSummaryBuilder::summary(const luci::CircleDepthwiseConv2D *node,
549                                        locop::NodeSummary &s) const
550 {
551   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
552   assert(node->padding() != luci::Padding::UNDEFINED);
553
554   s.args().append("input", tbl()->lookup(node->input()));
555   s.args().append("filter", tbl()->lookup(node->filter()));
556   s.args().append("bias", tbl()->lookup(node->bias()));
557
558   s.args().append("stride(h,w)", to_str(node->stride()));
559   s.args().append("dilation(h,w)", to_str(node->dilation()));
560   s.args().append("padding", to_str(node->padding()));
561   s.args().append("depthMultiplier", std::to_string(node->depthMultiplier()));
562   s.args().append("fused", to_str(node->fusedActivationFunction()));
563
564   s.state(locop::NodeSummary::State::Complete);
565
566   return true;
567 }
568
569 bool CircleNodeSummaryBuilder::summary(const luci::CircleDiv *node, locop::NodeSummary &s) const
570 {
571   return use_xy(tbl(), node, s);
572 }
573
574 bool CircleNodeSummaryBuilder::summary(const luci::CircleElu *node, locop::NodeSummary &s) const
575 {
576   return use_features(tbl(), node, s);
577 }
578
579 bool CircleNodeSummaryBuilder::summary(const luci::CircleExp *node, locop::NodeSummary &s) const
580 {
581   return use_x(tbl(), node, s);
582 }
583
584 bool CircleNodeSummaryBuilder::summary(const luci::CircleExpandDims *node,
585                                        locop::NodeSummary &s) const
586 {
587   s.args().append("input", tbl()->lookup(node->input()));
588   s.args().append("axis", tbl()->lookup(node->axis()));
589   s.state(locop::NodeSummary::State::Complete);
590   return true;
591 }
592
593 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloor *node, locop::NodeSummary &s) const
594 {
595   return use_x(tbl(), node, s);
596 }
597
598 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloorDiv *node,
599                                        locop::NodeSummary &s) const
600 {
601   return use_xy(tbl(), node, s);
602 }
603
604 bool CircleNodeSummaryBuilder::summary(const luci::CircleFloorMod *node,
605                                        locop::NodeSummary &s) const
606 {
607   return use_xy(tbl(), node, s);
608 }
609
610 bool CircleNodeSummaryBuilder::summary(const luci::CircleFill *node, locop::NodeSummary &s) const
611 {
612   s.args().append("dims", tbl()->lookup(node->dims()));
613   s.args().append("value", tbl()->lookup(node->value()));
614   s.state(locop::NodeSummary::State::Complete);
615   return true;
616 }
617
618 bool CircleNodeSummaryBuilder::summary(const luci::CircleFullyConnected *node,
619                                        locop::NodeSummary &s) const
620 {
621   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
622
623   s.args().append("input", tbl()->lookup(node->input()));
624   s.args().append("weights", tbl()->lookup(node->weights()));
625   s.args().append("bias", tbl()->lookup(node->bias()));
626   s.args().append("fused", to_str(node->fusedActivationFunction()));
627
628   s.state(locop::NodeSummary::State::Complete);
629
630   return true;
631 }
632
633 bool CircleNodeSummaryBuilder::summary(const luci::CircleGather *node, locop::NodeSummary &s) const
634 {
635   s.args().append("params", tbl()->lookup(node->params()));
636   s.args().append("indices", tbl()->lookup(node->indices()));
637   s.args().append("axis", pepper::str(node->axis()));
638
639   s.state(locop::NodeSummary::State::Complete);
640   return true;
641 }
642
643 bool CircleNodeSummaryBuilder::summary(const luci::CircleGatherNd *node,
644                                        locop::NodeSummary &s) const
645 {
646   s.args().append("params", tbl()->lookup(node->params()));
647   s.args().append("indices", tbl()->lookup(node->indices()));
648   s.state(locop::NodeSummary::State::Complete);
649   return true;
650 }
651
652 bool CircleNodeSummaryBuilder::summary(const luci::CircleGreater *node, locop::NodeSummary &s) const
653 {
654   return use_xy(tbl(), node, s);
655 }
656
657 bool CircleNodeSummaryBuilder::summary(const luci::CircleGreaterEqual *node,
658                                        locop::NodeSummary &s) const
659 {
660   return use_xy(tbl(), node, s);
661 }
662
663 bool CircleNodeSummaryBuilder::summary(const luci::CircleIf *node, locop::NodeSummary &s) const
664 {
665   s.args().append("cond", tbl()->lookup(node->cond()));
666   for (uint32_t i = 0; i < node->input_count(); ++i)
667     s.args().append("input", tbl()->lookup(node->input(i)));
668
669   if (node->then_graph() != nullptr)
670     s.args().append("then_graph", node->then_graph()->name());
671   else
672     s.args().append("then_branch", pepper::str(node->then_branch()));
673
674   if (node->else_graph() != nullptr)
675     s.args().append("else_graph", node->else_graph()->name());
676   else
677     s.args().append("else_branch", pepper::str(node->else_branch()));
678
679   s.state(locop::NodeSummary::State::Complete);
680
681   return true;
682 }
683
684 bool CircleNodeSummaryBuilder::summary(const luci::CircleL2Normalize *node,
685                                        locop::NodeSummary &s) const
686 {
687   s.args().append("x", tbl()->lookup(node->x()));
688   s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
689   s.state(locop::NodeSummary::State::Complete);
690   return true;
691 }
692
693 bool CircleNodeSummaryBuilder::summary(const luci::CircleLess *node, locop::NodeSummary &s) const
694 {
695   return use_xy(tbl(), node, s);
696 }
697
698 bool CircleNodeSummaryBuilder::summary(const luci::CircleLessEqual *node,
699                                        locop::NodeSummary &s) const
700 {
701   return use_xy(tbl(), node, s);
702 }
703
704 bool CircleNodeSummaryBuilder::summary(const luci::CircleLeakyRelu *node,
705                                        locop::NodeSummary &s) const
706 {
707   s.args().append("features", tbl()->lookup(node->features()));
708   s.args().append("alpha", std::to_string(node->alpha()));
709   s.state(locop::NodeSummary::State::Complete);
710   return true;
711 }
712
713 bool CircleNodeSummaryBuilder::summary(const luci::CircleLocalResponseNormalization *node,
714                                        locop::NodeSummary &s) const
715 {
716   s.args().append("input", tbl()->lookup(node->input()));
717   s.args().append("radius", pepper::str(node->radius()));
718   s.args().append("bias", pepper::str(node->bias()));
719   s.args().append("alpha", pepper::str(node->alpha()));
720   s.args().append("beta", pepper::str(node->beta()));
721   s.state(locop::NodeSummary::State::Complete);
722   return true;
723 }
724
725 bool CircleNodeSummaryBuilder::summary(const luci::CircleLog *node, locop::NodeSummary &s) const
726 {
727   return use_x(tbl(), node, s);
728 }
729
730 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalAnd *node,
731                                        locop::NodeSummary &s) const
732 {
733   return use_xy(tbl(), node, s);
734 }
735
736 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalNot *node,
737                                        locop::NodeSummary &s) const
738 {
739   return use_x(tbl(), node, s);
740 }
741
742 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogicalOr *node,
743                                        locop::NodeSummary &s) const
744 {
745   return use_xy(tbl(), node, s);
746 }
747
748 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogistic *node,
749                                        locop::NodeSummary &s) const
750 {
751   return use_x(tbl(), node, s);
752 }
753
754 bool CircleNodeSummaryBuilder::summary(const luci::CircleLogSoftmax *node,
755                                        locop::NodeSummary &s) const
756 {
757   s.args().append("logits", tbl()->lookup(node->logits()));
758   s.state(locop::NodeSummary::State::Complete);
759   return true;
760 }
761
762 bool CircleNodeSummaryBuilder::summary(const luci::CircleMatrixDiag *node,
763                                        locop::NodeSummary &s) const
764 {
765   s.args().append("diagonal", tbl()->lookup(node->diagonal()));
766   s.state(locop::NodeSummary::State::Complete);
767   return true;
768 }
769
770 bool CircleNodeSummaryBuilder::summary(const luci::CircleMatrixSetDiag *node,
771                                        locop::NodeSummary &s) const
772 {
773   s.args().append("input", tbl()->lookup(node->input()));
774   s.args().append("diagonal", tbl()->lookup(node->diagonal()));
775   s.state(locop::NodeSummary::State::Complete);
776   return true;
777 }
778
779 bool CircleNodeSummaryBuilder::summary(const luci::CircleMaximum *node, locop::NodeSummary &s) const
780 {
781   return use_xy(tbl(), node, s);
782 }
783
784 bool CircleNodeSummaryBuilder::summary(const luci::CircleMaxPool2D *node,
785                                        locop::NodeSummary &s) const
786 {
787   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
788
789   s.args().append("value", tbl()->lookup(node->value()));
790   s.args().append("filter(h,w)", to_str(node->filter()));
791   s.args().append("stride(h,w)", to_str(node->stride()));
792   s.args().append("padding", to_str(node->padding()));
793   s.args().append("fused", to_str(node->fusedActivationFunction()));
794
795   s.state(locop::NodeSummary::State::Complete);
796
797   return true;
798 }
799
800 bool CircleNodeSummaryBuilder::summary(const luci::CircleMean *node, locop::NodeSummary &s) const
801 {
802   return use_reducer(tbl(), node, s);
803 }
804
805 bool CircleNodeSummaryBuilder::summary(const luci::CircleMinimum *node, locop::NodeSummary &s) const
806 {
807   return use_xy(tbl(), node, s);
808 }
809
810 bool CircleNodeSummaryBuilder::summary(const luci::CircleMirrorPad *node,
811                                        locop::NodeSummary &s) const
812 {
813   s.args().append("input", tbl()->lookup(node->input()));
814   s.args().append("paddings", tbl()->lookup(node->paddings()));
815   s.args().append("mode", to_str(node->mode()));
816   s.state(locop::NodeSummary::State::Complete);
817   return true;
818 }
819
820 bool CircleNodeSummaryBuilder::summary(const luci::CircleMul *node, locop::NodeSummary &s) const
821 {
822   return use_xy_act(tbl(), node, s);
823 }
824
825 bool CircleNodeSummaryBuilder::summary(const luci::CircleNeg *node, locop::NodeSummary &s) const
826 {
827   return use_x(tbl(), node, s);
828 }
829
830 bool CircleNodeSummaryBuilder::summary(const luci::CircleNonMaxSuppressionV4 *node,
831                                        locop::NodeSummary &s) const
832 {
833   s.args().append("boxes", pepper::str(node->boxes()));
834   s.args().append("scores", pepper::str(node->scores()));
835   s.args().append("max_output_size", pepper::str(node->max_output_size()));
836   s.args().append("iou_threshold", pepper::str(node->iou_threshold()));
837   s.args().append("score_threshold", pepper::str(node->score_threshold()));
838
839   s.state(locop::NodeSummary::State::Complete);
840   return true;
841 }
842
843 bool CircleNodeSummaryBuilder::summary(const luci::CircleNotEqual *node,
844                                        locop::NodeSummary &s) const
845 {
846   return use_xy(tbl(), node, s);
847 }
848
849 bool CircleNodeSummaryBuilder::summary(const luci::CircleOneHot *node, locop::NodeSummary &s) const
850 {
851   s.args().append("indices", tbl()->lookup(node->indices()));
852   s.args().append("depth", tbl()->lookup(node->depth()));
853   s.args().append("on_value", tbl()->lookup(node->on_value()));
854   s.args().append("off_value", tbl()->lookup(node->off_value()));
855   s.args().append("axis", pepper::str(node->axis()));
856
857   s.state(locop::NodeSummary::State::Complete);
858   return true;
859 }
860
861 bool CircleNodeSummaryBuilder::summary(const luci::CirclePack *node, locop::NodeSummary &s) const
862 {
863   for (uint32_t i = 0; i < node->values_count(); ++i)
864     s.args().append("values", tbl()->lookup(node->values(i)));
865   s.args().append("values_count", pepper::str(node->values_count()));
866   s.args().append("axis", pepper::str(node->axis()));
867   s.state(locop::NodeSummary::State::Complete);
868   return true;
869 }
870
871 bool CircleNodeSummaryBuilder::summary(const luci::CirclePad *node, locop::NodeSummary &s) const
872 {
873   s.args().append("input", tbl()->lookup(node->input()));
874   s.args().append("paddings", tbl()->lookup(node->paddings()));
875   s.state(locop::NodeSummary::State::Complete);
876   return true;
877 }
878
879 bool CircleNodeSummaryBuilder::summary(const luci::CirclePow *node, locop::NodeSummary &s) const
880 {
881   return use_xy(tbl(), node, s);
882 }
883
884 bool CircleNodeSummaryBuilder::summary(const luci::CirclePRelu *node, locop::NodeSummary &s) const
885 {
886   s.args().append("input", tbl()->lookup(node->input()));
887   s.args().append("alpha", tbl()->lookup(node->alpha()));
888   s.state(locop::NodeSummary::State::Complete);
889   return true;
890 }
891
892 bool CircleNodeSummaryBuilder::summary(const luci::CircleRange *node, locop::NodeSummary &s) const
893 {
894   s.args().append("start", tbl()->lookup(node->start()));
895   s.args().append("limit", tbl()->lookup(node->limit()));
896   s.args().append("delta", tbl()->lookup(node->delta()));
897
898   s.state(locop::NodeSummary::State::Complete);
899   return true;
900 }
901
902 bool CircleNodeSummaryBuilder::summary(const luci::CircleRank *node, locop::NodeSummary &s) const
903 {
904   return use_input(tbl(), node, s);
905 }
906
907 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceAny *node,
908                                        locop::NodeSummary &s) const
909 {
910   return use_reducer(tbl(), node, s);
911 }
912
913 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceMax *node,
914                                        locop::NodeSummary &s) const
915 {
916   return use_reducer(tbl(), node, s);
917 }
918
919 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceMin *node,
920                                        locop::NodeSummary &s) const
921 {
922   return use_reducer(tbl(), node, s);
923 }
924
925 bool CircleNodeSummaryBuilder::summary(const luci::CircleReduceProd *node,
926                                        locop::NodeSummary &s) const
927 {
928   return use_reducer(tbl(), node, s);
929 }
930
931 bool CircleNodeSummaryBuilder::summary(const luci::CircleRelu *node, locop::NodeSummary &s) const
932 {
933   return use_features(tbl(), node, s);
934 }
935
936 bool CircleNodeSummaryBuilder::summary(const luci::CircleRelu6 *node, locop::NodeSummary &s) const
937 {
938   return use_features(tbl(), node, s);
939 }
940
941 bool CircleNodeSummaryBuilder::summary(const luci::CircleReluN1To1 *node,
942                                        locop::NodeSummary &s) const
943 {
944   return use_features(tbl(), node, s);
945 }
946
947 bool CircleNodeSummaryBuilder::summary(const luci::CircleReshape *node, locop::NodeSummary &s) const
948 {
949   s.args().append("tensor", tbl()->lookup(node->tensor()));
950   s.args().append("shape", tbl()->lookup(node->shape()));
951   // TODO Show newShape info
952   s.state(locop::NodeSummary::State::PartiallyKnown);
953   return true;
954 }
955
956 bool CircleNodeSummaryBuilder::summary(const luci::CircleResizeBilinear *node,
957                                        locop::NodeSummary &s) const
958 {
959   s.args().append("input", tbl()->lookup(node->input()));
960   s.args().append("size", tbl()->lookup(node->size()));
961   s.args().append("align_corners", node->align_corners() ? "true" : "false");
962   s.args().append("half_pixel_centers", node->half_pixel_centers() ? "true" : "false");
963   s.state(locop::NodeSummary::State::Complete);
964   return true;
965 }
966
967 bool CircleNodeSummaryBuilder::summary(const luci::CircleResizeNearestNeighbor *node,
968                                        locop::NodeSummary &s) const
969 {
970   s.args().append("input", tbl()->lookup(node->input()));
971   s.args().append("size", tbl()->lookup(node->size()));
972   s.args().append("align_corners", node->align_corners() ? "true" : "false");
973   s.state(locop::NodeSummary::State::Complete);
974   return true;
975 }
976
977 bool CircleNodeSummaryBuilder::summary(const luci::CircleReverseSequence *node,
978                                        locop::NodeSummary &s) const
979 {
980   s.args().append("input", tbl()->lookup(node->input()));
981   s.args().append("seq_lengths", tbl()->lookup(node->seq_lengths()));
982   s.args().append("seq_axis", std::to_string(node->seq_axis()));
983   s.args().append("batch_axis", std::to_string(node->batch_axis()));
984   s.state(locop::NodeSummary::State::Complete);
985   return true;
986 }
987
988 bool CircleNodeSummaryBuilder::summary(const luci::CircleReverseV2 *node,
989                                        locop::NodeSummary &s) const
990 {
991   s.args().append("tensor", tbl()->lookup(node->tensor()));
992   s.args().append("axis", tbl()->lookup(node->axis()));
993   s.state(locop::NodeSummary::State::Complete);
994   return true;
995 }
996
997 bool CircleNodeSummaryBuilder::summary(const luci::CircleRound *node, locop::NodeSummary &s) const
998 {
999   return use_x(tbl(), node, s);
1000 }
1001
1002 bool CircleNodeSummaryBuilder::summary(const luci::CircleRsqrt *node, locop::NodeSummary &s) const
1003 {
1004   return use_x(tbl(), node, s);
1005 }
1006
1007 bool CircleNodeSummaryBuilder::summary(const luci::CircleScatterNd *node,
1008                                        locop::NodeSummary &s) const
1009 {
1010   s.args().append("indices", tbl()->lookup(node->indices()));
1011   s.args().append("updates", tbl()->lookup(node->updates()));
1012   s.args().append("shape", tbl()->lookup(node->shape()));
1013   s.state(locop::NodeSummary::State::Complete);
1014   return true;
1015 }
1016
1017 bool CircleNodeSummaryBuilder::summary(const luci::CircleSegmentSum *node,
1018                                        locop::NodeSummary &s) const
1019 {
1020   s.args().append("input", tbl()->lookup(node->input()));
1021   s.args().append("segment_ids", tbl()->lookup(node->segment_ids()));
1022   s.state(locop::NodeSummary::State::Complete);
1023   return true;
1024 }
1025
1026 bool CircleNodeSummaryBuilder::summary(const luci::CircleSelect *node, locop::NodeSummary &s) const
1027 {
1028   s.args().append("condition", tbl()->lookup(node->condition()));
1029   s.args().append("t", tbl()->lookup(node->t()));
1030   s.args().append("e", tbl()->lookup(node->e()));
1031   s.state(locop::NodeSummary::State::Complete);
1032   return true;
1033 }
1034
1035 bool CircleNodeSummaryBuilder::summary(const luci::CircleSelectV2 *node,
1036                                        locop::NodeSummary &s) const
1037 {
1038   s.args().append("condition", tbl()->lookup(node->condition()));
1039   s.args().append("t", tbl()->lookup(node->t()));
1040   s.args().append("e", tbl()->lookup(node->e()));
1041   s.state(locop::NodeSummary::State::Complete);
1042   return true;
1043 }
1044
1045 bool CircleNodeSummaryBuilder::summary(const luci::CircleShape *node, locop::NodeSummary &s) const
1046 {
1047   s.args().append("input", tbl()->lookup(node->input()));
1048   s.args().append("out_type", to_str(node->out_type()));
1049   s.state(locop::NodeSummary::State::Complete);
1050   return true;
1051 }
1052
1053 bool CircleNodeSummaryBuilder::summary(const luci::CircleSin *node, locop::NodeSummary &s) const
1054 {
1055   return use_x(tbl(), node, s);
1056 }
1057
1058 bool CircleNodeSummaryBuilder::summary(const luci::CircleSlice *node, locop::NodeSummary &s) const
1059 {
1060   s.args().append("input", tbl()->lookup(node->input()));
1061   s.args().append("begin", tbl()->lookup(node->begin()));
1062   s.args().append("size", tbl()->lookup(node->size()));
1063   s.state(locop::NodeSummary::State::Complete);
1064   return true;
1065 }
1066
1067 bool CircleNodeSummaryBuilder::summary(const luci::CircleSoftmax *node, locop::NodeSummary &s) const
1068 {
1069   s.args().append("logits", tbl()->lookup(node->logits()));
1070   s.args().append("beta", pepper::str(node->beta()));
1071   s.state(locop::NodeSummary::State::Complete);
1072   return true;
1073 }
1074
1075 bool CircleNodeSummaryBuilder::summary(const luci::CircleSpaceToBatchND *node,
1076                                        locop::NodeSummary &s) const
1077 {
1078   s.args().append("input", tbl()->lookup(node->input()));
1079   s.args().append("block_shape", tbl()->lookup(node->block_shape()));
1080   s.args().append("paddings", tbl()->lookup(node->paddings()));
1081
1082   s.state(locop::NodeSummary::State::Complete);
1083
1084   return true;
1085 }
1086
1087 bool CircleNodeSummaryBuilder::summary(const luci::CircleSpaceToDepth *node,
1088                                        locop::NodeSummary &s) const
1089 {
1090   s.args().append("input", tbl()->lookup(node->input()));
1091   s.args().append("block_size", pepper::str(node->block_size()));
1092
1093   s.state(locop::NodeSummary::State::Complete);
1094
1095   return true;
1096 }
1097
1098 bool CircleNodeSummaryBuilder::summary(const luci::CircleSparseToDense *node,
1099                                        locop::NodeSummary &s) const
1100 {
1101   s.args().append("indices", tbl()->lookup(node->indices()));
1102   s.args().append("output_shape", tbl()->lookup(node->output_shape()));
1103   s.args().append("values", tbl()->lookup(node->values()));
1104   s.args().append("default_value", tbl()->lookup(node->default_value()));
1105
1106   s.args().append("Validate_indices", pepper::str(node->validate_indices()));
1107
1108   s.state(locop::NodeSummary::State::Complete);
1109
1110   return true;
1111 }
1112
1113 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplit *node, locop::NodeSummary &s) const
1114 {
1115   s.args().append("split_dim", tbl()->lookup(node->split_dim()));
1116   s.args().append("input", tbl()->lookup(node->input()));
1117
1118   s.args().append("num_split", pepper::str(node->num_split()));
1119
1120   s.state(locop::NodeSummary::State::Complete);
1121
1122   return true;
1123 }
1124
1125 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitV *node, locop::NodeSummary &s) const
1126 {
1127   s.args().append("input", tbl()->lookup(node->input()));
1128   s.args().append("size_splits", tbl()->lookup(node->size_splits()));
1129   s.args().append("split_dim", tbl()->lookup(node->split_dim()));
1130
1131   s.args().append("num_split", pepper::str(node->num_split()));
1132
1133   s.state(locop::NodeSummary::State::Complete);
1134
1135   return true;
1136 }
1137
1138 bool CircleNodeSummaryBuilder::summary(const luci::CircleSqrt *node, locop::NodeSummary &s) const
1139 {
1140   return use_x(tbl(), node, s);
1141 }
1142
1143 bool CircleNodeSummaryBuilder::summary(const luci::CircleSquare *node, locop::NodeSummary &s) const
1144 {
1145   return use_x(tbl(), node, s);
1146 }
1147
1148 bool CircleNodeSummaryBuilder::summary(const luci::CircleSquaredDifference *node,
1149                                        locop::NodeSummary &s) const
1150 {
1151   return use_xy(tbl(), node, s);
1152 }
1153
1154 bool CircleNodeSummaryBuilder::summary(const luci::CircleSqueeze *node, locop::NodeSummary &s) const
1155 {
1156   s.args().append("input", tbl()->lookup(node->input()));
1157
1158   std::stringstream ss{"("};
1159   for (size_t i = 0; i < node->squeeze_dims().size(); ++i)
1160   {
1161     if (i != 0)
1162       ss << ", ";
1163     ss << node->squeeze_dims()[i];
1164   }
1165   ss << ")";
1166
1167   s.args().append("squeeze_dims", ss.str());
1168   s.state(locop::NodeSummary::State::Complete);
1169   return true;
1170 }
1171
1172 bool CircleNodeSummaryBuilder::summary(const luci::CircleStridedSlice *node,
1173                                        locop::NodeSummary &s) const
1174 {
1175   s.args().append("input", tbl()->lookup(node->input()));
1176   s.args().append("begin", tbl()->lookup(node->begin()));
1177   s.args().append("end", tbl()->lookup(node->end()));
1178   s.args().append("strides", tbl()->lookup(node->strides()));
1179
1180   s.args().append("begin_mask", pepper::str(node->begin_mask()));
1181   s.args().append("end_mask", pepper::str(node->end_mask()));
1182   s.args().append("ellipsis_mask", pepper::str(node->ellipsis_mask()));
1183   s.args().append("new_axis_mask", pepper::str(node->new_axis_mask()));
1184   s.args().append("shrink_axis_mask", pepper::str(node->shrink_axis_mask()));
1185
1186   s.state(locop::NodeSummary::State::Complete);
1187   return true;
1188 }
1189
1190 bool CircleNodeSummaryBuilder::summary(const luci::CircleSub *node, locop::NodeSummary &s) const
1191 {
1192   return use_xy(tbl(), node, s);
1193 }
1194
1195 bool CircleNodeSummaryBuilder::summary(const luci::CircleSum *node, locop::NodeSummary &s) const
1196 {
1197   return use_reducer(tbl(), node, s);
1198 }
1199
1200 bool CircleNodeSummaryBuilder::summary(const luci::CircleTanh *node, locop::NodeSummary &s) const
1201 {
1202   return use_x(tbl(), node, s);
1203 }
1204
1205 bool CircleNodeSummaryBuilder::summary(const luci::CircleTile *node, locop::NodeSummary &s) const
1206 {
1207   s.args().append("input", tbl()->lookup(node->input()));
1208   s.args().append("multiples", tbl()->lookup(node->multiples()));
1209   s.state(locop::NodeSummary::State::Complete);
1210   return true;
1211 }
1212
1213 bool CircleNodeSummaryBuilder::summary(const luci::CircleTopKV2 *node, locop::NodeSummary &s) const
1214 {
1215   s.args().append("input", tbl()->lookup(node->input()));
1216   s.args().append("k", tbl()->lookup(node->k()));
1217   s.state(locop::NodeSummary::State::Complete);
1218   return true;
1219 }
1220
1221 bool CircleNodeSummaryBuilder::summary(const luci::CircleTranspose *node,
1222                                        locop::NodeSummary &s) const
1223 {
1224   s.args().append("a", tbl()->lookup(node->a()));
1225   s.args().append("perm", tbl()->lookup(node->perm()));
1226   s.state(locop::NodeSummary::State::Complete);
1227   return true;
1228 }
1229
1230 bool CircleNodeSummaryBuilder::summary(const luci::CircleTransposeConv *node,
1231                                        locop::NodeSummary &s) const
1232 {
1233   assert(node->padding() != luci::Padding::UNDEFINED);
1234
1235   s.args().append("inputSizes", tbl()->lookup(node->inputSizes()));
1236   s.args().append("filter", tbl()->lookup(node->filter()));
1237   s.args().append("outBackprop", tbl()->lookup(node->outBackprop()));
1238
1239   s.args().append("stride(h,w)", to_str(node->stride()));
1240   s.args().append("padding", to_str(node->padding()));
1241
1242   s.state(locop::NodeSummary::State::Complete);
1243
1244   return true;
1245 }
1246
1247 bool CircleNodeSummaryBuilder::summary(const luci::CircleUnique *node, locop::NodeSummary &s) const
1248 {
1249   s.args().append("input", tbl()->lookup(node->input()));
1250   s.args().append("idx_out_type", to_str(node->idx_out_type()));
1251   s.state(locop::NodeSummary::State::Complete);
1252   return true;
1253 }
1254
1255 bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpack *node, locop::NodeSummary &s) const
1256 {
1257   s.args().append("value", tbl()->lookup(node->value()));
1258
1259   s.args().append("num", pepper::str(node->num()));
1260   s.args().append("axis", pepper::str(node->axis()));
1261
1262   s.state(locop::NodeSummary::State::Complete);
1263
1264   return true;
1265 }
1266
1267 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhere *node, locop::NodeSummary &s) const
1268 {
1269   s.args().append("condition", tbl()->lookup(node->condition()));
1270   s.state(locop::NodeSummary::State::Complete);
1271
1272   return true;
1273 }
1274
1275 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhile *node, locop::NodeSummary &s) const
1276 {
1277   for (uint32_t i = 0; i < node->input_count(); ++i)
1278     s.args().append("input", tbl()->lookup(node->input(i)));
1279
1280   if (node->cond_graph() != nullptr)
1281     s.args().append("cond_graph", node->cond_graph()->name());
1282   else
1283     s.args().append("cond_branch", pepper::str(node->cond_branch()));
1284
1285   if (node->body_graph() != nullptr)
1286     s.args().append("body_graph", node->body_graph()->name());
1287   else
1288     s.args().append("body_branch", pepper::str(node->body_branch()));
1289
1290   s.state(locop::NodeSummary::State::Complete);
1291
1292   return true;
1293 }
1294
1295 bool CircleNodeSummaryBuilder::summary(const luci::CircleZerosLike *node,
1296                                        locop::NodeSummary &s) const
1297 {
1298   return use_input(tbl(), node, s);
1299 }
1300
1301 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitOut *node,
1302                                        locop::NodeSummary &s) const
1303 {
1304   return use_input(tbl(), node, s);
1305 }
1306
1307 bool CircleNodeSummaryBuilder::summary(const luci::CircleSplitVOut *node,
1308                                        locop::NodeSummary &s) const
1309 {
1310   return use_input(tbl(), node, s);
1311 }
1312
1313 bool CircleNodeSummaryBuilder::summary(const luci::CircleTopKV2Out *node,
1314                                        locop::NodeSummary &s) const
1315 {
1316   s.args().append("topkv2", tbl()->lookup(node->input()));
1317   s.state(locop::NodeSummary::State::Complete);
1318   return true;
1319 }
1320
1321 bool CircleNodeSummaryBuilder::summary(const luci::CircleUniqueOut *node,
1322                                        locop::NodeSummary &s) const
1323 {
1324   s.args().append("unique", tbl()->lookup(node->input()));
1325
1326   s.state(locop::NodeSummary::State::Complete);
1327
1328   return true;
1329 }
1330
1331 bool CircleNodeSummaryBuilder::summary(const luci::CircleUnpackOut *node,
1332                                        locop::NodeSummary &s) const
1333 {
1334   s.args().append("unpack", tbl()->lookup(node->input()));
1335
1336   s.state(locop::NodeSummary::State::Complete);
1337
1338   return true;
1339 }
1340
1341 bool CircleNodeSummaryBuilder::summary(const luci::CircleIfOut *node, locop::NodeSummary &s) const
1342 {
1343   return use_input(tbl(), node, s);
1344 }
1345
1346 bool CircleNodeSummaryBuilder::summary(const luci::CircleNonMaxSuppressionV4Out *node,
1347                                        locop::NodeSummary &s) const
1348 {
1349   return use_input(tbl(), node, s);
1350 }
1351
1352 bool CircleNodeSummaryBuilder::summary(const luci::CircleWhileOut *node,
1353                                        locop::NodeSummary &s) const
1354 {
1355   s.args().append("while", tbl()->lookup(node->input()));
1356
1357   s.state(locop::NodeSummary::State::Complete);
1358
1359   return true;
1360 }
1361
1362 bool CircleNodeSummaryBuilder::summary(const luci::CircleInput *, locop::NodeSummary &s) const
1363 {
1364   s.state(locop::NodeSummary::State::Complete);
1365   return true;
1366 }
1367
1368 bool CircleNodeSummaryBuilder::summary(const luci::CircleOutput *node, locop::NodeSummary &s) const
1369 {
1370   s.args().append("from", tbl()->lookup(node->from()));
1371
1372   s.state(locop::NodeSummary::State::Complete);
1373   return true;
1374 }
1375
1376 bool CircleNodeSummaryBuilder::summary(const luci::CircleBCQFullyConnected *node,
1377                                        locop::NodeSummary &s) const
1378 {
1379   assert(node->fusedActivationFunction() != luci::FusedActFunc::UNDEFINED);
1380
1381   s.args().append("input", tbl()->lookup(node->input()));
1382   s.args().append("weights_scales", tbl()->lookup(node->weights_scales()));
1383   s.args().append("weights_binary", tbl()->lookup(node->weights_binary()));
1384   s.args().append("bias", tbl()->lookup(node->bias()));
1385   s.args().append("weights_clusters", tbl()->lookup(node->weights_clusters()));
1386
1387   s.args().append("fused", to_str(node->fusedActivationFunction()));
1388   s.args().append("weights_hidden_size", pepper::str(node->weights_hidden_size()));
1389
1390   s.state(locop::NodeSummary::State::Complete);
1391
1392   return true;
1393 }
1394
1395 bool CircleNodeSummaryBuilder::summary(const luci::CircleBCQGather *node,
1396                                        locop::NodeSummary &s) const
1397 {
1398   s.args().append("input_scales", tbl()->lookup(node->input_scales()));
1399   s.args().append("input_binary", tbl()->lookup(node->input_binary()));
1400   s.args().append("indices", tbl()->lookup(node->indices()));
1401   s.args().append("input_clusters", tbl()->lookup(node->input_clusters()));
1402
1403   s.args().append("axis", pepper::str(node->axis()));
1404   s.args().append("input_hidden_size", pepper::str(node->input_hidden_size()));
1405
1406   s.state(locop::NodeSummary::State::Complete);
1407   return true;
1408 }
1409
1410 bool CircleNodeSummaryBuilder::summary(const luci::CircleInstanceNorm *node,
1411                                        locop::NodeSummary &s) const
1412 {
1413   auto fused = node->fusedActivationFunction();
1414   assert(fused != luci::FusedActFunc::UNDEFINED);
1415
1416   s.args().append("input", tbl()->lookup(node->input()));
1417   s.args().append("gamma", tbl()->lookup(node->gamma()));
1418   s.args().append("beta", tbl()->lookup(node->beta()));
1419   s.args().append("epsilon", pepper::str(node->epsilon()));
1420   s.args().append("fused_activation_function", to_str(fused));
1421
1422   s.state(locop::NodeSummary::State::Complete);
1423
1424   return true;
1425 }
1426
1427 } // namespace
1428
1429 namespace luci
1430 {
1431
1432 bool NodeSummaryBuilder::build(const loco::Node *node, locop::NodeSummary &s) const
1433 {
1434   if (locop::CanonicalNodeSummaryBuilder(_tbl).build(node, s))
1435   {
1436     return true;
1437   }
1438
1439   if (CircleNodeSummaryBuilder(_tbl).build(node, s))
1440   {
1441     return true;
1442   }
1443
1444   return false;
1445 }
1446
1447 } // namespace luci