<> <> <> <> DIRECTORY CMosCMContacts, CMosObjects, CD, CDBasics, CDIO, CDLRUCache, CDOps, CDRects USING [CreateRect], CDStretchyBackdoor, CMos, Rope, TokenIO; CMosCMContactsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDIO, CDLRUCache, CDOps, CDStretchyBackdoor, CDRects, CMos, Rope, TokenIO, CMosObjects EXPORTS CMosCMContacts = BEGIN OPEN CMos; lambda: CD.Number = CMos.lambda; ContactType: TYPE = CMosCMContacts.ContactType; ContactPtr: TYPE = CMosCMContacts.ContactPtr; ContactRec: TYPE = CMosCMContacts.ContactRec; undef: CD.Layer = CD.undefLayer; wellSurround: CD.Number = CMos.wellSurround; 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]; 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] }; InsideRectWithSurround: PROC [ob: CD.Object] RETURNS [CD.Rect] = { RETURN [CDBasics.Extend[ob.bbox, -wellSurround]] }; ShowSelectedWithSurround: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = { pr.drawOutLine[CDBasics.Extend[CDBasics.MapRect[inst.ob.bbox, trans], -(wellSurround)], CD.selectionLayer, pr] }; MatchContact: PROC [me: CD.Object, r: CD.Rect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] = BEGIN <<-- Don't care about different diffusions and such>> IF layer=me.layer THEN RETURN [TRUE] ELSE { cp: ContactPtr = NARROW[me.specific]; RETURN [ SELECT cp.typ FROM burr => (layer=CMos.pol), mDif => (layer=CMos.met), difShort => FALSE, butt => (layer=CMos.met OR layer=CMos.pol), mPol => (layer=CMos.met), mm2 => (layer=CMos.met2), ENDCASE => FALSE ] } END; <<-- Dif and Pol -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForDifPolCon: CD.ObjectClass = RegisterObjectClass[$CMosContactDifAndPol]; pForWellDifPolCon: CD.ObjectClass = RegisterObjectClass[$CMosContactWellDifAndPol]; difpolRimWidth: CD.Number = lambda; CreateDifCon: PUBLIC PROC [l: CD.Number, difLev: CD.Layer] RETURNS [CD.Object] = <<--connect diffusion with metal>> BEGIN cob: CD.Object ~ difCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; IF difLev=undef THEN difLev_ndif; IF l=butConSX THEN { IF difLev=CMos.pdif THEN difLev _ CMos.wpdif; IF difLev=CMos.pol THEN RETURN [CMosObjects.CreatePolyCon[]] ELSE RETURN [CMosObjects.CreateDifCon[difLev]] }; l _ MAX[l, butConSX]; cp.typ _ mDif; cob.layer _ difLev; IF difLev=CMos.pdif THEN { cob.class _ pForWellDifPolCon; cob.bbox _ [-wellSurround, -wellSurround, butConSX+wellSurround, l+wellSurround]; } ELSE { cob.class _ pForDifPolCon; 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]; IF l=butConSX THEN { RETURN [CMosObjects.CreatePolyCon[]] }; l _ MAX[l, butConSX]; cp.typ _ mPol; cob.class _ pForDifPolCon; cob.bbox _ [0, 0, butConSX, l]; cob.layer _ pol; RETURN [polyCache.ReplaceByAequivalent[cob]] END; ReadDifPolCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN lev: CD.Layer = CDIO.ReadLayer[h]; IF lev=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[h]] ] ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[h], lev] ] END; WriteDifPolCon: CD.InternalWriteProc -- PROC [ob: Object] -- = BEGIN CDIO.WriteLayer[h, ob.layer]; TokenIO.WriteInt[h, CD.InterestSize[ob].y]; END; DrawDifPolCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = BEGIN r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans]; pr.drawRect[r, met, pr]; pr.drawRect[r, inst.ob.layer, pr]; pr.drawRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr]; END; DrawWellDifPolCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = BEGIN r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans]; inr: CD.Rect = CDBasics.Extend[r, -wellSurround]; pr.drawRect[inr, met, pr]; pr.drawRect[inr, inst.ob.layer, pr]; pr.drawRect[CDBasics.Extend[inr, -difpolRimWidth], cut, pr]; pr.drawRect[r, nwell, pr]; END; <<-- DifShort -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForDifShorts: CD.ObjectClass = RegisterObjectClass[$CMosContactDifShort]; pForWellDifShorts: CD.ObjectClass = RegisterObjectClass[$CMosContactWellDifShort]; difShortRimWidth: CD.Number = lambda; CreateDifShortCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.Object] = BEGIN IF difLev=CMos.pdif THEN difLev _ CMos.wpdif; RETURN [CMosObjects.CreateDifShortCon[difLev]] END; ReadDifShortCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN RETURN [ CreateDifShortCon[CDIO.ReadLayer[h]] ] END; -- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- pForButContact: CD.ObjectClass = RegisterObjectClass[$CMosContactBut]; pForWellButContact: CD.ObjectClass = RegisterObjectClass[$CMosContactWellBut]; butConSX: CD.Number = 4*lambda; CreateButCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.Object] = <<--connects metal with poly and diffusion>> BEGIN IF difLev=CMos.pdif THEN difLev _ CMos.wpdif; RETURN [CMosObjects.CreateButCon[difLev]] END; ReadButCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN RETURN [ CreateButCon[CDIO.ReadLayer[h]] ] END; <<>> <<-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForBurCon: CD.ObjectClass = RegisterObjectClass[$CMosBurContact]; pForWellBurCon: CD.ObjectClass = RegisterObjectClass[$CMosWellBurContact]; <<>> <<-- Buried contacts come in three flavours, Pol-Surround, Dif-Surround and Crossing. The buried contacts in chipndale are parameterized by lExt and wExt, their interpretation is as follows: Diff always extends 1l to the left, material above/below and to the right is determined by lExt and wExt respectively. 2l is the pivotal value, below 2l the material is Pol, at 2l or above the material is Diff. (Note: some combinations give Diff on all four sides, it is assumed that such combinations will not be created.)>> <<>> CreateBurCon: PUBLIC PROC [w, l: CD.Number, wex: CD.Number, lex: CD.Number, difLev: CD.Layer] RETURNS [CD.Object] = <<-- connects diffusion with poly without accessing metal>> BEGIN <<-- copied from chipmonk without understanding>> burAct: CD.Number = 2*lambda; actWidth, xMargins: CD.Number; cob: CD.Object ~ burCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specific]; IF difLev=undef THEN difLev_ndif; 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> RETURN[CDRects.CreateRect[[w, l], CD.errorLayer]]; } ELSE { cob.class _ pForBurCon; cob.bbox _ [0, 0, w, l]; }; cob.layer _ difLev; RETURN [burCache.ReplaceByAequivalent[cob]] END; ReadBurCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN w: INT = TokenIO.ReadInt[h]; l: INT = TokenIO.ReadInt[h]; wex: INT = TokenIO.ReadInt[h]; lex: INT = TokenIO.ReadInt[h]; difLev: CD.Layer = CDIO.ReadLayer[h]; RETURN [ CreateBurCon[w, l, wex, lex, difLev] ] END; WriteBurCon: CD.InternalWriteProc = BEGIN cp: ContactPtr = NARROW[ob.specific]; CDIO.WritePos[h, CD.InterestSize[ob]]; TokenIO.WriteInt[h, cp.wExt]; TokenIO.WriteInt[h, cp.lExt]; CDIO.WriteLayer[h, ob.layer]; END; DrawBurrCon: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE { <<--uses outer stuff!!>> pr.drawRect[CDBasics.MapRect[r, trans], l, pr] }; <<--copied from chipmonk without understanding>> class: ContactPtr = NARROW[inst.ob.specific]; dBur: CD.Number = lambda/2; burAct: CD.Number = lambda*2; diffBur: CD.Position = [ x: IF class.wExt> pForVia: CD.ObjectClass = RegisterObjectClass[$CMosMmContact]; mmRimWidth: CD.Number = lambda; cut2min: CD.Number = 3*lambda; CreateMmCon: PUBLIC PROC [l: CD.Number, wex: CD.Number, lex: CD.Number] 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]; IF l=mins THEN RETURN [CMosObjects.CreateMmCon[]]; cp.typ _ mm2; <<--cp.wExt _ ;>> <<--cp.wExt _ ;>> cob.class _ pForVia; IF l> BEGIN mins: CD.Number = cut2min+2*mmRimWidth; r: CD.Rect = CDBasics.MapRect[inst.ob.bbox, trans]; pr.drawRect[r, met, pr]; pr.drawRect[r, met2, pr]; IF inst.ob.bbox.x2>mins THEN --old technology-- pr.drawRect[CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2, pr] ELSE --new technology-- pr.drawRect[CDBasics.Extend[r, -mmRimWidth], cut2, pr]; END; <<-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] = BEGIN cp: ContactPtr = NARROW[me.specific]; RETURN [ SELECT cp.typ FROM burr => Rope.Concat["buried contact ", CDOps.LayerRope[me.layer]], mDif => Rope.Concat[CDOps.LayerRope[me.layer], " contact"], difShort => Rope.Concat["dif - short contact ", CDOps.LayerRope[me.layer]], butt => Rope.Concat["butting contact ", CDOps.LayerRope[me.layer]], mPol => "contact poly", mm2 => "via", ENDCASE => "unknown contact" ] END; Init: PROC [] = BEGIN pForDifPolCon.drawMe _ pForDifPolCon.quickDrawMe _ DrawDifPolCon; pForDifPolCon.internalRead _ ReadDifPolCon; pForDifPolCon.internalWrite _ WriteDifPolCon; pForDifPolCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForDifPolCon, MatchContact]; pForWellDifPolCon.drawMe _ pForWellDifPolCon.quickDrawMe _ DrawWellDifPolCon; pForWellDifPolCon.interestRect _ InsideRectWithSurround; pForWellDifPolCon.showMeSelected _ ShowSelectedWithSurround; pForWellDifPolCon.internalRead _ ReadDifPolCon; pForWellDifPolCon.internalWrite _ WriteDifPolCon; pForWellDifPolCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForWellDifPolCon, MatchContact]; pForButContact.internalRead _ ReadButCon; pForWellButContact.internalRead _ ReadButCon; pForBurCon.drawMe _ pForBurCon.quickDrawMe _ DrawBurrCon; pForBurCon.internalRead _ ReadBurCon; pForBurCon.internalWrite _ WriteBurCon; pForBurCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForBurCon, MatchContact]; <> pForWellBurCon.interestRect _ InsideRectWithSurround; pForWellBurCon.internalRead _ ReadBurCon; pForWellBurCon.internalWrite _ WriteBurCon; pForWellBurCon.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForWellBurCon, MatchContact]; <<>> pForVia.drawMe _ pForVia.quickDrawMe _ DrawVia; pForVia.internalRead _ ReadVia; pForVia.internalWrite _ WriteVia; pForVia.describe _ Describe; CDStretchyBackdoor.InstallMatchProc[pForVia, MatchContact]; pForDifShorts.internalRead _ ReadDifShortCon; pForWellDifShorts.internalRead _ ReadDifShortCon; END; Init[]; END.