CMosCMContactsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
Christian Jacobi, June 24, 1983 5:03 pm
Last edited by: Christian Jacobi, October 31, 1986 4:21:10 pm PST
DIRECTORY
CMosCMContacts,
CMosObjects,
CD,
CDBasics,
CDIO,
CDLRUCache,
CDOps,
CDRects USING [CreateRect],
CDStretchyBackdoor,
CMos,
Rope,
TokenIO;
CMosCMContactsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDIO, CDLRUCache, CDOps, CDStretchyBackdoor, CDRects, CMos, Rope, TokenIO, CMosObjects
EXPORTS CMosCMContacts =
BEGIN OPEN CMos;
lambda: CD.Number = CMos.lambda;
ContactType: TYPE = CMosCMContacts.ContactType;
ContactPtr: TYPE = CMosCMContacts.ContactPtr;
ContactRec: TYPE = CMosCMContacts.ContactRec;
undef: CD.Layer = CD.undefLayer;
wellSurround: CD.Number = 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];
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.Object] = {
ob: CD.Object ← NEW[CD.ObjectRep];
ob.specific ← NEW[ContactRec];
RETURN [ob]
};
InsideRectWithSurround: PROC [ob: CD.Object] RETURNS [CD.Rect] = {
RETURN [CDBasics.Extend[ob.bbox, -wellSurround]]
};
ShowSelectedWithSurround: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = {
pr.drawOutLine[CDBasics.Extend[CDBasics.MapRect[inst.ob.bbox, trans], -(wellSurround)], CD.selectionLayer, pr]
};
MatchContact: PROC [me: CD.Object, r: CD.Rect, 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.specific];
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: CD.ObjectClass = RegisterObjectClass[$CMosContactDifAndPol];
pForWellDifPolCon: CD.ObjectClass = RegisterObjectClass[$CMosContactWellDifAndPol];
difpolRimWidth: CD.Number = lambda;
CreateDifCon: PUBLIC PROC [l: CD.Number, difLev: CD.Layer] RETURNS [CD.Object] =
--connect diffusion with metal
BEGIN
cob: CD.Object ~ difCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
IF difLev=undef THEN difLev←ndif;
IF l=butConSX THEN {
IF difLev=CMos.pdif THEN difLev ← CMos.wpdif;
IF difLev=CMos.pol THEN RETURN [CMosObjects.CreatePolyCon[]]
ELSE RETURN [CMosObjects.CreateDifCon[difLev]]
};
l ← MAX[l, butConSX];
cp.typ ← mDif;
cob.layer ← difLev;
IF difLev=CMos.pdif THEN {
cob.class ← pForWellDifPolCon;
cob.bbox ← [-wellSurround, -wellSurround, butConSX+wellSurround, l+wellSurround];
}
ELSE {
cob.class ← pForDifPolCon;
cob.bbox ← [0, 0, butConSX, l];
};
RETURN [difCache.ReplaceByAequivalent[cob]]
END;
CreatePolyCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] =
--connect poly with metal
BEGIN
cob: CD.Object ~ polyCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
IF l=butConSX THEN {
RETURN [CMosObjects.CreatePolyCon[]]
};
l ← MAX[l, butConSX];
cp.typ ← mPol;
cob.class ← pForDifPolCon;
cob.bbox ← [0, 0, butConSX, l];
cob.layer ← pol;
RETURN [polyCache.ReplaceByAequivalent[cob]]
END;
ReadDifPolCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
lev: CD.Layer = CDIO.ReadLayer[h];
IF lev=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[h]] ]
ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[h], lev] ]
END;
WriteDifPolCon: CD.InternalWriteProc -- PROC [ob: Object] -- =
BEGIN
CDIO.WriteLayer[h, ob.layer];
TokenIO.WriteInt[h, CD.InterestSize[ob].y];
END;
DrawDifPolCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans];
pr.drawRect[r, met, pr];
pr.drawRect[r, inst.ob.layer, pr];
pr.drawRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr];
END;
DrawWellDifPolCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans];
inr: CD.Rect = CDBasics.Extend[r, -wellSurround];
pr.drawRect[inr, met, pr];
pr.drawRect[inr, inst.ob.layer, pr];
pr.drawRect[CDBasics.Extend[inr, -difpolRimWidth], cut, pr];
pr.drawRect[r, nwell, pr];
END;
-- DifShort -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifShorts: CD.ObjectClass = RegisterObjectClass[$CMosContactDifShort];
pForWellDifShorts: CD.ObjectClass = RegisterObjectClass[$CMosContactWellDifShort];
difShortRimWidth: CD.Number = lambda;
CreateDifShortCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.Object] =
BEGIN
IF difLev=CMos.pdif THEN difLev ← CMos.wpdif;
RETURN [CMosObjects.CreateDifShortCon[difLev]]
END;
ReadDifShortCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateDifShortCon[CDIO.ReadLayer[h]] ]
END;
-- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForButContact: CD.ObjectClass = RegisterObjectClass[$CMosContactBut];
pForWellButContact: CD.ObjectClass = RegisterObjectClass[$CMosContactWellBut];
butConSX: CD.Number = 4*lambda;
CreateButCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.Object] =
--connects metal with poly and diffusion
BEGIN
IF difLev=CMos.pdif THEN difLev ← CMos.wpdif;
RETURN [CMosObjects.CreateButCon[difLev]]
END;
ReadButCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateButCon[CDIO.ReadLayer[h]] ]
END;
-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForBurCon: CD.ObjectClass = RegisterObjectClass[$CMosBurContact];
pForWellBurCon: CD.ObjectClass = RegisterObjectClass[$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.Number,
wex: CD.Number,
lex: CD.Number,
difLev: CD.Layer] RETURNS [CD.Object] =
-- connects diffusion with poly without accessing metal
BEGIN
-- copied from chipmonk without understanding
burAct: CD.Number = 2*lambda;
actWidth, xMargins: CD.Number;
cob: CD.Object ~ burCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
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 {
--can not be produced
RETURN[CDRects.CreateRect[[w, l], CD.errorLayer]];
}
ELSE {
cob.class ← pForBurCon;
cob.bbox ← [0, 0, w, l];
};
cob.layer ← difLev;
RETURN [burCache.ReplaceByAequivalent[cob]]
END;
ReadBurCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
w: INT = TokenIO.ReadInt[h];
l: INT = TokenIO.ReadInt[h];
wex: INT = TokenIO.ReadInt[h];
lex: INT = TokenIO.ReadInt[h];
difLev: CD.Layer = CDIO.ReadLayer[h];
RETURN [ CreateBurCon[w, l, wex, lex, difLev] ]
END;
WriteBurCon: CD.InternalWriteProc =
BEGIN
cp: ContactPtr = NARROW[ob.specific];
CDIO.WritePos[h, CD.InterestSize[ob]];
TokenIO.WriteInt[h, cp.wExt];
TokenIO.WriteInt[h, cp.lExt];
CDIO.WriteLayer[h, ob.layer];
END;
DrawBurrCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[CDBasics.MapRect[r, trans], l, pr]
};
--copied from chipmonk without understanding
class: ContactPtr = NARROW[inst.ob.specific];
dBur: CD.Number = lambda/2;
burAct: CD.Number = lambda*2;
diffBur: CD.Position = [
x: IF class.wExt<burAct THEN MAX[class.wExt+lambda, burAct] ELSE class.wExt-lambda,
y: IF class.lExt<burAct THEN MAX[class.lExt+lambda, burAct] ELSE class.lExt-lambda
];
Draw[[dBur, dBur, inst.ob.bbox.x2-dBur, inst.ob.bbox.y2-dBur], bur];
Draw[[burAct, class.lExt, inst.ob.bbox.x2-class.wExt, inst.ob.bbox.y2-class.lExt], pol];
Draw[[lambda, diffBur.y, inst.ob.bbox.x2-diffBur.x, inst.ob.bbox.y2-diffBur.y], inst.ob.layer];
END;
--Mm -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForVia: CD.ObjectClass = RegisterObjectClass[$CMosMmContact];
mmRimWidth: CD.Number = lambda;
cut2min: CD.Number = 3*lambda;
CreateMmCon: PUBLIC PROC [l: CD.Number,
wex: CD.Number,
lex: CD.Number] RETURNS [CD.Object] =
--ignores wex and lex in chipmonk, why???
--connects two layers of metal
BEGIN
cob: CD.Object ~ mmCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
mins: CD.Number = cut2min+2*mmRimWidth;
oldMins: CD.Number = cut2min+2*--mmRimWidth--2*lambda;
l ← MAX[l, mins];
IF l=mins THEN RETURN [CMosObjects.CreateMmCon[]];
cp.typ ← mm2;
--cp.wExt ← ;
--cp.wExt ← ;
cob.class ← pForVia;
IF l<oldMins THEN --new technology; we use new technology only for small sizes--
cob.bbox ← [0, 0, mins, l]
ELSE --old technology--
cob.bbox ← [0, 0, oldMins, l];
cob.layer ← CMos.met;
RETURN [mmCache.ReplaceByAequivalent[cob]]
END;
ReadVia: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateMmCon[TokenIO.ReadInt[h], 0, 0] ]
END;
WriteVia: CD.InternalWriteProc -- PROC [ob: Object] -- =
BEGIN
TokenIO.WriteInt[h, CD.InterestSize[ob].y];
END;
DrawVia: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
--does not read specific !!!!!!
BEGIN
mins: CD.Number = cut2min+2*mmRimWidth;
r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans];
pr.drawRect[r, met, pr];
pr.drawRect[r, met2, pr];
IF inst.ob.bbox.x2>mins THEN --old technology--
pr.drawRect[CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2, pr]
ELSE --new technology--
pr.drawRect[CDBasics.Extend[r, -mmRimWidth], cut2, pr];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
cp: ContactPtr = NARROW[me.specific];
RETURN [
SELECT cp.typ FROM
burr => Rope.Concat["buried contact ", CDOps.LayerRope[me.layer]],
mDif => Rope.Concat[CDOps.LayerRope[me.layer], " contact"],
difShort => Rope.Concat["dif - short contact ", CDOps.LayerRope[me.layer]],
butt => Rope.Concat["butting contact ", CDOps.LayerRope[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;
CDStretchyBackdoor.InstallMatchProc[pForDifPolCon, MatchContact];
pForWellDifPolCon.drawMe ← pForWellDifPolCon.quickDrawMe ← DrawWellDifPolCon;
pForWellDifPolCon.interestRect ← InsideRectWithSurround;
pForWellDifPolCon.showMeSelected ← ShowSelectedWithSurround;
pForWellDifPolCon.internalRead ← ReadDifPolCon;
pForWellDifPolCon.internalWrite ← WriteDifPolCon;
pForWellDifPolCon.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForWellDifPolCon, MatchContact];
pForButContact.internalRead ← ReadButCon;
pForWellButContact.internalRead ← ReadButCon;
pForBurCon.drawMe ← pForBurCon.quickDrawMe ← DrawBurrCon;
pForBurCon.internalRead ← ReadBurCon;
pForBurCon.internalWrite ← WriteBurCon;
pForBurCon.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForBurCon, MatchContact];
pForWellBurCon.drawMe ← pForWellBurCon.quickDrawMe ← DrawWellBurrCon;
pForWellBurCon.interestRect ← InsideRectWithSurround;
pForWellBurCon.internalRead ← ReadBurCon;
pForWellBurCon.internalWrite ← WriteBurCon;
pForWellBurCon.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForWellBurCon, MatchContact];
pForVia.drawMe ← pForVia.quickDrawMe ← DrawVia;
pForVia.internalRead ← ReadVia;
pForVia.internalWrite ← WriteVia;
pForVia.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForVia, MatchContact];
pForDifShorts.internalRead ← ReadDifShortCon;
pForWellDifShorts.internalRead ← ReadDifShortCon;
END;
Init[];
END.