1 ;;; gEDA - GPL Electronic Design Automation
2 ;;; gnetlist - gEDA Netlist
3 ;;; Copyright (C) 1998-2010 Ales Hvezda
4 ;;; Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
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
18 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 ;; --------------------------------------------------------------------------
22 ;; DRC backend written by Carlos Nieves Onega starts here.
24 ;; 2010-12-11: Fix stack overflows with large designs.
25 ;; 2010-10-02: Applied patch from Karl Hammar. Do drc-matrix lower triangular
26 ;; and let get-drc-matrixelement swap row/column if row < column.
27 ;; 2006-04-22: Display the pins when reporting a net with only one connection.
28 ;; 2006-04-08: Added support for DRC directives (DontCheckPintypes and
29 ;; NoConnection), so the DRC doesn't depend on the net name
31 ;; Changed the drc connection matrix. Now an unknown pin doesn't
32 ;; generate an error, and it can drive a net.
33 ;; Added report for pins without the 'pintype' attribute.
34 ;; 2006-04-05: Fixed parenthesis mismatch in function drc2:check-slots.
35 ;; Thanks to David Logan for reporting the bug.
36 ;; 2006-03-02: Don't check pintypes of net "NoConnection".
37 ;; Thanks to Holger Oehm for the bug report and providing
39 ;; 2006-02-28: Added netname in the output message when checking pintype
40 ;; connections. Thanks to Holger Oehm for providing the patch.
41 ;; 2006-01-15: Changed error message to explain it a little bit.
42 ;; 2006-01-07: Added missing 'passive' in the pintype-full-names list, and
43 ;; changed the pintype error/warning message to something more
45 ;; 2005-02-11: Output to stdout if the output filename is "-".
46 ;; 2005-02-08: Use a parameter instead of the quiet mode of gnetlist so
47 ;; gnetlist doesn't return a non-zero value when there are only
48 ;; warnings. This parameter is 'ignore-warnings-in-return-value'.
49 ;; 2005-02-06: Make gnetlist return a non-zero value when errors or warnings
50 ;; are found. If there is only warnings, the non-zero return value
51 ;; can be disabled using the "quiet mode" option of gnetlist.
52 ;; 2005-02-06: Fixed bug when packages list is empty.
53 ;; 2005-01-23: Added check for duplicated references.
54 ;; 2003-10-24: Added numslots and slot attributes check.
55 ;; 2003-06-17: Added configuration support and slots check.
56 ;; 2003-06-05: Now checking for unconnected pins look into the DRC matrix if
57 ;; it should issue an error, warning, or do nothing.
58 ;; If the drc-matrix is defined before the execution of the backend,
59 ;; then it's not overwritten. It allows backend configuration.
61 ;; 2003-06-04: Added check for unconnected pins and fix one small error (index limit error).
62 ;; 2003-06-03: First release
66 ;; Parameters should be passed to the backed using -O option in gnetlist's
69 ;; * ignore-warnings-in-return-value: By default, this backend makes gnetlist
70 ;; return a non-zero value when warnings or errors are found. This is
71 ;; useful for Makefiles. Using this option, gnetlist will return a zero
72 ;; value if there are only DRC warnings.
76 ;; By default, the backend outputs to the filename specified in the command line, or to
77 ;; stdout if the output filename is "-".
82 ;; Some test can be disabled defining some variables. Following is a list with a pair of check
83 ;; and variable. If the variable is defined, then that check is not performed.
85 ;; Check Variable Value
86 ;; -----------------------------------------------------------------------------------------------
87 ;; Not numbered parts. dont-check-non-numbered-parts whatever you want
88 ;; Duplicated part references (Note 1) dont-check-duplicated-references whatever you want
89 ;; Nets with only one connection. dont-check-one-connection-nets whatever you want
90 ;; Type of pins connected to each net. dont-check-pintypes-of-nets whatever you want
91 ;; Net not driven. dont-check-not-driven-nets whatever you want
92 ;; Unconnected pins dont-check-unconnected-pins whatever you want
93 ;; Values of slot and numslots attribs. dont-check-slots whatever you want
94 ;; Slot is used more than one time. dont-check-duplicated-slots whatever you want
95 ;; Reports unused slots dont-check-unused-slots whatever you want
96 ;; Don't report anything action-unused-slots #\c
97 ;; Report them as a warning action-unused-slots #\w
98 ;; Report them as an error action-unused-slots #\w
100 ;; Note 1: DRC checks are case sensitive by default. If you want them to be case insensitive, then you
101 ;; only have to define the variable 'case_insensitive' to whatever value you want.
104 ;; (define dont-check-non-numbered-parts 1)
105 ;; (define dont-check-duplicated-references 1)
106 ;; (define dont-check-one-connection-nets 1)
107 ;; (define dont-report-unknown-pintypes 1)
108 ;; (define dont-check-pintypes-of-nets 1)
109 ;; (define dont-check-not-driven-nets 1)
110 ;; (define dont-check-unconnected-pins 1)
111 ;; (define dont-check-duplicated-slots 1)
112 ;; (define dont-check-unused-slots 1)
113 ;; (define action-unused-slots #\w)
114 ;; (define case_insensitive 1)
116 ;; The check for not driven nets only is performed when checking the type of the pins connected
118 ;; There is a list which specifies which type of pin can drive a net. It's called pintype-can-drive.
119 ;; It's a list, with 0 or 1 integer elements. The order is specified below and is very important, since
120 ;; each position in the list matches one type of pin. This list can be specified before running this
121 ;; backend, otherwise, the backend will use the default values.
124 ;; (define pintype-can-drive (list 0 0 1 1 1 1 1 1 1 0 1 0 ))
126 ;; There are two checks that are configurable by a DRC connection matrix: check for unconnected pins
127 ;; and check for the type of pins connected to each net.
128 ;; Each element of the DRC matrix matches one connection between two pins (the "row" pin and the "column"
129 ;; pin). The order is specified below and is very important, since each position in the list matches
131 ;; The DRC matrix can be specified before running this backend. Otherwise, the backend will use the
134 ;; Example (default matrix):
136 ;; (define drc-matrix (list
137 ;;; Order is important !
138 ;;; unknown in out io oc oe pas tp tri clk pwr unconnected
146 ;; '( #\c #\c #\w #\c)
148 ;; '( #\c #\c #\e #\w #\e)
150 ;; '( #\c #\c #\e #\w #\c #\e)
152 ;; '( #\c #\c #\c #\c #\c #\c #\c)
154 ;; '( #\c #\c #\e #\w #\e #\e #\c #\e)
156 ;; '( #\c #\c #\e #\c #\c #\c #\c #\e #\c)
158 ;; '( #\c #\c #\c #\c #\c #\c #\c #\c #\c #\c)
160 ;; '( #\c #\c #\e #\w #\e #\e #\c #\e #\e #\e #\c)
162 ;; '( #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e )))
166 ;; -------------------------------------------------------------------------------
167 ;; IMPORTANT: Don't modify anything below unless you know what you are doing.
168 ;; -------------------------------------------------------------------------------
170 (use-modules (srfi srfi-1))
171 (or (defined? 'define-syntax)
172 (use-modules (ice-9 syncase)))
174 (define-syntax define-undefined
177 (define name (if (defined? (quote name)) name expr)))))
180 ;; Some internal definitions
184 ; Pintype definitions. Overwrite previous definitions, because the backend depends on them.
196 (define undefined 11)
197 (define pintype-names (list "unknown" "in" "out" "io" "oc" "oe" "pas" "tp" "tri" "clk" "pwr" "unconnected"))
198 (define pintype-full-names (list "unknown" "input" "output" "input/output" "open collector" "open emitter" "passive" "totem-pole" "tristate" "clock" "power" "unconnected"))
200 ; define if a specified pin can drive a net
201 (define (pintype-can-drive-valid? lst)
207 (= (length lst) (length pintype-names))
210 (define pintype-can-drive
211 (if (defined? 'pintype-can-drive)
212 (if (pintype-can-drive-valid? pintype-can-drive)
215 (display "INTERNAL ERROR: List of pins which can drive a net bad specified. Using default value.")
220 (if (not pintype-can-drive)
221 ; unk in out io oc oe pas tp tri clk pwr undef
222 (set! pintype-can-drive (list 1 0 1 1 1 1 1 1 1 0 1 0 )))
226 ; #\e: error #\w: warning #\c: correct
227 (define-undefined drc-matrix
229 ; Order is important !
230 ; unknown in out io oc oe pas tp tri clk pwr unconnected
240 '( #\c #\c #\e #\w #\e )
242 '( #\c #\c #\e #\w #\c #\e )
244 '( #\c #\c #\c #\c #\c #\c #\c )
246 '( #\c #\c #\e #\w #\e #\e #\c #\e )
248 '( #\c #\c #\e #\c #\c #\c #\c #\e #\c )
250 '( #\c #\c #\c #\c #\c #\c #\c #\c #\c #\c )
252 '( #\c #\c #\e #\w #\e #\e #\c #\e #\e #\e #\c )
254 '( #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e #\e )
257 ;; Number of errors and warnings found
258 (define errors_number 0)
259 (define warnings_number 0)
261 (define-undefined action-unused-slots #\w)
263 (if (or (not (char? action-unused-slots))
264 (not (or (char=? action-unused-slots #\w)
265 (char=? action-unused-slots #\c)
266 (char=? action-unused-slots #\e))))
268 (display "INTERNAL ERROR: Action when unused slots are found has a wrong value. Using default.")
270 (set! action-unused-slots #\w)))
272 ;-----------------------------------------------------------------------
273 ; DRC matrix functions
276 ; Get the position of a pintype in the list, by its pintype name ("io", "in",...)
277 (define drc2:position-of-pintype
279 (- (length pintype-names) (length (member (string-downcase type) pintype-names)))))
281 ; Get the full name of a specified position in the pintype list.
282 (define drc2:get-full-name-of-pintype-by-number
284 (list-ref pintype-full-names type)))
286 ; Get the full name of a specified pintype short name. (i.e "io" -> "input/output")
287 (define drc2:get-full-name-of-pintype-by-name
289 (list-ref pintype-full-names (drc2:position-of-pintype (string-downcase type)))))
291 ; Get value x y from matrix
292 (define drc2:get-drc-matrix-element
295 (list-ref (list-ref drc-matrix column) row)
296 (list-ref (list-ref drc-matrix row) column))))
298 ; Check if all elements of the DRC matrix are characters
299 (define drc2:drc-matrix-elements-are-correct?
301 (let check-row ((row 0))
302 (if (let check-column ((column 0))
303 (if (not (char? (drc2:get-drc-matrix-element row column)))
305 (if (< column (- (length pintype-names) 1))
306 (check-column (+ column 1))
310 (if (< row (- (length pintype-names) 1))
311 (check-row (+ row 1))
319 ; End of DRC matrix functions
320 ;-----------------------------------------------------------------------
322 ;-----------------------------------------------------------------------
323 ; SYMBOLS checking functions
327 ;; Check for symbols not numbered.
329 ;; example of packages: (U100 U101 U102)
330 (define drc2:check-non-numbered-items
331 (lambda (port packages)
332 (if (not (null? packages))
333 (let ((package (car packages)))
335 (if (not (eq? (string-index package #\?) #f))
336 (begin (display "ERROR: Reference not numbered: " port)
337 (display package port)
339 (set! errors_number (+ errors_number 1))
342 (drc2:check-non-numbered-items port (cdr packages)))))))
346 ;; Check for duplicated slots
348 ;; Check if a slot of a package is used more than one time. Checks all packages in the design.
349 (define drc2:check-duplicated-slots
351 (define check-duplicated-slots-of-package
353 (define check-slots-loop
355 (if (> (length slots_list) 1)
357 (if (member (car slots_list) (cdr slots_list))
359 (display (string-append "ERROR: duplicated slot "
360 (number->string (car slots_list))
364 (set! errors_number (+ errors_number 1))))
365 (check-slots-loop (cdr slots_list))
367 (check-slots-loop (gnetlist:get-slots uref))))
368 (for-each check-duplicated-slots-of-package packages)
374 ;; Checks for slots not used.
376 (define drc2:check-unused-slots
378 (define check-unused-slots-of-package
381 (define check-slots-loop
382 (lambda (slot_number slots_list)
383 (let ( (numslots (string->number (gnetlist:get-package-attribute uref "numslots"))) )
384 (if (not (member slot_number slots_list))
386 (if (not (char=? action-unused-slots #\c))
388 (if (char=? action-unused-slots #\e)
390 (display (string-append "ERROR: Unused slot "
391 (number->string slot_number)
392 " of uref " uref) port)
393 (set! errors_number (+ errors_number 1)))
395 (display (string-append "WARNING: Unused slot "
396 (number->string slot_number)
397 " of uref " uref) port)
398 (set! warnings_number (+ warnings_number 1))))
400 (if (< slot_number numslots)
401 (check-slots-loop (+ slot_number 1) slots_list)))))
403 (if (integer? (string->number (gnetlist:get-package-attribute uref "numslots")))
404 (check-slots-loop 1 (gnetlist:get-unique-slots uref))
408 (for-each check-unused-slots-of-package packages)
412 ;; Check slot number is greater or equal than numslots for all packages
414 (define drc2:check-slots
416 (define check-slots-of-package
419 (let* ( (numslots_string (gnetlist:get-package-attribute uref "numslots"))
420 (numslots (string->number numslots_string))
421 (slot_string (let ((slots (gnetlist:get-all-package-attributes uref "slot")))
422 (if (or (null? slots) (not (car slots)))
423 "unknown" (car slots))))
424 (slot (string->number slot_string))
427 (define check-slots-loop
429 (if (not (null? slots_list))
430 (let ((this_slot (car slots_list)))
431 (if (integer? this_slot)
432 (if (not (and (<= this_slot numslots) (>= this_slot 1)))
433 ;; If slot is not between 1 and numslots, then report an error.
435 (display (string-append "ERROR: Reference " uref
436 ": Slot out of range ("
437 (number->string this_slot)
440 (set! errors_number (+ errors_number 1)))))
442 (check-slots-loop (cdr slots_list))
445 (if (string-ci=? slot_string "unknown")
447 ;; If slot attribute is not defined.
448 (if (or (string-ci=? numslots_string "unknown") (= numslots 0))
450 ;; No slot neither numslots (or set to zero) attributes defined.
452 ;;(display (string-append "No slotted reference: " uref))
457 ;; Slot not defined, but numslots defined or different than 0.
458 ;; This is incorrect. Check if numslots is a number and
459 ;; report the situation to the user.
460 (if (integer? numslots)
461 ;; If no slot attribute, but numslots is defined and not zero.
463 ;; If numslots is a number, then slot should be defined.
464 (display (string-append "ERROR: Multislotted reference " uref
465 " has no slot attribute defined.") port)
467 (set! errors_number (+ errors_number 1)))
469 (display (string-append "ERROR: Reference " uref
470 ": Incorrect value of numslots attribute ("
471 numslots_string ").")
474 (set! errors_number (+ errors_number 1))
480 ;; Slot attribute defined.
481 ;; If it's a number, then check slots. If it's not, then report an error.
483 (if (integer? numslots)
484 (check-slots-loop (gnetlist:get-unique-slots uref))
486 ;; Slot is defined and it's a number, but numslots it's not a number.
487 (display (string-append "ERROR: Reference " uref
488 ": Incorrect value of numslots attribute ("
489 numslots_string ").") port)
491 (set! errors_number (+ errors_number 1))))
493 ;; Slot attribute is not a number.
494 (display (string-append "ERROR: Reference " uref
495 ": Incorrect value of slot attribute ("
496 slot_string ").") port)
498 (set! errors_number (+ errors_number 1))))
502 (for-each check-slots-of-package packages)
505 ;; Count the ocurrences of a given reference in the given list.
506 (define (drc2:count-reference-in-list refdes lst)
507 (define refdes=? (if (defined? 'case_insensitive) string-ci=? string=?))
509 (lambda (x count) (if (refdes=? refdes x) (1+ count) count))
512 ;; Check duplicated references of the given list
513 ;; If the number of ocurrences of a reference in the schematic doesn't match the number
514 ;; of unique slots used by that part, then that reference is used more than one time in
516 (define drc2:check-duplicated-references
520 (let ( (refdes (car list)))
521 (if (> (drc2:count-reference-in-list refdes (gnetlist:get-non-unique-packages ""))
522 (length (gnetlist:get-unique-slots refdes)))
524 (display (string-append "ERROR: Duplicated reference " refdes ".") port)
526 (set! errors_number (+ errors_number 1))))
527 (drc2:check-duplicated-references port (cdr list))
533 ; End of symbol checking functions
534 ;-----------------------------------------------------------------------
537 ;-----------------------------------------------------------------------
538 ; NETs checking functions
542 ;; Check for NoConnection nets with more than one pin connected.
544 ;; Example of all-nets: (net1 net2 net3 net4)
545 (define (drc2:check-connected-noconnects port all-nets)
549 ((directives (gnetlist:graphical-objs-in-net-with-attrib-get-attrib
551 "device=DRC_Directive"
553 ;Only check nets with a NoConnection directive
555 (member "NoConnection" directives)
556 ( > (length (gnetlist:get-all-connections netname)) '1)
558 (display (string-append "ERROR: Net '"
559 netname "' has connections, but "
560 "has the NoConnection DRC directive: ") port)
561 (drc2:display-pins-of-type port "all" (gnetlist:get-all-connections netname))
564 (set! errors_number (1+ errors_number))))))
568 ;; Check for nets with less than two pins connected.
570 ;; Example of all-nets: (net1 net2 net3 net4)
571 (define drc2:check-single-nets
572 (lambda (port all-nets)
573 (if (not (null? all-nets))
574 (let* ((netname (car all-nets))
575 (directives (gnetlist:graphical-objs-in-net-with-attrib-get-attrib
577 "device=DRC_Directive"
580 ; If one of the directives is NoConnection,
581 ; then it shouldn't be checked.
582 (if (not (member "NoConnection" directives))
584 (if (eq? (length (gnetlist:get-all-connections netname)) '0)
585 (begin (display (string-append "ERROR: Net '"
586 netname "' has no connections.") port)
588 (set! errors_number (+ errors_number 1))
591 (if (eq? (length (gnetlist:get-all-connections netname)) '1)
592 (begin (display (string-append "ERROR: Net '"
593 netname "' is connected to only one pin: ") port)
594 (drc2:display-pins-of-type port "all" (gnetlist:get-all-connections netname))
597 (set! errors_number (+ errors_number 1))
601 (drc2:check-single-nets port (cdr all-nets)))))
605 ;; Return a list with the pintypes of the pins connected to a net.
607 ;; Example. net-conn: ((U100 1) (U101 1)). pintypes-list: ("in" "out" "in")
608 (define drc2:get-pintypes-of-net-connections
609 (lambda (net-conn pintypes-list)
610 (if (not (null? net-conn))
611 (let* ( (element (car net-conn))
612 (device (car element))
613 (pin (car (cdr (car net-conn))))
614 (pintype (gnetlist:get-attribute-by-pinnumber device pin "pintype"))
618 (drc2:get-pintypes-of-net-connections (cdr net-conn)
627 ;; Count pintypes of a net.
629 ;; net: "in", "out", for example.
630 (define drc2:count-pintypes-of-net
632 (define output-list (make-list (length pintype-names) 0))
635 (if (not (member (string-downcase type) pintype-names))
637 (display "INTERNAL ERROR: unknown pin type : " port)
641 (list-set! output-list (drc2:position-of-pintype type)
642 (+ 1 (list-ref output-list (drc2:position-of-pintype type))))))
644 (for-each add-pintype net)
650 ;; Display pins of a specified type connected to a net
652 ;; type: number of the position of the type in the vector, or
653 ;; the string "all" to display all the pins.
654 ;; connections: ((U100 1) (U101 1)), for example.
655 (define drc2:display-pins-of-type
656 (lambda (port type connections)
657 (if (not (null? connections))
659 (let ((device (car (car connections)))
660 (pin (car (cdr (car connections)))))
661 (if (or (and (string? type) (string-ci=? type "all"))
662 (string-ci=? (list-ref pintype-names type)
663 (gnetlist:get-attribute-by-pinnumber device pin "pintype"))
666 (display device port)
670 (drc2:display-pins-of-type port type (cdr connections))
675 ;; Check connection between two pintypes
677 ;; type1,type2: number of the position of the type in the vector.
678 ;; connections: ((U100 1) (U101 1)), for example.
679 (define drc2:check-connection-of-two-pintypes
680 (lambda (port type1 type2 connections netname)
681 (let* (( drc-matrix-value (drc2:get-drc-matrix-element type1 type2)))
683 ((eqv? drc-matrix-value #\c) 1)
684 (else (if (and (not (eqv? drc-matrix-value #\e)) (not (eqv? drc-matrix-value #\w)))
686 (display "INTERNAL ERROR: DRC matrix has unknown value on position " port)
691 (error "INTERNAL ERROR: DRC matrix has unknown value. See output for more information"))
694 (if (eqv? drc-matrix-value #\w)
696 (display "WARNING: " port)
697 (set! warnings_number (+ warnings_number 1)))
699 (display "ERROR: " port)
700 (set! errors_number (+ errors_number 1))
702 (display "Pin(s) with pintype '" port)
703 (display (drc2:get-full-name-of-pintype-by-number type1) port)
705 (display (drc2:display-pins-of-type port type1
707 (display (string-append "\n\tare connected by net '" netname) port)
708 (display "'\n\tto pin(s) with pintype '" port)
709 (display (drc2:get-full-name-of-pintype-by-number type2) port)
711 (display (drc2:display-pins-of-type port type2
718 ;; Check pintypes of the pins connected to a single net
720 ;; type1,type2: number of the position of the type in the vector.
721 ;; connections: ((U100 1) (U101 1)), for example.
722 ;; pintype-count: vector with the number of pins connected to a single net, by pintype.
723 ;; (1 2 3 4 ... 10), for example.
724 (define drc2:check-pintypes-of-single-net
725 (lambda (port connections pintypes pintype-count type1 type2 netname)
726 (define type1-count (list-ref pintype-count type1))
727 (define type2-count (list-ref pintype-count type2))
729 (lambda (port connections pintypes pintype-count type1 type2 netname)
730 (if (< type1 (- (length pintype-names) 2))
731 (drc2:check-pintypes-of-single-net port connections pintypes pintype-count
732 (+ type1 1) (+ type1 1) netname)
736 (lambda (port connections pintypes pintype-count type1 type2 netname)
737 (if (< type2 (- (length pintype-names) 2))
738 (drc2:check-pintypes-of-single-net port connections pintypes pintype-count
739 type1 (+ type2 1) netname)
740 (next-type1 port connections pintypes pintype-count type1 type1 netname)
743 ; Check type1 with type1 first
744 (if (= type1-count 0)
745 ; if no pins of type1 connected, then continue with (+ type1 1)
747 (next-type1 port connections pintypes pintype-count type1 type2 netname))
750 (if (> type1-count 1)
752 (drc2:check-connection-of-two-pintypes port type1 type1 connections netname)
753 (next-type2 port connections pintypes pintype-count type1 type2 netname)
756 (next-type2 port connections pintypes pintype-count type1 type2 netname))
758 (if (= type2-count 0)
759 ; if no pins of type2 connected, then continue with (+ type2 1)
760 (next-type2 port connections pintypes pintype-count type1 type2 netname)
762 (if (and (> type1-count 0) (> type2-count 0))
764 ; Check connections between type1 and type2.
765 (drc2:check-connection-of-two-pintypes port type1 type2 connections netname)
766 ; and continue with the next type2 if within the limits
767 (next-type2 port connections pintypes pintype-count type1 type2 netname)
773 ;; Check if a net has a pintype which can drive the net.
775 ;; pintype-count: vector with the number of pins connected to a single net, by pintype.
776 ;; (1 2 3 4 ... 10), for example.
777 ;; position: number of the position the function is checking.
778 (define drc2:check-if-net-is-driven
779 (lambda (pintype-count position)
780 (if (< position (- (length pintype-names) 1))
781 (if (and (> (list-ref pintype-count position) 0)
782 (= (list-ref pintype-can-drive position) 1))
784 (drc2:check-if-net-is-driven pintype-count (+ position 1)))
788 ;; Check pintype of the pins connected to every net in the design.
790 ;; all-nets: (net1 net2 net3), for example
791 (define drc2:check-pintypes-of-nets
792 (lambda (port all-nets)
793 (if (not (null? all-nets))
794 (let ((netname (car all-nets)))
796 (let* ( (connections (gnetlist:get-all-connections netname))
797 (pintypes (drc2:get-pintypes-of-net-connections
800 (pintype-count (drc2:count-pintypes-of-net pintypes port))
801 (directives (gnetlist:graphical-objs-in-net-with-attrib-get-attrib
803 "device=DRC_Directive"
806 ; If some directives are defined, then it shouldn't be checked.
807 (if (not (member "DontCheckPintypes" directives))
808 (drc2:check-pintypes-of-single-net port connections pintypes pintype-count 0 0 netname))
809 (if (not (defined? 'dont-check-not-driven-nets))
811 (if (and (not (member "DontCheckIfDriven" directives))
812 (not (member "NoConnection" directives)))
813 (if (eqv? (drc2:check-if-net-is-driven pintype-count 0) #f)
815 (set! errors_number (+ errors_number 1))
816 (display "ERROR: Net " port)
817 (display netname port)
818 (display " is not driven." port)
825 (drc2:check-pintypes-of-nets port (cdr all-nets))
830 ;; Check unconnected pins
832 ;; ref-list: ("U1" "U2"), for example.
833 ;; pin-net: ( (pin net) (pin net) ... )
834 (define drc2:check-unconnected-pins
835 (lambda (port ref-list pin-net)
837 (if (not (null? ref-list))
839 (set! ref (car ref-list))
840 (if (not (null? pin-net))
841 (let* ( (pair (car pin-net))
843 (connection (cdr pair))
846 (if (strncmp? connection "unconnected_pin" 15)
848 (let* ((position (drc2:position-of-pintype
849 (gnetlist:get-attribute-by-pinnumber ref pin "pintype")))
850 (drc-matrix-value (drc2:get-drc-matrix-element undefined position)))
852 (if (eqv? drc-matrix-value #\c)
855 (if (eqv? drc-matrix-value #\w)
857 (display "WARNING: " port)
858 (set! warnings_number (+ warnings_number 1)))
860 (display "ERROR: " port)
861 (set! errors_number (+ errors_number 1))
863 (display "Unconnected pin " port)
868 (drc2:check-unconnected-pins port ref-list (cdr pin-net))
872 (drc2:check-unconnected-pins port ref-list (cdr pin-net))
875 (if (> (length ref-list) 1)
876 (drc2:check-unconnected-pins port (cdr ref-list)
877 (gnetlist:get-pins-nets (car (cdr ref-list)))))
882 ; Report pins without the 'pintype' attribute (pintype=unknown)
883 (define (drc2:report-unknown-pintypes port nets)
884 (define (count-unknown-pintypes nets)
886 (lambda (netname count)
887 (let* ((connections (gnetlist:get-all-connections netname))
888 (pintypes (drc2:get-pintypes-of-net-connections connections '()))
889 (pintype-count (drc2:count-pintypes-of-net pintypes port)))
891 (list-ref pintype-count (drc2:position-of-pintype "unknown")))))
893 (define (display-unknown-pintypes nets)
896 (drc2:display-pins-of-type port
897 (drc2:position-of-pintype "unknown")
898 (gnetlist:get-all-connections netname)))
900 (and (> (count-unknown-pintypes nets) 0)
902 (display "NOTE: Found pins without the 'pintype' attribute: " port)
903 (display-unknown-pintypes nets)
907 ; End of Net checking functions
908 ;-----------------------------------------------------------------------
913 ;;; Highest level function
914 ;;; Write my special testing netlist format
917 (lambda (output-filename)
918 (let ((port (if (string=? "-" output-filename)
919 (current-output-port)
920 (open-output-file output-filename))))
923 ;; Perform DRC-matrix sanity checks.
924 ; See if all elements of the matrix are chars
925 (if (not (drc2:drc-matrix-elements-are-correct?))
926 (begin (display "INTERNAL ERROR: DRC matrix elements are NOT all chars." port)
929 (error "INTERNAL ERROR. DRC matrix elements are NOT all chars.")))
931 ;; Check non-numbered symbols
932 (if (not (defined? 'dont-check-non-numbered-parts))
934 (display "Checking non-numbered parts..." port)
936 (drc2:check-non-numbered-items port packages)
939 ;; Check for duplicated references
940 (if (not (defined? 'dont-check-duplicated-references))
942 (display "Checking duplicated references..." port)
944 (drc2:check-duplicated-references port packages)
947 ;; Check for NoConnection nets with more than one pin connected.
948 (if (not (defined? 'dont-check-connected-noconnects))
950 (display "Checking NoConnection nets for connections..." port)
952 (drc2:check-connected-noconnects port (gnetlist:get-all-unique-nets "dummy"))
955 ;; Check nets with only one connection
956 (if (not (defined? 'dont-check-one-connection-nets))
958 (display "Checking nets with only one connection..." port)
960 (drc2:check-single-nets port (gnetlist:get-all-unique-nets "dummy"))
963 ;; Check "unknown" pintypes
964 (if (not (defined? 'dont-report-unknown-pintypes))
966 (display "Checking pins without the 'pintype' attribute..." port)
968 (drc2:report-unknown-pintypes port (gnetlist:get-all-unique-nets "dummy"))
971 ;; Check pintypes of the pins connected to every net
972 (if (not (defined? 'dont-check-pintypes-of-nets))
974 (display "Checking type of pins connected to a net..." port)
976 (drc2:check-pintypes-of-nets port (gnetlist:get-all-unique-nets "dummy"))
979 ;; Check unconnected pins
980 (if (not (defined? 'dont-check-unconnected-pins))
982 (display "Checking unconnected pins..." port)
984 (if (not (null? packages))
985 (drc2:check-unconnected-pins port packages (gnetlist:get-pins-nets (car packages))))
989 (if (not (defined? 'dont-check-slots))
991 (display "Checking slots..." port)
993 (drc2:check-slots port)
996 ;; Check for duplicated slots
997 (if (not (defined? 'dont-check-duplicated-slots))
999 (display "Checking duplicated slots..." port)
1001 (drc2:check-duplicated-slots port)
1004 ;; Check for unused slots
1005 (if (not (defined? 'dont-check-unused-slots))
1007 (display "Checking unused slots..." port)
1009 (drc2:check-unused-slots port)
1012 ;; Display total number of warnings
1013 (if (> warnings_number 0)
1015 (display "Found " port)
1016 (display warnings_number port)
1017 (display " warnings." port)
1020 (display "No warnings found. " port)
1023 ;; Display total number of errors
1024 (if (> errors_number 0)
1026 (display "Found " port)
1027 (display errors_number port)
1028 (display " errors." port)
1031 (display "No errors found. " port)
1034 (close-output-port port)
1036 ;; Make gnetlist return an error if there are DRC errors.
1037 ;; If there are only warnings and it's in quiet mode, then
1038 ;; do not return an error.
1039 (if (> errors_number 0)
1040 (begin (display "DRC errors found. See output file.")
1042 (if (> warnings_number 0)
1043 (if (not (calling-flag? "ignore-warnings-in-return-value" (gnetlist:get-calling-flags)))
1044 (begin (display "DRC warnings found. See output file.")
1051 ;; DRC backend written by Carlos Nieves Onega ends here.
1053 ;; --------------------------------------------------------------------------