diff options
Diffstat (limited to 'src/python/m5')
-rw-r--r-- | src/python/m5/main.py | 3 | ||||
-rw-r--r-- | src/python/m5/simulate.py | 7 | ||||
-rw-r--r-- | src/python/m5/util/dot_writer.py | 107 |
3 files changed, 116 insertions, 1 deletions
diff --git a/src/python/m5/main.py b/src/python/m5/main.py index deb4725ac..ea2a06e9e 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -91,6 +91,9 @@ def parse_options(): help="Create JSON output of the configuration [Default: %default]") option("--dot-config", metavar="FILE", default="config.dot", help="Create DOT & pdf outputs of the configuration [Default: %default]") + option("--dot-dvfs-config", metavar="FILE", default="config_dvfs.dot", + help="Create DOT & pdf outputs of the DVFS configuration" + \ + " [Default: %default]") # Debugging options group("Debugging Options") diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 5d70f4b18..1d7ebeb9d 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -51,7 +51,7 @@ import stats import SimObject import ticks import objects -from m5.util.dot_writer import do_dot +from m5.util.dot_writer import do_dot, do_dvfs_dot from m5.internal.stats import updateEvents as updateStatEvents from util import fatal @@ -126,6 +126,11 @@ def instantiate(ckpt_dir=None): # Do a fifth pass to connect probe listeners for obj in root.descendants(): obj.regProbeListeners() + # We want to generate the DVFS diagram for the system. This can only be + # done once all of the CPP objects have been created and initialised so + # that we are able to figure out which object belongs to which domain. + do_dvfs_dot(root, options.outdir, options.dot_dvfs_config) + # We're done registering statistics. Enable the stats package now. stats.enable() diff --git a/src/python/m5/util/dot_writer.py b/src/python/m5/util/dot_writer.py index f54d6a1ab..f0ad15adf 100644 --- a/src/python/m5/util/dot_writer.py +++ b/src/python/m5/util/dot_writer.py @@ -35,6 +35,7 @@ # # Authors: Andreas Hansson # Uri Wiener +# Sascha Bischoff ##################################################################### # @@ -256,6 +257,96 @@ def dot_gen_colour(simNode, isPort = False): def dot_rgb_to_html(r, g, b): return "#%.2x%.2x%.2x" % (r, g, b) +# We need to create all of the clock domains. We abuse the alpha channel to get +# the correct domain colouring. +def dot_add_clk_domain(c_dom, v_dom): + label = "\"" + str(c_dom) + "\ :\ " + str(v_dom) + "\"" + label = re.sub('\.', '_', str(label)) + full_path = re.sub('\.', '_', str(c_dom)) + return pydot.Cluster( \ + full_path, \ + shape = "Mrecord", \ + label = label, \ + style = "\"rounded, filled, dashed\"", \ + color = "#000000", \ + fillcolor = "#AFC8AF8F", \ + fontname = "Arial", \ + fontsize = "14", \ + fontcolor = "#000000" \ + ) + +def dot_create_dvfs_nodes(simNode, callgraph, domain=None): + if isRoot(simNode): + label = "root" + 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) + + # create nodes per port + for port_name in simNode._ports.keys(): + port = simNode._port_refs.get(port_name, None) + if port != None: + full_port_name = full_path + "_" + port_name + port_node = dot_create_node(simNode, full_port_name, port_name) + cluster.add_node(port_node) + + # Dictionary of DVFS domains + dvfs_domains = {} + + # recurse to children + if simNode._children: + for c in simNode._children: + child = simNode._children[c] + if isSimObjectVector(child): + for obj in child: + try: + c_dom = obj.__getattr__('clk_domain') + v_dom = c_dom.__getattr__('voltage_domain') + except AttributeError: + # Just re-use the domain from above + c_dom = domain + c_dom.__getattr__('voltage_domain') + pass + + if c_dom == domain or c_dom == None: + dot_create_dvfs_nodes(obj, cluster, domain) + else: + if c_dom not in dvfs_domains: + dvfs_cluster = dot_add_clk_domain(c_dom, v_dom) + dvfs_domains[c_dom] = dvfs_cluster + else: + dvfs_cluster = dvfs_domains[c_dom] + dot_create_dvfs_nodes(obj, dvfs_cluster, c_dom) + else: + try: + c_dom = child.__getattr__('clk_domain') + v_dom = c_dom.__getattr__('voltage_domain') + except AttributeError: + # Just re-use the domain from above + c_dom = domain + c_dom.__getattr__('voltage_domain') + pass + + if c_dom == domain or c_dom == None: + dot_create_dvfs_nodes(child, cluster, domain) + else: + if c_dom not in dvfs_domains: + dvfs_cluster = dot_add_clk_domain(c_dom, v_dom) + dvfs_domains[c_dom] = dvfs_cluster + else: + dvfs_cluster = dvfs_domains[c_dom] + dot_create_dvfs_nodes(child, dvfs_cluster, c_dom) + + for key in dvfs_domains: + cluster.add_subgraph(dvfs_domains[key]) + + callgraph.add_subgraph(cluster) + def do_dot(root, outdir, dotFilename): if not pydot: return @@ -275,3 +366,19 @@ def do_dot(root, outdir, dotFilename): callgraph.write_pdf(dot_filename + ".pdf") except: warn("failed to generate dot output from %s", dot_filename) + +def do_dvfs_dot(root, outdir, dotFilename): + if not pydot: + return + dvfsgraph = pydot.Dot(graph_type='digraph', ranksep='1.3') + dot_create_dvfs_nodes(root, dvfsgraph) + dot_create_edges(root, dvfsgraph) + dot_filename = os.path.join(outdir, dotFilename) + dvfsgraph.write(dot_filename) + try: + # dot crashes if the figure is extremely wide. + # So avoid terminating simulation unnecessarily + dvfsgraph.write_svg(dot_filename + ".svg") + dvfsgraph.write_pdf(dot_filename + ".pdf") + except: + warn("failed to generate dot output from %s", dot_filename) |