CleanObjectsImpl.mesa
Last Edited by: Gbier, July 11, 1985 12:181:45 pm PDT
Last Edited by: Gbier, July 26, 1985 10:56:06 am PDT
DIRECTORY
CD,
CDBasics,
CornerStitching,
CDOrient,
CDCells,
CDRects,
CDMenus,
CDSequencer,
CDInstances,
CDProperties,
CDDirectory,
Recognizer,
TerminalIO,
CleanObjects;
CleanObjectsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CornerStitching, CDOrient, CDCells, CDInstances, CDProperties, CDDirectory, CDRects, CDMenus, CDSequencer, Recognizer, TerminalIO
EXPORTS CleanObjects =
BEGIN
LayerAndTessPtr: TYPE = REF LayerAndTessRec;
LayerAndTessRec: TYPE = RECORD [
design: CD.Design,
cellOb: CD.Object,
cellPtr: CD.CellPtr,
abstract: CD.Layer ← CD.combined,
actual: CD.Layer ← CD.combined,
surround: CD.Layer ← CD.combined,
surroundExt: CD.Number ← 0,
actualPlane: REF CornerStitching.Tesselation ← NIL,
surroundPlane: REF CornerStitching.Tesselation ← NIL,
instance: CD.Instance ← NIL
];
AbstractLayerRec: TYPE = RECORD [
technology: CD.Technology,
abstract: CD.Layer,
actual: CD.Layer,
surround: CD.Layer, --The surrounding layer of an abstract layer
surroundExt: CD.Number --The extension of the surrounding layer
];
abstractLayerList: LIST OF REF AbstractLayerRec ← NIL; --contains registered abstract Layers
RegionList: TYPE = LIST OF REF CornerStitching.Region;
CleanObjects: PUBLIC PROC [cellOb: CD.Object, design: CD.Design, recognizeObjects: BOOLTRUE] =
BEGIN
WITH cellOb.specificRef SELECT FROM
cp: CD.CellPtr => {
IF recognizeObjects THEN Recognizer.RecognizeObjects[design, cellOb];
CleanCell[design, cellOb];
[] ← CDCells.RepositionCell[cellOb, design];
CDDirectory.PropagateChange[cellOb, design];
};
ENDCASE => NULL;
END;
CleanObjectsAllLevels: PROC [design: CD.Design, recognizeObjects: BOOL] =
BEGIN
DoIt: CDDirectory.EachEntryAction = {
CleanObjects[cellOb: ob, design: design, recognizeObjects: recognizeObjects]
};
[] ← CDDirectory.Enumerate[design, DoIt];
CleanObjects[design.actual.first.dummyCell.ob, design, recognizeObjects];
END;
RecognizeAllCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Recognize on all levels\n"];
CleanObjectsAllLevels[design: comm.design, recognizeObjects: TRUE];
TerminalIO.WriteRope["Recognizer and Cleaning Done\n"];
END;
RecognizeTopCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Recognize on top level\n"];
CleanObjects[comm.design.actual.first.dummyCell.ob, comm.design, TRUE];
TerminalIO.WriteRope["Recognizer and Cleaning Done\n"];
END;
CleanCell: PROC [design: CD.Design, cellOb: CD.Object] =
BEGIN
passTessInfo: LayerAndTessPtr ← NEW[LayerAndTessRec ← [design, cellOb, NARROW[cellOb.specificRef]]];
FOR layerList: LIST OF CD.Layer ← design.technology.usedLayers, layerList.rest WHILE layerList #NIL DO
passTessInfo.abstract ← layerList.first;
passTessInfo.actual ← layerList.first;
passTessInfo.surround ← CD.combined;
FOR abstractList: LIST OF REF AbstractLayerRec ← abstractLayerList, abstractList.rest WHILE abstractList #NIL DO
IF abstractList.first.technology = design.technology AND abstractList.first.abstract = passTessInfo.abstract THEN {
passTessInfo.actual ← abstractList.first.actual;
passTessInfo.surround ← abstractList.first.surround;
passTessInfo.surroundExt ← abstractList.first.surroundExt;
EXIT;
}
ENDLOOP;
passTessInfo.actualPlane ← CornerStitching.NewTesselation[];
passTessInfo.surroundPlane ← CornerStitching.NewTesselation[];
FillPlanesByDrawingObjects[passTessInfo];
CheckRectsAgainstPlane[passTessInfo];
ENDLOOP;
END;
FillPlanesByDrawingObjects: PROC [passTessInfo: LayerAndTessPtr] =
BEGIN
pr: CD.DrawRef ← CD.CreateDrawRef[passTessInfo.design];
pr.devicePrivate ← passTessInfo;
pr.drawRect ← DrawObjectsIntoPlanes;
FOR instanceList: CD.InstanceList ← passTessInfo.cellPtr.contents, instanceList.rest WHILE instanceList #NIL DO
IF ~instanceList.first.ob.class.wireTyped AND FlattenObject[instance: instanceList.first] THEN
instanceList.first.ob.class.drawMe[inst: instanceList.first, pos: instanceList.first.location, orient: instanceList.first.orientation, pr: pr];
ENDLOOP;
END;
FlattenObject: PROC [instance: CD.Instance] RETURNS [BOOLTRUE] =
BEGIN
IF instance.ob.class.inDirectory THEN RETURN[FALSE];
END;
DrawObjectsIntoPlanes: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] =
BEGIN
passTessInfo: LayerAndTessPtr ← NARROW[pr.devicePrivate];
IF passTessInfo.actual = l THEN
CornerStitching.ChangeRect [plane: passTessInfo.actualPlane, rect: r, newValue: $cover]
ELSE
IF passTessInfo.surround = l THEN
CornerStitching.ChangeRect[plane: passTessInfo.surroundPlane, rect: r, newValue: $cover];
END;
CheckRectsAgainstPlane: PROC [passTessInfo: LayerAndTessPtr] =
BEGIN
FOR instanceList: CD.InstanceList ← passTessInfo.cellPtr.contents, instanceList.rest WHILE instanceList#NIL DO
IF instanceList.first.ob.class.wireTyped AND instanceList.first.ob.layer = passTessInfo.abstract AND WireNeededCleaning [instanceList.first, passTessInfo] THEN
[] ← CDCells.RemoveInstance[design: passTessInfo.design, cell: passTessInfo.cellOb, inst: instanceList.first];
ENDLOOP;
END;
WireNeededCleaning: PROC [instance: CD.Instance, passTessInfo: LayerAndTessPtr] RETURNS [addedWire: BOOLFALSE] =
BEGIN
rect: CD.Rect ← CDInstances.InstRectI[instance];
keepList: RegionList ← NARROW[CornerStitching.EnumerateArea [plane: passTessInfo.actualPlane, rect: rect, backgroundValue: $cover]];
throwAwayList: RegionList ← NARROW[CornerStitching.EnumerateArea [plane: passTessInfo.actualPlane, rect: rect]];
IF passTessInfo.surround #CD.combined THEN --current Layer is an abstract Layer
keepList ← UncoveredSurroundPieces[keepList, throwAwayList, passTessInfo.surroundPlane, passTessInfo.surroundExt];
keepList ← BuildKeepList[keepList, instance, rect];
IF keepList = NIL THEN RETURN[TRUE];
IF (keepList.first.value = NIL) AND (keepList.first.rect = rect) AND (keepList.rest = NIL) THEN RETURN; --keep whole wire
WHILE keepList #NIL DO {
location: CD.Position ← CDBasics.BaseOfRect [keepList.first.rect];
object: CD.Object ← CDRects.CreateRect[CDOrient.OrientedSize[CDBasics.SizeOfRect[keepList.first.rect], instance.orientation], passTessInfo.abstract];
newInst: CD.Instance ← CDCells.IncludeOb[
design: passTessInfo.design,
cell: passTessInfo.cellOb,
ob: object,
position: location,
orientation: instance.orientation,
cellCSystem: cdCoords,
obCSystem: interrestCoords,
mode: dontPropagate
].newInst;
newInst.properties ← CDProperties.CopyProps[instance.properties];
addedWire ← TRUE;
};
keepList ← keepList.rest;
ENDLOOP;
END;
BuildKeepList: PROC [keepList: RegionList, instance: CD.Instance, rect: CD.Rect] RETURNS [newKeepList: RegionList] =
--If a piece on the keeplist is actually a cut along the width then the piece is grown to the full width of the original wire.
BEGIN
xWidth: BOOL;
width: CD.Number;
length: CD.Number;
changed: BOOLTRUE;
wirePlane: REF CornerStitching.Tesselation ← CornerStitching.NewTesselation[];
WHILE keepList #NIL DO
CornerStitching.ChangeRect[plane: wirePlane, rect: keepList.first.rect, newValue: $cover];
keepList ← keepList.rest;
ENDLOOP;
IF CDOrient.IncludesOddRot90[instance.orientation] THEN {
xWidth ← FALSE;
width ← rect.y2-rect.y1;
length ← rect.x2-rect.x1;
}
ELSE {
xWidth ← TRUE;
width ← rect.x2-rect.x1;
length ← rect.y2-rect.y1;
};
IF length > width THEN -- normal shaped object
WHILE changed DO
changed ← FALSE;
newKeepList ← NARROW[CornerStitching.EnumerateArea[plane: wirePlane, rect: rect]];
WHILE newKeepList #NIL DO
IF xWidth AND (newKeepList.first.rect.x2-newKeepList.first.rect.x1) #width THEN {
changed ← TRUE;
CornerStitching.ChangeRect[plane: wirePlane, rect: [rect.x1, newKeepList.first.rect.y1, rect.x2, newKeepList.first.rect.y2], newValue: $cover];
};
IF ~xWidth AND (newKeepList.first.rect.y2-newKeepList.first.rect.y1) #width THEN {
changed ← TRUE;
CornerStitching.ChangeRect[plane: wirePlane, rect: [newKeepList.first.rect.x1, rect.y1, newKeepList.first.rect.x2, rect.y2], newValue: $cover];
};
newKeepList ← newKeepList.rest;
ENDLOOP;
ENDLOOP;
RETURN[newKeepList ← NARROW[CornerStitching.EnumerateArea[plane: wirePlane, rect: rect]]];
END;
UncoveredSurroundPieces: PROC [keepList, throwAwayList: RegionList, surroundPlane: REF CornerStitching.Tesselation, surroundExt: CD.Number] RETURNS [newKeepList: RegionList] =
--Used for verifying abstract layers. All pieces on throwAwayList must be surrounded, otherwise the piece is moved onto the keepList
BEGIN
newKeepList ← keepList;
WHILE keepList #NIL DO
CornerStitching.ChangeRect[plane: surroundPlane, rect: CDBasics.Extend[keepList.first.rect, surroundExt], newValue: $cover];
keepList ← keepList.rest;
ENDLOOP;
WHILE throwAwayList #NIL DO
IF ~RectCoveredCompletely[throwAwayList.first.rect, surroundPlane, surroundExt] THEN
newKeepList ← CONS[throwAwayList.first, newKeepList];
throwAwayList ← throwAwayList.rest;
ENDLOOP;
END;
RectCoveredCompletely: PROC [rect: CD.Rect, plane: REF CornerStitching.Tesselation, surroundExt: CD.Number] RETURNS [BOOLTRUE] =
BEGIN
FOR surroundList: RegionList ← NARROW[CornerStitching.EnumerateArea[plane: plane, rect: CDBasics.Extend[rect, surroundExt], backgroundValue: $none]], surroundList.rest WHILE surroundList #NIL DO
IF surroundList.first.value = NIL THEN
RETURN[FALSE];
ENDLOOP;
END;
RegisterAbstractLayer: PUBLIC PROC [technology: CD.Technology, abstract, actual, surround: CD.Layer, surroundExt: CD.Number] =
BEGIN
abstractLayerList ← CONS[NEW[AbstractLayerRec ← [technology, abstract, actual, surround, surroundExt]], abstractLayerList];
END;
CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Recognize All", key: $RecognizeAll];
CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Recognize Top", key: $RecognizeTop];
CDSequencer.ImplementCommand[a: $RecognizeAll, p: RecognizeAllCommand, queue: doQueue];
CDSequencer.ImplementCommand[a: $RecognizeTop, p: RecognizeTopCommand, queue: doQueue];
END.