Basic Operations
ignoreMeProp: PUBLIC ATOM ← $DAUserIgnoreForSelection; -- Fix CellLibraries some day to have this atom correspond to the package in which CoreCDUser is contained.
EnumerateSelectedFlatWires:
PUBLIC
PROC [root: Core.CellType, eachSelectedFlatWire: EachSelectedFlatWireProc, cutSet: CoreFlat.CutSet ←
NIL, design:
CD.Design ←
NIL, decoration: CoreGeometry.Decoration ←
NIL]
RETURNS [quit:
BOOL ←
FALSE] = {
ThisSelectedWire: EachSelectedWireProc = {
quit ← eachSelectedFlatWire[[
flatCell: flatCell,
wireRoot: IF publicWire THEN public ELSE internal,
wire: selectedWire]];
};
publicWire: BOOL ← FALSE;
cellType: Core.CellType ← NIL;
flatCell: CoreFlat.FlatCellTypeRec ← [];
[design, decoration] ← FindDesignAndDecoration[root, design, decoration];
[cellType, flatCell] ← FlatCellTypeFromPushed[design, decoration, root, cutSet];
publicWire ← cellType.class#CoreClasses.recordCellClass;
quit ← EnumerateSelectedWires[design, decoration, IF publicWire THEN cellType.public ELSE NARROW[cellType.data, CoreClasses.RecordCellType].internal, publicWire, ThisSelectedWire];
};
EachSelectedWireProc:
TYPE =
PROC [selectedWire: Core.Wire]
RETURNS [quit:
BOOL ←
FALSE];
EnumerateSelectedWires:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, root: Core.Wire, public:
BOOL ←
FALSE, eachSelectedWire: EachSelectedWireProc]
RETURNS [quit:
BOOL ←
FALSE] = {
ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = {
ThisWire: CoreOps.EachWireProc = {
ThisWireInstance: CoreGeometry.EachInstanceProc = {
quit ← instance=selectedInstance;
};
match: BOOL ← IF public THEN CoreGeometry.EnumeratePins[decoration, wire, ThisWireInstance] ELSE CoreGeometry.EnumerateGeometry[decoration, wire, ThisWireInstance];
IF match
THEN {
quit ← eachSelectedWire[wire];
someMatch ← TRUE;
};
};
someMatch: BOOL ← FALSE;
quit ← CoreOps.VisitWire[root, ThisWire];
IF
NOT someMatch
AND
NOT CDRects.IsBareRect[selectedInstance.obj]
THEN {
EachFlatInstance: CoreGeometry.EachInstanceProc = {
ThisWire: CoreOps.EachWireProc = {
ThisWireInstance: CoreGeometry.EachInstanceProc = {
quit ← instance=flatInstance;
};
match: BOOL ← IF public THEN CoreGeometry.EnumeratePins[decoration, wire, ThisWireInstance] ELSE CoreGeometry.EnumerateGeometry[decoration, wire, ThisWireInstance];
IF match
THEN {
quit ← eachSelectedWire[wire];
someMatch ← TRUE;
};
};
flatInstance: CoreGeometry.Instance ← instance;
quit ← CoreOps.VisitWire[root, ThisWire];
};
quit ← CoreGeometry.FlattenInstance[selectedInstance, EachFlatInstance];
};
IF NOT someMatch THEN ERROR CoreCDUserError["CoreCDUser: Some selected instance does not correspond to any wire"];
};
quit ← ExtractOps.EnumerateSelectedInstances[design, ThisSelectedInstance];
};
EnumerateSelectedFlatCells:
PUBLIC
PROC [root: Core.CellType, eachSelectedFlatCell: EachSelectedFlatCellProc, cutSet: CoreFlat.CutSet ←
NIL, design:
CD.Design ←
NIL, decoration: CoreGeometry.Decoration ←
NIL]
RETURNS [quit:
BOOL ←
FALSE] = {
[design, decoration] ← FindDesignAndDecoration[root, design, decoration];
IF design.actual.rest=
NIL
THEN {
ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = {
errorMessage: Rope.ROPE ← NIL;
flatCellType: CoreFlat.FlatCellTypeRec ← [];
cdInstance.trans ← selectedInstance.trans;
cdInstance.ob ← selectedInstance.obj;
[errorMessage,,flatCellType] ← BuildFlatCell[cell: root, instances: LIST[cdInstance], pushData: pushData];
IF errorMessage#NIL THEN ERROR CoreCDUserError[errorMessage];
quit ← eachSelectedFlatCell[flatCellType]
};
cdInstance: CD.Instance ← NEW[CD.InstanceRep];
pushData: DesignPushData ← GetPushData[design, decoration, root, cutSet];
quit ← ExtractOps.EnumerateSelectedInstances[design, ThisSelectedInstance];
}
ELSE {
SelectedCellType: EachSelectedCellInstanceProc = {
quit ← eachSelectedFlatCell[[CoreFlat.ExtendPath[flatCell.path, selectedCellInstance, rct], 0]];
};
cellType: Core.CellType ← NIL;
flatCell: CoreFlat.FlatCellTypeRec ← [];
rct: CoreClasses.RecordCellType ← NIL;
[cellType, flatCell] ← FlatCellTypeFromPushed[design, decoration, root, cutSet];
rct ← NARROW[cellType.data]; -- All pushed in objects must be record cells so this must succeed
quit ← EnumerateSelectedCellInstances[design, decoration, rct, SelectedCellType];
};
};
EachSelectedCellInstanceProc:
TYPE =
PROC [selectedCellInstance:
NAT]
RETURNS [quit:
BOOL ←
FALSE];
EnumerateSelectedCellInstances:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, rct: CoreClasses.RecordCellType, eachSelectedCellInstance: EachSelectedCellInstanceProc]
RETURNS [quit:
BOOL ←
FALSE] = {
ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = {
FOR i:
NAT
IN [0..rct.size)
DO
IF CoreGeometry.HasTrans[decoration, rct[i]]
AND CoreGeometry.HasObject[decoration, rct[i].type]
THEN {
IF CoreGeometry.GetTrans[decoration, rct[i]]=selectedInstance.trans
AND ExtractOps.SameCDObject[selectedInstance.obj, CoreGeometry.GetObject[decoration, rct[i].type]]
THEN {
quit ← eachSelectedCellInstance[i];
EXIT;
};
};
REPEAT FINISHED => ERROR CoreCDUserError["CoreCDUser: Some selected instance does not correspond to any cell type"];
ENDLOOP;
};
quit ← ExtractOps.EnumerateSelectedInstances[design, ThisSelectedInstance];
};
pushDataAtom: ATOM = $CoreCDUserPushData;
CellPushData: TYPE = REF CellPushDataRec;
CellPushDataRec:
TYPE =
RECORD [
decoration: CoreGeometry.Decoration ← NIL,
root: Core.CellType ← NIL,
cutSet: CoreFlat.CutSet ← NIL,
selectionData: RefTab.Ref ← NIL,
transitiveClosure: RefTab.Ref ← NIL,
viewer: ViewerClasses.Viewer ← NIL,
doesNotMatterDesign: CD.Design ← NIL,
designPushData: LIST OF DesignPushData ← NIL];
DesignPushData: TYPE = REF DesignPushDataRec;
DesignPushDataRec:
TYPE =
RECORD [
design: CD.Design ← NIL,
cellPushData: CellPushData ← NIL,
cellType: Core.CellType ← NIL,
flatCellType: CoreFlat.FlatCellTypeRec ← [],
errorMessage: Rope.ROPE ← NIL];
ResolveData: TYPE = REF ResolveDataRec;
ResolveDataRec:
TYPE =
RECORD [
cell: Core.CellType ← NIL,
instanceData: IntHashTable.Table ← NIL,
feedBackButton: TiogaButtons.TiogaButton ← NIL,
selectedInstance: NAT ← 0,
doesNotMatter: BOOL ← TRUE,
struckOut: BOOL ← FALSE];
InstanceData: TYPE = REF InstanceDataRec;
InstanceDataRec:
TYPE =
RECORD [
design: CD.Design ← NIL,
pushData: CellPushData ← NIL,
resolve: ResolveData ← NIL,
instance: NAT ← 0,
objects: LIST OF CoreGeometry.Object ← NIL, -- only needed for debug
cells: LIST OF Core.CellType ← NIL, -- only needed for debug
button: TiogaButtons.TiogaButton ← NIL];
FlatCellTypeFromPushed:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [pushedCellType: Core.CellType ←
NIL, pushedFlatCellType: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType] = {
pushData: DesignPushData ← GetPushData[design, decoration, root, cutSet];
IF pushData.errorMessage#NIL THEN ERROR CoreCDUserError[pushData.errorMessage];
pushedCellType ← pushData.cellType;
pushedFlatCellType ← pushData.flatCellType;
IF pushedCellType=NIL THEN ERROR CoreCDUserError["CoreCDUser: The object of the instance at the top of the push stack is not reachable from the root cell type"];
};
GetPushData:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [pushData: DesignPushData] = {
pushData ← NARROW[CDProperties.GetDesignProp[design, pushDataAtom]];
IF pushData=
NIL
OR (pushData#
NIL
AND (pushData.cellPushData.root#root
OR pushData.cellPushData.decoration#decoration))
THEN {
cellPushData: CellPushData ← NARROW[CoreProperties.GetCellTypeProp[root, pushDataAtom]];
IF cellPushData=
NIL
OR (cellPushData#
NIL
AND (cellPushData.root#root
OR cellPushData.decoration#decoration))
THEN {
IF pushData#NIL AND pushData.cellPushData.viewer#NIL THEN ViewerOps.DestroyViewer[pushData.cellPushData.viewer];
cellPushData ← CreatePushData[design, root, decoration, cutSet];
CoreProperties.PutCellTypeProp[root, pushDataAtom, cellPushData];
};
pushData ← CreateDesignPushData[design, cellPushData];
RecomputePushedCellType[pushData];
}
ELSE IF pushData.cellPushData.doesNotMatterDesign#design THEN RecomputePushedCellType[pushData];
};
CreateDesignPushData:
PROC [design:
CD.Design, cellPushData: CellPushData]
RETURNS [pushData: DesignPushData] = {
pushData ← NEW[DesignPushDataRec];
pushData.design ← design;
pushData.cellPushData ← cellPushData;
cellPushData.designPushData ← CONS[pushData, cellPushData.designPushData];
CDProperties.PutDesignProp[design, pushDataAtom, pushData];
};
CreatePushData:
PROC [design:
CD.Design, root: Core.CellType, decoration: CoreGeometry.Decoration, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [pushData: CellPushData] = {
RecordEachAncestor: EachLeastCommonObjectAncestorProc = {
resolveData: ResolveData ← NARROW[RefTab.Fetch[pushData.selectionData, ancestor].val];
instanceData: InstanceData ← NIL;
IF resolveData=
NIL
THEN {
resolveData ← NEW[ResolveDataRec];
IF NOT RefTab.Insert[pushData.selectionData, ancestor, resolveData] THEN ERROR;
resolveData.cell ← ancestor;
resolvers ← CONS[resolveData, resolvers];
resolveData.instanceData ← IntHashTable.Create[];
};
instanceData ← NARROW[IntHashTable.Fetch[resolveData.instanceData, instance].value];
IF instanceData=
NIL
THEN {
instanceData ← NEW[InstanceDataRec];
instanceData.design ← design;
instanceData.pushData ← pushData;
instanceData.resolve ← resolveData;
instanceData.instance ← instance;
IF NOT IntHashTable.Insert[resolveData.instanceData, instance, instanceData] THEN ERROR;
};
IF object#
NIL
THEN
FOR objects:
LIST
OF CoreGeometry.Object ← instanceData.objects, objects.rest
UNTIL objects=
NIL
DO
IF objects.first=object THEN EXIT;
REPEAT FINISHED => instanceData.objects ← CONS[object, instanceData.objects];
ENDLOOP;
IF cell#
NIL
THEN
FOR cells:
LIST
OF Core.CellType ← instanceData.cells, cells.rest
UNTIL cells=
NIL
DO
IF cells.first=cell THEN EXIT;
REPEAT FINISHED => instanceData.cells ← CONS[cell, instanceData.cells];
ENDLOOP;
};
resolvers: LIST OF ResolveData ← NIL;
pushData ← NEW[CellPushDataRec];
pushData.decoration ← decoration;
pushData.root ← root;
pushData.cutSet ← cutSet;
pushData.selectionData ← RefTab.Create[];
pushData.transitiveClosure ← EnumerateLeastCommonObjectAncestors[design, root, decoration, RecordEachAncestor, cutSet];
IF resolvers#
NIL
THEN {
externalViewer: ViewerClasses.Viewer ← Containers.Create[[
--
JMF: TiogaButtons hack
name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"],
scrollable: FALSE,
iconic: TRUE,
column: left]];
viewer: ViewerClasses.Viewer ← TiogaButtons.CreateViewer[[
--
JMF: TiogaButtons hack
name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"],
column: left,
border: FALSE,
parent: externalViewer]];
pushData.viewer ← viewer;
Containers.ChildXBound[externalViewer, viewer];
Containers.ChildYBound[externalViewer, viewer];
viewer: ViewerClasses.Viewer ← TiogaButtons.CreateViewer[[ -- JMF: TiogaButtons hack
name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"],
iconic: FALSE,
column: left]];
pushData.viewer ← viewer;
FOR resolveList:
LIST
OF ResolveData ← resolvers, resolveList.rest
UNTIL resolveList=
NIL
DO
FindType: IntHashTable.EachPairAction = {
IF RefTab.Insert[x: finishedSubCells, key: data[key].type, val: $Finished]
THEN {
subCellType ← data[key].type;
quit ← TRUE;
};
};
data: CoreClasses.RecordCellType ← NARROW[resolveList.first.cell.data];
subCellType: Core.CellType ← NIL;
resolveName: Rope.ROPE ← CoreOps.GetCellTypeName[resolveList.first.cell];
button: TiogaButtons.TiogaButton ← TiogaButtons.CreateButton[viewer: viewer, rope: Rope.Cat[resolveName, ": "], looks: "f"];
finishedSubCells: RefTab.Ref ← RefTab.Create[];
firstChoice: BOOL ← TRUE;
IF pushDebug THEN TerminalIO.PutRopes[resolveName, "\n"];
resolveList.first.feedBackButton ← button;
WHILE IntHashTable.Pairs[resolveList.first.instanceData, FindType]
DO
AddInstanceChoice: IntHashTable.EachPairAction = {
IF data[key].type=subCellType
THEN {
instanceData: InstanceData ← NARROW[value];
instanceName: Rope.ROPE ← CoreClasses.GetCellInstanceName[data[key]];
instanceData.button ← TiogaButtons.AppendToButton[button: button, rope: IF instanceName=NIL THEN IO.PutFR["%g", IO.int[key]] ELSE instanceName, looks: "f", proc: RecordInstanceNumber, clientData: instanceData, fork: FALSE];
[] ← TiogaButtons.AppendToButton[button: button, rope: " "];
IF firstChoice
THEN {
SetInstanceNumber[instanceData];
firstChoice ← FALSE;
};
IF pushDebug
THEN {
TerminalIO.PutRopes[" ", IO.PutFR["%g(%g)", IO.int[key], IO.rope[CoreOps.GetCellTypeName[data[key].type]]], "\n"];
TerminalIO.PutRope[" Cells:\n"];
FOR cells:
LIST
OF Core.CellType ← instanceData.cells, cells.rest
UNTIL cells=
NIL
DO
TerminalIO.PutRopes[" ", CoreOps.GetCellTypeName[cells.first], "\n"];
ENDLOOP;
TerminalIO.PutRope[" Objects:\n"];
FOR objects:
LIST
OF CoreGeometry.Object ← instanceData.objects, objects.rest
UNTIL objects=
NIL
DO
TerminalIO.PutRopes[" ", PW.Name[objects.first], "\n"];
ENDLOOP;
};
};
};
[] ← IntHashTable.Pairs[resolveList.first.instanceData, AddInstanceChoice];
[] ← TiogaButtons.AppendToButton[button: button, rope: Rope.Cat["(", CoreOps.GetCellTypeName[subCellType], ") "], looks: "f"];
ENDLOOP;
ENDLOOP;
ViewerOps.OpenIcon[externalViewer]; -- JMF: TiogaButtoms hack
};
};
RecordInstanceNumber: TiogaButtons.TiogaButtonProc = {
instanceData: InstanceData ← NARROW[clientData];
oldInstanceData: InstanceData ← NARROW[IntHashTable.Fetch[table: instanceData.resolve.instanceData, key: instanceData.resolve.selectedInstance].value];
pushData: DesignPushData ← NARROW[CDProperties.GetDesignProp[ instanceData.pushData.doesNotMatterDesign, pushDataAtom]];
TiogaButtons.ChangeButtonLooks[oldInstanceData.button, NIL, "i"];
SetInstanceNumber[instanceData];
FOR dpd:
LIST
OF DesignPushData ← instanceData.pushData.designPushData, dpd.rest
UNTIL dpd=
NIL
DO
IF dpd.first#pushData THEN RecomputePushedCellType[dpd.first];
ENDLOOP;
RecomputePushedCellType[pushData];
};
SetInstanceNumber:
PROC [instanceData: InstanceData] = {
instanceData.resolve.selectedInstance ← instanceData.instance;
TiogaButtons.ChangeButtonLooks[instanceData.button, "i"];
instanceData ← instanceData;
};
PushPop: CDEvents.EventProc = {
pushData: DesignPushData ← NARROW[CDProperties.GetDesignProp[design, pushDataAtom]];
importerDesign: CD.Design ← GetImporterDesign[design];
IF importerDesign#
NIL
THEN {
importerPushData: DesignPushData ← NARROW[CDProperties.GetDesignProp[importerDesign, pushDataAtom]];
IF importerPushData#NIL AND pushData=NIL THEN pushData ← CreateDesignPushData[design, importerPushData.cellPushData];
};
IF pushData#NIL THEN RecomputePushedCellType[pushData];
};
RecomputePushedCellType:
PROC [pushData: DesignPushData] = {
design: CD.Design ← pushData.design;
instanceStack: LIST OF CD.Instance ← NIL;
pushData.errorMessage ← NIL;
pushData.cellPushData.doesNotMatterDesign ← design;
IF design.actual.rest=NIL THEN pushData.errorMessage ← "CoreCDUser: No currently pushed-in cell."
ELSE {
FOR stack:
LIST
OF
CD.PushRec ← design.actual, stack.rest
WHILE stack.rest#
NIL
DO
IF stack.first.specific.changed
THEN {
pushData.errorMessage ← IO.PutFR["CoreCDUser: Impossible to unwind stack, cell %g has been changed and not saved.", IO.rope[PW.Name[stack.first.mightReplace.ob]]];
EXIT;
};
instanceStack ← CONS[stack.first.mightReplace, instanceStack];
ENDLOOP;
IF pushData.errorMessage=
NIL
THEN {
IF RefTab.Pairs[pushData.cellPushData.selectionData, SetDoesNotMatter] THEN ERROR;
[pushData.errorMessage, pushData.cellType, pushData.flatCellType] ← BuildFlatCell[cell: pushData.cellPushData.root, instances: instanceStack, pushData: pushData];
IF pushData.errorMessage=NIL THEN IF RefTab.Pairs[pushData.cellPushData.selectionData, DisplayDoesNotMatter] THEN ERROR;
};
};
};
BuildFlatCell:
PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ←
NIL, instances:
LIST
OF
CD.Instance, pushData: DesignPushData]
RETURNS [errorMessage: Rope.
ROPE ←
NIL, cellType: Core.CellType, flatCellType: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType] = {
matchingObject: BOOL ← ExtractOps.SameCDObject[instances.first.ob, CoreGeometry.GetObject[pushData.cellPushData.decoration, cell]];
SELECT
TRUE
FROM
matchingObject
AND instances.rest=
NIL => {
cellType ← cell;
flatCellType ← flatCell;
};
CoreFlat.CutSetMemberResolved[flatCell, instance, cell, pushData.cellPushData.cutSet] => errorMessage ← "CoreCDUser: No such cell above current cut set";
cell.class=CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
IF matchingObject
THEN
FOR inst:
NAT
IN [0..rct.size)
DO
thisInstance: CoreClasses.CellInstance ← rct[inst];
possibleInst: CoreGeometry.Instance ← [CoreGeometry.GetObject[pushData.cellPushData.decoration, thisInstance.type], CoreGeometry.GetTrans[pushData.cellPushData.decoration, thisInstance]];
IF ExtractOps.SameCDInstance[instances.rest.first, instances.first.trans, possibleInst]
THEN {
[errorMessage, cellType, flatCellType] ← BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances.rest, pushData];
EXIT;
};
REPEAT FINISHED => ERROR; -- record cell with CD object and next instance does not match?
ENDLOOP
ELSE {
cdObject: CD.Object ← instances.first.ob;
found: BOOL ← FALSE;
multiple: BOOL ← FALSE;
inst: NAT ← LAST[NAT];
WHILE CDImports.IsImport[cdObject] DO cdObject ← CDDirectory.Expand1[cdObject].new ENDLOOP;
FOR i:
NAT
IN [0..rct.size)
DO
subCellTable: RefTab.Ref ← NARROW[RefTab.Fetch[ pushData.cellPushData.transitiveClosure, rct[i].type].val];
IF RefTab.Fetch[subCellTable, cdObject].found
THEN {
multiple ← found;
found ← TRUE;
inst ← i;
IF multiple THEN EXIT;
};
ENDLOOP;
SELECT
TRUE
FROM
NOT found => errorMessage ← "CoreCDUser: Cell cannot be reached with current selection viewer settings or selection viewer cannot disambiguate this object";
NOT multiple => {
thisInstance: CoreClasses.CellInstance ← rct[inst];
[errorMessage, cellType, flatCellType] ← BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances, pushData];
};
ENDCASE => {
resolveData: ResolveData ← NARROW[RefTab.Fetch[pushData.cellPushData.selectionData, cell].val];
IF resolveData=NIL THEN errorMessage ← "CoreCDUser: Cannot disambiguate this object"
ELSE {
thisInstance: CoreClasses.CellInstance ← rct[resolveData.selectedInstance];
resolveData.doesNotMatter ← FALSE;
[errorMessage, cellType, flatCellType] ← BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, resolveData.selectedInstance, rct], 0], thisInstance, instances, pushData];
};
};
};
};
ENDCASE => {
thisCell: Core.CellType ← CoreOps.Recast[cell];
[errorMessage, cellType, flatCellType] ← BuildFlatCell[thisCell, IF thisCell=cell THEN flatCell ELSE [flatCell.path, flatCell.recastCount+1], instance, IF matchingObject THEN instances.rest ELSE instances, pushData];
};
};
SetDoesNotMatter: RefTab.EachPairAction = {
resolveData: ResolveData ← NARROW[val];
resolveData.doesNotMatter ← TRUE;
};
DisplayDoesNotMatter: RefTab.EachPairAction = {
resolveData: ResolveData ← NARROW[val];
IF resolveData.doesNotMatter#resolveData.struckOut
THEN {
IF resolveData.doesNotMatter THEN TiogaButtons.ChangeButtonLooks[resolveData.feedBackButton, "y"] ELSE TiogaButtons.ChangeButtonLooks[resolveData.feedBackButton, NIL, "y"];
resolveData.struckOut ← resolveData.doesNotMatter;
};
};
Using the ignore bindings form of enumeration keep a hash table of objects and cell types reachable from a cell, including the cell itself and the object belonging to it. While combining the objects and cells reachable from a cell notice if an object or cell is inserted more than once, i.e. accessable through more than one instance. If it is then call eachLeastCommonAncestor for the current cell. This routine only understands record cells and therefore only record cells are passed to eachLeastCommonAncestor. eachLeastCommonAncestor may be called multiple times with the same arguments. It will be called with all of the multiple instances through which a cell or object may be reached. transitiveClosure maps CellType to RefTab which then maps Object or CellType to $DependsOn or REF NAT.
EachLeastCommonObjectAncestorProc:
TYPE =
PROC [ancestor: Core.CellType, instance:
NAT, cell: Core.CellType ←
NIL, object: CoreGeometry.Object ←
NIL];
EnumerateLeastCommonObjectAncestors:
PROC [design:
CD.Design, root: Core.CellType, decoration: CoreGeometry.Decoration, eachLeastCommonAncestor: EachLeastCommonObjectAncestorProc, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [transitiveClosure: RefTab.Ref ←
NIL] = {
ComputeCellObjectDependence:
PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ←
NIL]
RETURNS [cellObjects: RefTab.Ref] = {
cellObjects ← NARROW[RefTab.Fetch[transitiveClosure, cell].val];
IF cellObjects=
NIL
THEN {
cellObjects ← RefTab.Create[];
IF CoreProperties.GetCellTypeProp[cell, ignoreMeProp]=
NIL
THEN {
IF NOT RefTab.Insert[cellObjects, cell, $DependsOn] THEN ERROR;
IF cell.class#CoreClasses.transistorCellClass AND CoreGeometry.HasObject[decoration, cell] THEN IF NOT RefTab.Insert[cellObjects, CoreGeometry.GetObject[ decoration, cell], $DependsOn] THEN ERROR;
SELECT
TRUE
FROM
CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => NULL;
cell.class=CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
rctHasObject: BOOL ← CoreGeometry.HasObject[decoration, cell];
FOR i:
NAT
IN [0..rct.size)
DO
InsertRecordSubObject: RefTab.EachPairAction = {
subCell: Core.CellType ← NIL;
object: CoreGeometry.Object ← NIL;
IF
NOT RefTab.Insert[cellObjects, key,
NEW[
NAT ← i]]
THEN {
firstInstance: REF ANY ← RefTab.Fetch[cellObjects, key].val;
ambiguousMultipath: BOOL ← TRUE;
WITH key
SELECT
FROM
o: CoreGeometry.Object => {
object ← o;
IF rctHasObject THEN ambiguousMultipath ← RefTab.Fetch[topObjects, object].found;
};
s: Core.CellType => {
subCell ← s;
ambiguousMultipath ← NOT CoreGeometry.HasObject[decoration, subCell];
};
ENDCASE => ERROR;
IF ambiguousMultipath
THEN {
IF
ISTYPE[firstInstance,
REF
NAT]
THEN {
eachLeastCommonAncestor[cell, NARROW[firstInstance, REF NAT]^, subCell, object];
[] ← RefTab.Store[cellObjects, key, $DependsOn];
};
eachLeastCommonAncestor[cell, i, subCell, object];
};
};
};
subCellObjects: RefTab.Ref ← ComputeCellObjectDependence[rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
IF RefTab.Pairs[subCellObjects, InsertRecordSubObject] THEN ERROR;
ENDLOOP;
};
ENDCASE => {
InsertOtherSubObject: RefTab.EachPairAction = {
[] ← RefTab.Store[cellObjects, key, $DependsOn];
};
new: Core.CellType ← CoreOps.Recast[cell];
recastCellObjects: RefTab.Ref ← IF cell=new THEN ComputeCellObjectDependence[cell, flatCell, instance] ELSE ComputeCellObjectDependence[new, [flatCell.path, flatCell.recastCount+1], instance];
IF RefTab.Pairs[recastCellObjects, InsertOtherSubObject] THEN ERROR;
};
};
IF NOT RefTab.Insert[transitiveClosure, cell, cellObjects] THEN ERROR;
};
};
topObjects: RefTab.Ref ← RefTab.Create[];
FOR ti: ExtractOps.TopInstanceLists ← ExtractOps.GetTopInstances[design], ti.rest
UNTIL ti=
NIL
DO
FOR il:
CD.InstanceList ← ti.first.instances, il.rest
UNTIL il=
NIL
DO
[] ← RefTab.Insert[topObjects, il.first.ob, $TopLevelInstance];
ENDLOOP;
ENDLOOP;
transitiveClosure ← RefTab.Create[];
[] ← ComputeCellObjectDependence[root];
};