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, January 9, 1986 12:39:55 pm PST
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
RegList: TYPE=LIST OF REF CornerStitching.Region;
Plane: TYPE=REF CornerStitching.Tesselation;
Handle: TYPE=REF HandleRep;
HandleRep:
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: 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] = {
CornerStitching.FreeTesselation[p, FALSE];
};
DoCleanObjects:
PUBLIC
PROC [cellOb:
CD.Object, design:
CD.Design, recognizeObjects:
BOOL ←
TRUE] =
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.combined;
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[design];
h.pr.drawRect ← DrawRectOfSimpleObject;
h.pr.drawChild ← DrawChildOfSimpleObject;
h.pr.devicePrivate ← NEW[DevicePrivateRec ← [h, NIL]];
FOR layerList:
LIST
OF
CD.Layer ← actualCleanList, layerList.rest
WHILE layerList#
NIL
DO
SetUpLayer[h, layerList.first];
h.actualPlane ← CornerStitching.NewTesselation[];
h.surroundPlane ← CornerStitching.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
CornerStitching.ChangeRect[plane: handle.actualPlane, rect: r, newValue: $cover]
ELSE
IF handle.surround = l
THEN
CornerStitching.ChangeRect[plane: handle.surroundPlane, rect: r, newValue: $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:
BOOL ←
FALSE] =
BEGIN
rect: CD.Rect ← CDInstances.InstRectI[instance];
keepList: RegList ← CornerStitching.ListArea[h.actualPlane, rect, $cover];
IF h.surround#
CD.combined
THEN {
--current Layer is an abstract Layer
throwAwayList: RegList ← CornerStitching.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: BOOL ← TRUE;
wirePlane: Plane ← 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 ← CornerStitching.ListArea[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;
newKeepList ← CornerStitching.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
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: Plane, surroundExt:
CD.Number]
RETURNS [
BOOL ←
TRUE] =
BEGIN
FOR surList: RegList ← CornerStitching.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: REF 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[a: $RecognizeAll, p: RecognizeAllCommand];
CDSequencer.ImplementCommand[a: $RecognizeTop, p: RecognizeTopCommand];
END.