<> <> <> <> <> DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDImports, CDOrient, CDPinObjects, CDProperties, Convert, PWPins, Rope; PWPinsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDImports, CDOrient, CDPinObjects, CDProperties, Convert, Rope EXPORTS PWPins = BEGIN OPEN PWPins; GetSide: PUBLIC PROC [ob: CD.ObPtr, pin: CD.ApplicationPtr] RETURNS [isOnBorder: BOOL, side: Side] = { LargerSide: PROC [hSide, vSide: Side] RETURNS [side: Side] = { side _ IF pinRect.x2-pinRect.x1>pinRect.y2-pinRect.y1 THEN hSide ELSE vSide; }; rect: CD.Rect _ CD.InterestRect[ob]; -- the border pinRect: CD.Rect _ CDOrient.RectAt[pin.location, pin.ob.size, pin.orientation]; -- bbox of the pin isOnBorder _ TRUE; SELECT TRUE FROM rect.y2 = pinRect.y2 AND rect.x1 = pinRect.x1 => side _ LargerSide[top, left]; rect.y2 = pinRect.y2 AND rect.x2 = pinRect.x2 => side _ LargerSide[top, right]; rect.y1 = pinRect.y1 AND rect.x1 = pinRect.x1 => side _ LargerSide[bottom, left]; rect.y1 = pinRect.y1 AND rect.x2 = pinRect.x2 => side _ LargerSide[bottom, right]; rect.y2 = pinRect.y2 => side _ top; rect.y1 = pinRect.y1 => side _ bottom; rect.x1 = pinRect.x1 => side _ left; rect.x2 = pinRect.x2 => side _ right; ENDCASE => isOnBorder _ FALSE; }; FilterProc: TYPE = PROC [subRect: CD.Rect] RETURNS [isSubInteresting: BOOL _ TRUE]; DefaultFilter: FilterProc = {}; <> EnumerateDeepPinsInContext: PRIVATE PROC [ob: CD.ObPtr, location: CD.Position _ [0, 0], orientation: CD.Orientation _ 0, properties: CD.Properties _ NIL, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOL, filter: FilterProc] RETURNS [quit: BOOL _ FALSE] = { IF ~filter[CDOrient.MapRect[ itemInCell: CD.InterestRect[ob], cellSize: ob.size, cellInstOrient: orientation, cellInstPos: location]] THEN RETURN; SELECT TRUE FROM CDPinObjects.IsPinOb[ob] => { quit _ eachPin[NEW[CD.Application _ [ob: ob, location: location, orientation: orientation, properties: CDProperties.CopyProps[properties]]]]; }; CDCells.IsCell[ob] => { cellPtr: CD.CellPtr _ NARROW[ob.specificRef]; FOR list: CD.ApplicationList _ cellPtr.contents, list.rest WHILE (list#NIL AND ~quit) DO IF ~stopEnumerateDeepPins OR CDProperties.GetPropFromApplication[list.first, $StopEnumerateDeepPins]=NIL THEN quit _ EnumerateDeepPinsInContext[ list.first.ob, CDBasics.BaseOfRect[ CDOrient.MapRect[ itemInCell: CDOrient.RectAt[list.first.location, list.first.ob.size, list.first.orientation], cellSize: ob.size, cellInstOrient: orientation, cellInstPos: location]], CDOrient.ComposeOrient[list.first.orientation, orientation], list.first.properties, eachPin, stopEnumerateDeepPins, filter]; IF quit THEN EXIT; ENDLOOP; }; CDImports.IsImport[ob] => { <> ip: CDImports.ReferencePtr _ NARROW[ob.specificRef]; IF ip.boundApp=NIL THEN RETURN; quit _ EnumerateDeepPinsInContext[ip.boundApp.ob, location, orientation, NIL, eachPin, stopEnumerateDeepPins, filter]; }; ENDCASE => { newOb: CD.ObPtr _ CDDirectory.Expand[ob, NIL, NIL]; quit _ newOb#NIL AND EnumerateDeepPinsInContext[newOb, location, orientation, NIL, eachPin, stopEnumerateDeepPins, filter]; }; }; EnumerateDeepPins: PUBLIC PROC [ob: CD.ObPtr, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOL _ TRUE] RETURNS [quit: BOOL] = { quit _ EnumerateDeepPinsInContext[ob: ob, eachPin: eachPin, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: DefaultFilter]; }; EnumerateEdgePins: PUBLIC PROC [ob: CD.ObPtr, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOL _ TRUE] RETURNS [quit: BOOL] = { iRectShrank: CD.Rect _ CDBasics.Extend[CD.InterestRect[ob], -1]; EdgeFilter: FilterProc = {isSubInteresting _ ~CDBasics.Inside[subRect, iRectShrank]}; EachPinFilter: AppEnumerator -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE] -- = { IF GetSide[ob, app].isOnBorder THEN quit _ eachPin[app]; }; quit _ EnumerateDeepPinsInContext[ob: ob, eachPin: EachPinFilter, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: EdgeFilter]; }; RenamePins: PUBLIC PROC [design: CD.Design, ob: CD.ObPtr, renameProc: RenameProc _ DefaultRenameProc, stopEnumerateDeepPins: BOOL _ TRUE] RETURNS [cell: CD.ObPtr] = BEGIN cellPtr: CD.CellPtr; KeepPinOnEdge: AppEnumerator -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE] -- = { newApp: CD.ApplicationPtr; newRope: ROPE _ renameProc[CDPinObjects.GetName[app]]; IF Rope.IsEmpty[newRope] THEN RETURN; newApp _ NEW[CD.Application _ [ ob: CDPinObjects.CreatePinOb[app.ob.size], location: app.location, orientation: app.orientation, properties: CDProperties.CopyProps[app.properties]]]; CDPinObjects.SetName[newApp, newRope]; cellPtr.contents _ CONS[newApp, cellPtr.contents]; }; app: CD.ApplicationPtr _ NEW[CD.Application _ [ob: ob]]; IF stopEnumerateDeepPins THEN CDProperties.PutPropOnApplication[app, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; cell _ CDCells.CreateEmptyCell[]; cellPtr _ NARROW[cell.specificRef]; [] _ EnumerateEdgePins[ob, KeepPinOnEdge]; cellPtr.contents _ CONS[app, cellPtr.contents]; CDCells.SetInterestRect[cell, CD.InterestRect[ob]]; [] _ CDCells.RepositionCell[cell, NIL]; [] _ CDDirectory.Include[design, cell, "RenamedPins"]; END; DefaultRenameProc: PUBLIC RenameProc = {newRope _ oldRope}; <> Index: PUBLIC PROC [rope: ROPE, index: INT] RETURNS [indexedRope: ROPE] = { indexedRope _ Rope.Cat[rope, "[", Convert.RopeFromInt[index], "]"]; }; [] _ CDProperties.RegisterProperty[$StopEnumerateDeepPins, $CDPinExtras]; CDProperties.FetchProcs[$StopEnumerateDeepPins].makeCopy _ CDProperties.CopyVal; END.