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
Frank Bowers January 22, 1986 1:53:49 pm PST
Jacobi, March 25, 1986 6:19:37 pm PST
DIRECTORY
CD,
CDBasics,
CStitching,
CDOrient,
CDCells,
CDRects,
CDMenus,
CDSequencer,
CDInstances,
CDProperties,
CDDirectory,
Recognizer,
TerminalIO,
CleanObjects;
CleanObjectsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CStitching, CDOrient, CDCells, CDInstances, CDProperties, CDDirectory, CDRects, CDMenus, CDSequencer, Recognizer, TerminalIO
EXPORTS CleanObjects=
BEGIN
RegList: TYPE=LIST OF REF CStitching.Region;
Plane: TYPE=CStitching.Tesselation;
Handle: TYPE=REF HandleRep;
HandleRep: TYPE=RECORD [
design: CD.Design,
cellOb: CD.Object,
cellPtr: CD.CellPtr,
abstract: CD.Layer ← CD.undefLayer,
actual: CD.Layer ← CD.undefLayer,
surround: CD.Layer ← CD.undefLayer,
surroundExt: CD.Number ← 0,
actualPlane: Plane ← NIL,
surroundPlane: Plane ← NIL,
instance: CD.Instance ← NIL,
pr: CD.DrawRef ← NIL --used to fill stuff into planes...
];
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
];
CleanListRec: TYPE = RECORD [
technology: CD.Technology,
clean: LIST OF CD.Layer
];
DevicePrivateRec: TYPE = RECORD [
handle: Handle,
object: CD.Object
];
abstractLayerList: LIST OF REF AbstractLayerRec ← NIL; --contains registered abstract Layers
cleanList: LIST OF REF CleanListRec ← NIL;
Free: PROC [p: Plane] = {
CStitching.ResetTesselation[p];
};
DoCleanObjects: 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={
DoCleanObjects[cellOb: ob, design: design, recognizeObjects: recognizeObjects]
};
[] ← CDDirectory.Enumerate[design, DoIt];
DoCleanObjects[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[" done\n"];
END;
RecognizeTopCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["recognize on top level\n"];
DoCleanObjects[comm.design.actual.first.dummyCell.ob, comm.design, TRUE];
TerminalIO.WriteRope[" done\n"];
END;
CleanCell: PROC [design: CD.Design, cellOb: CD.Object] =
BEGIN
SetUpLayer: PROC [h: Handle, lay: CD.Layer] =
BEGIN
h.abstract ← lay;
h.actual ← lay;
h.surround ← CD.undefLayer;
FOR abstractList: LIST OF REF AbstractLayerRec ← abstractLayerList, abstractList.rest WHILE abstractList#NIL DO
IF abstractList.first.abstract=lay AND abstractList.first.technology=h.design.technology THEN {
h.actual ← abstractList.first.actual;
h.surround ← abstractList.first.surround;
h.surroundExt ← abstractList.first.surroundExt;
EXIT;
}
ENDLOOP;
END;
dummyInst: CD.Instance ~ NEW[CD.InstanceRep ← [ob: cellOb]];
h: Handle ← NEW[HandleRep ← [design, cellOb, NARROW[cellOb.specificRef]]];
actualCleanList: LIST OF CD.Layer ← NIL;
FOR cl: LIST OF REF CleanListRec ← cleanList, cl.rest WHILE cl # NIL DO
IF cl.first.technology = design.technology THEN {actualCleanList ← cl.first.clean; EXIT};
REPEAT FINISHED => actualCleanList ← design.technology.usedLayers;
ENDLOOP;
h.pr ← CD.CreateDrawRef[[
drawRect: DrawRectOfSimpleObject,
drawChild: DrawChildOfSimpleObject,
devicePrivate: NEW[DevicePrivateRec ← [h, NIL]],
design: design
]];
FOR layerList: LIST OF CD.Layer ← actualCleanList, layerList.rest WHILE layerList#NIL DO
SetUpLayer[h, layerList.first];
h.actualPlane ← CStitching.NewTesselation[];
h.surroundPlane ← CStitching.NewTesselation[];
--fill in the simple objects
cellOb.class.drawMe[inst: dummyInst, pos: [0, 0], orient: CD.original, pr: h.pr];
CheckRectsAgainstPlane[h];
Free[h.actualPlane];
Free[h.surroundPlane];
ENDLOOP;
--break circularity
h.pr.devicePrivate ← NIL;
h.pr ← NIL;
END;
DrawChildOfSimpleObject: CD.DrawProc =
BEGIN
IF ~inst.ob.class.wireTyped AND ~inst.ob.class.inDirectory THEN {
private: REF DevicePrivateRec ← NARROW[pr.devicePrivate];
remember: CD.Object ← private.object;
private.object ← inst.ob;
inst.ob.class.drawMe[inst, pos, orient, pr];
private.object ← remember;
}
END;
DrawRectOfSimpleObject: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] =
BEGIN
IF CDBasics.NonEmpty[r] THEN {
private: REF DevicePrivateRec ← NARROW[pr.devicePrivate];
handle: Handle ← private.handle;
cont: CD.Object ← private.object;
filter: REF CleanObjects.Filter ← IF cont # NIL THEN NARROW[CDProperties.GetProp[cont.class, $cleanSpecial]] ELSE NIL;
IF filter#NIL AND filter[l] THEN RETURN;
IF handle.actual = l THEN
CStitching.ChangeRect[plane: handle.actualPlane, rect: r, new: $cover]
ELSE IF handle.surround = l THEN
CStitching.ChangeRect[plane: handle.surroundPlane, rect: r, new: $cover];
}
END;
CheckRectsAgainstPlane: PROC [h: Handle] =
BEGIN
FOR il: CD.InstanceList ← h.cellPtr.contents, il.rest WHILE il#NIL DO
IF il.first.ob.class.wireTyped AND il.first.ob.layer=h.abstract THEN {
IF WireNeededCleaning[il.first, h] THEN
[] ← CDCells.RemoveInstance[design: h.design, cell: h.cellOb, inst: il.first, mode: dontPropagate]
ELSE il.first.ob.class.drawMe[il.first, il.first.location, il.first.orientation, h.pr]
}
ENDLOOP;
END;
WireNeededCleaning: PROC [instance: CD.Instance, h: Handle] RETURNS [removeInst: BOOLFALSE] =
BEGIN
rect: CD.Rect ← CDInstances.InstRectI[instance];
keepList: RegList ← CStitching.ListArea[h.actualPlane, rect, $cover];
IF h.surround#CD.undefLayer THEN { --current Layer is an abstract Layer
throwAwayList: RegList ← CStitching.ListArea[h.actualPlane, rect];
keepList ← AddUncoveredSurround[keepList, throwAwayList, h.surroundPlane, h.surroundExt];
};
keepList ← UpdateKeepList[keepList, instance, rect]; Bowers January 21, 1986 4:47:36 pm PST
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], h.abstract];
newInst: CD.Instance ← CDCells.IncludeOb[
design: h.design,
cell: h.cellOb,
ob: object,
position: location,
orientation: instance.orientation,
cellCSystem: cdCoords,
obCSystem: interrestCoords,
mode: dontPropagate
].newInst;
CDProperties.CopyProps[instance.properties, newInst];
removeInst ← TRUE;
keepList ← keepList.rest;
ENDLOOP;
END;
UpdateKeepList: PROC [keepList: RegList, instance: CD.Instance, rect: CD.Rect] RETURNS [newKeepList: RegList] =
--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: Plane ← CStitching.NewTesselation[];
WHILE keepList#NIL DO
CStitching.ChangeRect[plane: wirePlane, rect: keepList.first.rect, new: $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 ← CStitching.ListArea[plane: wirePlane, rect: rect];
WHILE newKeepList#NIL DO
IF xWidth AND (newKeepList.first.rect.x2-newKeepList.first.rect.x1)#width THEN {
changed ← TRUE;
CStitching.ChangeRect[plane: wirePlane, rect: [rect.x1, newKeepList.first.rect.y1, rect.x2, newKeepList.first.rect.y2], new: $cover];
};
IF ~xWidth AND (newKeepList.first.rect.y2-newKeepList.first.rect.y1)#width THEN {
changed ← TRUE;
CStitching.ChangeRect[plane: wirePlane, rect: [newKeepList.first.rect.x1, rect.y1, newKeepList.first.rect.x2, rect.y2], new: $cover];
};
newKeepList ← newKeepList.rest;
ENDLOOP;
ENDLOOP;
newKeepList ← CStitching.ListArea[plane: wirePlane, rect: rect];
Free[wirePlane];
END;
AddUncoveredSurround: PROC [keepList, throwAwayList: RegList, surroundPlane: Plane, surroundExt: CD.Number] RETURNS [newKeepList: RegList] =
--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
CStitching.ChangeRect[plane: surroundPlane, rect: CDBasics.Extend[keepList.first.rect, surroundExt], new: $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: Plane, surroundExt: CD.Number] RETURNS [BOOLTRUE] =
BEGIN
FOR surList: RegList ← CStitching.ListArea[plane, CDBasics.Extend[rect, surroundExt], $none], surList.rest WHILE surList#NIL DO
IF surList.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;
RegisterCleanList: PUBLIC PROC [technology: CD.Technology, clean: LIST OF CD.Layer] =
BEGIN
cleanList ← CONS[NEW[CleanListRec ← [technology, clean]], cleanList];
END;
RegisterClassLayerFilter: PUBLIC PROC [technology: CD.Technology, classKey: REF, filter: CleanObjects.Filter] =
BEGIN
objectClass: CD.ObjectClass ← CD.FetchObjectClass[classKey, technology];
CDProperties.PutProp[objectClass, $cleanSpecial, NEW[CleanObjects.Filter ← filter]];
END;
CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Recognize All", key: $RecognizeAll];
CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Recognize Top", key: $RecognizeTop];
CDSequencer.ImplementCommand[key: $RecognizeAll, proc: RecognizeAllCommand];
CDSequencer.ImplementCommand[key: $RecognizeTop, proc: RecognizeTopCommand];
END.