From 4f25a4a4aa7fa077ea3ca2ab031926a9936de63e Mon Sep 17 00:00:00 2001 From: Julian Daube Date: Tue, 11 Dec 2018 15:52:37 +0100 Subject: [PATCH] added nofill layers, refactor code --- inductor_2.il | 512 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 331 insertions(+), 181 deletions(-) diff --git a/inductor_2.il b/inductor_2.il index 964798d..03f4f06 100644 --- a/inductor_2.il +++ b/inductor_2.il @@ -12,7 +12,6 @@ debug = nil ; DEBUG output function, uncomment to get all output (procedure output( @rest args) (when debug (apply 'printf args)) - ;() ) ; VECTOR HELPER FUNCTIONS @@ -63,6 +62,33 @@ debug = nil 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 ; creates a pin using database functions ; and a corresponding net with name name @@ -145,20 +171,22 @@ debug = nil ; Creates the start of the inductor ; and places a pin there (defun ind_createStart (id start width dir) - center = start; (addVect start multVect((invVect dir) width/2)) - - points = list( - (addVect center (-width):width) - (addVect center width:width) - (addVect center width:(-width)) - (addVect center (-width):(-width)) + (let (center points) + center = start; (addVect start multVect((invVect dir) width/2)) + + points = list( + (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 @@ -201,7 +229,7 @@ debug = nil isend = (n < 1) ; 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 l = (lenVect dir) @@ -238,8 +266,9 @@ debug = nil ) ) - when(isstart ind_createStart(id start whalv ndir)) - when((n<=1) ind_createEnd(id end whalv ndir)) + ; FIXME: broken, and underpass is not generated anyway + ;when(isstart ind_createStart(id start whalv ndir)) + ;when((n<=1) ind_createEnd(id end whalv ndir)) n -= 1 (output "n=%L\n", n) @@ -249,74 +278,110 @@ debug = nil ) ; 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 - m = 1/tan(mconst.PI/nseg) - segw = 2*r/m - pitch += width - - (defun iszero (x) - abs(x) < 1/mfgGrid - ) - - (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)) - ) +(defun ind_drawOctagon (r w1 w2 layer shorting) + (let (a b start end) + ; define start + a = (snap r*tanalpha) +; a = (floor r*tanalpha*mfgGrid)/(0.25*mfgGrid) + b = (snap r) + + start = 0:0 + end = 0:0 - w1 = width - w = w1 - (when ((mod n 2) == 1) - 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) + (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 = 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) 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 = (snap (car start)):(snap (cadr start)) start = (floor((car start)*50.0)/50.0):(floor((cadr start)*50.0)/50.0) end = (addVect start (multVect dir l)) + ; DEBUG + (output "start=%P, end=%P (dir=%P)\n" start end dir) + (dbCreatePathSeg id gndshield_layer @@ -326,11 +391,13 @@ defun(ind_gndshield (r width pitch gap window) "truncate" "truncate" ) - - when(y != 0 + + when(yr != 0 + ; DEBUG + (output "create mirror at y=%L\n" -yr) start = -car(start):cadr(start) end = -car(end):cadr(end) - + dbCreatePathSeg( id gndshield_layer @@ -341,122 +408,187 @@ defun(ind_gndshield (r width pitch gap window) "truncate" ) ) - ) ; for - - a = (floor r/m*mfgGrid/2)/(0.5*mfgGrid) - b = (snap r) - start = 0:0 - end = 0:0 - (print n) + (ind_gndshield2 yr+pitch) + ) ; END when + ) ; END let +) - (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 -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) - ) - ) +(defun ind_gndshield (r w1 w2 pitch gap window) + (let (n w) + for(n 0 nseg-1 + ; DEBUG + angle = mconst.PI*2/nseg * n + rotmat = list( + list(cos(angle) -sin(angle)) + list(sin(angle) cos(angle)) ) - ) - ) + + 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 ; the given specification defun(drawInductor (n r width pitch) - ; the PCell cell view id - id = pcCellView - - (when (not id) - (error "could not find cell view") - ) ; when - - - ; set multiple globals - inductorLayer = '("TopMetal2", "drawing") - 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 - ; diagonal segment width - w2halv = snap(width*sqrt(2)/2) - w2 = 2*w2halv - - - pitch = snap(pitch + w) ; pitch from segment sides - r = snap(r - whalv) ; middle radius - nseg = 8 ; octagonal inductor - - ; calculation globals - ahalv = mconst.PI/nseg ; angle between segments - talpha = tan(ahalv) - hl = snap((r-w/2)*talpha) ; start point - - ; draw inductor - (ind_drawSegment id n*nseg 0 -hl:r r) + (let (id w whalv w2 w2halv ahalv talpha hl nseg) + ; the PCell cell view id + id = pcCellView + + (when (not id) + (error "could not find cell view") + ) ; when + + + ; set multiple globals + inductorLayer = '("TopMetal2", "drawing") + 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 + ; diagonal segment width + w2halv = snap(width*sqrt(2)/2) + w2 = 2*w2halv + + pitch = snap(pitch + w) ; pitch from segment sides + r = snap(r - whalv) ; middle radius + nseg = 8 ; octagonal inductor + + ; calculation globals + ahalv = mconst.PI/nseg ; angle between segments + talpha = tan(ahalv) + hl = snap((r-w/2)*talpha) ; start point + + ; draw inductor + (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 - id = pcCellView - gndshield_layer = '("Metal1" "drawing") - nseg = 8 + (let (id gndshield_layer nseg dir tanalpha m w1 w2 ymax) + r -= (snap width/2) + 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 () @@ -471,20 +603,38 @@ defun(drawInductor (n r width pitch) list( ( turns "float" 1.0 ) ( radius "float" 100.0 ) - ( width "float" 2.1 ); techGetSpacingRule(techGetTechFile(pcCellView) "minWidth" "TopMetal2" )) + ( width "float" 2.1 ) ( pitch "float" 2.1 ) + ; gndshield parameters ( gndshield "boolean" nil ) ( gndpitch "float" 2.1 ) ( gndwidth "float" 2.1 ) ( gndoverlap "float" 3 ) ( 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 () (setup) +; (print blockLayers) (drawInductor turns radius width pitch) (when gndshield - (drawGndShield radius+gndoverlap gndwidth gndpitch gndwindow) + (drawGndShield radius+gndoverlap gndShieldLayer gndwidth gndpitch gndwindow) + ) + (when blockLayers + (drawBlockLayers radius+gndoverlap blockLayers) ) ) )