diff -r 70ef8cbec4fe -r 2d964402b9fc src/python/m5/SimObject.py --- a/src/python/m5/SimObject.py Wed May 02 16:08:49 2012 -0400 +++ b/src/python/m5/SimObject.py Wed May 02 16:09:02 2012 -0400 @@ -1061,42 +1061,105 @@ self._ccObject.takeOverFrom(old_cpu._ccObject) # generate output file for 'dot' to display as a pretty graph. - def outputDot(self, dot): + # need to create all nodes (components) before creating edges (memory channels) + def dotCreateNodes(self, callgraph): if isRoot(self): - label = "{root|" + label = "root" else: - label = "{%s|" % self._name + label = self._name + full_path = re.sub('\.', '_', self.path()) - if isSimObject(self._base): - label += '%s|' % self.type + # each component is a sub-graph (cluster) + cluster = self.dotCreateCluster(full_path, label) + # create nodes per port + for port_name in self._ports.keys(): + port = self._port_refs.get(port_name, None) + if port != None: + full_port_name = full_path + "_" + port_name + port_node = self.dotCreateNode(full_port_name, port_name) + cluster.add_node(port_node) + + # recurse to children if self._children: for c in self._children: child = self._children[c] if isSimObjectVector(child): for obj in child: - dot.add_edge(pydot.Edge(self.path(), obj.path(), style="bold")) + obj.dotCreateNodes(cluster) else: - dot.add_edge(pydot.Edge(self.path(), child.path(), style="bold")) + child.dotCreateNodes(cluster) - for param in self._params.keys(): - value = self._values.get(param) - if value != None: - ini_str_value = self._values[param].ini_str() - label += '%s = %s\\n' % (param, re.sub(':', '-', ini_str_value)) + callgraph.add_subgraph(cluster) - label += '}' + # create all edges according to memory hierarchy + def dotCreateEdges(self, callgraph): + for port_name in self._ports.keys(): + port = self._port_refs.get(port_name, None) + if port != None: + full_path = re.sub('\.', '_', self.path()) + full_port_name = full_path + "_" + port_name + port_node = self.dotCreateNode(full_port_name, port_name) + # create edges + if type(port) is m5.params.PortRef: + self.dotAddEdge(callgraph, full_port_name, port) + else: + for p in port.elements: + self.dotAddEdge(callgraph, full_port_name, p) - dot.add_node(pydot.Node(self.path(), shape="Mrecord",label=label)) + # recurse to children + if self._children: + for c in self._children: + child = self._children[c] + if isSimObjectVector(child): + for obj in child: + obj.dotCreateEdges(callgraph) + else: + child.dotCreateEdges(callgraph) - # recursively dump out children - for c in self._children: - child = self._children[c] - if isSimObjectVector(child): - for obj in child: - obj.outputDot(dot) - else: - child.outputDot(dot) + def dotAddEdge(self, callgraph, full_port_name, peerPort): + if peerPort.role == "MASTER": + peer_port_name = re.sub('\.', '_', peerPort.peer.simobj.path() \ + + "." + peerPort.peer.name) + callgraph.add_edge(pydot.Edge(full_port_name, peer_port_name)) + + def dotCreateCluster(self, full_path, label): + # if you read this, feel free to modify colors / style + return pydot.Cluster( \ + full_path, \ + shape = "Mrecord", \ + label = label, \ + style = "\"rounded, filled\"", \ + color = "#000000", \ + fillcolor = self.dotGenColor(), \ + fontname = "Arial", \ + fontsize = "14", \ + fontcolor = "#000000" \ + ) + + def dotCreateNode(self, full_path, label): + # if you read this, feel free to modify colors / style. + # leafs may have a different style => seperate function + return pydot.Node( \ + full_path, \ + shape = "Mrecord", \ + label = label, \ + style = "\"rounded, filled\"", \ + color = "#000000", \ + fillcolor = "#808080", \ + fontname = "Arial", \ + fontsize = "14", \ + fontcolor = "#000000" \ + ) + # generate color for nodes + # currently a simple grayscale. placeholder for aesthetic programmers. + def dotGenColor(self): + depth = len(self.path().split('.')) + depth = 256 - depth * 16 * 3 + return self.dotRgbToHtml(depth, depth, depth) + + def dotRgbToHtml(self, r, g, b): + return "#%.2x%.2x%.2x" % (r, g, b) # Function to provide to C++ so it can look up instances based on paths def resolveSimObject(name): diff -r 70ef8cbec4fe -r 2d964402b9fc src/python/m5/simulate.py --- a/src/python/m5/simulate.py Wed May 02 16:08:49 2012 -0400 +++ b/src/python/m5/simulate.py Wed May 02 16:09:02 2012 -0400 @@ -1,3 +1,15 @@ +# Copyright (c) 2012 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2005 The Regents of The University of Michigan # Copyright (c) 2010 Advanced Micro Devices, Inc. # All rights reserved. @@ -122,15 +134,17 @@ def doDot(root): from m5 import options - dot = pydot.Dot() - root.outputDot(dot) - dot.orientation = "portrait" - dot.size = "8.5,11" - dot.ranksep="equally" - dot.rank="samerank" + callgraph = pydot.Dot(graph_type='digraph') + root.dotCreateNodes(callgraph) + root.dotCreateEdges(callgraph) dot_filename = os.path.join(options.outdir, options.dot_config) - dot.write(dot_filename) - dot.write_pdf(dot_filename + ".pdf") + callgraph.write(dot_filename) + try: + # dot crashes if the figure is extremely wide. + # So avoid terminating simulation unnecessarily + callgraph.write_pdf(dot_filename + ".pdf") + except: + print "warning: failed to generate pdf output from %s" % dot_filename need_resume = [] need_startup = True