ExtractUtilitiesImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Bertrand Serlet September 17, 1987 4:05:32 pm PDT
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;
Some Extract Procs
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]]];
};
Computing corresponding cells
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.ROPENIL, 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];
};
Looking for a named Core.CellType
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];
};
Sorting Cells by number of instances
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]];
};
Squeezing Core Structures
CleanUpDecorations: PUBLIC PROC [decoration: CoreGeometry.Decoration, cell: Core.CellType, keepObject: BOOLFALSE, 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: BOOLFALSE] 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]];
};
Initialization
Registering extract procs
Sinix.RegisterExtractProc[$ExtractCellAsWireWithPins, ExtractCellAsWireWithPins];
Sinix.RegisterExtractProc[$PreExtracted, PreExtracted];
END.