CMosCMTransistorsImpl.mesa (part of Chipndale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi June 24, 1983 5:03 pm
Last edited by: Christian Jacobi, October 31, 1986 4:12:31 pm PST
DIRECTORY
Atom,
CMosCMTransistors,
CMosObjects,
CD,
CDBasics,
CDIO,
CDLRUCache,
CDOps,
CDStretchyBackdoor,
CMos,
Rope,
TokenIO;
CMosCMTransistorsImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDBasics, CDIO, CDLRUCache, CDOps, CDStretchyBackdoor, CMos, CMosObjects, Rope, TokenIO
EXPORTS CMosCMTransistors =
BEGIN OPEN CMos;
lambda: CD.Number = CMos.lambda;
undef: CD.Layer = CD.undefLayer;
depletionOverlap: CD.Number = (3*lambda)/2;
wXExtension: CD.Number = CMosCMTransistors.wXExtension;
lXExtension: CD.Number = CMosCMTransistors.lXExtension;
wellSurround: CD.Number = CMos.wellSurround;
TransistorPtr: TYPE = CMosCMTransistors.TransistorPtr;
TransistorRec: TYPE = CMosCMTransistors.TransistorRec;
tCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 15, aequivalenceProc: Aequivalent, newProc: NewTrans];
aCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 15, aequivalenceProc: Aequivalent, newProc: NewTrans];
Init: PROC [] = {
pForTransistors.drawMe ← pForTransistors.quickDrawMe ← DrawMeForTransistors;
pForTransistors.internalRead ← ReadTrans;
pForTransistors.internalWrite ← WriteTrans;
pForTransistors.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForTransistors, MatchTrans];
pForPTypeTransistors.drawMe ← pForPTypeTransistors.quickDrawMe ← DrawPTypeTransistors;
pForPTypeTransistors.internalRead ← ReadTrans;
pForPTypeTransistors.internalWrite ← WriteTrans;
pForPTypeTransistors.interestRect ← PTransInterestRect;
pForPTypeTransistors.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForPTypeTransistors, MatchTrans];
pForATransistors.drawMe ← pForATransistors.quickDrawMe ← DrawMeForATransistors;
pForATransistors.internalRead ← ReadATrans;
pForATransistors.internalWrite ← WriteATrans;
pForATransistors.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForATransistors, MatchTrans];
pForPTypeATransistors.drawMe ← pForPTypeATransistors.quickDrawMe ← DrawPTypeATransistors;
pForPTypeATransistors.internalRead ← ReadATrans;
pForPTypeATransistors.internalWrite ← WriteATrans;
pForPTypeATransistors.interestRect ← APTransInterestRect;
pForPTypeATransistors.describe ← Describe;
CDStretchyBackdoor.InstallMatchProc[pForPTypeATransistors, MatchTrans];
};
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]
};
Describe: CD.DescribeProc = {
tp: TransistorPtr = NARROW[ob.specific];
RETURN [
Rope.Cat[
(IF tp.angle THEN "angle transistor " ELSE "transistor "),
Atom.GetPName[CD.LayerKey[ob.layer]],
Rope.Cat[
" [",
CDOps.LambdaRope[tp.width, 2],
CDOps.LambdaRope[tp.length, 2],
"]"
]
]
]
};
PTransInterestRect: PROC [ob: CD.Object] RETURNS [CD.Rect] = {
beyondPolyX: CD.Number = MAX[0, wellSurround-NARROW[ob.specific, TransistorPtr].wExt];
RETURN [CD.Rect[x1: 0, y1: 0, x2: ob.bbox.x2-beyondPolyX, y2: ob.bbox.y2-wellSurround]]
};
APTransInterestRect: PROC [ob: CD.Object] RETURNS [CD.Rect] = {
beyondPolyX: CD.Number = MAX[0, wellSurround-NARROW[ob.specific, TransistorPtr].wExt];
RETURN [CD.Rect[x1: 0, y1: 0, x2: ob.bbox.x2-wellSurround, y2: ob.bbox.y2-beyondPolyX]]
?? RETURN [CD.Rect[x1: beyondPolyX, y1: wellSurround, x2: ob.size.x-wellSurround, y2: ob.size.y-beyondPolyX]]
};
-- Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForTransistors: CD.ObjectClass ~ RegisterObjectClass[$CMosTransistor];
pForPTypeTransistors: CD.ObjectClass ~ RegisterObjectClass[$CMosPTypeTransistor];
CreateTransistor: PUBLIC PROC [w, l: CD.Number, wExt: CD.Number←wXExtension, lExt: CD.Number←lXExtension, difLev: CD.Layer←undef] RETURNS [CD.Object] =
BEGIN
tob: CD.Object ← tCache.UnusedOrNew[];
tp: TransistorPtr ← NARROW[tob.specific];
IF difLev=undef THEN difLev←ndif;
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;
tp.angle ← FALSE;
tob.layer ← difLev;
IF difLev=pdif THEN {
beyondPolyX: CD.Number = MAX[0, wellSurround-tp.wExt];
tob.class ← pForPTypeTransistors;
tob.bbox ← [-beyondPolyX, -wellSurround, w+2*wExt+beyondPolyX, l+2*lExt+wellSurround];
}
ELSE {
tob.bbox ← [0, 0, w+2*wExt, l+2*lExt];
tob.class ← pForTransistors;
};
IF wExt=wXExtension AND lExt=lXExtension THEN {
IF difLev=CMos.pdif THEN difLev ← CMos.wpdif;
RETURN [CMosObjects.CreateTransistor[[w+2*wExt, l+2*lExt], difLev]]
};
RETURN [tCache.ReplaceByAequivalent[tob]]
END;
MatchTrans: 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
RETURN [layer=CMos.pol OR layer=me.layer]
END;
ReadTrans: 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];
difLev: CD.Layer = CDIO.ReadLayer[h];
RETURN [CreateTransistor[w: w, l: l, wExt: wExt, lExt: lExt, difLev: difLev]];
END;
WriteTrans: CD.InternalWriteProc -- PROC [ob: Object] -- =
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];
CDIO.WriteLayer[h, ob.layer];
END;
DrawMeForTransistors: CD.DrawProc =
BEGIN
class: TransistorPtr = NARROW[ob.specific];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
--uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[r, trans], l]
};
CDDraw[[class.wExt, 0, class.wExt+class.width, ob.bbox.y2], ob.layer]; -- ndif or pdiff
CDDraw[[0, class.lExt, ob.bbox.x2, class.lExt+class.length], pol];
END;
DrawPTypeTransistors: CD.DrawProc =
BEGIN
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[r, trans], l]
};
class: TransistorPtr = NARROW[ob.specific];
beyondWellX: CD.Number = MAX[0, class.wExt-wellSurround]; --object outside well
beyondDiffusionX: CD.Number = MAX[class.wExt, wellSurround]; --object outside diffusion
beyondPolyX: CD.Number = MAX[0, wellSurround-class.wExt]; --object outside poly
CDDraw[ob.bbox, nwell];
CDDraw[[class.wExt, 0, class.wExt+class.width, ob.bbox.y2-wellSurround], ob.layer]; -- dif or pdiff
CDDraw[[0, class.lExt, ob.bbox.x2-beyondPolyX, class.lExt+class.length], pol];
END;
-- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForATransistors: CD.ObjectClass ~ RegisterObjectClass[$CMosATransistor];
pForPTypeATransistors: CD.ObjectClass ~ RegisterObjectClass[$CMosPTypeATransistor];
CreateAngleTransistor: PUBLIC PROC [w, l: CD.Number,
wExt: CD.Number←wXExtension,
lExt: CD.Number←lXExtension,
aExt: CD.Number𡤀,
difLev: CD.Layer←undef]
RETURNS [CD.Object] =
BEGIN
tob: CD.Object ← aCache.UnusedOrNew[];
tp: TransistorPtr ← NARROW[tob.specific];
IF difLev=undef THEN difLev←ndif;
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;
tp.angle ← TRUE;
tob.layer ← difLev;
IF difLev=pdif THEN {
beyondPolyX: CD.Number = MAX[0, wellSurround-tp.wExt];
tob.class ← pForPTypeATransistors;
tob.bbox ← [-beyondPolyX, -wellSurround, w+l+wExt-aExt+wellSurround, wExt+2*lExt+aExt+l+beyondPolyX];
}
ELSE {
tob.bbox ← [0, 0, w+l+wExt-aExt, wExt+2*lExt+aExt+l];
tob.class ← pForATransistors;
};
RETURN [aCache.ReplaceByAequivalent[tob]]
END;
ReadATrans: 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];
aExt: INT = TokenIO.ReadInt[h];
difLev: CD.Layer = CDIO.ReadLayer[h];
RETURN [ CreateAngleTransistor[w: w, l: l, wExt: wExt, lExt: lExt, aExt: aExt, difLev: difLev] ];
END;
AngleExt: PROC[tob: CD.Object] RETURNS [CD.Number] = {
tp: TransistorPtr = NARROW[tob.specific];
IF tob.layer=pdif OR tob.layer=nwellCont THEN {
beyondPolyX: CD.Number = MAX[0, wellSurround-tp.wExt];
RETURN [tp.width+tp.length+tp.wExt+beyondPolyX+wellSurround-tob.bbox.x2+tob.bbox.x1]
};
RETURN [tp.width+tp.length+tp.wExt-tob.bbox.x2]
};
WriteATrans: CD.InternalWriteProc -- PROC [ob: Object] -- =
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];
TokenIO.WriteInt[h, AngleExt[ob]];
CDIO.WriteLayer[h, ob.layer];
END;
DrawMeForATransistors: CD.DrawProc =
BEGIN
class: TransistorPtr = NARROW[ob.specific];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[r, trans], l]
};
--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 = CDBasics.MapRect[ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip] THEN {
ele: CD.Number = 2*class.lExt+class.length;
sz: CD.Position ← CDBasics.SizeOfRect[ob.bbox];
hPoly: CD.Rect = [0, class.lExt, sz.x-class.lExt, class.length+class.lExt]; -- horizontal
vPoly: CD.Rect = [sz.x-class.length-class.lExt, hPoly.y2, hPoly.x2, sz.y]; -- vertical
nDrain: CD.Rect = [class.wExt, 0, sz.x, hPoly.y1]; -- north
eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, sz.y-class.wExt]; -- east
wSource: CD.Rect = [sz.x-ele, eDrain.y1, eDrain.x1, sz.y-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
BEGIN
CDDraw[nDrain, ob.layer];
CDDraw[eDrain, ob.layer];
END;
CDDraw[wSource, ob.layer];
CDDraw[sSource, ob.layer];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
}
END;
DrawPTypeATransistors: CD.DrawProc =
BEGIN
class: TransistorPtr = NARROW[ob.specific];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE {
uses outer stuff!!
pr.drawRect[pr, CDBasics.MapRect[r, trans], l]
};
--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 = CDBasics.MapRect[ob.bbox, trans];
IF CDBasics.Intersect[r, pr.interestClip] THEN {
sz: CD.Position ← CD.InterestSize[ob];
ele: CD.Number = 2*class.lExt+class.length;
hPoly: CD.Rect = [0, class.lExt, sz.x-class.lExt, class.length+class.lExt]; -- horizontal
vPoly: CD.Rect = [sz.x-class.length-class.lExt, hPoly.y2, hPoly.x2, sz.y]; -- vertical
nDrain: CD.Rect = [class.wExt, 0, sz.x, hPoly.y1]; -- north
eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, sz.y-class.wExt]; -- east
wSource: CD.Rect = [sz.x-ele, eDrain.y1, eDrain.x1, sz.y-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
BEGIN
CDDraw[nDrain, ob.layer];
CDDraw[eDrain, ob.layer];
END;
CDDraw[wSource, ob.layer];
CDDraw[sSource, ob.layer];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
CDDraw[ob.bbox, nwell];
}
END;
Init[];
END.