Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
guile.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.guile
21 ## Scheme API for retrieving netlist information.
22 #
23 # This module mirrors the gnetlist Scheme API which exposes the
24 # results of a netlister run to a netlist backend written in Scheme.
25 # For each gnetlist API function, this module contains an equivalent
26 # Python function and makes it available by creating a top-level
27 # Scheme binding.
28 #
29 # The gnetlist API included a function \c gnetlist:get-renamed-nets
30 # which returned a list of "renamed nets" and could be used to unit
31 # test the internals of the netlister. Due to the way nets are
32 # handled, the concept of a "renamed net" isn't applicable and this
33 # function isn't supported any more.
34 #
35 # Some functions take a dummy argument "level" which must be a string
36 # but is otherwise ignored.
37 
38 import sys
39 from gettext import gettext as _
40 import xorn.guile
41 import xorn.geda.attrib
42 
43 ## Global netlist object.
44 # Set this to the netlist to be inspected.
45 the_netlist = None
46 
47 ## Global backend argument list.
48 # Set this to the actual list of arguments.
49 the_backend_arguments = None
50 
51 ## Global backend verbosity flag.
52 # Set this to \c 1 if a \c `-v' option has been passed, to \c -1 if a
53 # \c `-q' option has been passed, to \c 0 otherwise.
54 the_verbosity = None
55 
56 ## Whether to return net names appropriate for SPICE backends.
57 # Set this to \c True or \c False depending on whether the backend
58 # expects the API functions to return SPICE net names.
59 # \see spicified_net_name
60 the_spice_mode = None
61 
62 ## Helper function for checking the type of an API function argument.
63 #
64 # When constructing an error message, \a fun and \a i are used to
65 # indicate the API function and argument index, respectively.
66 #
67 # \throws TypeError if \a arg is not an instance of \a t or of a
68 # subclass thereof
69 
70 def check_argument_type(fun, i, arg, t):
71  if not isinstance(arg, t):
72  raise TypeError, '"%s" argument %d must be %s, not %s' % (
73  fun, i, t.__name__, arg.__class__.__name__)
74 
75 ## Return the net name visible through the API.
76 #
77 # If the name of the invoked backend starts with \c "spice", \c
78 # gnetlist omits the \c "unnamed_net" net name prefix. Here, however,
79 # the generated netlist is independent of the backend, so the API
80 # needs to fix up the net name before passing it to the backend.
81 #
82 # If \ref the_spice_mode isn't true when evaluated in a boolean
83 # context, this function just returns \a net.name.
84 
86  if the_spice_mode and net.unnamed_counter is not None:
87  return str(net.unnamed_counter)
88  else:
89  return net.name
90 
91 # ============================ netlist functions =============================
92 
93 ## Return a list of all package refdes's in the design.
94 #
95 # For historical reasons, this function returns its results in
96 # reversed order.
97 
98 def get_packages(level):
99  check_argument_type('gnetlist:get-packages', 1, level, basestring)
100  return [package.refdes for package in reversed(the_netlist.packages)]
101 
102 ## Return a list of all package refdes's in the design; might return
103 ## duplicates.
104 #
105 # \note Don't use this function. Use \ref get_packages instead.
106 #
107 # Walks through the list of components and returns a list of each
108 # component's refdes. Power symbols don't have a refdes and are
109 # skipped.
110 #
111 # For historical reasons, this function returns its results in
112 # reversed order.
113 
115  check_argument_type('gnetlist:get-non-unique-packages', 1,
116  level, basestring)
117  return [component.refdes
118  for component in reversed(the_netlist.components)
119  # filter out power symbols
120  if component.refdes is not None]
121 
122 ## Return a list of pin numbers for a given package.
123 #
124 # If \a refdes doesn't refer to an existing package, an empty list is
125 # returned.
126 #
127 # For historical reasons, this function returns its results in
128 # reversed order.
129 
130 def get_pins(refdes):
131  check_argument_type('gnetlist:get-pins', 1, refdes, basestring)
132  try:
133  package = the_netlist.packages_by_refdes[refdes]
134  except KeyError:
135  return []
136 
137  return [pin.number for pin in reversed(package.pins)]
138 
139 ## Return a list of all net names in the design; might return duplicates.
140 #
141 # \note Don't use this function. Use \ref get_all_unique_nets instead.
142 #
143 # Walks through the list of components (skipping power symbols) and
144 # through the list of individual pins on each component (skipping
145 # unconnected pins), and returns a list of the names of all found
146 # nets.
147 #
148 # Due to the way hierarchy is handled in the new netlisting code,
149 # subsheet symbols and ports aren't part of the finished netlist.
150 # Therefore, when using hierarchical schematics, this function doesn't
151 # return some of the net name duplications the old function did.
152 #
153 # For historical reasons, this function returns its results in
154 # reversed order.
155 
156 def get_all_nets(level):
157  check_argument_type('gnetlist:get-all-nets', 1, level, basestring)
158 
159  # g_get_all_nets doesn't seem to filter out power symbols, but for
160  # a flat hierarchy, the corresponding net names are omitted from
161  # the returned list. Strange...
162 
163  return [spicified_net_name(cpin.local_net.net)
164  for component in reversed(the_netlist.components)
165  for cpin in reversed(component.cpins)
166  # filter out power symbols
167  if component.refdes is not None
168  # filter out stub nets for unconnected pins
169  and not cpin.local_net.net.is_unconnected_pin]
170 
171 ## Return a list of all net names in the design.
172 #
173 # Stub nets for unconnected pins are not included.
174 #
175 # For historical reasons, this function returns its results in
176 # reversed order.
177 
179  check_argument_type('gnetlist:get-all-unique-nets', 1, level, basestring)
180  return [spicified_net_name(net) for net in reversed(the_netlist.nets)]
181 
182 ## Return a list of pins connected to the a given net.
183 #
184 # For each pin, a pair <tt>(refdes, pinnumber)</tt> is returned.
185 #
186 # If \a wanted_net_name doesn't refer to an existing net, an empty
187 # list is returned.
188 #
189 # For historical reasons, this function returns its results in
190 # reversed order.
191 
192 def get_all_connections(wanted_net_name):
193  check_argument_type('gnetlist:get-all-connections', 1,
194  wanted_net_name, basestring)
195  try:
196  net = the_netlist.nets_by_name[wanted_net_name]
197  except KeyError:
198  return []
199 
200  return [(pin.package.refdes, pin.number)
201  for pin in reversed(net.connections)]
202 
203 ## Return the net to which a given pin is connected and a list of pins
204 ## graphically connected to it.
205 #
206 # The result is a pair
207 # <tt>(netname, [(refdes, pin), (refdes, pin), ...]</tt>).
208 #
209 # If \a wanted_refdes and \a wanted_pin don't refer to an existing
210 # pin, the pair <tt>('ERROR_INVALID_PIN', None)</tt> is returned.
211 #
212 # \note This function is different to all other API functions in that
213 # it does not consider the actual logical net but only pins
214 # which are graphically connected to the given pin. Unless you
215 # are analyzing the graphical properties of a netlist, you
216 # should only use the netname part of its return value.
217 #
218 # Reflecting the behavior of \c gnetlist:get-nets, this function
219 # doesn't return the pin itself if it isn't connected to anything.
220 #
221 # For historical reasons, this function returns the list in
222 # reversed order.
223 
224 def get_nets(wanted_refdes, wanted_pin):
225  check_argument_type('gnetlist:get-nets', 1, wanted_refdes, basestring)
226  check_argument_type('gnetlist:get-nets', 2, wanted_pin, basestring)
227 
228  try:
229  package = the_netlist.packages_by_refdes[wanted_refdes]
230  pin = package.pins_by_number[wanted_pin]
231  except KeyError:
232  sys.stderr.write(_("Invalid refdes ('%s') and pin ('%s') passed "
233  "to get_nets\n") % (wanted_refdes, wanted_pin))
234  return 'ERROR_INVALID_PIN', None
235 
236  if pin.net.is_unconnected_pin:
237  return spicified_net_name(pin.net), []
238 
239  # The behavior of this gnetlist API function is ***BUGGED***!
240  # It lists only the pins graphically connected to the given pin
241  # (the "local net" in xorn.netlist terminology).
242  #
243  # To get the correct behavior, uncomment the following lines:
244  # return pin.net.name, [(pin_.package.refdes, pin_.number)
245  # for pin_ in pin.net.connections]
246 
247  return spicified_net_name(pin.net), [
248  (cpin_.component.refdes, cpin_.blueprint.number)
249  for cpin in pin.cpins
250  for cpin_ in cpin.local_net.cpins
251  # filter out power pins
252  if cpin_.component.refdes is not None]
253 
254 ## Return a list of pairs <tt>(pinnumber, netname)</tt> for a given
255 ## package.
256 #
257 ## Each pair contains the name of a pin of that package and the name
258 ## of the net connected to that pin.
259 #
260 # If \a refdes doesn't refer to an existing package, an empty list is
261 # returned.
262 #
263 # This function *does not* return its results in reversed order.
264 
265 def get_pins_nets(wanted_refdes):
266  check_argument_type('gnetlist:get-pins-nets', 1, wanted_refdes, basestring)
267  try:
268  package = the_netlist.packages_by_refdes[wanted_refdes]
269  except KeyError:
270  return []
271 
272  return [(pin.number, spicified_net_name(pin.net)) for pin in package.pins]
273 
274 # ----------------------------------------------------------------------------
275 
276 ## Get attribute value(s) from a package with given refdes.
277 #
278 # This function returns the values of a specific attribute type
279 # attached to the symbol instances with the given refdes.
280 #
281 # Every first attribute value found is added to the return list.
282 # \c False is added if the instance has no such attribute.
283 #
284 # \note The order of the values in the return list is the order of
285 # symbol instances within gnetlist (the first element is the
286 # value associated with the first symbol instance).
287 #
288 # This function *does not* return its results in reversed order.
289 #
290 # \param [in] refdes package reference
291 # \param [in] wanted_attrib attribute name
292 #
293 # \returns a list of attribute values as strings and \c False
294 
295 def get_all_package_attributes(refdes, wanted_attrib):
296  check_argument_type('gnetlist:get-all-package-attributes', 1,
297  refdes, basestring)
298  check_argument_type('gnetlist:get-all-package-attributes', 2,
299  wanted_attrib, basestring)
300  try:
301  package = the_netlist.packages_by_refdes[refdes]
302  except KeyError:
303  return []
304 
305  # search for refdes instances and through the entire list
306  l = []
307  for component in package.components:
308  try:
309  value = component.blueprint.get_attribute(wanted_attrib)
310  except KeyError:
311  l.append(False)
312  else:
313  l.append(value)
314  return l
315 
316 ## Return value of attribute, otherwise string \c "not found".
317 
318 def get_toplevel_attribute(wanted_attrib):
319  check_argument_type('gnetlist:get-toplevel-attribute', 1,
320  wanted_attrib, basestring)
321  return the_netlist.get_toplevel_attribute(wanted_attrib, 'not found')
322 
323 ## Take a refdes and pinseq number and return wanted_attribute
324 ## associated with that pinseq pin and component.
325 
326 def get_attribute_by_pinseq(refdes, pinseq, wanted_attrib):
327  check_argument_type('gnetlist:get-attribute-by-pinseq', 1,
328  refdes, basestring)
329  check_argument_type('gnetlist:get-attribute-by-pinseq', 2,
330  pinseq, basestring)
331  check_argument_type('gnetlist:get-attribute-by-pinseq', 3,
332  wanted_attrib, basestring)
333 
334  try:
335  pinseq = int(pinseq)
336  except ValueError:
337  return 'unknown'
338 
339  try:
340  package = the_netlist.packages_by_refdes[refdes]
341  pin = package.get_pin_by_pinseq(pinseq)
342  return pin.get_attribute(wanted_attrib)
343  except KeyError:
344  return 'unknown'
345 
346 ## Take a pin number and return the appropriate attribute on that pin.
347 #
348 # \a pin is the value associated with the pinnumber= attribute and refdes.
349 
350 def get_attribute_by_pinnumber(refdes, pin, wanted_attrib):
351  check_argument_type('gnetlist:get-attribute-by-pinnumber', 1,
352  refdes, basestring)
353  check_argument_type('gnetlist:get-attribute-by-pinnumber', 2,
354  pin, basestring)
355  check_argument_type('gnetlist:get-attribute-by-pinnumber', 3,
356  wanted_attrib, basestring)
357 
358  try:
359  package = the_netlist.packages_by_refdes[refdes]
360  pin = package.pins_by_number[pin]
361  return pin.get_attribute(wanted_attrib)
362  except KeyError:
363  return 'unknown'
364 
365 # For historical reasons, this function returns its results in
366 # reversed order.
367 
369  check_argument_type('gnetlist:vams-get-package-attributes', 1,
370  refdes, basestring)
371 
372  try:
373  package = the_netlist.packages_by_refdes[refdes]
374  except KeyError:
375  return []
376  else:
377  # search outside the symbol (attached attributes only)
378  return list(reversed(package.get_attribute_names(False)))
379 
380 # ----------------------------------------------------------------------------
381 
382 ## Given a net name, an attribute, and a wanted attribute, return all
383 ## the given attribute of all the graphical objects connected to that net.
384 #
385 # For historical reasons, this function returns its results in
386 # reversed order.
387 
389  wanted_net_name, has_attrib, wanted_attrib):
391  'gnetlist:graphical-objs-in-net-with-attrib-get-attrib', 1,
392  wanted_net_name, basestring)
394  'gnetlist:graphical-objs-in-net-with-attrib-get-attrib', 2,
395  has_attrib, basestring)
397  'gnetlist:graphical-objs-in-net-with-attrib-get-attrib', 3,
398  wanted_attrib, basestring)
399 
400  try:
401  has_attrib_name, has_attrib_value = \
404  return []
405 
406  try:
407  net = the_netlist.nets_by_name[wanted_net_name]
408  except KeyError:
409  return []
410 
411  return list(reversed(net.graphical_objs_with_attrib_get_attrib(
412  has_attrib_name, has_attrib_value, wanted_attrib)))
413 
414 # ============================= SDB -- 9.1.2003 ==============================
415 
416 ## Obtain a list of `-O' backend arguments.
417 #
418 # Returns a list of arguments passed to the gnetlist backend via the
419 # \c `-O' gnetlist command-line option.
420 
422  return the_backend_arguments
423 
424 ## Get input files from command line.
425 #
426 # This function returns a list of the files named on the command line.
427 #
428 # \returns a list of filenames as strings
429 
431  return [sheet.blueprint.filename
432  for sheet in the_netlist.toplevel_sheets]
433 
434 ## Indicate the verbosity level for messages.
435 #
436 # If the \c "-q" gnetlist command-line option was specified, returns \c -1.
437 # If the \c "-v" gnetlist command-line option was specified, returns \c 1.
438 # Otherwise, returns \c 0.
439 
441  return the_verbosity
442 
443 # ============================================================================
444 
445 xorn.guile.define('quit', lambda: sys.exit(0))
446 xorn.guile.define('exit', lambda: sys.exit(0))
447 
448 for name, value in {
449  # netlist functions
450  'get-packages': get_packages,
451  'get-non-unique-packages': get_non_unique_packages,
452  'get-pins': get_pins,
453  'get-all-nets': get_all_nets,
454  'get-all-unique-nets': get_all_unique_nets,
455  'get-all-connections': get_all_connections,
456  'get-nets-internal': get_nets,
457  'get-pins-nets-internal': get_pins_nets,
458 
459  'get-all-package-attributes': get_all_package_attributes,
460  'get-toplevel-attribute': get_toplevel_attribute,
461  'get-attribute-by-pinseq': get_attribute_by_pinseq,
462  'get-attribute-by-pinnumber': get_attribute_by_pinnumber,
463  'vams-get-package-attributes': vams_get_package_attributes,
464 
465  'graphical-objs-in-net-with-attrib-get-attrib':
466  graphical_objs_in_net_with_attrib_get_attrib,
467 
468  # SDB -- 9.1.2003
469  'get-backend-arguments': get_backend_arguments,
470  'get-input-files': get_input_files,
471  'get-verbosity': get_verbosity
472  }.iteritems():
473  xorn.guile.define('gnetlist:' + name, value)
474 
476 (define (gnetlist:get-pins-nets refdes)
477  (map (lambda (x) (cons (car x) (cadr x)))
478  (gnetlist:get-pins-nets-internal refdes)))
479 
480 (define (gnetlist:get-nets refdes pin)
481  (let ((x (gnetlist:get-nets-internal refdes pin)))
482  (cons (car x) (cadr x))))
483 ''')
def get_attribute_by_pinseq
Take a refdes and pinseq number and return wanted_attribute associated with that pinseq pin and compo...
Definition: guile.py:326
Raised when trying to parse a text object that is not recognized as an attribute. ...
Definition: attrib.py:44
def get_attribute_by_pinnumber
Take a pin number and return the appropriate attribute on that pin.
Definition: guile.py:350
Embedding a Guile interpreter.
Definition: guile.py:1
Attribute parsing and lookup.
Definition: attrib.py:1
def get_pins
Return a list of pin numbers for a given package.
Definition: guile.py:130
def get_verbosity
Indicate the verbosity level for messages.
Definition: guile.py:440
def get_input_files
Get input files from command line.
Definition: guile.py:430
def get_all_unique_nets
Return a list of all net names in the design.
Definition: guile.py:178
def get_all_connections
Return a list of pins connected to the a given net.
Definition: guile.py:192
def get_pins_nets
Return a list of pairs (pinnumber, netname) for a given package.
Definition: guile.py:265
def get_backend_arguments
Obtain a list of `-O' backend arguments.
Definition: guile.py:421
def get_nets
Return the net to which a given pin is connected and a list of pins graphically connected to it...
Definition: guile.py:224
def get_all_nets
Return a list of all net names in the design; might return duplicates.
Definition: guile.py:156
def spicified_net_name
Return the net name visible through the API.
Definition: guile.py:85
def get_packages
Return a list of all package refdes's in the design.
Definition: guile.py:98
def eval_string
Parse a string as Scheme and evaluate the expressions it contains, in order, returning the last expre...
Definition: guile.py:87
def check_argument_type
Helper function for checking the type of an API function argument.
Definition: guile.py:70
def get_toplevel_attribute
Return value of attribute, otherwise string "not found".
Definition: guile.py:318
def graphical_objs_in_net_with_attrib_get_attrib
Given a net name, an attribute, and a wanted attribute, return all the given attribute of all the gra...
Definition: guile.py:389
def get_non_unique_packages
Return a list of all package refdes's in the design; might return duplicates.
Definition: guile.py:114
def vams_get_package_attributes
Definition: guile.py:368
def define
Create a top level variable.
Definition: guile.py:68
def get_all_package_attributes
Get attribute value(s) from a package with given refdes.
Definition: guile.py:295
def parse_string
Parse an attribute string of the form name=value into its name and value parts.
Definition: attrib.py:55