CMosContactsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
Christian Jacobi, June 24, 1983 5:03 pm
last edited Christian Jacobi, October 22, 1984 11:05:31 am PDT
DIRECTORY
Atom,
CMosContacts,
CD,
CDBasics,
CDCallSpecific,
CDIO,
CDLRUCache,
CDOrient,
CDRects USING [CreateRect],
CDStretchyExtras,
CDApplications,
CMos,
Rope,
TokenIO;
CMosContactsImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDBasics, CDCallSpecific, CDIO, CDLRUCache, CDOrient, CDStretchyExtras, CDApplications, CDRects, CMos, Rope, TokenIO
EXPORTS CMosContacts =
BEGIN OPEN CMos;
lambda: CD.DesignNumber = CD.lambda;
ContactType: TYPE = CMosContacts.ContactType;
ContactPtr: TYPE = CMosContacts.ContactPtr;
ContactRec: TYPE = CMosContacts.ContactRec;
undef: CD.Layer = CMosContacts.undef;
wellSurround: CD.DesignNumber = CMos.wellSurround;
difCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
polyCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
dsCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
butCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
burCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
mmCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
ToPosition: PROC [x: REF] RETURNS [p: CD.DesignPosition] =
--y field defaults to lambda, x field defaults to 0
--[0, 0] if not done
BEGIN
IF x=NIL THEN p ← [0, lambda]
ELSE WITH x SELECT FROM
rp: REF CD.DesignPosition => p ← rp^;
rn: REF CD.DesignNumber => p ← [0, rn^];
ENDCASE => p ← [0, 0];
END;
Aequivalent: PROC[mySpecific, other: REF ANY] RETURNS [BOOL] = {
WITH other SELECT FROM
p2: ContactPtr => RETURN [NARROW[mySpecific, ContactPtr]^=p2^];
ENDCASE => RETURN [FALSE]
};
NewCont: PROC [] RETURNS [CD.ObPtr] = {
ob: CD.ObPtr ← NEW[CD.ObjectDefinition];
ob.specificRef ← NEW[ContactRec];
RETURN [ob]
};
InsideRectWithSurround: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] =
BEGIN
RETURN [CDBasics.Extend[CDBasics.RectAt[[0, 0], ob.size], -wellSurround]]
END;
ShowSelectedWithSurround: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition,
orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
pr.outLineProc[CDBasics.Extend[CDOrient.RectAt[pos, aptr.ob.size, orient], -wellSurround], pr]
END;
HitInsideWithSurround: PROC [aptr: CD.ApplicationPtr, hitRect: CD.DesignRect]
RETURNS [BOOL] =
BEGIN
RETURN [CDBasics.Intersect[
CDBasics.Extend[
CDApplications.ARectO[aptr],
-wellSurround],
hitRect]]
END;
MatchContact: PROC [me: CD.ObPtr, r: CD.DesignRect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] =
BEGIN
-- Don't care about different diffusions and such
IF layer=me.layer THEN RETURN [TRUE]
ELSE {
cp: ContactPtr = NARROW[me.specificRef];
RETURN [
SELECT cp.typ FROM
burr => (layer=CMos.pol),
mDif => (layer=CMos.met),
difShort => FALSE,
butt => (layer=CMos.met OR layer=CMos.pol),
mPol => (layer=CMos.met),
mm2 => (layer=CMos.met2),
ENDCASE => FALSE
]
}
END;
-- Dif and Pol -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifPolCon: REF CD.ObjectProcs = RegisterObjectType[$CMosContactDifAndPol];
pForWellDifPolCon: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellDifAndPol];
difpolRimWidth: CD.DesignNumber = lambda;
CreateDifCon: PUBLIC PROC [l: CD.DesignNumber, difLev: CD.Layer] RETURNS [CD.ObPtr] =
--connect diffusion with metal
BEGIN
cob: CD.ObPtr ~ difCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
IF difLev=undef THEN difLev←ndif;
l ← MAX[l, butConSX];
cp.typ ← mDif;
cob.layer ← difLev;
IF difLev=CMos.pdif THEN {
cob.p ← pForWellDifPolCon;
cob.size ← [butConSX+2*wellSurround, l+2*wellSurround];
}
ELSE {
cob.p ← pForDifPolCon;
cob.size ← [butConSX, l];
};
RETURN [difCache.ReplaceByAequivalent[cob]]
END;
CreatePolyCon: PUBLIC PROC [l: CD.DesignNumber] RETURNS [CD.ObPtr] =
--connect poly with metal
BEGIN
cob: CD.ObPtr ~ polyCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
l ← MAX[l, butConSX];
cp.typ ← mPol;
cob.p ← pForDifPolCon;
cob.size ← [butConSX, l];
cob.layer ← pol;
RETURN [polyCache.ReplaceByAequivalent[cob]]
END;
LengthenPolyDif: CDCallSpecific.CallProc =
BEGIN
amount: CD.DesignPosition = ToPosition[x];
IF amount.y=0 OR amount.x#0 THEN done ← FALSE
ELSE {
new: CD.ObPtr;
sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0;
cp: ContactPtr = NARROW[aptr.ob.specificRef];
sz: CD.DesignPosition ← CDBasics.SubPoints[CDBasics.AddPoints[aptr.ob.size, amount], [sur, sur]];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
IF aptr.ob.layer=pol THEN new ← CreatePolyCon[sz.y] ELSE new ← CreateDifCon[sz.y, aptr.ob.layer];
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
}
END;
DefaultenPolyDif: CDCallSpecific.CallProc =
BEGIN
new: CD.ObPtr;
cp: ContactPtr = NARROW[aptr.ob.specificRef];
IF aptr.ob.layer=pol THEN new ← CreatePolyCon[4*lambda] ELSE new ← CreateDifCon[4*lambda, aptr.ob.layer];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
END;
ReadDifPolCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
lev: CD.Layer = CDIO.ReadLayer[];
IF lev=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[]] ]
ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[], lev] ]
END;
WriteDifPolCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
sur: INT = IF me.layer=CMos.pdif THEN 2*wellSurround ELSE 0;
CDIO.WriteLayer[me.layer];
TokenIO.WriteInt[me.size.y-sur];
END;
DrawDifPolCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient];
pr.drawRect[r, met, pr];
pr.drawRect[r, aptr.ob.layer, pr];
pr.saveRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr];
END;
DrawWellDifPolCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient];
inr: CD.DesignRect = CDBasics.Extend[r, -wellSurround];
pr.drawRect[inr, met, pr];
pr.drawRect[inr, aptr.ob.layer, pr];
pr.saveRect[CDBasics.Extend[inr, -difpolRimWidth], cut, pr];
pr.drawRect[r, nwel, pr];
END;
-- DifShort -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifShorts: REF CD.ObjectProcs = RegisterObjectType[$CMosContactDifShort];
pForWellDifShorts: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellDifShort];
difShortRimWidth: CD.DesignNumber = lambda;
CreateDifShortCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.ObPtr] =
BEGIN
cob: CD.ObPtr ~ dsCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
IF difLev=undef THEN difLev ← ndif;
cp.typ ← difShort;
cob.layer ← difLev;
IF difLev=CMos.pdif THEN {
cob.p ← pForWellDifShorts;
cob.size ← [butConSX+2*wellSurround, 8*lambda+2*wellSurround]
}
ELSE IF difLev=CMos.ndif THEN {
cob.p ← pForDifShorts;
cob.size ← [butConSX, 8*lambda]
}
ELSE ERROR;
RETURN [dsCache.ReplaceByAequivalent[cob]]
END;
ReadDifShortCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
RETURN [ CreateDifShortCon[CDIO.ReadLayer[]] ]
END;
WriteDifShortCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
CDIO.WriteLayer[me.layer];
END;
DrawDifShortContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.saveRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
r: CD.DesignRect = CDOrient.RectAt[[0, 0], aptr.ob.size];
mr: CD.DesignRect = CDBasics.Extend[r, -difShortRimWidth];
h: CD.DesignNumber = (r.y2-r.y1)/2;
Draw[r, met];
Draw[[x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y1+h], CMos.ndif];
Draw[[x1: r.x1, y1: r.y1+h, x2: r.x2, y2: r.y2], CMos.pwelCont];
Save[[x1: mr.x1, x2: mr.x2, y1: mr.y1, y2: mr.y1+2*lambda], cut];
Save[[x1: mr.x1, x2: mr.x2, y1: mr.y2-2*lambda, y2: mr.y2], cut];
END;
DrawWellDifShortContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
r: CD.DesignRect = CDOrient.RectAt[[0, 0], aptr.ob.size];
inr: CD.DesignRect = CDBasics.Extend[r, -wellSurround];
mr: CD.DesignRect = CDBasics.Extend[inr, -difShortRimWidth];
h: CD.DesignNumber = (inr.y2-inr.y1)/2;
Draw[inr, met];
Draw[[x1: inr.x1, y1: inr.y1, x2: inr.x2, y2: inr.y1+h], CMos.pdif];
Draw[[x1: inr.x1, y1: inr.y1+h, x2: inr.x2, y2: inr.y2], CMos.nwelCont];
Save[[x1: mr.x1, x2: mr.x2, y1: mr.y1, y2: mr.y1+2*lambda], cut];
Save[[x1: mr.x1, x2: mr.x2, y1: mr.y2-2*lambda, y2: mr.y2], cut];
Draw[[x1: r.x1, x2: r.x2, y1: r.y1, y2: r.y2-h], nwel];
END;
-- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForButContact: REF CD.ObjectProcs = RegisterObjectType[$CMosContactBut];
pForWellButContact: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellBut];
butContactPolyYS: CD.DesignNumber = 3*lambda;
butContactDiffY: CD.DesignNumber = butContactPolyYS-lambda;
butContactDiffYS: CD.DesignNumber = 4*lambda;
butConSX: CD.DesignNumber = 4*lambda;
butConSY: CD.DesignNumber = butContactDiffY+butContactDiffYS;
butContactRimWidth: CD.DesignNumber = lambda;
pButConInnerY: CD.DesignNumber = wellSurround-butContactDiffY;
pButConSX: CD.DesignNumber = butConSX+2*wellSurround;
pButConSY: CD.DesignNumber = pButConInnerY+butConSY+wellSurround;
pButConInner: CD.DesignRect = [
x1: wellSurround, x2: wellSurround+butConSX,
y1: pButConInnerY, y2: pButConInnerY+butConSY
];
CreateButCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.ObPtr] =
--connects metal with poly and diffusion
BEGIN
cob: CD.ObPtr ~ butCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
cp.typ ← butt;
IF difLev=undef THEN difLev←ndif;
cob.layer ← difLev;
IF difLev=CMos.pdif THEN {
cob.p ← pForWellButContact;
cob.size ← [pButConSX, pButConSY];
}
ELSE {
cob.p ← pForButContact;
cob.size ← [butConSX, butConSY];
};
RETURN [butCache.ReplaceByAequivalent[cob]]
END;
ReadButCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
RETURN [ CreateButCon[CDIO.ReadLayer[]] ]
END;
WriteButCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
CDIO.WriteLayer[me.layer];
END;
DrawButContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.saveRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Draw[[0, 0, butConSX, butConSY], met];
Draw[[0, 0, butConSX, butContactPolyYS], pol];
Draw[[0, butContactDiffY, butConSX, butConSY], aptr.ob.layer];
Save[[butContactRimWidth, butContactRimWidth,
butConSX-butContactRimWidth, butConSY-butContactRimWidth], cut];
END;
DrawWellButContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.saveRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
inr: CD.DesignRect = [
x1: wellSurround, y1: pButConInnerY,
x2: wellSurround+butConSX, y2: pButConInnerY+butConSY
];
Draw[inr, met];
Draw[[x1: inr.x1, y1: inr.y1, x2: inr.x2, y2: inr.y1+butContactPolyYS], pol];
Draw[[x1: inr.x1, y1: inr.y1+butContactDiffY, x2: inr.x2, y2: inr.y2], aptr.ob.layer];
Draw[[x1: 0, y1: 0, x2: pButConSX, y2: pButConSY], nwel];
Save[CDBasics.Extend[inr, -butContactRimWidth], cut];
END;
PButInsideRectWithSurround: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] =
BEGIN
RETURN [pButConInner]
END;
PButHitInsideWithSurround: PROC [aptr: CD.ApplicationPtr, hitRect: CD.DesignRect]
RETURNS [BOOL] =
BEGIN
RETURN [CDBasics.Intersect[
CDOrient.MapRect[
itemInCell: pButConInner,
cellSize: [pButConSX, pButConSY],
cellInstOrient: aptr.orientation,
cellInstPos: aptr.location
],
hitRect]]
END;
PButShowSelectedWithSurround: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition,
orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
pr.outLineProc[
CDOrient.MapRect[
itemInCell: pButConInner,
cellSize: [pButConSX, pButConSY],
cellInstOrient: orient,
cellInstPos: pos
],
pr]
END;
-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForBurCon: REF CD.ObjectProcs = RegisterObjectType[$CMosBurContact];
pForWellBurCon: REF CD.ObjectProcs = RegisterObjectType[$CMosWellBurContact];
-- Buried contacts come in three flavours, Pol-Surround, Dif-Surround and Crossing. The buried contacts in chipndale are parameterized by lExt and wExt, their interpretation is as follows: Diff always extends 1l to the left, material above/below and to the right is determined by lExt and wExt respectively. 2l is the pivotal value, below 2l the material is Pol, at 2l or above the material is Diff. (Note: some combinations give Diff on all four sides, it is assumed that such combinations will not be created.)
CreateBurCon: PUBLIC PROC [w, l: CD.DesignNumber,
wex: CD.DesignNumber,
lex: CD.DesignNumber,
difLev: CD.Layer] RETURNS [CD.ObPtr] =
-- connects diffusion with poly without accessing metal
BEGIN
-- copied from chipmonk without understanding
burAct: CD.DesignNumber = 2*lambda;
actWidth, xMargins: CD.DesignNumber;
cob: CD.ObPtr ~ burCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
IF difLev=undef THEN difLev←ndif;
wex ← MAX[0, wex];
lex ← MAX[0, lex];
xMargins ← burAct +
(IF wex< burAct THEN MAX[wex+lambda, burAct] ELSE wex);
actWidth ← MAX[2*lambda, w-xMargins];
w ← actWidth+xMargins;
l ← MAX[l,
(IF lex<burAct THEN MAX[lex+lambda, burAct] ELSE lex)*2+lambda*MAX[6*lambda/actWidth, 2]
];
cp.typ ← burr;
cp.wExt ← wex;
cp.lExt ← lex;
IF difLev=CMos.pdif THEN {
--some people told me that this can not be produced
cob.p ← pForWellBurCon;
cob.size ← [w+2*wellSurround, l+2*wellSurround];
RETURN[CDRects.CreateRect[[w, l], CD.highLightError]];
}
ELSE {
cob.p ← pForBurCon;
cob.size ← [w, l];
};
cob.layer ← difLev;
RETURN [burCache.ReplaceByAequivalent[cob]]
END;
ReadBurCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
w: INT = TokenIO.ReadInt[];
l: INT = TokenIO.ReadInt[];
wex: INT = TokenIO.ReadInt[];
lex: INT = TokenIO.ReadInt[];
difLev: CD.Layer = CDIO.ReadLayer[];
RETURN [ CreateBurCon[w, l, wex, lex, difLev] ]
END;
WriteBurCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
cp: ContactPtr = NARROW[me.specificRef];
IF me.layer = CMos.pdif THEN {
TokenIO.WriteInt[me.size.x-2*wellSurround];
TokenIO.WriteInt[me.size.y-2*wellSurround];
}
ELSE {
TokenIO.WriteInt[me.size.x];
TokenIO.WriteInt[me.size.y];
};
TokenIO.WriteInt[cp.wExt];
TokenIO.WriteInt[cp.lExt];
CDIO.WriteLayer[me.layer];
END;
DrawBurrCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.saveRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
--copied from chipmonk without understanding
p: ContactPtr = NARROW[aptr.ob.specificRef];
dBur: CD.DesignNumber = lambda/2;
burAct: CD.DesignNumber = lambda*2;
diffBur: CD.DesignPosition = [
x: IF p.wExt<burAct THEN MAX[p.wExt+lambda, burAct] ELSE p.wExt-lambda,
y: IF p.lExt<burAct THEN MAX[p.lExt+lambda, burAct] ELSE p.lExt-lambda
];
Save[[dBur, dBur, aptr.ob.size.x-dBur, aptr.ob.size.y-dBur], bur];
Draw[[burAct, p.lExt, aptr.ob.size.x-p.wExt, aptr.ob.size.y-p.lExt], pol];
Draw[[lambda, diffBur.y, aptr.ob.size.x-diffBur.x, aptr.ob.size.y-diffBur.y], aptr.ob.layer];
END;
DrawWellBurrCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.saveRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
dBur: CD.DesignNumber = lambda/2;
burAct: CD.DesignNumber = lambda*2;
r: CD.DesignRect = CDOrient.RectAt[[0, 0], aptr.ob.size];
p: ContactPtr = NARROW[aptr.ob.specificRef];
inr: CD.DesignRect = CDBasics.Extend[r, -wellSurround];
diffBur: CD.DesignPosition = [
x: IF p.wExt<burAct THEN MAX[p.wExt+lambda, burAct] ELSE p.wExt-lambda,
y: IF p.lExt<burAct THEN MAX[p.lExt+lambda, burAct] ELSE p.lExt-lambda
];
Save[CDBasics.Extend[inr, -dBur], bur];
Draw[[inr.x1+burAct, inr.y1+p.lExt, inr.x2-p.wExt, inr.y2-p.lExt], pol];
Draw[[inr.x1+lambda, inr.y1+diffBur.y, inr.x2-diffBur.x, inr.y2-diffBur.y], aptr.ob.layer];
Draw[r, nwel];
END;
LengthenBur: CDCallSpecific.CallProc =
BEGIN
amount: CD.DesignPosition = ToPosition[x];
IF amount.y=0 AND amount.x=0 THEN done ← FALSE
ELSE {
new: CD.ObPtr;
sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0;
cp: ContactPtr ← NARROW[aptr.ob.specificRef];
sz: CD.DesignPosition ← CDBasics.SubPoints[CDBasics.AddPoints[aptr.ob.size, amount], [sur, sur]];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
new ← CreateBurCon[w: sz.x, l: sz.y, wex: cp.wExt, lex: cp.lExt, difLev: aptr.ob.layer];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
};
END;
ChangeExtensionBur: CDCallSpecific.CallProc =
BEGIN
amount: CD.DesignPosition = ToPosition[x];
IF amount.y=0 AND amount.x=0 THEN done ← FALSE
ELSE {
sur: INT = (IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0);
cp: ContactPtr = NARROW[aptr.ob.specificRef];
new: CD.ObPtr ← CreateBurCon[
w: aptr.ob.size.x-sur+amount.x,
l: aptr.ob.size.y-sur+amount.y,
wex: cp.wExt+amount.x,
lex: cp.lExt+amount.y,
difLev: aptr.ob.layer
];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
}
END;
DefaultenBur: CDCallSpecific.CallProc =
BEGIN
sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0;
cp: ContactPtr = NARROW[aptr.ob.specificRef];
new: CD.ObPtr ← CreateBurCon[w: aptr.ob.size.x-sur, l: 4*lambda, wex: cp.wExt, lex: cp.lExt, difLev: aptr.ob.layer];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
END;
--Mm -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForVia: REF CD.ObjectProcs = RegisterObjectType[$CMosMmContact];
mmRimWidth: CD.DesignNumber = lambda;
cut2min: CD.DesignNumber = 3*lambda;
CreateMmCon: PUBLIC PROC [l: CD.DesignNumber,
wex: CD.DesignNumber,
lex: CD.DesignNumber] RETURNS [CD.ObPtr] =
--ignores wex and lex in chipmonk, why???
--connects two layers of metal
BEGIN
cob: CD.ObPtr ~ mmCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
mins: CD.DesignNumber = cut2min+2*mmRimWidth;
oldMins: CD.DesignNumber = cut2min+2*--mmRimWidth--2*lambda;
l ← MAX[l, mins];
cp.typ ← mm2;
--cp.wExt ← ;
--cp.wExt ← ;
cob.p ← pForVia;
IF l<oldMins THEN --new technology; we use new technology only for small sizes--
cob.size ← [mins, l]
ELSE --old technology--
cob.size ← [oldMins, l];
cob.layer ← CMos.met;
RETURN [mmCache.ReplaceByAequivalent[cob]]
END;
LengthenVia: CDCallSpecific.CallProc =
BEGIN
amount: CD.DesignPosition = ToPosition[x];
IF amount.y=0 OR amount.x#0 THEN done ← FALSE
ELSE {
new: CD.ObPtr;
cp: ContactPtr ← NARROW[aptr.ob.specificRef];
sz: CD.DesignPosition ← CDBasics.AddPoints[aptr.ob.size, amount];
IF sz.x<=0 OR sz.y<=0 THEN {done←FALSE; RETURN};
new ← CreateMmCon[l: sz.y, wex: cp.wExt, lex: cp.lExt];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
}
END;
DefaultenVia: CDCallSpecific.CallProc =
BEGIN
cp: ContactPtr ← NARROW[aptr.ob.specificRef];
new: CD.ObPtr ← CreateMmCon[l: 4*lambda, wex: cp.wExt, lex: cp.lExt];
repaintMe ← TRUE;
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
END;
ReadVia: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
RETURN [ CreateMmCon[TokenIO.ReadInt[], 0, 0] ]
END;
WriteVia: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
TokenIO.WriteInt[me.size.y];
END;
DrawVia: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
--does not read specificRef !!!!!!
BEGIN
mins: CD.DesignNumber = cut2min+2*mmRimWidth;
r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient];
pr.drawRect[r, met, pr];
pr.drawRect[r, met2, pr];
IF aptr.ob.size.x>mins THEN --old technology--
pr.saveRect[CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2, pr]
ELSE --new technology--
pr.saveRect[CDBasics.Extend[r, -mmRimWidth], cut2, pr];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
DescribeLayer: PROC[l: CD.Layer] RETURNS [Rope.ROPE] =
{RETURN [Atom.GetPName[CD.LayerKey[l]]]};
Describe: PROC[me: CD.ObPtr] RETURNS [Rope.ROPE] =
BEGIN
cp: ContactPtr = NARROW[me.specificRef];
RETURN [
SELECT cp.typ FROM
burr => Rope.Concat["buried contact ", DescribeLayer[me.layer]],
mDif => Rope.Concat[DescribeLayer[me.layer], " contact"],
difShort => Rope.Concat["dif - short contact ", DescribeLayer[me.layer]],
butt => Rope.Concat["butting contact ", DescribeLayer[me.layer]],
mPol => "contact poly",
mm2 => "via",
ENDCASE => "unknown contact"
]
END;
Init: PROC [] =
BEGIN
pForDifPolCon.drawMe ← pForDifPolCon.quickDrawMe ← DrawDifPolCon;
pForDifPolCon.internalRead ← ReadDifPolCon;
pForDifPolCon.internalWrite ← WriteDifPolCon;
pForDifPolCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForDifPolCon, MatchContact];
CDCallSpecific.Register[$Lengthen, pForDifPolCon, LengthenPolyDif];
CDCallSpecific.Register[$Default, pForDifPolCon, DefaultenPolyDif];
pForWellDifPolCon.drawMe ← pForWellDifPolCon.quickDrawMe ← DrawWellDifPolCon;
pForWellDifPolCon.interestRect ← pForWellDifPolCon.oldInsideRect ← InsideRectWithSurround;
pForWellDifPolCon.showMeSelected ← ShowSelectedWithSurround;
pForWellDifPolCon.hitInside ← HitInsideWithSurround;
pForWellDifPolCon.internalRead ← ReadDifPolCon;
pForWellDifPolCon.internalWrite ← WriteDifPolCon;
pForWellDifPolCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForWellDifPolCon, MatchContact];
CDCallSpecific.Register[$Lengthen, pForWellDifPolCon, LengthenPolyDif];
CDCallSpecific.Register[$Default, pForWellDifPolCon, DefaultenPolyDif];
pForButContact.drawMe ← pForButContact.quickDrawMe ← DrawButContact;
pForButContact.internalRead ← ReadButCon;
pForButContact.internalWrite ← WriteButCon;
pForButContact.describe ← Describe;
CDStretchyExtras.InstallMatch[pForButContact, MatchContact];
pForWellButContact.drawMe ← pForWellButContact.quickDrawMe ← DrawWellButContact;
pForWellButContact.interestRect ← pForWellButContact.oldInsideRect ← PButInsideRectWithSurround;
pForWellButContact.hitInside ← PButHitInsideWithSurround;
pForWellButContact.showMeSelected ← PButShowSelectedWithSurround;
pForWellButContact.internalRead ← ReadButCon;
pForWellButContact.internalWrite ← WriteButCon;
pForWellButContact.describe ← Describe;
CDStretchyExtras.InstallMatch[pForWellButContact, MatchContact];
pForBurCon.drawMe ← pForBurCon.quickDrawMe ← DrawBurrCon;
pForBurCon.internalRead ← ReadBurCon;
pForBurCon.internalWrite ← WriteBurCon;
pForBurCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForBurCon, MatchContact];
CDCallSpecific.Register[$Lengthen, pForBurCon, LengthenBur];
CDCallSpecific.Register[$ChangeExt, pForBurCon, ChangeExtensionBur];
CDCallSpecific.Register[$Default, pForBurCon, DefaultenBur];
pForWellBurCon.drawMe ← pForWellBurCon.quickDrawMe ← DrawWellBurrCon;
pForWellBurCon.interestRect ← pForWellBurCon.oldInsideRect ← InsideRectWithSurround;
pForWellBurCon.hitInside ← HitInsideWithSurround;
pForWellBurCon.internalRead ← ReadBurCon;
pForWellBurCon.internalWrite ← WriteBurCon;
pForWellBurCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForWellBurCon, MatchContact];
CDCallSpecific.Register[$Lengthen, pForWellBurCon, LengthenBur];
CDCallSpecific.Register[$ChangeExt, pForWellBurCon, ChangeExtensionBur];
CDCallSpecific.Register[$Default, pForWellBurCon, DefaultenBur];
pForVia.drawMe ← pForVia.quickDrawMe ← DrawVia;
pForVia.internalRead ← ReadVia;
pForVia.internalWrite ← WriteVia;
pForVia.describe ← Describe;
CDStretchyExtras.InstallMatch[pForVia, MatchContact];
CDCallSpecific.Register[$Lengthen, pForVia, LengthenVia]; --I'm not shure changing size is a good idea
CDCallSpecific.Register[$Default, pForVia, DefaultenVia];
pForDifShorts.drawMe ← pForDifShorts.quickDrawMe ← DrawDifShortContact;
pForDifShorts.internalRead ← ReadDifShortCon;
pForDifShorts.internalWrite ← WriteDifShortCon;
pForDifShorts.describe ← Describe;
CDStretchyExtras.InstallMatch[pForDifShorts, MatchContact];
pForWellDifShorts.drawMe ← pForWellDifShorts.quickDrawMe ← DrawWellDifShortContact;
pForWellDifShorts.interestRect ← pForWellDifShorts.oldInsideRect ← InsideRectWithSurround;
pForWellDifShorts.hitInside ← HitInsideWithSurround;
pForWellDifShorts.internalRead ← ReadDifShortCon;
pForWellDifShorts.internalWrite ← WriteDifShortCon;
pForWellDifShorts.describe ← Describe;
CDStretchyExtras.InstallMatch[pForWellDifShorts, MatchContact];
END;
Init[];
END.