<> <> <> DIRECTORY BitOps, CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDEvents, CDProperties, CDSequencer, Core, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, HashTable, IntHashTable, IO, Ports, Rope, Rosemary, RosemaryUser, Sisyph, TerminalIO, TiogaButtons, ViewerClasses, ViewerOps; SchematicSimulation: CEDAR PROGRAM IMPORTS BitOps, CDBasics, CDCells, CDCommandOps, CDDirectory, CDEvents, CDProperties, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, HashTable, IntHashTable, IO, Ports, Rope, Rosemary, RosemaryUser, Sisyph, TerminalIO, TiogaButtons, ViewerOps = BEGIN SchSimError: ERROR [msg: Rope.ROPE] = CODE; SchSimDebug: BOOL _ FALSE; <> SchematicSimulationValue: PROC [command: CDSequencer.Command] = { PrintAValue: SelectedFlatWireActionProc = { TerminalIO.PutF[ "Value[%g] = %g\n", IO.rope[CoreFlat.WirePathRope[display.cellType, flatWire^]], IO.rope[Ports.LSToRope[ Rosemary.WireValue[display.simulation, flatWire], CoreOps.WireBits[flatWire.wire]]]]; }; DoForSelectedFlatWire[command, PrintAValue]; }; SchematicSimulationAddToPlot: PROC [command: CDSequencer.Command] = { AddAWire: SelectedFlatWireActionProc = { errorMsg _ RosemaryUser.AddWireToPlot[display, flatWire]; }; DoForSelectedFlatWire[command, AddAWire]; }; SelectedFlatWireActionProc: TYPE = PROC [display: RosemaryUser.RoseDisplay, flatWire: CoreFlat.FlatWire] RETURNS [errorMsg: Rope.ROPE _ NIL]; DoForSelectedFlatWire: PROC [command: CDSequencer.Command, action: SelectedFlatWireActionProc] = { errorMsg: Rope.ROPE; { ENABLE SchSimError, CoreFlat.PathError => {errorMsg _ msg; GOTO Done}; DoAValue: EachSelectedFlatWireProc = { flatWireRef: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; flatWireRef^ _ selectedFlatWire; IF HashTable.Insert[table: enumeratedWires, key: flatWireRef, value: $Enumerated] THEN { errorMsg _ action[display, flatWireRef]; someValueFound _ TRUE; quit _ errorMsg#NIL; }; }; display: RosemaryUser.RoseDisplay _ NARROW [CDProperties.GetDesignProp[command.design, $DAUserRoseDisplay]]; someValueFound: BOOL _ FALSE; enumeratedWires: HashTable.Table _ HashTable.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; [] _ EnumerateSelectedFlatWires[command.design, Sisyph.mode.decoration, display.cellType, display.cutSet, DoAValue]; IF NOT someValueFound THEN errorMsg _ "*** No such wire(s) found."; EXITS Done => NULL; }; IF errorMsg#NIL THEN TerminalIO.PutRopes[errorMsg, "\n"]; }; <> 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; }; <<>> <> <<>> <> <> <> <> <> <<}>> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> <> < {pushedData.errorMessage _ msg; GOTO Quit}] THEN IF NOT alreadyCalled THEN pushedData.errorMessage _ "*** Selection data picks no cell.";>> < 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] = { <> 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]; CDEvents.RegisterEventProc[event: $AfterPush, proc: PushPop]; CDEvents.RegisterEventProc[event: $AfterPop, proc: PushPop]; END. <<>>