Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
net.py
Go to the documentation of this file.
1 # xorn.geda.netlist - gEDA Netlist Extraction and Generation
2 # Copyright (C) 1998-2010 Ales Hvezda
3 # Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
4 # Copyright (C) 2013-2016 Roland Lutz
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ## \namespace xorn.geda.netlist.net
21 ## Grouping local nets with the same name into a net.
22 
23 import sys
24 from gettext import gettext as _
25 
26 class Net:
27  def __init__(self, netlist):
28  self.netlist = netlist
29  self.local_nets = []
30  self.names = { False: [], True: [] }
31  self.namespace = None
32  self.unmangled_name = None
33  self.name = None # set by netlist ctor
34  self.unnamed_counter = None # only for unnamed nets/buses
35  self.is_unconnected_pin = False
36 
37  self.component_pins = []
38  self.connections = None # populated by xorn.geda.netlist.package
39 
41 
42  # populated by xorn.geda.netlist.pp_graphical
44 
45  ## Given an attribute and a wanted attribute, return all the given
46  ## attribute of all the graphical objects connected to this net.
47 
49  self, has_attrib_name, has_attrib_value, wanted_attrib):
50  if not isinstance(has_attrib_name, basestring) or \
51  not isinstance(has_attrib_value, basestring) or \
52  not isinstance(wanted_attrib, basestring):
53  raise ValueError
54 
55  # walk through the list of components, and through the list
56  # of individual pins on each, adding net names to the list
57  # being careful to ignore duplicates, and unconnected pins
58  l = []
59  for cpin in self.graphical_component_pins:
60  if cpin.component.blueprint.get_attribute(has_attrib_name, None) \
61  != has_attrib_value:
62  continue
63  try:
64  l.append(cpin.component.blueprint.get_attribute(wanted_attrib))
65  except KeyError:
66  pass
67  return l
68 
69  def merge_into(self, other):
70  if not isinstance(other, Net):
71  raise ValueError
72  if other.netlist != self.netlist:
73  raise ValueError
74  if other == self:
75  raise ValueError
76 
77  for local_net in self.local_nets:
78  assert local_net.net == self
79  local_net.net = other
80 
81  other.local_nets += self.local_nets
82  for from_netattrib in [False, True]:
83  for name in self.names[from_netattrib]:
84  if name not in other.names[from_netattrib]:
85  other.names[from_netattrib].append(name)
86 
87  del self.local_nets[:]
88  del self.names[False][:]
89  del self.names[True][:]
90 
91  self.netlist.nets.remove(self)
92 
93  def error(self, msg):
94  sys.stderr.write(_("net `%s': error: %s\n") % (self.name, msg))
95  self.netlist.failed = True
96 
97  def warn(self, msg):
98  sys.stderr.write(_("net `%s': warning: %s\n") % (self.name, msg))
99 
100 def postproc_instances(netlist, flat_namespace, prefer_netname_attribute,
101  default_net_name, default_bus_name):
102  netlist.nets = []
103  net_dict = {}
104 
105  # Naming nets
106  for sheet in netlist.sheets:
107  for local_net in sheet.local_nets:
108  # handle netname= attributes
109  # TODO: Ignore netname attributes on buses
110 
111  for net_name, from_netattrib in \
112  [(name, False) for name in local_net.blueprint.names] + \
113  [(net_name, True) for net_name in
114  local_net.blueprint.names_from_net_attribute]:
115  if not isinstance(net_name, basestring):
116  raise ValueError
117 
118  if flat_namespace[from_netattrib] \
119  or sheet.instantiating_component is None:
120  net_name = None, net_name
121  else:
122  net_name = sheet, net_name
123 
124  try:
125  net = net_dict[net_name]
126  except KeyError:
127  net = Net(netlist)
128  netlist.nets.append(net)
129  net_dict[net_name] = net
130 
131  if net_name not in net.names[from_netattrib]:
132  net.names[from_netattrib].append(net_name)
133 
134  if local_net.net == net:
135  continue
136 
137  if local_net.net is None:
138  local_net.net = net
139  net.local_nets.append(local_net)
140  else:
141  a = netlist.nets.index(local_net.net)
142  b = netlist.nets.index(net)
143  dst = netlist.nets[min(a, b)]
144  src = netlist.nets[max(a, b)]
145 
146  for name in set(src.names[False] + src.names[True]):
147  assert net_dict[name] == src
148  net_dict[name] = dst
149 
150  src.merge_into(dst)
151  assert local_net in dst.local_nets
152 
153  # prioritize net names
154  prio = not prefer_netname_attribute
155 
156  for net in netlist.nets:
157  if len(net.names[prio]) == 0:
158  # looking for non-prioritized name
159  if len(net.names[not prio]) == 0:
160  raise AssertionError # shouldn't happen
161  elif len(net.names[not prio]) == 1:
162  net.namespace, net.unmangled_name = net.names[not prio][0]
163  else:
164  netlist.warn(_("net has more than one name: %s")
165  % _(" vs. ").join(
166  _("\"%s\"") % name
167  for ns, name in net.names[not prio]))
168  net.namespace, net.unmangled_name = net.names[not prio][-1]
169  elif len(net.names[prio]) == 1:
170  net.namespace, net.unmangled_name = net.names[prio][0]
171  else:
172  netlist.warn(_("net has more than one name: %s")
173  % _(" vs. ").join("\"%s\"" % name
174  for ns, name in net.names[prio]))
175  net.namespace, net.unmangled_name = net.names[prio][-1]
176 
177  # give all remaining unnamed nets a name
178 
179  unnamed_net_bus_counter = { False: 1, True: 1 }
180  unnamed_pin_counter = 1
181 
182  for component in netlist.components:
183  for cpin in component.cpins:
184  local_net = cpin.local_net
185  assert local_net is not None
186  assert cpin in local_net.cpins
187 
188  net = local_net.net
189  if net is not None:
190  continue
191 
192  # didn't find named net
193  # didn't find previously named
194  net = Net(netlist)
195  netlist.nets.append(net)
196  local_net.net = net
197  net.local_nets.append(local_net)
198 
199  if len(net.local_nets) == 1 and \
200  len(net.local_nets[0].blueprint.pins) == 1 and \
201  not net.local_nets[0].blueprint.net_segments:
202  net.is_unconnected_pin = True
203 
204  net_name = None
205  unnamed_counter = None
206 
207  while net_name is None or net_name in net_dict:
208  # we don't want to assign a dangling pin
209  # which is signified by having only a head node
210  # which is just a place holder
211  # and the head node shows up here
212 
213  if net.is_unconnected_pin:
214  net_name = 'unconnected_pin-%d' % unnamed_pin_counter
215  unnamed_pin_counter += 1
216  else:
217  is_bus = False # there are no busses yet
218 
219  unnamed_counter = unnamed_net_bus_counter[is_bus]
220  unnamed_net_bus_counter[is_bus] += 1
221 
222  if not is_bus:
223  unnamed_string = default_net_name
224  else:
225  unnamed_string = default_bus_name
226 
227  net_name = '%s%d' % (unnamed_string, unnamed_counter)
228 
229  if flat_namespace[False] \
230  or component.sheet.instantiating_component is None:
231  net_name = None, net_name
232  else:
233  net_name = component.sheet, net_name
234 
235  net.namespace, net.unmangled_name = net_name
236  net.unnamed_counter = unnamed_counter
237  net_dict[net_name] = net
238 
239  # reorder nets
240 
241  # walk through the list of components, and through the list of
242  # individual pins on each, adding nets to the list being careful
243  # to ignore duplicates
244 
245  # Searching for an element in a list is incredibly inefficient.
246  # It is *much* better to keep a set as reference.
247 
248  nets = []
249  net_set = set()
250 
251  for component in netlist.components:
252  for cpin in component.cpins:
253  if cpin.local_net.net not in net_set:
254  # add the net to the list
255  nets.append(cpin.local_net.net)
256  net_set.add(cpin.local_net.net)
257 
258  #for local_net in cpin.local_net.net.local_nets:
259  # net._cpins += local_net.cpins
260 
261  assert sorted(netlist.nets) == sorted(nets)
262  netlist.nets = nets
def postproc_instances
Definition: net.py:101
def graphical_objs_with_attrib_get_attrib
Given an attribute and a wanted attribute, return all the given attribute of all the graphical object...
Definition: net.py:49