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
26 ;; Given a uref, returns the device associated nets(s) ordered by
27 ;; their pin#, what when not defined?
28 ;; problem is slotted components e.g. ../examples/singlenet_1.sch
31 ;; Ales' changed implemenation
32 ;; Commented out since it has some problems
33 ;; (define spice:write-net-name-of-node
34 ;; (lambda (uref pins port)
35 ;; (if (not (null? pins))
36 ;; (let ((pin (car pins)))
38 ;; (display pin) (newline)
39 ;; (display (car (gnetlist:get-nets uref pin)) port)
40 ;; (write-char #\space port)
41 ;; (spice:write-net-name-of-node uref (cdr pins) port)
50 ;; gnet-spice replacement of gnetlist:get-nets, a net labeled "GND" becomes 0
53 (lambda (uref pin-name )
54 (let ((net-name (gnetlist:get-nets uref pin-name)))
55 (cond ((string=? (car net-name) "GND") (cons "0" #t))
56 (else (cons (car net-name) #t))))))
60 ;; write netnames connected to pin-a and pin-b
61 ;; (currently used by the controlled sources (e,g,f and h)
63 (define spice:write-two-pin-names
64 (lambda (package pin-a pin-b port)
65 (display (string-append
66 (car (spice:get-net package (gnetlist:get-attribute-by-pinseq package pin-a "pinnumber"))) " ") port)
67 (display (string-append
68 (car (spice:get-net package (gnetlist:get-attribute-by-pinseq package pin-b "pinnumber"))) " ") port)))
73 ;; write a current controlled voltage source and implement the necessary
74 ;; current measuring voltage source
75 (define spice:write-ccvs
76 (lambda (package port)
78 (display "* begin ccvs expansion, h<name>\n" port)
79 ;; implement the controlled current source
80 ;; the user should create the uref label begining with a h
81 (display (string-append package " ") port)
82 (spice:write-two-pin-names package "1" "2" port)
83 (display (string-append "Vsense_" package " " (spice:component-value package) "\n" ) port)
84 ;; implement the current measuring voltage source
85 (display (string-append "Vsense_" package " ") port)
86 (spice:write-two-pin-names package "3" "4" port)
87 (display "dc 0\n" port)
88 ;; now it is possible to leave the output voltage source unconnected
89 ;; i.e. spice won't complain about unconnected nodes
90 (display (string-append "Iout_" package " ") port)
91 (spice:write-two-pin-names package "1" "2" port)
92 (display "dc 0\n" port)
93 (display "* end ccvs expansion\n" port))))
97 ;; write a current controlled current source and implement the necessary
98 ;; current measuring voltage source
99 (define spice:write-cccs
100 (lambda (package port)
102 (display "* begin cccs expansion, f<name>\n" port)
103 ;; implement the controlled current source
104 ;; the user should create the uref label begining with a f
105 (display (string-append package " ") port)
106 (spice:write-two-pin-names package "1" "2" port)
107 (display (string-append "Vsense_" package " " (gnetlist:get-package-attribute package "value") "\n" ) port)
108 ;; implement the current measuring voltage source
109 (display (string-append "Vsense_" package " ") port)
110 (spice:write-two-pin-names package "3" "4" port)
111 (display "dc 0\n" port)
112 (display "* end cccs expansion\n" port))))
117 ;; write a voltage controlled current source and implement the necessary
118 ;; voltage measuring current source
119 (define spice:write-vccs
120 (lambda (package port)
122 (display "* begin vccs expansion, g<name>\n" port)
123 ;; implement the controlled current source
124 ;; the user should create a uref label beginning with a g
125 (display (string-append package " ") port)
126 (spice:write-net-name-of-component package (length (gnetlist:get-pins package)) port)
127 (display (string-append (spice:component-value package) "\n") port)
128 ;; implement the voltage measuring current source
129 ;; imagine yourself copying the voltage of a voltage source with an internal
130 ;; impedance, spice starts complaining about unconnected nets if this current
131 ;; source is not here.
132 (display (string-append "Imeasure_" package " ") port)
133 (spice:write-two-pin-names package "3" "4" port)
134 (display "dc 0\n" port)
135 (display "* end vccs expansion\n" port))))
139 ;; write a voltage controlled voltage source and implement the necessary
140 ;; voltage measuring current source
141 (define spice:write-vcvs
142 (lambda (package port)
144 (display "* begin vcvs expansion, e<name>\n" port)
145 ;; implement the controlled voltage source
146 ;; the user should create a uref label beginning with an e
147 (display (string-append package " ") port)
148 (spice:write-net-name-of-component package (length (gnetlist:get-pins package)) port)
149 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
150 ;; implement the voltage measuring current source
151 ;; imagine yourself copying the voltage of a voltage source with an internal
152 ;; impedance, spice starts complaining about unconnected nets if this current
153 ;; source is not here.
154 (display (string-append "Isense_" package " ") port)
155 (spice:write-two-pin-names package "3" "4" port)
156 (display "dc 0\n" port)
157 ;; with an output current source it is possible to leave the output voltage source
158 ;; unconnected i.e. spice won't complain about unconnected nodes
159 (display (string-append "Iout_" package " ") port)
160 (spice:write-two-pin-names package "1" "2" port)
161 (display "dc 0\n" port)
162 (display "* end vcvs expansion\n" port))))
166 ;; Create a nullor, make sure it consists of a voltage controlled source
168 (define spice:write-nullor
169 (lambda (package port)
171 (display "* begin nullor expansion, e<name>\n" port)
172 ;; implement the controlled voltage source
173 (display (string-append "E-" package " ") port)
174 (spice:write-net-name-of-component package (length (gnetlist:get-pins package)) port)
175 (display (string-append (gnetlist:get-package-attribute package "value") "\n" ) port)
176 ;; implement the voltage measuring current source
177 ;; imagine yourself copying the voltage of a voltage source with an internal
178 ;; impedance, spice starts complaining about unconnected nets if this current
179 ;; source is not here.
180 (display (string-append "Imeasure_" package " ") port)
181 (spice:write-two-pin-names package "3" "4" port)
182 (display "dc 0\n" port)
183 ;; with an output current source it is possible to leave the output voltage source
184 ;; unconnected i.e. spice won't complain about unconnected nodes
185 (display (string-append "Iout_" package " ") port)
186 (spice:write-two-pin-names package "1" "2" port)
187 (display "dc 0\n" port)
188 (display "* end of nullor expansion\n" port))))
193 ;; write all listed and available attributes in the form of <variable>=<value>
195 (define spice:write-list-of-attributes
196 (lambda (package attrib-list port)
197 (if (not (null? attrib-list))
199 ; Is it possible to make no differentiation between upper and lower case?
200 ; That relieves you of mixed case forms e.g. As, AS, as..., they are the
201 ; same attributes, spice3f5 is case insensitive. And other spice versions?
202 (if (not (string=? (gnetlist:get-package-attribute package (car attrib-list)) "unknown"))
203 (display (string-append " " (car attrib-list) "="
204 (gnetlist:get-package-attribute package (car attrib-list))) port))
205 (spice:write-list-of-attributes package (cdr attrib-list) port)))))
209 ;; write mos transistor
211 (define spice:write-mos-transistor
212 (lambda (package port)
213 (spice:write-one-component package port)
214 ;; create list of attributes which can be attached to a mosfet
215 (let ((attrib-list (list "l" "w" "as" "ad" "pd" "ps" "nrd" "nrs" "temp" "ic")))
216 (spice:write-list-of-attributes package attrib-list port))
217 ;; write the off attribute separately
218 (let ((off-value (gnetlist:get-package-attribute package "off")))
219 (cond ((string=? off-value "#t") (display " off" port))
220 ((string=? off-value "1" ) (display " off" port))))
225 ;; Given a uref, returns the device associated nets(s) ordered by their pin#,
226 ;; what when not defined?
227 ;; problem is slotted components e.g. ../examples/singlenet_1.sch
229 (define spice:write-net-name-of-component
230 (lambda (uref number-of-pin port)
231 (if (> number-of-pin 0)
233 ;; first find pin1 and then start writing the connected net name
234 (spice:write-net-name-of-component uref (- number-of-pin 1) port)
235 ;; generate a pin-name e.g. pin1, pin2, pin3 ...
236 (let ((pin-name (number->string number-of-pin)))
237 (display (car (spice:get-net uref (gnetlist:get-attribute-by-pinseq uref pin-name "pinnumber"))) port)
238 (write-char #\space port))))))
242 ;; Given a uref, returns the device attribute value as string
244 (define spice:component-value
246 (let ((value (gnetlist:get-package-attribute package "value")))
247 (if (not (string=? value "unknown"))
249 "<No valid value attribute found>"))))
255 (define spice:write-include
256 (lambda (package port)
257 (display (string-append package " " (spice:component-value package) "\n") port)))
261 ;; write the uref, the net name connected to pin# and the component value. No extra attributes.
263 (define spice:write-one-component
264 (lambda (package port)
265 (display (string-append package " ") port)
266 ;; write net names, slotted components not implemented
267 (spice:write-net-name-of-component package (length (gnetlist:get-pins package)) port)
268 ;; write component value, if components have a label "value=#"
269 ;; what if a component has no value label, currently unknown is written
270 (display (spice:component-value package) port)))
274 ;; write the uref, to the pin# connected net and component value and optional extra attributes
275 ;; check if the component is a special spice component
277 (define spice:write-netlist
280 (let ((package (car ls))) ;; search for specific device labels
282 ( (string=? (get-device package) "SPICE-ccvs")
283 (spice:write-ccvs package port))
284 ( (string=? (get-device package) "SPICE-cccs")
285 (spice:write-cccs package port))
286 ( (string=? (get-device package) "SPICE-vcvs")
287 (spice:write-vcvs package port))
288 ( (string=? (get-device package) "SPICE-vccs")
289 (spice:write-vccs package port))
290 ( (string=? (get-device package) "SPICE-nullor")
291 (spice:write-nullor package port))
292 ( (string=? (get-device package) "PMOS_TRANSISTOR")
293 (spice:write-mos-transistor package port))
294 ( (string=? (get-device package) "NMOS_TRANSISTOR")
295 (spice:write-mos-transistor package port))
296 ( (string=? (get-device package) "include")
297 (spice:write-include package port))
298 ( else (spice:write-one-component package port)
300 (spice:write-netlist port (cdr ls)) ))))
304 ;; Spice netlist header
306 (define spice:write-top-header
308 (display "* Spice netlister for gnetlist\n" port)))
312 ;; Write the .END line
314 (define spice:write-bottom-footer
316 (display ".END" port)
320 ;; Spice netlist generation
323 (lambda (output-filename)
324 (let ((port (open-output-file output-filename)))
326 ;; (gnetlist:set-netlist-mode "SPICE")
327 (spice:write-top-header port)
328 (spice:write-netlist port packages)
329 (spice:write-bottom-footer port)
330 (close-output-port port))))
333 ;; SPICE netlist backend written by S. Gieltjes ends here
335 ;; --------------------------------------------------------------------------