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(0)
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) { dumpUnaryInputOp(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 BinaryArithmetic &node) { dumpBinaryInputOp(node); }
87 void OperationDumper::visit(const operation::BroadcastTo &node) { dumpBinaryInputOp(node); }
89 void OperationDumper::visit(const Comparison &node) { dumpBinaryInputOp(node); }
91 void OperationDumper::visit(const Concat &node) { dumpPackingOp(node); }
93 void OperationDumper::visit(const Conv2D &node)
95 std::string padding_type =
96 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
97 dumpConvOp(node, padding_type);
100 void OperationDumper::visit(const ConvertFp16ToFp32 &node) { dumpUnaryInputOp(node); }
102 void OperationDumper::visit(const ConvertFp32ToFp16 &node) { dumpUnaryInputOp(node); }
104 void OperationDumper::visit(const DepthToSpace &node) { dumpUnaryInputOp(node); }
106 void OperationDumper::visit(const DepthwiseConv2D &node)
108 std::string padding_type =
109 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
110 dumpConvOp(node, padding_type);
113 void OperationDumper::visit(const ElementwiseActivation &node)
116 if (node.param().op_type == ElementwiseActivation::Type::RELU)
118 params = " lower value(" + std::to_string(node.param().alpha) + ") upper value(" +
119 std::to_string(node.param().beta) + ")";
121 else if (node.param().op_type == ElementwiseActivation::Type::LEAKY_RELU)
123 params = " alpha value(" + std::to_string(node.param().alpha) + ")";
125 dumpUnaryInputOp(node, params);
128 void OperationDumper::visit(const ElementwiseBinary &node) { dumpBinaryInputOp(node); }
130 void OperationDumper::visit(const ElementwiseUnary &node) { dumpUnaryInputOp(node); }
132 void OperationDumper::visit(const EmbeddingLookup &node)
134 VERBOSE(LIR) << "* " << node.name() << std::endl;
135 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(EmbeddingLookup::Input::LOOKUPS)
136 << ") VALUES(" << node.getInputs().at(EmbeddingLookup::Input::VALUES) << ")"
138 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
141 void OperationDumper::visit(const ExpandDims &node)
144 "AXIS(" + std::to_string(node.getInputs().at(ExpandDims::Input::AXIS).value()) + ")";
145 dumpUnaryInputOp(node, axis);
148 void OperationDumper::visit(const FullyConnected &node)
151 "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
152 ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
153 dumpUnaryInputOp(node, inputs);
156 void OperationDumper::visit(const Gather &node)
158 std::string indices =
159 "Indices(" + std::to_string(node.getInputs().at(Gather::Input::INDICES).value()) + ")";
160 dumpUnaryInputOp(node, indices);
163 void OperationDumper::visit(const HashtableLookup &node)
165 VERBOSE(LIR) << "* HashTableLookup" << std::endl;
166 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(HashtableLookup::Input::LOOKUPS)
167 << ") Keys(" << node.getInputs().at(HashtableLookup::Input::KEYS) << ") Values("
168 << node.getInputs().at(HashtableLookup::Input::VALUES) << ")" << std::endl;
169 VERBOSE(LIR) << " - Outputs : Output(" << node.getInputs().at(HashtableLookup::Output::OUTPUT)
170 << ") Hits(" << node.getInputs().at(HashtableLookup::Output::HITS) << ")"
174 void OperationDumper::visit(const InstanceNorm &node)
177 "Gamma(" + std::to_string(node.getInputs().at(InstanceNorm::Input::GAMMA).value()) +
178 ") Beta(" + std::to_string(node.getInputs().at(InstanceNorm::Input::BETA).value()) + ")";
179 dumpUnaryInputOp(node, inputs);
182 void OperationDumper::visit(const L2Normalization &node) { dumpUnaryInputOp(node); }
184 void OperationDumper::visit(const LocalResponseNormalization &node) { dumpUnaryInputOp(node); }
186 void OperationDumper::visit(const LSTM &node)
189 << " - Inputs : Input(" << node.getInputs().at(LSTM::Input::INPUT)
190 << ") Input To Input Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_INPUT_WEIGHTS)
191 << ") Input To Forget Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_FORGET_WEIGHTS)
192 << ") Input To Cell Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_CELL_WEIGHTS)
193 << ") Input To Output Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_OUTPUT_WEIGHTS)
194 << ") Recurrent To Input Weights("
195 << node.getInputs().at(LSTM::Input::RECURRENT_TO_INPUT_WEIGHTS)
196 << ") Recurrent To Forget Weights("
197 << node.getInputs().at(LSTM::Input::RECURRENT_TO_FORGET_WEIGHTS)
198 << ") Recurrent To Cell Weights("
199 << node.getInputs().at(LSTM::Input::RECURRENT_TO_CELL_WEIGHTS)
200 << ") Recurrent To Output Weights("
201 << node.getInputs().at(LSTM::Input::RECURRENT_TO_OUTPUT_WEIGHTS) << ") Cell To Input Weights("
202 << node.getInputs().at(LSTM::Input::CELL_TO_INPUT_WEIGHTS) << ") Cell To Forget Weights("
203 << node.getInputs().at(LSTM::Input::CELL_TO_FORGET_WEIGHTS) << ") Cell To OUTPUT Weights("
204 << node.getInputs().at(LSTM::Input::CELL_TO_OUTPUT_WEIGHTS) << ") Input Gate Bias("
205 << node.getInputs().at(LSTM::Input::INPUT_GATE_BIAS) << ") Forget Gate Bias("
206 << node.getInputs().at(LSTM::Input::FORGET_GATE_BIAS) << ") Cell Bias("
207 << node.getInputs().at(LSTM::Input::CELL_BIAS) << ") Output Gate Bias("
208 << node.getInputs().at(LSTM::Input::OUTPUT_GATE_BIAS) << ") Projection Weights("
209 << node.getInputs().at(LSTM::Input::PROJECTION_WEIGHTS) << ") Projection Bias("
210 << node.getInputs().at(LSTM::Input::PROJECTION_BIAS) << ") Output State In("
211 << node.getInputs().at(LSTM::Input::OUTPUT_STATE_IN) << ") Cell State In("
212 << node.getInputs().at(LSTM::Input::CELL_STATE_IN) << ")" << std::endl;
213 VERBOSE(LIR) << " - Output : Scratch Buffer("
214 << node.getOutputs().at(LSTM::Output::SCRATCH_BUFFER) << ") Output State Out("
215 << node.getInputs().at(LSTM::Output::OUTPUT_STATE_OUT) << ") Cell State Out("
216 << node.getInputs().at(LSTM::Output::CELL_STATE_OUT) << ") Output("
217 << node.getInputs().at(LSTM::Output::OUTPUT) << ")" << std::endl;
220 void OperationDumper::visit(const Pack &node) { dumpPackingOp(node); }
222 void OperationDumper::visit(const Pad &node)
224 std::string pad = "Pad(" + std::to_string(node.getInputs().at(Pad::Input::PAD).value()) + ")";
225 dumpUnaryInputOp(node, pad);
228 void OperationDumper::visit(const Permute &node)
230 std::string permute_type = "Unknown";
231 switch (node.getPermuteType())
233 case Permute::Type::COPY:
234 permute_type = "Copy";
236 case Permute::Type::NHWC_TO_NCHW:
237 permute_type = "NHWC to NCHW";
239 case Permute::Type::NCHW_TO_NHWC:
240 permute_type = "NCHW to NHWC";
244 VERBOSE(LIR) << "* Permute(" + permute_type + ")" << std::endl;
245 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ")" << std::endl;
246 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
249 void OperationDumper::visit(const Pool2D &node)
251 std::string padding_type =
252 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
253 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
254 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Pool2D::Input::INPUT) << ")"
256 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
259 void OperationDumper::visit(const Pow &node) { dumpBinaryInputOp(node); }
261 void OperationDumper::visit(const PReLU &node)
264 "Alpha(" + std::to_string(node.getInputs().at(PReLU::Input::ALPHA).value()) + ")";
265 dumpUnaryInputOp(node, alpha);
268 void OperationDumper::visit(const Rank &node) { dumpUnaryInputOp(node); }
270 void OperationDumper::visit(const Reduce &node) { dumpUnaryInputOp(node); }
272 void OperationDumper::visit(const Reshape &node)
276 node.getInputs().size() == 2
277 ? "Shape(" + std::to_string(node.getInputs().at(Reshape::Input::SHAPE).value()) + ")"
278 : "Shape(not provided)";
279 dumpUnaryInputOp(node, shape);
282 void OperationDumper::visit(const ResizeBilinear &node) { dumpUnaryInputOp(node); }
284 void OperationDumper::visit(const Reverse &node)
287 "Axis(" + std::to_string(node.getInputs().at(Reverse::Input::AXIS).value()) + ")";
288 dumpUnaryInputOp(node, axis);
291 void OperationDumper::visit(const RNN &node)
293 VERBOSE(LIR) << "* RNN" << std::endl;
294 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(RNN::Input::INPUT) << ") Weights("
295 << node.getInputs().at(RNN::Input::WEIGHTS) << ") Recurrent Weights("
296 << node.getInputs().at(RNN::Input::RECURRENT_WEIGHTS) << ") Bias("
297 << node.getInputs().at(RNN::Input::BIAS) << ") Hidden State("
298 << node.getInputs().at(RNN::Input::HIDDEN_STATE_IN) << ")" << std::endl;
299 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(RNN::Output::OUTPUT)
300 << ") Hidden State(" << node.getInputs().at(RNN::Output::HIDDEN_STATE_OUT) << ")"
304 void OperationDumper::visit(const Range &node)
306 VERBOSE(LIR) << "* Range" << std::endl;
307 VERBOSE(LIR) << " - Inputs : Start(" << node.getInputs().at(Range::Input::START) << ")"
308 << " Limit(" << node.getInputs().at(Range::Input::LIMIT) << ")"
309 << " Delta(" << node.getInputs().at(Range::Input::DELTA) << ")" << std::endl;
310 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
313 void OperationDumper::visit(const Select &node)
315 VERBOSE(LIR) << "* Select" << std::endl;
316 VERBOSE(LIR) << " - Inputs : Condition(" << node.getInputs().at(Select::Input::CONDITION) << ")"
317 << " Input_X(" << node.getInputs().at(Select::Input::INPUT_TRUE) << ")"
318 << " Input_Y(" << node.getInputs().at(Select::Input::INPUT_FALSE) << ")"
320 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
323 void OperationDumper::visit(const ir::operation::Shape &node) { dumpUnaryInputOp(node); }
325 void OperationDumper::visit(const Softmax &node) { dumpUnaryInputOp(node); }
327 void OperationDumper::visit(const SpaceToBatchND &node)
331 std::to_string(node.getInputs().at(SpaceToBatchND::Input::BLOCK_SIZE).value()) +
332 ") Paddings(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::PADDINGS).value()) +
334 dumpUnaryInputOp(node, inputs);
337 void OperationDumper::visit(const SpaceToDepth &node) { dumpUnaryInputOp(node); }
339 void OperationDumper::visit(const Split &node) { dumpUnaryInputOp(node); }
341 void OperationDumper::visit(const SquaredDifference &node) { dumpBinaryInputOp(node); }
343 void OperationDumper::visit(const StatelessRandomUniform &node)
345 VERBOSE(LIR) << "* StatelessRandomUniform" << std::endl;
346 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(StatelessRandomUniform::Input::SHAPE)
347 << " Seed(" << node.getInputs().at(StatelessRandomUniform::Input::SEED) << ")"
349 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
352 void OperationDumper::visit(const Squeeze &node) { dumpUnaryInputOp(node); }
354 void OperationDumper::visit(const Slice &node) { dumpUnaryInputOp(node); }
356 void OperationDumper::visit(const StridedSlice &node) { dumpUnaryInputOp(node); }
358 void OperationDumper::visit(const Tile &node)
360 std::string multiples =
361 "Multiples(" + std::to_string(node.getInputs().at(Tile::Input::MULTIPLES).value()) + ")";
362 dumpUnaryInputOp(node, multiples);
365 void OperationDumper::visit(const TopKV2 &node)
367 VERBOSE(LIR) << "* TopKV2" << std::endl;
368 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(TopKV2::Input::INPUT) << ")"
370 VERBOSE(LIR) << " - Outputs : Values(" << node.getOutputs().at(TopKV2::Output::OUTPUT_VALUES)
371 << ") Indices(" << node.getOutputs().at(TopKV2::Output::OUTPUT_INDICES) << ")"
375 void OperationDumper::visit(const TransposeConv &node)
377 std::string padding_type =
378 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
379 VERBOSE(LIR) << "* TransposeConv(" << padding_type << ")" << std::endl;
380 VERBOSE(LIR) << " - Inputs : Output Shape("
381 << node.getInputs().at(TransposeConv::Input::OUTPUT_SHAPE) << ") KERNEL("
382 << node.getInputs().at(TransposeConv::Input::KERNEL) << ") IFM("
383 << node.getInputs().at(TransposeConv::Input::INPUT) << ")" << std::endl;
384 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
387 void OperationDumper::visit(const Transpose &node) { dumpUnaryInputOp(node); }
389 void OperationDumper::visit(const Unpack &node)
391 VERBOSE(LIR) << "* " << node.name() << std::endl;
392 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(Unpack::Input::INPUT) << ")"
395 const auto &output_indices = node.getOutputs();
396 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
398 outputs += std::to_string(it->value());
399 if (std::next(it) != std::end(output_indices))
402 VERBOSE(LIR) << " - Outputs : Outputs(" << outputs << ")" << std::endl;
405 void OperationDumper::visit(const OneHot &node)
407 VERBOSE(LIR) << "* " << node.name() << std::endl;
408 VERBOSE(LIR) << " - Inputs : "
409 << "Indices(" << node.getInputs().at(OneHot::Input::INDICES) << ") " << std::endl;
410 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
413 void OperationDumper::visit(const If &node)
415 VERBOSE(LIR) << "* " << node.name() << std::endl;
417 const auto &input_indices = node.getInputs();
418 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
420 inputs += std::to_string(it->value());
421 if (std::next(it) != std::end(input_indices))
424 VERBOSE(LIR) << " - Inputs : "
425 << "Then subgraph (" << node.param().then_subg_index << ") Else subgraph ("
426 << node.param().else_subg_index << ") Inputs(" << inputs << ")" << std::endl;
428 const auto &output_indices = node.getOutputs();
429 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
431 outputs += std::to_string(it->value());
432 if (std::next(it) != std::end(output_indices))
435 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;
438 void OperationDumper::visit(const While &node)
440 VERBOSE(LIR) << "* " << node.name() << std::endl;
442 const auto &input_indices = node.getInputs();
443 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
445 inputs += std::to_string(it->value());
446 if (std::next(it) != std::end(input_indices))
449 VERBOSE(LIR) << " - Inputs : "
450 << "Cond subgraph (" << node.param().cond_subg_index << ") Body subgraph ("
451 << node.param().cond_subg_index << ") Inputs(" << inputs << ")" << std::endl;
453 const auto &output_indices = node.getOutputs();
454 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
456 outputs += std::to_string(it->value());
457 if (std::next(it) != std::end(output_indices))
460 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;