<> <> <> <> DIRECTORY CD, CDBasics, CDIO, CDBasicsInline, CDLRUCache, CDOps, CDStretchyBackdoor, NMos, NMosTransistors, Rope, TokenIO; NMosTransistorsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDBasicsInline, CDIO, CDLRUCache, CDOps, CDStretchyBackdoor, NMos, Rope, TokenIO EXPORTS NMosTransistors = BEGIN OPEN NMos; lambda: CD.Number = NMos.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.specific _ NEW[TransistorRec]; RETURN [ob] }; Init: PROC [] = BEGIN pForTransistors.drawMe _ pForTransistors.quickDrawMe _ DrawMeForTransistors; pForTransistors.internalRead _ ReadTrans; pForTransistors.internalWrite _ WriteTrans; pForTransistors.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForTransistors, MatchTrans]; CDStretchyBackdoor.InstallMakeSimilarProc[pForTransistors, MakeSimilarTrans]; 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; CDStretchyBackdoor.InstallMatchProc[pForPullUps, MatchTrans]; END; Describe: CD.DescribeProc = BEGIN tp: TransistorPtr = NARROW[ob.specific]; 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, " [", CDOps.LambdaRope[tp.width, 2], CDOps.LambdaRope[tp.length, 2], "]" ]; 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: 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.specific]; 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.bbox _ [0, 0, 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[h]; l: INT = TokenIO.ReadInt[h]; implant: INT = TokenIO.ReadInt[h]; wExt: INT = TokenIO.ReadInt[h]; lExt: INT = TokenIO.ReadInt[h]; IF ~h.oldVersion AND CDIO.VersionKey[h]>=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; MakeSimilarTrans: CDStretchyBackdoor.MakeSimilarProc = { tp: TransistorPtr = NARROW[me.specific]; sz: CD.Position _ CDBasics.SizeOfRect[ir]; RETURN [ CreateTransistor[w: sz.x-2*tp.wExt, l: sz.y-2*tp.lExt, wExt: tp.wExt, lExt: tp.lExt,implant: tp.implant] ]; }; WriteTrans: CD.InternalWriteProc = BEGIN tp: TransistorPtr = NARROW[ob.specific]; TokenIO.WriteInt[h, tp.width]; TokenIO.WriteInt[h, tp.length]; TokenIO.WriteInt[h, tp.implant]; TokenIO.WriteInt[h, tp.wExt]; TokenIO.WriteInt[h, tp.lExt]; END; AngleExt: PROC[tob: CD.Object] RETURNS [CD.Number] = { tp: TransistorPtr = NARROW[tob.specific]; RETURN [tp.width+tp.length+tp.wExt-tob.bbox.x2] }; 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[itemInCell: r, cellInWorld: trans], l]; }; CDDraw[[class.wExt, 0, class.wExt+class.width, ob.bbox.y2], ob.layer]; -- dif or pdiff CDDraw[[0, class.lExt, ob.bbox.x2, class.lExt+class.length], pol]; IF class.implant>0 THEN CDDraw[[class.wExt-depletionOverlap, class.lExt-depletionOverlap, ob.bbox.x2-class.wExt+depletionOverlap, ob.bbox.y2-class.lExt+depletionOverlap], SELECT class.implant FROM NMosTransistors.strongDepletion => imp, NMosTransistors.weakDepletion => impWeak, NMosTransistors.zeroTresh => imp0, NMosTransistors.enhancement => CD.errorLayer, ENDCASE => CD.errorLayer ]; END; <<-- Angle Transistor -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForATransistors: 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_0] RETURNS [CD.Object] = BEGIN tob: CD.Object _ aCache.UnusedOrNew[]; tp: TransistorPtr _ NARROW[tob.specific]; 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.bbox _ [0, 0, 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 = BEGIN w: INT = TokenIO.ReadInt[h]; l: INT = TokenIO.ReadInt[h]; implant: INT = TokenIO.ReadInt[h]; wExt: INT = TokenIO.ReadInt[h]; lExt: INT = TokenIO.ReadInt[h]; aExt: INT = TokenIO.ReadInt[h]; IF ~h.oldVersion AND CDIO.VersionKey[h]>=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 = BEGIN tp: TransistorPtr = NARROW[ob.specific]; TokenIO.WriteInt[h, tp.width]; TokenIO.WriteInt[h, tp.length]; TokenIO.WriteInt[h, tp.implant]; TokenIO.WriteInt[h, tp.wExt]; TokenIO.WriteInt[h, tp.lExt]; TokenIO.WriteInt[h, tp.width+tp.length+tp.wExt-CD.InterestSize[ob].x]; 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[itemInCell: r, cellInWorld: 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 = CDBasicsInline.MapRect[ob.bbox, trans]; IF CDBasics.Intersect[r, pr.interestClip] THEN BEGIN ele: CD.Number = 2*class.lExt+class.length; hPoly: CD.Rect = [0, class.lExt, ob.bbox.x2-class.lExt, class.length+class.lExt]; -- horizontal vPoly: CD.Rect = [ob.bbox.x2-class.length-class.lExt, hPoly.y2, hPoly.x2, ob.bbox.y2]; -- vertical nDrain: CD.Rect = [class.wExt, 0, ob.bbox.x2, hPoly.y1]; -- north eDrain: CD.Rect = [vPoly.x2, nDrain.y2, nDrain.x2, ob.bbox.y2-class.wExt]; -- east wSource: CD.Rect = [ob.bbox.x2-ele, eDrain.y1, eDrain.x1, ob.bbox.y2-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 { CDDraw[nDrain, ob.layer]; CDDraw[eDrain, ob.layer]; }; CDDraw[wSource, ob.layer]; CDDraw[sSource, ob.layer]; CDDraw[hPoly, pol]; CDDraw[vPoly, pol]; IF class.implant>0 THEN { 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; <<-- PullUp -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForPullUps: 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.specific]; 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.bbox _ [0, 0, 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[h]; l: INT = TokenIO.ReadInt[h]; wExt: INT = TokenIO.ReadInt[h]; lExt: INT = TokenIO.ReadInt[h]; RETURN [ CreatePullUp[w: w, l: l, wExt: wExt, lExt: lExt] ]; END; WritePull: CD.InternalWriteProc = 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]; END; DrawMeForPullUps: CD.DrawProc = BEGIN CDDraw: PROC[r: CD.Rect, l: CD.Layer] = INLINE { <<--uses outer stuff!!>> pr.drawRect[pr, CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l]; }; r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans]; IF CDBasics.Intersect[r, pr.interestClip] THEN { class: TransistorPtr = NARROW[ob.specific]; middleX: CD.Number = ob.bbox.x2/2; metal: CD.Rect = [x1: middleX-2*lambda, y1: ob.bbox.y2-6*lambda, x2: middleX+2*lambda, y2: ob.bbox.y2]; CDDraw[[class.wExt, 0, class.wExt+class.width, ob.bbox.y2], ob.layer]; CDDraw[[0, class.lExt, ob.bbox.x2, class.lExt+class.length], pol]; CDDraw[[0, 0, ob.bbox.x2, ob.bbox.y2-lambda], imp]; CDDraw[[metal.x1, metal.y1+2*lambda, metal.x2, metal.y2], ob.layer]; CDDraw[metal, met]; CDDraw[[metal.x1+lambda, metal.y1+lambda, metal.x2-lambda, metal.y2-lambda], cut]; } END; Init[]; END.