c1c5ff3ac5def1558188b3d3e55900d651a71297
1 # Copyright (c) 2012 ARM Limited
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
13 # Redistribution and use in source and binary forms, with or without
14 # modification, are permitted provided that the following conditions are
15 # met: redistributions of source code must retain the above copyright
16 # notice, this list of conditions and the following disclaimer;
17 # redistributions in binary form must reproduce the above copyright
18 # notice, this list of conditions and the following disclaimer in the
19 # documentation and/or other materials provided with the distribution;
20 # neither the name of the copyright holders nor the names of its
21 # contributors may be used to endorse or promote products derived from
22 # this software without specific prior written permission.
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 # Authors: Andreas Hansson
39 #####################################################################
41 # System visualization using DOT
43 # While config.ini and config.json provide an almost complete listing
44 # of a system's components and connectivity, they lack a birds-eye view.
45 # The output generated by do_dot() is a DOT-based figure (pdf) and its
46 # source dot code. Nodes are components, and edges represent
47 # the memory hierarchy: the edges are directed, from a master to a slave.
48 # Initially all nodes are generated, and then all edges are added.
49 # do_dot should be called with the top-most SimObject (namely root
50 # but not necessarily), the output folder and the output dot source
51 # filename. From the given node, both processes (node and edge creation)
52 # is performed recursivly, traversing all children of the given root.
54 # pydot is required. When missing, no output will be generated.
56 #####################################################################
59 from m5
.SimObject
import isRoot
, isSimObjectVector
65 # need to create all nodes (components) before creating edges (memory channels)
66 def dot_create_nodes(simNode
, callgraph
):
71 full_path
= re
.sub('\.', '_', simNode
.path())
73 # each component is a sub-graph (cluster)
74 cluster
= dot_create_cluster(simNode
, full_path
, label
)
76 # create nodes per port
77 for port_name
in simNode
._ports
.keys():
78 port
= simNode
._port
_refs
.get(port_name
, None)
80 full_port_name
= full_path
+ "_" + port_name
81 port_node
= dot_create_node(simNode
, full_port_name
, port_name
)
82 cluster
.add_node(port_node
)
86 for c
in simNode
._children
:
87 child
= simNode
._children
[c
]
88 if isSimObjectVector(child
):
90 dot_create_nodes(obj
, cluster
)
92 dot_create_nodes(child
, cluster
)
94 callgraph
.add_subgraph(cluster
)
96 # create all edges according to memory hierarchy
97 def dot_create_edges(simNode
, callgraph
):
98 for port_name
in simNode
._ports
.keys():
99 port
= simNode
._port
_refs
.get(port_name
, None)
101 full_path
= re
.sub('\.', '_', simNode
.path())
102 full_port_name
= full_path
+ "_" + port_name
103 port_node
= dot_create_node(simNode
, full_port_name
, port_name
)
105 if type(port
) is m5
.params
.PortRef
:
106 dot_add_edge(simNode
, callgraph
, full_port_name
, port
)
108 for p
in port
.elements
:
109 dot_add_edge(simNode
, callgraph
, full_port_name
, p
)
111 # recurse to children
112 if simNode
._children
:
113 for c
in simNode
._children
:
114 child
= simNode
._children
[c
]
115 if isSimObjectVector(child
):
117 dot_create_edges(obj
, callgraph
)
119 dot_create_edges(child
, callgraph
)
121 def dot_add_edge(simNode
, callgraph
, full_port_name
, peerPort
):
122 if peerPort
.role
== "MASTER":
123 peer_port_name
= re
.sub('\.', '_', peerPort
.peer
.simobj
.path() \
124 + "." + peerPort
.peer
.name
)
125 callgraph
.add_edge(pydot
.Edge(full_port_name
, peer_port_name
))
127 def dot_create_cluster(simNode
, full_path
, label
):
128 # if you read this, feel free to modify colors / style
129 return pydot
.Cluster( \
133 style
= "\"rounded, filled\"", \
135 fillcolor
= dot_gen_color(simNode
), \
136 fontname
= "Arial", \
138 fontcolor
= "#000000" \
141 def dot_create_node(simNode
, full_path
, label
):
142 # if you read this, feel free to modify colors / style.
143 # leafs may have a different style => seperate function
148 style
= "\"rounded, filled\"", \
150 fillcolor
= "#808080", \
151 fontname
= "Arial", \
153 fontcolor
= "#000000" \
156 # generate color for nodes
157 # currently a simple grayscale. placeholder for aesthetic programmers.
158 def dot_gen_color(simNode
):
159 depth
= len(simNode
.path().split('.'))
160 depth
= 256 - depth
* 16 * 3
161 return dot_rgb_to_html(simNode
, depth
, depth
, depth
)
163 def dot_rgb_to_html(simNode
, r
, g
, b
):
164 return "#%.2x%.2x%.2x" % (r
, g
, b
)
166 def do_dot(root
, outdir
, dotFilename
):
169 callgraph
= pydot
.Dot(graph_type
='digraph')
170 dot_create_nodes(root
, callgraph
)
171 dot_create_edges(root
, callgraph
)
172 dot_filename
= os
.path
.join(outdir
, dotFilename
)
173 callgraph
.write(dot_filename
)
175 # dot crashes if the figure is extremely wide.
176 # So avoid terminating simulation unnecessarily
177 callgraph
.write_pdf(dot_filename
+ ".pdf")
179 print "warning: failed to generate pdf output from %s" % dot_filename