Wall cleanup, optimize ssd_multibox
[tidl/tidl-api.git] / viewer / dot_graph.cpp
1 /******************************************************************************
2  * Copyright (c) 2017-2018, Texas Instruments Incorporated - http://www.ti.com/
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *      * Redistributions of source code must retain the above copyright
8  *        notice, this list of conditions and the following disclaimer.
9  *      * Redistributions in binary form must reproduce the above copyright
10  *        notice, this list of conditions and the following disclaimer in the
11  *        documentation and/or other materials provided with the distribution.
12  *      * Neither the name of Texas Instruments Incorporated nor the
13  *        names of its contributors may be used to endorse or promote products
14  *        derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  *  THE POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
28 #include "dot_graph.h"
30 using Edge   =  boost::graph_traits<Graph>::edge_descriptor;
32 template<typename T>
33 using VertexPropertyMap =
34               typename boost::property_map<T, boost::vertex_attribute_t>::type;
36 template<typename T>
37 using EdgePropertyMap =
38               typename boost::property_map<T, boost::edge_attribute_t>::type;
40 using LayerIdMap = std::map<uint32_t, Graph*>;
42 static const char* FILLED = "filled";
43 static const char* LABEL  = "label";
44 static const char* COLOR  = "color";
45 static const char* STYLE  = "style";
46 static const char* SHAPE  = "shape";
47 static const char* BOLD   = "bold";
49 static const char* GetVertexColor(uint32_t layer_type);
50 static std::string PoolingProperties(const sTIDL_PoolingParams_t& p);
51 static std::string BiasProperties(const sTIDL_BiasParams_t& p);
52 static std::string ReLUProperties(const sTIDL_ReLUParams_t& p);
55 DotGraph::DotGraph(const sTIDL_Network_t& net):
56                     graph_m(net.numLayers), net_m(net)
57 {
58     AddVertices();
59     AddEdges();
60     AddMetaData();
61 }
64 void DotGraph::AddVertices()
65 {
66     // Add a vertex for each layer
67     LayerIdMap layerid_map;
68     for (int i = 0 ; i < net_m.numLayers; i++)
69     {
70         const sTIDL_Layer_t& layer = net_m.TIDLLayers[i];
72         // Special handling for input & output data layers:
73         // Do not put them in the same subgraph
74         if (layer.layerType == TIDL_DataLayer)
75         {
76             auto V = vertex(i, graph_m);
77             VertexPropertyMap<Graph> vpm = boost::get(vertex_attribute, graph_m);
78             vpm[V][LABEL] = TIDL_LayerString[layer.layerType];
79             vpm[V][COLOR] = GetVertexColor(layer.layerType);
80             vpm[V][STYLE] = FILLED;
81             vpm[V][SHAPE] = "ellipse";
83             continue;
84         }
86         // Use the layer group ID to create subgraphs
87         // Place all layers with the same ID into a single subgraph
88         uint32_t layerGroupId = layer.layersGroupId;
89         Graph* sub = nullptr;
90         if (layerid_map.find(layerGroupId) == layerid_map.end())
91         {
92             sub = &(graph_m.create_subgraph());
93             layerid_map[layerGroupId] = sub;
94             get_property(*sub, graph_name) = std::string("cluster") +
95                                              std::to_string(layerGroupId);
96             get_property(*sub, graph_graph_attribute)[LABEL] =
97                                     "Group " + std::to_string(layerGroupId);
98             get_property(*sub, graph_graph_attribute)[STYLE] = BOLD;
99         }
100         else
101             sub = layerid_map[layerGroupId];
103         auto V = add_vertex(i, *sub);
105         AddVertexProperties(V, sub, layer, i);
106     }
110 void DotGraph::AddVertexProperties(Vertex& V, Graph* g,
111                                    const sTIDL_Layer_t& layer,
112                                    int index)
114     VertexPropertyMap<Graph> vpm = boost::get(vertex_attribute, *g);
115     vpm[V][COLOR] = GetVertexColor(layer.layerType);
116     vpm[V][STYLE] = BOLD;
117     vpm[V]["xlabel"] = std::to_string(index);
118     vpm[V][LABEL] = "{";
120     switch (layer.layerType)
121     {
122         case TIDL_ConvolutionLayer:
123         {
124             vpm[V][LABEL] += TIDL_LayerString[layer.layerType];
125             const sTIDL_ConvParams_t& p = layer.layerParams.convParams;
126             vpm[V][LABEL] += " " + std::to_string(p.kernelW) + "x" +
127                              std::to_string(p.kernelH);
129             if (p.enablePooling)
130                 vpm[V][LABEL] += "|" + PoolingProperties(p.poolParams);
132             if (p.enableRelU)
133                 vpm[V][LABEL] += "|" + ReLUProperties(p.reluParams);
135             if (p.enableBias)
136                 vpm[V][LABEL] += "|" +
137                                  std::string(TIDL_LayerString[TIDL_BiasLayer]);
139             break;
140         }
142         case TIDL_PoolingLayer:
143         {
144             const sTIDL_PoolingParams_t& p = layer.layerParams.poolParams;
145             vpm[V][LABEL] += PoolingProperties(p);
146             break;
147         }
149         case TIDL_BiasLayer:
150         {
151             const sTIDL_BiasParams_t& p = layer.layerParams.biasParams;
152             vpm[V][LABEL] += BiasProperties(p);
153             break;
154         }
156         case TIDL_ReLULayer:
157         {
158             const sTIDL_ReLUParams_t& p = layer.layerParams.reluParams;
159             vpm[V][LABEL] += ReLUProperties(p);
160             break;
161         }
163         case TIDL_EltWiseLayer:
164         {
166             vpm[V][LABEL] += TIDL_LayerString[layer.layerType];
167             const sTIDL_EltWiseParams_t& p = layer.layerParams.eltWiseParams;
168             if (p.eltWiseType == TIDL_EltWiseProduct)
169                 vpm[V][LABEL] += " Product";
170             else if (p.eltWiseType == TIDL_EltWiseSum)
171                 vpm[V][LABEL] += " Sum";
172             else if (p.eltWiseType == TIDL_EltWiseMax)
173                 vpm[V][LABEL] += " Max";
175             break;
176         }
178         default:
179             vpm[V][LABEL] += TIDL_LayerString[layer.layerType];
180             break;
181     }
183     vpm[V][LABEL] += "}";
187 void DotGraph::AddEdges()
189     // Add edges based on dataId i.e. there is an edge from layer A -> B
190     // iff dataId is in outData for A and inData for B.
191     EdgePropertyMap<Graph> ep = boost::get(boost::edge_attribute, graph_m);
192     for (int i = 0 ; i < net_m.numLayers; i++)
193     {
194         const sTIDL_Layer_t& layer = net_m.TIDLLayers[i];
196         if (layer.numOutBufs < 0)
197             continue;
199         // Create a string to  annotate the edge - num_channels, height, width
200         const sTIDL_DataParams_t& outData = layer.outData[0];
201         int32_t out_id = outData.dataId;
202         std::string edge_info = std::to_string(outData.dimValues[1])+ "x" +
203                                 std::to_string(outData.dimValues[2])+ "x" +
204                                 std::to_string(outData.dimValues[3]);
206         for (int j = 0; j < net_m.numLayers; j++)
207         {
208             if (j == i) continue;
210             for (int x = 0; x < net_m.TIDLLayers[j].numInBufs; x++)
211                 if (net_m.TIDLLayers[j].inData[x].dataId == out_id)
212                 {
213                     Edge e = add_edge(i, j, graph_m).first;
214                     ep[e][LABEL] = edge_info;
215                 }
217         }
218     }
222 void DotGraph::AddMetaData()
224     get_property(graph_m, graph_name) = "TIDL Network";
225     get_property(graph_m, graph_vertex_attribute)[SHAPE] = "Mrecord";
226     get_property(graph_m, graph_graph_attribute)["fontname"] = "Arial";
227     get_property(graph_m, graph_vertex_attribute)["fontname"] = "Arial";
228     get_property(graph_m, graph_vertex_attribute)["fontsize"] = "12";
229     get_property(graph_m, graph_edge_attribute)["fontname"] = "Arial";
230     get_property(graph_m, graph_edge_attribute)["fontsize"] = "10";
234 // Generate dot file from boost graph
235 void DotGraph::Write(const std::string& filename) const
237     std::ofstream dot(filename);
238     boost::write_graphviz(dot, graph_m);
241 std::string PoolingProperties(const sTIDL_PoolingParams_t& p)
243     std::string s = TIDL_LayerString[TIDL_PoolingLayer];
245     if (p.poolingType == TIDL_MaxPooling)
246         s += " Max";
247     else if (p.poolingType == TIDL_AveragePooling)
248         s += " Average";
250     if (p.kernelW != 0 && p.kernelH != 0)
251         s+= "\\n" + std::to_string(p.kernelW) + "x" + std::to_string(p.kernelH);
253     return s;
256 std::string ReLUProperties(const sTIDL_ReLUParams_t& p)
258     std::string s;
260     if (p.reluType == TIDL_RelU)
261         s += "ReLU";
262     else if (p.reluType == TIDL_PRelU)
263         s += "PReLU";
264     else if (p.reluType == TIDL_RelU6)
265         s += "ReLU6";
267     return s;
270 std::string BiasProperties(const sTIDL_BiasParams_t& p)
272     std::string s = TIDL_LayerString[TIDL_BiasLayer];
273     s += "\\n (BQ: " + std::to_string(p.biasQ) + ")";
274     return s;
279 const char* GetVertexColor(uint32_t layer_type)
281     static const char* LayerColors[] =
282     {
283         "lightblue",
284         "red",
285         "darkorange",
286         "royalblue",
287         "darkgreen",
288         "yellow",
289         "magenta",
290         "darkviolet",
291         "brown",
292         "darksalmon",
293         "violet",
294         "darkturquoise",
295         "darkseagreen",
296         "limegreen"
298     };
300     return LayerColors[layer_type % (sizeof(LayerColors)/sizeof(char *))];
304 const char* TIDL_LayerString[] =
306     "Data",
307     "Convolution",
308     "Pooling",
309     "ReLU",
310     "PReLU",
311     "EltWise",
312     "InnerProduct",
313     "SoftMax",
314     "BatchNorm",
315     "Bias",
316     "Scale",
317     "Deconv2D",
318     "Concat",
319     "Split",
320     "Slice",
321     "Crop",
322     "Flatten",
323     "DropOut",
324     "ArgMax",
325     "DetectionOutput",
326     "Reshape",
327 };