<> <> <> <> 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; <> CountTransistors: PROC [obj: CD.Object] RETURNS [count: INT _ 0] = { value: REF INT _ NARROW [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]; }; <> FlattenInstance: PUBLIC PROC [instance: CD.Instance, eachInstance: CDCells.InstEnumerator] RETURNS [quit: BOOL _ FALSE] = { 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 [BOOL _ FALSE] = { 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 [BOOL _ FALSE] = { 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]; }; <> 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; }; <> old _ PW.Flatten[old]; <> [] _ CDCells.EnumerateInstances[old, AddInst]; <> CStitching.ResetTesselation[plane]; <> [] _ CDCells.EnumerateInstances[old, AddRootInst]; <> [] _ HashTable.Pairs[fused, AddFusedInst]; <> [] _ HashTable.Pairs[rootInsts, MakeNode]; <> new _ PWObjects.CreateRouting[CD.InterestRect[old], nodes]; TerminalIO.PutF["Object %g translated to routing: %g nodes.\n", IO.rope[name], IO.int[nodesNb]]; }; END.