util: Add class name to dot graph and output to svg

This patch adds the class name to the label, creates some more space
by increasing the rank separation, and additionally outputs the graph
as an editable SVG in addition to the PDF.
This commit is contained in:
Andreas Hansson
2013-09-04 13:22:58 -04:00
parent 0495b7e9e7
commit 62cf785178

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2012 ARM Limited
# Copyright (c) 2012-2013 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@@ -41,15 +41,16 @@
# System visualization using DOT
#
# While config.ini and config.json provide an almost complete listing
# of a system's components and connectivity, they lack a birds-eye view.
# The output generated by do_dot() is a DOT-based figure (pdf) and its
# source dot code. Nodes are components, and edges represent
# the memory hierarchy: the edges are directed, from a master to a slave.
# Initially all nodes are generated, and then all edges are added.
# do_dot should be called with the top-most SimObject (namely root
# but not necessarily), the output folder and the output dot source
# filename. From the given node, both processes (node and edge creation)
# is performed recursivly, traversing all children of the given root.
# of a system's components and connectivity, they lack a birds-eye
# view. The output generated by do_dot() is a DOT-based figure (as a
# pdf and an editable svg file) and its source dot code. Nodes are
# components, and edges represent the memory hierarchy: the edges are
# directed, from a master to slave. Initially all nodes are
# generated, and then all edges are added. do_dot should be called
# with the top-most SimObject (namely root but not necessarily), the
# output folder and the output dot source filename. From the given
# node, both processes (node and edge creation) is performed
# recursivly, traversing all children of the given root.
#
# pydot is required. When missing, no output will be generated.
#
@@ -70,6 +71,8 @@ def dot_create_nodes(simNode, callgraph):
else:
label = simNode._name
full_path = re.sub('\.', '_', simNode.path())
# add class name under the label
label = "\"" + label + " \\n: " + simNode.__class__.__name__ + "\""
# each component is a sub-graph (cluster)
cluster = dot_create_cluster(simNode, full_path, label)
@@ -155,19 +158,28 @@ def dot_create_node(simNode, full_path, label):
)
# generate color for nodes
# currently a simple grayscale. placeholder for aesthetic programmers.
def dot_gen_color(simNode):
# start off with white
base = (256, 256, 256)
# scale the color based on the depth
depth = len(simNode.path().split('.'))
depth = 256 - depth * 16 * 3
return dot_rgb_to_html(simNode, depth, depth, depth)
# slightly arbitrary, but assume that the depth is less than six
# levels
r, g, b = map(lambda x: x * max(1 - depth / 6.0, 0.3), base)
def dot_rgb_to_html(simNode, r, g, b):
return dot_rgb_to_html(r, g, b)
def dot_rgb_to_html(r, g, b):
return "#%.2x%.2x%.2x" % (r, g, b)
def do_dot(root, outdir, dotFilename):
if not pydot:
return
callgraph = pydot.Dot(graph_type='digraph')
# * use ranksep > 1.0 for for vertical separation between nodes
# especially useful if you need to annotate edges using e.g. visio
# which accepts svg format
# * no need for hoizontal separation as nothing moves horizonally
callgraph = pydot.Dot(graph_type='digraph', ranksep='1.3')
dot_create_nodes(root, callgraph)
dot_create_edges(root, callgraph)
dot_filename = os.path.join(outdir, dotFilename)
@@ -175,6 +187,7 @@ def do_dot(root, outdir, dotFilename):
try:
# dot crashes if the figure is extremely wide.
# So avoid terminating simulation unnecessarily
callgraph.write_svg(dot_filename + ".svg")
callgraph.write_pdf(dot_filename + ".pdf")
except:
warn("failed to generate pdf output from %s", dot_filename)