1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "DotSerializer.hpp"
7 #include "armnn/utility/StringUtils.hpp"
8 #include <common/include/ProfilingGuid.hpp>
9
10 #include <sstream>
11 #include <cstring>
12
13 namespace armnn
14 {
15
16 namespace
17 {
Indent(int numSpaces)18 std::string Indent(int numSpaces)
19 {
20 std::stringstream ss;
21 for (int i = 0; i < numSpaces; i++)
22 {
23 ss << " ";
24 }
25 return ss.str();
26 }
27
Escape(std::string s)28 std::string Escape(std::string s)
29 {
30 armnn::stringUtils::StringReplaceAll(s, "<", "\\<");
31 armnn::stringUtils::StringReplaceAll(s, ">", "\\>");
32 return s;
33 }
34
35 } //namespace
36
37
HtmlFont(std::ostream & stream,int fontSize,const char * color,const char * face)38 HtmlFont::HtmlFont(std::ostream& stream, int fontSize, const char *color, const char *face)
39 : DotBase(stream)
40 {
41 GetStream() << "<FONT";
42
43 if (fontSize > -1)
44 {
45 GetStream() << " POINT-SIZE=" << "\"" << fontSize << "\"";
46 }
47
48 if (color && std::strlen(color) != 0)
49 {
50 GetStream() << " COLOR=\"" << color << "\" ";
51 }
52
53 if (face && std::strlen(face) != 0)
54 {
55 GetStream() << " FACE=\"" << face << "\" ";
56 }
57
58 GetStream() << ">";
59 }
60
61
HtmlFont(std::ostream & stream)62 HtmlFont::HtmlFont(std::ostream& stream)
63 : HtmlFont(stream, -1, nullptr, nullptr)
64 {}
65
~HtmlFont()66 HtmlFont::~HtmlFont()
67 {
68 GetStream() << "</FONT>";
69 }
70
71
DotAttributeSet(std::ostream & stream)72 DotAttributeSet::DotAttributeSet(std::ostream& stream)
73 : DotBase(stream)
74 {
75 GetStream() << "[";
76 }
77
~DotAttributeSet()78 DotAttributeSet::~DotAttributeSet()
79 {
80 bool doSpace=false;
81 for (auto&& attrib : m_Attributes)
82 {
83 if (doSpace)
84 {
85 GetStream() << " ";
86 }
87
88 GetStream() << attrib;
89 doSpace=true;
90 }
91
92 GetStream() << "]";
93 }
94
AddAttribute(const std::string & name,const std::stringstream & value)95 DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, const std::stringstream& value)
96 {
97 std::stringstream ss;
98 ss << name <<"=" << value.str();
99 m_Attributes.push_back(ss.str());
100 return *this;
101 }
102
AddAttribute(const std::string & name,int value)103 DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, int value)
104 {
105 std::stringstream ss;
106 ss << name <<"=" << value;
107 m_Attributes.push_back(ss.str());
108 return *this;
109 }
110
AddAttribute(const std::string & name,const std::string & value)111 DotAttributeSet & DotAttributeSet::AddAttribute(const std::string& name, const std::string& value)
112 {
113 std::stringstream ss;
114 ss << name <<"=\"" << value << "\"";
115 m_Attributes.push_back(ss.str());
116 return *this;
117 }
118
DotEdge(std::ostream & stream,LayerGuid fromNodeId,LayerGuid toNodeId)119 DotEdge::DotEdge(std::ostream& stream, LayerGuid fromNodeId, LayerGuid toNodeId)
120 : DotBase(stream)
121 {
122 std::stringstream ss;
123 ss << Indent(4) << fromNodeId << " -> " << toNodeId << " ";
124 GetStream() << ss.str();
125
126 m_Attributes = std::make_unique<DotAttributeSet>(stream);
127 }
128
~DotEdge()129 DotEdge::~DotEdge()
130 {
131 m_Attributes.reset(nullptr);
132 GetStream() << ";" << std::endl;
133 }
134
135
NodeContent(std::ostream & stream)136 NodeContent::NodeContent(std::ostream& stream)
137 : DotBase(stream)
138 {
139 }
140
SetName(const std::string & name)141 NodeContent & NodeContent::SetName(const std::string & name)
142 {
143 m_Name = name;
144 return *this;
145 }
146
AddContent(const std::string & content)147 NodeContent & NodeContent::AddContent(const std::string & content)
148 {
149 m_Contents.push_back(content);
150 return *this;
151 }
152
~NodeContent()153 NodeContent::~NodeContent()
154 {
155 std::stringstream ss;
156 ss << "label=\"{" << m_Name;
157 if (!m_Contents.empty())
158 {
159 ss << "|";
160 }
161 for (auto & content : m_Contents)
162 {
163 ss << Escape(content);
164 ss << "\\l";
165 }
166 ss << "}\"";
167
168 std::string s;
169 try
170 {
171 // Coverity fix: std::stringstream::str() may throw an exception of type std::length_error.
172 s = ss.str();
173 }
174 catch (const std::exception&) { } // Swallow any exception.
175
176 GetStream() << s;
177 }
178
DotNode(std::ostream & stream,LayerGuid nodeId,const char * label)179 DotNode::DotNode(std::ostream& stream, LayerGuid nodeId, const char* label)
180 : DotBase(stream)
181 {
182 std::stringstream ss;
183 ss << Indent(4) << nodeId;
184
185 GetStream() << ss.str() << " ";
186
187 m_Contents = std::make_unique<NodeContent>(stream);
188 m_Attributes = std::make_unique<DotAttributeSet>(stream);
189
190 if (std::strlen(label) != 0)
191 {
192 m_Contents->SetName(label);
193 }
194 else
195 {
196 m_Contents->SetName("<noname>");
197 }
198 }
199
~DotNode()200 DotNode::~DotNode()
201 {
202 m_Contents.reset(nullptr);
203 m_Attributes.reset(nullptr);
204 GetStream() << ";" << std::endl;
205 }
206
207
DotDefaults(std::ostream & stream,const char * type)208 DotDefaults::DotDefaults(std::ostream& stream, const char* type)
209 : DotBase(stream)
210 {
211 std::stringstream ss;
212 ss << Indent(4) << type;
213
214 GetStream() << ss.str() << " ";
215 m_Attributes = std::make_unique<DotAttributeSet>(stream);
216 }
217
~DotDefaults()218 DotDefaults::~DotDefaults()
219 {
220 m_Attributes.reset(nullptr);
221 GetStream() << ";" << std::endl;
222 }
223
DotGraph(std::ostream & stream,const char * name)224 DotGraph::DotGraph(std::ostream& stream, const char* name)
225 : DotBase(stream)
226 {
227 GetStream() << "digraph " << name << " {" << std::endl;
228 }
229
~DotGraph()230 DotGraph::~DotGraph()
231 {
232 GetStream() << "}" << std::endl;
233 }
234
235 } //namespace armnn
236
237
238