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:
PROC[me:
CD.Object]
RETURNS [Rope.
ROPE] =
BEGIN
RETURN [
SELECT
NARROW[me.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:
PROC [inst:
CD.Instance, trans:
CD.Transformation, pr:
CD.DrawRef] = {
--does not read specific !!!!!!
r: CD.Rect = CDBasicsInline.MapRect[inst.ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip]
THEN {
pr.drawRect[r, met, pr];
pr.drawRect[r, inst.ob.layer, pr];
pr.drawRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr];
}
};
-- 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:
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[itemInCell: r, cellInWorld: trans], l, pr];
};
--DrawButContact
Draw[[0, 0, butConSX, butConSY], met];
Draw[[0, 0, butConSX, butContactPolyYS], pol];
Draw[[0, butContactDiffY, butConSX, butConSY], inst.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:
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[itemInCell: r, cellInWorld: trans], l, pr];
};
--DrawMeForBurrNMosContacts
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[$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:
PROC [inst: CD.Instance, trans:
CD.Transformation, pr:
CD.DrawRef] =
--does not read specific !!!!!!
BEGIN
mins: CD.Number = cut2min+2*mmRimWidth;
r: CD.Rect = CDBasicsInline.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;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
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.