1# Copyright (c) 2019 ARM Limited 2# All rights reserved. 3# 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. 12# 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. 23# 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. 35# 36# Authors: Tiago Muck 37 38# Creates a visual representation of a Ruby network topology 39 40import os 41import m5 42from m5.util import warn 43try: 44 import pydot 45except: 46 pydot = False 47 48 49def _dot_rgb_to_html(r, g, b): 50 return "#%.2x%.2x%.2x" % (r, g, b) 51 52def _dot_create_router_node(full_path, label): 53 return pydot.Node( \ 54 full_path, \ 55 shape = "Mrecord", \ 56 label = label, \ 57 style = "\"rounded, filled\"", \ 58 color = "#000000", \ 59 fillcolor = _dot_rgb_to_html(204, 230, 252), \ 60 fontname = "Arial", \ 61 fontsize = "14", \ 62 fontcolor = "#000000" \ 63 ) 64 65def _dot_create_ctrl_node(full_path, label): 66 return pydot.Node( \ 67 full_path, \ 68 shape = "Mrecord", \ 69 label = label, \ 70 style = "\"rounded, filled\"", \ 71 color = "#000000", \ 72 fillcolor = _dot_rgb_to_html(229, 188, 208), \ 73 fontname = "Arial", \ 74 fontsize = "14", \ 75 fontcolor = "#000000" \ 76 ) 77 78 79def _dot_create(network, callgraph): 80 for r in network.routers: 81 callgraph.add_node(_dot_create_router_node(r.path(), 82 'R %d' % r.router_id)) 83 84 # One link for each direction but draw one edge only 85 connected = dict() 86 for link in network.int_links: 87 if (link.src_node.path() in connected) and \ 88 (connected[link.src_node.path()] == link.dst_node.path()): 89 continue 90 callgraph.add_edge( 91 pydot.Edge(link.src_node.path(), link.dst_node.path()) 92 ) 93 connected[link.dst_node.path()] = link.src_node.path() 94 95 for link in network.ext_links: 96 ctrl = link.ext_node 97 label = ctrl._name 98 if hasattr(ctrl, '_node_type'): 99 label += ' (' + ctrl._node_type + ')' 100 callgraph.add_node( 101 _dot_create_ctrl_node(ctrl.path(), label) 102 ) 103 104 callgraph.add_edge( 105 pydot.Edge(link.ext_node.path(), link.int_node.path()) 106 ) 107 108def _do_dot(network, outdir, dotFilename): 109 callgraph = pydot.Dot(graph_type='graph', rankdir='LR') 110 _dot_create(network, callgraph) 111 dot_filename = os.path.join(outdir, dotFilename) 112 callgraph.write(dot_filename) 113 try: 114 # dot crashes if the figure is extremely wide. 115 # So avoid terminating simulation unnecessarily 116 callgraph.write_svg(dot_filename + ".svg", prog='neato') 117 callgraph.write_pdf(dot_filename + ".pdf", prog='neato') 118 except: 119 warn("failed to generate dot output from %s", dot_filename) 120 121 122def do_ruby_dot(root, outdir, dotFilename): 123 if not pydot: 124 return 125 126 # Generate a graph for all ruby systems 127 networks = [] 128 for obj in root.descendants(): 129 if isinstance(obj, m5.objects.RubyNetwork): 130 networks.append(obj) 131 132 for network in networks: 133 # We assume each ruby system has a single network 134 rubydotFilename = dotFilename.replace(".dot", 135 "." + network.get_parent().path() + ".dot") 136 _do_dot(network, outdir, rubydotFilename) 137