NMosTransistorsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, June 24, 1983 5:03 pm
last edited Christian Jacobi, May 29, 1985 10:42:11 am PDT
DIRECTORY
CD,
CDCallSpecific,
CDExtras,
CDBasics,
CDIO,
CDLRUCache,
CDOrient,
CDStretchyExtras,
CDValue,
NMos,
NMosTransistors,
Rope,
TokenIO;
NMosTransistorsImpl: CEDAR PROGRAM
IMPORTS CDCallSpecific, CDExtras, CDBasics, CDIO, CDLRUCache, CDOrient, CDStretchyExtras, CDValue, NMos, Rope, TokenIO
EXPORTS NMosTransistors =
BEGIN OPEN NMos;
lambda: CD.Number = CD.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.specificRef ← NEW[TransistorRec];
RETURN [ob]
};
Init: PROC [] =
BEGIN
pForTransistors.drawMe ← pForTransistors.quickDrawMe ← DrawMeForTransistors;
pForTransistors.internalRead ← ReadTrans;
pForTransistors.internalWrite ← WriteTrans;
pForTransistors.describe ← Describe;
CDStretchyExtras.InstallMatch[pForTransistors, MatchTrans];
CDCallSpecific.Register[$ChangeExt, pForTransistors, ChangeExtensionTrans];
CDCallSpecific.Register[$Lengthen, pForTransistors, LengthenTrans];
CDCallSpecific.Register[$Default, pForTransistors, DefaultenTrans];
CDCallSpecific.Register[$SetLength, pForTransistors, SetLengthTrans];
CDCallSpecific.Register[$SetWidth, pForTransistors, SetWidthTrans];
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;
CDStretchyExtras.InstallMatch[pForPullUps, MatchTrans];
CDCallSpecific.Register[$ChangeExt, pForPullUps, ChangeExtensionPullUps];
CDCallSpecific.Register[$Lengthen, pForPullUps, LengthenPullUps];
CDCallSpecific.Register[$Default, pForPullUps, DefaultenPullUps];
CDCallSpecific.Register[$SetLength, pForPullUps, SetLengthPullUps];
CDCallSpecific.Register[$SetWidth, pForPullUps, SetWidthPullUps];
END;
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
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,
" [",
CDExtras.ToLambda[tp.width],
CDExtras.ToLambda[tp.length],
"]"
];
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: REF 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.specificRef];
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.size ← [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[];
l: INT = TokenIO.ReadInt[];
implant: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
IF CDIO.VersionKey[]>=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;
WriteTrans: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
TokenIO.WriteInt[tp.width];
TokenIO.WriteInt[tp.length];
TokenIO.WriteInt[tp.implant];
TokenIO.WriteInt[tp.wExt];
TokenIO.WriteInt[tp.lExt];
END;
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;
AngleExt: PROC[tob: CD.Object] RETURNS [CD.Number] = {
tp: TransistorPtr = NARROW[tob.specificRef];
RETURN [tp.width+tp.length+tp.wExt-tob.size.x]
};
ChangeExtensionTrans: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount=[0, 0] THEN done ← FALSE
ELSE {
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
sz: CD.Position ← 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
ap.ob ← CreateAngleTransistor[w: tp.width, l: tp.length,
implant: tp.implant,
wExt: sz.x, lExt: sz.y,
aExt: AngleExt[inst.ob]
]
ELSE
ap.ob ← CreateTransistor[w: tp.width, l: tp.length,
implant: tp.implant,
wExt: sz.x, lExt: sz.y
];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.x<0 OR amount.y<0;
repaintInclude ← amount.x>0 OR amount.y>0;
}
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,
implant: tp.implant,
aExt: AngleExt[inst.ob]
]
ELSE
new ← CreateTransistor[w: sz.x, l: sz.y,
wExt: tp.wExt, lExt: tp.lExt,
implant: tp.implant
];
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;
DefaultenTrans: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateTransistor[
w: CDValue.FetchInt[design, $NMosTransistorW]*lambda,
l: CDValue.FetchInt[design, $NMosTransistorH]*lambda,
wExt: tp.wExt,
lExt: tp.lExt,
implant: CDValue.FetchInt[design, $NMosTransistorImplant]
];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← TRUE;
repaintInclude ← TRUE;
END;
SetWidthTrans: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
newWidth: CD.Number ← NARROW[x, REF CD.Number]^;
oldWidth: CD.Number ← tp.width;
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateTransistor[w: newWidth, l: tp.length, wExt: tp.wExt, lExt: tp.lExt, implant: tp.implant];
include ← LIST[ap];
removeMe ← TRUE;
IF newWidth>oldWidth THEN repaintInclude ← TRUE ELSE repaintMe ← TRUE;
END;
SetLengthTrans: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
oldLength: CD.Number ← tp.length;
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateTransistor[w: tp.width, l: newLength, wExt: tp.wExt, lExt: tp.lExt, implant: tp.implant];
include ← LIST[ap];
removeMe ← TRUE;
IF newLength>oldLength THEN repaintInclude←TRUE ELSE repaintMe←TRUE;
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]; -- dif or pdiff
CDDraw[[0, class.lExt, inst.ob.size.x, class.lExt+class.length], pol];
IF class.implant>0 THEN
CDDraw[[class.wExt-depletionOverlap, class.lExt-depletionOverlap,
inst.ob.size.x-class.wExt+depletionOverlap, inst.ob.size.y-class.lExt+depletionOverlap],
SELECT class.implant FROM
NMosTransistors.strongDepletion => imp,
NMosTransistors.weakDepletion => impWeak,
NMosTransistors.zeroTresh => imp0,
NMosTransistors.enhancement => CD.highLightError,
ENDCASE => CD.highLightError
];
END;
-- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForATransistors: REF 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.specificRef];
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.size ← [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 --PROC [] RETURNS [Object]-- =
BEGIN
w: INT = TokenIO.ReadInt[];
l: INT = TokenIO.ReadInt[];
implant: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
aExt: INT = TokenIO.ReadInt[];
IF CDIO.VersionKey[]>=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 -- PROC [me: Object] -- =
BEGIN
tp: TransistorPtr = NARROW[me.specificRef];
TokenIO.WriteInt[tp.width];
TokenIO.WriteInt[tp.length];
TokenIO.WriteInt[tp.implant];
TokenIO.WriteInt[tp.wExt];
TokenIO.WriteInt[tp.lExt];
TokenIO.WriteInt[tp.width+tp.length+tp.wExt-me.size.x];
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.
IF CDBasics.Intersect[CDOrient.RectAt[pos, inst.ob.size, orient], pr.interestClip] THEN
BEGIN
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];
IF class.implant>0 THEN
BEGIN
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
END;
-- PullUp -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForPullUps: REF 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.specificRef];
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.size ← [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[];
l: INT = TokenIO.ReadInt[];
wExt: INT = TokenIO.ReadInt[];
lExt: INT = TokenIO.ReadInt[];
RETURN [ CreatePullUp[w: w, l: l, wExt: wExt, lExt: lExt] ];
END;
WritePull: 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];
END;
LengthenPullUps: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount=[0, 0] THEN done ← FALSE
ELSE {
tp: TransistorPtr = NARROW[inst.ob.specificRef];
ap: CD.Instance = NEW[CD.InstanceRep←inst^];
sz: CD.Position = CDBasics.AddPoints[[x: tp.width, y: tp.length], amount];
IF sz.x<=0 OR sz.y<=0 THEN {done←FALSE; RETURN};
ap.ob ← CreatePullUp[w: sz.x, l: sz.y, wExt: tp.wExt, lExt: tp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.x<0 OR amount.y<0;
repaintInclude ← amount.x>0 OR amount.y>0;
}
END;
ChangeExtensionPullUps: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount=[0, 0] THEN done ← FALSE
ELSE {
tp: TransistorPtr = NARROW[inst.ob.specificRef];
ap: CD.Instance = NEW[CD.InstanceRep←inst^];
sz: CD.Position ← CDBasics.AddPoints[[x: tp.wExt, y: tp.lExt], amount];
IF sz.x<0 OR sz.y<0 THEN {done←FALSE; RETURN};
ap.ob ← CreatePullUp[w: tp.width, l: tp.length, wExt: sz.x, lExt: sz.y];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.x<0 OR amount.y<0;
repaintInclude ← amount.x>0 OR amount.y>0;
}
END;
DefaultenPullUps: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr = NARROW[inst.ob.specificRef];
ap: CD.Instance = NEW[CD.InstanceRep←inst^];
ap.ob ← CreatePullUp[
w: CDValue.FetchInt[design, $NMosPullUpW]*lambda,
l: CDValue.FetchInt[design, $NMosPullUpH]*lambda,
wExt: tp.wExt,
lExt: tp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← TRUE;
repaintInclude ← TRUE;
END;
SetWidthPullUps: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
newWidth: CD.Number ← NARROW[x, REF CD.Number]^;
oldWidth: CD.Number ← tp.width;
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreatePullUp[w: newWidth, l: tp.length, wExt: tp.wExt, lExt: tp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
IF newWidth>oldWidth THEN repaintInclude ← TRUE ELSE repaintMe ← TRUE;
END;
SetLengthPullUps: CDCallSpecific.CallProc =
BEGIN
tp: TransistorPtr ← NARROW[inst.ob.specificRef];
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
oldLength: CD.Number ← tp.length;
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreatePullUp[w: tp.width, l: newLength, wExt: tp.wExt, lExt: tp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
IF newLength>oldLength THEN repaintInclude ← TRUE ELSE repaintMe ← TRUE;
END;
DrawMeForPullUps: 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;
IF CDBasics.Intersect[CDOrient.RectAt[pos, inst.ob.size, orient], pr.interestClip] THEN
BEGIN
class: TransistorPtr = NARROW[inst.ob.specificRef];
middleX: CD.Number = inst.ob.size.x/2;
metal: CD.Rect = [x1: middleX-2*lambda, y1: inst.ob.size.y-6*lambda,
x2: middleX+2*lambda, y2: inst.ob.size.y];
CDDraw[[class.wExt, 0, class.wExt+class.width, inst.ob.size.y], inst.ob.layer];
CDDraw[[0, class.lExt, inst.ob.size.x, class.lExt+class.length], pol];
CDDraw[[0, 0, inst.ob.size.x, inst.ob.size.y-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
END;
Init[];
END.