<> <> <> <> 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[SinixRawCMosB.mode.decoration, ct, Leaf, 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.