<> <> <> <<>> DIRECTORY Basics, CD, CDCells, CDSymbolicObjects, Core, CoreClasses, CoreFlat, CoreGeometry, CoreIO, CoreOps, ExtractUtilities, GList, PW, RefTab, Rope, Sinix; ExtractUtilitiesImpl: CEDAR PROGRAM IMPORTS Basics, CDCells, CDSymbolicObjects, CoreFlat, CoreGeometry, CoreClasses, CoreIO, CoreOps, GList, PW, RefTab, Rope, Sinix EXPORTS ExtractUtilities SHARES CDCells = BEGIN OPEN ExtractUtilities; <> ExtractCellAsWireWithPins: PUBLIC Sinix.ExtractProc = { EachInst: CDCells.InstEnumerator = { obj: CD.Object _ IF CDSymbolicObjects.IsSymbolicOb[inst.ob] THEN CoreGeometry.CDPinToCoreGeometryPin[inst.ob, inst.properties] ELSE inst.ob; pins _ CONS [[obj, inst.trans], pins]; }; pins: CoreGeometry.Instances _ NIL; wire: Core.Wire _ CoreOps.CreateWire[]; [] _ CDCells.EnumerateInstances[obj, EachInst]; CoreGeometry.PutPins[mode.decoration, wire, pins]; result _ wire; }; PreExtracted: PUBLIC Sinix.ExtractProc = { result _ CoreOps.Recast[CoreIO.RestoreCellType[PW.Name[obj]]]; }; <> SortedEdges: TYPE = ARRAY CoreGeometry.Side OF LIST OF Core.Wire _ ALL [NIL]; WireMinMax: TYPE = RECORD [wire: Core.Wire, min, max: INT]; SortEdges: PROC [decoration: CoreGeometry.Decoration, ll: CD.Layer, cellType: Core.CellType] RETURNS [edges: SortedEdges] = { FOR ss: CoreGeometry.Side IN CoreGeometry.Side DO wmm: LIST OF REF WireMinMax _ NIL; edge: LIST OF Core.Wire _ NIL; EachWirePin: CoreGeometry.EachWirePinProc = { IF wire.size#0 OR side#ss OR layer#ll THEN RETURN; wmm _ CONS [NEW [WireMinMax _ [wire, min, max]], wmm]; }; CompareWMM: GList.CompareProc = { wmm1: REF WireMinMax = NARROW [ref1]; wmm2: REF WireMinMax = NARROW [ref2]; RETURN [Basics.CompareInt[wmm2.min, wmm1.min]]; }; [] _ CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, EachWirePin]; FOR list: LIST OF REF WireMinMax _ NARROW [GList.Sort[wmm, CompareWMM]], list.rest WHILE list#NIL DO edge _ CONS [list.first.wire , edge]; ENDLOOP; edges[ss] _ edge; ENDLOOP; }; MatchSourceToExtracted: PUBLIC PROC [sdecoration, edecoration: CoreGeometry.Decoration, slayer, elayer: CD.Layer, source, extracted: Core.CellType, name: Core.ROPE _ NIL, props: Core.Properties _ NIL] RETURNS [new: Core.CellType] = { sourceEdges: SortedEdges _ SortEdges[sdecoration, slayer, source]; extractedEdges: SortedEdges _ SortEdges[edecoration, elayer, extracted]; public: Core.Wire _ CoreOps.CopyWire[source.public]; table: RefTab.Ref _ RefTab.Create[]; -- from extracted to new sourceToNew: RefTab.Ref _ CoreOps.CreateBindingTable[source.public, public]; -- from source to new FOR side: CoreGeometry.Side IN CoreGeometry.Side DO length: INT = GList.Length[sourceEdges[side]]; IF length#GList.Length[extractedEdges[side]] THEN ERROR; THROUGH [0 .. length) DO sourceWire: Core.Wire _ sourceEdges[side].first; extractedWire: Core.Wire _ extractedEdges[side].first; newWire: Core.Wire _ NARROW [RefTab.Fetch[sourceToNew, sourceWire].val]; prevNew: Core.Wire _ NARROW [RefTab.Fetch[table, extractedWire].val]; IF prevNew#NIL AND prevNew#newWire THEN ERROR; [] _ RefTab.Store[table, extractedWire, newWire]; sourceEdges[side] _ sourceEdges[side].rest; extractedEdges[side] _ extractedEdges[side].rest; ENDLOOP; ENDLOOP; IF RefTab.GetSize[table]#CoreOps.WireBits[public] THEN ERROR; new _ CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extracted, table: table, name: name, props: props]; }; <> Search: PUBLIC PROC [rootCT: Core.CellType, name: Core.ROPE] RETURNS [ct: Core.CellType _ NIL, flat: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] = { UnboundFlatCell: CoreFlat.UnboundFlatCellProc = { IF Rope.Equal[CoreOps.GetCellTypeName[cell], name] THEN {ct _ cell; flat _ flatCell; RETURN}; IF cell.class=CoreClasses.recordCellClass THEN CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, UnboundFlatCell]; }; UnboundFlatCell[rootCT]; }; <> ReverseIntCompare: GList.CompareProc = { RETURN [Basics.CompareInt[NARROW [ref2, REF INT]^, NARROW [ref1, REF INT]^]]; }; CountInstances: PUBLIC PROC [object: CD.Object] RETURNS [instanceCounts: RefInts] = { RecurseCountInstances: PROC [object: CD.Object, oldInstanceCount: RefInts] RETURNS [instanceCounts: RefInts] = { instanceCounts _ oldInstanceCount; IF RefTab.Fetch[objectVisitTable, object].found THEN RETURN; IF NOT RefTab.Insert[objectVisitTable, object, $Visited] THEN ERROR; IF object.class=CDCells.pCellClass THEN { EachSubObject: CDCells.InstEnumerator = { instanceCounts _ RecurseCountInstances[inst.ob, instanceCounts]; }; ic: INT _ CDCells.CountInstances[object]; FOR icl: RefInts _ instanceCounts, icl.rest UNTIL icl=NIL DO IF icl.first^=ic THEN EXIT; REPEAT FINISHED => instanceCounts _ CONS[NEW[INT _ ic], instanceCounts]; ENDLOOP; [] _ CDCells.EnumerateInstances[object, EachSubObject]; }; }; objectVisitTable: RefTab.Ref _ RefTab.Create[]; instanceCounts _ RecurseCountInstances[object, NIL]; instanceCounts _ NARROW[GList.Sort[instanceCounts, ReverseIntCompare]]; }; <> CleanUpDecorations: PUBLIC PROC [decoration: CoreGeometry.Decoration, cell: Core.CellType, keepObject: BOOL _ FALSE, keepPins: KeepChoice _ none, keepGeometry: KeepChoice _ one] = { visited: RefTab.Ref _ RefTab.Create[]; inst: CoreGeometry.Instance; Quit: CoreGeometry.EachInstanceProc = {inst _ instance; quit _ TRUE}; KillPins: PROC [wire: Core.Wire] = {CoreGeometry.PutPins[decoration, wire, NIL]}; KeepOnePin: PROC [wire: Core.Wire] = { IF CoreGeometry.EnumeratePins[decoration, wire, Quit] THEN CoreGeometry.PutPins[decoration, wire, LIST [inst]]; }; KillGeometry: PROC [wire: Core.Wire] = {CoreGeometry.PutGeometry[decoration, wire, NIL]}; KeepOneGeometry: PROC [wire: Core.Wire] = { IF CoreGeometry.EnumerateGeometry[decoration, wire, Quit] THEN CoreGeometry.PutGeometry[decoration, wire, LIST [inst]]; }; CleanUpDecorationsInternal: PROC [cell: Core.CellType] = { IF RefTab.Fetch[visited, cell].found THEN RETURN; [] _ RefTab.Store[visited, cell, $True]; SELECT cell.class FROM CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType = NARROW [cell.data]; IF NOT keepObject THEN CoreGeometry.PutObject[decoration, cell, NIL]; SELECT keepPins FROM all => {}; none => CoreOps.VisitRootAtomics[cell.public, KillPins]; one => CoreOps.VisitRootAtomics[cell.public, KeepOnePin]; ENDCASE => ERROR; SELECT keepGeometry FROM all => {}; none => CoreOps.VisitRootAtomics[rct.internal, KillGeometry]; one => CoreOps.VisitRootAtomics[rct.internal, KeepOneGeometry]; ENDCASE => ERROR; FOR i: NAT IN [0 .. rct.size) DO CleanUpDecorationsInternal[rct[i].type]; ENDLOOP; }; CoreClasses.transistorCellClass => {}; ENDCASE => ERROR; }; CleanUpDecorationsInternal[cell]; }; FlattenUniques: PUBLIC PROC [decoration: CoreGeometry.Decoration, cell: Core.CellType, flattenNamed: BOOL _ FALSE] RETURNS [Core.CellType] = { count: RefTab.Ref _ RefTab.Create[]; -- $Once or $Many as value visited: RefTab.Ref _ RefTab.Create[]; CountInternal: PROC [cell: Core.CellType] = { previous: REF _ RefTab.Fetch[count, cell].val; SELECT RefTab.Fetch[count, cell].val FROM $Many => {}; $Once => [] _ RefTab.Store[count, cell, $Many]; NIL => { [] _ RefTab.Store[count, cell, $Once]; SELECT cell.class FROM CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType = NARROW [cell.data]; FOR i: NAT IN [0 .. rct.size) DO CountInternal[rct[i].type] ENDLOOP; }; CoreClasses.transistorCellClass => {}; ENDCASE => ERROR; }; ENDCASE => ERROR; }; FlattenUniquesInternal: PROC [cell: Core.CellType] RETURNS [new: Core.CellType] = { new _ NARROW [RefTab.Fetch[visited, cell].val]; IF new#NIL THEN RETURN; <<... to be done>> [] _ RefTab.Store[visited, cell, new]; ERROR; }; RETURN [FlattenUniquesInternal[cell]]; }; <> <> Sinix.RegisterExtractProc[$ExtractCellAsWireWithPins, ExtractCellAsWireWithPins]; Sinix.RegisterExtractProc[$PreExtracted, PreExtracted]; END.