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
91 ;;**********************************************************************************
93 ;; Organization of gnet-spice-sdb.scm file:
94 ;; -- Functions for program housekeeping, handling of calling flags, file manipulation.
95 ;; -- Functions for handling nets & devices and creating SPICE cards.
96 ;; -- High-level functions which control program flow. Note that the program entry
97 ;; point lives at the very bottom of this file.
99 ;; Unfortunately, no organization is present beneath this top level. . . .
101 ;;**********************************************************************************
104 ;;**********************************************************************************
105 ;;************ Program housekeeping, handling calling flags, etc. ****************
106 ;;**********************************************************************************
108 ;; The following is needed to make guile 1.8.x happy.
109 (use-modules (ice-9 rdelim))
111 ;;--------------------------------------------------------------------------------
112 ;; spice-sdb:loop-through-files -- loops through the model-file list, and for each file
113 ;; name discovered in the list, it processes the file by invoking handle-spice-file.
114 ;;--------------------------------------------------------------------------------
115 (define spice-sdb:loop-through-files
116 (lambda (file-info-list port)
117 (if (not (null? file-info-list))
118 (let* ((list-element (car file-info-list))
119 (model-name (car list-element))
120 (file-name (cadr list-element))
121 (file-type (caddr list-element))
123 (spice-sdb:handle-spice-file file-name port)
124 (spice-sdb:loop-through-files (cdr file-info-list) port)
129 ;;--------------------------------------------------------------------------------
130 ;; spice-sdb:get-file-info-list-item -- loops through the model-file list looking
131 ;; for triplet corresponding to model-name. If found, it returns the corresponding
132 ;; list. If not found, returns #f
133 ;;--------------------------------------------------------------------------------
134 (define spice-sdb:get-file-info-list-item
135 (lambda (model-name file-info-list)
136 (if (null? file-info-list)
137 '() ;; return #f upon empty list.
138 ;; #f replaced with '() by peter
139 (let* ((list-element (car file-info-list)) ;; else process list-item
140 (list-elt-model-name (car list-element))
141 (list-elt-file-name (cadr list-element))
142 (list-elt-file-type (caddr list-element))
144 (if (string=? list-elt-model-name model-name)
145 list-element ;; found model-name. Reutrn list-element.
146 (spice-sdb:get-file-info-list-item model-name (cdr file-info-list)) ;; otherwise, recurse.
153 ;;--------------------------------------------------------------------------
154 ;; handle-spice-file: This wraps insert-text-file.
155 ;; Calling form: (handle-spice-file file-name)
156 ;; It looks to see if the -I flag was set at the command line. If so,
157 ;; it just writes a .INCLUDE card with the file name. If not, it calls
158 ;; insert-text-file to stick the file's contents into the SPICE netlist.
159 ;;--------------------------------------------------------------------------
160 (define spice-sdb:handle-spice-file
161 (lambda (file-name port)
162 (debug-spew (string-append "Handling spice model file " file-name "\n"))
163 (if (calling-flag? "include_mode" (gnetlist:get-calling-flags))
164 (display (string-append ".INCLUDE " file-name "\n") port) ;; -I found: just print out .INCLUDE card
165 (spice-sdb:insert-text-file file-name port) ;; -I not found: invoke insert-text-file
166 ) ;; end of if (calling-flag
171 ;;--------------------------------------------------------------------------
172 ;; Given a filename, open the file, get the contents, and dump them
173 ;; into the spice file.
174 ;; Calling form is "(insert-text-file input-file output-file)"
175 ;; The function opens input-file, but assumes that output-file is
178 ;; This function is usually used to include spice models contained in
179 ;; files into the netlist. Note that it doesn't
180 ;; check the correctness of the spice code in the file -- you're on your own!
181 ;;---------------------------------------------------------------------------
182 (define spice-sdb:insert-text-file
183 (lambda (model-filename port)
184 (let ((model-file (open-input-file model-filename)) )
185 (display (string-append "*vvvvvvvv Included SPICE model from " model-filename " vvvvvvvv\n") port)
186 (let while ((model-line (read-line model-file)))
187 (if (not (eof-object? model-line))
189 (display (string-append model-line "\n") port)
190 ;; (display (string-append "-- model-line = " model-line "\n")) ;; super debug statement
191 (while (read-line model-file))
192 ) ;; end of inner begin
194 ) ;; end of inner let
195 (close-port model-file)
196 (display (string-append "*^^^^^^^^ End of included SPICE model from " model-filename " ^^^^^^^^\n") port)
197 (display (string-append "*\n") port)
198 ) ;; end of outer let
202 ;;----------------------------------------------------------
203 ;; Figure out if this schematic is a .SUBCKT lower level.
204 ;; This is determined if there is a spice-subcircuit-LL
205 ;; device instantiated somewhere on the schematic.
206 ;; If it is a .SUBCKT, return ".SUBCKT model-name"
207 ;;----------------------------------------------------------
208 (define spice-sdb:get-schematic-type
211 (let* ((package (car ls)) ;; assign package
212 (device (get-device package)) ;; assign device.
213 ) ;; end of let* assignments
215 ;; (display (string-append "in get-schematic-type, device = " device "\n"))
216 (if (string=? device "spice-subcircuit-LL") ;; look for subcircuit label
217 (string-append ".SUBCKT " (gnetlist:get-package-attribute package "model-name"))
218 (spice-sdb:get-schematic-type (cdr ls)) ;; otherwise just iterate to next package.
222 "normal schematic" ; return "normal schematic" if no spice-subcircuit-LL is found
227 ;;----------------------------------------------------------
228 ;; Extract the modelname from the .SUBCKT modelname line.
229 ;; Just grab the chars from char 8 to the end of the string.
230 ;;---------------------------------------------------------
231 (define spice-sdb:get-subcircuit-modelname
232 (lambda (schematic-type)
233 (substring schematic-type 8 (string-length schematic-type))
238 ;;-----------------------------------------------------------
239 ;; This iterates through the schematic and compiles a list of
240 ;; all spice-IO pins found. This is used when writing out
241 ;; a .SUBCKT lower level netlist.
242 ;;-----------------------------------------------------------
243 (define spice-sdb:get-spice-IO-pins
244 (lambda (ls spice-io-package-list)
247 spice-io-package-list ;; end iteration & return list if ls is empty.
249 (let* ((package (car ls)) ;; otherwise process package. . .
250 (device (get-device package))
252 (if (string=? device "spice-IO") ;; look for subcircuit label
254 ;; we have found a spice-IO pin.
255 (spice-sdb:get-spice-IO-pins (cdr ls) (cons package spice-io-package-list))
257 ;; no spice-IO pin found. Iterate . . . .
258 (spice-sdb:get-spice-IO-pins (cdr ls) spice-io-package-list)
260 ) ;; end of if string=?
267 ;;----------------------------------------------------------------
268 ;; This takes the list of io-pin-packages and sorts it in order of
270 ;; Repaired on 12.27.2005 to correctly sort pin numbers > 9.
271 ;;----------------------------------------------------------------
272 (define spice-sdb:sort-spice-IO-pins
273 (lambda (package-list)
274 ;; Yes, this isn't good Scheme form. Tough! Writing this out
275 ;; in a functional programming form would be totally confusing!
276 ;; Note that this fcn requires that
277 ;; each spice-IO pin have the same, single character prefix (i.e. 'P')
278 (let* ((char-prefixes (map car (map string->list package-list))) ;; Pull off first char (prefix)
279 (prefixes (map string char-prefixes)) ;; Make list of strings from prefixes
280 (split-numbers-list (map cdr (map string->list package-list))) ;; Pull off refdes numbers as list elements
281 (string-numbers-list (map list->string split-numbers-list)) ;; Recombine split up (multidigit) number strings
282 (numbers-list (map string->number string-numbers-list)) ;; Convert strings to numbers for sorting
283 (sorted-numbers-list (sort numbers-list <)) ;; Sort refdes numbers as numbers
284 (sorted-string-numbers-list (map number->string sorted-numbers-list)) ) ;; Create sorted list of refdes strings.
286 ;; (debug-spew "Packages found = \n")
287 ;; (debug-spew package-list)
288 ;; (debug-spew "\nPrefixes found = \n")
289 ;; (debug-spew prefixes)
290 ;; (debug-spew "\nNumbers found -- split-numbers-list\n")
291 ;; (debug-spew split-numbers-list)
292 ;; (debug-spew "\nNumbers found -- numbers-list\n")
293 ;; (debug-spew numbers-list)
294 ;; (debug-spew "\nSorted-numbers-list\n")
295 ;; (debug-spew sorted-numbers-list)
296 ;; (debug-spew "\nSorted-string-numbers-list\n")
297 ;; (debug-spew sorted-string-numbers-list)
299 (map-in-order string-append prefixes sorted-string-numbers-list) ;; Laminate prefixes back onto refdes numbers & return.
307 ;;----------------------------------------------------------------
308 ;; Given a list of spice-IO packages (refdeses), this function returns the list
309 ;; of nets attached to the IOs.
310 ;;----------------------------------------------------------------
311 (define spice-sdb:get-IO-nets
312 (lambda (package-list net-list)
313 (if (null? package-list)
315 net-list ;; end iteration & return net-list if ls is empty.
317 (let* ((package (car package-list)) ;; otherwise process package. . .
318 (net (car (gnetlist:get-nets package "1"))) ;; get the net attached to pin 1
321 (spice-sdb:get-IO-nets (cdr package-list) (cons net net-list))
328 ;;----------------------------------------------------------
329 ;; This takes a list and turns it into a string.
330 ;; The difference between this and list->string is that
331 ;; this fun can handle lists made up of multi-char strings.
332 ;;----------------------------------------------------------
333 (define list-2-string
339 (if (null? local-list)
340 st ;; end iteration & return string if list is empty.
341 (begin ;; otherwise turn next element of list into string. . .
342 (set! st (string-append (car local-list) " " st)) ;; stuff next element onto st
343 (while st (cdr local-list)) ;; iterate with remainder of ls
350 ;;----------------------------------------------------------
351 ;; This returns #t if the string is composed only of
352 ;; whitespace. It works by turning the string into
353 ;; a list, and then checking to see if it is the empty
354 ;; list. If so, it returns #t.
355 ;;----------------------------------------------------------
356 (define empty-string?
358 (null? (string->list string))
362 ;;----------------------------------------------------------
363 ;; Given a filename, open the file, get the first line,
364 ;; and see if it is a .MODEL or .SUBCKT file.
365 ;; Returns either ".MODEL" or ".SUBCKT" or "OTHER"
366 ;; Calling form is "(spice-sdb:get-file-type input-file)"
367 ;; The function opens input-file, and closes it when it is done.
368 ;;----------------------------------------------------------
369 (define spice-sdb:get-file-type
370 (lambda (model-filename)
372 (let ((model-file (open-input-file model-filename)) )
373 (let while ((file-line (read-line model-file)) )
376 ((eof-object? file-line) ;; Arrived at end of line without finding .MODEL or .SUBCKT. Return "OTHER"
379 ((empty-string? file-line)
380 (while (read-line model-file)) ) ;; Found empty line. Iterate before doing anything else.
382 ((string=? (string (string-ref file-line 0)) "*")
383 (while (read-line model-file)) ) ;; Found *comment. Iterate.
385 ((string=? (string (string-ref file-line 0)) ".")
387 (debug-spew "In get-file-type, first-char = .\n") ;; DEBUG stuff
390 ((string-ci=? (safe-string-head file-line 7) ".subckt") ;; found .subckt as first line.
393 ((string-ci=? (safe-string-head file-line 6) ".model") ;; found .model as first line.
396 (else "OTHER") ;; first . spice card is neither .model nor .subckt
404 ;; (display "In get-file-type, first-char = <other>\n")
405 (while (read-line model-file))
411 ) ;; end of inner lets
412 ) ;; end of outer let
417 ;;-------------------------------------------------------------------
418 ;; write all listed and available attributes in the form of <variable>=<value>
419 ;;-------------------------------------------------------------------
420 (define spice-sdb:write-list-of-attributes
421 (lambda (package attrib-list port)
422 (if (not (null? attrib-list))
424 ; Is it possible to make no differentiation between upper and lower case?
425 ; That relieves you of mixed case forms e.g. As, AS, as..., they are the
426 ; same attributes, spice3f5 is case insensitive. And other spice versions?
427 (if (not (string=? (gnetlist:get-package-attribute package (car attrib-list)) "unknown"))
428 (display (string-append " " (car attrib-list) "="
429 (gnetlist:get-package-attribute package (car attrib-list))) port))
430 (spice-sdb:write-list-of-attributes package (cdr attrib-list) port)))))
433 ;;---------------------------------------------------------------
434 ;; write prefix if first char of refdes is improper,
435 ;; eg. if MOSFET is named T1 then becomes MT1 in SPICE
436 ;;---------------------------------------------------------------
437 (define spice-sdb:write-prefix
438 (lambda (package prefix port)
439 (let ((different-prefix (not (string=? (substring package 0 1) prefix)) )
440 (nomunge (calling-flag? "nomunge_mode" (gnetlist:get-calling-flags)) )
442 (debug-spew (string-append "Checking prefix. Package prefix =" (substring package 0 1) "\n"))
443 (debug-spew (string-append " correct prefix =" prefix "\n"))
444 (debug-spew " nomunge mode = ")
446 (debug-spew (string-append "\n different-prefix="))
447 (debug-spew different-prefix)
449 (if (and different-prefix (not nomunge))
450 (display prefix port) )
456 ;;---------------------------------------------------------------
457 ;; spice-sdb:packsort
458 ;; Sort procedure to order refdes's alphabetically but
459 ;; keep A? packages at the end of list so SPICE simulation
460 ;; directives operate correctly.
461 ;; This fcn written by Ken Healy to enable SPICE netlisting for
462 ;; Gnucap, which wants A refdes cards (i.e. SPICE directives)
463 ;; to appear last in the SPICE netlist. Slightly modified
464 ;; and incorporated into main spice-sdb release by SDB on 9.1.2003.
465 ;; To output the netlist in sorted order, use the -s switch
466 ;; when invoking gnetlist from the command line. Example:
467 ;; gnetlist -s -g spice-sdb -o output.spice Schematic.sch
468 ;; The default behavior (i.e. if -s is not specified) is to do
470 ;;---------------------------------------------------------------
471 (define spice-sdb:packsort
473 (let ((xdes (string-ref x 0))
474 (ydes (string-ref y 0))
475 (xnum (string-tail x 1))
476 (ynum (string-tail y 1))
479 (if (char-ci=? xdes ydes)
480 (if (string-ci<? xnum ynum) #t #f)
481 (if (char-ci=? xdes #\A) #f
482 (if (char-ci=? ydes #\A) #t
483 (if (char-ci<? xdes ydes) #t #f)))))))
485 (define (string-tail string start)
486 (substring string start (string-length string)))
489 ;;---------------------------------------------------------------
490 ;; spice-sdb:sort_refdes?
491 ;; Returns #t or #f depending upon if -s was discovered in
492 ;; the calling flags given to gnetlist. Used in conjunction with
493 ;; spice-sdb:packsort.
494 ;; Calling form: (spice-sdb:sort-refdes? (gnetlist:get-calling-flags))
496 ;;---------------------------------------------------------------
497 ;; Note: I should re-write this to use calling-flag? . . . .
498 (define spice-sdb:sort-refdes?
499 (lambda (calling-flag-list)
501 (if (null? calling-flag-list)
502 '#f ;; return #f if null list -- sort_mode not found.
503 (let* ((calling-pair (car calling-flag-list)) ;; otherwise look for sort_mode in remainder of list.
504 (calling-flag (car calling-pair))
505 (flag-value (cadr calling-pair)) )
507 (if (string=? calling-flag "sort_mode")
508 flag-value ;; return flag-value if sort_mode found
509 (spice-sdb:sort-refdes? (cdr calling-flag-list)) ;; otherwise recurse until sort_mode is found
518 ;;**********************************************************************************
519 ;;*************** Dealing with nets, devices, & SPICE cards. *******************
520 ;;**********************************************************************************
522 ;;-----------------------------------------------------------
523 ;; gnet-spice replacement of gnetlist:get-nets, a net labeled "GND" becomes 0
524 ;;-----------------------------------------------------------
525 (define spice-sdb:get-net
526 (lambda (refdes pin-name)
527 (let ((net-name (gnetlist:get-nets refdes pin-name)))
528 (cond ((string=? (car net-name) "GND") (cons "0" #t))
529 (else (cons (car net-name) #t)))
534 ;;---------------------------------------------------------------------
535 ;; write netnames connected to pin-a and pin-b
536 ;; (currently used by the controlled sources (e, g, f and h)
537 ;;---------------------------------------------------------------------
538 (define spice-sdb:write-two-pin-names
539 (lambda (package pin-a pin-b port)
540 (display (string-append
541 (car (spice-sdb:get-net package (gnetlist:get-attribute-by-pinseq package pin-a "pinnumber"))) " ") port)
542 (display (string-append
543 (car (spice-sdb:get-net package (gnetlist:get-attribute-by-pinseq package pin-b "pinnumber"))) " ") port)))
546 ;;----------------------------------------------------------------
547 ;; write a current controlled voltage source and implement the necessary
548 ;; current measuring voltage source
549 ;;----------------------------------------------------------------
550 (define spice-sdb:write-ccvs
551 (lambda (package port)
553 (display "* begin ccvs expansion, h<name>\n" port)
554 ;; implement the controlled current source
555 ;; the user should create the refdes label begining with a h
556 (display (string-append package " ") port)
557 (spice-sdb:write-two-pin-names package "1" "2" port)
558 (display (string-append "Vsense_" package " " (spice-sdb:component-value package) "\n" ) port)
559 ;; implement the current measuring voltage source
560 (display (string-append "Vsense_" package " ") port)
561 (spice-sdb:write-two-pin-names package "3" "4" port)
562 (display "dc 0\n" port)
563 ;; now it is possible to leave the output voltage source unconnected
564 ;; i.e. spice won't complain about unconnected nodes
565 (display (string-append "IOut_" package " ") port)
566 (spice-sdb:write-two-pin-names package "1" "2" port)
567 (display "dc 0\n" port)
568 (display "* end ccvs expansion\n" port))))
571 ;;-----------------------------------------------------------------------
572 ;; write a current controlled current source and implement the necessary
573 ;; current measuring voltage source
574 ;;-----------------------------------------------------------------------
575 (define spice-sdb:write-cccs
576 (lambda (package port)
578 (display "* begin cccs expansion, f<name>\n" port)
579 ;; implement the controlled current source
580 ;; the user should create the refdes label begining with a f
581 (display (string-append package " ") port)
582 (spice-sdb:write-two-pin-names package "1" "2" port)
583 (display (string-append "Vsense_" package " " (gnetlist:get-package-attribute package "value") "\n" ) port)
584 ;; implement the current measuring voltage source
585 (display (string-append "Vsense_" package " ") port)
586 (spice-sdb:write-two-pin-names package "3" "4" port)
587 (display "dc 0\n" port)
588 (display "* end cccs expansion\n" port))))
591 ;;-------------------------------------------------------------------------
592 ;; write a voltage controlled current source and implement the necessary
593 ;; voltage measuring current source
594 ;;-------------------------------------------------------------------------
595 (define spice-sdb:write-vccs
596 (lambda (package port)
598 (display "* begin vccs expansion, g<name>\n" port)
599 ;; implement the controlled current source
600 ;; the user should create a refdes label beginning with a g
601 (display (string-append package " ") port)
602 (spice-sdb:write-net-names-on-component package (length (gnetlist:get-pins package)) port)
603 (display (string-append (spice-sdb:component-value package) "\n") port)
604 ;; implement the voltage measuring current source
605 ;; imagine yourself copying the voltage of a voltage source with an internal
606 ;; impedance, spice starts complaining about unconnected nets if this current
607 ;; source is not here.
608 (display (string-append "IMeasure_" package " ") port)
609 (spice-sdb:write-two-pin-names package "3" "4" port)
610 (display "dc 0\n" port)
611 (display "* end vccs expansion\n" port))))
614 ;;------------------------------------------------------------------------
615 ;; write a voltage controlled voltage source and implement the necessary
616 ;; voltage measuring current source
617 ;;------------------------------------------------------------------------
618 (define spice-sdb:write-vcvs
619 (lambda (package port)
621 (display "* begin vcvs expansion, e<name>\n" port)
622 ;; implement the controlled voltage source
623 ;; the user should create a refdes label beginning with an e
624 (display (string-append package " ") port)
625 (spice-sdb:write-net-names-on-component package (length (gnetlist:get-pins package)) port)
626 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
627 ;; implement the voltage measuring current source
628 ;; imagine yourself copying the voltage of a voltage source with an internal
629 ;; impedance, spice starts complaining about unconnected nets if this current
630 ;; source is not here.
631 (display (string-append "Isense_" package " ") port)
632 (spice-sdb:write-two-pin-names package "3" "4" port)
633 (display "dc 0\n" port)
634 ;; with an output current source it is possible to leave the output voltage source
635 ;; unconnected i.e. spice won't complain about unconnected nodes
636 (display (string-append "IOut_" package " ") port)
637 (spice-sdb:write-two-pin-names package "1" "2" port)
638 (display "dc 0\n" port)
639 (display "* end vcvs expansion\n" port))))
642 ;;--------------------------------------------------------------------------
643 ;; Create a nullor, make sure it consists of a voltage controlled source
644 ;;--------------------------------------------------------------------------
645 (define spice-sdb:write-nullor
646 (lambda (package port)
648 (display "* begin nullor expansion, e<name>\n" port)
649 ;; implement the controlled voltage source
650 (display (string-append "E-" package " ") port)
651 (spice-sdb:write-net-names-on-component package (length (gnetlist:get-pins package)) port)
652 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
653 ;; implement the voltage measuring current source
654 ;; imagine yourself copying the voltage of a voltage source with an internal
655 ;; impedance, spice starts complaining about unconnected nets if this current
656 ;; source is not here.
657 (display (string-append "IMeasure_" package " ") port)
658 (spice-sdb:write-two-pin-names package "3" "4" port)
659 (display "dc 0\n" port)
660 ;; with an output current source it is possible to leave the output voltage source
661 ;; unconnected i.e. spice won't complain about unconnected nodes
662 (display (string-append "IOut_" package " ") port)
663 (spice-sdb:write-two-pin-names package "1" "2" port)
664 (display "dc 0\n" port)
665 (display "* end of nullor expansion\n" port))))
668 ;;----------------------------------------------------------------
670 ;; Write-transistor-diode: writes out component followed by
671 ;; model or model file associated
672 ;; with the component.
673 ;; This function does the following:
674 ;; 1. Writes out the correct refdes prefix (if specified and necessary).
675 ;; 2. Writes out the refdes and nets
676 ;; 3. Looks for "model-name" attribute. Writes it out if it exists.
677 ;; 4. If there is no "model-name" attribute, it writes out the "value"
678 ;; attribute. If there is no "value" attribute, it writes out "unknown"
679 ;; and returns, causing the spice simulator to puke when the netlist
680 ;; is run. This is important
681 ;; 'cause the spice simulator needs to have some indication of what
682 ;; model to look for.
683 ;; 5. Outputs optional attributes attached to device, if any. Feature
684 ;; added by SDB on 12.25.2003.
685 ;; 6. Outputs a new line
686 ;; 7. Looks for a the "model" attribute. If it exists, it it writes out
687 ;; a .MODEL line like this: .MODEL model-name type (model)
689 ;;----------------------------------------------------------------
690 (define spice-sdb:write-transistor-diode
691 (lambda (package prefix type attrib-list port)
693 ;; First do local assignments
694 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
695 (model (gnetlist:get-package-attribute package "model"))
696 (value (gnetlist:get-package-attribute package "value"))
697 (area (gnetlist:get-package-attribute package "area"))
698 (off (gnetlist:get-package-attribute package "off"))
699 (model-file (gnetlist:get-package-attribute package "file"))
700 ) ;; end of local assignments
702 ;; Write out the refdes prefix, if specified and necessary.
704 (spice-sdb:write-prefix package prefix port)
707 ;; Next we write out the refdes and nets.
708 (spice-sdb:write-component-no-value package port)
710 ;; next look for "model-name" attribute. Write it out if it exists.
711 ;; otherwise look for "device" attribute.
712 (if (not (string=? model-name "unknown"))
713 (display (string-append model-name " " ) port) ;; display model-name if known
714 (display (string-append value " ") port)) ;; otherwise display device
716 ;; Next write out attribtes if they exist
717 ;; First attribute is area. It is written as a simple string
718 (if (not (string=? area "unknown"))
719 (display (string-append area " ") port))
721 ;; Next attribute is off. It is written as a simple string
722 (if (not (string=? off "unknown"))
723 (display (string-append off " ") port))
725 ;; Write out remaining attributes
726 (spice-sdb:write-list-of-attributes package attrib-list port)
728 ;; Now write out newline in preparation for writing out model.
731 ;; Now write out any model which is pointed to by the part.
734 ;; one line model and model name exist
735 ( (not (or (string=? model "unknown") (string=? model-name "unknown")))
736 (debug-spew (string-append "found model and model-name for " package "\n"))
737 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port) )
739 ;; one line model and component value exist
740 ( (not (or (string=? model "unknown") (string=? value "unknown")))
741 (debug-spew (string-append "found model and value for " package "\n"))
742 (display (string-append ".MODEL " model-name " " type " (" value ")\n") port) )
744 ;; model file and model name exist
745 ( (not (or (string=? model-file "unknown") (string=? model-name "unknown")))
746 (debug-spew (string-append "found file and model-name for " package "\n"))
747 (debug-spew "I'll deal with the file later . . .\n")
750 ;; model file and component value exist
751 ( (not (or (string=? model-file "unknown") (string=? value "unknown")))
752 (debug-spew (string-append "found file and value for " package "\n"))
753 (debug-spew "I'll deal with the file later . . .\n")
762 ;;----------------------------------------------------------------
764 ;; This writes out a valid diode refdes & then calls
765 ;; the function which writes the rest of the line.
766 ;;----------------------------------------------------------------
767 (define spice-sdb:write-diode
768 (lambda (package port)
769 (debug-spew (string-append "Found diode. Refdes = " package "\n"))
770 (let ((attrib-list (list "ic" "temp") ))
771 (spice-sdb:write-transistor-diode package "D" "D" attrib-list port))
776 ;;----------------------------------------------------------------
777 ;; spice-sdb:write-ic
778 ;; This writes out a valid ic line.
779 ;; The algorithm is as follows:
780 ;; 1. Figure out what type of model goes with this part from
781 ;; file-info-list. If it isn't listed, look for a MODEL attribute.
782 ;; If MODEL attribute is attached, write out SPICE card, and then
783 ;; write out .MODEL on next line.
784 ;; If no MODEL attribute is attached, just write out what litte
785 ;; we know. Then return
786 ;; 2. If the model-name is in the file-info-list, get the associated
787 ;; file-type. Compare it against the component's refdes. If model-type
788 ;; == .SUBCKT and refdes doesn't begin with X, prepend an X to the refdes.
789 ;; 3. Print out the rest of the line.
791 ;;----------------------------------------------------------------
792 (define spice-sdb:write-ic
793 (lambda (package file-info-list port)
795 (debug-spew (string-append "Found ic. Refdes = " package "\n"))
797 ;; First do local assignments
798 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
799 (model (gnetlist:get-package-attribute package "model"))
800 (value (gnetlist:get-package-attribute package "value"))
801 (model-file (gnetlist:get-package-attribute package "file"))
803 ) ;; end of local assignments
805 ;; First, if model-name is empty, we use value attribute instead.
806 ;; We do this by sticking the contents of "value" into "model-name".
807 (if (string=? model-name "unknown")
808 (set! model-name value))
810 ;; Now get item from file-info-list using model-name as key
811 (set! list-item (spice-sdb:get-file-info-list-item model-name file-info-list))
813 ;; check to see if list-item is null.
814 (if (null? list-item)
816 ;; list-item is null. Evidently, we didn't discover any files holding this model.
817 ;; Instead we look for model attribute
818 (if (not (string=? model "unknown"))
819 (begin ;; model attribute exists -- write out card and model.
820 (debug-spew "Model info not found in model file list, but model attribute exists. Write out spice card and .model line..\n")
821 (spice-sdb:write-component-no-value package port)
822 (display (string-append model-name "\n" ) port)
823 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port)
825 (begin ;; no model attribute either. Just write out card.
826 (debug-spew "Model info not found in model file list. No model attribute either. Just write what we know.\n")
827 (spice-sdb:write-component-no-value package port)
828 (display (string-append model-name "\n" ) port)
830 ) ;; end if (not (string=? . . . .
832 ;; list-item is not null. Therefore we process line depending upon contents of list-item
833 (let ((file-type (caddr list-item)) )
835 ;; ---- file holds a model ----
836 ((string=? file-type ".MODEL")
838 (debug-spew (string-append "Found .MODEL with model-file and model-name for " package "\n"))
839 (spice-sdb:write-prefix package "U" port) ;; this appends an "U" to the refdes since we have a .model
840 (spice-sdb:write-component-no-value package port)
841 (display (string-append model-name "\n" ) port)
842 (debug-spew "We'll handle the file contents later . . .\n")
845 ;; ---- file holds a subcircuit ----
846 ((string=? file-type ".SUBCKT")
848 (debug-spew (string-append "Found .SUBCKT with model-file and model-name for " package "\n"))
849 (spice-sdb:write-prefix package "X" port) ;; this appends an "X" to the refdes since we have a .subckt
850 (spice-sdb:write-component-no-value package port)
851 (display (string-append model-name "\n" ) port)
852 (debug-spew "We'll handle the file contents later . . .\n")
854 ) ;; close of inner cond
855 ) ;; end of inner let
856 ) ;; end of if (null? list-item
858 ) ;; end of outer let
863 ;;----------------------------------------------------------------
864 ;; spice-sdb:write-subcircuit
865 ;; This writes out a valid subcircuit line.
866 ;; The algorithm is as follows:
867 ;; 1. Figure out what type of model goes with this part from
868 ;; file-info-list. If it isn't listed, look for a MODEL attribute.
869 ;; If MODEL attribute is attached, write out SPICE card, and then
870 ;; write out .MODEL on next line.
871 ;; If no MODEL attribute is attached, just write out what little
872 ;; we know. Then return.
873 ;; 2. If the model-name is in the file-info-list, get the associated
874 ;; file-type. Compare it against the component's refdes. If model-type
875 ;; == .MODEL and refdes doesn't begin with U, prepend an U to the refdes.
876 ;; 3. Print out the rest of the line.
878 ;; Note: This is basically a clone of write-ic. I can probably just
879 ;; eliminate this fcn and call write-ic for all U or X refdeses.
880 ;; Maybe on the next revision?
881 ;;----------------------------------------------------------------
882 (define spice-sdb:write-subcircuit
883 (lambda (package file-info-list port)
885 (debug-spew (string-append "Found subcircuit. Refdes = " package "\n"))
887 ;; First do local assignments
888 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
889 (model (gnetlist:get-package-attribute package "model"))
890 (value (gnetlist:get-package-attribute package "value"))
891 (model-file (gnetlist:get-package-attribute package "file"))
893 ) ;; end of local assignments
895 ;; First, if model-name is empty, we use value attribute instead.
896 ;; We do this by sticking the contents of "value" into "model-name".
897 (if (string=? model-name "unknown")
898 (set! model-name value))
900 ;; Now get item from file-info-list using model-name as key
901 (set! list-item (spice-sdb:get-file-info-list-item model-name file-info-list))
903 ;; check to see if list-item is null.
904 (if (null? list-item)
906 ;; list-item is null. Evidently, we didn't discover any files holding this model.
907 ;; Instead we look for model attribute
908 (if (not (string=? model "unknown"))
909 (begin ;; model attribute exists -- write out card and model.
910 (debug-spew "Model info not found in model file list, but model attribute exists. Write out spice card and .model line..\n")
911 (spice-sdb:write-component-no-value package port)
912 (display (string-append model-name "\n" ) port)
913 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port)
915 (begin ;; no model attribute either. Just write out card.
916 (debug-spew "Model info not found in model file list. No model attribute either. Just write what we know.\n")
917 (spice-sdb:write-component-no-value package port)
918 (display (string-append model-name "\n" ) port)
920 ) ;; end if (not (string=? . . . .
922 ;; list-item is not null. Therefore we process line depending upon contents of list-item
923 (let ((file-type (caddr list-item)) )
925 ;; ---- file holds a model ----
926 ((string=? file-type ".MODEL")
928 (debug-spew (string-append "Found .MODEL with model-file and model-name for " package "\n"))
929 (spice-sdb:write-prefix package "U" port) ;; this prepends an "U" to the refdes if needed
930 (spice-sdb:write-component-no-value package port)
931 (display (string-append model-name "\n" ) port)
932 (debug-spew "We'll handle the file contents later . . .\n")
935 ;; ---- file holds a subcircuit ----
936 ((string=? file-type ".SUBCKT")
938 (debug-spew (string-append "Found .SUBCKT with model-file and model-name for " package "\n"))
939 (spice-sdb:write-prefix package "X" port) ;; this appends an "X" to the refdes if needed
940 (spice-sdb:write-component-no-value package port)
941 (display (string-append model-name "\n" ) port)
942 (debug-spew "We'll handle the file contents later . . .\n")
944 ) ;; close of inner cond
945 ) ;; end of inner let
946 ) ;; end of if (null? list-item
948 ) ;; end of outer let
955 ;;-----------------------------------------------------------
956 ;; write npn bipolar transistor
957 ;; This writes out a valid transistor refdes & then calls
958 ;; the function which writes the rest of the line.
959 ;;-----------------------------------------------------------
960 (define spice-sdb:write-npn-bipolar-transistor
961 (lambda (package port)
962 (debug-spew (string-append "Found npn bipolar transistor. Refdes = " package "\n"))
963 (let ((attrib-list (list "ic" "temp") ))
964 (spice-sdb:write-transistor-diode package "Q" "NPN" attrib-list port))
969 ;;-----------------------------------------------------------
970 ;; write pnp bipolar transistor
971 ;;-----------------------------------------------------------
972 (define spice-sdb:write-pnp-bipolar-transistor
973 (lambda (package port)
974 (debug-spew (string-append "Found pnp bipolar transistor. Refdes = " package "\n"))
975 (let ((attrib-list (list "ic" "temp") ))
976 (spice-sdb:write-transistor-diode package "Q" "PNP" attrib-list port))
981 ;;-----------------------------------------------------------
982 ;; write n-channel jfet transistor
983 ;;-----------------------------------------------------------
984 (define spice-sdb:write-nfet-transistor
985 (lambda (package port)
986 (debug-spew (string-append "Found n-channel JFET. Refdes = " package "\n"))
987 (let ((attrib-list (list "ic" "temp") ))
988 (spice-sdb:write-transistor-diode package "J" "NJF" attrib-list port))
992 ;;-----------------------------------------------------------
993 ;; write p-channel jfet transistor
994 ;;-----------------------------------------------------------
995 (define spice-sdb:write-pfet-transistor
996 (lambda (package port)
997 (debug-spew (string-append "Found p-channel JFET. Refdes = " package "\n"))
998 (let ((attrib-list (list "ic" "temp") ))
999 (spice-sdb:write-transistor-diode package "J" "PJF" attrib-list port))
1004 ;;------------------------------------------------------
1005 ;; write pmos transistor
1006 ;;------------------------------------------------------
1007 (define spice-sdb:write-pmos-transistor
1008 (lambda (package port)
1009 (debug-spew (string-append "Found PMOS transistor. Refdes = " package "\n"))
1010 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
1011 (spice-sdb:write-transistor-diode package "M" "PMOS" attrib-list port))
1015 ;;------------------------------------------------------
1016 ;; write nmos transistor
1017 ;;------------------------------------------------------
1018 (define spice-sdb:write-nmos-transistor
1019 (lambda (package port)
1020 (debug-spew (string-append "Found NMOS transistor. Refdes = " package "\n"))
1021 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic" "m")))
1022 (spice-sdb:write-transistor-diode package "M" "NMOS" attrib-list port))
1027 ;;------------------------------------------------------------
1028 ;; write mesfet transistor
1029 ;;------------------------------------------------------------
1030 ;; ************ Fix this!!!!!!!!!! **************
1031 (define spice-sdb:write-mesfet-transistor
1032 (lambda (package port)
1033 (spice-sdb:write-transistor-diode package "Z" "MESFET" (list) port))) ;; XXXXXX Fix this!!!
1036 ;;-----------------------------------------------------------
1037 ;; write voltage controled switch
1038 ;;-----------------------------------------------------------
1039 (define spice-sdb:write-vc-switch
1040 (lambda (package port)
1041 (debug-spew (string-append "Found voltage controled switch. Refdes = " package "\n"))
1042 (let ((attrib-list (list " " ) ))
1043 (spice-sdb:write-transistor-diode package "S" "SW" attrib-list port))
1048 ;;--------------------------------------------------------------------
1050 ;;--------------------------------------------------------------------
1051 (define spice-sdb:write-resistor
1052 (lambda (package port)
1054 (debug-spew (string-append "Found resistor. Refdes = " package "\n"))
1056 ;; first write out refdes and attached nets
1057 (spice-sdb:write-component-no-value package port)
1059 ;; next write out mandatory resistor value if it exists.
1060 (let ((value (gnetlist:get-package-attribute package "value")))
1061 (if (not (string=? value "unknown"))
1062 (display (string-append value " " ) port))
1065 ;; next write our model name if it exists
1066 (let* ((model-name (gnetlist:get-package-attribute package "model-name")))
1067 (if (not (string=? model-name "unknown"))
1068 (display (string-append model-name " " ) port))
1071 ;; next create list of attributes which can be attached to a resistor.
1072 ;; I include non-standard "area" attrib here per popular demand.
1073 (let ((attrib-list (list "area" "l" "w" "temp")))
1074 ;; write the attributes (if any) separately
1075 (spice-sdb:write-list-of-attributes package attrib-list port)
1076 (display " " port)) ;; add additional space. . . .
1078 ;; finally output a new line
1085 ;;----------------------------------------------------------------------------
1087 ;;----------------------------------------------------------------------------
1088 (define spice-sdb:write-capacitor
1089 (lambda (package port)
1091 (debug-spew (string-append "Found capacitor. Refdes = " package "\n"))
1093 ;; first write out refdes and attached nets
1094 (spice-sdb:write-component-no-value package port)
1096 ;; next write capacitor value, if any. Note that if the
1097 ;; component value is not assigned nothing will be written out.
1098 (let ((value (gnetlist:get-package-attribute package "value")))
1099 (if (not (string=? value "unknown"))
1100 (display (string-append value " " ) port))
1103 ;; next write capacitor model name, if any. This is applicable to
1104 ;; semiconductor caps used in chip design.
1105 (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1106 (if (not (string=? model-name "unknown"))
1107 (display (string-append model-name " " ) port))
1110 ;; Next write out attribtes if they exist. Use
1111 ;; a list of attributes which can be attached to a capacitor.
1112 ;; I include non-standard "area" attrib here per request of Peter Kaiser.
1113 (let ((attrib-list (list "area" "l" "w" "ic")))
1114 (spice-sdb:write-list-of-attributes package attrib-list port)
1115 ;; write the off attribute separately
1116 (display " " port)) ;; add additional space. . . .
1123 ;;----------------------------------------------------------------------------
1125 ;;----------------------------------------------------------------------------
1126 (define spice-sdb:write-inductor
1127 (lambda (package port)
1129 (debug-spew (string-append "Found inductor. Refdes = " package "\n"))
1131 ;; first write out refdes and attached nets
1132 (spice-sdb:write-component-no-value package port)
1134 ;; ;; next write inductor model name, if any.
1135 ;; (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1136 ;; (if (not (string=? model "unknown"))
1137 ;; (display (string-append model-name " " ) port)
1140 ;; next write inductor value, if any. Note that if the
1141 ;; component value is not assigned, then it will write "unknown"
1142 (let ((value (gnetlist:get-package-attribute package "value")))
1143 (display value port)
1147 ;; create list of attributes which can be attached to a inductor
1148 (let ((attrib-list (list "l" "w" "ic")))
1149 (spice-sdb:write-list-of-attributes package attrib-list port)
1151 ;; write the off attribute separately
1152 (display " " port)) ;; add additional space. . . .
1159 ;;-------------------------------------------------------------------------
1160 ;; write independent voltage source
1161 ;; The behavior of the voltage source is held in the "value" attribute
1162 ;;-------------------------------------------------------------------------
1163 (define spice-sdb:write-independent-voltage-source
1164 (lambda (package port)
1165 (debug-spew (string-append "Found independent voltage source. Refdes = " package "\n"))
1167 ;; first write out refdes and attached nets
1168 (spice-sdb:write-component-no-value package port)
1170 ;; next write voltage value, if any. Note that if the
1171 ;; voltage value is not assigned, then it will write "unknown"
1172 (let ((value (gnetlist:get-package-attribute package "value")))
1173 (display value port)
1180 ;;-------------------------------------------------------------------------
1181 ;; write independent current source
1182 ;; The behavior of the current source is held in the "value" attribute
1183 ;;-------------------------------------------------------------------------
1184 (define spice-sdb:write-independent-current-source
1185 (lambda (package port)
1187 (debug-spew (string-append "Found independent current source. Refdes = " package "\n"))
1189 ;; first write out refdes and attached nets
1190 (spice-sdb:write-component-no-value package port)
1192 ;; next write current value, if any. Note that if the
1193 ;; current value is not assigned, then it will write "unknown"
1194 (let ((value (gnetlist:get-package-attribute package "value")))
1195 (display value port)
1202 ;;----------------------------------------------------------------------------
1203 ;; write Josephson junction in wrspice format. Paul Bunyk, Sep 2, 2005
1204 ;;----------------------------------------------------------------------------
1205 (define spice-sdb:write-josephson-junction
1206 (lambda (package port)
1208 (debug-spew (string-append "Found Josephson junction. Refdes = " package "\n"))
1210 ;; first write out refdes and attached nets
1211 (spice-sdb:write-component-no-value package port)
1213 ;; next, add a dummy node for JJ phase. Unlike in Xic netlister, give it
1214 ;; a reasonable name, not a number, e.g., refdes.
1215 (display (string-append package " ") port)
1217 ;; next write JJ model name, if any.
1218 (let ((model-name (gnetlist:get-package-attribute package "model-name")))
1219 (if (not (string=? model-name "unknown"))
1220 (display (string-append model-name " " ) port))
1223 ;; Next write out attribtes if they exist. Use
1224 ;; a list of attributes which can be attached to a junction.
1225 (let ((attrib-list (list "area")))
1226 (spice-sdb:write-list-of-attributes package attrib-list port)
1227 ;; write the off attribute separately
1228 (display " " port)) ;; add additional space. . . .
1234 ;;----------------------------------------------------------------------------
1235 ;; write mutual inductance(actually K). Paul Bunyk, Sep 2, 2005
1236 ;;----------------------------------------------------------------------------
1237 (define spice-sdb:write-coupling-coefficient
1238 (lambda (package port)
1240 (debug-spew (string-append "Found mutual inductance. Refdes = " package "\n"))
1242 ;; first write out refdes and attached nets (none)
1243 (spice-sdb:write-component-no-value package port)
1245 ;; next two inductor names and value
1246 (let ((inductors (gnetlist:get-package-attribute package "inductors"))
1247 (value (gnetlist:get-package-attribute package "value")) )
1248 (if (not (string=? inductors "unknown"))
1249 (display (string-append inductors " " ) port))
1250 (if (not (string=? value "unknown"))
1251 (display (string-append value " " ) port))
1259 ;;--------------------------------------------------------------------
1260 ;; Given a refdes and number of pins, this writes out the nets
1261 ;; attached to the component's pins. This is used to write out
1262 ;; non-slotted parts. Call it with a component refdes and the number
1263 ;; of pins left on this component to look at.
1264 ;;--------------------------------------------------------------------
1265 (define spice-sdb:write-net-names-on-component
1266 (lambda (refdes number-of-pins port)
1267 (if (> number-of-pins 0)
1269 ;; first find pin1 and then start writing the connected net name
1270 (spice-sdb:write-net-names-on-component refdes (- number-of-pins 1) port)
1271 ;; generate a pin-name e.g. pin1, pin2, pin3 ...
1272 (let* ((pin-name (number->string number-of-pins))
1273 (pinnumber (gnetlist:get-attribute-by-pinseq refdes pin-name "pinnumber"))
1274 (pinseq (gnetlist:get-attribute-by-pinseq refdes pin-name "pinseq"))
1275 (netname (car (spice-sdb:get-net refdes pinnumber)) )
1278 ;; ------- Super debug stuff --------
1279 (debug-spew " In write-net-names-on-component. . . . \n")
1280 (debug-spew (string-append " pin-name = " pin-name "\n"))
1281 (debug-spew (string-append " pinnumber = " pinnumber "\n"))
1282 (debug-spew (string-append " pinseq = " pinseq "\n"))
1283 (debug-spew (string-append " netname = " netname "\n"))
1284 ;; ------------------------------
1286 (if (not (string=? netname "ERROR_INVALID_PIN"))
1287 (display (string-append netname " ") port) ;; write out attached net if OK.
1288 (debug-spew (string-append "For " refdes ", found pin with no pinseq attribute. Ignoring. . . .\n"))
1297 ;;-------------------------------------------------------------------
1298 ;; Write the refdes and the net names connected to pins on this component.
1299 ;; No return, and no component value is written, or extra attribs.
1300 ;; Those are handled later.
1301 ;;-------------------------------------------------------------------
1302 (define spice-sdb:write-component-no-value
1303 (lambda (package port)
1304 (display (string-append package " ") port) ;; write component refdes
1305 (spice-sdb:write-net-names-on-component package (length (gnetlist:get-pins package)) port)
1310 ;;-----------------------------------------------------------
1311 ;; Given a refdes, returns the device attribute "value" as string
1312 ;; Used when "value" is a mandatory attribute.
1313 ;; Returns "<no valid attribute . . .>" if not available.
1314 ;;-----------------------------------------------------------
1315 (define spice-sdb:component-value
1317 (let ((value (gnetlist:get-package-attribute package "value")))
1318 ;; (display (string-append "in get-package-attribute, value = " value "\n"))
1319 (if (not (string=? value "unknown"))
1321 "<No valid value attribute found>"))))
1324 ;;------------------------------------------------------------
1325 ;; Given a refdes, returns the device attribute "value" as string
1326 ;; Used when "value" is an optional attribute.
1327 ;; Returns "unknown" if not available.
1328 ;;------------------------------------------------------------
1329 (define spice-sdb:component-optional-value
1331 (let ((value (gnetlist:get-package-attribute package "value")))
1332 (if (not (string=? value "unknown"))
1333 (string-append value " ")
1337 ;;-----------------------------------------------------------
1338 ;; Given a refdes, returns the device attribute "model" as string
1339 ;;-----------------------------------------------------------
1340 (define spice-sdb:component-model
1342 (let ((model (gnetlist:get-package-attribute package "model")))
1343 (if (not (string=? model "unknown"))
1344 model spice-sdb:component-value))))
1347 ;;----------------------------------------------------------
1348 ;; Include SPICE statements from a SPICE directive block.
1349 ;;----------------------------------------------------------
1350 (define spice-sdb:write-directive
1351 (lambda (package port)
1352 ;; Collect variables used in creating spice code
1353 (let ((value (gnetlist:get-package-attribute package "value"))
1354 (file (gnetlist:get-package-attribute package "file"))
1355 ) ;; end of local assignments
1357 (debug-spew (string-append "Found SPICE directive box. Refdes = " package "\n"))
1361 ;; First look to see if there is a value.
1362 ((not (string=? value "unknown"))
1364 (display (string-append value "\n") port)
1365 (debug-spew (string-append "Appending value = \"" value "\" to output file.\n"))
1368 ;; since there is no value, look for file.
1369 ((not (string=? file "unknown"))
1371 (spice-sdb:insert-text-file file port) ;; Note that we don't wait until the end here. Is that OK?
1372 (debug-spew (string-append "Inserting contents of file = " file " into output file.\n"))
1377 ) ;; close of lambda
1378 ) ;; close of define
1381 ;;----------------------------------------------------------
1382 ;; Include a file using an .INCLUDE directive
1383 ;; Changed on 6.12.2005: to embedd the contents of the file,
1384 ;; you must call gnetlist with the -e flag set.
1385 ;;----------------------------------------------------------
1386 (define spice-sdb:write-include
1387 (lambda (package port)
1388 (let ((value (gnetlist:get-package-attribute package "value"))
1389 (file (gnetlist:get-package-attribute package "file"))
1390 ) ;; end of local assignments
1392 (debug-spew (string-append "Found SPICE include box. Refdes = " package "\n"))
1393 ;; (debug-spew (string-append " value = " value "\n"))
1394 ;; (debug-spew (string-append " file = " file "\n"))
1397 ;; First look to see if value attribute is used
1398 ((not (string=? value "unknown"))
1400 ;; (debug-spew "This include directive uses a value attribute.\n")
1401 (if (calling-flag? "embedd_mode" (gnetlist:get-calling-flags))
1403 (spice-sdb:insert-text-file value port) ;; -e found: invoke insert-text-file
1404 (debug-spew (string-append "embedding contents of " value " into netlist.\n")))
1406 (display (string-append ".INCLUDE " value "\n") port) ;; -e not found: just print out .INCLUDE card
1407 (debug-spew "placing .include directive string into netlist.\n"))
1410 ;; Now look to see if file is used
1411 ((not (string=? file "unknown"))
1413 ;; (debug-spew "This include directive uses a file attribute.\n")
1414 (if (calling-flag? "embedd_mode" (gnetlist:get-calling-flags))
1416 (spice-sdb:insert-text-file file port) ;; -e found: invoke insert-text-file
1417 (debug-spew (string-append "embedding contents of " value " into netlist.\n")))
1419 (display (string-append ".INCLUDE " file "\n") port) ;; -e not found: just print out .INCLUDE card
1420 (debug-spew "placing .include directive string into netlist.\n"))
1421 ) ;; end of if (calling-flag
1427 ;;----------------------------------------------------------
1428 ;; Include an option using an .OPTIONS directive
1429 ;;----------------------------------------------------------
1430 (define spice-sdb:write-options
1431 (lambda (package port)
1432 (debug-spew (string-append "Found .OPTIONS box. Refdes = " package "\n"))
1433 (display (string-append ".OPTIONS " (spice-sdb:component-value package) "\n") port)))
1436 ;;----------------------------------------------------------
1437 ;; Include a spice model (instantiated as a model box on the schematic)
1438 ;; Two types of model can be included:
1439 ;; 1. An embedded model, which is a one- or multi-line string held in the attribute "model".
1440 ;; In this case, the following attributes are mandatory:
1441 ;; -- model (i.e. list of parameter=value strings)
1444 ;; In this case, the function creates and formats the correct spice model line(s).
1445 ;; 2. A model held in a file whose name is held in the attribute "file"
1446 ;; In this case, the following attribute are mandatory:
1447 ;; -- file (i.e. list of parameter=value strings)
1448 ;; In this case, the function just opens the file and dumps the contents
1449 ;; into the netlist.
1450 ;;----------------------------------------------------------
1451 (define spice-sdb:write-model
1452 (lambda (package port)
1453 ;; Collect variables used in creating spice code
1454 (let ((model-name (gnetlist:get-package-attribute package "model-name"))
1455 (model-file (gnetlist:get-package-attribute package "file"))
1456 (model (gnetlist:get-package-attribute package "model"))
1457 (type (gnetlist:get-package-attribute package "type"))
1458 ) ;; end of local assignments
1460 (debug-spew (string-append "Found .MODEL box. Refdes = " package "\n"))
1462 ;; Now, depending upon what combination of model, model-file, and model-name
1463 ;; exist (as described above) write out lines into spice netlist.
1465 ;; one model and model name exist
1466 ( (not (or (string=? model "unknown") (string=? model-name "unknown")))
1467 (debug-spew (string-append "found model and model-name for " package "\n"))
1468 (display (string-append ".MODEL " model-name " " type " (" model ")\n") port) )
1470 ;; model file exists
1471 ( (not (or (string=? model-file "unknown") ))
1472 (debug-spew (string-append "found model-file for " package "\n"))
1473 ;; (spice-sdb:insert-text-file model-file port) ;; don't write it out -- it's handled after the second pass.
1478 ) ;; close of lambda
1479 ) ;; close of define
1484 ;;-------------------------------------------------------------------
1485 ;; This writes out the default component (i.e. the "device" attribute
1486 ;; was not recognized). This function does the following:
1488 ;; 1. Gets the refdes (package).
1489 ;; 2. Checks the refdes against a short list of possible values.
1490 ;; Depending upon the refdes, it does the following thing:
1491 ;; D? -- Invokes write-diode
1492 ;; Q? -- Invokes write-transistor-diode. (The "type" attribute is <unknown>
1493 ;; in this case so that the spice simulator will barf if the user
1494 ;; has been careless.)
1495 ;; U? -- Invokes write-ic. This provides the opportunity for a component
1496 ;; model to be instantiated.
1497 ;; X? -- Invokes write-subcircuit. This provides the opportunity for a component
1498 ;; model to be instantiated.
1499 ;; V? -- Invokes write-independent-voltage-source
1500 ;; I? -- Invokes write-independent-current-source
1501 ;; Otherwise, it just outputs the refdes, the attached nets, and the
1502 ;; value of the "value" attribute.
1504 ;;-------------------------------------------------------------------
1505 (define spice-sdb:write-default-component
1506 (lambda (package file-info-list port)
1508 (let ((first-char (string (string-ref package 0)) )) ;; extract first char of refdes.
1510 ((string=? first-char "D") (spice-sdb:write-diode package port))
1511 ((string=? first-char "Q") (spice-sdb:write-transistor-diode package #f "<unknown>" (list) port))
1512 ((string=? first-char "M") (spice-sdb:write-transistor-diode package #f "<unknown>" (list) port))
1513 ((string=? first-char "U") (spice-sdb:write-ic package file-info-list port))
1514 ((string=? first-char "V") (spice-sdb:write-independent-voltage-source package port))
1515 ((string=? first-char "I") (spice-sdb:write-independent-current-source package port))
1516 ((string=? first-char "X") (spice-sdb:write-subcircuit package file-info-list port))
1518 (display (string-append "Found unknown component. Refdes = " package "\n"))
1519 (spice-sdb:write-component-no-value package port)
1520 ;; write component value, if components have a label "value=#"
1521 ;; what if a component has no value label, currently unknown is written
1522 (display (spice-sdb:component-value package) port)
1532 ;;**********************************************************************************
1533 ;;*************** High-level functions for program control ***********************
1534 ;;**********************************************************************************
1536 ;;----------------------------------------------------------------------
1537 ;; write-netlist is passed a list of refdess (ls). It uses
1538 ;; each refdes to get the corresponding
1539 ;; "device" attribute. Depending upon the device, it then invokes one or another of the
1540 ;; spice line output fcns to output a line of the spice netlist.
1541 ;; I have enlarged the number of devices it recognizes -- SDB.
1542 ;; write the refdes, to the pin# connected net and component
1543 ;; value and optional extra attributes
1544 ;; check if the component is a special spice component.
1545 ;;----------------------------------------------------------------------
1546 (define spice-sdb:write-netlist
1547 (lambda (port file-info-list ls)
1548 (if (not (null? ls))
1549 (let* ((package (car ls)) ;; assign package
1550 (device (get-device package)) ;; assign device.
1551 ) ;; end of let* assignments
1553 ;; Super debug stuff -- outputs line describing device being processed.
1554 (debug-spew (string-append "--- checking package = " package "\n"))
1555 (debug-spew (string-append " device = " device "\n"))
1556 ;; done with debug stuff
1559 ( (string=? device "none")) ;; do nothing for graphical symbols.
1560 ( (string=? device "spice-subcircuit-LL")) ;; do nothing for subcircuit declaration.
1561 ( (string=? device "spice-IO")) ;; do nothing for SPICE IO pins.
1562 ( (string=? device "SPICE-ccvs")
1563 (spice-sdb:write-ccvs package port))
1564 ( (string=? device "SPICE-cccs")
1565 (spice-sdb:write-cccs package port))
1566 ( (string=? device "SPICE-vcvs")
1567 (spice-sdb:write-vcvs package port))
1568 ( (string=? device "SPICE-vccs")
1569 (spice-sdb:write-vccs package port))
1570 ( (string=? device "SPICE-nullor")
1571 (spice-sdb:write-nullor package port))
1572 ( (string=? device "DIODE")
1573 (spice-sdb:write-diode package port))
1574 ( (string=? device "PMOS_TRANSISTOR")
1575 (spice-sdb:write-pmos-transistor package port))
1576 ( (string=? device "NMOS_TRANSISTOR")
1577 (spice-sdb:write-nmos-transistor package port))
1578 ( (string=? device "PNP_TRANSISTOR")
1579 (spice-sdb:write-pnp-bipolar-transistor package port))
1580 ( (string=? device "SPICE-PNP")
1581 (spice-sdb:write-pnp-bipolar-transistor package port))
1582 ( (string=? device "NPN_TRANSISTOR")
1583 (spice-sdb:write-npn-bipolar-transistor package port))
1584 ( (string=? device "SPICE-NPN")
1585 (spice-sdb:write-npn-bipolar-transistor package port))
1586 ( (string=? device "PFET_TRANSISTOR")
1587 (spice-sdb:write-pfet-transistor package port))
1588 ( (string=? device "NFET_TRANSISTOR")
1589 (spice-sdb:write-nfet-transistor package port))
1590 ( (string=? device "MESFET_TRANSISTOR")
1591 (spice-sdb:write-mesfet-transistor package port))
1592 ( (string=? device "SPICE-VC-switch")
1593 (spice-sdb:write-vc-switch package port))
1594 ( (string=? device "RESISTOR")
1595 (spice-sdb:write-resistor package port))
1596 ( (string=? device "CAPACITOR")
1597 (spice-sdb:write-capacitor package port))
1598 ( (string=? device "POLARIZED_CAPACITOR")
1599 (spice-sdb:write-capacitor package port)) ;; change someday
1600 ( (string=? device "INDUCTOR")
1601 (spice-sdb:write-inductor package port))
1602 ( (string=? device "COIL") ;; Added to enable netlisting of coil-*.sym
1603 (spice-sdb:write-inductor package port))
1604 ( (string=? device "VOLTAGE_SOURCE")
1605 (spice-sdb:write-independent-voltage-source package port)) ;; change someday
1606 ( (string=? device "CURRENT_SOURCE")
1607 (spice-sdb:write-independent-current-source package port)) ;; change someday
1608 ( (string=? device "JOSEPHSON_JUNCTION")
1609 (spice-sdb:write-josephson-junction package port))
1610 ( (string=? device "K")
1611 (spice-sdb:write-coupling-coefficient package port))
1612 ( (string=? device "model")
1613 (spice-sdb:write-model package port))
1614 ( (string=? device "options")
1615 (spice-sdb:write-options package port))
1616 ( (string=? device "directive")
1617 (spice-sdb:write-directive package port))
1618 ( (string=? device "include")
1619 (spice-sdb:write-include package port))
1621 (spice-sdb:write-default-component package file-info-list port))
1623 (spice-sdb:write-netlist port file-info-list (cdr ls))
1628 ;;----------------------------------------------------------------------
1629 ;; create-file-info-list: This takes as arugment the list of packages (refdesses).
1630 ;; It runs through the package list, and for each gets the attributes. If there is a
1631 ;; "FILE" attribute, it gets the file info & uses it to build the
1632 ;; file-info-list. When done, it returns the file-info-list.
1633 ;;----------------------------------------------------------------------
1634 (define spice-sdb:create-file-info-list
1635 (lambda (package-list file-info-list)
1636 (if (null? package-list)
1637 file-info-list ;; end of packages processed. Return file-info-list
1638 (let* ((package (car package-list)) ;; otherwise get next package (i.e. refdes)
1642 (model-file (string))
1643 ) ;; end of let* assignments
1645 (set! device (get-device package) )
1646 (set! model (gnetlist:get-package-attribute package "model-name") )
1647 (set! value (gnetlist:get-package-attribute package "value") )
1648 (set! model-file (gnetlist:get-package-attribute package "file") )
1650 ;; sometimes get-package-attribute returns "?" instead of "unknown". WTF? This should fix that . . .
1651 (if (string-ci=? model-file "?")
1652 (set! model-file "unknown"))
1654 ;; Now run a series of checks to see if we should stick this file into the file-info-list
1655 ;; Check to see if "file" attribute is non-empty
1656 (if (not (string-ci=? model-file "unknown"))
1659 (string-append "found file attribute for " package ". File name = " model-file "\n")) ;; ******* Debug stuff
1661 ;; Now check to see if file is in file-info-list
1662 (if (not (spice-sdb:in-file-info-list? model-file file-info-list))
1664 ;; File is new. Open file, find out what type it is, and push info into file-info-list
1665 (let ((file-type (spice-sdb:get-file-type model-file))
1667 (debug-spew (string-append "File is new. New file type is " file-type " \n")) ;; DEBUG
1669 ;; Check to see if file-type is known.
1670 (if (not (string=? file-type "OTHER"))
1671 ;; file-type is OK. Return file-info-list with new triplet attached.
1673 (debug-spew (string-append "Inserting " model-file " into list of known model files.\n"))
1674 (set! file-info-list (append (list (list model model-file file-type)) file-info-list) )
1677 ;; Otherwise, file type is not a model type. Don't stick it in list. Print debug spew if desired.
1678 (debug-spew "File type is OTHER, and therefore will not be entered in known model file list.\n")
1679 ) ;; end if (not (string=?
1681 ) ;; end let ((file-type . . .
1683 ;; File is already in list. Print debug spew if desired.
1684 (debug-spew "File has already been seen and entered into known model file list.\n")
1685 ) ;; end if (spice-sdb:in-file-info-list . . .
1687 ) ;; end begin . . .
1688 ) ;; end if (not( string-ci=? model-file
1690 ;; having done checking and processing of this package, iterate to the next one.
1691 (spice-sdb:create-file-info-list (cdr package-list) file-info-list)
1694 ) ;; 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?
1725 ;;--------------------------------------------------------------
1726 ;; Write out spice netlist header
1727 ;;--------------------------------------------------------------
1728 (define spice-sdb:write-top-header
1730 (display "*********************************************************\n" port)
1731 (display "* Spice file generated by gnetlist *\n" port)
1732 (display "* spice-sdb version 4.28.2007 by SDB -- *\n" port)
1733 (display "* provides advanced spice netlisting capability. *\n" port)
1734 (display "* Documentation at http://www.brorson.com/gEDA/SPICE/ *\n" port)
1735 (display "*********************************************************\n" port)
1739 ;;--------------------------------------------------------------
1740 ;; Write out .SUBCKT netlist header
1741 ;;--------------------------------------------------------------
1742 (define spice-sdb:write-subcircuit-header
1744 (display "*******************************\n" port)
1745 (display "* Begin .SUBCKT model *\n" port)
1746 (display "* spice-sdb ver 4.28.2007 *\n" port)
1747 (display "*******************************\n" port)
1752 ;;---------------------------------------------------------------
1753 ;; Write the .END line
1754 ;;---------------------------------------------------------------
1755 (define spice-sdb:write-bottom-footer
1756 (lambda (salutation port)
1757 (display salutation port)
1761 ;;---------------------------------------------------------------
1762 ;; Spice netlist generation
1763 ;; This is the entry point.
1764 ;; Hacked on 3.31.2003 to enable writing out .SUBCKT models -- SDB.
1765 ;; Hacked again in Sept 2003 to enable more intelligent embedding of external
1766 ;; SPICE files into netlist -- SDB.
1767 ;; The algorithm is as follows:
1768 ;; 1. Figure out if there is a .SUBCKT block on the schematic,
1769 ;; or if it is just a normal schematic.
1771 ;; -- Write out subcircuit header (a comment identifying the netlister).
1772 ;; -- find all spice-IO pins. Get a list of the packages.
1773 ;; -- put them in order (ordered by package refdes)
1774 ;; -- get the list of nets attached to the spice-IO pins.
1775 ;; -- write out .SUBCKT line
1776 ;; If a normal schematic:
1777 ;; -- Write out top header (a comment identifying the netlister).
1778 ;; 2. Loop through all components, looking for components with a "file"
1779 ;; attribute. Every time a "file" attribute is found do this:
1780 ;; -- Open the file and find out what kind of file it is (.SUBCKT or .MODEL).
1781 ;; -- Determine if the file has previously been processed. If not: stick the
1782 ;; follwing info into the file-info list: (model-name file-name file-type).
1783 ;; Otherwise just continue.
1784 ;; 3. Loop through all components again, and write out a SPICE card for each.
1785 ;; 4. Afterwards, for each item in the file-info list, open the file, and
1786 ; write its contents into the netlist.
1787 ;; 5. If the schematic-type is .SUBCKT: write out .ENDS, Otherwise: write out .END
1788 ;; 6. Close up the SPICE netlist file and return.
1789 ;;---------------------------------------------------------------
1791 (lambda (output-filename)
1793 ;; First find out if this is a .SUBCKT lower level,
1794 ;; or if it is a regular schematic.
1796 (let* ((port (open-output-file output-filename))
1797 (schematic-type (spice-sdb:get-schematic-type packages))
1798 (model-name (spice-sdb:get-subcircuit-modelname schematic-type))
1799 (file-info-list (list))
1801 (display "Using SPICE backend by SDB -- Version of 4.28.2007\n")
1802 (display (string-append "schematic-type = " schematic-type "\n"))
1803 ;; (display (string-append "model-name = " model-name "\n"))
1805 (if (not (string=? schematic-type "normal schematic"))
1806 ;; we have found a .SUBCKT type schematic.
1807 (let* ((io-pin-packages (spice-sdb:get-spice-IO-pins packages (list) ))
1808 (io-pin-packages-ordered (spice-sdb:sort-spice-IO-pins io-pin-packages))
1809 (io-nets-list (spice-sdb:get-IO-nets io-pin-packages-ordered (list) ))
1811 (debug-spew "found .SUBCKT type schematic")
1812 ;; now write out .SUBCKT header and .SUBCKT line
1813 (spice-sdb:write-subcircuit-header port)
1814 (let ((io-nets-string (list-2-string io-nets-list)) )
1815 ;; (display (string-append "Found IO nets for subckt = " io-nets-string "\n")) ;; DEBUG stuff . . .
1816 ;; (write io-nets-list)
1818 (display (string-append schematic-type " " (list-2-string io-nets-list) "\n") port)
1822 ;; Otherwise it's a regular schematic. Write out command line followed by comments in file header.
1824 (debug-spew "found normal type schematic")
1825 (display (string-append "* " (gnetlist:get-command-line) "\n") port)
1826 (spice-sdb:write-top-header port)
1829 ) ;; end of if (not (string=? . . . .
1833 ;; Now loop through all devices and process all "FILE" attributes. Create
1835 ;; Thanks to Carlos Nieves Onega for his e-mail to
1836 ;; geda-dev which is the genesis of this section.
1838 (debug-spew "\nMake first pass through design and create list of all model files referenced.\n")
1839 (set! file-info-list (spice-sdb:create-file-info-list packages file-info-list))
1840 (debug-spew "Done creating file-info-list.\n")
1842 ;; extra debug spew -- comment out when done . . .
1843 ;; (display "file-info-list = \n")
1844 ;; (write file-info-list)
1851 ;; Moved this loop before the next one to get numparam to work with ngspice,
1852 ;; because numparam will at the subckt definition come before the main netlist.
1853 ;; Change suggested by Dominique Michel; implemented in code on 6.12.2005.
1855 ;; Next loop through all items in file-info-list in the SPICE netlist.
1856 ;; For each model-name, open up the corresponding file, and call handle-spice-file
1857 ;; to stick the corresponding stuff into the output SPICE file.
1859 (debug-spew "Now process the items in model file list -- stick appropriate references to models in output SPICE file.\n")
1860 (spice-sdb:loop-through-files file-info-list port)
1861 (debug-spew "Done processing items in model file list.\n")
1865 ;; Now write out netlist as before. But don't write file contents out.
1866 ;; **** Modified by kh to sort list of packages so Spice directives, etc. (A?) are output last,
1867 ;; **** and in increasing order.
1869 (debug-spew "Make second pass through design and write out a SPICE card for each component found.\n")
1870 (display (string-append "*============== Begin SPICE netlist of main design ============\n") port)
1871 (if (spice-sdb:sort-refdes? (gnetlist:get-calling-flags))
1872 (spice-sdb:write-netlist port file-info-list (sort packages spice-sdb:packsort)) ;; sort on refdes
1873 (spice-sdb:write-netlist port file-info-list packages) ;; don't sort.
1875 (debug-spew "Done writing SPICE cards . . .\n\n")
1879 ;; Now write out .END(S) of netlist, depending upon whether this schematic is a
1880 ;; "normal schematic" or a .SUBCKT.
1882 (if (not (string=? schematic-type "normal schematic"))
1884 (spice-sdb:write-bottom-footer (string-append ".ends " model-name) port)
1885 (display "*******************************\n" port)
1887 (spice-sdb:write-bottom-footer ".end" port)
1893 ;; Finally, close up and go home.
1895 (close-output-port port)
1896 (debug-spew "\nOutput file is written. We are done.\n")
1897 ) ;; (let* ((port . . . .
1902 ;; Custom get-uref function to append ".${SLOT}" where a component
1903 ;; has a "slot=${SLOT}" attribute attached.
1905 ;; NOTE: Original test for appending the ".<SLOT>" was this:
1906 ;; (let ((numslots (gnetlist:get-package-attribute package "numslots"))
1907 ;; (slot-count (length (gnetlist:get-unique-slots package)))
1908 ;; (if (or (string=? numslots "unknown") (string=? numslots "0"))
1912 (let ((real_uref (gnetlist:get-uref object)))
1913 (if (null? (get-attrib-value-by-attrib-name object "slot"))
1915 (string-append real_uref "."
1916 (car (get-attrib-value-by-attrib-name object "slot")))