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;
33 // Dump all input and output.
34 // Use this function when there is no special input or(and) output.
35 void dumpOpGeneric(const Operation &node, const std::string &adding_input = "")
37 VERBOSE(LIR) << "* " << node.name() << std::endl;
38 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs() << ") " << adding_input << std::endl;
39 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs() << ")" << std::endl;
42 void dumpUnaryInputOp(const Operation &node, const std::string &adding_input = "")
44 VERBOSE(LIR) << "* " << node.name() << std::endl;
45 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ") " << adding_input
47 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
50 void dumpConvOp(const Operation &node, const std::string &padding_type)
52 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
53 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Conv2D::Input::INPUT) << ") Kernel("
54 << node.getInputs().at(Conv2D::Input::KERNEL) << ") Bias("
55 << node.getInputs().at(Conv2D::Input::BIAS) << ")" << std::endl;
56 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
60 OperationDumper::OperationDumper(const std::string &start_msg)
62 VERBOSE(LIR) << start_msg << std::endl;
65 void OperationDumper::visit(const ArgMinMax &node)
67 std::string min_max = node.param().is_arg_max ? "(Max)" : "(Min)";
68 VERBOSE(LIR) << "* " << node.name() << min_max << std::endl;
69 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(ArgMinMax::INPUT) << ") Axis("
70 << node.getInputs().at(ArgMinMax::AXIS) << ") " << std::endl;
71 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
74 void OperationDumper::visit(const BatchToSpaceND &node)
76 std::string block_size =
77 "BlockSize(" + std::to_string(node.getInputs().at(BatchToSpaceND::Input::BLOCK_SIZE).value()) +
79 dumpOpGeneric(node, block_size);
82 void OperationDumper::visit(const BCQFullyConnected &node)
84 VERBOSE(LIR) << "* " << node.name() << std::endl;
85 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(BCQFullyConnected::Input::INPUT)
87 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_BINARY)
89 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_SCALES)
90 << ") WeightsClusters("
91 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_CLUSTERS) << ") Bias("
92 << node.getInputs().at(BCQFullyConnected::Input::BIAS) << ")" << std::endl;
93 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
96 void OperationDumper::visit(const BinaryArithmetic &node) { dumpOpGeneric(node); }
98 void OperationDumper::visit(const operation::BroadcastTo &node) { dumpOpGeneric(node); }
100 void OperationDumper::visit(const Comparison &node) { dumpOpGeneric(node); }
102 void OperationDumper::visit(const Concat &node) { dumpOpGeneric(node); }
104 void OperationDumper::visit(const Conv2D &node)
106 std::string padding_type =
107 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
108 dumpConvOp(node, padding_type);
111 void OperationDumper::visit(const ConvertFp16ToFp32 &node) { dumpOpGeneric(node); }
113 void OperationDumper::visit(const ConvertFp32ToFp16 &node) { dumpOpGeneric(node); }
115 void OperationDumper::visit(const DepthToSpace &node) { dumpOpGeneric(node); }
117 void OperationDumper::visit(const DepthwiseConv2D &node)
119 std::string padding_type =
120 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
121 dumpConvOp(node, padding_type);
124 void OperationDumper::visit(const ElementwiseActivation &node)
127 if (node.param().op_type == ElementwiseActivation::Type::RELU)
129 params = " lower value(" + std::to_string(node.param().alpha) + ") upper value(" +
130 std::to_string(node.param().beta) + ")";
132 else if (node.param().op_type == ElementwiseActivation::Type::LEAKY_RELU)
134 params = " alpha value(" + std::to_string(node.param().alpha) + ")";
136 dumpOpGeneric(node, params);
139 void OperationDumper::visit(const ElementwiseBinary &node) { dumpOpGeneric(node); }
141 void OperationDumper::visit(const ElementwiseUnary &node) { dumpOpGeneric(node); }
143 void OperationDumper::visit(const EmbeddingLookup &node)
145 VERBOSE(LIR) << "* " << node.name() << std::endl;
146 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(EmbeddingLookup::Input::LOOKUPS)
147 << ") VALUES(" << node.getInputs().at(EmbeddingLookup::Input::VALUES) << ")"
149 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
152 void OperationDumper::visit(const ExpandDims &node)
155 "AXIS(" + std::to_string(node.getInputs().at(ExpandDims::Input::AXIS).value()) + ")";
156 dumpUnaryInputOp(node, axis);
159 void OperationDumper::visit(const Fill &node)
161 VERBOSE(LIR) << "* " << node.name() << std::endl;
162 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(Fill::Input::SHAPE) << ") Value("
163 << node.getInputs().at(Fill::Input::VALUE) << ")" << std::endl;
164 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
167 void OperationDumper::visit(const FullyConnected &node)
170 "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
171 ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
172 dumpUnaryInputOp(node, inputs);
175 void OperationDumper::visit(const Gather &node)
177 std::string indices =
178 "Indices(" + std::to_string(node.getInputs().at(Gather::Input::INDICES).value()) + ")";
179 dumpUnaryInputOp(node, indices);
182 void OperationDumper::visit(const HashtableLookup &node)
184 VERBOSE(LIR) << "* HashTableLookup" << std::endl;
185 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(HashtableLookup::Input::LOOKUPS)
186 << ") Keys(" << node.getInputs().at(HashtableLookup::Input::KEYS) << ") Values("
187 << node.getInputs().at(HashtableLookup::Input::VALUES) << ")" << std::endl;
188 VERBOSE(LIR) << " - Outputs : Output(" << node.getInputs().at(HashtableLookup::Output::OUTPUT)
189 << ") Hits(" << node.getInputs().at(HashtableLookup::Output::HITS) << ")"
193 void OperationDumper::visit(const InstanceNorm &node)
196 "Gamma(" + std::to_string(node.getInputs().at(InstanceNorm::Input::GAMMA).value()) + ") Beta(" +
197 std::to_string(node.getInputs().at(InstanceNorm::Input::BETA).value()) + ")";
198 dumpUnaryInputOp(node, inputs);
201 void OperationDumper::visit(const L2Normalization &node) { dumpOpGeneric(node); }
203 void OperationDumper::visit(const LocalResponseNormalization &node) { dumpOpGeneric(node); }
205 void OperationDumper::visit(const Loss &node)
207 VERBOSE(LIR) << "* " << node.name() << std::endl;
208 VERBOSE(LIR) << " - Inputs : Prediction(" << node.getInputs().at(Loss::Input::Y_PRED) << ") True("
209 << node.getInputs().at(Loss::Input::Y_TRUE) << ")" << std::endl;
210 VERBOSE(LIR) << " - Outputs : Output(" << node.getOutputs().at(0) << ")" << std::endl;
213 void OperationDumper::visit(const LSTM &node)
215 VERBOSE(LIR) << "* " << node.name() << std::endl;
217 << " - Inputs : Input(" << node.getInputs().at(LSTM::Input::INPUT)
218 << ") Input To Input Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_INPUT_WEIGHTS)
219 << ") Input To Forget Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_FORGET_WEIGHTS)
220 << ") Input To Cell Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_CELL_WEIGHTS)
221 << ") Input To Output Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_OUTPUT_WEIGHTS)
222 << ") Recurrent To Input Weights("
223 << node.getInputs().at(LSTM::Input::RECURRENT_TO_INPUT_WEIGHTS)
224 << ") Recurrent To Forget Weights("
225 << node.getInputs().at(LSTM::Input::RECURRENT_TO_FORGET_WEIGHTS)
226 << ") Recurrent To Cell Weights(" << node.getInputs().at(LSTM::Input::RECURRENT_TO_CELL_WEIGHTS)
227 << ") Recurrent To Output Weights("
228 << node.getInputs().at(LSTM::Input::RECURRENT_TO_OUTPUT_WEIGHTS) << ") Cell To Input Weights("
229 << node.getInputs().at(LSTM::Input::CELL_TO_INPUT_WEIGHTS) << ") Cell To Forget Weights("
230 << node.getInputs().at(LSTM::Input::CELL_TO_FORGET_WEIGHTS) << ") Cell To OUTPUT Weights("
231 << node.getInputs().at(LSTM::Input::CELL_TO_OUTPUT_WEIGHTS) << ") Input Gate Bias("
232 << node.getInputs().at(LSTM::Input::INPUT_GATE_BIAS) << ") Forget Gate Bias("
233 << node.getInputs().at(LSTM::Input::FORGET_GATE_BIAS) << ") Cell Bias("
234 << node.getInputs().at(LSTM::Input::CELL_BIAS) << ") Output Gate Bias("
235 << node.getInputs().at(LSTM::Input::OUTPUT_GATE_BIAS) << ") Projection Weights("
236 << node.getInputs().at(LSTM::Input::PROJECTION_WEIGHTS) << ") Projection Bias("
237 << node.getInputs().at(LSTM::Input::PROJECTION_BIAS) << ") Output State In("
238 << node.getInputs().at(LSTM::Input::OUTPUT_STATE_IN) << ") Cell State In("
239 << node.getInputs().at(LSTM::Input::CELL_STATE_IN);
240 if (node.getInputs().size() == 24)
242 VERBOSE(LIR) << ") Input Layer Normalization Weights("
243 << node.getInputs().at(LSTM::Input::INPUT_LAYER_NORMALIZATION_WEIGHTS)
244 << ") Forget Layer Normalization Weights("
245 << node.getInputs().at(LSTM::Input::FORGET_LAYER_NORMALIZATION_WEIGHTS)
246 << ") Cell Layer Normalization Weights("
247 << node.getInputs().at(LSTM::Input::CELL_LAYER_NORMALIZATION_WEIGHTS)
248 << ") Ouput Layer Normalization Weights("
249 << node.getInputs().at(LSTM::Input::OUTPUT_LAYER_NORMALIZATION_WEIGHTS);
251 VERBOSE(LIR) << ")" << std::endl;
252 VERBOSE(LIR) << " - Output : Scratch Buffer("
253 << node.getOutputs().at(LSTM::Output::SCRATCH_BUFFER) << ") Output State Out("
254 << node.getOutputs().at(LSTM::Output::OUTPUT_STATE_OUT) << ") Cell State Out("
255 << node.getOutputs().at(LSTM::Output::CELL_STATE_OUT) << ") Output("
256 << node.getOutputs().at(LSTM::Output::OUTPUT) << ")" << std::endl;
259 void OperationDumper::visit(const Pack &node) { dumpOpGeneric(node); }
261 void OperationDumper::visit(const Pad &node)
263 std::string pad = "Pad(" + std::to_string(node.getInputs().at(Pad::Input::PAD).value()) + ")";
264 dumpUnaryInputOp(node, pad);
267 void OperationDumper::visit(const Permute &node)
269 std::string permute_type = "Unknown";
270 switch (node.getPermuteType())
272 case Permute::Type::COPY:
273 permute_type = "Copy";
275 case Permute::Type::NHWC_TO_NCHW:
276 permute_type = "NHWC to NCHW";
278 case Permute::Type::NCHW_TO_NHWC:
279 permute_type = "NCHW to NHWC";
283 VERBOSE(LIR) << "* Permute(" + permute_type + ")" << std::endl;
284 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ")" << std::endl;
285 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
288 void OperationDumper::visit(const Pool2D &node)
290 std::string padding_type =
291 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
292 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
293 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Pool2D::Input::INPUT) << ")"
295 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
298 void OperationDumper::visit(const Pow &node) { dumpOpGeneric(node); }
300 void OperationDumper::visit(const PReLU &node)
303 "Alpha(" + std::to_string(node.getInputs().at(PReLU::Input::ALPHA).value()) + ")";
304 dumpOpGeneric(node, alpha);
307 void OperationDumper::visit(const Rank &node) { dumpOpGeneric(node); }
309 void OperationDumper::visit(const Reduce &node) { dumpUnaryInputOp(node); }
311 void OperationDumper::visit(const Reshape &node)
315 node.getInputs().size() == 2
316 ? "Shape(" + std::to_string(node.getInputs().at(Reshape::Input::SHAPE).value()) + ")"
317 : "Shape(not provided)";
318 dumpUnaryInputOp(node, shape);
321 void OperationDumper::visit(const ResizeBilinear &node) { dumpOpGeneric(node); }
323 void OperationDumper::visit(const ResizeNearestNeighbor &node) { dumpOpGeneric(node); }
325 void OperationDumper::visit(const Reverse &node)
328 "Axis(" + std::to_string(node.getInputs().at(Reverse::Input::AXIS).value()) + ")";
329 dumpUnaryInputOp(node, axis);
332 void OperationDumper::visit(const RNN &node)
334 VERBOSE(LIR) << "* RNN" << std::endl;
335 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(RNN::Input::INPUT) << ") Weights("
336 << node.getInputs().at(RNN::Input::WEIGHTS) << ") Recurrent Weights("
337 << node.getInputs().at(RNN::Input::RECURRENT_WEIGHTS) << ") Bias("
338 << node.getInputs().at(RNN::Input::BIAS) << ") Hidden State("
339 << node.getInputs().at(RNN::Input::HIDDEN_STATE_IN) << ")" << std::endl;
340 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(RNN::Output::OUTPUT)
341 << ") Hidden State(" << node.getInputs().at(RNN::Output::HIDDEN_STATE_OUT) << ")"
345 void OperationDumper::visit(const Range &node)
347 VERBOSE(LIR) << "* Range" << std::endl;
348 VERBOSE(LIR) << " - Inputs : Start(" << node.getInputs().at(Range::Input::START) << ")"
349 << " Limit(" << node.getInputs().at(Range::Input::LIMIT) << ")"
350 << " Delta(" << node.getInputs().at(Range::Input::DELTA) << ")" << std::endl;
351 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
354 void OperationDumper::visit(const Select &node)
356 VERBOSE(LIR) << "* Select" << std::endl;
357 VERBOSE(LIR) << " - Inputs : Condition(" << node.getInputs().at(Select::Input::CONDITION) << ")"
358 << " Input_X(" << node.getInputs().at(Select::Input::INPUT_TRUE) << ")"
359 << " Input_Y(" << node.getInputs().at(Select::Input::INPUT_FALSE) << ")"
361 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
364 void OperationDumper::visit(const ir::operation::Shape &node) { dumpOpGeneric(node); }
366 void OperationDumper::visit(const Softmax &node) { dumpOpGeneric(node); }
368 void OperationDumper::visit(const SpaceToBatchND &node)
371 "BlockSize(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::BLOCK_SIZE).value()) +
372 ") Paddings(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::PADDINGS).value()) +
374 dumpUnaryInputOp(node, inputs);
377 void OperationDumper::visit(const SpaceToDepth &node) { dumpOpGeneric(node); }
379 void OperationDumper::visit(const Split &node) { dumpOpGeneric(node); }
381 void OperationDumper::visit(const SquaredDifference &node) { dumpOpGeneric(node); }
383 void OperationDumper::visit(const StatelessRandomUniform &node)
385 VERBOSE(LIR) << "* StatelessRandomUniform" << std::endl;
386 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(StatelessRandomUniform::Input::SHAPE)
387 << " Seed(" << node.getInputs().at(StatelessRandomUniform::Input::SEED) << ")"
389 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
392 void OperationDumper::visit(const Squeeze &node) { dumpOpGeneric(node); }
394 void OperationDumper::visit(const Slice &node) { dumpUnaryInputOp(node); }
396 void OperationDumper::visit(const StridedSlice &node) { dumpUnaryInputOp(node); }
398 void OperationDumper::visit(const Tile &node)
400 std::string multiples =
401 "Multiples(" + std::to_string(node.getInputs().at(Tile::Input::MULTIPLES).value()) + ")";
402 dumpUnaryInputOp(node, multiples);
405 void OperationDumper::visit(const TopKV2 &node)
407 VERBOSE(LIR) << "* TopKV2" << std::endl;
408 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(TopKV2::Input::INPUT) << ")"
410 VERBOSE(LIR) << " - Outputs : Values(" << node.getOutputs().at(TopKV2::Output::OUTPUT_VALUES)
411 << ") Indices(" << node.getOutputs().at(TopKV2::Output::OUTPUT_INDICES) << ")"
415 void OperationDumper::visit(const TransposeConv &node)
417 std::string padding_type =
418 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
419 VERBOSE(LIR) << "* TransposeConv(" << padding_type << ")" << std::endl;
420 VERBOSE(LIR) << " - Inputs : Output Shape("
421 << node.getInputs().at(TransposeConv::Input::OUTPUT_SHAPE) << ") KERNEL("
422 << node.getInputs().at(TransposeConv::Input::KERNEL) << ") IFM("
423 << node.getInputs().at(TransposeConv::Input::INPUT) << ")" << std::endl;
424 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
427 void OperationDumper::visit(const Transpose &node) { dumpOpGeneric(node); }
429 void OperationDumper::visit(const Unpack &node)
431 VERBOSE(LIR) << "* " << node.name() << std::endl;
432 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(Unpack::Input::INPUT) << ")"
434 VERBOSE(LIR) << " - Output : Outputs(" << node.getOutputs() << ")" << std::endl;
437 void OperationDumper::visit(const OneHot &node)
439 VERBOSE(LIR) << "* " << node.name() << std::endl;
440 VERBOSE(LIR) << " - Inputs : "
441 << "Indices(" << node.getInputs().at(OneHot::Input::INDICES) << ") " << std::endl;
442 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
445 void OperationDumper::visit(const If &node)
447 VERBOSE(LIR) << "* " << node.name() << std::endl;
448 VERBOSE(LIR) << " - Inputs : "
449 << "Then subgraph (" << node.param().then_subg_index << ") Else subgraph ("
450 << node.param().else_subg_index << ") Inputs(" << node.getInputs() << ")"
452 VERBOSE(LIR) << " - Output : Outputs(" << node.getOutputs() << ")" << std::endl;
455 void OperationDumper::visit(const While &node)
457 VERBOSE(LIR) << "* " << node.name() << std::endl;
458 VERBOSE(LIR) << " - Inputs : "
459 << "Cond subgraph (" << node.param().cond_subg_index << ") Body subgraph ("
460 << node.param().body_subg_index << ") Inputs(" << node.getInputs() << ")"
462 VERBOSE(LIR) << " - Output : Outputs(" << node.getOutputs() << ")" << std::endl;