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 ;; SPICE netlist backend written by S. Gieltjes starts here
24 ;; further modified by W. Kazubski to use scaling parameters for devices
27 ;;----------------------------------------------------------------------
29 ;; Started with gnet-spice1.scm by W. Kazubski. Radically
30 ;; hacked by SDB to support advanced spice netlist generation.
31 ;; Project started 3.5.2003 -- SDB.
33 ;; Details and documentation at http://www.brorson.com/gEDA/SPICE/
36 ;; 3.5.2003 -- Started hacking. SDB.
37 ;; 3.17.2003 -- 2nd version. Hacked to allow for .SUBCKT files to model ics.
38 ;; Changed write-ic. Added get-file-type. Added
39 ;; write-subcircuit. SDB.
40 ;; 3.31.2003 -- 3rd version. Hacked to enable creating .SUBCKT schematics for
41 ;; hierarchical circuit modeling.
42 ;; 8.29.2003 -- 4th version. Include patches from Ken Healy to sort netlist,
43 ;; code by SDB to use gnetlist command line args in Scheme fcns,
44 ;; as well as from Theo Deckers to fix strange problem with '.SUBCKT
46 ;; 9.9.2003 -- 5th version. Rearranged code for more organization (I was beginning
47 ;; to get lost. . . .). Incorporated changes to handle external SPICE
48 ;; files more intelligently. Changed spew to be configurable by setting
49 ;; -v from the command line. Placed new fcn debug-spew into gnetlist.scm.
50 ;; Added -I command line flag.
51 ;; 10.14.2003 -- Bugfixes: Added empty-string? and hacked get-file-type to handle
52 ;; case where a model file has an empty line before .SUBCKT or .MODEL.
53 ;; Also modified write-net-names-on-component to gracefully handle
54 ;; case where not every pin has a pinseq attribute. Now only outputs
55 ;; pins with valid pinseq attribute.
56 ;; 12.25.2003 -- Bugfix: Unswizzled emission of pins from user-defined .subckts.
57 ;; (Now correctly uses pinseq to define emission order of pins.) Also
58 ;; added ability to emit attributes for semiconductors (e.g. area, off,
59 ;; ic, etc.) Added in response to user requests.
60 ;; 12.29.2003 -- Two small enhancements requested by Peter Kaiser.
61 ;; 12.29.2003.a -- Minor bugfix.
62 ;; 12.29.2003.b -- Second minor bugfix.
63 ;; 12.29.2003.c -- Change res & cap to incorporate modelname & "area=" attrib.
64 ;; 3.24.2004 -- Bugfixes made to JFET stuff during Feb. Change released now.
65 ;; 8.22.2004 -- Added command line as first line of file.
66 ;; 8.29.2004 -- Changed sense source naming in controlled sources because the old convention
67 ;; was confusing ngspice.
68 ;; 10.9.2004 -- Added patches for voltage controlled switches from Peter Kaiser.
69 ;; 3.16.2005 -- Fixed CCCS bug (typo in Vsense) noticed by David Logan
70 ;; 5.16.2005 -- Modified behavior of .INCLUDE directive. Now by default it just
71 ;; spits out the string instead of putting the contents of the file
72 ;; into the SPICE netlist. You can force insertion of the file using
74 ;; 6.12.2005 -- Changed order of writing out netlist and .model/.subckt cards to
75 ;; facilitate use of numparam with ngspice. Change supplied by
77 ;; 9.11.2005 -- Incorporated patch from Paul Bunyk to enable netlisting of
78 ;; Josephson junctions and "K" mutual inductances. Also enabled
79 ;; netlisting of "COIL" devices as inductors.
80 ;; 12.27.2005 -- Fix bug discovered by John Doty: spice-IO pins with refdes greater
81 ;; than P9 were sorted incorrectly (as strings). Now they are sorted
83 ;; 3.10.2006 -- Added "m" attribute to PMOS and NMOS per request of Peter Kaiser.
84 ;; 4.11.2006 -- Changed the .END and .ENDS cards to lowercase.
85 ;; This fixes bug 1442912. Carlos Nieves Onega.
86 ;; 2.10.2007 -- Various bugfixes. Also incorporated slotted part
87 ;; netlist patch from Jeff Mallatt. SDB.
88 ;; 4.28.2007 -- Fixed slotted part stuff so that it uses pinseq to emit pins. SDB
89 ;; 1.9.2008 -- Fix slotted part handling to work without a modified pinseq. pcjc2
90 ;; 1.3.2011 -- Combine write-ic and write-subcircuit with a fix to the unbound
91 ;; type variable. Fully document a check for the special "?" value
92 ;; explaining why it fails silently. Clean up
93 ;; write-net-names-on-component to make it a bit more flexible.
94 ;; Combine write-probe-item and write-net-names-on-component. Add
95 ;; a range utility function. CC
97 ;;**********************************************************************************
99 ;; Organization of gnet-spice-sdb.scm file:
100 ;; -- Functions for program housekeeping, handling of calling flags, file manipulation.
101 ;; -- Functions for handling nets & devices and creating SPICE cards.
102 ;; -- High-level functions which control program flow. Note that the program entry
103 ;; point lives at the very bottom of this file.
105 ;; Unfortunately, no organization is present beneath this top level. . . .
107 ;;**********************************************************************************
110 ;;**********************************************************************************
111 ;;************ Program housekeeping, handling calling flags, etc. ****************
112 ;;**********************************************************************************
114 ;; The following is needed to make guile 1.8.x happy.
115 (use-modules (ice-9 rdelim) (srfi srfi-1))
117 ;;--------------------------------------------------------------------------------
118 ;; spice-sdb:loop-through-files -- loops through the model-file list, and for each file
119 ;; name discovered in the list, it processes the file by invoking handle-spice-file.
120 ;;--------------------------------------------------------------------------------
121 (define spice-sdb:loop-through-files
122 (lambda (file-info-list port)
123 (if (not (null? file-info-list))
124 (let* ((list-element (car file-info-list))
125 (model-name (car list-element))
126 (file-name (cadr list-element))
127 (file-type (caddr list-element))
129 (spice-sdb:handle-spice-file file-name port)
130 (spice-sdb:loop-through-files (cdr file-info-list) port)
135 ;;--------------------------------------------------------------------------------
136 ;; spice-sdb:get-file-info-list-item -- loops through the model-file list looking
137 ;; for triplet corresponding to model-name. If found, it returns the corresponding
138 ;; list. If not found, returns #f
139 ;;--------------------------------------------------------------------------------
140 (define spice-sdb:get-file-info-list-item
141 (lambda (model-name file-info-list)
142 (if (null? file-info-list)
143 '() ;; return #f upon empty list.
144 ;; #f replaced with '() by peter
145 (let* ((list-element (car file-info-list)) ;; else process list-item
146 (list-elt-model-name (car list-element))
147 (list-elt-file-name (cadr list-element))
148 (list-elt-file-type (caddr list-element))
150 (if (string=? list-elt-model-name model-name)
151 list-element ;; found model-name. Reutrn list-element.
152 (spice-sdb:get-file-info-list-item model-name (cdr file-info-list)) ;; otherwise, recurse.
158 ;;--------------------------------------------------------------------------
159 ;; handle-spice-file: This wraps insert-text-file.
160 ;; Calling form: (handle-spice-file file-name)
161 ;; It looks to see if the -I flag was set at the command line. If so,
162 ;; it just writes a .INCLUDE card with the file name. If not, it calls
163 ;; insert-text-file to stick the file's contents into the SPICE netlist.
164 ;;--------------------------------------------------------------------------
165 (define spice-sdb:handle-spice-file
166 (lambda (file-name port)
167 (debug-spew (string-append "Handling spice model file " file-name "\n"))
168 (if (calling-flag? "include_mode" (gnetlist:get-calling-flags))
169 (display (string-append ".INCLUDE " file-name "\n") port) ;; -I found: just print out .INCLUDE card
170 (spice-sdb:insert-text-file file-name port) ;; -I not found: invoke insert-text-file
171 ) ;; end of if (calling-flag
175 ;;--------------------------------------------------------------------------
176 ;; Given a filename, open the file, get the contents, and dump them
177 ;; into the spice file.
178 ;; Calling form is "(insert-text-file input-file output-file)"
179 ;; The function opens input-file, but assumes that output-file is
182 ;; This function is usually used to include spice models contained in
183 ;; files into the netlist. Note that it doesn't
184 ;; check the correctness of the spice code in the file -- you're on your own!
185 ;;---------------------------------------------------------------------------
186 (define spice-sdb:insert-text-file
187 (lambda (model-filename port)
188 (let ((model-file (open-input-file model-filename)) )
189 (display (string-append "*vvvvvvvv Included SPICE model from " model-filename " vvvvvvvv\n") port)
190 (let while ((model-line (read-line model-file)))
191 (if (not (eof-object? model-line))
193 (display (string-append model-line "\n") port)
194 ;; (display (string-append "-- model-line = " model-line "\n")) ;; super debug statement
195 (while (read-line model-file))
196 ) ;; end of inner begin
198 ) ;; end of inner let
199 (close-port model-file)
200 (display (string-append "*^^^^^^^^ End of included SPICE model from " model-filename " ^^^^^^^^\n") port)
201 (display (string-append "*\n") port)
202 ) ;; end of outer let
207 ;;----------------------------------------------------------
208 ;; Figure out if this schematic is a .SUBCKT lower level.
209 ;; This is determined if there is a spice-subcircuit-LL
210 ;; device instantiated somewhere on the schematic.
211 ;; If it is a .SUBCKT, return ".SUBCKT model-name"
212 ;;----------------------------------------------------------
213 (define spice-sdb:get-schematic-type
216 (let* ((package (car ls)) ;; assign package
217 (device (get-device package)) ;; assign device.
218 ) ;; end of let* assignments
220 ;; (display (string-append "in get-schematic-type, device = " device "\n"))
221 (if (string=? device "spice-subcircuit-LL") ;; look for subcircuit label
222 (string-append ".SUBCKT " (gnetlist:get-package-attribute package "model-name"))
223 (spice-sdb:get-schematic-type (cdr ls)) ;; otherwise just iterate to next package.
227 "normal schematic" ; return "normal schematic" if no spice-subcircuit-LL is found
232 ;;----------------------------------------------------------
233 ;; Extract the modelname from the .SUBCKT modelname line.
234 ;; Just grab the chars from char 8 to the end of the string.
235 ;;---------------------------------------------------------
236 (define spice-sdb:get-subcircuit-modelname
237 (lambda (schematic-type)
238 (substring schematic-type 8 (string-length schematic-type))
243 ;;-----------------------------------------------------------
244 ;; This iterates through the schematic and compiles a list of
245 ;; all spice-IO pins found. This is used when writing out
246 ;; a .SUBCKT lower level netlist.
247 ;;-----------------------------------------------------------
248 (define spice-sdb:get-spice-IO-pins
249 (lambda (ls spice-io-package-list)
252 spice-io-package-list ;; end iteration & return list if ls is empty.
254 (let* ((package (car ls)) ;; otherwise process package. . .
255 (device (get-device package))
257 (if (string=? device "spice-IO") ;; look for subcircuit label
259 ;; we have found a spice-IO pin.
260 (spice-sdb:get-spice-IO-pins (cdr ls) (cons package spice-io-package-list))
262 ;; no spice-IO pin found. Iterate . . . .
263 (spice-sdb:get-spice-IO-pins (cdr ls) spice-io-package-list)
265 ) ;; end of if string=?
273 ;;----------------------------------------------------------------
274 ;; This takes the list of io-pin-packages and sorts it in order of
276 ;; Repaired on 12.27.2005 to correctly sort pin numbers > 9.
277 ;;----------------------------------------------------------------
278 (define spice-sdb:sort-spice-IO-pins
279 (lambda (package-list)
280 ;; Yes, this isn't good Scheme form. Tough! Writing this out
281 ;; in a functional programming form would be totally confusing!
282 ;; Note that this fcn requires that
283 ;; each spice-IO pin have the same, single character prefix (i.e. 'P')
284 (let* ((char-prefixes (map car (map string->list package-list))) ;; Pull off first char (prefix)
285 (prefixes (map string char-prefixes)) ;; Make list of strings from prefixes
286 (split-numbers-list (map cdr (map string->list package-list))) ;; Pull off refdes numbers as list elements
287 (string-numbers-list (map list->string split-numbers-list)) ;; Recombine split up (multidigit) number strings
288 (numbers-list (map string->number string-numbers-list)) ;; Convert strings to numbers for sorting
289 (sorted-numbers-list (sort numbers-list <)) ;; Sort refdes numbers as numbers
290 (sorted-string-numbers-list (map number->string sorted-numbers-list)) ) ;; Create sorted list of refdes strings.
292 ;; (debug-spew "Packages found = \n")
293 ;; (debug-spew package-list)
294 ;; (debug-spew "\nPrefixes found = \n")
295 ;; (debug-spew prefixes)
296 ;; (debug-spew "\nNumbers found -- split-numbers-list\n")
297 ;; (debug-spew split-numbers-list)
298 ;; (debug-spew "\nNumbers found -- numbers-list\n")
299 ;; (debug-spew numbers-list)
300 ;; (debug-spew "\nSorted-numbers-list\n")
301 ;; (debug-spew sorted-numbers-list)
302 ;; (debug-spew "\nSorted-string-numbers-list\n")
303 ;; (debug-spew sorted-string-numbers-list)
305 (map-in-order string-append prefixes sorted-string-numbers-list) ;; Laminate prefixes back onto refdes numbers & return.
312 ;;----------------------------------------------------------------
313 ;; Given a list of spice-IO packages (refdeses), this function returns the list
314 ;; of nets attached to the IOs.
315 ;;----------------------------------------------------------------
316 (define spice-sdb:get-IO-nets
317 (lambda (package-list net-list)
318 (if (null? package-list)
320 net-list ;; end iteration & return net-list if ls is empty.
322 (let* ((package (car package-list)) ;; otherwise process package. . .
323 (net (car (gnetlist:get-nets package "1"))) ;; get the net attached to pin 1
326 (spice-sdb:get-IO-nets (cdr package-list) (cons net net-list))
333 ;;----------------------------------------------------------
334 ;; This takes a list and turns it into a string.
335 ;; The difference between this and list->string is that
336 ;; this fun can handle lists made up of multi-char strings.
337 ;;----------------------------------------------------------
338 (define list-2-string
344 (if (null? local-list)
345 st ;; end iteration & return string if list is empty.
346 (begin ;; otherwise turn next element of list into string. . .
347 (set! st (string-append (car local-list) " " st)) ;; stuff next element onto st
348 (while st (cdr local-list)) ;; iterate with remainder of ls
356 ;;----------------------------------------------------------
357 ;; This returns #t if the string is composed only of
358 ;; whitespace. It works by turning the string into
359 ;; a list, and then checking to see if it is the empty
360 ;; list. If so, it returns #t.
361 ;;----------------------------------------------------------
362 (define empty-string?
364 (null? (string->list string))
369 ;;----------------------------------------------------------
370 ;; This returns a list of all the integers from start to
371 ;; stop. It is similar to perl's range operator '..'
372 ;;----------------------------------------------------------
373 (define (range start stop . step)
375 (iota (+ (- stop start) 1) start)
377 (set! step (car step))
378 (iota (+ (ceiling (/ (- stop start) step)) 1) start step)
384 ;;----------------------------------------------------------
385 ;; Given a filename, open the file, get the first line,
386 ;; and see if it is a .MODEL or .SUBCKT file.
387 ;; Returns either ".MODEL" or ".SUBCKT" or "OTHER"
388 ;; Calling form is "(spice-sdb:get-file-type input-file)"
389 ;; The function opens input-file, and closes it when it is done.
390 ;;----------------------------------------------------------
391 (define spice-sdb:get-file-type
392 (lambda (model-filename)
394 (let ((model-file (open-input-file model-filename)) )
395 (let while ((file-line (read-line model-file)) )
398 ((eof-object? file-line) ;; Arrived at end of line without finding .MODEL or .SUBCKT. Return "OTHER"
401 ((empty-string? file-line)
402 (while (read-line model-file)) ) ;; Found empty line. Iterate before doing anything else.
404 ((string=? (string (string-ref file-line 0)) "*")
405 (while (read-line model-file)) ) ;; Found *comment. Iterate.
407 ((string=? (string (string-ref file-line 0)) ".")
409 (debug-spew "In get-file-type, first-char = .\n") ;; DEBUG stuff
412 ((string-ci=? (safe-string-head file-line 7) ".subckt") ;; found .subckt as first line.
415 ((string-ci=? (safe-string-head file-line 6) ".model") ;; found .model as first line.
418 (else "OTHER") ;; first . spice card is neither .model nor .subckt
426 ;; (display "In get-file-type, first-char = <other>\n")
427 (while (read-line model-file))
433 ) ;; end of inner lets
434 ) ;; end of outer let
439 ;;-------------------------------------------------------------------
440 ;; write all listed and available attributes in the form of <variable>=<value>
441 ;;-------------------------------------------------------------------
442 (define spice-sdb:write-list-of-attributes
443 (lambda (package attrib-list port)
444 (if (not (null? attrib-list))
446 ; Is it possible to make no differentiation between upper and lower case?
447 ; That relieves you of mixed case forms e.g. As, AS, as..., they are the
448 ; same attributes, spice3f5 is case insensitive. And other spice versions?
449 (if (not (string=? (gnetlist:get-package-attribute package (car attrib-list)) "unknown"))
450 (display (string-append " " (car attrib-list) "="
451 (gnetlist:get-package-attribute package (car attrib-list))) port))
452 (spice-sdb:write-list-of-attributes package (cdr attrib-list) port)))))
455 ;;---------------------------------------------------------------
456 ;; write prefix if first char of refdes is improper,
457 ;; eg. if MOSFET is named T1 then becomes MT1 in SPICE
458 ;;---------------------------------------------------------------
459 (define spice-sdb:write-prefix
460 (lambda (package prefix port)
461 (let ((different-prefix (not (string=? (substring package 0 1) prefix)) )
462 (nomunge (calling-flag? "nomunge_mode" (gnetlist:get-calling-flags)) )
464 (debug-spew (string-append "Checking prefix. Package prefix =" (substring package 0 1) "\n"))
465 (debug-spew (string-append " correct prefix =" prefix "\n"))
466 (debug-spew " nomunge mode = ")
468 (debug-spew (string-append "\n different-prefix="))
469 (debug-spew different-prefix)
471 (if (and different-prefix (not nomunge))
472 (display prefix port) )
478 ;;---------------------------------------------------------------
479 ;; spice-sdb:packsort
480 ;; Sort procedure to order refdes's alphabetically but
481 ;; keep A? packages at the end of list so SPICE simulation
482 ;; directives operate correctly.
483 ;; This fcn written by Ken Healy to enable SPICE netlisting for
484 ;; Gnucap, which wants A refdes cards (i.e. SPICE directives)
485 ;; to appear last in the SPICE netlist. Slightly modified
486 ;; and incorporated into main spice-sdb release by SDB on 9.1.2003.
487 ;; To output the netlist in sorted order, use the -s switch
488 ;; when invoking gnetlist from the command line. Example:
489 ;; gnetlist -s -g spice-sdb -o output.spice Schematic.sch
490 ;; The default behavior (i.e. if -s is not specified) is to do
492 ;;---------------------------------------------------------------
493 (define spice-sdb:packsort
495 (let ((xdes (string-ref x 0))
496 (ydes (string-ref y 0))
497 (xnum (string-tail x 1))
498 (ynum (string-tail y 1))
501 (if (char-ci=? xdes ydes)
502 (if (string-ci<? xnum ynum) #t #f)
503 (if (char-ci=? xdes #\A) #f
504 (if (char-ci=? ydes #\A) #t
505 (if (char-ci<? xdes ydes) #t #f)))))))
507 (define (string-tail string start)
508 (substring string start (string-length string)))
511 ;;---------------------------------------------------------------
512 ;; spice-sdb:sort_refdes?
513 ;; Returns #t or #f depending upon if -s was discovered in
514 ;; the calling flags given to gnetlist. Used in conjunction with
515 ;; spice-sdb:packsort.
516 ;; Calling form: (spice-sdb:sort-refdes? (gnetlist:get-calling-flags))
518 ;;---------------------------------------------------------------
519 ;; Note: I should re-write this to use calling-flag? . . . .
520 (define spice-sdb:sort-refdes?
521 (lambda (calling-flag-list)
523 (if (null? calling-flag-list)
524 '#f ;; return #f if null list -- sort_mode not found.
525 (let* ((calling-pair (car calling-flag-list)) ;; otherwise look for sort_mode in remainder of list.
526 (calling-flag (car calling-pair))
527 (flag-value (cadr calling-pair)) )
529 (if (string=? calling-flag "sort_mode")
530 flag-value ;; return flag-value if sort_mode found
531 (spice-sdb:sort-refdes? (cdr calling-flag-list)) ;; otherwise recurse until sort_mode is found
538 ;;**********************************************************************************
539 ;;*************** Dealing with nets, devices, & SPICE cards. *******************
540 ;;**********************************************************************************
542 ;;-----------------------------------------------------------
543 ;; gnet-spice replacement of gnetlist:get-nets, a net labeled "GND" becomes 0
544 ;;-----------------------------------------------------------
545 (define spice-sdb:get-net
546 (lambda (refdes pin-name)
547 (let ((net-name (gnetlist:get-nets refdes pin-name)))
548 (cond ((string=? (car net-name) "GND") (cons "0" #t))
549 (else (cons (car net-name) #t)))
555 ;;---------------------------------------------------------------------
556 ;; write netnames connected to pin-a and pin-b
557 ;; (currently used by the controlled sources (e, g, f and h)
558 ;;---------------------------------------------------------------------
559 (define spice-sdb:write-two-pin-names
560 (lambda (package pin-a pin-b port)
561 (display (string-append
562 (car (spice-sdb:get-net package (gnetlist:get-attribute-by-pinseq package pin-a "pinnumber"))) " ") port)
563 (display (string-append
564 (car (spice-sdb:get-net package (gnetlist:get-attribute-by-pinseq package pin-b "pinnumber"))) " ") port)))
567 ;;----------------------------------------------------------------
568 ;; write a current controlled voltage source and implement the necessary
569 ;; current measuring voltage source
570 ;;----------------------------------------------------------------
571 (define spice-sdb:write-ccvs
572 (lambda (package port)
574 (display "* begin ccvs expansion, h<name>\n" port)
575 ;; implement the controlled current source
576 ;; the user should create the refdes label begining with a h
577 (display (string-append package " ") port)
578 (spice-sdb:write-two-pin-names package "1" "2" port)
579 (display (string-append "Vsense_" package " " (spice-sdb:component-value package) "\n" ) port)
580 ;; implement the current measuring voltage source
581 (display (string-append "Vsense_" package " ") port)
582 (spice-sdb:write-two-pin-names package "3" "4" port)
583 (display "dc 0\n" port)
584 ;; now it is possible to leave the output voltage source unconnected
585 ;; i.e. spice won't complain about unconnected nodes
586 (display (string-append "IOut_" package " ") port)
587 (spice-sdb:write-two-pin-names package "1" "2" port)
588 (display "dc 0\n" port)
589 (display "* end ccvs expansion\n" port))))
592 ;;-----------------------------------------------------------------------
593 ;; write a current controlled current source and implement the necessary
594 ;; current measuring voltage source
595 ;;-----------------------------------------------------------------------
596 (define spice-sdb:write-cccs
597 (lambda (package port)
599 (display "* begin cccs expansion, f<name>\n" port)
600 ;; implement the controlled current source
601 ;; the user should create the refdes label begining with a f
602 (display (string-append package " ") port)
603 (spice-sdb:write-two-pin-names package "1" "2" port)
604 (display (string-append "Vsense_" package " " (gnetlist:get-package-attribute package "value") "\n" ) port)
605 ;; implement the current measuring voltage source
606 (display (string-append "Vsense_" package " ") port)
607 (spice-sdb:write-two-pin-names package "3" "4" port)
608 (display "dc 0\n" port)
609 (display "* end cccs expansion\n" port))))
612 ;;-------------------------------------------------------------------------
613 ;; write a voltage controlled current source and implement the necessary
614 ;; voltage measuring current source
615 ;;-------------------------------------------------------------------------
616 (define spice-sdb:write-vccs
617 (lambda (package port)
619 (display "* begin vccs expansion, g<name>\n" port)
620 ;; implement the controlled current source
621 ;; the user should create a refdes label beginning with a g
622 (display (string-append package " ") port)
623 (spice-sdb:write-net-names-on-component package port)
624 (display (string-append (spice-sdb:component-value package) "\n") port)
625 ;; implement the voltage measuring current source
626 ;; imagine yourself copying the voltage of a voltage source with an internal
627 ;; impedance, spice starts complaining about unconnected nets if this current
628 ;; source is not here.
629 (display (string-append "IMeasure_" package " ") port)
630 (spice-sdb:write-two-pin-names package "3" "4" port)
631 (display "dc 0\n" port)
632 (display "* end vccs expansion\n" port))))
635 ;;------------------------------------------------------------------------
636 ;; write a voltage controlled voltage source and implement the necessary
637 ;; voltage measuring current source
638 ;;------------------------------------------------------------------------
639 (define spice-sdb:write-vcvs
640 (lambda (package port)
642 (display "* begin vcvs expansion, e<name>\n" port)
643 ;; implement the controlled voltage source
644 ;; the user should create a refdes label beginning with an e
645 (display (string-append package " ") port)
646 (spice-sdb:write-net-names-on-component package port)
647 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
648 ;; implement the voltage measuring current source
649 ;; imagine yourself copying the voltage of a voltage source with an internal
650 ;; impedance, spice starts complaining about unconnected nets if this current
651 ;; source is not here.
652 (display (string-append "Isense_" package " ") port)
653 (spice-sdb:write-two-pin-names package "3" "4" port)
654 (display "dc 0\n" port)
655 ;; with an output current source it is possible to leave the output voltage source
656 ;; unconnected i.e. spice won't complain about unconnected nodes
657 (display (string-append "IOut_" package " ") port)
658 (spice-sdb:write-two-pin-names package "1" "2" port)
659 (display "dc 0\n" port)
660 (display "* end vcvs expansion\n" port))))
663 ;;--------------------------------------------------------------------------
664 ;; Create a nullor, make sure it consists of a voltage controlled source
665 ;;--------------------------------------------------------------------------
666 (define spice-sdb:write-nullor
667 (lambda (package port)
669 (display "* begin nullor expansion, e<name>\n" port)
670 ;; implement the controlled voltage source
671 (display (string-append "E-" package " ") port)
672 (spice-sdb:write-net-names-on-component package port)
673 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
674 ;; implement the voltage measuring current source
675 ;; imagine yourself copying the voltage of a voltage source with an internal
676 ;; impedance, spice starts complaining about unconnected nets if this current
677 ;; source is not here.
678 (display (string-append "IMeasure_" package " ") port)
679 (spice-sdb:write-two-pin-names package "3" "4" port)
680 (display "dc 0\n" port)
681 ;; with an output current source it is possible to leave the output voltage source
682 ;; unconnected i.e. spice won't complain about unconnected nodes
683 (display (string-append "IOut_" package " ") port)
684 (spice-sdb:write-two-pin-names package "1" "2" port)
685 (display "dc 0\n" port)
686 (display "* end of nullor expansion\n" port))))
689 ;;----------------------------------------------------------------
691 ;; Write-transistor-diode: writes out component followed by
692 ;; model or model file associated
693 ;; with the component.
694 ;; This function does the following:
695 ;; 1. Writes out the correct refdes prefix (if specified and necessary).
696 ;; 2. Writes out the refdes and nets
697 ;; 3. Looks for "model-name" attribute. Writes it out if it exists.
698 ;; 4. If there is no "model-name" attribute, it writes out the "value"
699 ;; attribute. If there is no "value" attribute, it writes out "unknown"
700 ;; and returns, causing the spice simulator to puke when the netlist
701 ;; is run. This is important
702 ;; 'cause the spice simulator needs to have some indication of what
703 ;; model to look for.
704 ;; 5. Outputs optional attributes attached to device, if any. Feature
705 ;; added by SDB on 12.25.2003.
706 ;; 6. Outputs a new line
707 ;; 7. Looks for a the "model" attribute. If it exists, it it writes out
708 ;; a .MODEL line like this: .MODEL model-name type (model)
710 ;;----------------------------------------------------------------
711 (define spice-sdb:write-transistor-diode
712 (lambda (package prefix type attrib-list port)
714 ;; First do local assignments
715 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
716 (model (gnetlist:get-package-attribute package "model"))
717 (value (gnetlist:get-package-attribute package "value"))
718 (area (gnetlist:get-package-attribute package "area"))
719 (off (gnetlist:get-package-attribute package "off"))
720 (model-file (gnetlist:get-package-attribute package "file"))
721 ) ;; end of local assignments
723 ;; Write out the refdes prefix, if specified and necessary.
725 (spice-sdb:write-prefix package prefix port)
728 ;; Next we write out the refdes and nets.
729 (spice-sdb:write-component-no-value package port)
731 ;; next look for "model-name" attribute. Write it out if it exists.
732 ;; otherwise look for "device" attribute.
733 (if (not (string=? model-name "unknown"))
734 (display (string-append model-name " " ) port) ;; display model-name if known
735 (display (string-append value " ") port)) ;; otherwise display device
737 ;; Next write out attribtes if they exist
738 ;; First attribute is area. It is written as a simple string
739 (if (not (string=? area "unknown"))
740 (display (string-append area " ") port))
742 ;; Next attribute is off. It is written as a simple string
743 (if (not (string=? off "unknown"))
744 (display (string-append off " ") port))
746 ;; Write out remaining attributes
747 (spice-sdb:write-list-of-attributes package attrib-list port)
749 ;; Now write out newline in preparation for writing out model.
752 ;; Now write out any model which is pointed to by the part.
755 ;; one line model and model name exist
756 ( (not (or (string=? model "unknown") (string=? model-name "unknown")))
757 (debug-spew (string-append "found model and model-name for " package "\n"))
758 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port) )
760 ;; one line model and component value exist
761 ( (not (or (string=? model "unknown") (string=? value "unknown")))
762 (debug-spew (string-append "found model and value for " package "\n"))
763 (display (string-append ".MODEL " model-name " " type " (" value ")\n") port) )
765 ;; model file and model name exist
766 ( (not (or (string=? model-file "unknown") (string=? model-name "unknown")))
767 (debug-spew (string-append "found file and model-name for " package "\n"))
768 (debug-spew "I'll deal with the file later . . .\n")
771 ;; model file and component value exist
772 ( (not (or (string=? model-file "unknown") (string=? value "unknown")))
773 (debug-spew (string-append "found file and value for " package "\n"))
774 (debug-spew "I'll deal with the file later . . .\n")
783 ;;----------------------------------------------------------------
785 ;; This writes out a valid diode refdes & then calls
786 ;; the function which writes the rest of the line.
787 ;;----------------------------------------------------------------
788 (define spice-sdb:write-diode
789 (lambda (package port)
790 (debug-spew (string-append "Found diode. Refdes = " package "\n"))
791 (let ((attrib-list (list "ic" "temp") ))
792 (spice-sdb:write-transistor-diode package "D" "D" attrib-list port))
797 ;;----------------------------------------------------------------
798 ;; spice-sdb:write-ic
799 ;; This writes out a valid ic or subcircuit line.
800 ;; The algorithm is as follows:
801 ;; 1. Figure out what type of model goes with this part from
802 ;; file-info-list. If it isn't listed, look for a MODEL attribute.
803 ;; If MODEL attribute is attached, write out SPICE card, and then
804 ;; write out .MODEL on next line.
805 ;; If no MODEL attribute is attached, just write out what little
806 ;; we know. Then return
807 ;; 2. If the model-name is in the file-info-list, get the associated
808 ;; file-type. Compare it against the component's refdes. If model-type
809 ;; is .MODEL or .SUBCKT and refdes doesn't begin with a U or X
810 ;; respectively, prepend the correct prefix to the refdes.
811 ;; 3. Print out the rest of the line.
813 ;;----------------------------------------------------------------
814 (define (spice-sdb:write-ic package file-info-list port)
816 ;; First do local assignments
817 (let ((first-char (string (string-ref package 0))) ;; extract first char of refdes
818 (model-name (gnetlist:get-package-attribute package "model-name"))
819 (model (gnetlist:get-package-attribute package "model"))
820 (value (gnetlist:get-package-attribute package "value"))
821 (type (gnetlist:get-package-attribute package "type"))
822 (model-file (gnetlist:get-package-attribute package "file"))
824 ) ;; end of local assignments
827 ((string=? first-char "U") (debug-spew (string-append "Found ic. Refdes = " package "\n")))
828 ((string=? first-char "X") (debug-spew (string-append "Found subcircuit. Refdes = " package "\n")))
831 ;; First, if model-name is empty, we use value attribute instead.
832 ;; We do this by sticking the contents of "value" into "model-name".
833 (if (string=? model-name "unknown")
834 (set! model-name value))
836 ;; Now get item from file-info-list using model-name as key
837 (set! list-item (spice-sdb:get-file-info-list-item model-name file-info-list))
839 ;; check to see if list-item is null.
840 (if (null? list-item)
842 ;; list-item is null. Evidently, we didn't discover any files holding this model.
843 ;; Instead we look for model attribute
844 (if (not (string=? model "unknown"))
845 (begin ;; model attribute exists -- write out card and model.
846 (debug-spew "Model info not found in model file list, but model attribute exists. Write out spice card and .model line..\n")
847 (spice-sdb:write-component-no-value package port)
848 (display (string-append model-name "\n" ) port)
849 (display (string-append ".MODEL " model-name " ") port)
850 (if (not (string=? type "unknown")) (display (string-append type " ") port)) ;; If no type then just skip it.
851 (display (string-append "(" model ")\n") port)
853 (begin ;; no model attribute either. Just write out card.
854 (debug-spew "Model info not found in model file list. No model attribute either. Just write what we know.\n")
855 (spice-sdb:write-component-no-value package port)
856 (display (string-append model-name "\n" ) port)
858 ) ;; end if (not (string=? . . . .
860 ;; list-item is not null. Therefore we process line depending upon contents of list-item
861 (let ((file-type (caddr list-item)) )
863 ;; ---- file holds a model ----
864 ((string=? file-type ".MODEL")
866 (debug-spew (string-append "Found .MODEL with model-file and model-name for " package "\n"))
867 (spice-sdb:write-prefix package "U" port) ;; this prepends an "U" to the refdes if needed, since we have a .model
868 (spice-sdb:write-component-no-value package port)
869 (display (string-append model-name "\n" ) port)
870 (debug-spew "We'll handle the file contents later . . .\n")
873 ;; ---- file holds a subcircuit ----
874 ((string=? file-type ".SUBCKT")
876 (debug-spew (string-append "Found .SUBCKT with model-file and model-name for " package "\n"))
877 (spice-sdb:write-prefix package "X" port) ;; this prepends an "X" to the refdes if needed, since we have a .subckt
878 (spice-sdb:write-component-no-value package port)
879 (display (string-append model-name "\n" ) port)
880 (debug-spew "We'll handle the file contents later . . .\n")
882 ) ;; close of inner cond
883 ) ;; end of inner let
884 ) ;; end of if (null? list-item
886 ) ;; end of outer let
890 ;;-----------------------------------------------------------
891 ;; write npn bipolar transistor
892 ;; This writes out a valid transistor refdes & then calls
893 ;; the function which writes the rest of the line.
894 ;;-----------------------------------------------------------
895 (define spice-sdb:write-npn-bipolar-transistor
896 (lambda (package port)
897 (debug-spew (string-append "Found npn bipolar transistor. Refdes = " package "\n"))
898 (let ((attrib-list (list "ic" "temp") ))
899 (spice-sdb:write-transistor-diode package "Q" "NPN" attrib-list port))
904 ;;-----------------------------------------------------------
905 ;; write pnp bipolar transistor
906 ;;-----------------------------------------------------------
907 (define spice-sdb:write-pnp-bipolar-transistor
908 (lambda (package port)
909 (debug-spew (string-append "Found pnp bipolar transistor. Refdes = " package "\n"))
910 (let ((attrib-list (list "ic" "temp") ))
911 (spice-sdb:write-transistor-diode package "Q" "PNP" attrib-list port))
916 ;;-----------------------------------------------------------
917 ;; write n-channel jfet transistor
918 ;;-----------------------------------------------------------
919 (define spice-sdb:write-nfet-transistor
920 (lambda (package port)
921 (debug-spew (string-append "Found n-channel JFET. Refdes = " package "\n"))
922 (let ((attrib-list (list "ic" "temp") ))
923 (spice-sdb:write-transistor-diode package "J" "NJF" attrib-list port))
928 ;;-----------------------------------------------------------
929 ;; write p-channel jfet transistor
930 ;;-----------------------------------------------------------
931 (define spice-sdb:write-pfet-transistor
932 (lambda (package port)
933 (debug-spew (string-append "Found p-channel JFET. Refdes = " package "\n"))
934 (let ((attrib-list (list "ic" "temp") ))
935 (spice-sdb:write-transistor-diode package "J" "PJF" attrib-list port))
940 ;;------------------------------------------------------
941 ;; write pmos transistor
942 ;;------------------------------------------------------
943 (define spice-sdb:write-pmos-transistor
944 (lambda (package port)
945 (debug-spew (string-append "Found PMOS transistor. Refdes = " package "\n"))
946 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
947 (spice-sdb:write-transistor-diode package "M" "PMOS" attrib-list port))
952 ;;------------------------------------------------------
953 ;; write nmos transistor
954 ;;------------------------------------------------------
955 (define spice-sdb:write-nmos-transistor
956 (lambda (package port)
957 (debug-spew (string-append "Found NMOS transistor. Refdes = " package "\n"))
958 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
959 (spice-sdb:write-transistor-diode package "M" "NMOS" attrib-list port))
964 ;;------------------------------------------------------
965 ;; write subckt pmos transistor
966 ;;------------------------------------------------------
967 (define spice-sdb:write-subckt-pmos-transistor
968 (lambda (package port)
969 (debug-spew (string-append "Found PMOS subcircuit transistor. Refdes = " package "\n"))
970 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
971 (spice-sdb:write-transistor-diode package "X" "PMOS" attrib-list port))
975 ;;------------------------------------------------------
976 ;; write subckt nmos transistor
977 ;;------------------------------------------------------
978 (define spice-sdb:write-subckt-nmos-transistor
979 (lambda (package port)
980 (debug-spew (string-append "Found NMOS subcircuit transistor. Refdes = " package "\n"))
981 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
982 (spice-sdb:write-transistor-diode package "X" "NMOS" attrib-list port))
985 ;;------------------------------------------------------------
986 ;; write mesfet transistor
987 ;;------------------------------------------------------------
988 ;; ************ Fix this!!!!!!!!!! **************
989 (define spice-sdb:write-mesfet-transistor
990 (lambda (package port)
991 (spice-sdb:write-transistor-diode package "Z" "MESFET" (list) port))) ;; XXXXXX Fix this!!!
994 ;;-----------------------------------------------------------
995 ;; write voltage controled switch
996 ;;-----------------------------------------------------------
997 (define spice-sdb:write-vc-switch
998 (lambda (package port)
999 (debug-spew (string-append "Found voltage controled switch. Refdes = " package "\n"))
1000 (let ((attrib-list (list " " ) ))
1001 (spice-sdb:write-transistor-diode package "S" "SW" attrib-list port))
1006 ;;--------------------------------------------------------------------
1008 ;;--------------------------------------------------------------------
1009 (define spice-sdb:write-resistor
1010 (lambda (package port)
1012 (debug-spew (string-append "Found resistor. Refdes = " package "\n"))
1014 ;; first write out refdes and attached nets
1015 (spice-sdb:write-component-no-value package port)
1017 ;; next write out mandatory resistor value if it exists.
1018 (let ((value (gnetlist:get-package-attribute package "value")))
1019 (if (not (string=? value "unknown"))
1020 (display (string-append value " " ) port))
1023 ;; next write our model name if it exists
1024 (let* ((model-name (gnetlist:get-package-attribute package "model-name")))
1025 (if (not (string=? model-name "unknown"))
1026 (display (string-append model-name " " ) port))
1029 ;; next create list of attributes which can be attached to a resistor.
1030 ;; I include non-standard "area" attrib here per popular demand.
1031 (let ((attrib-list (list "area" "l" "w" "temp")))
1032 ;; write the attributes (if any) separately
1033 (spice-sdb:write-list-of-attributes package attrib-list port)
1034 (display " " port)) ;; add additional space. . . .
1036 ;; finally output a new line
1043 ;;----------------------------------------------------------------------------
1045 ;;----------------------------------------------------------------------------
1046 (define spice-sdb:write-capacitor
1047 (lambda (package port)
1049 (debug-spew (string-append "Found capacitor. Refdes = " package "\n"))
1051 ;; first write out refdes and attached nets
1052 (spice-sdb:write-component-no-value package port)
1054 ;; next write capacitor value, if any. Note that if the
1055 ;; component value is not assigned nothing will be written out.
1056 (let ((value (gnetlist:get-package-attribute package "value")))
1057 (if (not (string=? value "unknown"))
1058 (display (string-append value " " ) port))
1061 ;; next write capacitor model name, if any. This is applicable to
1062 ;; semiconductor caps used in chip design.
1063 (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1064 (if (not (string=? model-name "unknown"))
1065 (display (string-append model-name " " ) port))
1068 ;; Next write out attribtes if they exist. Use
1069 ;; a list of attributes which can be attached to a capacitor.
1070 ;; I include non-standard "area" attrib here per request of Peter Kaiser.
1071 (let ((attrib-list (list "area" "l" "w" "ic")))
1072 (spice-sdb:write-list-of-attributes package attrib-list port)
1073 ;; write the off attribute separately
1074 (display " " port)) ;; add additional space. . . .
1081 ;;----------------------------------------------------------------------------
1083 ;;----------------------------------------------------------------------------
1084 (define spice-sdb:write-inductor
1085 (lambda (package port)
1087 (debug-spew (string-append "Found inductor. Refdes = " package "\n"))
1089 ;; first write out refdes and attached nets
1090 (spice-sdb:write-component-no-value package port)
1092 ;; ;; next write inductor model name, if any.
1093 ;; (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1094 ;; (if (not (string=? model "unknown"))
1095 ;; (display (string-append model-name " " ) port)
1098 ;; next write inductor value, if any. Note that if the
1099 ;; component value is not assigned, then it will write "unknown"
1100 (let ((value (gnetlist:get-package-attribute package "value")))
1101 (display value port)
1105 ;; create list of attributes which can be attached to a inductor
1106 (let ((attrib-list (list "l" "w" "ic")))
1107 (spice-sdb:write-list-of-attributes package attrib-list port)
1109 ;; write the off attribute separately
1110 (display " " port)) ;; add additional space. . . .
1117 ;;-------------------------------------------------------------------------
1118 ;; write independent voltage source
1119 ;; The behavior of the voltage source is held in the "value" attribute
1120 ;;-------------------------------------------------------------------------
1121 (define spice-sdb:write-independent-voltage-source
1122 (lambda (package port)
1123 (debug-spew (string-append "Found independent voltage source. Refdes = " package "\n"))
1125 ;; first write out refdes and attached nets
1126 (spice-sdb:write-component-no-value package port)
1128 ;; next write voltage value, if any. Note that if the
1129 ;; voltage value is not assigned, then it will write "unknown"
1130 (let ((value (gnetlist:get-package-attribute package "value")))
1131 (display value port)
1139 ;;-------------------------------------------------------------------------
1140 ;; write independent current source
1141 ;; The behavior of the current source is held in the "value" attribute
1142 ;;-------------------------------------------------------------------------
1143 (define spice-sdb:write-independent-current-source
1144 (lambda (package port)
1146 (debug-spew (string-append "Found independent current source. Refdes = " package "\n"))
1148 ;; first write out refdes and attached nets
1149 (spice-sdb:write-component-no-value package port)
1151 ;; next write current value, if any. Note that if the
1152 ;; current value is not assigned, then it will write "unknown"
1153 (let ((value (gnetlist:get-package-attribute package "value")))
1154 (display value port)
1162 ;;----------------------------------------------------------------------------
1163 ;; write Josephson junction in wrspice format. Paul Bunyk, Sep 2, 2005
1164 ;;----------------------------------------------------------------------------
1165 (define spice-sdb:write-josephson-junction
1166 (lambda (package port)
1168 (debug-spew (string-append "Found Josephson junction. Refdes = " package "\n"))
1170 ;; first write out refdes and attached nets
1171 (spice-sdb:write-component-no-value package port)
1173 ;; next, add a dummy node for JJ phase. Unlike in Xic netlister, give it
1174 ;; a reasonable name, not a number, e.g., refdes.
1175 (display (string-append package " ") port)
1177 ;; next write JJ model name, if any.
1178 (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1179 (if (not (string=? model-name "unknown"))
1180 (display (string-append model-name " " ) port))
1183 ;; Next write out attribtes if they exist. Use
1184 ;; a list of attributes which can be attached to a junction.
1185 (let ((attrib-list (list "area")))
1186 (spice-sdb:write-list-of-attributes package attrib-list port)
1187 ;; write the off attribute separately
1188 (display " " port)) ;; add additional space. . . .
1195 ;;----------------------------------------------------------------------------
1196 ;; write mutual inductance(actually K). Paul Bunyk, Sep 2, 2005
1197 ;;----------------------------------------------------------------------------
1198 (define spice-sdb:write-coupling-coefficient
1199 (lambda (package port)
1201 (debug-spew (string-append "Found mutual inductance. Refdes = " package "\n"))
1203 ;; first write out refdes and attached nets (none)
1204 (spice-sdb:write-component-no-value package port)
1206 ;; next two inductor names and value
1207 (let ((inductors (gnetlist:get-package-attribute package "inductors"))
1208 (value (gnetlist:get-package-attribute package "value")) )
1209 (if (not (string=? inductors "unknown"))
1210 (display (string-append inductors " " ) port))
1211 (if (not (string=? value "unknown"))
1212 (display (string-append value " " ) port))
1221 ;;----------------------------------------------------------------------------
1222 ; write a voltage probe
1223 ;;----------------------------------------------------------------------------
1224 (define (spice-sdb:write-probe package port)
1225 ;; fetch only one attr we care about, so far
1226 (let ((value (gnetlist:get-package-attribute package "value"))
1227 ) ;; end of local assignments
1229 (debug-spew (string-append "Found Probe item, refdes = " package "\n"))
1231 (if (string=? value "unknown")
1232 (set! value "TRAN"))
1234 (display (string-append "* Probe device " package " on nets ") port)
1235 (spice-sdb:write-net-names-on-component package port)
1237 (display (string-append ".print " value " +") port)
1238 (spice-sdb:write-net-names-on-component package port
1239 (string-join (map (lambda (x) "V(~a)") (gnetlist:get-pins package)) " " 'infix) ) ;; make format string
1242 ) ;; close of define
1245 ;;--------------------------------------------------------------------
1246 ;; Given a refdes and port, and optionaly a format string, this writes
1247 ;; out the nets attached to the component's pins. This is used to write
1248 ;; out non-slotted parts.
1249 ;;--------------------------------------------------------------------
1250 (define (spice-sdb:write-net-names-on-component refdes port . format)
1252 ;; get-net-name -- helper function. Called with pinseq, returns net name,
1253 ;; unless net name is "ERROR_INVALID_PIN" then it returns false.
1254 (define (get-net-name pin)
1255 (set! pin (number->string pin))
1257 ;; ------- Super debug stuff --------
1260 (debug-spew " In write-net-names-on-component. . . . \n")
1261 (debug-spew (string-append " pin-name = " pin "\n"))
1262 (debug-spew (string-append " pinnumber = " (gnetlist:get-attribute-by-pinseq refdes pin "pinnumber") "\n"))
1263 (debug-spew (string-append " pinseq = " (gnetlist:get-attribute-by-pinseq refdes pin "pinseq")))
1264 (if (not (string=? pin (gnetlist:get-attribute-by-pinseq refdes pin "pinseq")))
1265 (debug-spew " <== INCONSISTANT!\n")
1267 (debug-spew (string-append " netname = " (car (spice-sdb:get-net refdes (gnetlist:get-attribute-by-pinseq refdes pin "pinnumber"))) "\n"))
1268 )) ;; if #T for super debugging
1269 ;; -------------------------------------
1271 (set! pin (car (spice-sdb:get-net refdes (gnetlist:get-attribute-by-pinseq refdes pin "pinnumber"))))
1272 (if (string=? pin "ERROR_INVALID_PIN")
1274 (debug-spew (string-append "For " refdes ", found pin with no pinseq attribute. Ignoring. . . .\n"))
1277 ) ;; define get-net-name
1279 ;; First do local assignments
1280 (let ((netnames (filter-map get-net-name (range 1 (length (gnetlist:get-pins refdes)))))
1283 (display (string-join netnames " " 'suffix) port) ;; write out nets.
1284 (apply simple-format (cons port (cons (car format) netnames))) ) ;; write out nets with format string
1289 ;;-------------------------------------------------------------------
1290 ;; Write the refdes and the net names connected to pins on this component.
1291 ;; No return, and no component value is written, or extra attribs.
1292 ;; Those are handled later.
1293 ;;-------------------------------------------------------------------
1294 (define spice-sdb:write-component-no-value
1295 (lambda (package port)
1296 (display (string-append package " ") port) ;; write component refdes
1297 (spice-sdb:write-net-names-on-component package port)
1302 ;;-----------------------------------------------------------
1303 ;; Given a refdes, returns the device attribute "value" as string
1304 ;; Used when "value" is a mandatory attribute.
1305 ;; Returns "<no valid attribute . . .>" if not available.
1306 ;;-----------------------------------------------------------
1307 (define spice-sdb:component-value
1309 (let ((value (gnetlist:get-package-attribute package "value")))
1310 ;; (display (string-append "in get-package-attribute, value = " value "\n"))
1311 (if (not (string=? value "unknown"))
1313 "<No valid value attribute found>"))))
1316 ;;------------------------------------------------------------
1317 ;; Given a refdes, returns the device attribute "value" as string
1318 ;; Used when "value" is an optional attribute.
1319 ;; Returns "unknown" if not available.
1320 ;;------------------------------------------------------------
1321 (define spice-sdb:component-optional-value
1323 (let ((value (gnetlist:get-package-attribute package "value")))
1324 (if (not (string=? value "unknown"))
1325 (string-append value " ")
1329 ;;-----------------------------------------------------------
1330 ;; Given a refdes, returns the device attribute "model" as string
1331 ;;-----------------------------------------------------------
1332 (define spice-sdb:component-model
1334 (let ((model (gnetlist:get-package-attribute package "model")))
1335 (if (not (string=? model "unknown"))
1336 model spice-sdb:component-value))))
1339 ;;----------------------------------------------------------
1340 ;; Include SPICE statements from a SPICE directive block.
1341 ;;----------------------------------------------------------
1342 (define spice-sdb:write-directive
1343 (lambda (package port)
1344 ;; Collect variables used in creating spice code
1345 (let ((value (gnetlist:get-package-attribute package "value"))
1346 (file (gnetlist:get-package-attribute package "file"))
1347 ) ;; end of local assignments
1349 (debug-spew (string-append "Found SPICE directive box. Refdes = " package "\n"))
1353 ;; First look to see if there is a value.
1354 ((not (string=? value "unknown"))
1356 (display (string-append value "\n") port)
1357 (debug-spew (string-append "Appending value = \"" value "\" to output file.\n"))
1360 ;; since there is no value, look for file.
1361 ((not (string=? file "unknown"))
1363 (spice-sdb:insert-text-file file port) ;; Note that we don't wait until the end here. Is that OK?
1364 (debug-spew (string-append "Inserting contents of file = " file " into output file.\n"))
1369 ) ;; close of lambda
1370 ) ;; close of define
1373 ;;----------------------------------------------------------
1374 ;; Include a file using an .INCLUDE directive
1375 ;; Changed on 6.12.2005: to embedd the contents of the file,
1376 ;; you must call gnetlist with the -e flag set.
1377 ;;----------------------------------------------------------
1378 (define spice-sdb:write-include
1379 (lambda (package port)
1380 (let ((value (gnetlist:get-package-attribute package "value"))
1381 (file (gnetlist:get-package-attribute package "file"))
1382 ) ;; end of local assignments
1384 (debug-spew (string-append "Found SPICE include box. Refdes = " package "\n"))
1385 ;; (debug-spew (string-append " value = " value "\n"))
1386 ;; (debug-spew (string-append " file = " file "\n"))
1389 ;; First look to see if value attribute is used
1390 ((not (string=? value "unknown"))
1392 ;; (debug-spew "This include directive uses a value attribute.\n")
1393 (if (calling-flag? "embedd_mode" (gnetlist:get-calling-flags))
1395 (spice-sdb:insert-text-file value port) ;; -e found: invoke insert-text-file
1396 (debug-spew (string-append "embedding contents of " value " into netlist.\n")))
1398 (display (string-append ".INCLUDE " value "\n") port) ;; -e not found: just print out .INCLUDE card
1399 (debug-spew "placing .include directive string into netlist.\n"))
1402 ;; Now look to see if file is used
1403 ((not (string=? file "unknown"))
1405 ;; (debug-spew "This include directive uses a file attribute.\n")
1406 (if (calling-flag? "embedd_mode" (gnetlist:get-calling-flags))
1408 (spice-sdb:insert-text-file file port) ;; -e found: invoke insert-text-file
1409 (debug-spew (string-append "embedding contents of " value " into netlist.\n")))
1411 (display (string-append ".INCLUDE " file "\n") port) ;; -e not found: just print out .INCLUDE card
1412 (debug-spew "placing .include directive string into netlist.\n"))
1413 ) ;; end of if (calling-flag
1420 ;;----------------------------------------------------------
1421 ;; Include an option using an .OPTIONS directive
1422 ;;----------------------------------------------------------
1423 (define spice-sdb:write-options
1424 (lambda (package port)
1425 (debug-spew (string-append "Found .OPTIONS box. Refdes = " package "\n"))
1426 (display (string-append ".OPTIONS " (spice-sdb:component-value package) "\n") port)))
1429 ;;----------------------------------------------------------
1430 ;; Include a spice model (instantiated as a model box on the schematic)
1431 ;; Two types of model can be included:
1432 ;; 1. An embedded model, which is a one- or multi-line string held in the attribute "model".
1433 ;; In this case, the following attributes are mandatory:
1434 ;; -- model (i.e. list of parameter=value strings)
1437 ;; In this case, the function creates and formats the correct spice model line(s).
1438 ;; 2. A model held in a file whose name is held in the attribute "file"
1439 ;; In this case, the following attribute are mandatory:
1440 ;; -- file (i.e. list of parameter=value strings)
1441 ;; In this case, the function just opens the file and dumps the contents
1442 ;; into the netlist.
1443 ;;----------------------------------------------------------
1444 (define spice-sdb:write-model
1445 (lambda (package port)
1446 ;; Collect variables used in creating spice code
1447 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
1448 (model-file (gnetlist:get-package-attribute package "file"))
1449 (model (gnetlist:get-package-attribute package "model"))
1450 (type (gnetlist:get-package-attribute package "type"))
1451 ) ;; end of local assignments
1453 (debug-spew (string-append "Found .MODEL box. Refdes = " package "\n"))
1455 ;; Now, depending upon what combination of model, model-file, and model-name
1456 ;; exist (as described above) write out lines into spice netlist.
1458 ;; one model and model name exist
1459 ( (not (or (string=? model "unknown") (string=? model-name "unknown")))
1460 (debug-spew (string-append "found model and model-name for " package "\n"))
1461 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port) )
1463 ;; model file exists
1464 ( (not (or (string=? model-file "unknown") ))
1465 (debug-spew (string-append "found model-file for " package "\n"))
1466 ;; (spice-sdb:insert-text-file model-file port) ;; don't write it out -- it's handled after the second pass.
1471 ) ;; close of lambda
1472 ) ;; close of define
1475 ;;-------------------------------------------------------------------
1476 ;; This writes out the default component (i.e. the "device" attribute
1477 ;; was not recognized). This function does the following:
1479 ;; 1. Gets the refdes (package).
1480 ;; 2. Checks the refdes against a short list of possible values.
1481 ;; Depending upon the refdes, it does the following thing:
1482 ;; D? -- Invokes write-diode
1483 ;; Q? -- Invokes write-transistor-diode. (The "type" attribute is <unknown>
1484 ;; in this case so that the spice simulator will barf if the user
1485 ;; has been careless.)
1486 ;; U? -- Invokes write-ic. This provides the opportunity for a component
1487 ;; model to be instantiated.
1488 ;; X? -- Invokes write-ic. This provides the opportunity for a component
1489 ;; subcircuit to be instantiated.
1490 ;; V? -- Invokes write-independent-voltage-source
1491 ;; I? -- Invokes write-independent-current-source
1492 ;; Otherwise, it just outputs the refdes, the attached nets, and the
1493 ;; value of the "value" attribute.
1495 ;;-------------------------------------------------------------------
1496 (define spice-sdb:write-default-component
1497 (lambda (package file-info-list port)
1499 (let ((first-char (string (string-ref package 0)) )) ;; extract first char of refdes.
1501 ((string=? first-char "D") (spice-sdb:write-diode package port))
1502 ((string=? first-char "Q") (spice-sdb:write-transistor-diode package #f "<unknown>" (list) port))
1503 ((string=? first-char "M") (spice-sdb:write-transistor-diode package #f "<unknown>" (list) port))
1504 ((string=? first-char "U") (spice-sdb:write-ic package file-info-list port))
1505 ((string=? first-char "V") (spice-sdb:write-independent-voltage-source package port))
1506 ((string=? first-char "I") (spice-sdb:write-independent-current-source package port))
1507 ((string=? first-char "X") (spice-sdb:write-ic package file-info-list port))
1509 (display (string-append "Found unknown component. Refdes = " package "\n"))
1510 (spice-sdb:write-component-no-value package port)
1511 ;; write component value, if components have a label "value=#"
1512 ;; what if a component has no value label, currently unknown is written
1513 (display (spice-sdb:component-value package) port)
1522 ;;**********************************************************************************
1523 ;;*************** High-level functions for program control ***********************
1524 ;;**********************************************************************************
1526 ;;----------------------------------------------------------------------
1527 ;; write-netlist is passed a list of refdess (ls). It uses
1528 ;; each refdes to get the corresponding
1529 ;; "device" attribute. Depending upon the device, it then invokes one or another of the
1530 ;; spice line output fcns to output a line of the spice netlist.
1531 ;; I have enlarged the number of devices it recognizes -- SDB.
1532 ;; write the refdes, to the pin# connected net and component
1533 ;; value and optional extra attributes
1534 ;; check if the component is a special spice component.
1535 ;;----------------------------------------------------------------------
1536 (define spice-sdb:write-netlist
1537 (lambda (port file-info-list ls)
1538 (if (not (null? ls))
1539 (let* ((package (car ls)) ;; assign package
1540 (device (get-device package)) ;; assign device.
1541 ) ;; end of let* assignments
1543 ;; Super debug stuff -- outputs line describing device being processed.
1544 (debug-spew (string-append "--- checking package = " package "\n"))
1545 (debug-spew (string-append " device = " device "\n"))
1546 ;; done with debug stuff
1549 ( (string=? device "none")) ;; do nothing for graphical symbols.
1550 ( (string=? device "spice-subcircuit-LL")) ;; do nothing for subcircuit declaration.
1551 ( (string=? device "spice-IO")) ;; do nothing for SPICE IO pins.
1552 ( (string=? device "SPICE-ccvs")
1553 (spice-sdb:write-ccvs package port))
1554 ( (string=? device "SPICE-cccs")
1555 (spice-sdb:write-cccs package port))
1556 ( (string=? device "SPICE-vcvs")
1557 (spice-sdb:write-vcvs package port))
1558 ( (string=? device "SPICE-vccs")
1559 (spice-sdb:write-vccs package port))
1560 ( (string=? device "SPICE-nullor")
1561 (spice-sdb:write-nullor package port))
1562 ( (string=? device "DIODE")
1563 (spice-sdb:write-diode package port))
1564 ( (string=? device "PMOS_TRANSISTOR")
1565 (spice-sdb:write-pmos-transistor package port))
1566 ( (string=? device "NMOS_TRANSISTOR")
1567 (spice-sdb:write-nmos-transistor package port))
1568 ( (string=? device "PNP_TRANSISTOR")
1569 (spice-sdb:write-pnp-bipolar-transistor package port))
1570 ( (string=? device "SPICE-PNP")
1571 (spice-sdb:write-pnp-bipolar-transistor package port))
1572 ( (string=? device "NPN_TRANSISTOR")
1573 (spice-sdb:write-npn-bipolar-transistor package port))
1574 ( (string=? device "SPICE-NPN")
1575 (spice-sdb:write-npn-bipolar-transistor package port))
1576 ( (string=? device "PFET_TRANSISTOR")
1577 (spice-sdb:write-pfet-transistor package port))
1578 ( (string=? device "NFET_TRANSISTOR")
1579 (spice-sdb:write-nfet-transistor package port))
1580 ( (string=? device "MESFET_TRANSISTOR")
1581 (spice-sdb:write-mesfet-transistor package port))
1582 ( (string=? device "SPICE-VC-switch")
1583 (spice-sdb:write-vc-switch package port))
1584 ( (string=? device "RESISTOR")
1585 (spice-sdb:write-resistor package port))
1586 ( (string=? device "CAPACITOR")
1587 (spice-sdb:write-capacitor package port))
1588 ( (string=? device "POLARIZED_CAPACITOR")
1589 (spice-sdb:write-capacitor package port)) ;; change someday
1590 ( (string=? device "INDUCTOR")
1591 (spice-sdb:write-inductor package port))
1592 ( (string=? device "COIL") ;; Added to enable netlisting of coil-*.sym
1593 (spice-sdb:write-inductor package port))
1594 ( (string=? device "VOLTAGE_SOURCE")
1595 (spice-sdb:write-independent-voltage-source package port)) ;; change someday
1596 ( (string=? device "CURRENT_SOURCE")
1597 (spice-sdb:write-independent-current-source package port)) ;; change someday
1598 ( (string=? device "JOSEPHSON_JUNCTION")
1599 (spice-sdb:write-josephson-junction package port))
1600 ( (string=? device "K")
1601 (spice-sdb:write-coupling-coefficient package port))
1602 ( (string=? device "model")
1603 (spice-sdb:write-model package port))
1604 ( (string=? device "options")
1605 (spice-sdb:write-options package port))
1606 ( (string=? device "directive")
1607 (spice-sdb:write-directive package port))
1608 ( (string=? device "include")
1609 (spice-sdb:write-include package port))
1610 ( (string=? device "TESTPOINT")
1611 (spice-sdb:write-probe package port))
1612 ( (string=? device "SUBCKT_PMOS")
1613 (spice-sdb:write-subckt-pmos-transistor package port))
1614 ( (string=? device "SUBCKT_NMOS")
1615 (spice-sdb:write-subckt-nmos-transistor package port))
1617 (spice-sdb:write-default-component package file-info-list port))
1619 (spice-sdb:write-netlist port file-info-list (cdr ls))
1623 ;;----------------------------------------------------------------------
1624 ;; create-file-info-list: This takes as arugment the list of packages (refdesses).
1625 ;; It runs through the package list, and for each gets the attributes. If there is a
1626 ;; "FILE" attribute, it gets the file info & uses it to build the
1627 ;; file-info-list. When done, it returns the file-info-list.
1628 ;;----------------------------------------------------------------------
1629 (define spice-sdb:create-file-info-list
1630 (lambda (package-list file-info-list)
1631 (if (null? package-list)
1632 file-info-list ;; end of packages processed. Return file-info-list
1633 (let* ((package (car package-list)) ;; otherwise get next package (i.e. refdes)
1637 (model-file (string))
1638 ) ;; end of let* assignments
1640 (set! device (get-device package) )
1641 (set! model (gnetlist:get-package-attribute package "model-name") )
1642 (set! value (gnetlist:get-package-attribute package "value") )
1643 (set! model-file (gnetlist:get-package-attribute package "file") )
1645 ;; Sometimes get-package-attribute returns "?" instead of "unknown".
1646 ;; This is because some symbols use file=? as a place holder value to indicate that
1647 ;; it needs to be filled in. It is simular other place holders like footprint=none, and refdes=R?.
1648 ;; ? seems to be an ad hoc place holder for other attributes as well, like value for example.
1649 ;; FIXME: Of couse there could be many other places that this problem occurs. An effort should be
1650 ;; made to come up with a consistant way of representing place holders.
1652 (if (string-ci=? model-file "?")
1653 (set! model-file "unknown"))
1655 ;; Now run a series of checks to see if we should stick this file into the file-info-list
1656 ;; Check to see if "file" attribute is non-empty
1657 (if (not (string-ci=? model-file "unknown"))
1660 (string-append "found file attribute for " package ". File name = " model-file "\n")) ;; ******* Debug stuff
1662 ;; Now check to see if file is in file-info-list
1663 (if (not (spice-sdb:in-file-info-list? model-file file-info-list))
1665 ;; File is new. Open file, find out what type it is, and push info into file-info-list
1666 (let ((file-type (spice-sdb:get-file-type model-file))
1668 (debug-spew (string-append "File is new. New file type is " file-type " \n")) ;; DEBUG
1670 ;; Check to see if file-type is known.
1671 (if (not (string=? file-type "OTHER"))
1672 ;; file-type is OK. Return file-info-list with new triplet attached.
1674 (debug-spew (string-append "Inserting " model-file " into list of known model files.\n"))
1675 (set! file-info-list (append (list (list model model-file file-type)) file-info-list) )
1678 ;; Otherwise, file type is not a model type. Don't stick it in list. Print debug spew if desired.
1679 (debug-spew "File type is OTHER, and therefore will not be entered in known model file list.\n")
1680 ) ;; end if (not (string=?
1682 ) ;; end let ((file-type . . .
1684 ;; File is already in list. Print debug spew if desired.
1685 (debug-spew "File has already been seen and entered into known model file list.\n")
1686 ) ;; end if (spice-sdb:in-file-info-list . . .
1688 ) ;; end begin . . .
1689 ) ;; end if (not( string-ci=? model-file
1691 ;; having done checking and processing of this package, iterate to the next one.
1692 (spice-sdb:create-file-info-list (cdr package-list) file-info-list)
1695 ) ;; end if (null? package-list . . .
1700 ;; in-file-info-list? -- helper function. Returns #t if file is already in file-info-list, otherwise #f
1701 ;; assumes file-info-list of form: ((model1 file1 file-type1) (model2 file2 file-type2) . . . .)
1702 (define spice-sdb:in-file-info-list?
1703 (lambda (model-file file-info-list)
1704 (if (null? file-info-list)
1706 #f ;; return #f if file-info-list itself is empty.
1708 (let ((list-element (car file-info-list)) ) ;; otherwise process list-element
1709 (if (null? list-element)
1710 #f ;; item not found. Return #f. Note that we should never get here . . .
1711 (let ((list-file-name (cadr list-element)) )
1712 (if (string=? list-file-name model-file)
1713 #t ;; item found. Return #t
1714 (spice-sdb:in-file-info-list? model-file (cdr file-info-list)) ;; iterate . . .
1715 ) ;; end if (string=?
1716 ) ;; end of let . . .
1717 ) ;; end if (null? list-element . . .
1718 ) ;; end let* ((list-element . . .
1719 ) ;; end if (null? file-info-list . .
1720 )) ;; end define spice-sdb:in-file-info-list?
1723 ;;--------------------------------------------------------------
1724 ;; Write out spice netlist header
1725 ;;--------------------------------------------------------------
1726 (define spice-sdb:write-top-header
1728 (display "*********************************************************\n" port)
1729 (display "* Spice file generated by gnetlist *\n" port)
1730 (display "* spice-sdb version 4.28.2007 by SDB -- *\n" port)
1731 (display "* provides advanced spice netlisting capability. *\n" port)
1732 (display "* Documentation at http://www.brorson.com/gEDA/SPICE/ *\n" port)
1733 (display "*********************************************************\n" port)
1738 ;;--------------------------------------------------------------
1739 ;; Write out .SUBCKT netlist header
1740 ;;--------------------------------------------------------------
1741 (define spice-sdb:write-subcircuit-header
1743 (display "*******************************\n" port)
1744 (display "* Begin .SUBCKT model *\n" port)
1745 (display "* spice-sdb ver 4.28.2007 *\n" port)
1746 (display "*******************************\n" port)
1751 ;;---------------------------------------------------------------
1752 ;; Write the .END line
1753 ;;---------------------------------------------------------------
1754 (define spice-sdb:write-bottom-footer
1755 (lambda (salutation port)
1756 (display salutation port)
1760 ;;---------------------------------------------------------------
1761 ;; Spice netlist generation
1762 ;; This is the entry point.
1763 ;; Hacked on 3.31.2003 to enable writing out .SUBCKT models -- SDB.
1764 ;; Hacked again in Sept 2003 to enable more intelligent embedding of external
1765 ;; SPICE files into netlist -- SDB.
1766 ;; The algorithm is as follows:
1767 ;; 1. Figure out if there is a .SUBCKT block on the schematic,
1768 ;; or if it is just a normal schematic.
1770 ;; -- Write out subcircuit header (a comment identifying the netlister).
1771 ;; -- find all spice-IO pins. Get a list of the packages.
1772 ;; -- put them in order (ordered by package refdes)
1773 ;; -- get the list of nets attached to the spice-IO pins.
1774 ;; -- write out .SUBCKT line
1775 ;; If a normal schematic:
1776 ;; -- Write out top header (a comment identifying the netlister).
1777 ;; 2. Loop through all components, looking for components with a "file"
1778 ;; attribute. Every time a "file" attribute is found do this:
1779 ;; -- Open the file and find out what kind of file it is (.SUBCKT or .MODEL).
1780 ;; -- Determine if the file has previously been processed. If not: stick the
1781 ;; follwing info into the file-info list: (model-name file-name file-type).
1782 ;; Otherwise just continue.
1783 ;; 3. Loop through all components again, and write out a SPICE card for each.
1784 ;; 4. Afterwards, for each item in the file-info list, open the file, and
1785 ; write its contents into the netlist.
1786 ;; 5. If the schematic-type is .SUBCKT: write out .ENDS, Otherwise: write out .END
1787 ;; 6. Close up the SPICE netlist file and return.
1788 ;;---------------------------------------------------------------
1790 (lambda (output-filename)
1792 ;; First find out if this is a .SUBCKT lower level,
1793 ;; or if it is a regular schematic.
1795 (let* ((port (open-output-file output-filename))
1796 (schematic-type (spice-sdb:get-schematic-type packages))
1797 (model-name (spice-sdb:get-subcircuit-modelname schematic-type))
1798 (file-info-list (list))
1800 (display "Using SPICE backend by SDB -- Version of 4.28.2007\n")
1801 (display (string-append "schematic-type = " schematic-type "\n"))
1802 ;; (display (string-append "model-name = " model-name "\n"))
1804 (if (not (string=? schematic-type "normal schematic"))
1805 ;; we have found a .SUBCKT type schematic.
1806 (let* ((io-pin-packages (spice-sdb:get-spice-IO-pins packages (list) ))
1807 (io-pin-packages-ordered (spice-sdb:sort-spice-IO-pins io-pin-packages))
1808 (io-nets-list (spice-sdb:get-IO-nets io-pin-packages-ordered (list) ))
1810 (debug-spew "found .SUBCKT type schematic")
1811 ;; now write out .SUBCKT header and .SUBCKT line
1812 (spice-sdb:write-subcircuit-header port)
1813 (let ((io-nets-string (list-2-string io-nets-list)) )
1814 ;; (display (string-append "Found IO nets for subckt = " io-nets-string "\n")) ;; DEBUG stuff . . .
1815 ;; (write io-nets-list)
1817 (display (string-append schematic-type " " (list-2-string io-nets-list) "\n") port)
1821 ;; Otherwise it's a regular schematic. Write out command line followed by comments in file header.
1823 (debug-spew "found normal type schematic")
1824 (display (string-append "* " (gnetlist:get-command-line) "\n") port)
1825 (spice-sdb:write-top-header port)
1828 ) ;; end of if (not (string=? . . . .
1832 ;; Now loop through all devices and process all "FILE" attributes. Create
1834 ;; Thanks to Carlos Nieves Onega for his e-mail to
1835 ;; geda-dev which is the genesis of this section.
1837 (debug-spew "\nMake first pass through design and create list of all model files referenced.\n")
1838 (set! file-info-list (spice-sdb:create-file-info-list packages file-info-list))
1839 (debug-spew "Done creating file-info-list.\n")
1841 ;; extra debug spew -- comment out when done . . .
1842 ;; (display "file-info-list = \n")
1843 ;; (write file-info-list)
1850 ;; Moved this loop before the next one to get numparam to work with ngspice,
1851 ;; because numparam will at the subckt definition come before the main netlist.
1852 ;; Change suggested by Dominique Michel; implemented in code on 6.12.2005.
1854 ;; Next loop through all items in file-info-list in the SPICE netlist.
1855 ;; For each model-name, open up the corresponding file, and call handle-spice-file
1856 ;; to stick the corresponding stuff into the output SPICE file.
1858 (debug-spew "Now process the items in model file list -- stick appropriate references to models in output SPICE file.\n")
1859 (spice-sdb:loop-through-files file-info-list port)
1860 (debug-spew "Done processing items in model file list.\n")
1864 ;; Now write out netlist as before. But don't write file contents out.
1865 ;; **** Modified by kh to sort list of packages so Spice directives, etc. (A?) are output last,
1866 ;; **** and in increasing order.
1868 (debug-spew "Make second pass through design and write out a SPICE card for each component found.\n")
1869 (display (string-append "*============== Begin SPICE netlist of main design ============\n") port)
1870 (if (spice-sdb:sort-refdes? (gnetlist:get-calling-flags))
1871 (spice-sdb:write-netlist port file-info-list (sort packages spice-sdb:packsort)) ;; sort on refdes
1872 (spice-sdb:write-netlist port file-info-list packages) ;; don't sort.
1874 (debug-spew "Done writing SPICE cards . . .\n\n")
1878 ;; Now write out .END(S) of netlist, depending upon whether this schematic is a
1879 ;; "normal schematic" or a .SUBCKT.
1881 (if (not (string=? schematic-type "normal schematic"))
1883 (spice-sdb:write-bottom-footer (string-append ".ends " model-name) port)
1884 (display "*******************************\n" port)
1886 (spice-sdb:write-bottom-footer ".end" port)
1891 ;; Finally, close up and go home.
1893 (close-output-port port)
1894 (debug-spew "\nOutput file is written. We are done.\n")
1895 ) ;; (let* ((port . . . .
1900 ;; Custom get-uref function to append ".${SLOT}" where a component
1901 ;; has a "slot=${SLOT}" attribute attached.
1903 ;; NOTE: Original test for appending the ".<SLOT>" was this:
1904 ;; (let ((numslots (gnetlist:get-package-attribute package "numslots"))
1905 ;; (slot-count (length (gnetlist:get-unique-slots package)))
1906 ;; (if (or (string=? numslots "unknown") (string=? numslots "0"))
1910 (let ((real_uref (gnetlist:get-uref object)))
1911 (if (null? (get-attrib-value-by-attrib-name object "slot"))
1913 (string-append real_uref "."
1914 (car (get-attrib-value-by-attrib-name object "slot")))