NMosContactsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, June 24, 1983 5:03 pm
Last edited by: Christian Jacobi, October 31, 1986 12:04:52 pm PST
DIRECTORY
NMosContacts,
CD,
CDIO,
CDBasics,
CDBasicsInline,
CDLRUCache,
CDStretchyBackdoor,
NMos,
Rope,
TokenIO;
NMosContactsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDBasicsInline, CDIO, CDLRUCache, CDStretchyBackdoor, NMos, TokenIO
EXPORTS NMosContacts =
BEGIN OPEN NMos;
lambda: CD.Number = NMos.lambda;
ContactType: TYPE = NMosContacts.ContactType;
ContactPtr: TYPE = NMosContacts.ContactPtr;
ContactRec: TYPE = NMosContacts.ContactRec;
wXExtension: CD.Number = 2*lambda;
lXExtension: CD.Number = 2*lambda;
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 [class: CD.Position] =
--y field defaults to lambda, x field defaults to 0
--[0, 0] if not done
BEGIN
IF x=NIL THEN class ← [0, lambda]
ELSE WITH x SELECT FROM
rp: REF CD.Position => class ← rp^;
rn: REF CD.Number => class ← [0, rn^];
ENDCASE => class ← [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.Object] = {
ob: CD.Object ← NEW[CD.ObjectRep];
ob.specific ← NEW[ContactRec];
RETURN [ob]
};
MatchContact: PROC [me: CD.Object, r: CD.Rect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] =
BEGIN
IF layer=me.layer THEN RETURN [TRUE]
ELSE {
cp: ContactPtr = NARROW[me.specific];
RETURN [
SELECT cp.typ FROM
burr => (layer=NMos.pol),
mDif => (layer=NMos.met),
butt => (layer=NMos.met OR layer=NMos.pol),
mPol => (layer=NMos.met),
mm2 => (layer=NMos.met2),
ENDCASE => FALSE
]
}
END;
Describe: CD.DescribeProc =
BEGIN
RETURN [
SELECT NARROW[ob.specific, ContactPtr].typ FROM
burr => "buried contact",
mDif => "dif contact",
butt => "button contact",
mPol => "poly contact",
mm2 => "via",
ENDCASE => "unknown contact"
]
END;
-- Dif and Pol -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifPolCon: CD.ObjectClass ~ RegisterObjectClass[$NMosContactDifAndPol];
difpolRimWidth: CD.Number = lambda;
CreateDifCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] =
--connect diffusion with metal
BEGIN
cob: CD.Object ~ difCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
l ← MAX[l, butConSX];
cp.typ ← mDif;
cob.class ← pForDifPolCon; -- does not use specicRef !
cob.layer ← dif;
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];
l ← MAX[l, butConSX];
cp.typ ← mPol;
cob.class ← pForDifPolCon; -- does not use specicRef !
cob.bbox ← [0, 0, butConSX, l];
cob.layer ← pol;
RETURN [polyCache.ReplaceByAequivalent[cob]]
END;
ReadDifPolCon: CD.InternalReadProc =
BEGIN
layer: CD.Layer = CDIO.ReadLayer[h];
IF layer=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[h]] ]
ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[h]] ]
END;
WriteDifPolCon: CD.InternalWriteProc = {
CDIO.WriteLayer[h, ob.layer];
TokenIO.WriteInt[h, CD.InterestSize[ob].y];
};
DrawDifAndPolContact: CD.DrawProc = {
--does not read specific !!!!!!
r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip] THEN {
pr.drawRect[pr, r, met];
pr.drawRect[pr, r, ob.layer];
pr.drawRect[pr, CDBasics.Extend[r, -difpolRimWidth], cut];
}
};
-- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForButContact: CD.ObjectClass ~ RegisterObjectClass[$NMosContactBut];
butConSX: CD.Number = 4*lambda;
butConSY: CD.Number = 6*lambda;
butContactPolyYS: CD.Number = 3*lambda;
butContactDiffY: CD.Number = butContactPolyYS-lambda;
butContactRimWidth: CD.Number = lambda;
CreateButCon: PUBLIC PROC [] RETURNS [CD.Object] =
--connects metal with poly and diffusion
BEGIN
cob: CD.Object ~ butCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
cp.typ ← butt;
cob.class ← pForButContact;
cob.layer ← dif;
cob.bbox ← [0, 0, butConSX, butConSY];
RETURN [butCache.ReplaceByAequivalent[cob]]
END;
ReadButCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateButCon[] ]
END;
WriteButCon: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
END;
DrawButContact: CD.DrawProc =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l];
};
--DrawButContact
Draw[[0, 0, butConSX, butConSY], met];
Draw[[0, 0, butConSX, butContactPolyYS], pol];
Draw[[0, butContactDiffY, butConSX, butConSY], ob.layer];
Draw[[butContactRimWidth, butContactRimWidth,
butConSX-butContactRimWidth, butConSY-butContactRimWidth], cut]; 
END;
-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForBurCon: CD.ObjectClass ~ RegisterObjectClass[$NMosBurContact];
CreateBurCon: PUBLIC PROC [w, l: CD.Number,
wex: CD.Number←wXExtension,
lex: CD.Number←lXExtension] RETURNS [CD.Object] =
-- connects diffusion with poly without accessing metal
BEGIN
cob: CD.Object ~ burCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specific];
burAct: CD.Number = 2*lambda;
actWidth, xMargins: CD.Number;
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;
cob.class ← pForBurCon;
cob.bbox ← [0, 0, w, l];
cob.layer ← dif;
RETURN [burCache.ReplaceByAequivalent[cob]]
END;
MakeSimilarBur: CDStretchyBackdoor.MakeSimilarProc = {
cp: ContactPtr = NARROW[me.specific];
sz: CD.Position ← CDBasics.SizeOfRect[ir];
RETURN [CreateBurCon[w: sz.x, l: sz.y, wex: cp.wExt, lex: cp.lExt]];
};
ReadBurCon: CD.InternalReadProc =
BEGIN
w: INT = TokenIO.ReadInt[h];
l: INT = TokenIO.ReadInt[h];
wex: INT = TokenIO.ReadInt[h];
lex: INT = TokenIO.ReadInt[h];
RETURN [ CreateBurCon[w, l, wex, lex] ]
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];
END;
DrawMeForBurrNMosContacts: CD.DrawProc =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l];
};
--DrawMeForBurrNMosContacts
class: ContactPtr = NARROW[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, ob.bbox.x2-dBur, ob.bbox.y2-dBur], bur];
Draw[[burAct, class.lExt, ob.bbox.x2-class.wExt, ob.bbox.y2-class.lExt], pol];
Draw[[lambda, diffBur.y, ob.bbox.x2-diffBur.x, ob.bbox.y2-diffBur.y], ob.layer];
END;
-- Mm -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForVia: CD.ObjectClass ~ RegisterObjectClass[$NMosMmContact];
mmRimWidth: CD.Number = lambda;
cut2min: CD.Number = 3*lambda;
CreateMmCon: PUBLIC PROC [l: CD.Number,
wex: CD.Number←wXExtension,
lex: CD.Number←lXExtension] 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];
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 ← ;
RETURN [mmCache.ReplaceByAequivalent[cob]]
END;
ReadVia: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateMmCon[TokenIO.ReadInt[h]] ]
END;
WriteVia: CD.InternalWriteProc =
BEGIN
TokenIO.WriteInt[h, CD.InterestSize[ob].y];
END;
DrawVia: CD.DrawProc =
--does not read specific !!!!!!
BEGIN
mins: CD.Number = cut2min+2*mmRimWidth;
r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans];
pr.drawRect[pr, r, met];
pr.drawRect[pr, r, met2];
IF ob.bbox.x2>mins THEN --old technology--
pr.drawRect[pr, CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2]
ELSE --new technology--
pr.drawRect[pr, CDBasics.Extend[r, -mmRimWidth], cut2];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Init: PROC [] =
BEGIN
pForDifPolCon.drawMe ← pForDifPolCon.quickDrawMe ← DrawDifAndPolContact;
pForDifPolCon.internalRead ← ReadDifPolCon;
pForDifPolCon.internalWrite ← WriteDifPolCon;
pForDifPolCon.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForDifPolCon, MatchContact];
pForButContact.drawMe ← pForButContact.quickDrawMe ← DrawButContact;
pForButContact.internalRead ← ReadButCon;
pForButContact.internalWrite ← WriteButCon;
pForButContact.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForButContact, MatchContact];
pForBurCon.drawMe ← pForBurCon.quickDrawMe ← DrawMeForBurrNMosContacts;
pForBurCon.internalRead ← ReadBurCon;
pForBurCon.internalWrite ← WriteBurCon;
pForBurCon.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForBurCon, MatchContact];
CDStretchyBackdoor.InstallMakeSimilarProc[pForBurCon, MakeSimilarBur];
pForVia.drawMe ← pForVia.quickDrawMe ← DrawVia;
pForVia.internalRead ← ReadVia;
pForVia.internalWrite ← WriteVia;
pForVia.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForVia, MatchContact];
END;
Init[];
END.