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