<> <> <> <> <> DIRECTORY CD USING [Layer, NewLayer, Number, Object, Position, Rect], CDAtomicObjects USING [AtomicObsSpecific, DrawList], CDBasics USING [highposition, minposition, NonEmpty], CMosB USING [lambda, ndif, nwell, pdif, pol, pwell], Rope USING [ROPE], Saguaro; SaguaroImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CMosB EXPORTS Saguaro ~ BEGIN OPEN Saguaro; <> gate: PUBLIC CD.Layer ~ CD.NewLayer [NIL, $gate]; pol: CD.Layer ~ CMosB.pol; ndif: CD.Layer ~ CMosB.ndif; pdif: CD.Layer ~ CMosB.pdif; nwell: CD.Layer ~ CMosB.nwell; pwell: CD.Layer ~ CMosB.pwell; lambda: CD.Number ~ CMosB.lambda; invalidTransistor: PUBLIC SIGNAL [msg: Rope.ROPE] ~ CODE; <> <> <> <> <> <> <> ExtractTransistor: PUBLIC PROC [obj: CD.Object] RETURNS [et: ExtractedTransistor] ~ BEGIN <> tClass: ATOM ~ obj.class.objectType; isNType: BOOL ~ (obj.layer = ndif); -- fix isNWell: BOOL; sep: CD.Number ~ lambda; extensionLength: CD.Number ~ 3 * lambda; -- ch1/ch2 extension [rule 6.3.18] rect, wellRect: CD.Rect; polList, difList, chList, difListSouth: LIST OF CD.Rect _ NIL; extL, extW: CD.Number; <> IF ISTYPE [obj.specific, CDAtomicObjects.AtomicObsSpecific] THEN FOR geom: CDAtomicObjects.DrawList _ NARROW [obj.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO SELECT geom.first.layer FROM pol => polList _ CONS [geom.first.r, polList]; ndif, pdif => difList _ CONS [geom.first.r, difList]; nwell, pwell => {wellRect _ geom.first.r; isNWell _ (geom.first.layer = nwell)}; ENDCASE => SIGNAL invalidTransistor ["Unknown transistor geometry"] ENDLOOP ELSE SIGNAL invalidTransistor ["Replace this old Chipmonk transistor"]; <> et _ NEW [ExXtr]; SELECT tClass FROM $C2Trans, $C2WellTrans => BEGIN -- straight transistors difRect, polRect, chRect, difExtRectNorth, difExtRectSouth, polExtEast, polExtWest: CD.Rect; difRect _ difList.first; polRect _ polList.first; chRect _ [difRect.x1, polRect.y1, difRect.x2, polRect.y2]; difExtRectNorth _ difExtRectSouth _ difRect; difExtRectNorth.y1 _ polRect.y2; difExtRectSouth. y2 _ polRect.y1; polExtWest _ [polRect.x1, polRect.y1, difRect.x1, polRect.y2]; polExtEast _ [difRect.x2, polRect.y1, polRect.x2, polRect.y2]; et.length _ polRect.y2 - polRect.y1; et.width _ difRect.x2 - difRect.x1; extL _ polRect.y1 - difRect.y1; extW _ difRect.x1 - polRect.x1; et.gate.area _ (et.width + 2*extW) * et.length; et.gate.perimeter _ (et.width + 2*extW + et.length) * 2; et.ch1.area _ et.ch2.area _ extL * et.width; et.ch1.perimeter _ et.ch2.perimeter _ 2 * extL + et.width; IF (extL < extensionLength) THEN SIGNAL invalidTransistor ["Extension length too small"]; et.gate.layout _ LIST [[polExtEast, pol], [polExtWest, pol], [chRect, gate]]; et.ch1.layout _ LIST [[difExtRectNorth, obj.layer]]; et.ch2.layout _ LIST [[difExtRectSouth, obj.layer]]; et.length _ polRect.y2 - polRect.y1; et.width _ difRect.x2 - difRect.x1; IF tClass = $C2WellTrans THEN BEGIN l: CD.Layer ~ (IF isNWell THEN nwell ELSE pwell); -- fix IF NOT CDBasics.NonEmpty[wellRect] THEN SIGNAL invalidTransistor ["Well transistor must have a well"]; et.bulk.layout _ LIST [[wellRect, l]] END END; -- case $CTrans $C2LTrans, $C2LWellTrans => BEGIN -- angle transistors diffNE: CD.Position _ CDBasics.minposition; diffSW, polSW: CD.Position _ CDBasics.highposition; polHor, polVert, polExtWest, polExtNorth, chRectH, chRectV: CD.Rect; IF ((polList.first.y2-polList.first.y1) < (polList.rest.first.y2-polList.rest.first.y1)) THEN {polHor _ polList.first; polVert _ polList.rest.first} ELSE {polHor _ polList.rest.first; polVert _ polList.first}; FOR diff: LIST OF CD.Rect _ difList, diff.rest WHILE diff # NIL DO IF (diff.first.x1 <= diffSW.x) AND (diff.first.y1 <= diffSW.y) THEN diffSW _ [diff.first.x1, diff.first.y1]; IF (diff.first.x2 >= diffNE.x) AND (diff.first.y2 >= diffNE.y) THEN diffNE _ [diff.first.x2, diff.first.y2]; ENDLOOP; polSW _ [polHor.x1, polHor.y1]; extW _ diffSW.x - polSW.x; extL _ polSW.y - diffSW.y; et.length _ polHor.y2 - polHor.y1; et.width _ ((polHor.x2 - polHor.x1) - extW) + ((polVert.y2 - polVert.y1) - extW) - (et.length*3/2); et.gate.area _ ((et.width+et.length/2) + 2*extW) * et.length; et.gate.perimeter _ ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2; et.ch1.area _ ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL; et.ch1.perimeter _ 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y); et.ch2.perimeter _ diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + et.length); et.ch2.area _ et.ch2.perimeter * extL; IF (extL < extensionLength) THEN SIGNAL invalidTransistor ["Extension length too small"]; polExtWest _ [polSW.x, polSW.y, diffSW.x, polHor.y2]; polExtNorth _ [diffNE.x-extL-et.length, diffNE.y, diffNE.x-extL, polHor.y2]; chRectH _ polHor; chRectH.x1 _ chRectH.x1 + extW; chRectV _ polVert; chRectV.y1 _ chRectV.y1 + et.length; chRectV.y2 _ chRectV.y2 - extW; et.gate.layout _ LIST [[polExtWest, pol], [polExtNorth, pol], [chRectH, gate], [chRectV, gate]]; <> BEGIN -- Bogus but first approx. for a fast impl. d: CD.Number _ extL + et.length + sep; rect _ [x1: diffSW.x, y1: diffSW.y+extL+et.length, x2: diffNE.x-extL-et.length, y2: diffSW.y+d]; et.ch1.layout _ LIST [[rect, obj.layer]]; -- North rect _ [x1: diffNE.x-d, y1: diffSW.y+extL+et.length, x2: diffNE.x-extL-et.length, y2: diffNE.y]; et.ch1.layout _ CONS [[rect, obj.layer], et.ch1.layout]; -- West d _ extL - sep; rect _ [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+extL]; et.ch2.layout _ LIST [[rect, obj.layer]]; -- South rect _ [x1: diffNE.x-extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y]; et.ch2.layout _ CONS [[rect, obj.layer], et.ch2.layout] -- East END; -- gate lead-in <> IF tClass = $C2WellTrans THEN BEGIN l: CD.Layer ~ (IF isNWell THEN nwell ELSE pwell); -- fix IF NOT CDBasics.NonEmpty[wellRect] THEN SIGNAL invalidTransistor ["Well transistor must have a well"]; et.bulk.layout _ LIST [[wellRect, l]] END END; -- case $C2LTrans, $C2LWellTrans ENDCASE => SIGNAL invalidTransistor ["Unknown or antique transistor class"]; <> <> <> END; -- MakeTransistor <> END.