File: graph.py

package info (click to toggle)
tinyos-tools 1.4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 3,140 kB
  • ctags: 1,626
  • sloc: cpp: 10,398; sh: 1,229; python: 1,200; ansic: 562; makefile: 305; xml: 24
file content (154 lines) | stat: -rw-r--r-- 6,134 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Copyright (c) 2005 Intel Corporation
# All rights reserved.
#
# This file is distributed under the terms in the attached INTEL-LICENSE     
# file. If you do not find these files, copies can be found by writing to
# Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
# 94704.  Attention:  Intel License Inquiry.

# Generate the picture and cmap for a configuration's wiring

from xml.dom.minidom import *
from nesdoc.utils import *
from nesdoc.generators import *
from sys import *
from os import system

def generate_component_graph(comp):
  generate_graph("chtml", "..", comp, xml_tag(comp, "wiring"),
                 comp.getAttribute("qname"), comp.getAttribute("nicename"))
  
def generate_graph(dir, repository, xml, wiring, name, nicename):
  if not wiring:
    return

  # Return the element definition for a given wiring endpoint
  def lookup_elem(endpoint):
    elemref = xml_tagset(endpoint, [ "interface-ref", "function-ref" ])
    return refidx[elemref.getAttribute("ref")]

  # Define nodes in a dot graph file. Each node is given a name, a graphic
  # style and a label. The elements map is updated to record the mapping
  # from XML node names ("ref" attribute) and dot-file node names.
  #   gf is the dot graph file
  #   wire is a wiring graph edge
  #   tag specifies which node to extract from wire (either "to" or "from")
  # Does nothing if the node has already been added.
  def add_node(gf, wire, tag):
    endpoint = xml_tag(wire, tag)
    elem = lookup_elem(endpoint)
    ref = elem.getAttribute("ref")
    if endpoints.has_key(ref): return
    
    compref = xml_tag(lookup_elem(endpoint), "component-ref")
    if compref.getAttribute("qname") == name:
      # reference to one's own interfaces become ellipses
      endpoints[ref] = "n%s" % ref
      gf.write('  %s [shape=ellipse, style=filled, label="%s", fontsize=12];\n' % (endpoints[ref], elem.getAttribute("name")))
    else:
      # references to interfaces or functions of other components become
      # a reference to a box representing that component.
      # each instance of a generic component gets a separate box.
      # there is a link to the component's own HTML file.

      ncompname = compref.getAttribute("qname")
      ncomp = compidx[ncompname]
      # Map this function or interface to the component (note that different
      # instances of generic components have different qnames)
      endpoints[ref] = ncompname

      # Define the component style. We may define it several times, but all
      # definitions are identical...
      gf.write('  "%s" ' % ncompname)
      styles = ["fontsize=12"]
      if xml_tag(ncomp, "configuration"):
        # configurations gets a double box
        styles.append("shape=box,peripheries=2")
      else:
        styles.append("shape=box")

      # Check for generic component instances
      instance = xml_tag(ncomp, "instance")
      if instance:
        # Make these dashed, with a label showing the generic component
        # and the instance name
        styles.append("style=dashed")
        iname = ncompname[find(ncompname, ".") + 1:]
        instanceof = xml_tag(instance, "component-ref")
        instanceof_name = instanceof.getAttribute("qname")
        if iname == instanceof_name:
          styles.append('label="%s"' % instanceof_name)
        else:
          styles.append('label="%s\\n(%s)"' % (instanceof_name, iname))
        styles.append('URL="%s/chtml/%s.html"' % (repository, instanceof.getAttribute("nicename")))
      else:
        # Just a regular component
        styles.append('URL="%s/chtml/%s.html"' % (repository, ncomp.getAttribute("nicename")))
      if styles != []:
        gf.write("[%s]" % join(styles, ", "))
      gf.write(";\n")
    
  
  def compname(endpoint):
    return endpoints[lookup_elem(endpoint).getAttribute("ref")]

  def wirestyle(endpoint):
    elem = lookup_elem(endpoint)
    if elem.tagName == "function":
      # missing: bold style for parameterised functions
      styles = ['label="%s"' % function_signature_str(elem, lambda (name): "X")]
    else:
      assert elem.tagName == "interface"
      instance = xml_tag(elem, "instance")
      idef = xml_tag(instance, "interfacedef-ref")
      arguments = xml_tag(instance, "arguments")
      parameters = xml_tag(elem, "interface-parameters")
      def_name = idef.getAttribute("qname")

      sig = def_name
      if arguments:
        iargs = join(map(lambda (arg): typename_str(arg, ""),
                         xml_elements(arguments)), ", ")
        sig += "<" + iargs + ">"
      if parameters:
        iparms = join(map(lambda (arg): typename_str(arg, ""),
                          xml_elements(parameters)),  ", ")
        sig += "[" + iparms + "]"
      styles = [ 'label="%s"' % sig ]
      if xml_tag(elem, "interface-parameters"):
        styles.append('style=bold')
      styles.append('URL="%s/ihtml/%s.html"' % (repository, idef.getAttribute("nicename")))
    styles.append("fontsize=10")
    return styles


  # build indices from ref attribute values to the corresponding elements
  refidx = {}
  compidx = {}
  for intf in xml.getElementsByTagName("interface"):
    refidx[intf.getAttribute("ref")] = intf
  for fn in xml.getElementsByTagName("function"):
    refidx[fn.getAttribute("ref")] = fn
  for ncomp in xml.getElementsByTagName("component"):
    compidx[ncomp.getAttribute("qname")] = ncomp
  
  # create the dot graph specification
  gf = file("%s/%s.dot" % (dir, nicename), "w")
  gf.write('digraph "%s" {\n' % nicename)
  
  endpoints = {}
  for wire in wiring.getElementsByTagName("wire"):
    add_node(gf, wire, "from")
    add_node(gf, wire, "to")
    
  for wire in wiring.getElementsByTagName("wire"):
    src = xml_tag(wire, "from")
    dest = xml_tag(wire, "to")
    gf.write('  "%s" -> "%s"' % (compname(src), compname(dest)))
    gf.write(' [%s];\n' % join(wirestyle(src), ", "))
  gf.write("}\n")
  gf.close()

  # Run dot twice to get a picture and cmap
  system("dot -Tpng -o%s/%s.png %s/%s.dot" % (dir, nicename, dir, nicename))
  system("dot -Tcmap -o%s/%s.cmap %s/%s.dot" % (dir, nicename, dir, nicename))