<> <> <> <> DIRECTORY Atom, CMosContacts, CD, CDBasics, CDCallSpecific, CDIO, CDLRUCache, CDOrient, CDRects USING [CreateRect], CDStretchyExtras, CDApplications, CMos, Rope, TokenIO; CMosContactsImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCallSpecific, CDIO, CDLRUCache, CDOrient, CDStretchyExtras, CDApplications, CDRects, CMos, Rope, TokenIO EXPORTS CMosContacts = BEGIN OPEN CMos; lambda: CD.DesignNumber = CD.lambda; ContactType: TYPE = CMosContacts.ContactType; ContactPtr: TYPE = CMosContacts.ContactPtr; ContactRec: TYPE = CMosContacts.ContactRec; undef: CD.Layer = CMosContacts.undef; wellSurround: CD.DesignNumber = 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]; ToPosition: PROC [x: REF] RETURNS [p: CD.DesignPosition] = <<--y field defaults to lambda, x field defaults to 0>> <<--[0, 0] if not done>> 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; 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.ObPtr] = { ob: CD.ObPtr _ NEW[CD.ObjectDefinition]; ob.specificRef _ NEW[ContactRec]; RETURN [ob] }; InsideRectWithSurround: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN RETURN [CDBasics.Extend[CDBasics.RectAt[[0, 0], ob.size], -wellSurround]] END; ShowSelectedWithSurround: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN pr.outLineProc[CDBasics.Extend[CDOrient.RectAt[pos, aptr.ob.size, orient], -wellSurround], pr] END; HitInsideWithSurround: PROC [aptr: CD.ApplicationPtr, hitRect: CD.DesignRect] RETURNS [BOOL] = BEGIN RETURN [CDBasics.Intersect[ CDBasics.Extend[ CDApplications.ARectO[aptr], -wellSurround], hitRect]] END; MatchContact: PROC [me: CD.ObPtr, r: CD.DesignRect, 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.specificRef]; 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: REF CD.ObjectProcs = RegisterObjectType[$CMosContactDifAndPol]; pForWellDifPolCon: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellDifAndPol]; difpolRimWidth: CD.DesignNumber = lambda; CreateDifCon: PUBLIC PROC [l: CD.DesignNumber, difLev: CD.Layer] RETURNS [CD.ObPtr] = <<--connect diffusion with metal>> BEGIN cob: CD.ObPtr ~ difCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; IF difLev=undef THEN difLev_ndif; l _ MAX[l, butConSX]; cp.typ _ mDif; cob.layer _ difLev; IF difLev=CMos.pdif THEN { cob.p _ pForWellDifPolCon; cob.size _ [butConSX+2*wellSurround, l+2*wellSurround]; } ELSE { cob.p _ pForDifPolCon; cob.size _ [butConSX, l]; }; RETURN [difCache.ReplaceByAequivalent[cob]] END; CreatePolyCon: PUBLIC PROC [l: CD.DesignNumber] RETURNS [CD.ObPtr] = <<--connect poly with metal>> BEGIN cob: CD.ObPtr ~ polyCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; l _ MAX[l, butConSX]; cp.typ _ mPol; cob.p _ pForDifPolCon; cob.size _ [butConSX, l]; cob.layer _ pol; RETURN [polyCache.ReplaceByAequivalent[cob]] END; LengthenPolyDif: CDCallSpecific.CallProc = BEGIN amount: CD.DesignPosition = ToPosition[x]; IF amount.y=0 OR amount.x#0 THEN done _ FALSE ELSE { new: CD.ObPtr; sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0; cp: ContactPtr = NARROW[aptr.ob.specificRef]; sz: CD.DesignPosition _ CDBasics.SubPoints[CDBasics.AddPoints[aptr.ob.size, amount], [sur, sur]]; IF sz.x<=0 OR sz.y<=0 THEN {done _ FALSE; RETURN}; IF aptr.ob.layer=pol THEN new _ CreatePolyCon[sz.y] ELSE new _ CreateDifCon[sz.y, aptr.ob.layer]; IF new#NIL THEN aptr.ob _ new ELSE done _ FALSE; repaintMe _ TRUE; } END; DefaultenPolyDif: CDCallSpecific.CallProc = BEGIN new: CD.ObPtr; cp: ContactPtr = NARROW[aptr.ob.specificRef]; IF aptr.ob.layer=pol THEN new _ CreatePolyCon[4*lambda] ELSE new _ CreateDifCon[4*lambda, aptr.ob.layer]; repaintMe _ TRUE; IF new#NIL THEN aptr.ob _ new ELSE done _ FALSE; END; ReadDifPolCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN lev: CD.Layer = CDIO.ReadLayer[]; IF lev=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[]] ] ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[], lev] ] END; WriteDifPolCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN sur: INT = IF me.layer=CMos.pdif THEN 2*wellSurround ELSE 0; CDIO.WriteLayer[me.layer]; TokenIO.WriteInt[me.size.y-sur]; END; DrawDifPolCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient]; pr.drawRect[r, met, pr]; pr.drawRect[r, aptr.ob.layer, pr]; pr.saveRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr]; END; DrawWellDifPolCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient]; inr: CD.DesignRect = CDBasics.Extend[r, -wellSurround]; pr.drawRect[inr, met, pr]; pr.drawRect[inr, aptr.ob.layer, pr]; pr.saveRect[CDBasics.Extend[inr, -difpolRimWidth], cut, pr]; pr.drawRect[r, nwel, pr]; END; <<-- DifShort -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForDifShorts: REF CD.ObjectProcs = RegisterObjectType[$CMosContactDifShort]; pForWellDifShorts: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellDifShort]; difShortRimWidth: CD.DesignNumber = lambda; CreateDifShortCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.ObPtr] = BEGIN cob: CD.ObPtr ~ dsCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; IF difLev=undef THEN difLev _ ndif; cp.typ _ difShort; cob.layer _ difLev; IF difLev=CMos.pdif THEN { cob.p _ pForWellDifShorts; cob.size _ [butConSX+2*wellSurround, 8*lambda+2*wellSurround] } ELSE IF difLev=CMos.ndif THEN { cob.p _ pForDifShorts; cob.size _ [butConSX, 8*lambda] } ELSE ERROR; RETURN [dsCache.ReplaceByAequivalent[cob]] END; ReadDifShortCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN RETURN [ CreateDifShortCon[CDIO.ReadLayer[]] ] END; WriteDifShortCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN CDIO.WriteLayer[me.layer]; END; DrawDifShortContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.saveRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; r: CD.DesignRect = CDOrient.RectAt[[0, 0], aptr.ob.size]; mr: CD.DesignRect = CDBasics.Extend[r, -difShortRimWidth]; h: CD.DesignNumber = (r.y2-r.y1)/2; Draw[r, met]; Draw[[x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y1+h], CMos.ndif]; Draw[[x1: r.x1, y1: r.y1+h, x2: r.x2, y2: r.y2], CMos.pwelCont]; Save[[x1: mr.x1, x2: mr.x2, y1: mr.y1, y2: mr.y1+2*lambda], cut]; Save[[x1: mr.x1, x2: mr.x2, y1: mr.y2-2*lambda, y2: mr.y2], cut]; END; DrawWellDifShortContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; r: CD.DesignRect = CDOrient.RectAt[[0, 0], aptr.ob.size]; inr: CD.DesignRect = CDBasics.Extend[r, -wellSurround]; mr: CD.DesignRect = CDBasics.Extend[inr, -difShortRimWidth]; h: CD.DesignNumber = (inr.y2-inr.y1)/2; Draw[inr, met]; Draw[[x1: inr.x1, y1: inr.y1, x2: inr.x2, y2: inr.y1+h], CMos.pdif]; Draw[[x1: inr.x1, y1: inr.y1+h, x2: inr.x2, y2: inr.y2], CMos.nwelCont]; Save[[x1: mr.x1, x2: mr.x2, y1: mr.y1, y2: mr.y1+2*lambda], cut]; Save[[x1: mr.x1, x2: mr.x2, y1: mr.y2-2*lambda, y2: mr.y2], cut]; Draw[[x1: r.x1, x2: r.x2, y1: r.y1, y2: r.y2-h], nwel]; END; -- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- pForButContact: REF CD.ObjectProcs = RegisterObjectType[$CMosContactBut]; pForWellButContact: REF CD.ObjectProcs = RegisterObjectType[$CMosContactWellBut]; butContactPolyYS: CD.DesignNumber = 3*lambda; butContactDiffY: CD.DesignNumber = butContactPolyYS-lambda; butContactDiffYS: CD.DesignNumber = 4*lambda; butConSX: CD.DesignNumber = 4*lambda; butConSY: CD.DesignNumber = butContactDiffY+butContactDiffYS; butContactRimWidth: CD.DesignNumber = lambda; pButConInnerY: CD.DesignNumber = wellSurround-butContactDiffY; pButConSX: CD.DesignNumber = butConSX+2*wellSurround; pButConSY: CD.DesignNumber = pButConInnerY+butConSY+wellSurround; pButConInner: CD.DesignRect = [ x1: wellSurround, x2: wellSurround+butConSX, y1: pButConInnerY, y2: pButConInnerY+butConSY ]; CreateButCon: PUBLIC PROC [difLev: CD.Layer] RETURNS [CD.ObPtr] = <<--connects metal with poly and diffusion>> BEGIN cob: CD.ObPtr ~ butCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; cp.typ _ butt; IF difLev=undef THEN difLev_ndif; cob.layer _ difLev; IF difLev=CMos.pdif THEN { cob.p _ pForWellButContact; cob.size _ [pButConSX, pButConSY]; } ELSE { cob.p _ pForButContact; cob.size _ [butConSX, butConSY]; }; RETURN [butCache.ReplaceByAequivalent[cob]] END; ReadButCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN RETURN [ CreateButCon[CDIO.ReadLayer[]] ] END; WriteButCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN CDIO.WriteLayer[me.layer]; END; DrawButContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.saveRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Draw[[0, 0, butConSX, butConSY], met]; Draw[[0, 0, butConSX, butContactPolyYS], pol]; Draw[[0, butContactDiffY, butConSX, butConSY], aptr.ob.layer]; Save[[butContactRimWidth, butContactRimWidth, butConSX-butContactRimWidth, butConSY-butContactRimWidth], cut]; END; DrawWellButContact: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.saveRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; inr: CD.DesignRect = [ x1: wellSurround, y1: pButConInnerY, x2: wellSurround+butConSX, y2: pButConInnerY+butConSY ]; Draw[inr, met]; Draw[[x1: inr.x1, y1: inr.y1, x2: inr.x2, y2: inr.y1+butContactPolyYS], pol]; Draw[[x1: inr.x1, y1: inr.y1+butContactDiffY, x2: inr.x2, y2: inr.y2], aptr.ob.layer]; Draw[[x1: 0, y1: 0, x2: pButConSX, y2: pButConSY], nwel]; Save[CDBasics.Extend[inr, -butContactRimWidth], cut]; END; PButInsideRectWithSurround: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN RETURN [pButConInner] END; PButHitInsideWithSurround: PROC [aptr: CD.ApplicationPtr, hitRect: CD.DesignRect] RETURNS [BOOL] = BEGIN RETURN [CDBasics.Intersect[ CDOrient.MapRect[ itemInCell: pButConInner, cellSize: [pButConSX, pButConSY], cellInstOrient: aptr.orientation, cellInstPos: aptr.location ], hitRect]] END; PButShowSelectedWithSurround: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN pr.outLineProc[ CDOrient.MapRect[ itemInCell: pButConInner, cellSize: [pButConSX, pButConSY], cellInstOrient: orient, cellInstPos: pos ], pr] END; <<>> <<-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForBurCon: REF CD.ObjectProcs = RegisterObjectType[$CMosBurContact]; pForWellBurCon: REF CD.ObjectProcs = RegisterObjectType[$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.DesignNumber, wex: CD.DesignNumber, lex: CD.DesignNumber, difLev: CD.Layer] RETURNS [CD.ObPtr] = <<-- connects diffusion with poly without accessing metal>> BEGIN <<-- copied from chipmonk without understanding>> burAct: CD.DesignNumber = 2*lambda; actWidth, xMargins: CD.DesignNumber; cob: CD.ObPtr ~ burCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; 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.highLightError]]; } ELSE { cob.p _ pForBurCon; cob.size _ [w, l]; }; cob.layer _ difLev; RETURN [burCache.ReplaceByAequivalent[cob]] END; ReadBurCon: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN w: INT = TokenIO.ReadInt[]; l: INT = TokenIO.ReadInt[]; wex: INT = TokenIO.ReadInt[]; lex: INT = TokenIO.ReadInt[]; difLev: CD.Layer = CDIO.ReadLayer[]; RETURN [ CreateBurCon[w, l, wex, lex, difLev] ] END; WriteBurCon: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN cp: ContactPtr = NARROW[me.specificRef]; IF me.layer = CMos.pdif THEN { TokenIO.WriteInt[me.size.x-2*wellSurround]; TokenIO.WriteInt[me.size.y-2*wellSurround]; } ELSE { TokenIO.WriteInt[me.size.x]; TokenIO.WriteInt[me.size.y]; }; TokenIO.WriteInt[cp.wExt]; TokenIO.WriteInt[cp.lExt]; CDIO.WriteLayer[me.layer]; END; DrawBurrCon: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN Draw: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.drawRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; Save: PROC[r: CD.DesignRect, l: CD.Layer] = INLINE <<--uses outer stuff!!>> BEGIN pr.saveRect[ CDOrient.MapRect[ itemInCell: r, cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos], l, pr]; END; <<--copied from chipmonk without understanding>> p: ContactPtr = NARROW[aptr.ob.specificRef]; dBur: CD.DesignNumber = lambda/2; burAct: CD.DesignNumber = lambda*2; diffBur: CD.DesignPosition = [ x: IF p.wExt> <> <> <<>> <> <<--uses outer stuff!!>> <> <> <> <> <> <> <> <> <> <> <<>> <> <<--uses outer stuff!!>> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <<];>> <> <> <> <> <> <<>> LengthenBur: CDCallSpecific.CallProc = BEGIN amount: CD.DesignPosition = ToPosition[x]; IF amount.y=0 AND amount.x=0 THEN done _ FALSE ELSE { new: CD.ObPtr; sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0; cp: ContactPtr _ NARROW[aptr.ob.specificRef]; sz: CD.DesignPosition _ CDBasics.SubPoints[CDBasics.AddPoints[aptr.ob.size, amount], [sur, sur]]; IF sz.x<=0 OR sz.y<=0 THEN {done _ FALSE; RETURN}; new _ CreateBurCon[w: sz.x, l: sz.y, wex: cp.wExt, lex: cp.lExt, difLev: aptr.ob.layer]; repaintMe _ TRUE; IF new#NIL THEN aptr.ob _ new ELSE done _ FALSE; }; END; ChangeExtensionBur: CDCallSpecific.CallProc = BEGIN amount: CD.DesignPosition = ToPosition[x]; IF amount.y=0 AND amount.x=0 THEN done _ FALSE ELSE { sur: INT = (IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0); cp: ContactPtr = NARROW[aptr.ob.specificRef]; new: CD.ObPtr _ CreateBurCon[ w: aptr.ob.size.x-sur+amount.x, l: aptr.ob.size.y-sur+amount.y, wex: cp.wExt+amount.x, lex: cp.lExt+amount.y, difLev: aptr.ob.layer ]; repaintMe _ TRUE; IF new#NIL THEN aptr.ob _ new ELSE done _ FALSE; } END; DefaultenBur: CDCallSpecific.CallProc = BEGIN sur: INT = IF aptr.ob.layer=CMos.pdif THEN 2*wellSurround ELSE 0; cp: ContactPtr = NARROW[aptr.ob.specificRef]; new: CD.ObPtr _ CreateBurCon[w: aptr.ob.size.x-sur, l: 4*lambda, wex: cp.wExt, lex: cp.lExt, difLev: aptr.ob.layer]; repaintMe _ TRUE; IF new#NIL THEN aptr.ob _ new ELSE done _ FALSE; END; <<--Mm -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> pForVia: REF CD.ObjectProcs = RegisterObjectType[$CMosMmContact]; mmRimWidth: CD.DesignNumber = lambda; cut2min: CD.DesignNumber = 3*lambda; CreateMmCon: PUBLIC PROC [l: CD.DesignNumber, wex: CD.DesignNumber, lex: CD.DesignNumber] RETURNS [CD.ObPtr] = <<--ignores wex and lex in chipmonk, why???>> <<--connects two layers of metal>> BEGIN cob: CD.ObPtr ~ mmCache.UnusedOrNew[]; cp: ContactPtr ~ NARROW[cob.specificRef]; mins: CD.DesignNumber = cut2min+2*mmRimWidth; oldMins: CD.DesignNumber = cut2min+2*--mmRimWidth--2*lambda; l _ MAX[l, mins]; cp.typ _ mm2; <<--cp.wExt _ ;>> <<--cp.wExt _ ;>> cob.p _ pForVia; IF l> BEGIN mins: CD.DesignNumber = cut2min+2*mmRimWidth; r: CD.DesignRect = CDOrient.RectAt[pos, aptr.ob.size, orient]; pr.drawRect[r, met, pr]; pr.drawRect[r, met2, pr]; IF aptr.ob.size.x>mins THEN --old technology-- pr.saveRect[CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2, pr] ELSE --new technology-- pr.saveRect[CDBasics.Extend[r, -mmRimWidth], cut2, pr]; END; <<-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- >> DescribeLayer: PROC[l: CD.Layer] RETURNS [Rope.ROPE] = {RETURN [Atom.GetPName[CD.LayerKey[l]]]}; Describe: PROC[me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN cp: ContactPtr = NARROW[me.specificRef]; RETURN [ SELECT cp.typ FROM burr => Rope.Concat["buried contact ", DescribeLayer[me.layer]], mDif => Rope.Concat[DescribeLayer[me.layer], " contact"], difShort => Rope.Concat["dif - short contact ", DescribeLayer[me.layer]], butt => Rope.Concat["butting contact ", DescribeLayer[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; CDStretchyExtras.InstallMatch[pForDifPolCon, MatchContact]; <> <> pForWellDifPolCon.drawMe _ pForWellDifPolCon.quickDrawMe _ DrawWellDifPolCon; pForWellDifPolCon.interestRect _ pForWellDifPolCon.oldInsideRect _ InsideRectWithSurround; pForWellDifPolCon.showMeSelected _ ShowSelectedWithSurround; pForWellDifPolCon.hitInside _ HitInsideWithSurround; pForWellDifPolCon.internalRead _ ReadDifPolCon; pForWellDifPolCon.internalWrite _ WriteDifPolCon; pForWellDifPolCon.describe _ Describe; CDStretchyExtras.InstallMatch[pForWellDifPolCon, MatchContact]; <> <> pForButContact.drawMe _ pForButContact.quickDrawMe _ DrawButContact; pForButContact.internalRead _ ReadButCon; pForButContact.internalWrite _ WriteButCon; pForButContact.describe _ Describe; CDStretchyExtras.InstallMatch[pForButContact, MatchContact]; pForWellButContact.drawMe _ pForWellButContact.quickDrawMe _ DrawWellButContact; pForWellButContact.interestRect _ pForWellButContact.oldInsideRect _ PButInsideRectWithSurround; pForWellButContact.hitInside _ PButHitInsideWithSurround; pForWellButContact.showMeSelected _ PButShowSelectedWithSurround; pForWellButContact.internalRead _ ReadButCon; pForWellButContact.internalWrite _ WriteButCon; pForWellButContact.describe _ Describe; CDStretchyExtras.InstallMatch[pForWellButContact, MatchContact]; pForBurCon.drawMe _ pForBurCon.quickDrawMe _ DrawBurrCon; pForBurCon.internalRead _ ReadBurCon; pForBurCon.internalWrite _ WriteBurCon; pForBurCon.describe _ Describe; CDStretchyExtras.InstallMatch[pForBurCon, MatchContact]; CDCallSpecific.Register[$Lengthen, pForBurCon, LengthenBur]; CDCallSpecific.Register[$ChangeExt, pForBurCon, ChangeExtensionBur]; CDCallSpecific.Register[$Default, pForBurCon, DefaultenBur]; <> pForWellBurCon.interestRect _ pForWellBurCon.oldInsideRect _ InsideRectWithSurround; pForWellBurCon.hitInside _ HitInsideWithSurround; pForWellBurCon.internalRead _ ReadBurCon; pForWellBurCon.internalWrite _ WriteBurCon; pForWellBurCon.describe _ Describe; CDStretchyExtras.InstallMatch[pForWellBurCon, MatchContact]; CDCallSpecific.Register[$Lengthen, pForWellBurCon, LengthenBur]; CDCallSpecific.Register[$ChangeExt, pForWellBurCon, ChangeExtensionBur]; CDCallSpecific.Register[$Default, pForWellBurCon, DefaultenBur]; <<>> pForVia.drawMe _ pForVia.quickDrawMe _ DrawVia; pForVia.internalRead _ ReadVia; pForVia.internalWrite _ WriteVia; pForVia.describe _ Describe; CDStretchyExtras.InstallMatch[pForVia, MatchContact]; <> <> pForDifShorts.drawMe _ pForDifShorts.quickDrawMe _ DrawDifShortContact; pForDifShorts.internalRead _ ReadDifShortCon; pForDifShorts.internalWrite _ WriteDifShortCon; pForDifShorts.describe _ Describe; CDStretchyExtras.InstallMatch[pForDifShorts, MatchContact]; pForWellDifShorts.drawMe _ pForWellDifShorts.quickDrawMe _ DrawWellDifShortContact; pForWellDifShorts.interestRect _ pForWellDifShorts.oldInsideRect _ InsideRectWithSurround; pForWellDifShorts.hitInside _ HitInsideWithSurround; pForWellDifShorts.internalRead _ ReadDifShortCon; pForWellDifShorts.internalWrite _ WriteDifShortCon; pForWellDifShorts.describe _ Describe; CDStretchyExtras.InstallMatch[pForWellDifShorts, MatchContact]; END; Init[]; END.