util: Add colours to the dot output
This patch is adding a splash of colour to the dot output to make it easier to distinguish objects of different types. As a bonus, the pastel-colour palette also makes the output look like a something from the 21st century.
This commit is contained in:
parent
62cf785178
commit
fad36b35c6
1 changed files with 86 additions and 15 deletions
|
@ -129,43 +129,114 @@ def dot_add_edge(simNode, callgraph, full_port_name, peerPort):
|
||||||
callgraph.add_edge(pydot.Edge(full_port_name, peer_port_name))
|
callgraph.add_edge(pydot.Edge(full_port_name, peer_port_name))
|
||||||
|
|
||||||
def dot_create_cluster(simNode, full_path, label):
|
def dot_create_cluster(simNode, full_path, label):
|
||||||
# if you read this, feel free to modify colors / style
|
|
||||||
return pydot.Cluster( \
|
return pydot.Cluster( \
|
||||||
full_path, \
|
full_path, \
|
||||||
shape = "Mrecord", \
|
shape = "Mrecord", \
|
||||||
label = label, \
|
label = label, \
|
||||||
style = "\"rounded, filled\"", \
|
style = "\"rounded, filled\"", \
|
||||||
color = "#000000", \
|
color = "#000000", \
|
||||||
fillcolor = dot_gen_color(simNode), \
|
fillcolor = dot_gen_colour(simNode), \
|
||||||
fontname = "Arial", \
|
fontname = "Arial", \
|
||||||
fontsize = "14", \
|
fontsize = "14", \
|
||||||
fontcolor = "#000000" \
|
fontcolor = "#000000" \
|
||||||
)
|
)
|
||||||
|
|
||||||
def dot_create_node(simNode, full_path, label):
|
def dot_create_node(simNode, full_path, label):
|
||||||
# if you read this, feel free to modify colors / style.
|
|
||||||
# leafs may have a different style => seperate function
|
|
||||||
return pydot.Node( \
|
return pydot.Node( \
|
||||||
full_path, \
|
full_path, \
|
||||||
shape = "Mrecord", \
|
shape = "Mrecord", \
|
||||||
label = label, \
|
label = label, \
|
||||||
style = "\"rounded, filled\"", \
|
style = "\"rounded, filled\"", \
|
||||||
color = "#000000", \
|
color = "#000000", \
|
||||||
fillcolor = "#808080", \
|
fillcolor = dot_gen_colour(simNode, True), \
|
||||||
fontname = "Arial", \
|
fontname = "Arial", \
|
||||||
fontsize = "14", \
|
fontsize = "14", \
|
||||||
fontcolor = "#000000" \
|
fontcolor = "#000000" \
|
||||||
)
|
)
|
||||||
|
|
||||||
# generate color for nodes
|
# an enumerator for different kinds of node types, at the moment we
|
||||||
def dot_gen_color(simNode):
|
# discern the majority of node types, with the caches being the
|
||||||
# start off with white
|
# notable exception
|
||||||
base = (256, 256, 256)
|
class NodeType:
|
||||||
# scale the color based on the depth
|
SYS = 0
|
||||||
depth = len(simNode.path().split('.'))
|
CPU = 1
|
||||||
# slightly arbitrary, but assume that the depth is less than six
|
BUS = 2
|
||||||
# levels
|
MEM = 3
|
||||||
r, g, b = map(lambda x: x * max(1 - depth / 6.0, 0.3), base)
|
DEV = 4
|
||||||
|
OTHER = 5
|
||||||
|
|
||||||
|
# based on the sim object, determine the node type
|
||||||
|
def get_node_type(simNode):
|
||||||
|
if isinstance(simNode, m5.objects.System):
|
||||||
|
return NodeType.SYS
|
||||||
|
# NULL ISA has no BaseCPU or PioDevice, so check if these names
|
||||||
|
# exists before using them
|
||||||
|
elif 'BaseCPU' in dir(m5.objects) and \
|
||||||
|
isinstance(simNode, m5.objects.BaseCPU):
|
||||||
|
return NodeType.CPU
|
||||||
|
elif 'PioDevice' in dir(m5.objects) and \
|
||||||
|
isinstance(simNode, m5.objects.PioDevice):
|
||||||
|
return NodeType.DEV
|
||||||
|
elif isinstance(simNode, m5.objects.BaseBus):
|
||||||
|
return NodeType.BUS
|
||||||
|
elif isinstance(simNode, m5.objects.AbstractMemory):
|
||||||
|
return NodeType.MEM
|
||||||
|
else:
|
||||||
|
return NodeType.OTHER
|
||||||
|
|
||||||
|
# based on the node type, determine the colour as an RGB tuple, the
|
||||||
|
# palette is rather arbitrary at this point (some coherent natural
|
||||||
|
# tones), and someone that feels artistic should probably have a look
|
||||||
|
def get_type_colour(nodeType):
|
||||||
|
if nodeType == NodeType.SYS:
|
||||||
|
return (228, 231, 235)
|
||||||
|
elif nodeType == NodeType.CPU:
|
||||||
|
return (187, 198, 217)
|
||||||
|
elif nodeType == NodeType.BUS:
|
||||||
|
return (111, 121, 140)
|
||||||
|
elif nodeType == NodeType.MEM:
|
||||||
|
return (94, 89, 88)
|
||||||
|
elif nodeType == NodeType.DEV:
|
||||||
|
return (199, 167, 147)
|
||||||
|
elif nodeType == NodeType.OTHER:
|
||||||
|
# use a relatively gray shade
|
||||||
|
return (186, 182, 174)
|
||||||
|
|
||||||
|
# generate colour for a node, either corresponding to a sim object or a
|
||||||
|
# port
|
||||||
|
def dot_gen_colour(simNode, isPort = False):
|
||||||
|
# determine the type of the current node, and also its parent, if
|
||||||
|
# the node is not the same type as the parent then we use the base
|
||||||
|
# colour for its type
|
||||||
|
node_type = get_node_type(simNode)
|
||||||
|
if simNode._parent:
|
||||||
|
parent_type = get_node_type(simNode._parent)
|
||||||
|
else:
|
||||||
|
parent_type = NodeType.OTHER
|
||||||
|
|
||||||
|
# if this node is the same type as the parent, then scale the
|
||||||
|
# colour based on the depth such that the deeper levels in the
|
||||||
|
# hierarchy get darker colours
|
||||||
|
if node_type == parent_type:
|
||||||
|
# start out with a depth of zero
|
||||||
|
depth = 0
|
||||||
|
parent = simNode._parent
|
||||||
|
# find the closes parent that is not the same type
|
||||||
|
while parent and get_node_type(parent) == parent_type:
|
||||||
|
depth = depth + 1
|
||||||
|
parent = parent._parent
|
||||||
|
node_colour = get_type_colour(parent_type)
|
||||||
|
# slightly arbitrary, but assume that the depth is less than
|
||||||
|
# five levels
|
||||||
|
r, g, b = map(lambda x: x * max(1 - depth / 7.0, 0.3), node_colour)
|
||||||
|
else:
|
||||||
|
node_colour = get_type_colour(node_type)
|
||||||
|
r, g, b = node_colour
|
||||||
|
|
||||||
|
# if we are colouring a port, then make it a slightly darker shade
|
||||||
|
# than the node that encapsulates it, once again use a magic constant
|
||||||
|
if isPort:
|
||||||
|
r, g, b = map(lambda x: 0.8 * x, (r, g, b))
|
||||||
|
|
||||||
return dot_rgb_to_html(r, g, b)
|
return dot_rgb_to_html(r, g, b)
|
||||||
|
|
||||||
|
@ -190,4 +261,4 @@ def do_dot(root, outdir, dotFilename):
|
||||||
callgraph.write_svg(dot_filename + ".svg")
|
callgraph.write_svg(dot_filename + ".svg")
|
||||||
callgraph.write_pdf(dot_filename + ".pdf")
|
callgraph.write_pdf(dot_filename + ".pdf")
|
||||||
except:
|
except:
|
||||||
warn("failed to generate pdf output from %s", dot_filename)
|
warn("failed to generate dot output from %s", dot_filename)
|
||||||
|
|
Loading…
Reference in a new issue