scheme-api: Correct some comments.
[geda-gaf/whiteaudio.git] / gnetlist / scheme / gnet-drc2.scm
blobd63bf19fea0c9a0f030e4bcac3c5457e381bd03c
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)
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
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
30 ;;              anymore.
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 
38 ;;              a patch. 
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
44 ;;              self-explaining.
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
64 ;; Parameters
65 ;; ----------
66 ;; Parameters should be passed to the backed using -O option in gnetlist's
67 ;; command line.
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.
74 ;; Output
75 ;; ------
76 ;; By default, the backend outputs to the filename specified in the command line, or to
77 ;; stdout if the output filename is "-".
78 ;; 
79 ;; Configuration
80 ;; -------------
81 ;; 
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.
103 ;; Example:
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 
117 ;; to each net.
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.
123 ;; Example:
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 
130 ;; one type of pin.
131 ;; The DRC matrix can be specified before running this backend. Otherwise, the backend will use the
132 ;; default values.
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
139 ;;;unknown
140 ;;  '(            #\c )
141 ;;;in
142 ;;  '(            #\c   #\c)
143 ;;;out
144 ;;  '(            #\c   #\c   #\e )
145 ;;;io
146 ;;  '(            #\c   #\c   #\w   #\c)
147 ;;;oc
148 ;;  '(            #\c   #\c   #\e   #\w   #\e)
149 ;;;oe
150 ;;  '(            #\c   #\c   #\e   #\w   #\c   #\e)
151 ;;;pas
152 ;;  '(            #\c   #\c   #\c   #\c   #\c   #\c   #\c)
153 ;;;tp
154 ;;  '(            #\c   #\c   #\e   #\w   #\e   #\e   #\c   #\e)
155 ;;;tri
156 ;;  '(            #\c   #\c   #\e   #\c   #\c   #\c   #\c   #\e   #\c)
157 ;;;clk
158 ;;  '(            #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c)
159 ;;;pwr
160 ;;  '(            #\c   #\c   #\e   #\w   #\e   #\e   #\c   #\e   #\e   #\e   #\c)
161 ;;;unconnected
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
175   (syntax-rules ()
176     ((_ name expr)
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.
185 (define unknown  0)
186 (define in       1)
187 (define out      2)
188 (define io       3)
189 (define oc       4)
190 (define oe       5)
191 (define pas      6)
192 (define tp       7)
193 (define tri      8)
194 (define clk      9)
195 (define pwr     10)
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)
202   (define (int01? x)
203     (and (integer? x)
204          (or (= x 0)
205              (= x 1))))
206   (and (list? lst)
207        (= (length lst) (length pintype-names))
208        (every int01? lst)))
210 (define pintype-can-drive
211   (if (defined? 'pintype-can-drive)
212     (if (pintype-can-drive-valid? pintype-can-drive)
213         pintype-can-drive
214         (begin
215           (display "INTERNAL ERROR: List of pins which can drive a net bad specified. Using default value.")
216           (newline)
217           #f))
218     #f))
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 )))
224 ; DRC matrix
226 ; #\e: error    #\w: warning   #\c: correct
227 (define-undefined drc-matrix
228   (list
229 ;  Order is important !
230 ;             unknown in    out   io    oc    oe    pas   tp    tri   clk   pwr unconnected
231 ;unknown
232   '(            #\c )
234   '(            #\c   #\c   )
235 ;out
236   '(            #\c   #\c   #\e   )
238   '(            #\c   #\c   #\w   #\c   )
240   '(            #\c   #\c   #\e   #\w   #\e   )
242   '(            #\c   #\c   #\e   #\w   #\c   #\e   )
243 ;pas
244   '(            #\c   #\c   #\c   #\c   #\c   #\c   #\c   )
246   '(            #\c   #\c   #\e   #\w   #\e   #\e   #\c   #\e   )
247 ;tri
248   '(            #\c   #\c   #\e   #\c   #\c   #\c   #\c   #\e   #\c   )
249 ;clk
250   '(            #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c   #\c   )
251 ;pwr
252   '(            #\c   #\c   #\e   #\w   #\e   #\e   #\c   #\e   #\e   #\e   #\c  )
253 ;unconnected
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))))
267     (begin
268       (display "INTERNAL ERROR: Action when unused slots are found has a wrong value. Using default.")
269       (newline)
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 
278   (lambda (type)
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
283   (lambda (type)
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
288   (lambda (type)
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
293   (lambda (row column)
294     (if (< row column)
295         (list-ref (list-ref drc-matrix column) row)
296         (list-ref (list-ref drc-matrix row) column))))
297   
298 ; Check if all elements of the DRC matrix are characters
299 (define drc2:drc-matrix-elements-are-correct?
300   (lambda ()
301     (let check-row ((row 0))
302       (if (let check-column ((column 0)) 
303             (if (not (char? (drc2:get-drc-matrix-element row column)))
304                 #f
305                 (if (< column (- (length pintype-names) 1))
306                     (check-column (+ column 1))                     
307                     #t)
308                 )
309             )
310           (if (< row (- (length pintype-names) 1))
311               (check-row (+ row 1)) 
312               #t)         
313          #f)
314       )
315       
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)))
334             (begin
335                (if (not (eq? (string-index package #\?) #f))
336                    (begin (display "ERROR: Reference not numbered: " port)
337                           (display package port)
338                           (newline port)
339                           (set! errors_number (+ errors_number 1))
340                           )
341                    )
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
350   (lambda (port)
351     (define check-duplicated-slots-of-package
352       (lambda (uref)
353         (define check-slots-loop
354           (lambda (slots_list)
355             (if (> (length slots_list) 1)
356                 (begin
357                   (if (member (car slots_list) (cdr slots_list))
358                       (begin
359                         (display (string-append "ERROR: duplicated slot " 
360                                                 (number->string (car slots_list))
361                                                 " of uref "
362                                                 uref) port)
363                         (newline port)
364                         (set! errors_number (+ errors_number 1))))
365                   (check-slots-loop (cdr slots_list))
366                   ))))
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
377   (lambda (port)
378     (define check-unused-slots-of-package
379       (lambda (uref)
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))
385                   (begin
386                     (if (not (char=? action-unused-slots #\c))
387                         (begin
388                           (if (char=? action-unused-slots #\e)
389                               (begin 
390                                 (display (string-append "ERROR: Unused slot "
391                                                         (number->string slot_number)
392                                                         " of uref " uref) port)
393                                 (set! errors_number (+ errors_number 1)))
394                               (begin
395                                 (display (string-append "WARNING: Unused slot "
396                                                         (number->string slot_number)
397                                                         " of uref " uref) port)
398                                 (set! warnings_number (+ warnings_number 1))))
399                           (newline port)))))
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))
405             )
406         ))
408     (for-each check-unused-slots-of-package packages)
409     ))
412 ;; Check slot number is greater or equal than numslots for all packages
414 (define drc2:check-slots
415   (lambda (port)
416     (define check-slots-of-package
417       (lambda (uref)
418         
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))
425                 )
426           (let ()
427             (define check-slots-loop
428               (lambda (slots_list)
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.
434                               (begin
435                                 (display (string-append "ERROR: Reference " uref 
436                                                         ": Slot out of range (" 
437                                                         (number->string this_slot)
438                                                         ").") port)
439                                 (newline port)
440                                 (set! errors_number (+ errors_number 1)))))
441                       
442                       (check-slots-loop (cdr slots_list))
443                       ))))
444             
445             (if (string-ci=? slot_string "unknown")
446                 (begin
447                   ;; If slot attribute is not defined.
448                   (if (or (string-ci=? numslots_string "unknown") (= numslots 0))
449                       (begin
450                         ;; No slot neither numslots (or set to zero) attributes defined.
451                         ;; This is correct.
452                         ;;(display (string-append "No slotted reference: " uref))
453                         (display "")
454                         ;;(newline)
455                         )
456                       (begin
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.
462                             (begin
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)
466                               (newline port)
467                               (set! errors_number (+ errors_number 1)))
468                             (begin
469                               (display (string-append "ERROR: Reference " uref 
470                                                       ": Incorrect value of numslots attribute ("
471                                                       numslots_string ").") 
472                                        port)
473                               (newline port)
474                                (set! errors_number (+ errors_number 1))
475                               )
476                             )
477                         ))
478                   )
479                 (begin
480                   ;; Slot attribute defined.
481                   ;; If it's a number, then check slots. If it's not, then report an error.
482                   (if (integer? slot)
483                       (if (integer? numslots)
484                           (check-slots-loop (gnetlist:get-unique-slots uref))
485                           (begin
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)
490                             (newline port)
491                             (set! errors_number (+ errors_number 1))))
492                       (begin
493                         ;; Slot attribute is not a number.
494                         (display (string-append "ERROR: Reference " uref 
495                                                 ": Incorrect value of slot attribute ("
496                                                 slot_string ").") port)
497                         (newline port)
498                         (set! errors_number (+ errors_number 1))))
499                   ))))))
500     
502     (for-each check-slots-of-package packages)
503     ))
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=?))
508   (fold
509    (lambda (x count) (if (refdes=? refdes x) (1+ count) count))
510    0 lst))
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
515 ;;   the schematic.
516 (define drc2:check-duplicated-references 
517   (lambda (port list)
518     (if (null? list)
519         0
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)))
523                    (begin
524                      (display (string-append "ERROR: Duplicated reference " refdes ".") port)
525                      (newline port)
526                      (set! errors_number (+ errors_number 1))))
527                (drc2:check-duplicated-references port (cdr list))
528                ))
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)
546   (for-each
547     (lambda (netname)
548       (let
549         ((directives (gnetlist:graphical-objs-in-net-with-attrib-get-attrib
550                     netname
551                     "device=DRC_Directive"
552                     "value")))
553         ;Only check nets with a NoConnection directive
554         (and
555           (member "NoConnection" directives)
556           ( >  (length (gnetlist:get-all-connections netname)) '1)
557           (begin
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))
562             (display "." port)
563             (newline port)
564             (set! errors_number (1+ errors_number))))))
565     all-nets))
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
576                               netname
577                               "device=DRC_Directive"
578                               "value")))
579             (begin
580               ; If one of the directives is NoConnection, 
581               ; then it shouldn't be checked.
582               (if (not (member "NoConnection" directives))
583                   (begin
584                     (if (eq? (length (gnetlist:get-all-connections netname)) '0)
585                         (begin (display (string-append "ERROR: Net '"
586                                                        netname "' has no connections.") port)
587                                (newline port)
588                                (set! errors_number (+ errors_number 1))
589                                )                      
590                         )
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))
595                                (display "." port)
596                                (newline port)
597                                (set! errors_number (+ errors_number 1))
598                                )                      
599                         )
600                     ))
601               (drc2:check-single-nets port (cdr all-nets)))))
602   ))
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"))
615                 )
616           (begin
617             (cons pintype 
618                   (drc2:get-pintypes-of-net-connections (cdr net-conn)
619                                                           pintypes-list)
620                   )
621             ))
622         (list)
623         )
627 ;;  Count pintypes of a net.
629 ;; net: "in", "out", for example.
630 (define drc2:count-pintypes-of-net
631   (lambda (net port)
632     (define output-list (make-list (length pintype-names) 0))
633     (define add-pintype
634       (lambda (type)
635            (if (not (member (string-downcase type) pintype-names))
636                (begin
637                  (display "INTERNAL ERROR: unknown pin type : " port)
638                  (display type port)
639                  (newline port))
640                (begin
641                  (list-set! output-list (drc2:position-of-pintype type)
642                                        (+ 1 (list-ref output-list (drc2:position-of-pintype type))))))
643            ))
644     (for-each add-pintype net)
645     output-list
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))
658         (begin
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"))
664                     )
665                 (begin
666                   (display device port)
667                   (display ":" port)
668                   (display pin port)
669                   (display " " port)))
670             (drc2:display-pins-of-type port type (cdr connections))
671             ""
672             )))))
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)))
682       (cond
683        ((eqv? drc-matrix-value #\c) 1)
684        (else (if (and (not (eqv? drc-matrix-value #\e)) (not (eqv? drc-matrix-value #\w)))
685                  (begin
686                    (display "INTERNAL ERROR: DRC matrix has unknown value on position " port)
687                    (display type1 port)
688                    (display "," port)
689                    (display type2 port)
690                    (newline port)
691                    (error "INTERNAL ERROR: DRC matrix has unknown value. See output for more information"))
692                  
693                  (begin 
694                    (if (eqv? drc-matrix-value #\w) 
695                        (begin
696                          (display "WARNING: " port)
697                          (set! warnings_number (+ warnings_number 1)))
698                      (begin 
699                        (display "ERROR: " port)
700                        (set! errors_number (+ errors_number 1))
701                        ))         
702                    (display "Pin(s) with pintype '" port)
703                    (display (drc2:get-full-name-of-pintype-by-number type1) port)
704                    (display "': " port)
705                    (display (drc2:display-pins-of-type port type1 
706                                                          connections) port)
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)
710                    (display "': " port)
711                    (display (drc2:display-pins-of-type port type2
712                                                          connections) port)
713                    (newline port)
714                    )
715                  ))))))
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))
728     (define next-type1 
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)       
733             )
734         ))
735     (define next-type2
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)
741             )))
742     
743                                         ; Check type1 with type1 first
744     (if (= type1-count 0)
745                                         ; if no pins of type1 connected, then continue with (+ type1 1)
746         (begin
747           (next-type1 port connections pintypes pintype-count type1 type2 netname))
748           
749     (if (= type1 type2)
750         (if (> type1-count 1)
751             (begin
752               (drc2:check-connection-of-two-pintypes port type1 type1 connections netname)
753               (next-type2 port connections pintypes pintype-count type1 type2 netname)
754               
755               )
756               (next-type2 port connections pintypes pintype-count type1 type2 netname))
757         (begin
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)
761           )
762       (if (and (> type1-count 0) (> type2-count 0))
763           (begin          
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)
768             ))
769     )
770     ))))
772 ;; 
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))
783             #t
784             (drc2:check-if-net-is-driven pintype-count (+ position 1)))
785         #f)))
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)))
795             (begin      
796               (let*  ( (connections (gnetlist:get-all-connections netname))
797                        (pintypes    (drc2:get-pintypes-of-net-connections 
798                                      connections
799                                      '()))
800                        (pintype-count (drc2:count-pintypes-of-net pintypes port))
801                        (directives (gnetlist:graphical-objs-in-net-with-attrib-get-attrib
802                                     netname
803                                     "device=DRC_Directive"
804                                     "value"))
805                        )
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))
810                     (begin
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)
814                               (begin
815                                 (set! errors_number (+ errors_number 1))
816                                 (display "ERROR: Net " port)
817                                 (display netname port)
818                                 (display " is not driven." port)
819                                 (newline port)
820                                 ))
821                           )
822                       ))
823                 
824                 )
825               (drc2:check-pintypes-of-nets port (cdr all-nets))
826   )))
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)
836     (define ref "")
837     (if (not (null? ref-list))
838         (begin
839           (set! ref (car ref-list))
840           (if (not (null? pin-net))
841               (let* ( (pair (car pin-net)) 
842                       (pin (car pair)) 
843                       (connection (cdr pair))
844                       )
845                 (begin
846                   (if (strncmp? connection "unconnected_pin" 15)
847                       (begin
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)))
851                           (begin
852                             (if (eqv? drc-matrix-value #\c)
853                                 #t
854                                 (begin
855                                   (if (eqv? drc-matrix-value #\w) 
856                                       (begin
857                                         (display "WARNING: " port)
858                                         (set! warnings_number (+ warnings_number 1)))
859                                       (begin 
860                                         (display "ERROR: " port)
861                                         (set! errors_number (+ errors_number 1))
862                                         ))      
863                                   (display "Unconnected pin " port)
864                                   (display ref port)
865                                   (display ":" port)
866                                   (display pin port)
867                                   (newline port)
868                                   (drc2:check-unconnected-pins port ref-list (cdr pin-net))
869                                   ))
870                           ))
871                         )
872                       (drc2:check-unconnected-pins port ref-list (cdr pin-net))
873                   )
874                 ))
875               (if (> (length ref-list) 1)
876                   (drc2:check-unconnected-pins port (cdr ref-list) 
877                                                (gnetlist:get-pins-nets (car (cdr ref-list)))))
878             ))
879         )
880     ))
882 ; Report pins without the 'pintype' attribute (pintype=unknown)
883 (define (drc2:report-unknown-pintypes port nets)
884   (define (count-unknown-pintypes nets)
885     (fold
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)))
890          (+ count
891             (list-ref pintype-count (drc2:position-of-pintype "unknown")))))
892      0 nets))
893   (define (display-unknown-pintypes nets)
894     (for-each
895      (lambda (netname)
896        (drc2:display-pins-of-type port
897                                   (drc2:position-of-pintype "unknown")
898                                   (gnetlist:get-all-connections netname)))
899      nets))
900   (and (> (count-unknown-pintypes nets) 0)
901        (begin
902          (display "NOTE: Found pins without the 'pintype' attribute: " port)
903          (display-unknown-pintypes nets)
904          (display "\n"))))
907 ;  End of Net checking functions
908 ;-----------------------------------------------------------------------
913 ;;; Highest level function
914 ;;; Write my special testing netlist format
916 (define drc2
917    (lambda (output-filename)
918       (let ((port (if (string=? "-" output-filename)
919                       (current-output-port)
920                       (open-output-file output-filename))))
921          (begin
922                     
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)
927                        (newline port)
928                        (newline 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))
933                 (begin
934                   (display "Checking non-numbered parts..." port)
935                   (newline port)
936                   (drc2:check-non-numbered-items port packages)
937                   (newline port)))
939             ;; Check for duplicated references   
940             (if (not (defined? 'dont-check-duplicated-references))
941                 (begin
942                   (display "Checking duplicated references..." port)
943                   (newline port)
944                   (drc2:check-duplicated-references port packages)
945                   (newline port)))
947             ;; Check for NoConnection nets with more than one pin connected.
948             (if (not (defined? 'dont-check-connected-noconnects))
949                 (begin
950                   (display "Checking NoConnection nets for connections..." port)
951                   (newline port)
952                   (drc2:check-connected-noconnects port (gnetlist:get-all-unique-nets "dummy"))
953                   (newline port)))
955             ;; Check nets with only one connection
956             (if (not (defined? 'dont-check-one-connection-nets))
957                 (begin
958                   (display "Checking nets with only one connection..." port)
959                   (newline port)
960                   (drc2:check-single-nets port (gnetlist:get-all-unique-nets "dummy"))
961                   (newline port)))
963             ;; Check "unknown" pintypes
964             (if (not (defined? 'dont-report-unknown-pintypes))
965                 (begin
966                   (display "Checking pins without the 'pintype' attribute..." port)
967                   (newline port)
968                   (drc2:report-unknown-pintypes port (gnetlist:get-all-unique-nets "dummy"))
969                   (newline port)))
970             
971             ;; Check pintypes of the pins connected to every net
972             (if (not (defined? 'dont-check-pintypes-of-nets))
973                 (begin
974                   (display "Checking type of pins connected to a net..." port)
975                   (newline port)
976                   (drc2:check-pintypes-of-nets port (gnetlist:get-all-unique-nets "dummy"))
977                   (newline port)))
978             
979             ;; Check unconnected pins
980             (if (not (defined? 'dont-check-unconnected-pins))
981                 (begin
982                   (display "Checking unconnected pins..." port)
983                   (newline port)
984                   (if (not (null? packages))
985                       (drc2:check-unconnected-pins port packages (gnetlist:get-pins-nets (car packages))))
986                   (newline port)))
988             ;; Check slots   
989             (if (not (defined? 'dont-check-slots))
990                 (begin
991                   (display "Checking slots..." port)
992                   (newline port)
993                   (drc2:check-slots port)
994                   (newline port)))
996             ;; Check for duplicated slots   
997             (if (not (defined? 'dont-check-duplicated-slots))
998                 (begin
999                   (display "Checking duplicated slots..." port)
1000                   (newline port)
1001                   (drc2:check-duplicated-slots port)
1002                   (newline port)))
1004             ;; Check for unused slots
1005             (if (not (defined? 'dont-check-unused-slots))
1006                 (begin
1007                   (display "Checking unused slots..." port)
1008                   (newline port)
1009                   (drc2:check-unused-slots port)
1010                   (newline port)))
1012             ;; Display total number of warnings
1013             (if (> warnings_number 0)
1014                 (begin
1015                   (display "Found " port)
1016                   (display warnings_number port)
1017                   (display " warnings." port)
1018                   (newline port))
1019                 (begin
1020                   (display "No warnings found. " port)
1021                   (newline port)))
1023             ;; Display total number of errors
1024             (if (> errors_number 0)
1025                 (begin
1026                   (display "Found " port)
1027                   (display errors_number port)
1028                   (display " errors." port)
1029                   (newline port))
1030                 (begin
1031                   (display "No errors found. " port)
1032                   (newline port)))
1034          (close-output-port port)
1035          
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.")
1041                     (newline))
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.")
1045                             (newline)))))
1047          ))))
1051 ;; DRC backend written by Carlos Nieves Onega ends here.
1053 ;; --------------------------------------------------------------------------