SinixOps
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,
pushedData: PushedData ← NIL,
resolve: ResolveData ← NIL,
instance: NAT ← 0,
objects: LIST OF CoreGeometry.Object ← NIL, -- only needed for debug if ChoiceRequired changed to use transitiveClosure
cells: LIST OF Core.CellType ← NIL, -- only needed for debug
button: TiogaButtons.TiogaButton ← NIL];
pushedDataAtom: ATOM = $DAUserPushedData;
PushedData: TYPE = REF PushedDataRec;
PushedDataRec:
TYPE =
RECORD [
topViewer: ViewerClasses.Viewer ← NIL,
decoration: CoreGeometry.Decoration ← NIL,
root: Core.CellType ← NIL,
cutSet: CoreFlat.CutSet ← NIL,
selectionData: HashTable.Table ← NIL,
transitiveClosure: HashTable.Table ← NIL,
cellType: Core.CellType ← NIL,
flatCellType: CoreFlat.FlatCellTypeRec ← [],
errorMessage: Rope.ROPE ← NIL];
CreateSelectionViewer:
PROC [design:
CD.Design, pushedData: PushedData, root: Core.CellType, decoration: CoreGeometry.Decoration, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [selectionData: HashTable.Table ←
NIL, transitiveClosure: HashTable.Table ←
NIL] = {
RecordEachAncestor: EachLeastCommonObjectAncestorProc = {
resolveData: ResolveData ← NARROW[HashTable.Fetch[selectionData, ancestor].value];
instanceData: InstanceData ← NIL;
IF resolveData=
NIL
THEN {
resolveData ← NEW[ResolveDataRec];
IF NOT HashTable.Insert[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.pushedData ← pushedData;
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;
};
viewer: ViewerClasses.Viewer ← TiogaButtons.CreateViewer[[
name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"],
iconic: FALSE,
column: left]];
resolvers: LIST OF ResolveData ← NIL;
pushedData.topViewer ← viewer;
selectionData ← HashTable.Create[];
transitiveClosure ← EnumerateLeastCommonObjectAncestors[root, decoration, RecordEachAncestor, cutSet];
FOR resolveList:
LIST
OF ResolveData ← resolvers, resolveList.rest
UNTIL resolveList=
NIL
DO
FindType: IntHashTable.EachPairAction = {
IF HashTable.Insert[table: finishedSubCells, key: data[key].type, value: $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: HashTable.Table ← HashTable.Create[];
firstChoice: BOOL ← TRUE;
IF SchSimDebug 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 SchSimDebug
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[" ", CDDirectory.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;
};
RecordInstanceNumber: TiogaButtons.TiogaButtonProc = {
instanceData: InstanceData ← NARROW[clientData];
oldInstanceData: InstanceData ← NARROW[IntHashTable.Fetch[table: instanceData.resolve.instanceData, key: instanceData.resolve.selectedInstance].value];
TiogaButtons.ChangeButtonLooks[oldInstanceData.button, NIL, "i"];
SetInstanceNumber[instanceData];
RecomputePushedCellType[instanceData.design, instanceData.pushedData];
};
SetInstanceNumber:
PROC [instanceData: InstanceData] = {
instanceData.resolve.selectedInstance ← instanceData.instance;
TiogaButtons.ChangeButtonLooks[instanceData.button, "i"];
instanceData ← instanceData;
};
PushPop: CDEvents.EventProc = {
pushedData: PushedData ← NARROW[CDProperties.GetDesignProp[design, pushedDataAtom]];
IF pushedData#NIL THEN RecomputePushedCellType[design, pushedData];
};
RecomputePushedCellType:
PROC [design:
CD.Design, pushedData: PushedData] = {
BuildFlatCell:
PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ←
NIL, instances:
LIST
OF
CD.Instance] = {
matchingObject: BOOL ← CoreGeometry.GetObject[pushedData.decoration, cell]=instances.first.ob;
SELECT
TRUE
FROM
matchingObject
AND instances.rest=
NIL => {
pushedData.errorMessage ← NIL;
pushedData.cellType ← cell;
pushedData.flatCellType ← flatCell;
};
FixedCutSetMemberResolved[flatCell, instance, cell, pushedData.cutSet] => pushedData.errorMessage ← "*** No such cell";
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[pushedData.decoration, thisInstance.type], CoreGeometry.GetTrans[pushedData.decoration, thisInstance]];
IF SameCDInstance[instances.rest.first, instances.first.trans, possibleInst]
THEN {
BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances.rest];
EXIT;
};
REPEAT FINISHED => ERROR; -- record cell with CD object and next instance does not match?
ENDLOOP
ELSE {
found: BOOL ← FALSE;
multiple: BOOL ← FALSE;
inst: NAT ← LAST[NAT];
FOR i:
NAT
IN [0..rct.size)
DO
subCellTable: HashTable.Table ← NARROW[HashTable.Fetch[ pushedData.transitiveClosure, rct[i].type].value];
IF HashTable.Fetch[subCellTable, instances.first.ob].found
THEN {
multiple ← found;
found ← TRUE;
inst ← i;
IF multiple THEN EXIT;
};
ENDLOOP;
SELECT
TRUE
FROM
NOT found => pushedData.errorMessage ← "*** Cell cannot be reached with current selection viewer settings or selection viewer cannot disambiguate this object";
NOT multiple => {
thisInstance: CoreClasses.CellInstance ← rct[inst];
BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances];
};
ENDCASE => {
resolveData: ResolveData ← NARROW[HashTable.Fetch[pushedData.selectionData, cell].value];
IF resolveData=NIL THEN pushedData.errorMessage ← "*** Selection viewer cannot disambiguate the push stack"
ELSE {
thisInstance: CoreClasses.CellInstance ← rct[resolveData.selectedInstance];
resolveData.doesNotMatter ← FALSE;
BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, resolveData.selectedInstance, rct], 0], thisInstance, instances];
};
};
};
};
ENDCASE => {
thisCell: Core.CellType ← CoreOps.Recast[cell];
BuildFlatCell[thisCell, IF thisCell=cell THEN flatCell ELSE [flatCell.path, flatCell.recastCount+1], instance, IF matchingObject THEN instances.rest ELSE instances];
};
};
instanceStack: LIST OF CD.Instance ← UnwindCDStack[design ! SchSimError => {pushedData.errorMessage ← msg; GOTO Quit}];
IF HashTable.Pairs[pushedData.selectionData, SetDoesNotMatter] THEN ERROR;
BuildFlatCell[cell: pushedData.root, instances: instanceStack];
IF pushedData.errorMessage=NIL THEN IF HashTable.Pairs[pushedData.selectionData, DisplayDoesNotMatter] THEN ERROR;
EXITS Quit => NULL;
};
RecomputePushedCellType: PROC [design: CD.Design, pushedData: PushedData] = {
FilterSelections: EachSelectedFlatCellTypeProc = {
IF FilterUsingSelectionData[pushedData.root, flatCellType, pushedData.selectionData, instanceSelections] THEN {
IF alreadyCalled THEN {
quit ← TRUE;
pushedData.errorMessage ← "*** Selection data not enough to pick a flat cell.";
}
ELSE {
alreadyCalled ← TRUE;
pushedData.errorMessage ← NIL;
pushedData.cellType ← cellType;
pushedData.flatCellType ← flatCellType;
};
};
};
alreadyCalled: BOOL ← FALSE;
IF NOT EnumerateCellTypesForPushed[design, pushedData.decoration, pushedData.root, pushedData.cutSet, FilterSelections ! SchSimError => {pushedData.errorMessage ← msg; GOTO Quit}] THEN IF NOT alreadyCalled THEN pushedData.errorMessage ← "*** Selection data picks no cell.";
EXITS Quit => NULL;
};
FilterUsingSelectionData:
PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, selectionData: HashTable.Table, instanceSelections: HashTable.Table]
RETURNS [pass:
BOOL ←
FALSE] = {
CheckSelection: CoreFlat.UnboundFlatCellProc = {
SELECT TRUE FROM
CoreFlat.FlatCellTypeEqualRec[flatCell, target] => pass ← TRUE;
cell.class=CoreClasses.recordCellClass => {
resolveData: ResolveData ← NARROW[HashTable.Fetch[selectionData, cell].value];
IF resolveData=NIL THEN CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, NIL, CheckSelection]
ELSE {
ChoiceRequired: IntHashTable.EachPairAction = {
instanceData: InstanceData ← NARROW[value];
FOR objects:
LIST
OF CoreGeometry.Object ← instanceData.objects, objects.rest
UNTIL objects=
NIL
DO
IF objects.first=instanceSelect.subObject
THEN {
quit ← found;
found ← TRUE;
EXIT;
};
ENDLOOP;
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
pathBits: NAT ← BitOps.NBits[rct.size];
instanceBits: PACKED ARRAY [0..16) OF BOOL ← ALL [FALSE];
thisIndex: NAT ← 0;
found: BOOL ← FALSE;
instanceSelect: InstanceSelectionData ← NARROW[HashTable.Fetch[instanceSelections, cell].value];
FOR bit:
NAT
IN [0..pathBits)
DO
instanceBits[16-pathBits+bit] ← target.path.bits[flatCell.path.length+bit];
ENDLOOP;
thisIndex ← LOOPHOLE[instanceBits];
resolveData.doesNotMatter ← (instanceSelect#NIL AND (thisIndex=instanceSelect.instance OR (instanceSelect.subObject#NIL AND NOT IntHashTable.Pairs[resolveData.instanceData, ChoiceRequired])));
IF thisIndex=resolveData.selectedInstance OR resolveData.doesNotMatter THEN CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, NIL, CheckSelection]
};
};
ENDCASE => CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, NIL, CheckSelection];
};
IF HashTable.Pairs[selectionData, SetDoesNotMatter] THEN ERROR;
CheckSelection[cell: root, target: flatCell];
IF pass THEN IF HashTable.Pairs[selectionData, DisplayDoesNotMatter] THEN ERROR;
};
SetDoesNotMatter: HashTable.EachPairAction = {
resolveData: ResolveData ← NARROW[value];
resolveData.doesNotMatter ← TRUE;
};
DisplayDoesNotMatter: HashTable.EachPairAction = {
resolveData: ResolveData ← NARROW[value];
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;
};
};
EachLeastCommonObjectAncestorProc:
TYPE =
PROC [ancestor: Core.CellType, instance:
NAT, cell: Core.CellType ←
NIL, object: CoreGeometry.Object ←
NIL];
FixedCutSetMemberResolved:
PROC [flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, cellType: Core.CellType, cutSet: CoreFlat.CutSet]
RETURNS [member:
BOOL] = {
member ← cellType.class=CoreClasses.transistorCellClass OR cellType.class=CoreClasses.unspecifiedCellClass OR CoreFlat.CutSetMemberResolved[flatCell, instance, cellType, cutSet];
};
EnumerateLeastCommonObjectAncestors:
PROC [root: Core.CellType, decoration: CoreGeometry.Decoration, eachLeastCommonAncestor: EachLeastCommonObjectAncestorProc, cutSet: CoreFlat.CutSet ←
NIL]
RETURNS [transitiveClosure: HashTable.Table ←
NIL] = {
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 HashTable which then maps Object or CellType to $DependsOn or REF NAT.
ComputeCellObjectDependence:
PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ←
NIL]
RETURNS [cellObjects: HashTable.Table] = {
cellObjects ← NARROW[HashTable.Fetch[transitiveClosure, cell].value];
IF cellObjects=
NIL
THEN {
cellObjects ← HashTable.Create[];
IF CoreProperties.GetCellTypeProp[cell, $DAUserIgnoreForSelection]=
NIL
THEN {
IF NOT HashTable.Insert[cellObjects, cell, $DependsOn] THEN ERROR;
IF cell.class#CoreClasses.transistorCellClass AND CoreGeometry.HasObject[decoration, cell] THEN IF NOT HashTable.Insert[cellObjects, CoreGeometry.GetObject[ decoration, cell], $DependsOn] THEN ERROR;
SELECT
TRUE
FROM
FixedCutSetMemberResolved[flatCell, instance, cell, cutSet] => NULL;
cell.class=CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR i:
NAT
IN [0..rct.size)
DO
InsertRecordSubObject: HashTable.EachPairAction = {
subCell: Core.CellType ← NIL;
object: CoreGeometry.Object ← NIL;
IF
NOT HashTable.Insert[cellObjects, key,
NEW[
NAT ← i]]
THEN {
firstInstance: REF ANY ← HashTable.Fetch[cellObjects, key].value;
WITH key
SELECT
FROM
o: CoreGeometry.Object => object ← o;
s: Core.CellType => subCell ← s;
ENDCASE => ERROR;
IF
ISTYPE[firstInstance,
REF
NAT]
THEN {
eachLeastCommonAncestor[cell, NARROW[firstInstance, REF NAT]^, subCell, object];
[] ← HashTable.Store[cellObjects, key, $DependsOn];
};
eachLeastCommonAncestor[cell, i, subCell, object];
};
};
subCellObjects: HashTable.Table ← ComputeCellObjectDependence[rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
IF HashTable.Pairs[subCellObjects, InsertRecordSubObject] THEN ERROR;
ENDLOOP;
};
ENDCASE => {
InsertOtherSubObject: HashTable.EachPairAction = {
[] ← HashTable.Store[cellObjects, key, $DependsOn];
};
new: Core.CellType ← CoreOps.Recast[cell];
recastCellObjects: HashTable.Table ← IF cell=new THEN ComputeCellObjectDependence[cell, flatCell, instance] ELSE ComputeCellObjectDependence[new, [flatCell.path, flatCell.recastCount+1], instance];
IF HashTable.Pairs[recastCellObjects, InsertOtherSubObject] THEN ERROR;
};
};
IF NOT HashTable.Insert[transitiveClosure, cell, cellObjects] THEN ERROR;
};
};
transitiveClosure ← HashTable.Create[];
[] ← ComputeCellObjectDependence[root];
};
EachSelectedFlatWireProc:
TYPE =
PROC [selectedFlatWire: CoreFlat.FlatWireRec]
RETURNS [quit:
BOOL ←
FALSE];
EnumerateSelectedFlatWires:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet ←
NIL, eachSelectedFlatWire: EachSelectedFlatWireProc]
RETURNS [quit:
BOOL ←
FALSE] = {
ThisSelectedWire: EachSelectedWireProc = {
quit ← eachSelectedFlatWire[[
flatCell: flatCell,
wireRoot: IF publicWire THEN public ELSE internal,
wire: selectedWire]];
};
publicWire: BOOL ← FALSE;
flatCell: CoreFlat.FlatCellTypeRec ← [];
cellType: Core.CellType ← NIL;
[cellType, flatCell] ← FlatCellTypeFromPushed[design, decoration, root, cutSet];
IF cellType=NIL THEN ERROR SchSimError["The object of the instance at the top of the push stack does not appear in the simulation"];
publicWire ← cellType.class#CoreClasses.recordCellClass;
quit ← EnumerateSelectedWires[design, decoration, IF publicWire THEN cellType.public ELSE NARROW[cellType.data, CoreClasses.RecordCellType].internal, publicWire, ThisSelectedWire];
};
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] = {
GetPushData:
PROC = {
IF pushedData.errorMessage#NIL THEN ERROR SchSimError[pushedData.errorMessage];
pushedCellType ← pushedData.cellType;
pushedFlatCellType ← pushedData.flatCellType;
};
pushedData: PushedData ← NARROW[CDProperties.GetDesignProp[design, pushedDataAtom]];
IF pushedData#
NIL
AND pushedData.root#root
THEN {
ViewerOps.DestroyViewer[pushedData.topViewer];
TerminalIO.PutRope["*** Only single selection viewer allowed per ChipNDale design\n"];
pushedData ← NIL;
};
IF pushedData=
NIL
THEN {
CheckForMultiple: EachSelectedFlatCellTypeProc = {
pushedCellType ← cellType;
pushedFlatCellType ← flatCellType;
quit ← alreadyCalled;
alreadyCalled ← TRUE;
};
alreadyCalled: BOOL ← FALSE;
IF EnumerateCellTypesForPushed[design, decoration, root, cutSet, CheckForMultiple]
THEN {
pushedData ← NEW[PushedDataRec];
pushedData.decoration ← decoration;
pushedData.root ← root;
pushedData.cutSet ← cutSet;
[pushedData.selectionData, pushedData.transitiveClosure] ← CreateSelectionViewer[design, pushedData, root, decoration, cutSet];
CDProperties.PutDesignProp[design, pushedDataAtom, pushedData];
RecomputePushedCellType[design, pushedData];
GetPushData[];
};
}
ELSE GetPushData[];
};
EachSelectedFlatCellTypeProc:
TYPE =
PROC [cellType: Core.CellType, flatCellType: CoreFlat.FlatCellTypeRec, instanceSelections: HashTable.Table]
RETURNS [quit:
BOOL ←
FALSE];
instanceSelectionNoInstance: NAT = LAST[NAT];
InstanceSelectionData: TYPE = REF InstanceSelectionDataRec;
InstanceSelectionDataRec:
TYPE =
RECORD [
subObject: CoreGeometry.Object ← NIL,
instance: NAT ← instanceSelectionNoInstance];
UnwindEnumeration:
ERROR =
CODE;
EnumerateCellTypesForPushed:
PROC [design:
CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet ←
NIL, eachFlatCellType: EachSelectedFlatCellTypeProc]
RETURNS [quit:
BOOL ←
FALSE] = {
EnumerateCellTypes: CoreFlat.UnboundFlatCellProc = {
instances: LIST OF CD.Instance ← NARROW[data];
matchingObject: BOOL ← CoreGeometry.HasObject[decoration, cell] AND CoreGeometry.GetObject[decoration, cell]=instances.first.ob;
IF parent#
NIL
THEN {
selectionData: InstanceSelectionData ← GetSelectionData[parent];
selectionData.subObject ← instances.first.ob;
};
IF matchingObject AND instances.rest=NIL THEN {IF eachFlatCellType[cell, flatCell, instanceSelections] THEN ERROR UnwindEnumeration[]}
ELSE
IF
NOT FixedCutSetMemberResolved[flatCell, instance, cell, cutSet]
THEN
IF cell.class=CoreClasses.recordCellClass AND matchingObject THEN CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, instances, TransformInstance]
ELSE CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, IF matchingObject THEN instances.rest ELSE instances, EnumerateCellTypes];
};
TransformInstance: CoreFlat.UnboundFlatCellProc = {
instances: LIST OF CD.Instance = NARROW [data];
possibleInst: CoreGeometry.Instance = [CoreGeometry.GetObject[decoration, instance.type], CoreGeometry.GetTrans[decoration, instance]];
IF SameCDInstance[instances.rest.first, instances.first.trans, possibleInst]
THEN {
selectionData: InstanceSelectionData ← GetSelectionData[parent];
selectionData.instance ← index;
EnumerateCellTypes[cell, target, flatCell, instance, index, parent, flatParent, instances.rest];
selectionData.instance ← instanceSelectionNoInstance;
};
};
GetSelectionData:
PROC [parent: Core.CellType]
RETURNS [selectionData: InstanceSelectionData] = {
selectionData ← NARROW[HashTable.Fetch[instanceSelections, parent].value];
IF selectionData=
NIL
THEN {
selectionData ← NEW[InstanceSelectionDataRec];
IF NOT HashTable.Insert[instanceSelections, parent, selectionData] THEN ERROR;
};
};
instanceStack: LIST OF CD.Instance ← UnwindCDStack[design];
instanceSelections: HashTable.Table ← HashTable.Create[];
EnumerateCellTypes[cell: root, data: instanceStack ! UnwindEnumeration => GOTO Quit];
EXITS Quit => quit ← TRUE;
};
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: 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];
};
quit ← CoreOps.VisitWire[root, ThisWire]
};
quit ← EnumerateSelectedInstances[design, ThisSelectedInstance];
};
EachSelectedInstanceProc:
TYPE =
PROC [selectedInstance: CoreGeometry.Instance]
RETURNS [quit:
BOOL ←
FALSE];
EnumerateSelectedInstances:
PROC [design:
CD.Design, eachInstance: EachSelectedInstanceProc]
RETURNS [quit:
BOOL ←
FALSE] = {
ThisInstance: CDCells.InstEnumerator = {
IF inst.selected
THEN {
trans: CD.Transformation ← design.actual.first.mightReplace.trans;
quit ← eachInstance[[inst.ob, [CDBasics.DeMapPoint[inst.trans.off, trans], CDBasics.DecomposeOrient[itemInWorld: inst.trans.orient, cellInWorld: trans.orient]]]];
};
};
quit ← CDCells.EnumerateInstances[design.actual.first.dummyCell.ob, ThisInstance];
};
SameCDInstance:
PROC [cdinst:
CD.Instance, trans:
CD.Transformation, instance: CoreGeometry.Instance]
RETURNS [
BOOL] = {
RETURN [
cdinst.ob=instance.obj AND
CDBasics.DeMapPoint[cdinst.trans.off, trans]=instance.trans.off AND
CDBasics.DecomposeOrient[itemInWorld: cdinst.trans.orient, cellInWorld: trans.orient]=instance.trans.orient
];
};
UnwindCDStack:
PROC [design:
CD.Design]
RETURNS [instanceStack:
LIST
OF
CD.Instance] = {
IF design.actual.rest=NIL THEN ERROR SchSimError["*** No currently pushed-in cell."];
FOR stack:
LIST
OF
CD.PushRec ← design.actual, stack.rest
WHILE stack.rest#
NIL
DO
IF stack.first.specific.changed THEN ERROR SchSimError[IO.PutFR["*** Impossible to extract stack, cell %g has been changed and not saved.", IO.rope[CDDirectory.Name[stack.first.mightReplace.ob]]]];
instanceStack ← CONS[stack.first.mightReplace, instanceStack];
ENDLOOP;
};
CDCommandOps.RegisterWithMenu[menu: $OtherProgramMenu, entry: "Schematic Simulation Value", key: $DAUserSchematicSimulationValue, proc: SchematicSimulationValue, queue: doQueue];
CDCommandOps.RegisterWithMenu[menu: $OtherProgramMenu, entry: "Schematic Simulation Add To Plot", key: $DAUserSchematicSimulationAddToPlot, proc: SchematicSimulationAddToPlot, queue: doQueue];