DIRECTORY CD, CDAtomicObjects, CDBasics, CDCells, CDEvents, CDLayers, CDProperties, CDRects, CDSimpleRules, CDSimpleRulesBackdoor, CDOps, LRUCache, RealOps; CDStitchedViasImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDBasics, CDCells, CDEvents, CDLayers, CDOps, CDProperties, CDRects, CDSimpleRules, CDSimpleRulesBackdoor, LRUCache, RealOps = BEGIN Rules: TYPE = CDSimpleRules.Rules; GetSimpleBigContact: PROC [size: CD.Position, layer1, layer2: CD.Layer] RETURNS [obj: CD.Object _ NIL] = { tech: CD.Technology _ CD.LayerTechnology[layer1]; IF tech#NIL THEN SELECT tech.key FROM $cmosB => { l1a: ATOM _ CD.LayerKey[layer1]; l2a: ATOM _ CD.LayerKey[layer2]; SELECT TRUE FROM (l1a = $met2 AND l2a = $met) OR (l1a = $met AND l2a = $met2) => obj _ CDAtomicObjects.CreateAtomicOb[$C2LargeVia, size, tech]; (l1a = $pol AND l2a = $met) => obj _ CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer1]; (l1a = $met AND l2a = $pol) => obj _ CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer2]; ENDCASE => NULL; }; ENDCASE => NULL }; GetSingleViaForStitching: PROC [rules: Rules, size: CD.Position, layer1, layer2: CD.Layer] RETURNS [via: CD.Object _ NIL] = { tech: CD.Technology ~ CD.LayerTechnology[layer1]; minBigContact: CD.Object ~ GetSimpleBigContact[[1, 1], layer1, layer2]; IF minBigContact=NIL OR tech=NIL THEN { via _ CDSimpleRules.Contact[rules, layer1, layer2] } ELSE { -- big contact exists, determine size to use lambda: CD.Number ~ tech.lambda; ctSize: CD.Position ~ CD.InterestSize[minBigContact]; IF ctSize.x <= size.x AND ctSize.y <= size.y THEN { perim2x2: CD.Number ~ RealOps.ModalRound[size.x/(6*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(6*lambda), RealOps.FixMode]*8*lambda; -- 2x2 contacts go in a 6x6 square perim3x3: CD.Number ~ RealOps.ModalRound[size.x/(7*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(7*lambda), RealOps.FixMode]*12*lambda; -- 3x3 contacts go in a 7x7 square perim4x4: CD.Number ~ RealOps.ModalRound[size.x/(8*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(8*lambda), RealOps.FixMode]*16*lambda; -- 4x4 contacts go in a 8x8 square SELECT TRUE FROM perim4x4 >= perim2x2 AND perim4x4 >= perim3x3 => via _ GetSimpleBigContact[[8*lambda, 8*lambda], layer1, layer2]; perim3x3 >= perim2x2 AND perim3x3 >= perim4x4 => via _ GetSimpleBigContact[[7*lambda, 7*lambda], layer1, layer2]; perim2x2 >= perim4x4 AND perim2x2 >= perim3x3 => via _ GetSimpleBigContact[[6*lambda, 6*lambda], layer1, layer2]; ENDCASE => ERROR; } ELSE { -- big contact too big, must do it with small ones via _ CDSimpleRules.Contact[rules, layer1, layer2] } } }; MinDist: PROC [rules: Rules, layer1, layer2: CD.Layer] RETURNS [m: CD.Number_-1] = { minCt: CD.Object = CDSimpleRules.Contact[rules, layer1, layer2]; ap: CDAtomicObjects.AtomicObsSpecific = NARROW[minCt.specific]; layer1 _ CDLayers.AbstractToPaint[layer1]; layer2 _ CDLayers.AbstractToPaint[layer2]; FOR dl: CDAtomicObjects.DrawList _ ap.rList, dl.rest WHILE dl#NIL DO IF ~CDBasics.Inside[dl.first.r, ap.ir] THEN LOOP; --ignore wells IF dl.first.layer=layer1 OR dl.first.layer=layer2 THEN LOOP; --ignore layer1, layer2 m _ MAX[m, CDSimpleRules.MinWidth[rules, dl.first.layer] + CDSimpleRules.MinSpace[rules, dl.first.layer, dl.first.layer]]; ENDLOOP; IF m<1 OR m>1000--catch in case of non implementation-- THEN ERROR; }; InternalStitchedVia: PROC [rules: Rules, size: CD.Position, layer1, layer2: CD.Layer] RETURNS [via: CD.Object] = { Incl: PROC [cell: CD.Object, ob: CD.Object, iPos: CD.Position_[0, 0]] = { [] _ CDCells.IncludeOb[cell: cell, ob: ob, trans: [CDBasics.SubPoints[iPos, CD.InterestBase[ob]]], mode: dontResize]; }; contact: CD.Object _ GetSingleViaForStitching[rules, size, layer1, layer2]; ctSize: CD.Position _ CD.InterestSize[contact]; IF ctSize.x >= size.x AND ctSize.y >= size.y THEN via _ contact ELSE { tech: CD.Technology ~ CD.LayerTechnology[layer1]; minDist: CD.Number _ MinDist[rules, layer1, layer2]; grid: CD.Number _ IF tech#NIL THEN tech.lambda ELSE 1; step: CD.Position _ [MAX[minDist, ctSize.x], MAX[minDist, ctSize.y]]; numY: INT _ MAX[1, size.y/step.y]; numX: INT _ MAX[1, size.x/step.x]; ctCov: CD.Position _ [(numX-1)*step.x+ctSize.x, (numY-1)*step.y+ctSize.y]; off: CD.Position _ [ (MAX[size.x-ctCov.x, 0]/(2*grid))*grid, (MAX[size.y-ctCov.y, 0]/(2*grid))*grid ]; via _ CDCells.CreateEmptyCell[]; FOR indexY: CD.Number IN [0 .. numY) DO FOR indexX: CD.Number IN [0 .. numX) DO Incl[via, contact, [off.x+indexX*step.x, off.y+indexY*step.y]]; ENDLOOP; ENDLOOP; Incl[via, CDRects.CreateRect[size, layer1]]; Incl[via, CDRects.CreateRect[size, layer2]]; CDCells.ToSequenceMode[via]; [] _ CDCells.ResizeCell[NIL, via]; CDProperties.PutObjectProp[via, $CreatedBy, $StitchedVias]; IF ~CDOps.MakeImmutable[via] THEN ERROR; }; }; DescRep: TYPE = RECORD [size: CD.Position, layer1, layer2: CD.Layer, ob: CD.Object_NIL, rules: Rules]; cache: LRUCache.Handle _ LRUCache.Create[17, Hash, Equal]; Hash: PROC [x: REF] RETURNS [h: CARDINAL] = { d: REF DescRep = NARROW[x]; h _ (d.size.x MOD 10000B)*3+(d.size.y MOD 1000B)*19+d.layer1+d.layer2*13 }; Equal: PROC [x, y: REF] RETURNS [BOOL] = { d1: REF DescRep = NARROW[x]; d2: REF DescRep = NARROW[y]; RETURN [d1.size=d2.size AND d1.layer1=d2.layer1 AND d1.layer2=d2.layer2 AND d1.rules=d2.rules] }; StitchedVia: PROC [rules: Rules, design: CD.Design, size: CD.Position, l1, l2: CD.Layer] RETURNS [via: CD.Object_NIL] = { d: REF DescRep _ NEW[DescRep_[ size: size, layer1: MIN[l1, l2], layer2: MAX[l1, l2], rules: CDSimpleRules.GetRulesKey[rules] ]]; d _ NARROW[LRUCache.Include[cache, d].used]; IF d.ob#NIL THEN RETURN [via _ d.ob]; BEGIN --not found with exact size new: CD.Object _ InternalStitchedVia[size: size, layer1: l1, layer2: l2, rules: rules]; IF new=NIL OR size=CD.InterestSize[new] THEN RETURN [via _ d.ob _ new] ELSE { d1: REF DescRep _ NEW[DescRep_[ size: CD.InterestSize[new], layer1: d.layer1, layer2: d.layer2, rules: d.rules ]]; d1 _ NARROW[LRUCache.Include[cache, d1].used]; IF d1.ob#NIL THEN RETURN [via _ d.ob _ d1.ob]; --discard new to increase sharing RETURN [via _ d.ob _ d1.ob _ new]; }; END; }; EachTechnology: CD.TechnologyEnumerator = { SELECT tech.key FROM $cmosB, $CMosA, $NMosA => CDSimpleRulesBackdoor.RegisterRules[[ key: NIL, technology: tech, largeContact: StitchedVia ]]; ENDCASE => NULL; }; RegisterTechnology: CDEvents.EventProc = { [] _ EachTechnology[NARROW[x]] }; CDEvents.RegisterEventProc[$RegisterTechnology, RegisterTechnology]; [] _ CD.EnumerateTechnologies[EachTechnology]; END. ~CDStitchedViasImpl.mesa Copyright c 1987 by Xerox Corporation. All rights reversed. Created by: Christian Jacobi, March 23, 1987 12:37:36 pm PST; Using actual creation code from Brian Preas Last edited by: Christian Jacobi, March 23, 1987 2:33:09 pm PST Semi technology dependent: Does not import technology, but works correctly only for a certain range of technologies. --this is semi technology dependent; --no big contacts, must do it with small ones --use 2, 3, or 4 lambda square vias that give largest perimeter --sorry: halfway technology dependent -- assumes contact exists -- assumes contact is atomic object --Convention: layer1, layer2 are ordered! --it doesn't really matter whether the hash function is very good --layer1, layer2 are ordered --layer1, layer2 are ordered --size was not exact --if we want to introduce caching per design, use cache _ CDValue.Fetch[... Κ˜šœ™Jšœ Οmœ1™™>Jšœ+™+Jšœ?™?J™™J™BJ™—J˜—šΟk œ˜ Jšžœ˜’J™—codešΟnœžœžœ˜"Kšžœ”˜›—Kšž˜K˜Kšœžœ˜"K˜šŸœžœžœžœžœžœ žœ˜jKšœžœžœ˜1šžœžœžœ˜šžœ ž˜˜ Kšœžœžœ˜ Kšœžœžœ˜ šžœžœž˜šœ žœ žœ žœ˜@Kšœ>˜>—šœ žœ˜KšœL˜L—šœ žœ˜KšœL˜L—Kšžœžœ˜—Kšœ˜—Kšžœž˜——Kšœ˜—K˜šŸœžœžœžœžœžœ žœ˜}KšΟc%™%Kšœžœžœ˜1Kšœžœ6˜Gš žœžœžœžœžœ˜'Kš -™-Kšœ2˜2Kšœ˜—šžœ ,˜3Kšœžœ˜ Kšœžœ žœ˜5šžœžœžœ˜3Kš @™@Kšœ žœƒ "˜±Kšœ žœ„ "˜²Kšœ žœ„ "˜²šžœžœž˜šœžœ˜0Kšœ@˜@—šœžœ˜0Kšœ@˜@—šœžœ˜0Kšœ@˜@—Kšžœžœ˜—Kšœ˜—šžœ 2˜:Kšœ2˜2K˜—Kšœ˜—Kšœ˜K˜—š Ÿœžœ žœžœžœ˜TKš %™%Kš ™Kš #™#Kšœžœ7˜@Kšœ(žœ˜?Kšœ*˜*Kšœ*˜*šžœ2žœžœž˜DKšžœ%žœžœ ˜@Kš žœžœžœžœ ˜TKšœžœs˜zKšžœ˜—Jš žœžœ 'œžœžœ˜CKšœ˜—K˜š Ÿœžœžœžœžœžœ ˜rš Ÿœžœžœ žœžœ˜IKšœLžœ'˜uK˜—Kšœ žœ@˜KKšœžœ žœ˜/Kšžœžœžœ˜@šžœ˜Kšœžœžœ˜1Kšœ žœ)˜4Kš œžœ žœžœžœ žœ˜6Kšœžœ žœžœ˜FKšœžœžœ˜"Kšœžœžœ˜"KšœžœA˜Jšœžœ ˜Kšžœ#˜'Kšžœ"˜&K˜—Kšœ ˜ šžœ žœžœ ž˜'šžœ žœžœ ž˜'Kšœ?˜?Kšžœ˜—Kšžœ˜—Kšœ,˜,Kšœ,˜,Kšœ˜Kšœžœ˜"Kšœ;˜;Kšžœžœžœ˜(Kšœ˜—Kšœ˜K˜—š œ žœžœžœžœ žœžœ˜fKšœ)™)—K˜Kšœ:˜:K˜š Ÿœžœžœžœžœ˜-Kš A™AKšœžœ žœ˜šœžœžœ˜HKš ™—Kšœ˜—K˜š Ÿœžœžœžœžœ˜*Kšœžœ žœ˜Kšœžœ žœ˜šžœžœžœ+˜^Kš ™—Kšœ˜—K˜šŸ œžœžœžœžœžœžœžœ˜yšœžœ žœ ˜Kšœ ˜ Kšœžœ ˜Kšœžœ ˜Kšœ'˜'Kšœ˜—Kšœžœ"˜,Jšžœžœžœžœ˜%šžœ ˜!JšœžœQ˜XJš žœžœžœžœžœžœ˜Fšžœ˜Kš ™šœžœ žœ ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœžœ#˜.Jš žœžœžœžœ !˜PJšžœ˜"J˜—Jšžœ˜—Jš K™KJ˜—J˜šŸœžœ˜+šžœ žœ˜šœ˜šœ%˜%Kšœ ˜ Jšœ˜Jšœ˜Jšœ˜——Jšžœžœ˜—J˜—J˜šŸœ˜*Jšœžœ˜J˜—J˜JšœD˜DJšœžœ'˜.Jšžœ˜J˜—…—–%#