2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "OperationDumper.h"
21 #include "util/logging.h"
28 using namespace operation;
32 void dumpUnaryInputOp(const Operation &node, const std::string &adding_input = "")
34 VERBOSE(LIR) << "* " << node.name() << std::endl;
35 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ") " << adding_input
37 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
40 void dumpBinaryInputOp(const Operation &node, const std::string &adding_input = "")
42 VERBOSE(LIR) << "* " << node.name() << std::endl;
43 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ", " << node.getInputs().at(1)
44 << ") " << adding_input << std::endl;
45 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
48 void dumpConvOp(const Operation &node, const std::string &padding_type)
50 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
51 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Conv2D::Input::INPUT) << ") Kernel("
52 << node.getInputs().at(Conv2D::Input::KERNEL) << ") Bias("
53 << node.getInputs().at(Conv2D::Input::BIAS) << ")" << std::endl;
54 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
57 void dumpPackingOp(const Operation &node)
59 VERBOSE(LIR) << "* " << node.name() << std::endl;
61 for (auto i : node.getInputs())
63 inputs += std::to_string(i.value()) + ",";
65 VERBOSE(LIR) << " - Inputs : Inputs(" << inputs << ")" << std::endl;
66 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
70 OperationDumper::OperationDumper(const std::string &start_msg)
72 VERBOSE(LIR) << start_msg << std::endl;
75 void OperationDumper::visit(const ArgMax &node) { dumpBinaryInputOp(node); }
77 void OperationDumper::visit(const BatchToSpaceND &node)
79 std::string block_size =
81 std::to_string(node.getInputs().at(BatchToSpaceND::Input::BLOCK_SIZE).value()) + ")";
82 dumpUnaryInputOp(node, block_size);
85 void OperationDumper::visit(const BCQFullyConnected &node)
87 VERBOSE(LIR) << "* " << node.name() << std::endl;
88 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(BCQFullyConnected::Input::INPUT)
90 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_BINARY)
92 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_SCALES)
93 << ") WeightsClusters("
94 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_CLUSTERS) << ") Bias("
95 << node.getInputs().at(BCQFullyConnected::Input::BIAS) << ")" << std::endl;
96 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
99 void OperationDumper::visit(const BinaryArithmetic &node) { dumpBinaryInputOp(node); }
101 void OperationDumper::visit(const operation::BroadcastTo &node) { dumpBinaryInputOp(node); }
103 void OperationDumper::visit(const Comparison &node) { dumpBinaryInputOp(node); }
105 void OperationDumper::visit(const Concat &node) { dumpPackingOp(node); }
107 void OperationDumper::visit(const Conv2D &node)
109 std::string padding_type =
110 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
111 dumpConvOp(node, padding_type);
114 void OperationDumper::visit(const ConvertFp16ToFp32 &node) { dumpUnaryInputOp(node); }
116 void OperationDumper::visit(const ConvertFp32ToFp16 &node) { dumpUnaryInputOp(node); }
118 void OperationDumper::visit(const DepthToSpace &node) { dumpUnaryInputOp(node); }
120 void OperationDumper::visit(const DepthwiseConv2D &node)
122 std::string padding_type =
123 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
124 dumpConvOp(node, padding_type);
127 void OperationDumper::visit(const ElementwiseActivation &node)
130 if (node.param().op_type == ElementwiseActivation::Type::RELU)
132 params = " lower value(" + std::to_string(node.param().alpha) + ") upper value(" +
133 std::to_string(node.param().beta) + ")";
135 else if (node.param().op_type == ElementwiseActivation::Type::LEAKY_RELU)
137 params = " alpha value(" + std::to_string(node.param().alpha) + ")";
139 dumpUnaryInputOp(node, params);
142 void OperationDumper::visit(const ElementwiseBinary &node) { dumpBinaryInputOp(node); }
144 void OperationDumper::visit(const ElementwiseUnary &node) { dumpUnaryInputOp(node); }
146 void OperationDumper::visit(const EmbeddingLookup &node)
148 VERBOSE(LIR) << "* " << node.name() << std::endl;
149 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(EmbeddingLookup::Input::LOOKUPS)
150 << ") VALUES(" << node.getInputs().at(EmbeddingLookup::Input::VALUES) << ")"
152 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
155 void OperationDumper::visit(const ExpandDims &node)
158 "AXIS(" + std::to_string(node.getInputs().at(ExpandDims::Input::AXIS).value()) + ")";
159 dumpUnaryInputOp(node, axis);
162 void OperationDumper::visit(const FullyConnected &node)
165 "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
166 ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
167 dumpUnaryInputOp(node, inputs);
170 void OperationDumper::visit(const Gather &node)
172 std::string indices =
173 "Indices(" + std::to_string(node.getInputs().at(Gather::Input::INDICES).value()) + ")";
174 dumpUnaryInputOp(node, indices);
177 void OperationDumper::visit(const HashtableLookup &node)
179 VERBOSE(LIR) << "* HashTableLookup" << std::endl;
180 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(HashtableLookup::Input::LOOKUPS)
181 << ") Keys(" << node.getInputs().at(HashtableLookup::Input::KEYS) << ") Values("
182 << node.getInputs().at(HashtableLookup::Input::VALUES) << ")" << std::endl;
183 VERBOSE(LIR) << " - Outputs : Output(" << node.getInputs().at(HashtableLookup::Output::OUTPUT)
184 << ") Hits(" << node.getInputs().at(HashtableLookup::Output::HITS) << ")"
188 void OperationDumper::visit(const InstanceNorm &node)
191 "Gamma(" + std::to_string(node.getInputs().at(InstanceNorm::Input::GAMMA).value()) +
192 ") Beta(" + std::to_string(node.getInputs().at(InstanceNorm::Input::BETA).value()) + ")";
193 dumpUnaryInputOp(node, inputs);
196 void OperationDumper::visit(const L2Normalization &node) { dumpUnaryInputOp(node); }
198 void OperationDumper::visit(const LocalResponseNormalization &node) { dumpUnaryInputOp(node); }
200 void OperationDumper::visit(const LSTM &node)
202 VERBOSE(LIR) << "* " << node.name() << std::endl;
204 << " - Inputs : Input(" << node.getInputs().at(LSTM::Input::INPUT)
205 << ") Input To Input Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_INPUT_WEIGHTS)
206 << ") Input To Forget Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_FORGET_WEIGHTS)
207 << ") Input To Cell Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_CELL_WEIGHTS)
208 << ") Input To Output Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_OUTPUT_WEIGHTS)
209 << ") Recurrent To Input Weights("
210 << node.getInputs().at(LSTM::Input::RECURRENT_TO_INPUT_WEIGHTS)
211 << ") Recurrent To Forget Weights("
212 << node.getInputs().at(LSTM::Input::RECURRENT_TO_FORGET_WEIGHTS)
213 << ") Recurrent To Cell Weights("
214 << node.getInputs().at(LSTM::Input::RECURRENT_TO_CELL_WEIGHTS)
215 << ") Recurrent To Output Weights("
216 << node.getInputs().at(LSTM::Input::RECURRENT_TO_OUTPUT_WEIGHTS) << ") Cell To Input Weights("
217 << node.getInputs().at(LSTM::Input::CELL_TO_INPUT_WEIGHTS) << ") Cell To Forget Weights("
218 << node.getInputs().at(LSTM::Input::CELL_TO_FORGET_WEIGHTS) << ") Cell To OUTPUT Weights("
219 << node.getInputs().at(LSTM::Input::CELL_TO_OUTPUT_WEIGHTS) << ") Input Gate Bias("
220 << node.getInputs().at(LSTM::Input::INPUT_GATE_BIAS) << ") Forget Gate Bias("
221 << node.getInputs().at(LSTM::Input::FORGET_GATE_BIAS) << ") Cell Bias("
222 << node.getInputs().at(LSTM::Input::CELL_BIAS) << ") Output Gate Bias("
223 << node.getInputs().at(LSTM::Input::OUTPUT_GATE_BIAS) << ") Projection Weights("
224 << node.getInputs().at(LSTM::Input::PROJECTION_WEIGHTS) << ") Projection Bias("
225 << node.getInputs().at(LSTM::Input::PROJECTION_BIAS) << ") Output State In("
226 << node.getInputs().at(LSTM::Input::OUTPUT_STATE_IN) << ") Cell State In("
227 << node.getInputs().at(LSTM::Input::CELL_STATE_IN);
228 if (node.getInputs().size() == 24)
230 VERBOSE(LIR) << ") Input Layer Normalization Weights("
231 << node.getInputs().at(LSTM::Input::INPUT_LAYER_NORMALIZATION_WEIGHTS)
232 << ") Forget Layer Normalization Weights("
233 << node.getInputs().at(LSTM::Input::FORGET_LAYER_NORMALIZATION_WEIGHTS)
234 << ") Cell Layer Normalization Weights("
235 << node.getInputs().at(LSTM::Input::CELL_LAYER_NORMALIZATION_WEIGHTS)
236 << ") Ouput Layer Normalization Weights("
237 << node.getInputs().at(LSTM::Input::OUTPUT_LAYER_NORMALIZATION_WEIGHTS);
239 VERBOSE(LIR) << ")" << std::endl;
240 VERBOSE(LIR) << " - Output : Scratch Buffer("
241 << node.getOutputs().at(LSTM::Output::SCRATCH_BUFFER) << ") Output State Out("
242 << node.getOutputs().at(LSTM::Output::OUTPUT_STATE_OUT) << ") Cell State Out("
243 << node.getOutputs().at(LSTM::Output::CELL_STATE_OUT) << ") Output("
244 << node.getOutputs().at(LSTM::Output::OUTPUT) << ")" << std::endl;
247 void OperationDumper::visit(const Pack &node) { dumpPackingOp(node); }
249 void OperationDumper::visit(const Pad &node)
251 std::string pad = "Pad(" + std::to_string(node.getInputs().at(Pad::Input::PAD).value()) + ")";
252 dumpUnaryInputOp(node, pad);
255 void OperationDumper::visit(const Permute &node)
257 std::string permute_type = "Unknown";
258 switch (node.getPermuteType())
260 case Permute::Type::COPY:
261 permute_type = "Copy";
263 case Permute::Type::NHWC_TO_NCHW:
264 permute_type = "NHWC to NCHW";
266 case Permute::Type::NCHW_TO_NHWC:
267 permute_type = "NCHW to NHWC";
271 VERBOSE(LIR) << "* Permute(" + permute_type + ")" << std::endl;
272 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ")" << std::endl;
273 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
276 void OperationDumper::visit(const Pool2D &node)
278 std::string padding_type =
279 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
280 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
281 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Pool2D::Input::INPUT) << ")"
283 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
286 void OperationDumper::visit(const Pow &node) { dumpBinaryInputOp(node); }
288 void OperationDumper::visit(const PReLU &node)
291 "Alpha(" + std::to_string(node.getInputs().at(PReLU::Input::ALPHA).value()) + ")";
292 dumpUnaryInputOp(node, alpha);
295 void OperationDumper::visit(const Rank &node) { dumpUnaryInputOp(node); }
297 void OperationDumper::visit(const Reduce &node) { dumpUnaryInputOp(node); }
299 void OperationDumper::visit(const Reshape &node)
303 node.getInputs().size() == 2
304 ? "Shape(" + std::to_string(node.getInputs().at(Reshape::Input::SHAPE).value()) + ")"
305 : "Shape(not provided)";
306 dumpUnaryInputOp(node, shape);
309 void OperationDumper::visit(const ResizeBilinear &node)
311 if (node.getInputs().size() == 1)
313 dumpUnaryInputOp(node);
315 else if (node.getInputs().size() == 2)
317 dumpBinaryInputOp(node);
321 VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
325 void OperationDumper::visit(const ResizeNearestNeighbor &node)
327 if (node.getInputs().size() == 1)
329 dumpUnaryInputOp(node);
331 else if (node.getInputs().size() == 2)
333 dumpBinaryInputOp(node);
337 VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
341 void OperationDumper::visit(const Reverse &node)
344 "Axis(" + std::to_string(node.getInputs().at(Reverse::Input::AXIS).value()) + ")";
345 dumpUnaryInputOp(node, axis);
348 void OperationDumper::visit(const RNN &node)
350 VERBOSE(LIR) << "* RNN" << std::endl;
351 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(RNN::Input::INPUT) << ") Weights("
352 << node.getInputs().at(RNN::Input::WEIGHTS) << ") Recurrent Weights("
353 << node.getInputs().at(RNN::Input::RECURRENT_WEIGHTS) << ") Bias("
354 << node.getInputs().at(RNN::Input::BIAS) << ") Hidden State("
355 << node.getInputs().at(RNN::Input::HIDDEN_STATE_IN) << ")" << std::endl;
356 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(RNN::Output::OUTPUT)
357 << ") Hidden State(" << node.getInputs().at(RNN::Output::HIDDEN_STATE_OUT) << ")"
361 void OperationDumper::visit(const Range &node)
363 VERBOSE(LIR) << "* Range" << std::endl;
364 VERBOSE(LIR) << " - Inputs : Start(" << node.getInputs().at(Range::Input::START) << ")"
365 << " Limit(" << node.getInputs().at(Range::Input::LIMIT) << ")"
366 << " Delta(" << node.getInputs().at(Range::Input::DELTA) << ")" << std::endl;
367 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
370 void OperationDumper::visit(const Select &node)
372 VERBOSE(LIR) << "* Select" << std::endl;
373 VERBOSE(LIR) << " - Inputs : Condition(" << node.getInputs().at(Select::Input::CONDITION) << ")"
374 << " Input_X(" << node.getInputs().at(Select::Input::INPUT_TRUE) << ")"
375 << " Input_Y(" << node.getInputs().at(Select::Input::INPUT_FALSE) << ")"
377 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
380 void OperationDumper::visit(const ir::operation::Shape &node) { dumpUnaryInputOp(node); }
382 void OperationDumper::visit(const Softmax &node) { dumpUnaryInputOp(node); }
384 void OperationDumper::visit(const SpaceToBatchND &node)
388 std::to_string(node.getInputs().at(SpaceToBatchND::Input::BLOCK_SIZE).value()) +
389 ") Paddings(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::PADDINGS).value()) +
391 dumpUnaryInputOp(node, inputs);
394 void OperationDumper::visit(const SpaceToDepth &node) { dumpUnaryInputOp(node); }
396 void OperationDumper::visit(const Split &node) { dumpBinaryInputOp(node); }
398 void OperationDumper::visit(const SquaredDifference &node) { dumpBinaryInputOp(node); }
400 void OperationDumper::visit(const StatelessRandomUniform &node)
402 VERBOSE(LIR) << "* StatelessRandomUniform" << std::endl;
403 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(StatelessRandomUniform::Input::SHAPE)
404 << " Seed(" << node.getInputs().at(StatelessRandomUniform::Input::SEED) << ")"
406 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
409 void OperationDumper::visit(const Squeeze &node) { dumpUnaryInputOp(node); }
411 void OperationDumper::visit(const Slice &node) { dumpUnaryInputOp(node); }
413 void OperationDumper::visit(const StridedSlice &node) { dumpUnaryInputOp(node); }
415 void OperationDumper::visit(const Tile &node)
417 std::string multiples =
418 "Multiples(" + std::to_string(node.getInputs().at(Tile::Input::MULTIPLES).value()) + ")";
419 dumpUnaryInputOp(node, multiples);
422 void OperationDumper::visit(const TopKV2 &node)
424 VERBOSE(LIR) << "* TopKV2" << std::endl;
425 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(TopKV2::Input::INPUT) << ")"
427 VERBOSE(LIR) << " - Outputs : Values(" << node.getOutputs().at(TopKV2::Output::OUTPUT_VALUES)
428 << ") Indices(" << node.getOutputs().at(TopKV2::Output::OUTPUT_INDICES) << ")"
432 void OperationDumper::visit(const TransposeConv &node)
434 std::string padding_type =
435 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
436 VERBOSE(LIR) << "* TransposeConv(" << padding_type << ")" << std::endl;
437 VERBOSE(LIR) << " - Inputs : Output Shape("
438 << node.getInputs().at(TransposeConv::Input::OUTPUT_SHAPE) << ") KERNEL("
439 << node.getInputs().at(TransposeConv::Input::KERNEL) << ") IFM("
440 << node.getInputs().at(TransposeConv::Input::INPUT) << ")" << std::endl;
441 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
444 void OperationDumper::visit(const Transpose &node) { dumpBinaryInputOp(node); }
446 void OperationDumper::visit(const Unpack &node)
448 VERBOSE(LIR) << "* " << node.name() << std::endl;
449 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(Unpack::Input::INPUT) << ")"
452 const auto &output_indices = node.getOutputs();
453 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
455 outputs += std::to_string(it->value());
456 if (std::next(it) != std::end(output_indices))
459 VERBOSE(LIR) << " - Outputs : Outputs(" << outputs << ")" << std::endl;
462 void OperationDumper::visit(const OneHot &node)
464 VERBOSE(LIR) << "* " << node.name() << std::endl;
465 VERBOSE(LIR) << " - Inputs : "
466 << "Indices(" << node.getInputs().at(OneHot::Input::INDICES) << ") " << std::endl;
467 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
470 void OperationDumper::visit(const If &node)
472 VERBOSE(LIR) << "* " << node.name() << std::endl;
474 const auto &input_indices = node.getInputs();
475 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
477 inputs += std::to_string(it->value());
478 if (std::next(it) != std::end(input_indices))
481 VERBOSE(LIR) << " - Inputs : "
482 << "Then subgraph (" << node.param().then_subg_index << ") Else subgraph ("
483 << node.param().else_subg_index << ") Inputs(" << inputs << ")" << std::endl;
485 const auto &output_indices = node.getOutputs();
486 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
488 outputs += std::to_string(it->value());
489 if (std::next(it) != std::end(output_indices))
492 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;
495 void OperationDumper::visit(const While &node)
497 VERBOSE(LIR) << "* " << node.name() << std::endl;
499 const auto &input_indices = node.getInputs();
500 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
502 inputs += std::to_string(it->value());
503 if (std::next(it) != std::end(input_indices))
506 VERBOSE(LIR) << " - Inputs : "
507 << "Cond subgraph (" << node.param().cond_subg_index << ") Body subgraph ("
508 << node.param().cond_subg_index << ") Inputs(" << inputs << ")" << std::endl;
510 const auto &output_indices = node.getOutputs();
511 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
513 outputs += std::to_string(it->value());
514 if (std::next(it) != std::end(output_indices))
517 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;