PWSqueezeImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, February 3, 1985 12:49:51 pm PST
Last edited by Bertrand Serlet, March 15, 1987 6:30:27 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts,
CMosB,
CStitching,
GList, HashTable, IO, PW, PWObjects, Rope, TerminalIO;
PWSqueezeImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CStitching, GList, HashTable, IO, PW, PWObjects, TerminalIO
SHARES CDCells, CDRects =
BEGIN
ROPE: TYPE = Rope.ROPE;
Count Transistors
CountTransistors: PROC [obj: CD.Object] RETURNS [count: INT ← 0] = {
value: REF INTNARROW [CDProperties.GetObjectProp[obj, $TransistorCount]];
IF value#NIL THEN RETURN [value^];
SELECT obj.class FROM
CDCells.pCellClass => {
EachSub: CDCells.InstEnumerator = {count ← count + CountTransistors[inst.ob]};
[] ← CDCells.EnumerateInstances[obj, EachSub];
};
CD.FetchObjectClass[$C2Trans, CMosB.cmosB], CD.FetchObjectClass[$C2WellTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LWellTrans, CMosB.cmosB] => RETURN [1];
ENDCASE => RETURN [0];
};
Touching (a la CoreGeometry) and various utilities
FlattenInstance: PUBLIC PROC [instance: CD.Instance, eachInstance: CDCells.InstEnumerator] RETURNS [quit: BOOLFALSE] = {
EachSubInstance: CDCells.InstEnumerator = {
quit ← eachInstance[CDInstances.NewInst[inst.ob, CDBasics.ComposeTransform[itemInCell: inst.trans, cellInWorld: instance.trans]]];
};
SELECT TRUE FROM
instance.ob.class=CDRects.bareRectClass   => ERROR;
instance.ob.class=CDCells.pCellClass    => quit ← CDCells.EnumerateInstances[instance.ob, EachSubInstance];
ENDCASE         => {
flat: CD.Object ← CDDirectory.ExpandByDraw[instance.ob, TRUE, TRUE];
quit ← FlattenInstance[CDInstances.NewInst[CDDirectory.ExpandByDraw[instance.ob, TRUE, TRUE], instance.trans], eachInstance];
};
};
Touch: PROC [instance1, instance2: CD.Instance] RETURNS [BOOLFALSE] = {
IF NOT CDBasics.Intersect[CDInstances.InstRectO[instance1], CDInstances.InstRectO[instance2]] THEN RETURN;
SELECT TRUE FROM
instance1.ob.class=CDRects.bareRectClass    => RETURN [TouchRect[instance2, CDInstances.InstRectO[instance1], instance1.ob.layer]];
CDSymbolicObjects.IsSymbolicOb[instance1.ob]      => RETURN [TouchRect[instance2, CDInstances.InstRectO[instance1], CDSymbolicObjects.GetLayer[instance1]]];
ENDCASE             => {
TouchInstance2: CDCells.InstEnumerator = {quit ← Touch[inst, instance2]};
RETURN [FlattenInstance[instance1, TouchInstance2]];
};
};
TouchRect: PUBLIC PROC [instance: CD.Instance, rect: CD.Rect, layer: CD.Layer] RETURNS [BOOLFALSE] = {
IF ~CDBasics.Intersect[rect, CDInstances.InstRectO[instance]] THEN RETURN;
IF instance.ob.class=CDRects.bareRectClass THEN
RETURN [CDLayers.AbstractToPaint[instance.ob.layer]=CDLayers.AbstractToPaint[layer]];
RETURN [Touch[
instance,
CDInstances.NewInst[ob: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], trans: [CDBasics.BaseOfRect[rect]]]
]];
};
cacheRotate: ARRAY CD.Orientation OF HashTable.Table ← ALL[NIL];
CachedRotate: PROC [obj: CD.Object, orient: CD.Orientation] RETURNS [new: CD.Object] = {
table: HashTable.Table;
IF orient=original THEN RETURN [obj];
table ← cacheRotate[orient];
IF table=NIL THEN {table ← HashTable.Create[]; cacheRotate[orient] ← table};
new ← NARROW [HashTable.Fetch[table, obj].value];
IF new#NIL THEN RETURN;
new ← PW.ChangeOrientation[obj, orient];
[] ← HashTable.Store[table, obj, new];
};
Transform into a RoutingCell
RootInst: PROC [fused: HashTable.Table, inst: CD.Instance] RETURNS [root: CD.Instance] = {
IF inst=NIL THEN ERROR;
root ← NARROW [HashTable.Fetch[fused, inst].value];
IF root=NIL THEN RETURN [inst];
IF root=inst THEN ERROR;
root ← RootInst[fused, root];
[] ← HashTable.Replace[fused, inst, root];
};
ToRoutingCell: PROC [old: CD.Object] RETURNS [new: CD.Object] = {
plane: CStitching.Tesselation ← CStitching.NewTesselation[];
fused: HashTable.Table ← HashTable.Create[]; -- Fisher Galler table pointing instances to their father
rootInsts: HashTable.Table ← HashTable.Create[]; -- Table root instance -> other instances fused to it
nodes: LIST OF PWObjects.Node ← NIL;
nodesNb: INT ← 0;
name: ROPE = CDDirectory.Name[old];
AddInst: CDCells.InstEnumerator = {
Fuse: CStitching.TileProc = {
oldInst: CD.Instance ← NARROW [tile.value];
oldInst ← RootInst[fused, oldInst];
IF oldInst=inst THEN RETURN;
IF NOT Touch[oldInst, inst] THEN RETURN;
[] ← HashTable.Store[fused, oldInst, inst];
tile.value ← inst;
};
IF CDTexts.IsText[inst.ob] THEN {TerminalIO.PutF["Discarded text %g.\n", IO.rope[NARROW [inst.ob.specific, CDTexts.TextSpecific].text]]; RETURN};
CStitching.EnumerateArea[plane, CDInstances.InstRectO[inst], Fuse];
};
AddRootInst: CDCells.InstEnumerator = {
IF CDTexts.IsText[inst.ob] THEN RETURN;
IF RootInst[fused, inst]=inst THEN [] ← HashTable.Store[rootInsts, inst, NIL];
};
AddFusedInst: HashTable.EachPairAction = {
fusedInst: CD.Instance ← NARROW [key];
root: CD.Instance ← RootInst[fused, NARROW [value]];
insts: LIST OF CD.Instance;
IF fusedInst=root THEN ERROR;
insts ← NARROW [HashTable.Fetch[rootInsts, root].value];
IF NOT GList.Member[fusedInst, insts] THEN insts ← CONS [fusedInst, insts];
[] ← HashTable.Store[rootInsts, root, insts];
};
MakeNode: HashTable.EachPairAction = {
root: CD.Instance ← NARROW [key];
insts: LIST OF CD.Instance ← NARROW [value];
geometry: LIST OF PWObjects.PlacedObject ← NIL;
FOR list: LIST OF CD.Instance ← CONS [root, insts], list.rest WHILE list#NIL DO
instance: CD.Instance ← list.first;
object: CD.Object = CachedRotate[instance.ob, instance.trans.orient];
geometry ← CONS [
[object: object, position: CDBasics.BaseOfRect[CDInstances.InstRectO[instance]]],
geometry
];
ENDLOOP;
nodes ← CONS [PWObjects.CreateNode[geometry], nodes];
nodesNb ← nodesNb + 1;
};
We flatten!
old ← PW.Flatten[old];
We create the corner stitch
[] ← CDCells.EnumerateInstances[old, AddInst];
Let's release some space!
CStitching.ResetTesselation[plane];
We compute rootInsts by first putting all roots in the table
[] ← CDCells.EnumerateInstances[old, AddRootInst];
We add in rootInsts all the fused ones
[] ← HashTable.Pairs[fused, AddFusedInst];
We make node, now
[] ← HashTable.Pairs[rootInsts, MakeNode];
The final cell
new ← PWObjects.CreateRouting[CD.InterestRect[old], nodes];
TerminalIO.PutF["Object %g translated to routing: %g nodes.\n", IO.rope[name], IO.int[nodesNb]];
};
END.