missing NULL terminator in set_config_x
[geda-gaf.git] / xorn / src / backend / gnet_drc2.py
blobe1bf64241d6589793d9d72175f00d0c7c40b1b40
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
31 # anymore.
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
39 # a patch.
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
45 # self-explaining.
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
65 # Parameters
66 # ----------
67 # Parameters should be passed to the backed using -O option in gnetlist's
68 # command line.
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.
76 # Output
77 # ------
78 # By default, the backend outputs to the filename specified in the
79 # command line, or to stdout if the output filename is "-".
81 # Configuration
82 # -------------
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.
106 # Example:
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.
128 # Example:
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
137 # one type of pin.
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 !
143 # 'c', # unknown
144 # 'cc', # in
145 # 'cce', # out
146 # 'ccwc', # io
147 # 'ccewe', # oc
148 # 'ccewce', # oe
149 # 'ccccccc', # pas
150 # 'cceweece', # tp
151 # 'cceccccec', # tri
152 # 'cccccccccc', # clk
153 # 'cceweeceeec', # pwr
154 # 'eeeeeeeeeeee' # unconnected
157 import sys
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]
181 # DRC matrix
182 # 'e': error 'w': warning 'c': correct
183 # Order is important!
184 drc_matrix = [
185 # unknown in out io oc oe pas tp tri clk pwr unconnected
186 'c', # unknown
187 'cc', # in
188 'cce', # out
189 'ccwc', # io
190 'ccewe', # oc
191 'ccewce', # oe
192 'ccccccc', # pas
193 'cceweece', # tp
194 'cceccccec', # tri
195 'cccccccccc', # clk
196 'cceweeceeec', # pwr
197 'eeeeeeeeeeee', # unconnected
200 # =========================== Internal definitions ===========================
202 # Pintype definitions. Overwrite previous definitions, because the
203 # backend depends on them.
205 PINTYPE_COUNT = 12
207 (PINTYPE_UNKNOWN,
208 PINTYPE_IN,
209 PINTYPE_OUT,
210 PINTYPE_IO,
211 PINTYPE_OC,
212 PINTYPE_OE,
213 PINTYPE_PAS,
214 PINTYPE_TP,
215 PINTYPE_TRI,
216 PINTYPE_CLK,
217 PINTYPE_PWR,
218 PINTYPE_UNDEFINED) = xrange(PINTYPE_COUNT)
220 pintype_names = [
221 'unknown', 'in', 'out', 'io', 'oc', 'oe', 'pas', 'tp', 'tri', 'clk', 'pwr',
222 'unconnected'
224 descriptive_pintype_names = [
225 'unknown', 'input', 'output', 'input/output', 'open collector',
226 'open emitter', 'passive', 'totem-pole', 'tristate', 'clock', 'power',
227 'unconnected'
230 # Number of errors and warnings found
231 errors_number = 0
232 warnings_number = 0
234 def error(f, msg):
235 global errors_number
236 f.write("ERROR: %s\n" % msg)
237 errors_number += 1
239 def warning(f, msg):
240 global warnings_number
241 f.write("WARNING: %s\n" % msg)
242 warnings_number += 1
244 def ignore(f, msg):
245 pass
247 def get_drc_matrix_element(row, column):
248 if row < column:
249 row, column = column, row
250 try:
251 return {
252 'c': ignore,
253 'w': warning,
254 'e': error
255 }[drc_matrix[row][column]]
256 except KeyError:
257 sys.stderr.write("INTERNAL ERROR: DRC matrix has unknown value "
258 "on position %s,%s\n" % (row, column))
259 sys.exit(3)
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):
267 l = []
268 for slot in package.get_all_attributes('slot'):
269 if slot is None:
270 # no slot attribute, assume slot number is 1
271 l.append(1)
272 continue
274 # convert string attribute value to number
275 try:
276 l.append(int(slot))
277 except ValueError:
278 # conversion failed, invalid slot, ignore value
279 package.error("bad slot number: %s" % slot)
280 l.sort()
281 return l
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)))
287 l.sort()
288 return l
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):
306 slots = set()
307 for slot in get_slots(package):
308 if slot in slots:
309 error(f, "duplicated slot %d of uref %s"
310 % (slot, package.refdes))
311 break
312 slots.add(slot)
314 # Checks for slots not used.
316 def check_unused_slots(f, netlist):
317 if action_unused_slots == 'c':
318 return
320 for package in reversed(netlist.packages):
321 try:
322 numslots = int(package.get_attribute('numslots', 'unknown'))
323 except ValueError:
324 continue
326 slots_list = get_unique_slots(package)
328 for slot_number in xrange(numslots):
329 if slot_number + 1 in slots_list:
330 continue
332 if action_unused_slots == 'e':
333 error(f, "Unused slot %d of uref %s"
334 % (slot_number + 1, package.refdes))
335 else:
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'
347 else:
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.
355 # This is correct.
356 #f.write("No slotted reference: %s\n" % package.refdes)
357 continue
358 slot = None
359 else:
360 # Slot attribute defined.
361 # If it's a number, then check slots.
362 # If it's not, then report an error.
363 try:
364 slot = int(slot_string)
365 except ValueError:
366 # Slot attribute is not a number.
367 error(f, "Reference %s: "
368 "Incorrect value of slot attribute (%s)."
369 % (package.refdes, slot_string))
370 continue
372 try:
373 numslots = int(numslots_string)
374 except ValueError:
375 error(f, "Reference %s: "
376 "Incorrect value of numslots attribute (%s)."
377 % (package.refdes, numslots_string))
378 continue
380 if slot is None:
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)
385 continue
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):
402 count = 0
403 if case_insensitive:
404 for component in netlist.components:
405 if component.refdes.lower() == package.refdes.lower():
406 count += 1
407 else:
408 for component in netlist.components:
409 if component.refdes == package.refdes:
410 count += 1
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):
420 for net in 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:
426 continue
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):
436 for net in 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:
443 continue
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]
461 for type in net:
462 try:
463 output_list[pintype_names.index(type.lower())] += 1
464 except ValueError:
465 f.write("INTERNAL ERROR: unknown pin type : %s\n" % type)
466 return output_list
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):
473 return ''.join(
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),
491 net.name,
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,
498 # by pintype.
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]
504 if type1_count == 0:
505 continue
507 for type2 in xrange(type1, PINTYPE_COUNT - 1):
508 type2_count = pintype_count[type2]
509 if type2_count == 0:
510 continue
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,
520 # by pintype.
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:
525 return True
527 return False
529 # Check pintype of the pins connected to every net in the design.
531 def check_pintypes_of_nets(f, netlist, all_nets):
532 for net in 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:
555 continue
557 try:
558 position = pintype_names.index(
559 pin.get_attribute('pintype', 'unknown').lower())
560 except ValueError:
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):
569 nets = list(nets)
571 # count unknown pintypes
572 count = 0
573 for net in nets:
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
579 if count > 0:
580 f.write("NOTE: Found pins without the 'pintype' attribute: ")
581 f.write(''.join(
582 display_pins_of_type(netlist, PINTYPE_UNKNOWN, net)
583 for net in nets))
584 #message("\n")
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 "
598 "bad specified.\n")
599 sys.exit(3)
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))
610 sys.exit(3)
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")
615 sys.exit(3)
617 # Check non-numbered symbols
618 if not dont_check_non_numbered_parts:
619 f.write("Checking non-numbered parts...")
620 f.write("\n")
621 check_non_numbered_items(f, netlist, reversed(netlist.packages))
622 f.write("\n")
624 # Check for duplicated references
625 if not dont_check_duplicated_references:
626 f.write("Checking duplicated references...")
627 f.write("\n")
628 check_duplicated_references(f, netlist, reversed(netlist.packages))
629 f.write("\n")
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...")
634 f.write("\n")
635 check_connected_noconnects(f, netlist, reversed(netlist.nets))
636 f.write("\n")
638 # Check nets with only one connection
639 if not dont_check_one_connection_nets:
640 f.write("Checking nets with only one connection...")
641 f.write("\n")
642 check_single_nets(f, netlist, reversed(netlist.nets))
643 f.write("\n")
645 # Check "unknown" pintypes
646 if not dont_report_unknown_pintypes:
647 f.write("Checking pins without the 'pintype' attribute...")
648 f.write("\n")
649 report_unknown_pintypes(f, netlist, reversed(netlist.nets))
650 f.write("\n")
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...")
655 f.write("\n")
656 check_pintypes_of_nets(f, netlist, reversed(netlist.nets))
657 f.write("\n")
659 # Check unconnected pins
660 if not dont_check_unconnected_pins:
661 f.write("Checking unconnected pins...")
662 f.write("\n")
663 if netlist.packages:
664 check_unconnected_pins(f, netlist, reversed(netlist.packages))
665 f.write("\n")
667 # Check slots
668 if not dont_check_slots:
669 f.write("Checking slots...")
670 f.write("\n")
671 check_slots(f, netlist)
672 f.write("\n")
674 # Check for duplicated slots
675 if not dont_check_duplicated_slots:
676 f.write("Checking duplicated slots...")
677 f.write("\n")
678 check_duplicated_slots(f, netlist)
679 f.write("\n")
681 # Check for unused slots
682 if not dont_check_unused_slots:
683 f.write("Checking unused slots...")
684 f.write("\n")
685 check_unused_slots(f, netlist)
686 f.write("\n")
688 # Display total number of warnings
689 if warnings_number > 0:
690 f.write("Found %s warnings.\n" % warnings_number)
691 else:
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)
697 else:
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")