NMosRecognizerImpl.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, March 19, 1986 6:40:14 pm PST
DIRECTORY
CD,
NMos,
NMosTransistors,
NMosContacts,
CDInstances,
CDBasics,
Recognizer,
CStitching,
CDOrient;
NMosRecognizerImpl: CEDAR PROGRAM
IMPORTS NMos, NMosTransistors, NMosContacts, CDInstances, Recognizer, CDBasics, CDOrient =
BEGIN
RegionList: TYPE = LIST OF REF CStitching.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.NewInstI[ob: newObject, orientation: CDOrient.original, location: position];
PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList];
newObject ← NMosTransistors.CreateTransistor[w: xDistance, l: yDistance, implant: impList.first];
newInst ← CDInstances.NewInstI[ob: newObject, orientation: CDOrient.rotate90, location: position];
PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList];
newObject ← NMosTransistors.CreateTransistor[w: yDistance, l: xDistance, implant: impList.first];
newInst ← CDInstances.NewInstI[ob: newObject, orientation: CDOrient.original, location: position];
PlaceOnList[newInst, possibleInstListPtr, forbiddenLayerList];
newObject ← NMosTransistors.CreateTransistor[w: yDistance, l: xDistance, implant: impList.first];
newInst ← CDInstances.NewInstI[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.NewInstI[ob: newObject, orientation: CDOrient.original, location: [position.x-ext, position.y-ext]];
PlaceOnList[newInst, possibleInstListPtr];
newObject ← NMosTransistors.CreatePullUp[w: xDistance, l: yDistance];
newInst ← CDInstances.NewInstI[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.NewInstI[ob: newObject, orientation: CDOrient.rotate90, location: [position.x-polyButtingExt, position.y-ext]];
PlaceOnList[newInst, possibleInstListPtr];
newObject ← NMosTransistors.CreatePullUp[w: yDistance, l: xDistance];
newInst ← CDInstances.NewInstI[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.NewInstI[ob: NMosContacts.CreatePolyCon[l: length], location: position, orientation: orient], possibleInstListPtr];
PlaceOnList[CDInstances.NewInstI[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.NewInstI[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.NewInstI[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.NewInstI[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.NewInstI[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;
--Orientation 0
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.NewInstI[ob: newObject, orientation: CDOrient.original, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation 90
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𡤎xt;
};
IF width <= pullupWidthFor2or3 THEN {
position.x ← minX-polyButtingExt;
length ← maxX-minX;
newObject ← NMosTransistors.CreatePullUp[w: width, l: length];
newInst ← CDInstances.NewInstI[ob: newObject, orientation: CDOrient.rotate90, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation180 
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.NewInstI[ob: newObject, orientation: CDOrient.rotate180, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation 270
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.NewInstI[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;
--Orientation 0
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.NewInstI[ob: newObject, orientation: CDOrient.original, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation 90
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.NewInstI[ob: newObject, orientation: CDOrient.rotate90, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation180 
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.NewInstI[ob: newObject, orientation: CDOrient.rotate180, location: position];
PlaceOnList[newInst, possibleInstListPtr];
};
--Orientation 270
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.NewInstI[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] =
--places instance on possibleInstList
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.