DIRECTORY CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDDirectoryOps, CDIO, CDProperties, CDRects, CDRoutingObjects, CMosB, Core, CoreFlat, CoreGeometry, IO, PW, Rope, Sinix, SinixRawCMosB, SymTab, TerminalIO; PWSqueezeImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDDirectoryOps, CDIO, CDProperties, CDRects, CDRoutingObjects, CMosB, CoreFlat, CoreGeometry, IO, PW, Rope, Sinix, SinixRawCMosB, SymTab, 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]; CDProperties.PutObjectProp[obj, $TransistorCount, NEW [INT _ count]]; }; CDRoutingObjects.routingClass => {}; CD.FetchObjectClass[$C2Trans, CMosB.cmosB], CD.FetchObjectClass[$C2WellTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LWellTrans, CMosB.cmosB] => RETURN [1]; ENDCASE => RETURN [IF obj.class.composed THEN CountTransistors[CDDirectory.Expand1[obj].new] ELSE 0]; }; Leaf: CoreGeometry.LeafProc = {RETURN [FALSE]}; PObj: TYPE = CDRoutingObjects.PlacedObject; IntanceToPObj: PROC [instance: CoreGeometry.Instance] RETURNS [po: PObj] = { IF instance.trans.orient=original THEN RETURN [[instance.obj, instance.trans.off]]; po.object _ SELECT TRUE FROM instance.obj.class=CDRects.bareRectClass => CDRects.CreateRect[CDBasics.OrientedSize[CD.InterestSize[instance.obj], instance.trans.orient], instance.obj.layer], instance.obj.class.atomicOb => CDAtomicObjects.CreateAtomicOb[instance.obj.class.objectType, CDBasics.OrientedSize[CD.InterestSize[instance.obj], instance.trans.orient], CMosB.cmosB, instance.obj.layer], ENDCASE => PW.CreateRotation[instance.obj, instance.trans.orient]; po.position _ CDBasics.SubPoints[CDBasics.BaseOfRect[CoreGeometry.BBox[instance]], CDBasics.BaseOfRect[CoreGeometry.BBox[[po.object, []]]]]; }; Translator1: Rope.TranslatorType = { RETURN [SELECT old FROM '*, '[, '], '., '/ => '$, ENDCASE => old]; }; Translator2: Rope.TranslatorType = { RETURN [SELECT old FROM '*, '/ => '$, ENDCASE => old]; }; Area: PROC [rect: CD.Rect] RETURNS [INT] = {RETURN [(rect.y2-rect.y1)*(rect.x2-rect.x1)]}; Fusable: PROC [rect1, rect2: CD.Rect] RETURNS [BOOL] = { RETURN [Area[CDBasics.Surround[rect1, rect2]] + Area[CDBasics.Intersection[rect1, rect2]] = Area[rect1] + Area[rect2]]; }; BBox: PROC [pobj: PObj] RETURNS [rect: CD.Rect] = { RETURN [CDBasics.MapRect[CD.InterestRect[pobj.object], [pobj.position]]]; }; PObjSeq: TYPE = RECORD [c: SEQUENCE size: NAT OF PObj]; SimplifyPObj: PROC [pobjs: LIST OF PObj] RETURNS [news: LIST OF PObj _ NIL]= { changed: BOOL _ TRUE; count: NAT _ 0; seq: REF PObjSeq; FOR list: LIST OF PObj _ pobjs, list.rest WHILE list#NIL DO count _ count + 1 ENDLOOP; seq _ NEW [PObjSeq[count]]; FOR i: NAT IN [0 .. count) DO seq[i] _ pobjs.first; pobjs _ pobjs.rest ENDLOOP; WHILE changed AND count>0 DO changed _ FALSE; FOR i: NAT IN [0 .. count-1) DO IF seq[i].object#NIL THEN FOR j: NAT IN (i .. count) DO IF seq[j].object#NIL AND seq[i].object.class=CDRects.bareRectClass AND seq[j].object.class=CDRects.bareRectClass AND seq[i].object.layer=seq[j].object.layer AND Fusable[BBox[seq[i]], BBox[seq[j]]] THEN { fused: CD.Rect = CDBasics.Surround[BBox[seq[i]], BBox[seq[j]]]; seq[i] _ [ object: CDRects.CreateRect[CDBasics.SizeOfRect[fused], seq[i].object.layer], position: CDBasics.BaseOfRect[fused] ]; seq[j].object _ NIL; changed _ TRUE; } ENDLOOP; ENDLOOP; ENDLOOP; FOR i: NAT IN [0 .. count) DO IF seq[i].object#NIL THEN news _ CONS [seq[i], news]; ENDLOOP; }; ToRoutingCell: PROC [obj: CD.Object] RETURNS [routing: CD.Object] = { FiddleName: SymTab.EachPairAction = { name: ROPE = IF Rope.Find[key, "public."]=0 THEN Rope.Substr[key, 7] ELSE key; pobjs: REF LIST OF PObj = NARROW [val]; new: ROPE = SELECT TRUE FROM Rope.Fetch[name]='[ => Rope.Translate[base: name, translator: Translator1], Rope.Find[name, "*"]<0 AND Rope.Find[name, "/"]<0 => name, ENDCASE => Rope.Translate[base: name, translator: Translator2]; IF pobjs^=NIL THEN ERROR; -- there should be at least one piece of geometry per wire. IF NOT Rope.Equal[new, name] THEN TerminalIO.PutF["** Flat wire %g replaced by %g.\n", IO.rope[key], IO.rope[new]]; [] _ SymTab.Store[nodes, new, val]; }; EachFlatWire: CoreGeometry.EachFlatWireProc = { EachInstance: CoreGeometry.EachInstanceProc = { geometry^ _ CONS [IntanceToPObj[CoreGeometry.Transform[trans, instance]], geometry^]; }; name: ROPE _ CoreFlat.WirePathRope[ct, flatWire]; geometry: REF LIST OF PObj _ NARROW [SymTab.Fetch[table, name].val]; IF geometry=NIL THEN {geometry _ NEW [LIST OF PObj _ NIL]; [] _ SymTab.Store[table, name, geometry]}; [] _ CoreGeometry.EnumerateGeometry[SinixRawCMosB.mode.decoration, wire, EachInstance]; }; table: SymTab.Ref _ SymTab.Create[]; -- Table FlatWireRope -> REF LIST OF PObj nodes: SymTab.Ref _ SymTab.Create[]; -- Table Real names -> REF LIST OF PObj result: REF = Sinix.Extract[obj, SinixRawCMosB.mode, NIL, NEW [INT _ 40]].result; ct: Core.CellType; IF result=NIL OR NOT ISTYPE[result, Core.CellType] THEN ERROR; ct _ NARROW [result]; [] _ CoreGeometry.EnumerateFlatGeometry[decoration: SinixRawCMosB.mode.decoration, root: ct, leafProc: Leaf, eachFlatWire: EachFlatWire]; [] _ SymTab.Pairs[table, FiddleName]; routing _ CDRoutingObjects.CreateRoutingObject[CDRoutingObjects.CreateNodes[nodes], CD.InterestRect[obj]]; TerminalIO.PutF["Object %g translated to routing: %g nodes.\n", IO.rope[PW.Name[obj]], IO.int[SymTab.GetSize[table]]]; }; Prune: PROC [design: CD.Design] = { TerminalIO.PutF["Pruning ... "]; CDDirectoryOps.PruneDirectory[design]; TerminalIO.PutF["done.\n"]; }; PruneAndSave: PROC [design: CD.Design, file: ROPE] = { Prune[design]; [] _ CDIO.WriteDesign[design: design, to: file]; }; ReplaceAllRoutingCells: PROC [design: CD.Design, file: ROPE, saveEach: INT _ 10] RETURNS [replaced: INT _ 0] = { toBeReplaced: CD.Object; firstPass: BOOL _ TRUE; ReplaceRoutingCells: CDDirectory.EachObjectProc = { name: Rope.ROPE _ CDDirectory.Name[me, design]; IF NOT CDCells.IsCell[me] THEN RETURN; IF CountTransistors[me]#0 THEN RETURN; IF CDCells.CountInstances[me]=1 THEN RETURN; -- this is to deal with unnamed cells just containing a pin and other junk IF name=NIL AND firstPass THEN RETURN; IF CDProperties.GetObjectProp[me, $RawCMosBExtractProc]#NIL THEN RETURN; toBeReplaced _ me; TerminalIO.PutF["### Replacing routing cell '%g'...\n", IO.rope[name]]; quit _ TRUE; }; WHILE CDDirectory.EnumerateDesign[design: design, proc: ReplaceRoutingCells, top: FALSE] DO name: Rope.ROPE _ CDDirectory.Name[toBeReplaced, design]; new: CD.Object _ ToRoutingCell[toBeReplaced]; CDDirectory.ReplaceObject[design, toBeReplaced, new]; [] _ CDDirectory.Remove[design, name, toBeReplaced]; IF Rope.Fetch[name]#'- THEN [] _ CDDirectory.Include[design, new, name]; TerminalIO.PutF["Done replacing routing cell '%g'!\n", IO.rope[name]]; replaced _ replaced + 1; IF replaced MOD saveEach = 0 THEN PruneAndSave[design, file]; ENDLOOP; TerminalIO.PutF["=== %g objects replaced in the directory.\nPruning ... ", IO.int[replaced]]; Prune[design]; firstPass _ FALSE; WHILE CDDirectory.EnumerateDesign[design: design, proc: ReplaceRoutingCells, dir: FALSE] DO name: Rope.ROPE _ CD.Describe[toBeReplaced]; new: CD.Object _ ToRoutingCell[toBeReplaced]; CDDirectory.ReplaceObject[design, toBeReplaced, new]; TerminalIO.PutF["Done replacing routing cell '%g'!\n", IO.rope[name]]; replaced _ replaced + 1; IF replaced MOD saveEach = 0 THEN PruneAndSave[design, file]; ENDLOOP; CDDirectoryOps.RemoveProperties[design, $TransistorCount]; PruneAndSave[design, file]; }; END. rPWSqueezeImpl.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, May 7, 1987 0:10:15 am PDT Count Transistors Transform into a RoutingCell Serlet's third theorem: rect1 and rect2 are fusable (i.e. all points belonging to the surround belong either to rect1 or to rect2 or to both) iff their area follow the strange law in the code. The following statement does NOT work!!! pobjs^ _ SimplifyPObj[pobjs^]; We change all names that contain *[]/. if any! The final cell Replacing RoutingCells throughout the design Κ₯˜šœ™Jšœ<™Lšœœ ˜Lšœ‰˜‰L™.Lšœ%˜%Lšœ™LšœTœ˜jLšœ@œœ œ˜vL˜——™,šžœœ œ ˜#Lšœ ˜ Jšœ&˜&Lšœ˜L˜J˜—šž œœ œœ˜6Jšœ˜Jšœœ'˜0J˜J˜—šžœœ œœ œœ œ ˜pJšœœ˜Jšœ œœ˜šžœ ˜3Jšœ œ ˜/Lšœœœœ˜&Jšœœœ˜'Jšœœœ J˜wJš œœœ œœ˜&Jšœ6œœœ˜HJšœ˜Lšœ8œ ˜GJšœœ˜ J˜—šœMœ˜[Jšœ œ*˜9Lšœœ&˜-Jšœ6˜6Jšœ4˜4Jšœœ-˜HLšœ7œ ˜FJšœ˜Jšœ œœ˜=Jšœ˜—LšœKœ˜]Jšœ˜Jšœ œ˜šœMœ˜[Jšœ œœ˜,Lšœœ&˜-Jšœ6˜6Lšœ7œ ˜FJšœ˜Jšœ œœ˜=Jšœ˜—Jšœ:˜:Jšœ˜J˜—L˜—Jšœ˜—…—β)ω