Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / gnetlist / scheme / gnet-spice.scm
blob0f5d5754e159b8810b1ef2c31f381396188f288c
1 ;;; gEDA - GPL Electronic Design Automation
2 ;;; gnetlist - gEDA Netlist
3 ;;; Copyright (C) 1998-2010 Ales Hvezda
4 ;;; Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
5 ;;;
6 ;;; This program is free software; you can redistribute it and/or modify
7 ;;; it under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 2 of the License, or
9 ;;; (at your option) any later version.
10 ;;;
11 ;;; This program is distributed in the hope that it will be useful,
12 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;; GNU General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with this program; if not, write to the Free Software
18 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 ;; --------------------------------------------------------------------------
22 ;; 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)))
37 ;;             (begin
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)
42 ;;        )
43 ;;      )
44 ;;    )
45 ;;  )
46 ;;)
50 ;; gnet-spice replacement of gnetlist:get-nets, a net labeled "GND" becomes 0 
52 (define spice:get-net
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)))
69     
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)            
77     ( begin
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)            
101     ( begin
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)            
121     ( begin
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)            
143     ( begin
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)            
170     ( begin
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))
198       (begin      
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))))
221     (newline 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)
232       (begin                                   
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
245   (lambda (package) 
246     (let ((value (gnetlist:get-package-attribute package "value"))) 
247       (if (not (string=? value "unknown"))
248         value
249         "<No valid value attribute found>"))))
253 ;; Include a file
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
278   (lambda (port ls)
279      (if (not (null? ls))
280       (let ((package (car ls)))                           ;; search for specific device labels
281         (cond   
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)
299                (newline port)))
300         (spice:write-netlist port (cdr ls)) ))))  
303 ;; 
304 ;; Spice netlist header
306 (define spice:write-top-header
307   (lambda (port)
308     (display "* Spice netlister for gnetlist\n" port)))
312 ;; Write the .END line
314 (define spice:write-bottom-footer
315   (lambda (port)
316     (display ".END" port)
317     (newline port)))
320 ;; Spice netlist generation
322 (define spice
323   (lambda (output-filename)
324     (let ((port (open-output-file output-filename)))
325 ;; No longer needed
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 ;; --------------------------------------------------------------------------