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 "ir/OperandIndexMap.h"
23 #include "ir/OperationIndexMap.h"
24 #include "backend/Backend.h"
25 #include "backend/IConfig.h"
26 #include "compiler/BackendManager.h"
37 std::string backend_to_fillcolor(const backend::Backend *backend)
39 static const auto map = []() {
40 std::unordered_map<const backend::Backend *, std::string> ret;
41 uint32_t index = 1; // Start from 1 to avoid 0(red) which is too dark :(
42 for (const auto backend : compiler::BackendManager::get().getAll())
44 ret.emplace(backend, Node::BG_COLORS[index]);
45 index = (index + 1) % (sizeof(Node::BG_COLORS) / sizeof(Node::BG_COLORS[0]));
49 auto itr = map.find(backend);
52 return Node::DEFAULT_FILLCOLOR;
60 std::unordered_map<ir::OperandIndex, std::unique_ptr<Operand>>
61 generate_dot_operands(const ir::Graph &graph, const DotDumper::Level level)
63 std::unordered_map<ir::OperandIndex, std::unique_ptr<Operand>> dot_operands;
65 const auto &operands = graph.operands();
66 operands.iterate([&](const ir::OperandIndex &index, const ir::Operand &object) {
68 level == DotDumper::Level::ALL
70 : !object.isConstant() || (graph.getInputs() + graph.getOutputs()).contains(index);
74 using onert::dumper::dot::Operand;
75 if (graph.getInputs().contains(index))
76 return Operand::Type::MODEL_INPUT;
77 if (graph.getOutputs().contains(index))
78 return Operand::Type::MODEL_OUTPUT;
79 return Operand::Type::INTERNAL;
82 auto node = std::make_unique<Operand>(index, type);
83 std::string label = std::to_string(index.value());
84 std::string fillcolor = "";
85 node->setAttribute("label", label);
86 node->setAttribute("fillcolor", fillcolor);
88 dot_operands.emplace(index, std::move(node));
95 ir::OperationIndexMap<std::unique_ptr<Operation>>
96 generate_dot_operations(const ir::Graph &graph,
97 const ir::OperandIndexMap<std::unique_ptr<Operand>> &dot_operands)
99 ir::OperationIndexMap<std::unique_ptr<Operation>> dot_operations;
100 const auto &operations = graph.operations();
101 operations.iterate([&](const ir::OperationIndex &index, const ir::IOperation &op) {
102 auto node = std::make_unique<Operation>(index, op);
104 for (auto &&input : op.getInputs())
106 using onert::dumper::dot::Operand;
108 // Constant input and dump level is ALL_BUT_CONSTANTS
109 if (dot_operands.find(input) == dot_operands.end())
112 auto &input_node = dot_operands.at(input);
113 input_node->addOutEdge(node.get());
116 for (auto &&output : op.getOutputs() | ir::Remove::UNDEFINED)
118 using onert::dumper::dot::Operand;
119 auto &output_node = dot_operands.at(output);
120 node->addOutEdge(output_node.get());
123 dot_operations.emplace(index, std::move(node));
126 return dot_operations;
129 void update_lower_info(const compiler::ILoweredGraph &lowered_graph,
130 ir::OperandIndexMap<std::unique_ptr<Operand>> *dot_operands)
132 const auto &operands = lowered_graph.graph().operands();
133 operands.iterate([&](const ir::OperandIndex &index, const ir::Operand &) {
134 auto itr = dot_operands->find(index);
135 if (itr != dot_operands->end())
137 auto &node = itr->second;
138 // Display LowerInfo attributes
139 std::string label = node->getAttribute("label");
140 std::string fillcolor = node->getAttribute("fillcolor");
141 auto lower_info = lowered_graph.lower_info().operand.getRawPtr(index);
142 const auto &def_factors = lower_info->def_factors();
143 if (def_factors.size() > 0)
146 label += def_factors.getOnlyElement().backend()->config()->id();
148 fillcolor = backend_to_fillcolor(lower_info->def_factors().getOnlyElement().backend());
150 node->setAttribute("label", label);
151 node->setAttribute("fillcolor", fillcolor);
156 void update_lower_info(const compiler::ILoweredGraph &lowered_graph,
157 ir::OperationIndexMap<std::unique_ptr<Operation>> *dot_operations)
159 const auto &operations = lowered_graph.graph().operations();
160 operations.iterate([&](const ir::OperationIndex &index, const ir::IOperation &) {
161 const auto lower_info = lowered_graph.lower_info().operation.getRawPtr(index);
164 auto fillcolor = backend_to_fillcolor(lower_info->backend());
165 std::string backend_label = "[" + lower_info->backend()->config()->id() + "]";
166 auto itr = dot_operations->find(index);
167 if (itr != dot_operations->end())
169 auto &node = itr->second;
170 node->setAttribute("label", node->getAttribute("label") + "\n" + backend_label);
171 node->setAttribute("fillcolor", fillcolor);
177 void dump_to_file(const ir::OperandIndexMap<std::unique_ptr<Operand>> &operand_nodes,
178 const ir::OperationIndexMap<std::unique_ptr<Operation>> &operation_nodes,
179 const std::string &tag)
181 onert::dumper::dot::DotBuilder dot_builder;
182 for (const auto &e : operation_nodes)
183 dot_builder.update(*e.second);
184 for (const auto &e : operand_nodes)
185 dot_builder.update(*e.second);
189 std::string file_name;
194 fb.open(file_name, std::ios::out);
195 std::ostream os(&fb);
197 dot_builder.writeDot(os);
204 void DotDumper::dump(const ir::Graph &graph, const std::string &tag)
206 if (_level == Level::OFF)
211 const auto dot_operands = generate_dot_operands(graph, _level);
212 const auto dot_operations = generate_dot_operations(graph, dot_operands);
213 dump_to_file(dot_operands, dot_operations, tag);
216 // TODO Support derivative tensors
217 void DotDumper::dump(const compiler::ILoweredGraph &lowered_graph, const std::string &tag)
219 if (_level == Level::OFF)
224 auto dot_operands = generate_dot_operands(lowered_graph.graph(), _level);
225 auto dot_operations = generate_dot_operations(lowered_graph.graph(), dot_operands);
226 update_lower_info(lowered_graph, &dot_operands);
227 update_lower_info(lowered_graph, &dot_operations);
228 dump_to_file(dot_operands, dot_operations, tag);
232 } // namespace dumper