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
Last edited by: Christian Jacobi, November 4, 1986 6:01:44 pm PST
Frank Bowers January 22, 1986 1:53:49 pm PST
Jacobi, March 25, 1986 6:19:37 pm PST
DIRECTORY
CD,
CDBasics,
CStitching,
CDCells,
CDCommandOps,
CDOps,
CDRects,
CDSequencer,
CDInstances,
CDProperties,
CDDirectory,
Recognizer,
TerminalIO,
CleanObjects;
CleanObjectsImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCommandOps, CDOps, CStitching, CDCells, CDInstances, CDProperties, CDDirectory, CDRects, 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,
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;
DoCleanObjects:
PUBLIC
PROC [cellOb:
CD.Object, design:
CD.Design, recognizeObjects:
BOOL ←
TRUE] =
BEGIN
IF CDCells.IsCell[cellOb]
THEN {
IF recognizeObjects THEN Recognizer.RecognizeObjects[design, cellOb];
CleanCell[design, cellOb];
[] ← CDCells.ResizeCell[design, cellOb];
CDDirectory.PropagateChange[cellOb, design];
};
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.PutRope["recognize on all levels\n"];
CleanObjectsAllLevels[design: comm.design, recognizeObjects: TRUE];
TerminalIO.PutRope[" done\n"];
END;
RecognizeTopCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.PutRope["recognize on top level\n"];
DoCleanObjects[comm.design.actual.first.dummyCell.ob, comm.design, TRUE];
TerminalIO.PutRope[" 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]];
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, trans: [], pr: h.pr];
CheckRectsAgainstPlane[h];
CStitching.ResetTesselation[h.actualPlane];
CStitching.ResetTesselation[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, trans, 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
mustRemove: CD.InstanceList ← NIL;
EachInst: CDCells.InstEnumerator = {
IF inst.ob.class.wireTyped
AND inst.ob.layer=h.abstract
THEN {
IF WireNeededCleaning[inst, h] THEN mustRemove ← CONS[inst, mustRemove]
ELSE inst.ob.class.drawMe[inst, inst.trans, h.pr]
}
};
[] ← CDCells.EnumerateInstances[h.cellOb, EachInst];
FOR il:
CD.InstanceList ← mustRemove, il.rest
WHILE il#
NIL
DO
[] ← CDCells.RemoveInstance[design: h.design, cell: h.cellOb, inst: il.first, mode: dontResize]
ENDLOOP;
END;
WireNeededCleaning:
PROC [instance:
CD.Instance, h: Handle]
RETURNS [removeInst:
BOOL ←
FALSE] =
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[CDBasics.OrientedSize[CDBasics.SizeOfRect[keepList.first.rect], instance.trans.orient], h.abstract];
newInst: CD.Instance ← CDInstances.NewInst[object, CDOps.FitObjectI[object, location, instance.trans.orient]];
[] ← CDCells.IncludeInstance[
design: h.design,
cell: h.cellOb,
inst: newInst,
mode: dontResize
];
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 ← CStitching.NewTesselation[];
WHILE keepList#
NIL
DO
CStitching.ChangeRect[plane: wirePlane, rect: keepList.first.rect, new: $cover];
keepList ← keepList.rest;
ENDLOOP;
IF CDBasics.IncludesOddRot90[instance.trans.orient]
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];
CStitching.ResetTesselation[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 [
BOOL ←
TRUE] =
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;
CDCommandOps.RegisterWithMenu[menu: $ProgramMenu, entry: "Recognize All", key: $RecognizeAll, proc: RecognizeAllCommand];
CDCommandOps.RegisterWithMenu[menu: $ProgramMenu, entry: "Recognize Top", key: $RecognizeTop, proc: RecognizeTopCommand];
CDSequencer.ImplementCommand[key: $RecognizeAll, proc: RecognizeAllCommand];
CDSequencer.ImplementCommand[key: $RecognizeTop, proc: RecognizeTopCommand];
END.