1# Copyright (c) 2012-2013 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 --- 21 unchanged lines hidden (view full) --- 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: Andreas Hansson 37# Uri Wiener |
38# Sascha Bischoff |
39 40##################################################################### 41# 42# System visualization using DOT 43# 44# While config.ini and config.json provide an almost complete listing 45# of a system's components and connectivity, they lack a birds-eye 46# view. The output generated by do_dot() is a DOT-based figure (as a --- 205 unchanged lines hidden (view full) --- 252 if isPort: 253 r, g, b = map(lambda x: 0.8 * x, (r, g, b)) 254 255 return dot_rgb_to_html(r, g, b) 256 257def dot_rgb_to_html(r, g, b): 258 return "#%.2x%.2x%.2x" % (r, g, b) 259 |
260# We need to create all of the clock domains. We abuse the alpha channel to get 261# the correct domain colouring. 262def dot_add_clk_domain(c_dom, v_dom): 263 label = "\"" + str(c_dom) + "\ :\ " + str(v_dom) + "\"" 264 label = re.sub('\.', '_', str(label)) 265 full_path = re.sub('\.', '_', str(c_dom)) 266 return pydot.Cluster( \ 267 full_path, \ 268 shape = "Mrecord", \ 269 label = label, \ 270 style = "\"rounded, filled, dashed\"", \ 271 color = "#000000", \ 272 fillcolor = "#AFC8AF8F", \ 273 fontname = "Arial", \ 274 fontsize = "14", \ 275 fontcolor = "#000000" \ 276 ) 277 278def dot_create_dvfs_nodes(simNode, callgraph, domain=None): 279 if isRoot(simNode): 280 label = "root" 281 else: 282 label = simNode._name 283 full_path = re.sub('\.', '_', simNode.path()) 284 # add class name under the label 285 label = "\"" + label + " \\n: " + simNode.__class__.__name__ + "\"" 286 287 # each component is a sub-graph (cluster) 288 cluster = dot_create_cluster(simNode, full_path, label) 289 290 # create nodes per port 291 for port_name in simNode._ports.keys(): 292 port = simNode._port_refs.get(port_name, None) 293 if port != None: 294 full_port_name = full_path + "_" + port_name 295 port_node = dot_create_node(simNode, full_port_name, port_name) 296 cluster.add_node(port_node) 297 298 # Dictionary of DVFS domains 299 dvfs_domains = {} 300 301 # recurse to children 302 if simNode._children: 303 for c in simNode._children: 304 child = simNode._children[c] 305 if isSimObjectVector(child): 306 for obj in child: 307 try: 308 c_dom = obj.__getattr__('clk_domain') 309 v_dom = c_dom.__getattr__('voltage_domain') 310 except AttributeError: 311 # Just re-use the domain from above 312 c_dom = domain 313 c_dom.__getattr__('voltage_domain') 314 pass 315 316 if c_dom == domain or c_dom == None: 317 dot_create_dvfs_nodes(obj, cluster, domain) 318 else: 319 if c_dom not in dvfs_domains: 320 dvfs_cluster = dot_add_clk_domain(c_dom, v_dom) 321 dvfs_domains[c_dom] = dvfs_cluster 322 else: 323 dvfs_cluster = dvfs_domains[c_dom] 324 dot_create_dvfs_nodes(obj, dvfs_cluster, c_dom) 325 else: 326 try: 327 c_dom = child.__getattr__('clk_domain') 328 v_dom = c_dom.__getattr__('voltage_domain') 329 except AttributeError: 330 # Just re-use the domain from above 331 c_dom = domain 332 c_dom.__getattr__('voltage_domain') 333 pass 334 335 if c_dom == domain or c_dom == None: 336 dot_create_dvfs_nodes(child, cluster, domain) 337 else: 338 if c_dom not in dvfs_domains: 339 dvfs_cluster = dot_add_clk_domain(c_dom, v_dom) 340 dvfs_domains[c_dom] = dvfs_cluster 341 else: 342 dvfs_cluster = dvfs_domains[c_dom] 343 dot_create_dvfs_nodes(child, dvfs_cluster, c_dom) 344 345 for key in dvfs_domains: 346 cluster.add_subgraph(dvfs_domains[key]) 347 348 callgraph.add_subgraph(cluster) 349 |
350def do_dot(root, outdir, dotFilename): 351 if not pydot: 352 return 353 # * use ranksep > 1.0 for for vertical separation between nodes 354 # especially useful if you need to annotate edges using e.g. visio 355 # which accepts svg format 356 # * no need for hoizontal separation as nothing moves horizonally 357 callgraph = pydot.Dot(graph_type='digraph', ranksep='1.3') 358 dot_create_nodes(root, callgraph) 359 dot_create_edges(root, callgraph) 360 dot_filename = os.path.join(outdir, dotFilename) 361 callgraph.write(dot_filename) 362 try: 363 # dot crashes if the figure is extremely wide. 364 # So avoid terminating simulation unnecessarily 365 callgraph.write_svg(dot_filename + ".svg") 366 callgraph.write_pdf(dot_filename + ".pdf") 367 except: 368 warn("failed to generate dot output from %s", dot_filename) |
369 370def do_dvfs_dot(root, outdir, dotFilename): 371 if not pydot: 372 return 373 dvfsgraph = pydot.Dot(graph_type='digraph', ranksep='1.3') 374 dot_create_dvfs_nodes(root, dvfsgraph) 375 dot_create_edges(root, dvfsgraph) 376 dot_filename = os.path.join(outdir, dotFilename) 377 dvfsgraph.write(dot_filename) 378 try: 379 # dot crashes if the figure is extremely wide. 380 # So avoid terminating simulation unnecessarily 381 dvfsgraph.write_svg(dot_filename + ".svg") 382 dvfsgraph.write_pdf(dot_filename + ".pdf") 383 except: 384 warn("failed to generate dot output from %s", dot_filename) |