NMosTransistorsImpl.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 11:59:45 am PST
DIRECTORY
CD,
CDBasics,
CDIO,
CDBasicsInline,
CDLRUCache,
CDOps,
CDStretchyBackdoor,
NMos,
NMosTransistors,
Rope,
TokenIO;
NMosTransistorsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDBasicsInline, CDIO, CDLRUCache, CDOps, CDStretchyBackdoor, NMos, Rope, TokenIO
EXPORTS NMosTransistors =
BEGIN OPEN NMos;
lambda: CD.Number = NMos.lambda;
depletionOverlap: CD.Number = (3*lambda)/2;
wXExtension: CD.Number = NMosTransistors.wXExtension;
lXExtension: CD.Number = NMosTransistors.lXExtension;
TransistorPtr: TYPE = NMosTransistors.TransistorPtr;
TransistorRec: TYPE = NMosTransistors.TransistorRec;
tCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 10, aequivalenceProc: Aequivalent, newProc: NewTrans];
aCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 10, aequivalenceProc: Aequivalent, newProc: NewTrans];
pCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 10, aequivalenceProc: Aequivalent, newProc: NewTrans];
Aequivalent: PROC[mySpecific, other: REF ANY] RETURNS [BOOL] = {
WITH other SELECT FROM
tp2: TransistorPtr => RETURN [NARROW[mySpecific, TransistorPtr]^=tp2^];
ENDCASE => RETURN [FALSE]
};
NewTrans: PROC [] RETURNS [CD.Object] = {
ob: CD.Object ~ NEW[CD.ObjectRep];
ob.specific ← NEW[TransistorRec];
RETURN [ob]
};
Init: PROC [] =
BEGIN
pForTransistors.drawMe ← pForTransistors.quickDrawMe ← DrawMeForTransistors;
pForTransistors.internalRead ← ReadTrans;
pForTransistors.internalWrite ← WriteTrans;
pForTransistors.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForTransistors, MatchTrans];
CDStretchyBackdoor.InstallMakeSimilarProc[pForTransistors, MakeSimilarTrans];
pForATransistors.drawMe ← pForATransistors.quickDrawMe ← DrawMeForATransistors;
pForATransistors.internalRead ← ReadATrans;
pForATransistors.internalWrite ← WriteATrans;
pForPullUps.drawMe ← pForPullUps.quickDrawMe ← DrawMeForPullUps;
pForPullUps.internalRead ← ReadPull;
pForPullUps.internalWrite ← WritePull;
pForPullUps.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForPullUps, MatchTrans];
END;
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
tp: TransistorPtr = NARROW[me.specific];
r: Rope.ROPE;
IF tp.pullup THEN r ← "pullup "
ELSE {
r ← "transistor ";
IF tp.angle THEN r ← Rope.Concat["angle ", r];
r ← Rope.Concat[r,
SELECT tp.implant FROM
NMosTransistors.enhancement => "enh ",
NMosTransistors.zeroTresh => "0-tresh ",
NMosTransistors.weakDepletion => "wk depl ",
NMosTransistors.strongDepletion => "depl ",
ENDCASE => "ERROR"
]
};
r ← Rope.Cat[
r,
" [",
CDOps.LambdaRope[tp.width, 2],
CDOps.LambdaRope[tp.length, 2],
"]"
];
RETURN [r]
END;
MatchTrans: PROC [me: CD.Object, r: CD.Rect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] =
BEGIN
RETURN [layer=NMos.pol OR layer=me.layer]
END;
-- Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForTransistors: CD.ObjectClass = RegisterObjectClass[$NMosTransistor];
CreateTransistor: PUBLIC PROC [w, l: CD.Number,
implant: NMosTransistors.Implant←NMosTransistors.enhancement,
wExt: CD.Number←wXExtension,
lExt: CD.Number←lXExtension]
RETURNS [CD.Object] =
BEGIN
tob: CD.Object ~ tCache.UnusedOrNew[];
tp: TransistorPtr ~ NARROW[tob.specific];
tob.class ← pForTransistors;
w ← MAX[w, 2*lambda];
l ← MAX[l, 2*lambda];
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
tp.width ← w;
tp.length ← l;
tp.wExt ← wExt;
tp.lExt ← lExt;
tob.bbox ← [0, 0, w+2*wExt, l+2*lExt];
tp.implant ← implant;
tp.angle ← FALSE;
tp.pullup ← FALSE;
tob.layer ← dif;
RETURN [tCache.ReplaceByAequivalent[tob]]
END;
ReadTrans: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
w: INT = TokenIO.ReadInt[h];
l: INT = TokenIO.ReadInt[h];
implant: INT = TokenIO.ReadInt[h];
wExt: INT = TokenIO.ReadInt[h];
lExt: INT = TokenIO.ReadInt[h];
IF ~h.oldVersion AND CDIO.VersionKey[h]>=2 THEN
RETURN [CreateTransistor[w: w, l: l, implant: implant, wExt: wExt, lExt: lExt]]
ELSE
RETURN [CreateTransistor[w: w, l: l, implant: (IF implant=1 THEN 3 ELSE 0), wExt: wExt, lExt: lExt]];
END;
MakeSimilarTrans: CDStretchyBackdoor.MakeSimilarProc = {
tp: TransistorPtr = NARROW[me.specific];
sz: CD.Position ← CDBasics.SizeOfRect[ir];
RETURN [ CreateTransistor[w: sz.x-2*tp.wExt, l: sz.y-2*tp.lExt, wExt: tp.wExt, lExt: tp.lExt,implant: tp.implant] ];
};
WriteTrans: CD.InternalWriteProc =
BEGIN
tp: TransistorPtr = NARROW[ob.specific];
TokenIO.WriteInt[h, tp.width];
TokenIO.WriteInt[h, tp.length];
TokenIO.WriteInt[h, tp.implant];
TokenIO.WriteInt[h, tp.wExt];
TokenIO.WriteInt[h, tp.lExt];
END;
AngleExt: PROC[tob: CD.Object] RETURNS [CD.Number] = {
tp: TransistorPtr = NARROW[tob.specific];
RETURN [tp.width+tp.length+tp.wExt-tob.bbox.x2]
};
DrawMeForTransistors: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
class: TransistorPtr = NARROW[inst.ob.specific];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l, pr];
};
CDDraw[[class.wExt, 0, class.wExt+class.width, inst.ob.bbox.y2], inst.ob.layer]; -- dif or pdiff
CDDraw[[0, class.lExt, inst.ob.bbox.x2, class.lExt+class.length], pol];
IF class.implant>0 THEN
CDDraw[[class.wExt-depletionOverlap, class.lExt-depletionOverlap,
inst.ob.bbox.x2-class.wExt+depletionOverlap, inst.ob.bbox.y2-class.lExt+depletionOverlap],
SELECT class.implant FROM
NMosTransistors.strongDepletion => imp,
NMosTransistors.weakDepletion => impWeak,
NMosTransistors.zeroTresh => imp0,
NMosTransistors.enhancement => CD.errorLayer,
ENDCASE => CD.errorLayer
];
END;
-- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForATransistors: CD.ObjectClass = RegisterObjectClass[$NMosATransistor];
CreateAngleTransistor: PUBLIC PROC [w, l: CD.Number,
implant: NMosTransistors.Implant←NMosTransistors.enhancement,
wExt: CD.Number←wXExtension,
lExt: CD.Number←lXExtension,
aExt: CD.Number𡤀]
RETURNS [CD.Object] =
BEGIN
tob: CD.Object ← aCache.UnusedOrNew[];
tp: TransistorPtr ← NARROW[tob.specific];
tob.class ← pForATransistors;
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
aExt ← MAX[aExt, -lExt];
w ← MAX[w, 2*lExt]; -- the width of the straight-line
-- parts of the gate, excluding corner
l ← MAX[l, 2*lambda];
tp.width ← w;
tp.length ← l;
tp.wExt ← wExt;
tp.lExt ← lExt;
tob.bbox ← [0, 0, w+l+wExt-aExt, wExt+2*lExt+aExt+l];
tp.implant ← implant;
tp.angle ← TRUE;
tp.pullup ← FALSE;
tob.layer ← dif;
RETURN [aCache.ReplaceByAequivalent[tob]]
END;
ReadATrans: CD.InternalReadProc =
BEGIN
w: INT = TokenIO.ReadInt[h];
l: INT = TokenIO.ReadInt[h];
implant: INT = TokenIO.ReadInt[h];
wExt: INT = TokenIO.ReadInt[h];
lExt: INT = TokenIO.ReadInt[h];
aExt: INT = TokenIO.ReadInt[h];
IF ~h.oldVersion AND CDIO.VersionKey[h]>=2 THEN
RETURN [ CreateAngleTransistor[w: w, l: l, implant: implant, wExt: wExt, lExt: lExt, aExt: aExt] ]
ELSE
RETURN [ CreateAngleTransistor[w: w, l: l, implant: (IF implant=1 THEN 3 ELSE 0), wExt: wExt, lExt: lExt, aExt: aExt] ];
END;
WriteATrans: CD.InternalWriteProc =
BEGIN
tp: TransistorPtr = NARROW[ob.specific];
TokenIO.WriteInt[h, tp.width];
TokenIO.WriteInt[h, tp.length];
TokenIO.WriteInt[h, tp.implant];
TokenIO.WriteInt[h, tp.wExt];
TokenIO.WriteInt[h, tp.lExt];
TokenIO.WriteInt[h, tp.width+tp.length+tp.wExt-CD.InterestSize[ob].x];
END;
DrawMeForATransistors: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
class: TransistorPtr = NARROW[inst.ob.specific];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l, pr];
};
--The transistor makes a 90-degree bend, going eastward and
--then southward. The diffusion on the outer side of the angle,
--that is, on the northeast side, is arbitrarily called the drain.
r: CD.Rect = CDBasicsInline.MapRect[inst.ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip] THEN
BEGIN
ele: CD.Number = 2*class.lExt+class.length;
hPoly: CD.Rect = [0, class.lExt, inst.ob.bbox.x2-class.lExt, class.length+class.lExt]; -- horizontal
vPoly: CD.Rect = [inst.ob.bbox.x2-class.length-class.lExt, hPoly.y2, hPoly.x2, inst.ob.bbox.y2]; -- vertical
nDrain: CD.Rect = [class.wExt, 0, inst.ob.bbox.x2, hPoly.y1]; -- north
eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, inst.ob.bbox.y2-class.wExt]; -- east
wSource: CD.Rect = [inst.ob.bbox.x2-ele, eDrain.y1, eDrain.x1, inst.ob.bbox.y2-class.wExt]; -- west
sSource: CD.Rect = [MIN[class.wExt, wSource.x1], nDrain.y2, wSource.x1, MIN[ele, wSource.y2]]; -- south
IF class.lExt>0 THEN {
CDDraw[nDrain, inst.ob.layer];
CDDraw[eDrain, inst.ob.layer];
};
CDDraw[wSource, inst.ob.layer];
CDDraw[sSource, inst.ob.layer];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
IF class.implant>0 THEN {
CDDraw[[nDrain.x1-depletionOverlap, hPoly.y1-depletionOverlap,
hPoly.x2+depletionOverlap, hPoly.y2+depletionOverlap],
imp];
CDDraw[[vPoly.x1-depletionOverlap, vPoly.y1-depletionOverlap,
vPoly.x2+depletionOverlap, eDrain.y2+depletionOverlap],
imp];
}
END
END;
-- PullUp -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForPullUps: CD.ObjectClass = RegisterObjectClass[$NMosPullUp];
CreatePullUp: PUBLIC PROC [w, l: CD.Number,
wExt: CD.Number←wXExtension,
lExt: CD.Number←lXExtension]
RETURNS [CD.Object] =
BEGIN
puob: CD.Object ~ pCache.UnusedOrNew[];
pup: TransistorPtr ~ NARROW[puob.specific];
w ← MAX[w, 2*lambda];
l ← MAX[l, 2*lambda];
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
pup.wExt ← wExt;
pup.lExt ← lExt;
pup.width ← w;
pup.length ← l;
pup.pullup ← TRUE;
puob.class ← pForPullUps;
puob.bbox ← [0, 0, MAX[4*lambda, w+wExt*2], MAX[6*lambda, l+lExt+3*lambda]];
puob.layer ← dif;
RETURN [pCache.ReplaceByAequivalent[puob]]
END;
ReadPull: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
w: INT = TokenIO.ReadInt[h];
l: INT = TokenIO.ReadInt[h];
wExt: INT = TokenIO.ReadInt[h];
lExt: INT = TokenIO.ReadInt[h];
RETURN [ CreatePullUp[w: w, l: l, wExt: wExt, lExt: lExt] ];
END;
WritePull: CD.InternalWriteProc =
BEGIN
tp: TransistorPtr = NARROW[ob.specific];
TokenIO.WriteInt[h, tp.width];
TokenIO.WriteInt[h, tp.length];
TokenIO.WriteInt[h, tp.wExt];
TokenIO.WriteInt[h, tp.lExt];
END;
DrawMeForPullUps: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] =
BEGIN
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l, pr];
};
r: CD.Rect = CDBasicsInline.MapRect[inst.ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip] THEN {
class: TransistorPtr = NARROW[inst.ob.specific];
middleX: CD.Number = inst.ob.bbox.x2/2;
metal: CD.Rect = [x1: middleX-2*lambda, y1: inst.ob.bbox.y2-6*lambda,
x2: middleX+2*lambda, y2: inst.ob.bbox.y2];
CDDraw[[class.wExt, 0, class.wExt+class.width, inst.ob.bbox.y2], inst.ob.layer];
CDDraw[[0, class.lExt, inst.ob.bbox.x2, class.lExt+class.length], pol];
CDDraw[[0, 0, inst.ob.bbox.x2, inst.ob.bbox.y2-lambda], imp];
CDDraw[[metal.x1, metal.y1+2*lambda, metal.x2, metal.y2], inst.ob.layer];
CDDraw[metal, met];
CDDraw[[metal.x1+lambda, metal.y1+lambda, metal.x2-lambda, metal.y2-lambda], cut];
}
END;
Init[];
END.