PWPinsImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOrient, CDProperties, CDSymbolicObjects, Convert, Rope
EXPORTS PWPins
SHARES CDCells, CDSymbolicObjects =
BEGIN
OPEN PWPins;
GetSide:
PUBLIC
PROC [ob:
CD.Object, pin:
CD.Instance]
RETURNS [side: Side] = {
LargerSide:
PROC [hSide, vSide: Side]
RETURNS [side: Side] = {
delta: INT ← pinRect.x2-pinRect.x1- (pinRect.y2-pinRect.y1);
side ← IF delta=0 THEN ERROR ELSE IF delta>0 THEN hSide ELSE vSide;
};
rect: CD.Rect ← CD.InterestRect[ob]; -- the border
pinRect: CD.Rect ← CDSymbolicObjects.Denotes[pin]; -- bbox of the pin (CDInstances.InstRectO)
side ←
SELECT
TRUE
FROM
pinRect.x1 = pinRect.x2 AND pinRect.y1 = pinRect.y2 => none,
pinRect.x1 = pinRect.x2
AND pinRect.y1 = pinRect.y2 =>
SELECT pinRect.x1
FROM
rect.x1 => left,
rect.y1 => bottom,
rect.x2 => right,
rect.y2 => top,
ENDCASE => none,
pinRect.x1 = pinRect.x2 =>
SELECT pinRect.x1
FROM
rect.x1 => left,
rect.x2 => right,
ENDCASE => none,
pinRect.y1 = pinRect.y2 =>
SELECT pinRect.y1
FROM
rect.y1 => bottom,
rect.y2 => top,
ENDCASE => none,
rect.y1 = pinRect.y1 AND rect.y2 = pinRect.y2 => ERROR, -- pin on 2 opposite sides
rect.x1 = pinRect.x1 AND rect.x2 = pinRect.x2 => ERROR, -- pin on 2 opposite sides
rect.y2 = pinRect.y2 AND rect.x1 = pinRect.x1 => LargerSide[top, left],
rect.y2 = pinRect.y2 AND rect.x2 = pinRect.x2 => LargerSide[top, right],
rect.y1 = pinRect.y1 AND rect.x1 = pinRect.x1 => LargerSide[bottom, left],
rect.y1 = pinRect.y1 AND rect.x2 = pinRect.x2 => LargerSide[bottom, right],
rect.y2 = pinRect.y2 => top,
rect.y1 = pinRect.y1 => bottom,
rect.x1 = pinRect.x1 => left,
rect.x2 = pinRect.x2 => right,
ENDCASE => none;
};
CopyInstance:
PUBLIC
PROC [oldInst:
CD.Instance]
RETURNS [newInst:
CD.Instance] = {
newInst ← NEW [CD.InstanceRep ← [ob: oldInst.ob, location: oldInst.location, orientation: oldInst.orientation, properties: CDProperties.DCopyProps[oldInst.properties]]];
};
NewInstance:
PUBLIC
PROC [ob:
CD.Object, location:
CD.Position ← [0,0], orientation:
CD.Orientation𡤀, properties:
CD.PropList←
NIL]
RETURNS [
CD.Instance] = {
RETURN [NEW [CD.InstanceRep ← [ob: ob, location: location, orientation: orientation, properties: properties]]];
};
TransformInstance:
PUBLIC
PROC [instInCell:
CD.Instance, cellSize:
CD.Position, locationOfCellInWorld:
CD.Position, orientationOfCellInWorld:
CD.Orientation]
RETURNS [instInWorld:
CD.Instance] = {
instInWorld ←
NEW [
CD.InstanceRep ← [
ob: instInCell.ob,
location: CDBasics.BaseOfRect[
CDOrient.MapRect[
itemInCell: CDInstances.InstRectO[instInCell],
cellSize: cellSize,
cellInstOrient: orientationOfCellInWorld,
cellInstPos: locationOfCellInWorld]],
orientation: CDOrient.ComposeOrient[instInCell.orientation, orientationOfCellInWorld],
properties: CDProperties.DCopyProps[instInCell.properties]]];
};
Because we must finally get instances, this one has in its parameters all necessary information for reconstructing the application.
EnumerateDeepPinsInContext:
PUBLIC EnumerationProc = {
value: REF;
IF ~filter[CDOrient.MapRect[
itemInCell: CD.InterestRect[ob],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: location]] THEN RETURN;
value ← CDProperties.GetObjectProp[ob, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, location, orientation, properties, eachPin, stopEnumerateDeepPins, filter]];
value ← CDProperties.GetProp[ob.class, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, location, orientation, properties, eachPin, stopEnumerateDeepPins, filter]];
ob ← CDDirectory.Expand[ob, NIL, NIL].new;
quit ← ob#NIL AND EnumerateDeepPinsInContext[ob, location, orientation, NIL, eachPin, stopEnumerateDeepPins, filter];
};
PinEnumerateDeepPinsInContext: EnumerationProc = {
quit ← eachPin[NEW [CD.InstanceRep ← [ob: ob, location: location, orientation: orientation, properties: CDProperties.DCopyProps[properties]]]];
};
CellEnumerateDeepPinsInContext: EnumerationProc = {
cellPtr: CD.CellPtr ← NARROW [ob.specificRef];
FOR list:
CD.InstanceList ← cellPtr.contents, list.rest
WHILE (list#
NIL
AND ~quit)
DO
IF ~stopEnumerateDeepPins
OR CDProperties.GetInstanceProp[list.first, $StopEnumerateDeepPins]=
NIL
THEN
quit ← EnumerateDeepPinsInContext[
list.first.ob,
CDBasics.BaseOfRect[
CDOrient.MapRect[
itemInCell: CDInstances.InstRectO[list.first],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: location]],
CDOrient.ComposeOrient[list.first.orientation, orientation],
list.first.properties,
eachPin, stopEnumerateDeepPins, filter];
ENDLOOP;
};
EnumerateDeepPins:
PUBLIC
PROC [ob:
CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [quit:
BOOL] = {
DefaultFilter: FilterProc = {};
quit ← EnumerateDeepPinsInContext[ob: ob, eachPin: eachPin, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: DefaultFilter];
};
EnumerateEdgePins:
PUBLIC
PROC [ob:
CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [quit:
BOOL] = {
iRectShrank: CD.Rect ← CDBasics.Extend[CD.InterestRect[ob], -1];
EdgeFilter: FilterProc = {isSubInteresting ← ~CDBasics.Inside[subRect, iRectShrank]};
EachPinFilter: InstanceEnumerator
-- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
IF GetSide[ob, inst]#none THEN quit ← eachPin[inst];
};
quit ← EnumerateDeepPinsInContext[ob: ob, eachPin: EachPinFilter, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: EdgeFilter];
};
ChangePins:
PUBLIC
PROC [ob:
CD.Object, changePinProc: ChangePinProc ← DefaultChangePinProc, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [cell:
CD.Object] =
BEGIN
cellPtr: CD.CellPtr;
KeepPinOnEdge: InstanceEnumerator
-- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
newInst: CD.Instance ← changePinProc[inst];
IF newInst#NIL THEN cellPtr.contents ← CONS [newInst, cellPtr.contents];
};
inst: CD.Instance ← NEW [CD.InstanceRep ← [ob: ob]];
IF stopEnumerateDeepPins THEN CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
cell ← CDCells.CreateEmptyCell[]; cellPtr ← NARROW [cell.specificRef];
[] ← EnumerateEdgePins[ob, KeepPinOnEdge];
cellPtr.contents ← CONS[inst, cellPtr.contents];
CDCells.SetInterestRect[cell, CD.InterestRect[ob]];
[] ← CDCells.RepositionCell[cell, NIL];
END;
DefaultChangePinProc: PUBLIC ChangePinProc = {newPin ← oldPin};
RenamePins:
PUBLIC
PROC [ob:
CD.Object, renameProc: RenameProc ← DefaultRenameProc, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [cell:
CD.Object] = {
ChangePin: ChangePinProc = {
newRope: ROPE ← renameProc[CDSymbolicObjects.GetName[oldPin]];
IF Rope.IsEmpty[newRope] THEN RETURN;
newPin ← CopyInstance[oldPin];
CDSymbolicObjects.SetName[newPin, newRope];
};
cell ← ChangePins[ob, ChangePin, stopEnumerateDeepPins];
};
DefaultRenameProc: PUBLIC RenameProc = {newRope ← oldRope};
Useful in many RenameProcs for indexing names. e.g. Index["foo", 4]="foo[4]"
Index:
PUBLIC
PROC [rope:
ROPE, index:
INT]
RETURNS [indexedRope:
ROPE] = {
indexedRope ← Rope.Cat[rope, "[", Convert.RopeFromInt[index], "]"];
};
enumerationProcProp: PUBLIC ATOM ← $EnumerationProcPWPins;
[] ← CDProperties.RegisterAndInstall[enumerationProcProp, [makeCopy: CDProperties.CopyVal], $PWPins];
[] ← CDProperties.RegisterProperty[enumerationProcProp, $PWPins];
CDProperties.InstallProcs[enumerationProcProp, [makeCopy: CDProperties.CopyVal]];
[] ← CDProperties.RegisterAndInstall[$StopEnumerateDeepPins, [makeCopy: CDProperties.CopyVal], $PWPins];
[] ← CDProperties.RegisterProperty[$StopEnumerateDeepPins, $PWPins];
CDProperties.InstallProcs[$StopEnumerateDeepPins, [makeCopy: CDProperties.CopyVal]];
CDProperties.PutProp[CDSymbolicObjects.pinClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.segmentClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.markClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDCells.cellClass, enumerationProcProp, NEW [EnumerationProc ← CellEnumerateDeepPinsInContext]];
END.