DIRECTORY CD, NMos, NMosTransistors, NMosContacts, CDInstances, CDBasics, Recognizer, CornerStitching, CDOrient; NMosRecognizerImpl: CEDAR PROGRAM IMPORTS NMos, NMosTransistors, NMosContacts, CDInstances, Recognizer, CDBasics, CDOrient = BEGIN RegionList: TYPE = LIST OF REF CornerStitching.Region; ext: CD.Number = 2*NMos.lambda; cutExt: CD.Number = NMos.lambda; cutWidth: CD.Number = 2*NMos.lambda; cutMmWidth: CD.Number = 3*NMos.lambda; polyButtingExt: CD.Number = 3*NMos.lambda; --Starting from the uncovered poly edge of a butting contact, this is the distance from that edge to the start of the region where poly and diffusion overlap; pullupWidthFor2or3: CD.Number = 4*NMos.lambda; --The width of the butting contact contained in a pullup. If the width is less than this than a double or triple covered region list will result otherwise the pullup is wide enough so that only a single rect instance will result. SingleRectInstances: PROC [active1, active2: CD.Layer, coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN SELECT active1 FROM NMos.pol => IF active2 = NMos.dif THEN { SingleRectTransistors[coveredList, possibleInstListPtr]; SingleRectPullups[coveredList, possibleInstListPtr]; }; NMos.dif => IF active2 = NMos.pol THEN { SingleRectTransistors[coveredList, possibleInstListPtr]; SingleRectPullups[coveredList, possibleInstListPtr]; }; NMos.cut => IF active2 = NMos.met THEN SingleRectCutContacts[coveredList, possibleInstListPtr]; NMos.met => IF active2 = NMos.cut THEN SingleRectCutContacts[coveredList, possibleInstListPtr]; NMos.cut2 => IF active2 = NMos.met2 THEN SingleRectMmContacts[coveredList, possibleInstListPtr]; NMos.met2 => IF active2 = NMos.cut2 THEN SingleRectMmContacts[coveredList, possibleInstListPtr]; ENDCASE => NULL; END; SingleRectTransistors: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect: CD.Rect _ coveredList.first.rect; position: CD.Position _ CDBasics.BaseOfRect[rect]; xDistance: CD.Number _ rect.x2 - rect.x1; yDistance: CD.Number _ rect.y2 - rect.y1; forbiddenLayerList: LIST OF CD.Layer _ LIST [NMos.cut, NMos.bur]; newObject: CD.Object; newInst: CD.Instance; FOR impList: LIST OF NMosTransistors.Implant _ LIST[NMosTransistors.enhancement, NMosTransistors.strongDepletion], impList.rest WHILE impList #NIL DO position _ [position.x-ext, position.y-ext]; newObject _ NMosTransistors.CreateTransistor[w: xDistance, l: yDistance, implant: impList.first]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.original, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; newObject _ NMosTransistors.CreateTransistor[w: xDistance, l: yDistance, implant: impList.first]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate90, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; newObject _ NMosTransistors.CreateTransistor[w: yDistance, l: xDistance, implant: impList.first]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.original, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; newObject _ NMosTransistors.CreateTransistor[w: yDistance, l: xDistance, implant: impList.first]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate90, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; ENDLOOP; END; SingleRectPullups: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect: CD.Rect _ coveredList.first.rect; position: CD.Position _ CDBasics.BaseOfRect[rect]; xDistance: CD.Number _ rect.x2 - rect.x1; yDistance: CD.Number _ rect.y2 - rect.y1; newObject: CD.Object; newInst: CD.Instance; IF xDistance >= pullupWidthFor2or3 THEN { newObject _ NMosTransistors.CreatePullUp[w: xDistance, l: yDistance]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.original, location: [position.x-ext, position.y-ext]]; PlaceOnList[newInst, possibleInstListPtr]; newObject _ NMosTransistors.CreatePullUp[w: xDistance, l: yDistance]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate180, location: [position.x-ext, position.y-polyButtingExt]]; PlaceOnList[newInst, possibleInstListPtr]; }; IF yDistance >= pullupWidthFor2or3 THEN { newObject _ NMosTransistors.CreatePullUp[w: yDistance, l: xDistance]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate90, location: [position.x-polyButtingExt, position.y-ext]]; PlaceOnList[newInst, possibleInstListPtr]; newObject _ NMosTransistors.CreatePullUp[w: yDistance, l: xDistance]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate270, location: [position.x-ext, position.y-ext]]; PlaceOnList[newInst, possibleInstListPtr]; } END; SingleRectCutContacts: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect: CD.Rect _ coveredList.first.rect; position: CD.Position _ CDBasics.BaseOfRect[rect]; orient: CD.Orientation _ CDOrient.original; length: CD.Number _ rect.y2-rect.y1; forbiddenList: LIST OF CD.Layer _ LIST[NMos.imp]; IF length = cutWidth THEN { length _ rect.x2-rect.x1+2*cutExt; orient _ CDOrient.rotate90; }; position _ [position.x-cutExt, position.y-cutExt]; PlaceOnList[CDInstances.NewInstance[ob: NMosContacts.CreatePolyCon[l: length], location: position, orientation: orient], possibleInstListPtr]; PlaceOnList[CDInstances.NewInstance[ob: NMosContacts.CreateDifCon[l: length], location: position, orientation: orient], possibleInstListPtr]; FOR orient: CD.Orientation IN CD.Orientation DO IF ~CDOrient.IncludesMirrorX[orient] THEN { PlaceOnList[CDInstances.NewInstance[ob: NMosContacts.CreateButCon[], location: position, orientation: orient], possibleInstListPtr, forbiddenList]; } ENDLOOP; END; SingleRectMmContacts: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect: CD.Rect _ coveredList.first.rect; position: CD.Position _ CDBasics.BaseOfRect[rect]; orient: CD.Orientation _ CDOrient.original; length: CD.Number _ rect.y2-rect.y1; IF length = cutMmWidth THEN { length _ rect.x2-rect.x1; orient _ CDOrient.rotate90; }; IF length < 4*NMos.lambda THEN { --see NMosContactsImpl for why this is needed position _ [position.x-cutExt, position.y-cutExt]; length _ length+2*cutExt; } ELSE { position _ [position.x-2*cutExt, position.y-2*cutExt]; length _ length+4*cutExt; }; PlaceOnList[CDInstances.NewInstance[ob: NMosContacts.CreateMmCon[length], location: position, orientation: orient], possibleInstListPtr]; END; DoubleRectInstances: PROC [active1, active2: CD.Layer, coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN SELECT active1 FROM NMos.pol => IF active2 = NMos.dif THEN { DoubleRectAngleTransistors[coveredList, possibleInstListPtr]; DoubleRectPullups[coveredList, possibleInstListPtr]; }; NMos.dif => IF active2 = NMos.pol THEN { DoubleRectAngleTransistors[coveredList, possibleInstListPtr]; DoubleRectPullups[coveredList, possibleInstListPtr]; }; ENDCASE => NULL; END; DoubleRectAngleTransistors: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect1: CD.Rect _ coveredList.first.rect; rect2: CD.Rect _ coveredList.rest.first.rect; minX: CD.Number_ MIN[rect1.x1, rect2.x1]; minY: CD.Number _ MIN[rect1.y1, rect2.y1]; maxX: CD.Number _ MAX[rect1.x2, rect2.x2]; maxY: CD.Number _ MAX[rect1.y2, rect2.y2]; position: CD.Position _ [minX-ext, minY-ext]; forbiddenLayerList: LIST OF CD.Layer _ LIST [NMos.cut, NMos.bur]; IF rect1.x2-rect1.x1 = rect2.y2-rect2.y1 THEN { length: CD.Number _ rect1.x2-rect1.x1; width: CD.Number _ rect1.y2-rect1.y1+rect2.x2-rect2.x1-length; FOR orient: CD.Orientation IN CD.Orientation DO newObject: CD.Object _ NMosTransistors.CreateAngleTransistor[w: width, l: length]; newInst: CD.Instance _ CDInstances.NewInstance[ob: newObject, orientation: orient, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; ENDLOOP; }; IF rect1.y2-rect1.y1 = rect2.x2-rect2.x1 THEN { length: CD.Number _ rect1.y2-rect1.y1; width: CD.Number _ rect1.x2-rect1.x1+rect2.y2-rect2.y1-length; FOR orient: CD.Orientation IN CD.Orientation DO newObject: CD.Object _ NMosTransistors.CreateAngleTransistor[w: width, l: length]; newInst: CD.Instance _ CDInstances.NewInstance[ob: newObject, orientation: orient, location: position]; PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList]; ENDLOOP; }; END; DoubleRectPullups: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect1: CD.Rect _ coveredList.first.rect; rect2: CD.Rect _ coveredList.rest.first.rect; position: CD.Position; minX: CD.Number_ MIN[rect1.x1, rect2.x1]; minY: CD.Number _ MIN[rect1.y1, rect2.y1]; maxX: CD.Number _ MAX[rect1.x2, rect2.x2]; maxY: CD.Number _ MAX[rect1.y2, rect2.y2]; width: CD.Number; length: CD.Number; newObject: CD.Object; newInst: CD.Instance; IF minY = rect1.y1 THEN { width _ rect1.x2-rect1.x1; position.x _ rect1.x1-ext; } ELSE { width _ rect2.x2-rect2.x1; position.x _ rect2.x1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.y _ minY-ext; length _ maxY-minY; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.original, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF maxX = rect1.x1 THEN { width _ rect1.y2-rect1.y1; position.y _ rect1.y1-ext; } ELSE { width _ rect2.y2-rect2.y1; position.y _ rect2.y1_ext; }; IF width <= pullupWidthFor2or3 THEN { position.x _ minX-polyButtingExt; length _ maxX-minX; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate90, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF maxY = rect1.y1 THEN { width _ rect1.x2-rect1.x1; position.x _ rect1.x1-ext; } ELSE { width _ rect2.x2-rect2.x1; position.x _ rect2.x1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.y _ minY-polyButtingExt; length _ maxY-minY; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate180, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF minX = rect1.x1 THEN { width _ rect1.y2-rect1.y1; position.y _ rect1.y1-ext; } ELSE { width _ rect2.y2-rect2.y1; position.y _ rect2.y1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.x _ minX-ext; length _ maxX-minX; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate270, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; END; TripleRectInstances: PROC [active1, active2: CD.Layer, coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN SELECT active1 FROM NMos.pol => IF active2 = NMos.dif THEN TripleRectPullups[coveredList, possibleInstListPtr]; NMos.dif => IF active2 = NMos.pol THEN TripleRectPullups[coveredList, possibleInstListPtr]; ENDCASE => NULL; END; TripleRectPullups: PROC [coveredList: RegionList, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList] = BEGIN rect1: CD.Rect _ coveredList.first.rect; rect2: CD.Rect _ coveredList.rest.first.rect; rect3: CD.Rect _ coveredList.rest.rest.first.rect; position: CD.Position; minX: CD.Number_ MIN[MIN[rect1.x1, rect2.x1], rect3.x1]; minY: CD.Number _ MIN[MIN[rect1.y1, rect2.y1], rect3.y1]; maxX: CD.Number _ MAX[MAX[rect1.x2, rect2.x2], rect3.y1]; maxY: CD.Number _ MAX[MAX[rect1.y2, rect2.y2], rect3.y2]; width: CD.Number; length: CD.Number; newObject: CD.Object; newInst: CD.Instance; IF minY = rect1.y1 THEN { width _ rect1.x2-rect1.x1; position.x _ rect1.x1-ext; } ELSE IF minY = rect2.y1 THEN { width _ rect2.x2-rect2.x1; position.x _ rect2.x1-ext; } ELSE { width _ rect3.x2-rect3.x1; position.x _ rect3.x1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.y _ minY-ext; length _ maxY-minY; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.original, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF maxX = rect1.x1 THEN { width _ rect1.y2-rect1.y1; position.y _ rect1.y1-ext; } ELSE IF maxX = rect2.x1 THEN { width _ rect2.y2-rect2.y1; position.y _ rect2.y1-ext; } ELSE { width _ rect3.y2-rect3.y1; position.y _ rect3.y1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.x _ minX-polyButtingExt; length _ maxX-minX; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate90, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF maxY = rect1.y1 THEN { width _ rect1.x2-rect1.x1; position.x _ rect1.x1-ext; } ELSE IF maxY = rect2.y1 THEN { width _ rect2.x2-rect2.x1; position.x _ rect2.x1-ext; } ELSE { width _ rect3.x2-rect3.x1; position.x _ rect3.x1-ext; }; IF width <= pullupWidthFor2or3 THEN { position.y _ minY-polyButtingExt; length _ maxY-minY; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate180, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; IF minX = rect1.x1 THEN { width _ rect1.y2-rect1.y1; position.y _ rect1.y1-ext; } ELSE IF minX = rect2.x1 THEN { width _ rect2.y2-rect2.y1; position.y _ rect2.y1-ext; } ELSE { width _ rect3.y2-rect3.y1; position.y _ rect3.y2-ext; }; IF width <= pullupWidthFor2or3 THEN { position.x _ minX-ext; length _ maxX-minX; newObject _ NMosTransistors.CreatePullUp[w: width, l: length]; newInst _ CDInstances.NewInstance[ob: newObject, orientation: CDOrient.rotate270, location: position]; PlaceOnList[newInst, possibleInstListPtr]; }; END; PlaceOnList: PROC [instance: CD.Instance, possibleInstListPtr: REF Recognizer.InstAndForbidLayerList, forbiddenLayerList: LIST OF CD.Layer _ NIL] = BEGIN possibleInstListPtr^ _ CONS[NEW[Recognizer.InstAndForbidLayerRec _ [instance, forbiddenLayerList]], possibleInstListPtr^]; END; Recognizer.RegisterPossibleInstanceProc [NMos.nmos, 1, SingleRectInstances]; Recognizer.RegisterPossibleInstanceProc[NMos.nmos, 2, DoubleRectInstances]; Recognizer.RegisterPossibleInstanceProc[NMos.nmos, 3, TripleRectInstances]; Recognizer.RegisterLayerList[technology: NMos.nmos, active1: NMos.dif, active2: NMos.pol, layerList: LIST[NMos.cut, NMos.bur, NMos.imp, NMos.met]]; Recognizer.RegisterLayerList[technology: NMos.nmos, active1: NMos.cut, active2: NMos.met, layerList: LIST[NMos.pol, NMos.dif, NMos.imp]]; Recognizer.RegisterLayerList[technology: NMos.nmos, active1: NMos.cut2, active2: NMos.met2, layerList: LIST[NMos.met]]; END. zNMosRecognizerImpl.mesa The technology dependant part of recognizing objects Gbier, July 11, 1985 10:48:17 am PDT Gbier, August 2, 1985 5:01:42 pm PDT Jacobi, September 24, 1985 10:09:26 am PDT --Orientation 0 --Orientation 90 --Orientation180 --Orientation 270 --Orientation 0 --Orientation 90 --Orientation180 --Orientation 270 --places instance on possibleInstList Κ ι˜šœL™LJšœ$™$Jšœ$™$Icode™*—J˜J˜šΟk ˜ Jšœ˜J˜J˜J˜ J˜ J˜ Jšœ ˜ J˜Jšœ ˜ —J˜J˜šΟbœœ˜!JšœT˜[—Jš˜J˜Jš œ œœœœ˜6J˜Jšœœ˜Jšœœ˜ Jšœ œ˜$Jšœ œ˜&J˜JšœœΟcž˜ΚJšœœŸζ˜–J˜š žΠbn œœœ6œ&˜ŽJš˜šœ ˜˜ šœœ˜J˜8J˜4J˜——˜ šœ˜J˜8J˜4J˜——šœ ˜ šœ˜J˜8——šœ ˜ šœ˜J˜8——˜ šœ˜J˜7——˜ šœ˜J˜7——Jšœœ˜—Jšœ˜—J˜š œœ0œ%˜sJš˜Jšœœ˜'Jšœ œ'˜3J˜)J˜)Jš œœœœ œ˜AJšœ˜Jšœ œ ˜š œ œœœMœ œ˜•Jšœ,˜,Jšœa˜aJšœe˜eJ˜>Jšœa˜aJšœe˜eJ˜>Jšœa˜aJšœe˜eJ˜>Jšœa˜aJšœe˜eJ˜>Jšœ˜—Jšœ˜—J˜š œœ0œ&˜pJš˜Jšœœ˜'Jšœ œ'˜3Jšœ œ˜)Jšœ œ˜)Jšœ œ˜Jšœ œ ˜šœ!œ˜)JšœE˜EJšœ}˜}J˜*JšœE˜EJšœ‰˜‰J˜*J˜—šœ!œ˜)JšœE˜EJšœˆ˜ˆJ˜*JšœE˜EJšœ~˜~J˜*J˜—šœ˜J˜——š œœ0œ%˜sJš˜Jšœœ˜'Jšœ œ&˜2J˜+Jšœ$˜$J˜1˜J˜"J˜J˜—Jšœ2˜2JšœŽ˜Žšœ˜š œ œ œœ ˜/šœ#˜+Jšœ“˜“Jšœ˜—Jšœ˜——Jšœ˜—š œœ0œ%˜rJš˜Jšœœ˜'Jšœ œ&˜2Jšœœ!˜+Jšœœ˜$šœœ˜J˜J˜J˜—šœœŸ-˜OJšœ2˜2J˜J˜—š˜J˜Jšœ6˜6J˜J˜—Jšœ‰˜‰Jšœ˜—š œœœ6œ&˜ŽJš˜šœ ˜˜ šœœ˜J˜=J˜4J˜——˜ šœ˜J˜=J˜4J˜——Jšœœ˜—Jšœ˜—J˜šΟnœœ0œ%˜xJš˜Jšœœ˜(Jšœœ$˜-Jšœœ œ˜*Jšœœ œ˜*Jšœœ œ˜*Jšœœ œ˜*Jšœ.˜.Jš œœœœ œ˜A˜/J˜&J˜>š œ œ œœ ˜/Jšœ œE˜RJšœ œ\˜gJ˜>Jšœ˜—J˜—˜/J˜&J˜>š œ œ œœ ˜/Jšœ œE˜RJšœ œ\˜gJ˜>Jšœ˜—J˜—Jšœ˜—J˜š œœ0œ&˜pJš˜Jšœœ˜(J˜-Jšœ œ ˜Jšœœ œ˜*Jšœœ œ˜*Jšœœ œ˜*Jšœœ œ˜*J˜J˜Jšœ œ˜Jšœ œ ˜Jšœ™˜J˜J˜J˜—˜J˜J˜J˜—šœ&˜&J˜J˜Jšœ>˜>Jšœe˜eJ˜*J˜—Jšœ™˜J˜J˜J˜—˜J˜J˜J˜—šœ&˜&J˜!J˜Jšœ>˜>Jšœe˜eJ˜*J˜—J™˜J˜J˜J˜—˜J˜J˜J˜—šœ%˜%J˜!J˜Jšœ>˜>Jšœf˜fJ˜*J˜—J™˜J˜J˜J˜—˜J˜J˜J˜—šœ&˜&J˜J˜Jšœ>˜>Jšœf˜fJ˜*J˜—Jšœ˜—J˜š œœœ6œ&˜ŽJš˜šœ ˜˜ šœ˜Jšœ4˜4——˜ šœ˜J˜4——Jšœœ˜—Jšœ˜—J˜š œœ0œ&˜pJš˜Jšœœ˜(J˜-J˜2Jšœ œ ˜Jšœœ œ ˜9Jšœœ œ ˜9Jšœœ œ ˜9Jšœœ œ ˜9J˜J˜Jšœ œ˜Jšœ œ ˜Jšœ™˜J˜J˜J˜—˜˜J˜J˜J˜—˜J˜J˜——šœ&˜&J˜J˜Jšœ>˜>Jšœe˜eJ˜*J˜—Jšœ™˜J˜J˜J˜—˜˜J˜J˜J˜—˜J˜J˜J˜——šœ%˜%J˜!J˜Jšœ>˜>Jšœe˜eJ˜*J˜—J™˜J˜J˜J˜—˜˜J˜J˜J˜—˜J˜J˜J˜——šœ%˜%J˜!J˜Jšœ>˜>Jšœf˜fJ˜*J˜—J™˜J˜J˜J˜—˜˜J˜J˜J˜—˜J˜J˜J˜——šœ&˜&J˜J˜Jšœ>˜>Jšœf˜fJ˜*J˜—Jšœ˜—J˜š  œœ œ œ8œœœ œ˜“J™%Jš˜Jšœœœ[˜zJšœ˜—J˜JšœL˜LJšœK˜KJšœK˜KJ™Jšœeœ*˜“J˜Jšœeœ ˜‰J˜Jšœgœ ˜wJ˜Jšœ˜—…—:jFΝ