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.
18 #include <unordered_map>
20 #include "DotDumper.h"
21 #include "DotBuilder.h"
22 #include "DotSubgraphInfo.h"
23 #include "ir/OpSequence.h"
24 #include "ir/OperationIndexMap.h"
25 #include "backend/Backend.h"
26 #include "backend/IConfig.h"
27 #include "compiler/BackendManager.h"
36 void DotDumper::dump(const std::string &tag)
38 if (_level == Level::OFF)
43 onert::dumper::dot::DotBuilder dot_builder;
45 auto &operations = _graph.operations();
46 auto &operands = _graph.operands();
48 ir::OperationIndexMap<std::unique_ptr<Operation>> operation_nodes;
49 std::unordered_map<ir::OperandIndex, std::unique_ptr<Operand>> operand_nodes;
51 auto backend_to_fillcolor = [](const backend::Backend *backend) {
52 static const auto map = []() {
53 std::unordered_map<const backend::Backend *, std::string> ret;
54 uint32_t index = 1; // Start from 1 to avoid 0(red) which is too dark :(
55 for (const auto backend : compiler::BackendManager::get().getAll())
57 ret.emplace(backend, Node::BG_COLORS[index]);
58 index = (index + 1) % (sizeof(Node::BG_COLORS) / sizeof(Node::BG_COLORS[0]));
63 auto itr = map.find(backend);
66 return Node::DEFAULT_FILLCOLOR;
74 util::Set<ir::OperandIndex> shown_operand_set;
76 operands.iterate([&](const ir::OperandIndex &index, const ir::Operand &object) {
77 bool showing_cond = false;
78 if (_level == Level::ALL)
84 showing_cond = !object.isConstant();
86 if (object.isConstant() || _graph.getInputs().contains(index))
88 showing_cond = showing_cond && (object.getUses().size() > 0);
92 shown_operand_set.add(index);
95 using onert::dumper::dot::Operand;
96 if (_graph.getInputs().contains(index))
97 return Operand::Type::MODEL_INPUT;
98 if (_graph.getOutputs().contains(index))
99 return Operand::Type::MODEL_OUTPUT;
100 return Operand::Type::INTERNAL;
103 auto node = std::make_unique<Operand>(index, type);
106 // Display LowerInfo attributes
107 std::string label = std::to_string(index.value());
108 std::string fillcolor = "";
111 auto lower_info = _lowered_graph->getLowerInfo(index);
112 const auto &def_factors = lower_info->def_factors();
113 if (def_factors.size() > 0)
116 label += def_factors.getOnlyElement().backend()->config()->id();
119 fillcolor = backend_to_fillcolor(lower_info->def_factors().getOnlyElement().backend());
122 node->setAttribute("label", label);
123 node->setAttribute("fillcolor", fillcolor);
126 operand_nodes.emplace(index, std::move(node));
130 operations.iterate([&](const ir::OperationIndex &index, const ir::Operation &op) {
131 auto node = std::make_unique<Operation>(index, op);
133 for (auto input : op.getInputs())
135 using onert::dumper::dot::Operand;
137 // Constant input and dump level is ALL_BUT_CONSTANTS
138 if (operand_nodes.find(input) == operand_nodes.end())
141 auto &input_node = operand_nodes.at(input);
142 input_node->addOutEdge(node.get());
145 for (auto output : op.getOutputs())
147 using onert::dumper::dot::Operand;
148 auto &output_node = operand_nodes.at(output);
149 node->addOutEdge(output_node.get());
152 operation_nodes.emplace(index, std::move(node));
157 const auto &op_seqs = _lowered_graph->op_seqs();
158 op_seqs.iterate([&](const ir::OpSequenceIndex &index, const ir::OpSequence &op_seq) {
159 const auto lower_info = _lowered_graph->getLowerInfo(index);
160 auto fillcolor = backend_to_fillcolor(lower_info->backend());
162 std::to_string(index.value()) + " [" + lower_info->backend()->config()->id() + "]";
163 DotSubgraphInfo subgraph_info{index, op_seq, shown_operand_set, _graph.operations()};
164 subgraph_info.label(label);
165 subgraph_info.fillcolor(fillcolor);
166 dot_builder.addOpSequence(subgraph_info);
168 // Set fillcolor of all operations in the op_seq
169 for (const auto &op_idx : op_seq.operations())
171 auto found = operation_nodes.find(op_idx);
172 if (found != operation_nodes.end())
174 auto &&op = found->second;
175 op->setAttribute("fillcolor", fillcolor);
181 for (const auto &e : operation_nodes)
182 dot_builder.update(*e.second);
183 for (const auto &e : operand_nodes)
184 dot_builder.update(*e.second);
188 std::string file_name;
193 fb.open(file_name, std::ios::out);
194 std::ostream os(&fb);
196 dot_builder.writeDot(os);
203 } // namespace dumper