CMosCMTransistorsImpl.mesa (part of Chipndale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi June 24, 1983 5:03 pm
last edited Christian Jacobi March 25, 1986 4:33:38 pm PST
DIRECTORY
Atom,
CMosCMTransistors,
CMosObjects,
CD,
CDBasics,
CDCallSpecific,
CDCommandOps,
CDOrient,
CDIO,
CDLRUCache,
CDStretchyExtras,
CDValue,
CMos,
Rope,
TokenIO;
CMosCMTransistorsImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDBasics, CDCallSpecific, CDCommandOps, CDIO, CDLRUCache, CDOrient, CDStretchyExtras, CDValue, CMos, CMosObjects, Rope, TokenIO
EXPORTS CMosCMTransistors =
BEGIN OPEN CMos;
lambda: CD.Number = CMos.lambda;
undef: CD.Layer = CMosCMTransistors.undef;
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 [] =
BEGIN
pForTransistors.drawMe ← pForTransistors.quickDrawMe ← DrawMeForTransistors;
pForTransistors.internalRead ← ReadTrans;
pForTransistors.internalWrite ← WriteTrans;
pForTransistors.describe ← Describe;
CDStretchyExtras.InstallMatch[pForTransistors, MatchTrans];
CDCallSpecific.Register[$Lengthen, pForTransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForTransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForTransistors, DefaultenTrans];
pForPTypeTransistors.drawMe ← pForPTypeTransistors.quickDrawMe ← DrawPTypeTransistors;
pForPTypeTransistors.internalRead ← ReadTrans;
pForPTypeTransistors.internalWrite ← WriteTrans;
pForPTypeTransistors.interestRect ← InsidePTrans;
pForPTypeTransistors.showMeSelected ← ShowSelectedWithSurround;
pForPTypeTransistors.describe ← Describe;
CDStretchyExtras.InstallMatch[pForPTypeTransistors, MatchTrans];
CDCallSpecific.Register[$Lengthen, pForPTypeTransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForPTypeTransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForPTypeTransistors, DefaultenTrans];
pForATransistors.drawMe ← pForATransistors.quickDrawMe ← DrawMeForATransistors;
pForATransistors.internalRead ← ReadATrans;
pForATransistors.internalWrite ← WriteATrans;
pForATransistors.describe ← Describe;
CDStretchyExtras.InstallMatch[pForATransistors, MatchTrans];
CDCallSpecific.Register[$Lengthen, pForATransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForATransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForATransistors, DefaultenTrans];
pForPTypeATransistors.drawMe ← pForPTypeATransistors.quickDrawMe ← DrawPTypeATransistors;
pForPTypeATransistors.internalRead ← ReadATrans;
pForPTypeATransistors.internalWrite ← WriteATrans;
pForPTypeATransistors.interestRect ← InsideAPTrans;
pForPTypeATransistors.showMeSelected ← ShowSelectedWithSurround;
pForPTypeATransistors.describe ← Describe;
CDStretchyExtras.InstallMatch[pForPTypeATransistors, MatchTrans];
CDCallSpecific.Register[$Lengthen, pForPTypeATransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForPTypeATransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForPTypeATransistors, DefaultenTrans];
END;
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.specificRef ← NEW[TransistorRec];
RETURN [ob]
};
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
RETURN [
Rope.Cat[
IF tp.angle THEN "angle transistor " ELSE "transistor ",
Atom.GetPName[CD.LayerKey[me.layer]],
Rope.Cat[
" [",
CDCommandOps.LambdaRope[tp.width],
CDCommandOps.LambdaRope[tp.length],
"]"
]
]
]
END;
InsidePTrans: PROC [ob: CD.Object] RETURNS [CD.Rect] =
BEGIN
beyondPolyX: CD.Number = MAX[0, wellSurround-NARROW[ob.specificRef, TransistorPtr].wExt];
RETURN [CD.Rect[x1: beyondPolyX, y1: wellSurround, x2: ob.size.x-beyondPolyX, y2: ob.size.y-wellSurround]]
END;
InsideAPTrans: PROC [ob: CD.Object] RETURNS [CD.Rect] =
BEGIN
beyondPolyX: CD.Number = MAX[0, wellSurround-NARROW[ob.specificRef, TransistorPtr].wExt];
RETURN [CD.Rect[x1: beyondPolyX, y1: wellSurround, x2: ob.size.x-wellSurround, y2: ob.size.y-beyondPolyX]]
END;
ShowSelectedWithSurround: PROC [inst: CD.Instance, pos: CD.Position,
orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
pr.drawOutLine[
CDOrient.MapRect[
itemInCell: CD.InterestRect[inst.ob],
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos
],
CD.selectionLayer,
pr]
END;
-- 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.specificRef];
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.size ← [w+2*wExt+2*beyondPolyX, l+2*lExt+2*wellSurround];
}
ELSE {
tob.size ← [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[];
l: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
difLev: CD.Layer = CDIO.ReadLayer[];
RETURN [CreateTransistor[w: w, l: l, wExt: wExt, lExt: lExt, difLev: difLev]];
END;
WriteTrans: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
TokenIO.WriteInt[tp.width];
TokenIO.WriteInt[tp.length];
TokenIO.WriteInt[tp.wExt];
TokenIO.WriteInt[tp.lExt];
CDIO.WriteLayer[me.layer];
END;
DrawMeForTransistors: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
class: TransistorPtr = NARROW[inst.ob.specificRef];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
CDDraw[[class.wExt, 0, class.wExt+class.width, inst.ob.size.y], inst.ob.layer]; -- ndif or pdiff
CDDraw[[0, class.lExt, inst.ob.size.x, class.lExt+class.length], pol];
END;
DrawPTypeTransistors: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
class: TransistorPtr = NARROW[inst.ob.specificRef];
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[[beyondWellX, 0, inst.ob.size.x-beyondWellX, inst.ob.size.y], nwell];
CDDraw[[beyondDiffusionX, wellSurround, inst.ob.size.x-beyondDiffusionX, inst.ob.size.y-wellSurround], inst.ob.layer]; --some diffusion type
CDDraw[[beyondPolyX, class.lExt+wellSurround, inst.ob.size.x-beyondPolyX, inst.ob.size.y-class.lExt-wellSurround], pol];
END;
LengthenTrans: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr = NARROW[inst.ob.specificRef];
new: CD.Object;
amount, sz: CD.Position;
IF x=NIL THEN amount ← [0, lambda]
ELSE IF ISTYPE [x, REF CD.Position] THEN amount ← NARROW[x, REF CD.Position]^
ELSE {done←FALSE; RETURN};
sz ← CDBasics.AddPoints[[x: tp.width, y: tp.length], amount];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
IF tp.angle THEN
new ← CreateAngleTransistor[w: sz.x, l: sz.y,
wExt: tp.wExt, lExt: tp.lExt,
difLev: inst.ob.layer,
aExt: AngleExt[inst.ob]
]
ELSE
new ← CreateTransistor[w: sz.x, l: sz.y,
wExt: tp.wExt, lExt: tp.lExt,
difLev: inst.ob.layer
];
IF new#NIL AND (inst.ob.size#new.size OR NOT Aequivalent[tp, new.specificRef]) THEN inst.ob ← new ELSE done ← FALSE;
repaintMe ← done;
END;
ChangeExtensionTrans: CDCallSpecific.CallProc =
BEGIN
new: CD.Object;
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
amount, sz: CD.Position;
IF x=NIL THEN amount ← [0, lambda]
ELSE IF ISTYPE [x, REF CD.Position] THEN amount ← NARROW[x, REF CD.Position]^
ELSE {done←FALSE; RETURN};
sz ← CDBasics.AddPoints[[x: tp.wExt, y: tp.lExt], amount];
IF sz.x<0 OR sz.y<0 THEN {done ← FALSE; RETURN};
IF tp.angle THEN
new ← CreateAngleTransistor[w: tp.width, l: tp.length,
wExt: sz.x, lExt: sz.y,
difLev: inst.ob.layer,
aExt: AngleExt[inst.ob]
]
ELSE
new ← CreateTransistor[w: tp.width, l: tp.length,
wExt: sz.x, lExt: sz.y,
difLev: inst.ob.layer
];
IF new#NIL THEN inst.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
END;
DefaultenTrans: CDCallSpecific.CallProc =
BEGIN
new: CD.Object;
tp: TransistorPtr = NARROW[inst.ob.specificRef];
IF tp.angle THEN
new ← CreateAngleTransistor[
w: CDValue.FetchInt[design, $NMosTransistorW]*lambda,
l: CDValue.FetchInt[design, $NMosTransistorH]*lambda,
wExt: tp.wExt,
lExt: tp.lExt,
difLev: inst.ob.layer,
aExt: AngleExt[inst.ob]
]
ELSE
new ← CreateTransistor[
w: CDValue.FetchInt[design, $NMosTransistorW]*lambda,
l: CDValue.FetchInt[design, $NMosTransistorH]*lambda,
wExt: tp.wExt,
lExt: tp.lExt,
difLev: inst.ob.layer
];
IF new#NIL THEN inst.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
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.specificRef];
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.size ← [w+l+wExt-aExt+beyondPolyX+wellSurround, wExt+2*lExt+aExt+l+beyondPolyX+wellSurround];
}
ELSE {
tob.size ← [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[];
l: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
aExt: INT = TokenIO.ReadInt[];
difLev: CD.Layer = CDIO.ReadLayer[];
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.specificRef];
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.size.x]
};
RETURN [tp.width+tp.length+tp.wExt-tob.size.x]
};
WriteATrans: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
TokenIO.WriteInt[tp.width];
TokenIO.WriteInt[tp.length];
TokenIO.WriteInt[tp.wExt];
TokenIO.WriteInt[tp.lExt];
TokenIO.WriteInt[AngleExt[me]];
CDIO.WriteLayer[me.layer];
END;
DrawMeForATransistors: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
class: TransistorPtr = NARROW[inst.ob.specificRef];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
--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.
ele: CD.Number = 2*class.lExt+class.length;
hPoly: CD.Rect = [0, class.lExt, inst.ob.size.x-class.lExt, class.length+class.lExt]; -- horizontal
vPoly: CD.Rect = [inst.ob.size.x-class.length-class.lExt, hPoly.y2, hPoly.x2, inst.ob.size.y]; -- vertical
nDrain: CD.Rect = [class.wExt, 0, inst.ob.size.x, hPoly.y1]; -- north
eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, inst.ob.size.y-class.wExt]; -- east
wSource: CD.Rect = [inst.ob.size.x-ele, eDrain.y1, eDrain.x1, inst.ob.size.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, inst.ob.layer];
CDDraw[eDrain, inst.ob.layer];
END;
CDDraw[wSource, inst.ob.layer];
CDDraw[sSource, inst.ob.layer];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
END;
DrawPTypeATransistors: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
class: TransistorPtr = NARROW[inst.ob.specificRef];
CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
--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.
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
ele: CD.Number = 2*class.lExt+class.length;
hPoly: CD.Rect = [beyondPolyX, class.lExt+wellSurround, inst.ob.size.x-class.lExt-wellSurround, class.length+class.lExt+wellSurround]; -- horizontal
vPoly: CD.Rect = [inst.ob.size.x-class.length-class.lExt-wellSurround, hPoly.y2, hPoly.x2, inst.ob.size.y-beyondPolyX]; -- vertical
nDrain: CD.Rect = [beyondDiffusionX, wellSurround, inst.ob.size.x-wellSurround, hPoly.y1]; -- north
eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, inst.ob.size.y-beyondDiffusionX]; -- east
wSource: CD.Rect = [vPoly.x1-class.lExt, eDrain.y1, eDrain.x1, eDrain.y2]; -- west
sSource: CD.Rect = [MIN[beyondDiffusionX, wSource.x1], nDrain.y2, wSource.x1, MIN[hPoly.y2+class.lExt, wSource.y2]]; -- south
IF class.lExt>0 THEN
BEGIN
CDDraw[nDrain, inst.ob.layer];
CDDraw[eDrain, inst.ob.layer];
END;
CDDraw[wSource, inst.ob.layer];
CDDraw[sSource, inst.ob.layer];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
CDDraw[[beyondWellX, 0, inst.ob.size.x, inst.ob.size.y-beyondWellX], nwell];
END;
Init[];
END.