1 # gaf.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-2020 Roland Lutz
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.
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.
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.
20 # --------------------------------------------------------------------------
22 # DRC backend written by Carlos Nieves Onega
24 # 2015-06-23: Translated to Python by Roland Lutz.
25 # 2010-12-11: Fix stack overflows with large designs.
26 # 2010-10-02: Applied patch from Karl Hammar. Do drc-matrix lower triangular
27 # and let get-drc-matrixelement swap row/column if row < column.
28 # 2006-04-22: Display the pins when reporting a net with only one connection.
29 # 2006-04-08: Added support for DRC directives (DontCheckPintypes and
30 # NoConnection), so the DRC doesn't depend on the net name
32 # Changed the drc connection matrix. Now an unknown pin doesn't
33 # generate an error, and it can drive a net.
34 # Added report for pins without the 'pintype' attribute.
35 # 2006-04-05: Fixed parenthesis mismatch in function drc2:check-slots.
36 # Thanks to David Logan for reporting the bug.
37 # 2006-03-02: Don't check pintypes of net "NoConnection".
38 # Thanks to Holger Oehm for the bug report and providing
40 # 2006-02-28: Added netname in the output message when checking pintype
41 # connections. Thanks to Holger Oehm for providing the patch.
42 # 2006-01-15: Changed error message to explain it a little bit.
43 # 2006-01-07: Added missing 'passive' in the pintype-full-names list, and
44 # changed the pintype error/warning message to something more
46 # 2005-02-11: Output to stdout if the output filename is "-".
47 # 2005-02-08: Use a parameter instead of the quiet mode of gnetlist so
48 # gnetlist doesn't return a non-zero value when there are only
49 # warnings. This parameter is 'ignore-warnings-in-return-value'.
50 # 2005-02-06: Make gnetlist return a non-zero value when errors or warnings
51 # are found. If there is only warnings, the non-zero return value
52 # can be disabled using the "quiet mode" option of gnetlist.
53 # 2005-02-06: Fixed bug when packages list is empty.
54 # 2005-01-23: Added check for duplicated references.
55 # 2003-10-24: Added numslots and slot attributes check.
56 # 2003-06-17: Added configuration support and slots check.
57 # 2003-06-05: Now checking for unconnected pins look into the DRC matrix if
58 # it should issue an error, warning, or do nothing.
59 # If the drc-matrix is defined before the execution of the backend,
60 # then it's not overwritten. It allows backend configuration.
61 # 2003-06-04: Added check for unconnected pins and fix one small error
62 # (index limit error).
63 # 2003-06-03: First release
67 # Parameters should be passed to the backed using -O option in gnetlist's
70 # * ignore-warnings-in-return-value:
71 # By default, this backend makes gnetlist return a non-zero
72 # value when warnings or errors are found. This is useful for
73 # Makefiles. Using this option, gnetlist will return a zero
74 # value if there are only DRC warnings.
78 # By default, the backend outputs to the filename specified in the
79 # command line, or to stdout if the output filename is "-".
83 # Some test can be disabled defining some variables. Following is a
84 # list with a pair of check and variable. If the variable is set to
85 # True, then that check is not performed.
87 # Check Variable [= Value]
88 # ----------------------------------------------------------------------------
89 # Not numbered parts. dont_check_non_numbered_parts
90 # Duplicated part references (Note 1) dont_check_duplicated_references
91 # Nets with only one connection. dont_check_one_connection_nets
92 # Type of pins connected to each net. dont_check_pintypes_of_nets
93 # Net not driven. dont_check_not_driven_nets
94 # Unconnected pins dont_check_unconnected_pins
95 # Values of slot and numslots attribs. dont_check_slots
96 # Slot is used more than one time. dont_check_duplicated_slots
97 # Reports unused slots dont_check_unused_slots
98 # Don't report anything action_unused_slots = 'c'
99 # Report them as a warning action_unused_slots = 'w'
100 # Report them as an error action_unused_slots = 'e'
102 # Note 1: DRC checks are case sensitive by default. If you want them
103 # to be case insensitive, then you only have to set the variable
104 # 'case_insensitive' to True.
107 # dont_check_non_numbered_parts = True
108 # dont_check_duplicated_references = True
109 # dont_check_one_connection_nets = True
110 # dont_report_unknown_pintypes = True
111 # dont_check_pintypes_of_nets = True
112 # dont_check_not_driven_nets = True
113 # dont_check_unconnected_pins = True
114 # dont_check_duplicated_slots = True
115 # dont_check_unused_slots = True
116 # action_unused_slots = 'w'
117 # case_insensitive = True
119 # The check for not driven nets only is performed when checking the
120 # type of the pins connected to each net.
121 # There is a list which specifies which type of pin can drive a net.
122 # It's called pintype_can_drive. It's a list, with 0 or 1 integer
123 # elements. The order is specified below and is very important, since
124 # each position in the list matches one type of pin. This list can be
125 # specified before running this backend, otherwise, the backend will
126 # use the default values.
129 # pintype_can_drive = [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0]
131 # There are two checks that are configurable by a DRC connection
132 # matrix: check for unconnected pins and check for the type of pins
133 # connected to each net.
134 # Each element of the DRC matrix matches one connection between two
135 # pins (the "row" pin and the "column" pin). The order is specified
136 # below and is very important, since each position in the list matches
138 # The DRC matrix can be specified before running this backend.
139 # Otherwise, the backend will use the default values.
141 # Example (default matrix):
142 # drc-matrix = [ # Order is important !
152 # 'cccccccccc', # clk
153 # 'cceweeceeec', # pwr
154 # 'eeeeeeeeeeee' # unconnected
158 from util_getopt
import *
160 # ============================== Configuration ===============================
162 dont_check_not_driven_nets
= False
163 dont_check_non_numbered_parts
= False
164 dont_check_duplicated_references
= False
165 dont_check_connected_noconnects
= False
166 dont_check_one_connection_nets
= False
167 dont_report_unknown_pintypes
= False
168 dont_check_pintypes_of_nets
= False
169 dont_check_unconnected_pins
= False
170 dont_check_slots
= False
171 dont_check_duplicated_slots
= False
172 dont_check_unused_slots
= False
174 action_unused_slots
= 'w'
175 case_insensitive
= False
177 # define if a specified pin can drive a net
178 # unk in out io oc oe pas tp tri clk pwr undef
179 pintype_can_drive
= [1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0]
182 # 'e': error 'w': warning 'c': correct
183 # Order is important!
185 # unknown in out io oc oe pas tp tri clk pwr unconnected
197 'eeeeeeeeeeee', # unconnected
200 # =========================== Internal definitions ===========================
202 # Pintype definitions. Overwrite previous definitions, because the
203 # backend depends on them.
218 PINTYPE_UNDEFINED
) = xrange(PINTYPE_COUNT
)
221 'unknown', 'in', 'out', 'io', 'oc', 'oe', 'pas', 'tp', 'tri', 'clk', 'pwr',
224 descriptive_pintype_names
= [
225 'unknown', 'input', 'output', 'input/output', 'open collector',
226 'open emitter', 'passive', 'totem-pole', 'tristate', 'clock', 'power',
230 # Number of errors and warnings found
236 f
.write("ERROR: %s\n" % msg
)
240 global warnings_number
241 f
.write("WARNING: %s\n" % msg
)
247 def get_drc_matrix_element(row
, column
):
249 row
, column
= column
, row
255 }[drc_matrix
[row
][column
]]
257 sys
.stderr
.write("INTERNAL ERROR: DRC matrix has unknown value "
258 "on position %s,%s\n" % (row
, column
))
261 ## Return a sorted list of slots used by a package.
263 # It collects the slot attribute values of each symbol instance of a
264 # package. As a result, slots may be repeated in the returned list.
266 def get_slots(package
):
268 for slot
in package
.get_all_attributes('slot'):
270 # no slot attribute, assume slot number is 1
274 # convert string attribute value to number
278 # conversion failed, invalid slot, ignore value
279 package
.error("bad slot number: %s" % slot
)
283 ## Return a sorted list of unique slots used by a package.
285 def get_unique_slots(package
):
286 l
= list(set(get_slots(package
)))
290 # ======================== Symbol checking functions =========================
292 # Check for symbols not numbered.
294 def check_non_numbered_items(f
, netlist
, packages
):
295 for package
in packages
:
296 if '?' in package
.refdes
:
297 error(f
, "Reference not numbered: %s" % package
.refdes
)
299 # Check for duplicated slots.
301 # Check if a slot of a package is used more than one time.
302 # Checks all packages in the design.
304 def check_duplicated_slots(f
, netlist
):
305 for package
in reversed(netlist
.packages
):
307 for slot
in get_slots(package
):
309 error(f
, "duplicated slot %d of uref %s"
310 % (slot
, package
.refdes
))
314 # Checks for slots not used.
316 def check_unused_slots(f
, netlist
):
317 if action_unused_slots
== 'c':
320 for package
in reversed(netlist
.packages
):
322 numslots
= int(package
.get_attribute('numslots', 'unknown'))
326 slots_list
= get_unique_slots(package
)
328 for slot_number
in xrange(numslots
):
329 if slot_number
+ 1 in slots_list
:
332 if action_unused_slots
== 'e':
333 error(f
, "Unused slot %d of uref %s"
334 % (slot_number
+ 1, package
.refdes
))
336 warning(f
, "Unused slot %d of uref %s"
337 % (slot_number
+ 1, package
.refdes
))
339 # Check slot number is greater or equal than numslots for all packages.
341 def check_slots(f
, netlist
):
342 for package
in reversed(netlist
.packages
):
343 numslots_string
= package
.get_attribute('numslots', 'unknown')
344 slots
= package
.get_all_attributes('slot')
345 if not slots
or slots
[0] is None:
346 slot_string
= 'unknown'
348 slot_string
= slots
[0]
350 if slot_string
.lower() == 'unknown':
351 # If slot attribute is not defined.
352 if numslots_string
.lower() == 'unknown' or \
353 numslots_string
== '0':
354 # No slot neither numslots (or set to zero) attributes defined.
356 #f.write("No slotted reference: %s\n" % package.refdes)
360 # Slot attribute defined.
361 # If it's a number, then check slots.
362 # If it's not, then report an error.
364 slot
= int(slot_string
)
366 # Slot attribute is not a number.
367 error(f
, "Reference %s: "
368 "Incorrect value of slot attribute (%s)."
369 % (package
.refdes
, slot_string
))
373 numslots
= int(numslots_string
)
375 error(f
, "Reference %s: "
376 "Incorrect value of numslots attribute (%s)."
377 % (package
.refdes
, numslots_string
))
381 # If no slot attribute, but numslots is defined and not zero.
382 # If numslots is a number, then slot should be defined.
383 error(f
, "Multislotted reference %s "
384 "has no slot attribute defined." % package
.refdes
)
387 for this_slot
in get_unique_slots(package
):
388 if this_slot
> numslots
or this_slot
< 1:
389 # If slot is not between 1 and numslots,
390 # then report an error.
391 error(f
, "Reference %s: Slot out of range (%d)."
392 % (package
.refdes
, this_slot
))
394 # Check duplicated references of the given list.
396 # If the number of ocurrences of a reference in the schematic doesn't
397 # match the number of unique slots used by that part, then that
398 # reference is used more than one time in the schematic.
400 def check_duplicated_references(f
, netlist
, packages
):
401 for package
in reversed(netlist
.packages
):
404 for component
in netlist
.components
:
405 if component
.refdes
.lower() == package
.refdes
.lower():
408 for component
in netlist
.components
:
409 if component
.refdes
== package
.refdes
:
412 if count
> len(get_unique_slots(package
)):
413 error(f
, "Duplicated reference %s." % package
.refdes
)
415 # ========================== Net checking functions ==========================
417 # Check for NoConnection nets with more than one pin connected.
419 def check_connected_noconnects(f
, netlist
, all_nets
):
421 directives
= net
.graphical_objs_with_attrib_get_attrib(
422 'device', 'DRC_Directive', 'value')
424 # Only check nets with a NoConnection directive
425 if 'NoConnection' not in directives
:
428 if len(net
.connections
) > 1:
429 error(f
, "Net '%s' has connections, "
430 "but has the NoConnection DRC directive: %s."
431 % (net
.name
, display_pins_of_type(netlist
, 'all', net
)))
433 # Check for nets with less than two pins connected.
435 def check_single_nets(f
, netlist
, all_nets
):
437 directives
= net
.graphical_objs_with_attrib_get_attrib(
438 'device', 'DRC_Directive', 'value')
440 # If one of the directives is NoConnection,
441 # then it shouldn't be checked.
442 if 'NoConnection' in directives
:
445 if len(net
.connections
) == 0:
446 error(f
, "Net '%s' has no connections." % net
.name
)
447 if len(net
.connections
) == 1:
448 error(f
, "Net '%s' is connected to only one pin: %s."
449 % (net
.name
, display_pins_of_type(netlist
, 'all', net
)))
451 # Return a list with the pintypes of the pins connected to a net.
453 def get_pintypes_of_net_connections(netlist
, net
):
454 return [pin
.get_attribute('pintype', 'unknown')
455 for pin
in reversed(net
.connections
)]
457 # Count pintypes of a net.
459 def count_pintypes_of_net(f
, net
):
460 output_list
= PINTYPE_COUNT
* [0]
463 output_list
[pintype_names
.index(type.lower())] += 1
465 f
.write("INTERNAL ERROR: unknown pin type : %s\n" % type)
468 # Display pins of a specified type connected to a net.
470 # type: pin type index, or the string "all" to display all the pins.
472 def display_pins_of_type(netlist
, type, net
):
474 '%s:%s ' % (pin
.package
.refdes
, pin
.number
)
475 for pin
in reversed(net
.connections
)
476 if type == 'all' or pin
.get_attribute('pintype', 'unknown').lower()
477 == pintype_names
[type].lower())
479 # Check connection between two pintypes.
481 # type1, type2: pin type indices
483 def check_connection_of_two_pintypes(
484 f
, netlist
, type1
, type2
, net
):
485 proc
= get_drc_matrix_element(type1
, type2
)
486 proc(f
, "Pin(s) with pintype '%s': %s\n"
487 "\tare connected by net '%s'\n"
488 "\tto pin(s) with pintype '%s': %s" % (
489 descriptive_pintype_names
[type1
],
490 display_pins_of_type(netlist
, type1
, net
),
492 descriptive_pintype_names
[type2
],
493 display_pins_of_type(netlist
, type2
, net
)))
495 # Check pintypes of the pins connected to a single net.
497 # pintype_count: vector with the number of pins connected to a single net,
500 def check_pintypes_of_single_net(
501 f
, netlist
, net
, pintypes
, pintype_count
):
502 for type1
in xrange(PINTYPE_COUNT
- 1):
503 type1_count
= pintype_count
[type1
]
507 for type2
in xrange(type1
, PINTYPE_COUNT
- 1):
508 type2_count
= pintype_count
[type2
]
512 if (type1
== type2
and type1_count
> 1) or \
513 (type1
!= type2
and type1_count
> 0 and type2_count
> 0):
514 check_connection_of_two_pintypes(
515 f
, netlist
, type1
, type2
, net
)
517 # Check if a net has a pintype which can drive the net.
519 # pintype_count: vector with the number of pins connected to a single net,
522 def check_if_net_is_driven(pintype_count
):
523 for position
in xrange(PINTYPE_COUNT
- 1):
524 if pintype_count
[position
] > 0 and pintype_can_drive
[position
] == 1:
529 # Check pintype of the pins connected to every net in the design.
531 def check_pintypes_of_nets(f
, netlist
, all_nets
):
533 pintypes
= get_pintypes_of_net_connections(netlist
, net
)
534 pintype_count
= count_pintypes_of_net(f
, pintypes
)
535 directives
= net
.graphical_objs_with_attrib_get_attrib(
536 'device', 'DRC_Directive', 'value')
538 # If some directives are defined, then it shouldn't be checked.
539 if 'DontCheckPintypes' not in directives
:
540 check_pintypes_of_single_net(
541 f
, netlist
, net
, pintypes
, pintype_count
)
543 if not dont_check_not_driven_nets
and \
544 'DontCheckIfDriven' not in directives
and \
545 'NoConnection' not in directives
and \
546 not check_if_net_is_driven(pintype_count
):
547 error(f
, "Net %s is not driven." % net
.name
)
549 # Check unconnected pins.
551 def check_unconnected_pins(f
, netlist
, packages
):
552 for package
in packages
:
553 for pin
in package
.pins
:
554 if not pin
.net
.is_unconnected_pin
:
558 position
= pintype_names
.index(
559 pin
.get_attribute('pintype', 'unknown').lower())
561 position
= PINTYPE_COUNT
563 proc
= get_drc_matrix_element(PINTYPE_UNDEFINED
, position
)
564 proc(f
, "Unconnected pin %s:%s" % (package
.refdes
, pin
.number
))
566 # Report pins without the 'pintype' attribute (pintype=unknown).
568 def report_unknown_pintypes(f
, netlist
, nets
):
571 # count unknown pintypes
574 pintypes
= get_pintypes_of_net_connections(netlist
, net
)
575 pintype_count
= count_pintypes_of_net(f
, pintypes
)
576 count
+= pintype_count
[PINTYPE_UNKNOWN
]
578 # display unknown pintypes
580 f
.write("NOTE: Found pins without the 'pintype' attribute: ")
582 display_pins_of_type(netlist
, PINTYPE_UNKNOWN
, net
)
586 # ========================== Highest level function ==========================
588 def run(f
, netlist
, args
):
589 options
= backend_getopt(args
, {
590 'ignore-warnings-in-return-value': Option(False, NO_ARGUMENT
, None)
593 if not isinstance(pintype_can_drive
, list) or \
594 len(pintype_can_drive
) != PINTYPE_COUNT
or \
595 not next((False for x
in pintype_can_drive
596 if not isinstance(x
, int) or x
not in [0, 1]), True):
597 sys
.stderr
.write("INTERNAL ERROR: List of pins which can drive a net "
601 # Perform DRC-matrix sanity checks.
602 # See if all elements of the matrix are chars
604 for row
in xrange(PINTYPE_COUNT
):
605 for column
in xrange(row
+ 1):
606 c
= drc_matrix
[row
][column
]
607 if not isinstance(c
, basestring
) or len(c
) != 1:
608 sys
.stderr
.write("INTERNAL ERROR: DRC matrix has unknown "
609 "value on position %s,%s\n" % (row
, column
))
612 if action_unused_slots
not in 'wce':
613 sys
.stderr
.write("INTERNAL ERROR: Action when unused slots are found "
614 "has a wrong value.\n")
617 # Check non-numbered symbols
618 if not dont_check_non_numbered_parts
:
619 f
.write("Checking non-numbered parts...")
621 check_non_numbered_items(f
, netlist
, reversed(netlist
.packages
))
624 # Check for duplicated references
625 if not dont_check_duplicated_references
:
626 f
.write("Checking duplicated references...")
628 check_duplicated_references(f
, netlist
, reversed(netlist
.packages
))
631 # Check for NoConnection nets with more than one pin connected.
632 if not dont_check_connected_noconnects
:
633 f
.write("Checking NoConnection nets for connections...")
635 check_connected_noconnects(f
, netlist
, reversed(netlist
.nets
))
638 # Check nets with only one connection
639 if not dont_check_one_connection_nets
:
640 f
.write("Checking nets with only one connection...")
642 check_single_nets(f
, netlist
, reversed(netlist
.nets
))
645 # Check "unknown" pintypes
646 if not dont_report_unknown_pintypes
:
647 f
.write("Checking pins without the 'pintype' attribute...")
649 report_unknown_pintypes(f
, netlist
, reversed(netlist
.nets
))
652 # Check pintypes of the pins connected to every net
653 if not dont_check_pintypes_of_nets
:
654 f
.write("Checking type of pins connected to a net...")
656 check_pintypes_of_nets(f
, netlist
, reversed(netlist
.nets
))
659 # Check unconnected pins
660 if not dont_check_unconnected_pins
:
661 f
.write("Checking unconnected pins...")
664 check_unconnected_pins(f
, netlist
, reversed(netlist
.packages
))
668 if not dont_check_slots
:
669 f
.write("Checking slots...")
671 check_slots(f
, netlist
)
674 # Check for duplicated slots
675 if not dont_check_duplicated_slots
:
676 f
.write("Checking duplicated slots...")
678 check_duplicated_slots(f
, netlist
)
681 # Check for unused slots
682 if not dont_check_unused_slots
:
683 f
.write("Checking unused slots...")
685 check_unused_slots(f
, netlist
)
688 # Display total number of warnings
689 if warnings_number
> 0:
690 f
.write("Found %s warnings.\n" % warnings_number
)
692 f
.write("No warnings found. \n")
694 # Display total number of errors
695 if errors_number
> 0:
696 f
.write("Found %s errors.\n" % errors_number
)
698 f
.write("No errors found. \n")
700 # Make gnetlist return an error if there are DRC errors.
701 # If there are only warnings and it's in quiet mode, then
702 # do not return an error.
703 if f
is not sys
.stdout
and errors_number
> 0:
704 sys
.stderr
.write("DRC errors found. See output file.\n")
705 elif warnings_number
> 0 and \
706 'ignore-warnings-in-return-value' not in options
:
707 sys
.stderr
.write("DRC warnings found. See output file.\n")