<> <> <> <> DIRECTORY NMosContacts, CD, CDIO, CDBasics, CDBasicsInline, CDLRUCache, CDStretchyBackdoor, NMos, Rope, TokenIO; NMosContactsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDBasicsInline, CDIO, CDLRUCache, CDStretchyBackdoor, NMos, TokenIO EXPORTS NMosContacts = BEGIN OPEN NMos; lambda: CD.Number = NMos.lambda; ContactType: TYPE = NMosContacts.ContactType; ContactPtr: TYPE = NMosContacts.ContactPtr; ContactRec: TYPE = NMosContacts.ContactRec; wXExtension: CD.Number = 2*lambda; lXExtension: CD.Number = 2*lambda; difCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; polyCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; dsCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; butCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; burCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; mmCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont]; 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; Aequivalent: PROC[mySpecific, other: REF ANY] RETURNS [BOOL] = { WITH other SELECT FROM p2: ContactPtr => RETURN [NARROW[mySpecific, ContactPtr]^=p2^]; ENDCASE => RETURN [FALSE] }; NewCont: PROC [] RETURNS [CD.Object] = { ob: CD.Object _ NEW[CD.ObjectRep]; ob.specific _ NEW[ContactRec]; RETURN [ob] }; MatchContact: PROC [me: CD.Object, r: CD.Rect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] = BEGIN IF layer=me.layer THEN RETURN [TRUE] ELSE { cp: ContactPtr = NARROW[me.specific]; RETURN [ SELECT cp.typ FROM burr => (layer=NMos.pol), mDif => (layer=NMos.met), butt => (layer=NMos.met OR layer=NMos.pol), mPol => (layer=NMos.met), mm2 => (layer=NMos.met2), ENDCASE => FALSE ] } END; Describe: CD.DescribeProc = BEGIN RETURN [ SELECT NARROW[ob.specific, ContactPtr].typ FROM burr => "buried contact", mDif => "dif contact", butt => "button contact", mPol => "poly contact", mm2 => "via", ENDCASE => "unknown contact" ] END; <<-- Dif and Pol -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForDifPolCon: CD.ObjectClass ~ RegisterObjectClass[$NMosContactDifAndPol]; difpolRimWidth: CD.Number = lambda; CreateDifCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] = <<--connect diffusion with metal>> BEGIN cob: CD.Object ~ difCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; l _ MAX[l, butConSX]; cp.typ _ mDif; cob.class _ pForDifPolCon; -- does not use specicRef ! cob.layer _ dif; cob.bbox _ [0, 0, butConSX, l]; RETURN [difCache.ReplaceByAequivalent[cob]] END; CreatePolyCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] = <<--connect poly with metal>> BEGIN cob: CD.Object ~ polyCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; l _ MAX[l, butConSX]; cp.typ _ mPol; cob.class _ pForDifPolCon; -- does not use specicRef ! cob.bbox _ [0, 0, butConSX, l]; cob.layer _ pol; RETURN [polyCache.ReplaceByAequivalent[cob]] END; ReadDifPolCon: CD.InternalReadProc = BEGIN layer: CD.Layer = CDIO.ReadLayer[h]; IF layer=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[h]] ] ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[h]] ] END; WriteDifPolCon: CD.InternalWriteProc = { CDIO.WriteLayer[h, ob.layer]; TokenIO.WriteInt[h, CD.InterestSize[ob].y]; }; DrawDifAndPolContact: CD.DrawProc = { <<--does not read specific !!!!!!>> r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans]; IF CDBasics.Intersect[r, pr.interestClip] THEN { pr.drawRect[pr, r, met]; pr.drawRect[pr, r, ob.layer]; pr.drawRect[pr, CDBasics.Extend[r, -difpolRimWidth], cut]; } }; -- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- pForButContact: CD.ObjectClass ~ RegisterObjectClass[$NMosContactBut]; butConSX: CD.Number = 4*lambda; butConSY: CD.Number = 6*lambda; butContactPolyYS: CD.Number = 3*lambda; butContactDiffY: CD.Number = butContactPolyYS-lambda; butContactRimWidth: CD.Number = lambda; CreateButCon: PUBLIC PROC [] RETURNS [CD.Object] = <<--connects metal with poly and diffusion>> BEGIN cob: CD.Object ~ butCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; cp.typ _ butt; cob.class _ pForButContact; cob.layer _ dif; cob.bbox _ [0, 0, butConSX, butConSY]; RETURN [butCache.ReplaceByAequivalent[cob]] END; ReadButCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN RETURN [ CreateButCon[] ] END; WriteButCon: CD.InternalWriteProc -- PROC [me: Object] -- = BEGIN END; DrawButContact: CD.DrawProc = BEGIN Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE { <<--uses outer stuff!!>> pr.drawRect[pr, CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l]; }; <<--DrawButContact>> Draw[[0, 0, butConSX, butConSY], met]; Draw[[0, 0, butConSX, butContactPolyYS], pol]; Draw[[0, butContactDiffY, butConSX, butConSY], ob.layer]; Draw[[butContactRimWidth, butContactRimWidth, butConSX-butContactRimWidth, butConSY-butContactRimWidth], cut]; END; <<-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForBurCon: CD.ObjectClass ~ RegisterObjectClass[$NMosBurContact]; <<>> CreateBurCon: PUBLIC PROC [w, l: CD.Number, wex: CD.Number_wXExtension, lex: CD.Number_lXExtension] RETURNS [CD.Object] = <<-- connects diffusion with poly without accessing metal>> BEGIN cob: CD.Object ~ burCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; burAct: CD.Number = 2*lambda; actWidth, xMargins: CD.Number; wex _ MAX[0, wex]; lex _ MAX[0, lex]; xMargins _ burAct + (IF wex< burAct THEN MAX[wex+lambda, burAct] ELSE wex); actWidth _ MAX[2*lambda, w-xMargins]; w _ actWidth+xMargins; l _ MAX[l, (IF lex> pr.drawRect[pr, CDBasics.MapRect[itemInCell: r, cellInWorld: trans], l]; }; <<--DrawMeForBurrNMosContacts>> class: ContactPtr = NARROW[ob.specific]; dBur: CD.Number = lambda/2; burAct: CD.Number = lambda*2; diffBur: CD.Position = [ x: IF class.wExt> pForVia: CD.ObjectClass ~ RegisterObjectClass[$NMosMmContact]; mmRimWidth: CD.Number = lambda; cut2min: CD.Number = 3*lambda; CreateMmCon: PUBLIC PROC [l: CD.Number, wex: CD.Number_wXExtension, lex: CD.Number_lXExtension] RETURNS [CD.Object] = <<-- ignores wex and lex in chipmonk, why???>> <<-- connects two layers of metal>> BEGIN cob: CD.Object ~ mmCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; mins: CD.Number = cut2min+2*mmRimWidth; oldMins: CD.Number = cut2min+2*--mmRimWidth--2*lambda; l _ MAX[l, mins]; cp.typ _ mm2; <<--cp.wExt _ ;>> <<--cp.wExt _ ;>> cob.class _ pForVia; IF l> RETURN [mmCache.ReplaceByAequivalent[cob]] END; ReadVia: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN RETURN [ CreateMmCon[TokenIO.ReadInt[h]] ] END; WriteVia: CD.InternalWriteProc = BEGIN TokenIO.WriteInt[h, CD.InterestSize[ob].y]; END; DrawVia: CD.DrawProc = <<--does not read specific !!!!!!>> BEGIN mins: CD.Number = cut2min+2*mmRimWidth; r: CD.Rect = CDBasicsInline.MapRect[ob.bbox, trans]; pr.drawRect[pr, r, met]; pr.drawRect[pr, r, met2]; IF ob.bbox.x2>mins THEN --old technology-- pr.drawRect[pr, CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2] ELSE --new technology-- pr.drawRect[pr, CDBasics.Extend[r, -mmRimWidth], cut2]; END; <<-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> Init: PROC [] = BEGIN pForDifPolCon.drawMe _ pForDifPolCon.quickDrawMe _ DrawDifAndPolContact; pForDifPolCon.internalRead _ ReadDifPolCon; pForDifPolCon.internalWrite _ WriteDifPolCon; pForDifPolCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForDifPolCon, MatchContact]; pForButContact.drawMe _ pForButContact.quickDrawMe _ DrawButContact; pForButContact.internalRead _ ReadButCon; pForButContact.internalWrite _ WriteButCon; pForButContact.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForButContact, MatchContact]; pForBurCon.drawMe _ pForBurCon.quickDrawMe _ DrawMeForBurrNMosContacts; pForBurCon.internalRead _ ReadBurCon; pForBurCon.internalWrite _ WriteBurCon; pForBurCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForBurCon, MatchContact]; CDStretchyBackdoor.InstallMakeSimilarProc[pForBurCon, MakeSimilarBur]; pForVia.drawMe _ pForVia.quickDrawMe _ DrawVia; pForVia.internalRead _ ReadVia; pForVia.internalWrite _ WriteVia; pForVia.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForVia, MatchContact]; END; Init[]; END.