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.DesignNumber = CD.lambda; depletionOverlap: CD.DesignNumber = (3*lambda)/2; wXExtension: CD.DesignNumber = NMosTransistors.wXExtension; lXExtension: CD.DesignNumber = 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.ObPtr] = { ob: CD.ObPtr ~ NEW[CD.ObjectDefinition]; 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.ObPtr] 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.ObPtr, r: CD.DesignRect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] = BEGIN RETURN [layer=NMos.pol OR layer=me.layer] END; pForTransistors: REF CD.ObjectProcs = RegisterObjectType[$NMosTransistor]; CreateTransistor: PUBLIC PROC [w, l: CD.DesignNumber, implant: NMosTransistors.Implant_NMosTransistors.enhancement, wExt: CD.DesignNumber_wXExtension, lExt: CD.DesignNumber_lXExtension] RETURNS [CD.ObPtr] = BEGIN tob: CD.ObPtr ~ tCache.UnusedOrNew[]; tp: TransistorPtr ~ NARROW[tob.specificRef]; 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; 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 [ObPtr]-- = 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: ObPtr] -- = 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 [p: CD.DesignPosition] = BEGIN IF x=NIL THEN p _ [0, lambda] ELSE WITH x SELECT FROM rp: REF CD.DesignPosition => p _ rp^; rn: REF CD.DesignNumber => p _ [0, rn^]; ENDCASE => p _ [0, 0]; END; AngleExt: PROC[tob: CD.ObPtr] RETURNS [CD.DesignNumber] = { tp: TransistorPtr = NARROW[tob.specificRef]; RETURN [tp.width+tp.length+tp.wExt-tob.size.x] }; ChangeExtensionTrans: CDCallSpecific.CallProc = BEGIN amount: CD.DesignPosition = ToPosition[x]; IF amount=[0, 0] THEN done _ FALSE ELSE { tp: TransistorPtr _ NARROW[aptr.ob.specificRef]; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; sz: CD.DesignPosition _ 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[aptr.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[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 _ 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[aptr.ob] ] ELSE new _ CreateTransistor[w: sz.x, l: sz.y, wExt: tp.wExt, lExt: tp.lExt, implant: tp.implant ]; IF new#NIL AND (aptr.ob.size#new.size OR NOT Aequivalent[tp, new.specificRef]) THEN aptr.ob _ new ELSE done _ FALSE; repaintMe _ done; END; DefaultenTrans: CDCallSpecific.CallProc = BEGIN tp: TransistorPtr _ NARROW[aptr.ob.specificRef]; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; 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[aptr.ob.specificRef]; newWidth: CD.DesignNumber _ NARROW[x, REF CD.DesignNumber]^; oldWidth: CD.DesignNumber _ tp.width; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; 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[aptr.ob.specificRef]; newLength: CD.DesignNumber _ NARROW[x, REF CD.DesignNumber]^; oldLength: CD.DesignNumber _ tp.length; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; 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 [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.Layer] = INLINE 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.layer]; -- dif or pdiff CDDraw[[0, p.lExt, aptr.ob.size.x, p.lExt+p.length], pol]; IF p.implant>0 THEN CDDraw[[p.wExt-depletionOverlap, p.lExt-depletionOverlap, aptr.ob.size.x-p.wExt+depletionOverlap, aptr.ob.size.y-p.lExt+depletionOverlap], SELECT p.implant FROM NMosTransistors.strongDepletion => imp, NMosTransistors.weakDepletion => impWeak, NMosTransistors.zeroTresh => imp0, NMosTransistors.enhancement => CD.highLightError, ENDCASE => CD.highLightError ]; END; pForATransistors: REF CD.ObjectProcs = RegisterObjectType[$NMosATransistor]; CreateAngleTransistor: PUBLIC PROC [w, l: CD.DesignNumber, implant: NMosTransistors.Implant_NMosTransistors.enhancement, wExt: CD.DesignNumber_wXExtension, lExt: CD.DesignNumber_lXExtension, aExt: CD.DesignNumber_0] RETURNS [CD.ObPtr] = BEGIN tob: CD.ObPtr _ aCache.UnusedOrNew[]; tp: TransistorPtr _ NARROW[tob.specificRef]; tob.p _ pForATransistors; wExt _ MAX[wExt, 0]; lExt _ MAX[lExt, 0]; aExt _ MAX[aExt, -lExt]; w _ MAX[w, 2*lExt]; -- the width of the straight-line 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 [ObPtr]-- = 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: ObPtr] -- = 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 [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.Layer] = INLINE BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; IF CDBasics.Intersect[CDOrient.RectAt[pos, aptr.ob.size, orient], pr.interestClip] THEN BEGIN 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.layer]; CDDraw[eDrain, aptr.ob.layer]; END; CDDraw[wSource, aptr.ob.layer]; CDDraw[sSource, aptr.ob.layer]; CDDraw[hPoly, pol]; CDDraw[vPoly, pol]; IF p.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; pForPullUps: REF CD.ObjectProcs = RegisterObjectType[$NMosPullUp]; CreatePullUp: PUBLIC PROC [w, l: CD.DesignNumber, wExt: CD.DesignNumber_wXExtension, lExt: CD.DesignNumber_lXExtension] RETURNS [CD.ObPtr] = BEGIN puob: CD.ObPtr ~ 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.p _ 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 [ObPtr]-- = 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: ObPtr] -- = 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.DesignPosition = ToPosition[x]; IF amount=[0, 0] THEN done _ FALSE ELSE { tp: TransistorPtr = NARROW[aptr.ob.specificRef]; ap: CD.ApplicationPtr = NEW[CD.Application_aptr^]; sz: CD.DesignPosition = 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.DesignPosition = ToPosition[x]; IF amount=[0, 0] THEN done _ FALSE ELSE { tp: TransistorPtr = NARROW[aptr.ob.specificRef]; ap: CD.ApplicationPtr = NEW[CD.Application_aptr^]; sz: CD.DesignPosition _ 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[aptr.ob.specificRef]; ap: CD.ApplicationPtr = NEW[CD.Application_aptr^]; 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[aptr.ob.specificRef]; newWidth: CD.DesignNumber _ NARROW[x, REF CD.DesignNumber]^; oldWidth: CD.DesignNumber _ tp.width; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; 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[aptr.ob.specificRef]; newLength: CD.DesignNumber _ NARROW[x, REF CD.DesignNumber]^; oldLength: CD.DesignNumber _ tp.length; ap: CD.ApplicationPtr _ NEW[CD.Application_aptr^]; 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 [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN CDDraw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; IF CDBasics.Intersect[CDOrient.RectAt[pos, aptr.ob.size, orient], pr.interestClip] THEN BEGIN p: TransistorPtr = NARROW[aptr.ob.specificRef]; middleX: CD.DesignNumber = aptr.ob.size.x/2; metal: CD.DesignRect = [x1: middleX-2*lambda, y1: aptr.ob.size.y-6*lambda, x2: middleX+2*lambda, y2: aptr.ob.size.y]; CDDraw[[p.wExt, 0, p.wExt+p.width, aptr.ob.size.y], aptr.ob.layer]; CDDraw[[0, p.lExt, aptr.ob.size.x, p.lExt+p.length], pol]; CDDraw[[0, 0, aptr.ob.size.x, aptr.ob.size.y-lambda], imp]; CDDraw[[metal.x1, metal.y1+2*lambda, metal.x2, metal.y2], aptr.ob.layer]; CDDraw[metal, met]; CDDraw[[metal.x1+lambda, metal.y1+lambda, metal.x2-lambda, metal.y2-lambda], cut]; END END; Init[]; END. fNMosTransistorsImpl.mesa (part of ChipNDale) Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, June 24, 1983 5:03 pm last edited Christian Jacobi, April 11, 1985 11:17:47 am PST -- Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --y field defaults to lambda, x field defaults to 0 --[0, 0] if not done uses outer stuff!! -- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- parts of the gate, excluding corner --uses outer stuff!! --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. -- PullUp -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --uses outer stuff!! Ê%˜šœ-™-Jšœ Ïmœ7™BJšœ+™+Jšœ<™J˜7J˜—˜=J˜8J˜—Jšž˜—Jšž˜—Jšžœ˜J˜J˜—JšœX™XJ˜Jšœ žœžœ/˜BJ˜šŸ œžœžœžœ˜2Jšœžœ˜"Jšœžœ˜#Jšžœžœ ˜Jšž˜Jšœžœ˜&Jšœžœ˜.Jšœžœ˜Jšœžœ˜Jšœžœ ˜Jšœžœ ˜J˜J˜J˜J˜Jšœ žœ˜J˜Jšœ žœžœ˜FJ˜Jšžœ$˜*Jšžœ˜J˜—š¡œžœ¢œ˜;Jšž˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšžœ6˜