CMosTransistorsImpl.mesa (part of Chipndale)
by Christian Jacobi June 24, 1983 5:03 pm
last edited Christian Jacobi December 14, 1983 2:39 pm
DIRECTORY
Atom,
CMosTransistors,
CD,
CDCallSpecific,
CDExtras,
CDInline,
CDOrient,
CDIO,
CDLRUCache,
CDApplications,
CDValue,
CMos,
Rope,
TokenIO;
CMosTransistorsImpl:
CEDAR
PROGRAM
IMPORTS Atom, CD, CDCallSpecific, CDExtras, CDInline, CDIO, CDLRUCache, CDOrient, CDValue, CMos, Rope, TokenIO
EXPORTS CMosTransistors =
BEGIN OPEN CMos;
lambda: CD.DesignNumber = CD.lambda;
undef: CD.Level = CMosTransistors.undef;
depletionOverlap: CD.DesignNumber = (3*lambda)/2;
wXExtension: CD.DesignNumber = CMosTransistors.wXExtension;
lXExtension: CD.DesignNumber = CMosTransistors.lXExtension;
wellSurround: CD.DesignNumber = CMos.wellSurround;
TransistorPtr: TYPE = CMosTransistors.TransistorPtr;
TransistorRec: TYPE = CMosTransistors.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 ← DrawMeForTransistors;
pForTransistors.internalRead ← ReadTrans;
pForTransistors.internalWrite ← WriteTrans;
pForTransistors.describe ← Describe;
pForTransistors.match ← MatchTrans;
CDCallSpecific.Register[$Lengthen, pForTransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForTransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForTransistors, DefaultenTrans];
pForPTypeTransistors.drawMe ← DrawPTypeTransistors;
pForPTypeTransistors.internalRead ← ReadTrans;
pForPTypeTransistors.internalWrite ← WriteTrans;
pForPTypeTransistors.insideRect ← InsidePTrans;
pForPTypeTransistors.showMeSelected ← ShowSelectedWithSurround;
pForPTypeTransistors.hitInside ← HitInsideWithSurround;
pForPTypeTransistors.describe ← Describe;
pForPTypeTransistors.match ← MatchTrans;
CDCallSpecific.Register[$Lengthen, pForPTypeTransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForPTypeTransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForPTypeTransistors, DefaultenTrans];
pForATransistors.drawMe ← DrawMeForATransistors;
pForATransistors.internalRead ← ReadATrans;
pForATransistors.internalWrite ← WriteATrans;
pForATransistors.describe ← Describe;
pForATransistors.match ← MatchTrans;
CDCallSpecific.Register[$Lengthen, pForATransistors, LengthenTrans];
CDCallSpecific.Register[$ChangeExt, pForATransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Default, pForATransistors, DefaultenTrans];
pForPTypeATransistors.drawMe ← DrawPTypeATransistors;
pForPTypeATransistors.internalRead ← ReadATrans;
pForPTypeATransistors.internalWrite ← WriteATrans;
pForPTypeATransistors.insideRect ← InsideAPTrans;
pForPTypeATransistors.showMeSelected ← ShowSelectedWithSurround;
pForPTypeATransistors.hitInside ← HitInsideWithSurround;
pForPTypeATransistors.describe ← Describe;
pForPTypeATransistors.match ← 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.ObPtr] = {
ob: CD.ObPtr ← NEW[CD.ObjectDefinition];
ob.specificRef ← NEW[TransistorRec];
RETURN [ob]
};
Describe:
PROC[me:
CD.ObPtr]
RETURNS [Rope.
ROPE] =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
RETURN [
Rope.Cat[
IF tp.angle THEN "angle transistor " ELSE "transistor ",
Atom.GetPName[CD.LevelKey[me.level]],
" [",
CDExtras.ToLambda[tp.width],
CDExtras.ToLambda[tp.length],
"]"
]
]
END;
InsidePTrans:
PROC [ob:
CD.ObPtr]
RETURNS [
CD.DesignRect] =
BEGIN
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-NARROW[ob.specificRef, TransistorPtr].wExt];
RETURN [CD.DesignRect[x1: beyondPolyX, y1: wellSurround, x2: ob.size.x-beyondPolyX, y2: ob.size.y-wellSurround]]
END;
InsideAPTrans:
PROC [ob:
CD.ObPtr]
RETURNS [
CD.DesignRect] =
BEGIN
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-NARROW[ob.specificRef, TransistorPtr].wExt];
RETURN [CD.DesignRect[x1: beyondPolyX, y1: wellSurround, x2: ob.size.x-wellSurround, y2: ob.size.y-beyondPolyX]]
END;
ShowSelectedWithSurround:
PROC [aptr:
CD.ApplicationPtr, pos:
CD.DesignPosition,
orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
pr.outLineProc[
CDOrient.MapRect[
itemInCell: aptr.ob.p.insideRect[aptr.ob],
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos
],
pr]
END;
HitInsideWithSurround:
PROC [aptr:
CD.ApplicationPtr, hitRect:
CD.DesignRect]
RETURNS [BOOL] =
BEGIN
RETURN [CDInline.Intersect[
CDOrient.MapRect[
itemInCell: aptr.ob.p.insideRect[aptr.ob],
cellSize: aptr.ob.size,
cellInstOrient: aptr.orientation,
cellInstPos: aptr.location
],
hitRect]]
END;
-- Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForTransistors: REF CD.ObjectProcs ~ RegisterObjectType[$CMosTransistor];
pForPTypeTransistors: REF CD.ObjectProcs ~ RegisterObjectType[$CMosPTypeTransistor];
CreateTransistor:
PUBLIC
PROC [w, l:
CD.DesignNumber,
wExt: CD.DesignNumber←wXExtension,
lExt: CD.DesignNumber←lXExtension,
difLev: CD.Level←undef]
RETURNS [
CD.ObPtr] =
BEGIN
tob: CD.ObPtr ← tCache.UnusedOrNew[];
tp: TransistorPtr ← NARROW[tob.specificRef];
IF difLev=undef THEN difLev←ndif;
tob.p ← 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.level ← difLev;
IF difLev=pdif
THEN {
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-tp.wExt];
tob.p ← pForPTypeTransistors;
tob.size ← [w+2*wExt+2*beyondPolyX, l+2*lExt+2*wellSurround];
}
ELSE {
tob.size ← [w+2*wExt, l+2*lExt];
tob.p ← pForTransistors;
};
RETURN [tCache.ReplaceByAequivalent[tob]]
END;
MatchTrans:
PROC [me: CD.ObPtr, r: CD.DesignRect, level: CD.Level, prim:
BOOL, horz:
BOOL]
RETURNS [
BOOL] =
BEGIN
-- Don't care about different diffusions and such
RETURN [level=CMos.pol OR level=me.level]
END;
ReadTrans:
CD.InternalReadProc
--PROC [] RETURNS [ObPtr]-- =
BEGIN
w: INT = TokenIO.ReadInt[];
l: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
difLev: CD.Level = CDIO.ReadLevel[];
RETURN [CreateTransistor[w: w, l: l, wExt: wExt, lExt: lExt, difLev: difLev]];
END;
WriteTrans:
CD.InternalWriteProc
-- PROC [me: ObPtr] -- =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
TokenIO.WriteInt[tp.width];
TokenIO.WriteInt[tp.length];
TokenIO.WriteInt[tp.wExt];
TokenIO.WriteInt[tp.lExt];
CDIO.WriteLevel[me.level];
END;
DrawMeForTransistors:
PROC [aptr:
CD.ApplicationPtr, pos:
CD.DesignPosition, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
p: TransistorPtr = NARROW[aptr.ob.specificRef];
CDDraw:
PROC[r:
CD.DesignRect, l:
CD.Level] =
INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
CDDraw[[p.wExt, 0, p.wExt+p.width, aptr.ob.size.y], aptr.ob.level]; -- ndif or pdiff
CDDraw[[0, p.lExt, aptr.ob.size.x, p.lExt+p.length], pol];
END;
DrawPTypeTransistors:
PROC [aptr:
CD.ApplicationPtr, pos:
CD.DesignPosition, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
CDDraw:
PROC[r:
CD.DesignRect, l:
CD.Level] =
INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
p: TransistorPtr = NARROW[aptr.ob.specificRef];
beyondWellX: CD.DesignNumber = MAX[0, p.wExt-wellSurround]; --object outside well
beyondDiffusionX: CD.DesignNumber = MAX[p.wExt, wellSurround]; --object outside diffusion
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-p.wExt]; --object outside poly
CDDraw[[beyondWellX, 0, aptr.ob.size.x-beyondWellX, aptr.ob.size.y], nwel];
CDDraw[[beyondDiffusionX, wellSurround, aptr.ob.size.x-beyondDiffusionX, aptr.ob.size.y-wellSurround], aptr.ob.level]; --some diffusion type
CDDraw[[beyondPolyX, p.lExt+wellSurround, aptr.ob.size.x-beyondPolyX, aptr.ob.size.y-p.lExt-wellSurround], pol];
END;
LengthenTrans: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr = NARROW[aptr.ob.specificRef];
new: CD.ObPtr;
amount, sz: CD.DesignPosition;
IF x=NIL THEN amount ← [0, lambda]
ELSE IF ISTYPE [x, REF CD.DesignPosition] THEN amount ← NARROW[x, REF CD.DesignPosition]^
ELSE {done←FALSE; RETURN};
sz ← CDInline.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: aptr.ob.level,
aExt: AngleExt[aptr.ob]
]
ELSE
new ← CreateTransistor[w: sz.x, l: sz.y,
wExt: tp.wExt, lExt: tp.lExt,
difLev: aptr.ob.level
];
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
END;
ChangeExtensionTrans: CDCallSpecific.CallProc =
BEGIN
new: CD.ObPtr;
tp: TransistorPtr ← NARROW[aptr.ob.specificRef];
amount, sz: CD.DesignPosition;
IF x=NIL THEN amount ← [0, lambda]
ELSE IF ISTYPE [x, REF CD.DesignPosition] THEN amount ← NARROW[x, REF CD.DesignPosition]^
ELSE {done←FALSE; RETURN};
sz ← CDInline.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: aptr.ob.level,
aExt: AngleExt[aptr.ob]
]
ELSE
new ← CreateTransistor[w: tp.width, l: tp.length,
wExt: sz.x, lExt: sz.y,
difLev: aptr.ob.level
];
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
END;
DefaultenTrans: CDCallSpecific.CallProc =
BEGIN
new: CD.ObPtr;
tp: TransistorPtr = NARROW[aptr.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: aptr.ob.level,
aExt: AngleExt[aptr.ob]
]
ELSE
new ← CreateTransistor[
w: CDValue.FetchInt[design, $NMosTransistorW]*lambda,
l: CDValue.FetchInt[design, $NMosTransistorH]*lambda,
wExt: tp.wExt,
lExt: tp.lExt,
difLev: aptr.ob.level
];
IF new#NIL THEN aptr.ob ← new ELSE done ← FALSE;
repaintMe ← TRUE;
END;
-- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForATransistors: REF CD.ObjectProcs ~ RegisterObjectType[$CMosATransistor];
pForPTypeATransistors: REF CD.ObjectProcs ~ RegisterObjectType[$CMosPTypeATransistor];
CreateAngleTransistor:
PUBLIC
PROC [w, l:
CD.DesignNumber,
wExt: CD.DesignNumber←wXExtension,
lExt: CD.DesignNumber←lXExtension,
aExt: CD.DesignNumber𡤀,
difLev: CD.Level←undef]
RETURNS [CD.ObPtr] =
BEGIN
tob: CD.ObPtr ← 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.level ← difLev;
IF difLev=pdif
THEN {
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-tp.wExt];
tob.p ← 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.p ← pForATransistors;
};
RETURN [aCache.ReplaceByAequivalent[tob]]
END;
ReadATrans:
CD.InternalReadProc
--PROC [] RETURNS [ObPtr]-- =
BEGIN
w: INT = TokenIO.ReadInt[];
l: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
aExt: INT = TokenIO.ReadInt[];
difLev: CD.Level = CDIO.ReadLevel[];
RETURN [ CreateAngleTransistor[w: w, l: l, wExt: wExt, lExt: lExt, aExt: aExt, difLev: difLev] ];
END;
AngleExt:
PROC[tob:
CD.ObPtr]
RETURNS [
CD.DesignNumber] = {
tp: TransistorPtr = NARROW[tob.specificRef];
IF tob.level=pdif
OR tob.level=nwelCont
THEN {
beyondPolyX: CD.DesignNumber = 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: ObPtr] -- =
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.WriteLevel[me.level];
END;
DrawMeForATransistors:
PROC [aptr:
CD.ApplicationPtr, pos:
CD.DesignPosition, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
p: TransistorPtr = NARROW[aptr.ob.specificRef];
CDDraw:
PROC[r:
CD.DesignRect, l:
CD.Level] =
INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.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.DesignNumber = 2*p.lExt+p.length;
hPoly: CD.DesignRect = [0, p.lExt, aptr.ob.size.x-p.lExt, p.length+p.lExt]; -- horizontal
vPoly: CD.DesignRect = [aptr.ob.size.x-p.length-p.lExt, hPoly.y2, hPoly.x2, aptr.ob.size.y]; -- vertical
nDrain: CD.DesignRect = [p.wExt, 0, aptr.ob.size.x, hPoly.y1]; -- north
eDrain: CD.DesignRect = [vPoly.x2, nDrain.y2, nDrain.x2, aptr.ob.size.y-p.wExt]; -- east
wSource: CD.DesignRect = [aptr.ob.size.x-ele, eDrain.y1, eDrain.x1, aptr.ob.size.y-p.wExt]; -- west
sSource: CD.DesignRect = [MIN[p.wExt, wSource.x1], nDrain.y2, wSource.x1, MIN[ele, wSource.y2]]; -- south
IF p.lExt>0
THEN
BEGIN
CDDraw[nDrain, aptr.ob.level];
CDDraw[eDrain, aptr.ob.level];
END;
CDDraw[wSource, aptr.ob.level];
CDDraw[sSource, aptr.ob.level];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
END;
DrawPTypeATransistors:
PROC [aptr: CD.ApplicationPtr, pos:
CD.DesignPosition, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
p: TransistorPtr = NARROW[aptr.ob.specificRef];
CDDraw:
PROC[r:
CD.DesignRect, l:
CD.Level] =
INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: aptr.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.DesignNumber = MAX[0, p.wExt-wellSurround]; --object outside well
beyondDiffusionX: CD.DesignNumber = MAX[p.wExt, wellSurround]; --object outside diffusion
beyondPolyX: CD.DesignNumber = MAX[0, wellSurround-p.wExt]; --object outside poly
ele: CD.DesignNumber = 2*p.lExt+p.length;
hPoly: CD.DesignRect = [beyondPolyX, p.lExt+wellSurround, aptr.ob.size.x-p.lExt-wellSurround, p.length+p.lExt+wellSurround]; -- horizontal
vPoly: CD.DesignRect = [aptr.ob.size.x-p.length-p.lExt-wellSurround, hPoly.y2, hPoly.x2, aptr.ob.size.y-beyondPolyX]; -- vertical
nDrain: CD.DesignRect = [beyondDiffusionX, wellSurround, aptr.ob.size.x-wellSurround, hPoly.y1]; -- north
eDrain: CD.DesignRect = [vPoly.x2, nDrain.y2, nDrain.x2, aptr.ob.size.y-beyondDiffusionX]; -- east
wSource: CD.DesignRect = [vPoly.x1-p.lExt, eDrain.y1, eDrain.x1, eDrain.y2]; -- west
sSource: CD.DesignRect = [MIN[beyondDiffusionX, wSource.x1], nDrain.y2, wSource.x1, MIN[hPoly.y2+p.lExt, wSource.y2]]; -- south
IF p.lExt>0
THEN
BEGIN
CDDraw[nDrain, aptr.ob.level];
CDDraw[eDrain, aptr.ob.level];
END;
CDDraw[wSource, aptr.ob.level];
CDDraw[sSource, aptr.ob.level];
CDDraw[hPoly, pol];
CDDraw[vPoly, pol];
CDDraw[[beyondWellX, 0, aptr.ob.size.x, aptr.ob.size.y-beyondWellX], nwel];
END;
Init[];
END.