<> <> <> <<>> DIRECTORY BondingPads, BrineIO, CD, CDBasics, CDRects, CMosB, Core, CoreGeometry, CoreGeometryBackdoor, CoreIO, CoreOps, CoreProperties, IO, PWCore, RefTab; BondingPadsImpl: CEDAR PROGRAM IMPORTS BrineIO, CD, CDBasics, CDRects, CMosB, CoreGeometry, CoreGeometryBackdoor, CoreIO, CoreOps, CoreProperties, PWCore, RefTab EXPORTS BondingPads ~ BEGIN <> PadArray: TYPE = BondingPads.PadArray; Side: TYPE = CoreGeometry.Side; SidePads: TYPE = BondingPads.SidePads; Pads: TYPE = BondingPads.Pads; Pad: TYPE = BondingPads.Pad; tech: CD.Technology _ CMosB.cmosB; <> MarkBondingPads: PUBLIC PROC[cell: Core.CellType] ~ { overGlass: CD.Layer _ CD.FetchLayer[tech, $ovg]; cut2: CD.Layer _ CD.FetchLayer[tech, $cut2]; layDeco: CoreGeometry.Decoration _ PWCore.extractMode.decoration; ect: Core.CellType; extractedToSource: RefTab.Ref; layout: CD.Object; bondingFrameSize: REF CD.Position; fourteen: INT _ tech.lambda*14; IsBig: PROC[ob: CD.Object] RETURNS[isBig: BOOL] = { <7.0>XrVTI4x>CDMEBESCMOSB16Nov87.load:>> <> < 14) => ovg>> size: CD.Position _ CD.InterestSize[ob]; RETURN[size.x > fourteen AND size.y > fourteen]}; EachAtomic: PROC[wire: Core.Wire] ~ { sourceWire: Core.Wire _ NARROW[RefTab.Fetch[extractedToSource, wire].val]; instances: LIST OF CoreGeometry.Instance; EachInst: CoreGeometry.EachInstanceProc ~ { -- instance RETURNS quit IF ~CDRects.IsBareRect[instance.obj] THEN [] _ CoreGeometry.FlattenInstance[instance, EachInst] ELSE { IF instance.obj.layer=overGlass OR (instance.obj.layer=cut2 AND IsBig[instance.obj]) THEN instances _ CONS[instance, instances]}}; name: IO.ROPE; IF sourceWire=NIL THEN RETURN; instances _ NARROW[CoreProperties.GetWireProp[sourceWire, $BondingPads]]; name _ CoreOps.GetFullWireName[cell.public, sourceWire]; [] _ CoreGeometry.EnumerateAllGeometry[layDeco, ect, wire, EachInst]; <> instances _ MergeSort[instances]; CoreProperties.PutWireProp[sourceWire, $BondingPads, instances]}; IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]#NIL THEN RETURN; [] _ PWCore.Layout[cell]; IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]#NIL THEN RETURN; [layout, ect, extractedToSource, ] _ PWCore.LayoutInfo[cell]; CoreOps.VisitRootAtomics[ect.public, EachAtomic]; bondingFrameSize _ NEW[CD.Position _ CD.InterestSize[layout]]; CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, bondingFrameSize]}; EnsureBondingPads: PUBLIC PROC[cell: Core.CellType] = { IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]=NIL THEN IF cell.class.recast=NIL THEN MarkBondingPads[cell] ELSE { recast: Core.CellType _ CoreOps.Recast[cell]; size: REF CD.Position; EachPair: PROC[actualWire, publicWire: Core.Wire] RETURNS [subWires: BOOL _ TRUE, quit: BOOL _ FALSE]= { origWire: Core.Wire _ actualWire; recastWire: Core.Wire _ publicWire; origInsts: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[origWire, $BondingPads]]; recastInsts: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[recastWire, $BondingPads]]; IF origInsts#NIL THEN RETURN -- recasted and original publics identical => this wire done ELSE FOR recastInsts _ recastInsts, recastInsts.rest WHILE recastInsts#NIL DO origInsts _ CONS[recastInsts.first, origInsts] ENDLOOP; CoreProperties.PutWireProp[origWire, $BondingPads, origInsts]}; EnsureBondingPads[recast]; []_CoreOps.VisitBindingSeq[cell.public, recast.public, EachPair]; size _ NARROW[CoreProperties.GetCellTypeProp[recast, $BondingFrameSize]]; CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, NEW[CD.Position _ size^]] } }; GetSize: PUBLIC PROC[cell: Core.CellType] RETURNS[size: CD.Position] = { refSize: REF CD.Position _ NARROW[CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]]; RETURN[refSize^]}; GetPads: PUBLIC PROC[cell: Core.CellType] RETURNS[padArray: PadArray] = { size: CD.Position _ GetSize[cell]; cRect: CD.Rect _ [0, 0, size.x, size.y]; eachPublic: PROC[wire: Core.Wire] = { instances: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[wire, $BondingPads]]; FOR instances _ instances, instances.rest WHILE instances#NIL DO ir: CD.Rect _ CoreGeometry.BBox[instances.first]; side: Side _ NearestSide[ir, cRect]; offSet: CD.Position _ OffSet[ir, cRect, side]; pad: Pad _ [wire, offSet]; padArray[side].pads _ CONS[pad, padArray[side].pads] ENDLOOP }; <> []_CoreOps.VisitRootAtomics[cell.public, eachPublic]; FOR side: Side IN Side DO offSets: LIST OF INT _ NIL; <> FOR pads: Pads _ padArray[side].pads, pads.rest WHILE pads#NIL DO offSets _ CONS[pads.first.pos.x, offSets]; FOR oSets: LIST OF INT _ offSets, oSets.rest WHILE oSets#NIL AND oSets.rest#NIL DO TwoInts: TYPE = RECORD[i0, i1: INT]; IF oSets.first < oSets.rest.first THEN EXIT; IF oSets.first = oSets.rest.first THEN {oSets.rest _ oSets.rest.rest; EXIT}; [oSets.first, oSets.rest.first] _ TwoInts[oSets.rest.first, oSets.first] ENDLOOP; ENDLOOP; padArray[side].offSets _ offSets; IF offSets=NIL THEN LOOP; IF offSets.rest#NIL THEN{ IF offSets.rest.rest#NIL THEN ERROR; IF offSets.rest.first-offSets.first<100*tech.lambda THEN ERROR}; <> DO done: BOOL _ TRUE; FOR pads: Pads _ padArray[side].pads, pads.rest WHILE pads#NIL AND pads.rest#NIL DO TwoPads: TYPE = RECORD[p0, p1: Pad]; IF pads.first.pos.y < pads.rest.first.pos.y THEN { --IF (pads.rest.first.pos.y-pads.first.pos.y) < 100*tech.lambda THEN ERROR-- LOOP}; IF pads.first.pos.y > pads.rest.first.pos.y OR pads.first.pos.x > pads.rest.first.pos.x THEN {[pads.first, pads.rest.first] _ TwoPads[pads.rest.first, pads.first]; done _ FALSE} ENDLOOP; IF done THEN EXIT ENDLOOP; ENDLOOP}; CompareRectBottomLeft: PROC [rect1: CD.Rect, rect2: CD.Rect] RETURNS [BOOL] = { overlappingInY: BOOL _ rect1.y1= xr.x1) AND (xr.y2 >= xr.y1); IF touch THEN { union: CD.Rect _ CDBasics.Surround[ir1, ir2]; size: CD.Position _ CDBasics.SizeOfRect[union]; pos: CD.Position _ CDBasics.BaseOfRect[union]; newObj: CD.Object _ CDRects.CreateRect[size, list.first.obj.layer]; list.rest _ list.rest.rest; list.first _ [newObj, [pos]]; done _ FALSE} ELSE { IF ~CompareRectBottomLeft[ir1, ir2] THEN {[list.first, list.rest.first]_TwoInstances[list.rest.first, list.first]; done_FALSE}}; ENDLOOP; IF done THEN EXIT ENDLOOP; RETURN[instances]}; NearestSide: PROC[sml, lrg: CD.Rect] RETURNS[side: Side _ left] ~ { dist: INT _ ABS[lrg.x1 - sml.x1]; test: INT _ ABS[lrg.x2 - sml.x2]; IF test < dist THEN {dist _ test; side _ right}; test _ ABS[lrg.y1 - sml.y1]; IF test < dist THEN {dist _ test; side _ bottom}; test _ ABS[lrg.y2 - sml.y2]; IF test < dist THEN {dist _ test; side _ top}}; OffSet: PROC[sml, lrg: CD.Rect, side: Side] RETURNS[offSet: CD.Position] ~ { <> offSet _ SELECT side FROM left => [(sml.x1+sml.x2)/2 - lrg.x1, (sml.y1+sml.y2)/2], right => [lrg.x2 - (sml.x1+sml.x2)/2, (sml.y1+sml.y2)/2], bottom => [(sml.y1+sml.y2)/2 - lrg.y1, (sml.x1+sml.x2)/2], top => [lrg.y2 - (sml.y1+sml.y2)/2, (sml.x1+sml.x2)/2], ENDCASE => ERROR }; <> PropWriteInstances: CoreIO.PropWriteProc = {CoreGeometryBackdoor.WriteInstances[stream, NARROW[value]]}; PropReadInstances: CoreIO.PropReadProc = {value _ CoreGeometryBackdoor.ReadInstances[stream]}; PropWriteSize: CoreIO.PropWriteProc = { pos: REF CD.Position _ NARROW[value]; BrineIO.WriteInt[stream, pos.x]; BrineIO.WriteInt[stream, pos.y]}; PropReadSize: CoreIO.PropReadProc = { pos: REF CD.Position _ NEW[CD.Position _ [0,0]]; pos.x _ BrineIO.ReadInt[stream]; pos.y _ BrineIO.ReadInt[stream]; value _ pos}; []_CoreIO.RegisterProperty[$BondingPads, PropWriteInstances, PropReadInstances]; []_CoreIO.RegisterProperty[$BondingFrameSize, PropWriteSize, PropReadSize]; END.