added nofill layers, refactor code

This commit is contained in:
Julian Daube 2018-12-11 15:52:37 +01:00
parent c6499cab23
commit 4f25a4a4aa

View File

@ -12,7 +12,6 @@ debug = nil
; DEBUG output function, uncomment to get all output ; DEBUG output function, uncomment to get all output
(procedure output( @rest args) (procedure output( @rest args)
(when debug (apply 'printf args)) (when debug (apply 'printf args))
;()
) )
; VECTOR HELPER FUNCTIONS ; VECTOR HELPER FUNCTIONS
@ -63,6 +62,33 @@ debug = nil
result result
) )
; Tests if a float x is zero in respect to the manufacturing grid
; (smaller then one grid spacing)
(defun ind_isZero (x)
abs(x)<1/mfgGrid
)
; return the sign of the input
; (ind_sign 20) = 1
; (ind_sign -10) = -1
; (ind_sign 0) = 0
(defun ind_sign (x)
(if ind_isZero(x)
then 0
else
(if (x > 0)
then 1
else -1
)
)
)
; only returns vectors with their sign as components
; e.g. (cleanupDirVect 0.1:-20) == 1:-1
(defun cleanDirVect (vect)
(ind_sign car(vect)):(ind_sign cadr(vect))
))
; DRAWING HELPER FUNCTIONS ; DRAWING HELPER FUNCTIONS
; creates a pin using database functions ; creates a pin using database functions
; and a corresponding net with name name ; and a corresponding net with name name
@ -145,20 +171,22 @@ debug = nil
; Creates the start of the inductor ; Creates the start of the inductor
; and places a pin there ; and places a pin there
(defun ind_createStart (id start width dir) (defun ind_createStart (id start width dir)
center = start; (addVect start multVect((invVect dir) width/2)) (let (center points)
center = start; (addVect start multVect((invVect dir) width/2))
points = list(
(addVect center (-width):width) points = list(
(addVect center width:width) (addVect center (-width):width)
(addVect center width:(-width)) (addVect center width:width)
(addVect center (-width):(-width)) (addVect center width:(-width))
(addVect center (-width):(-width))
)
(ind_createPin
id
"outer"
points
list("TopMetal2" "drawing")
)
) )
/*(ind_createPin
id
"outer"
points
list("TopMetal2" "drawing")
)*/
) )
; creates one segment of the inductor and calls itself recursively to complete ; creates one segment of the inductor and calls itself recursively to complete
@ -201,7 +229,7 @@ debug = nil
isend = (n < 1) isend = (n < 1)
; DEBUG ; DEBUG
output("seg: %d, n: %L (start: %L, end: %L)\n", mod(seg, nseg), n, isstart, isend) (output "seg: %d, n: %L (start: %L, end: %L)\n", mod(seg, nseg), n, isstart, isend)
when(isend when(isend
l = (lenVect dir) l = (lenVect dir)
@ -238,8 +266,9 @@ debug = nil
) )
) )
when(isstart ind_createStart(id start whalv ndir)) ; FIXME: broken, and underpass is not generated anyway
when((n<=1) ind_createEnd(id end whalv ndir)) ;when(isstart ind_createStart(id start whalv ndir))
;when((n<=1) ind_createEnd(id end whalv ndir))
n -= 1 n -= 1
(output "n=%L\n", n) (output "n=%L\n", n)
@ -249,74 +278,110 @@ debug = nil
) ; when ) ; when
) )
defun(ind_gndshield (r width pitch gap window)
(output "draw gnd shield with r=%L and w=%L\n", r, width)
r2 = r + width (defun ind_drawOctagon (r w1 w2 layer shorting)
m = 1/tan(mconst.PI/nseg) (let (a b start end)
segw = 2*r/m ; define start
pitch += width a = (snap r*tanalpha)
; a = (floor r*tanalpha*mfgGrid)/(0.25*mfgGrid)
(defun iszero (x) b = (snap r)
abs(x) < 1/mfgGrid
) start = 0:0
end = 0:0
(defun sign (x)
(if iszero(x)
then 0
else
(if (x > 0)
then 1
else -1
)
)
)
(defun cleanup (vect)
(sign car(vect)):(sign cadr(vect))
)
for(n 0 nseg-1
angle = mconst.PI*2/nseg * n
rotmat = list(
list(cos(angle) -sin(angle))
list(sin(angle) cos(angle))
)
w1 = width (for n 0 8
w = w1 (let (w)
(when ((mod n 2) == 1) w = (if mod(n 2)==1 then w2 else w1)
w2 = w1*sqrt(2)
w= w2
)
w1 = (snap w1)
w2 = (snap w2)
w = (snap w)
; contact_ring = append(contact_ring list(list(r2*cos(angle-mconst.PI/nseg) r2*sin(angle-mconst.PI/nseg))))
for(y 0 floor(segw/(2*pitch))
yr = (snap y*pitch)
a = (snap min(yr*m + gap, r))
l = (r-a)
(case n
(0
start = -a:b
end = a:b
)
(1
start = b:-a
end = a:-b
)
(2
start = b:-a
end = b:a
)
(3
start = a:b
end = b:a
)
(4
start = a:-b
end = -a:-b
)
(5
start = -a:-b
end = -b:-a
)
(6
start = -b:-a
end = -b:a
)
(7
start = -b:a
end = (addVect -a:b -shorting:-shorting)
)
)
; draw ring segment
(apply 'dbCreatePathSeg
id
gndshield_layer
start
end
w
if(mod(n 2)==0
then list(
"truncate"
"truncate"
list(0 0)
)
else list(
"custom"
(if n==7 then "truncate" else "custom")
list(
w1/2
(if n==7 then 0 else w1/2)
list(w1/2 w1/2 w2/2 w1/2 w1/2 w2/2)
)
)
)
) ; END apply
) ; END let
) ; END for
)
)
(defun ind_gndshield2 (yr)
(let (a l)
a = min((yr*m + gap) r)
l = (r-a)
when(l>0
; DEBUG
(output "(r=%L, m=%L, w=%L) yr=%L, a=%L, length=%L\n" m r w yr a l)
(when ((mod n 2) == 1) (when ((mod n 2) == 1)
l /= sqrt(2) l /= sqrt(2)
) )
l = (snap l)
dir = (cleanup matmult(rotmat 0:-1)) l = (snap l)
dir = (cleanDirVect matmult(rotmat 0:-1))
(output "%P\n", dir)
start = matmult(rotmat yr:r) start = matmult(rotmat yr:r)
; start = (snap (car start)):(snap (cadr start))
start = (floor((car start)*50.0)/50.0):(floor((cadr start)*50.0)/50.0) start = (floor((car start)*50.0)/50.0):(floor((cadr start)*50.0)/50.0)
end = (addVect start (multVect dir l)) end = (addVect start (multVect dir l))
; DEBUG
(output "start=%P, end=%P (dir=%P)\n" start end dir)
(dbCreatePathSeg (dbCreatePathSeg
id id
gndshield_layer gndshield_layer
@ -326,11 +391,13 @@ defun(ind_gndshield (r width pitch gap window)
"truncate" "truncate"
"truncate" "truncate"
) )
when(y != 0 when(yr != 0
; DEBUG
(output "create mirror at y=%L\n" -yr)
start = -car(start):cadr(start) start = -car(start):cadr(start)
end = -car(end):cadr(end) end = -car(end):cadr(end)
dbCreatePathSeg( dbCreatePathSeg(
id id
gndshield_layer gndshield_layer
@ -341,122 +408,187 @@ defun(ind_gndshield (r width pitch gap window)
"truncate" "truncate"
) )
) )
) ; for
a = (floor r/m*mfgGrid/2)/(0.5*mfgGrid)
b = (snap r)
start = 0:0 (ind_gndshield2 yr+pitch)
end = 0:0 ) ; END when
(print n) ) ; END let
)
(case n (defun ind_gndshield (r w1 w2 pitch gap window)
(0 (let (n w)
start = -a:b for(n 0 nseg-1
end = a:b ; DEBUG
) angle = mconst.PI*2/nseg * n
(1 rotmat = list(
start = b:-a list(cos(angle) -sin(angle))
end = a:-b list(sin(angle) cos(angle))
)
(2
start = b:-a
end = b:a
)
(3
start = a:b
end = b:a
)
(4
start = a:-b
end = -a:-b
)
(5
start = -a:-b
end = -b:-a
)
(6
start = -b:-a
end = -b:a
)
(7
start = -b:a
end = (addVect -a:b -window:-window)
)
)
; draw contact ring
(apply 'dbCreatePathSeg
id
gndshield_layer
start
end
w
if(mod(n 2)==0
then list(
"truncate"
"truncate"
list(0 0)
)
else list(
"custom"
(if n==7 then "truncate" else "custom")
list(
w1/2
(if n==7 then 0 else w1/2)
list(w1/2 w1/2 w2/2 w1/2 w1/2 w2/2)
)
)
) )
)
) w = if((mod n 2)==1 then w2 else w1)
(output "draw a gndshield part with w=%L\n" w)
(ind_gndshield2 0)
) ; END for
) )
) )
; uses ind_drawSegment to create a complete inductor with ; uses ind_drawSegment to create a complete inductor with
; the given specification ; the given specification
defun(drawInductor (n r width pitch) defun(drawInductor (n r width pitch)
; the PCell cell view id (let (id w whalv w2 w2halv ahalv talpha hl nseg)
id = pcCellView ; the PCell cell view id
id = pcCellView
(when (not id)
(error "could not find cell view") (when (not id)
) ; when (error "could not find cell view")
) ; when
; set multiple globals
inductorLayer = '("TopMetal2", "drawing") ; set multiple globals
underpassLayer = '("TopMetal1", "drawing") inductorLayer = '("TopMetal2", "drawing")
output("generating inductor with r=%L, turns=%L, pitch=%L and width=%L\n" r n pitch width) underpassLayer = '("TopMetal1", "drawing")
output("generating inductor with r=%L, turns=%L, pitch=%L and width=%L\n" r n pitch width)
whalv = snap(width/2)
w = whalv*2 whalv = snap(width/2)
; diagonal segment width w = whalv*2
w2halv = snap(width*sqrt(2)/2) ; diagonal segment width
w2 = 2*w2halv w2halv = snap(width*sqrt(2)/2)
w2 = 2*w2halv
pitch = snap(pitch + w) ; pitch from segment sides pitch = snap(pitch + w) ; pitch from segment sides
r = snap(r - whalv) ; middle radius r = snap(r - whalv) ; middle radius
nseg = 8 ; octagonal inductor nseg = 8 ; octagonal inductor
; calculation globals ; calculation globals
ahalv = mconst.PI/nseg ; angle between segments ahalv = mconst.PI/nseg ; angle between segments
talpha = tan(ahalv) talpha = tan(ahalv)
hl = snap((r-w/2)*talpha) ; start point hl = snap((r-w/2)*talpha) ; start point
; draw inductor ; draw inductor
(ind_drawSegment id n*nseg 0 -hl:r r) (let (dir)
(ind_drawSegment id n*nseg 0 -hl:r r)
)
)
) )
(defun drawGndShield (r pitch width window) (defun drawGndShield (r layer pitch width window)
; setup gndshield ; setup gndshield
id = pcCellView (let (id gndshield_layer nseg dir tanalpha m w1 w2 ymax)
gndshield_layer = '("Metal1" "drawing") r -= (snap width/2)
nseg = 8 w1 = (snap width*1.0)
w2 = (snap width*1.0*sqrt(2))
(ind_gndshield r pitch width width*2 (snap window)) id = pcCellView
gndshield_layer = layer
nseg = 8
tanalpha = tan(mconst.PI/nseg)
segw = r/2.0*tanalpha
pitch += width
m = 1/tanalpha
ymax = floor(segw/(2*pitch))
(output "draw gnd shield with nfins=%L, r=%L, segw=%L, segcount=%L and w=%L on %L\n" ymax r segw (floor segw/(2*pitch)) width gndshield_layer)
; draw the gndshield itself
(ind_gndshield r w1 w2 pitch width*2 (snap window))
; draw contact ring
(ind_drawOctagon r w1 w2 gndshield_layer window)
)
)
(defun ind_getOctagonPoints (r w1 w2 shorting)
(let (a b start end)
; define start
a = (floor r*tan(mconst.PI/8)*mfgGrid*0.5)/(0.5*mfgGrid)
b = (snap r)
start = 0:0
end = 0:0
result=list()
(for n 0 8
(let (w)
w = (if mod(n 2)==1 then w2 else w1)
(case n
(0
start = -a:b
end = a:b
)
(1
start = a:b
end = b:a
)
(2
start = b:a
end = b:-a
)
(3
start = b:-a
end = a:-b
)
(4
start = a:-b
end = -a:-b
)
(5
start = -a:-b
end = -b:-a
)
(6
start = -b:-a
end = -b:a
)
(7
start = -b:a
end = (addVect -a:b -shorting:-shorting)
)
)
result=(append result list(list(start end w)))
)
)
)
result
)
(defun ind_segmentsToPolygon (seg)
(output "segments=%L\n" seg)
result = list(caar(seg))
seg = cdr(seg)
(when seg
result = (append result (ind_segmentsToPolygon seg))
)
result
)
(defun drawBlockLayer (points layers)
(let (layer)
layer = car(layers)
layers = cdr(layers)
; DEBUG
(output "draw block layer %L\n", layer)
(dbCreatePolygon
pcCellView
layer
points
)
(when layers
(drawBlockLayer points layers)
)
)
)
(defun drawBlockLayers (r layers)
points = (ind_segmentsToPolygon (ind_getOctagonPoints r 0 0 0))
(output "polygon points %L\n", points)
(drawBlockLayer points layers)
) )
(defun setup () (defun setup ()
@ -471,20 +603,38 @@ defun(drawInductor (n r width pitch)
list( list(
( turns "float" 1.0 ) ( turns "float" 1.0 )
( radius "float" 100.0 ) ( radius "float" 100.0 )
( width "float" 2.1 ); techGetSpacingRule(techGetTechFile(pcCellView) "minWidth" "TopMetal2" )) ( width "float" 2.1 )
( pitch "float" 2.1 ) ( pitch "float" 2.1 )
; gndshield parameters
( gndshield "boolean" nil ) ( gndshield "boolean" nil )
( gndpitch "float" 2.1 ) ( gndpitch "float" 2.1 )
( gndwidth "float" 2.1 ) ( gndwidth "float" 2.1 )
( gndoverlap "float" 3 ) ( gndoverlap "float" 3 )
( gndwindow "float" 2.1 ) ( gndwindow "float" 2.1 )
; layer setup
( blockLayers "ilList" '(
("Metal1" "nofill")
("Metal2" "nofill")
("Metal3" "nofill")
("TopMetal1" "nofill")
("TopMetal2" "nofill")
("GatPoly" "nofill")
("Activ" "nofill")
("PWell" "block")
)
)
( gndShieldLayer "ilList" '("Metal1" "drawing"))
) )
(let (let
() ()
(setup) (setup)
; (print blockLayers)
(drawInductor turns radius width pitch) (drawInductor turns radius width pitch)
(when gndshield (when gndshield
(drawGndShield radius+gndoverlap gndwidth gndpitch gndwindow) (drawGndShield radius+gndoverlap gndShieldLayer gndwidth gndpitch gndwindow)
)
(when blockLayers
(drawBlockLayers radius+gndoverlap blockLayers)
) )
) )
) )