magic/lisp/scm/stack.scm

518 lines
14 KiB
Scheme

;-------------------------------------------------------------------------
;
; Transistor stacks
;
; (c) 1996 California Institute of Technology
; Department of Computer Science
; Pasadena, CA 91125.
;
; Permission to use, copy, modify, and distribute this software
; and its documentation for any purpose and without fee is hereby
; granted, provided that the above copyright notice appear in all
; copies. The California Institute of Technology makes no representations
; about the suitability of this software for any purpose. It is
; provided "as is" without express or implied warranty. Export of this
; software outside of the United States of America may require an
; export license.
;
; $Id: stack.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
;
;-------------------------------------------------------------------------
(define stack.p ())
(define stack.n ())
(define stack.tallp ())
(define stack.talln ())
(letrec
(
(flush-left-contacts 0) ; # of contacts that were placed
; flush left in the middle of a
; stack
;------------------------------------------------------------------------
; The height of the transistor stack, assuming that the poly wires were
; not jogged and that there were no contacts in the middle of the
; stack.
;------------------------------------------------------------------------
(height-raw
(lambda (num-transistors type)
(+ (+ (* (- num-transistors 1)
(+ (drc.min-spacing "poly") (drc.min-width "poly"))
)
(* 2 (drc.min-overhang (string-append "gate-"
(string-append type "diff")
)
)
)
)
(drc.min-width "poly")
)
)
)
;------------------------------------------------------------------------
; The height of the transistor stack
;------------------------------------------------------------------------
(height
(lambda (num-transistors type)
(+ (height-raw num-transistors type)
(* flush-left-contacts (- (+ (* 2 (drc.min-spacing "contact-gate"))
(drc.min-width "contact")
)
(drc.min-spacing "poly")
)
)
)
)
)
;------------------------------------------------------------------------
; Draw a poly wire. The wire jogs around contacts and is spaced so that
; there all the diffusion between the contact/poly/poly is squished out.
; Returns the new position of "dx"
;------------------------------------------------------------------------
(draw-poly
(lambda (name dx y fullwidth a0 a1 a2 a3)
(let* ((cur (getbox))
(nx (+ (car cur) dx))
(cury (cadr cur))
)
(begin
(if (>? dx a2)
(begin
(box (car cur) cury (+ (car cur) fullwidth) (+ cury a3))
(paint "poly")
)
(begin
(box (car cur) cury (+ nx a0) (+ cury a3))
(paint "poly")
(box (+ nx a1) (- cury y) (+ nx a0) cury)
(paint "poly")
(box (+ nx a1) (- cury y)
(+ (car cur) fullwidth) (+ (- cury y) a3)
)
(paint "poly")
)
)
(eval (cons 'box cur))
(if (positive? (string-length name))
(label.draw name "poly")
()
)
(box (car cur) (+ cury a0) (car cur) (+ cury a0))
(+ dx a0)
)
)
)
)
;------------------------------------------------------------------------
; Draw a contact. Placed in the "notch" of a poly wire if possible, or
; placed flush left. Returns the new "dx" value.
;------------------------------------------------------------------------
(draw-contact
(lambda (name dx y a0 a1 a2 a3 a4 a5 yinc newdx type lastcontact big)
(let* ((cur (getbox))
(nx (+ (car cur) dx))
(cury (cadr cur))
)
(begin
(if (>? dx a0)
(begin
(set! flush-left-contacts
(+ flush-left-contacts (if lastcontact 0 1))
)
(box (+ (car cur) a4) (+ (- cury a5) a1)
(+ (+ (car cur) a4) a2) (+ (- cury a5) a3)
)
(paint type)
(if (positive? (string-length name))
(label.draw name type)
()
)
(box (car cur) (+ cury y) (car cur) (+ cury y))
(if lastcontact big newdx)
)
(begin
(box (+ nx a1) (+ (- (- cury y) a5) a1)
(+ nx a3) (+ (- (- cury y) a5) a3))
(paint type)
(if (positive? (string-length name))
(label.draw name type)
()
)
(box (car cur) cury (car cur) cury)
(if lastcontact dx (+ dx y))
)
)
)
)
)
)
;------------------------------------------------------------------------
; Actually draws the stacks. c-name is either "pdc" or "ndc", depending
; on the type of stack.
;------------------------------------------------------------------------
(drawing-aux
(let* (
(ca1 (drc.min-spacing "contact-gate"))
(ca2 (drc.min-width "contact"))
(ca3 (+ ca1 ca2))
(ca4 (drc.min-overhang "poly-gate"))
(ca5 (drc.min-spacing "poly"))
(ca6 (drc.min-width "poly"))
(dxp (drc.min-overhang "pdiff-gate"))
(dxn (drc.min-overhang "ndiff-gate"))
(y (max 0 (+ ca2 (- (* 2 ca1) ca5))))
)
(lambda (nl gw dx c-name)
(if (null? nl)
(list dx y)
(drawing-aux
(cdr nl) gw
(if (list? (car nl))
(draw-contact (caar nl) dx y (- (- gw ca1) ca2)
ca1 ca2 ca3 ca4 ca5
(+ ca5 ca6)
(- (+ ca4 ca3) ca5)
c-name (null? (cdr nl)) (+ gw ca4)
)
(draw-poly (car nl) dx y (+ gw ca4)
(+ ca5 ca6) ca5
(- (- gw (+ ca5 ca6))
(if (=? (string-ref c-name 0)
(string-ref "p" 0)
)
dxp
dxn))
ca6)
)
c-name
)
)
)
)
)
;------------------------------------------------------------------------
; Returns the number of gates in the stack.
;------------------------------------------------------------------------
(count-gates
(lambda (l)
(if (null? l) 0
(+ (count-gates (cdr l)) (if (list? (car l)) 0 1))
)
)
)
;------------------------------------------------------------------------
; Draws the transistor stacks and paints the diffusion layers.
;------------------------------------------------------------------------
(pn
(lambda (name-list gate-width type)
(let* ((dx-y
(begin (box.push (getbox))
(set! flush-left-contacts 0)
(if (list? (car name-list))
(begin
(box.move 0
(- (drc.min-overhang
(string-append
"gate-"
(string-append type "diff"))
)
(+ (drc.min-width "contact")
(drc.min-spacing "contact-gate")
)
)
)
(draw.layer (string-append type "dc")
(drc.min-width "contact")
(drc.min-width "contact")
)
(if (positive? (string-length (caar name-list)))
(label.draw (caar name-list) (string-append type "dc"))
()
)
(box.move (uminus (drc.min-overhang "gate-poly"))
(+ (drc.min-width "contact")
(drc.min-spacing "contact-gate")
)
)
(drawing-aux (cdr name-list)
(+ gate-width
(drc.min-overhang "gate-poly")
)
gate-width
(string-append type "dc")
)
)
(begin
(box.move (uminus (drc.min-overhang "gate-poly"))
(drc.min-overhang "gate-pdiff")
)
(drawing-aux name-list
(+ gate-width
(drc.min-overhang "gate-poly")
)
gate-width
(string-append type "dc")
)
)
)
)
)
(dx (car dx-y))
(y (cadr dx-y))
(strip (+ (- dx (drc.min-overhang "poly-gate"))
(drc.min-overhang (string-append type "diff-gate"))
))
)
(begin
(box.pop)
(define ret-box
(draw.layer (string-append type "diff") (min strip gate-width)
(height (count-gates name-list) type))
)
(if (<? strip gate-width)
(begin
(box.move strip 0)
(define ret-2
(draw.layer (string-append type "diff")
(- gate-width strip)
(- (height (count-gates name-list) type)
y)
)
)
(set! ret-box
(list
(min (car ret-box) (car ret-2))
(min (cadr ret-box) (cadr ret-2))
(max (caddr ret-box) (caddr ret-2))
(max (cadddr ret-box) (cadddr ret-2))
)
)
(box.move (uminus strip) 0)
)
#t
)
ret-box
)
)
)
)
;------------------------------------------------------------------------
; Counts all the internal contacts if passed the stack with the first
; contact missing
;------------------------------------------------------------------------
(count-all-but-last-contacts
(lambda (stack)
(if (null? (cdr stack)) 0
(+ (if (list? (car stack)) 1 0) (count-all-but-last-contacts
(cdr stack))
)
)
)
)
;------------------------------------------------------------------------
; Draws straight poly
;------------------------------------------------------------------------
(draw-unjogged-contact-poly
(let ((sz (drc.min-width "contact"))
(sz2 (drc.min-spacing "contact-gate"))
(sz3 (drc.min-spacing "poly"))
(sz4 (drc.min-overhang "gate-poly"))
(sz5 (drc.min-width "poly"))
)
(lambda (name-list type w last)
(if (null? name-list) #t
(begin
(if (list? (car name-list))
(begin
(box.move 0 sz2)
(draw.layer (string-append type "dc") sz sz)
(if (positive? (string-length (caar name-list)))
(label.draw (caar name-list) (string-append type "dc"))
#t
)
(box.move 0 sz)
(draw-unjogged-contact-poly (cdr name-list) type w #t)
)
(begin
(box.move (uminus sz4) (if last sz2 sz3))
(draw.layer "poly" w sz5)
(if (positive? (string-length (car name-list)))
(label.draw (car name-list) "poly")
#t
)
(box.move sz4 sz5)
(draw-unjogged-contact-poly (cdr name-list) type w #f)
)
)
)
)
)
)
)
;------------------------------------------------------------------------
; Draw stack without squished diffusion
;------------------------------------------------------------------------
(pntall
(lambda (name-list gate-width type)
(begin
(box.push (getbox))
(define x (- (count-gates name-list) 1))
(define y (count-all-but-last-contacts (cdr name-list)))
(define ht (+
(+
(* x (+ (drc.min-spacing "poly") (drc.min-width "poly"))
)
(drc.min-width "poly")
)
(+
(* 2 (drc.min-overhang (string-append type "diff-gate")))
(* y (+ (drc.min-width "contact")
(-
(* 2 (drc.min-spacing "contact-gate"))
(drc.min-spacing "poly")
)
)
)
)
)
)
(define ret-box
(draw.layer (string-append type "diff") gate-width ht)
)
(if (list? (car name-list))
(begin
(box.move
0
(- (drc.min-overhang (string-append type "diff-gate"))
(+ (drc.min-spacing "contact-gate")
(drc.min-width "contact"))
)
)
(draw.layer (string-append type "dc")
(drc.min-width "contact") (drc.min-width "contact")
)
(if (positive? (string-length (caar name-list)))
(label.draw (caar name-list) (string-append type "dc"))
#t
)
(box.move 0 (max (drc.min-width "contact")
(- (drc.min-overhang
(string-append type "diff-gate"))
(drc.min-spacing "contact-gate")
)
)
)
(draw-unjogged-contact-poly
(cdr name-list)
type
(+ (* 2 (drc.min-overhang "gate-poly")) gate-width)
#t
)
)
(begin
(box.move
0
(-
(drc.min-overhang (string-append type "diff-gate"))
(drc.min-spacing "poly")
)
)
(draw-unjogged-contact-poly
name-list
type
(+ (* 2 (drc.min-overhang "gate-poly")) gate-width)
#f
)
)
)
(box.pop)
ret-box
)
)
)
(is-a-stack?
(lambda (stk)
(cond ((null? stk) #t)
((string? (car stk)) (is-a-stack? (cdr stk)))
((list? (car stk))
(if (string? (caar stk)) (is-a-stack? (cdr stk)) #f)
)
(#t #f)
)
)
)
)
(begin
;------------------------------------------------------------------------
; Draw p-transistor stack, jogging poly to remove diffusion
;------------------------------------------------------------------------
(set! stack.p
(lambda (gate-width p-list)
(begin
(if (and (number? gate-width) (is-a-stack? p-list))
#t
(error "Usage: stack.p <num> stack-desc")
)
(pn p-list gate-width "p")
)
)
)
;------------------------------------------------------------------------
; Draw n-transistor stack, jogging poly to remove diffusion
;------------------------------------------------------------------------
(set! stack.n
(lambda (gate-width n-list)
(begin
(if (and (number? gate-width) (is-a-stack? n-list))
#t
(error "Usage: stack.n <num> stack-desc")
)
(pn n-list gate-width "n")
)
)
)
;------------------------------------------------------------------------
; Draw p-transistor stack, straight poly
;------------------------------------------------------------------------
(set! stack.tallp
(lambda (gate-width p-list)
(begin
(if (and (number? gate-width) (is-a-stack? p-list))
#t
(error "Usage: stack.tallp <num> stack-desc")
)
(pntall p-list gate-width "p")
)
)
)
;------------------------------------------------------------------------
; Draw n-transistor stack, straight poly
;------------------------------------------------------------------------
(set! stack.talln
(lambda (gate-width n-list)
(begin
(if (and (number? gate-width) (is-a-stack? n-list))
#t
(error "Usage: stack.talln <num> stack-desc")
)
(pntall n-list gate-width "n")
)
)
)
)
)