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; }; 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. SchematicSimulation.mesa Copyright Ó 1987 by Xerox Corporation. All rights reserved. Barth, March 20, 1987 2:34:19 pm PST DAUser SinixOps 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; }; 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. Êߘcode– "Cedar" stylešœ™K– "Cedar" style™˜EK˜šžœ!˜2šœœ˜$Kšœœ˜+Kšœœ.˜EKšœHœœœœ œ œWœ˜ßKšœ<˜<šœ œ˜Kšœ ˜ Kšœœ˜K˜—šœ œ˜Kšœœœ œ7˜sKšœ#˜#š œœœ0œœ˜TKšœJ˜JKšœ˜—Kšœ%˜%š œ œœ:œ œ˜bKšœE˜EKšœ˜—K˜—K˜—K˜K˜—KšœK˜KKšœ~˜~Kšœ˜—Kšœ˜—Kšœ˜K™—šžœ"˜6Kšœœ ˜0Kšœ œq˜—Kšœ7œ˜AKšœ ˜ KšœF˜FKšœ˜K™—šžœœ!˜8Kšœ>˜>Kšœ9˜9Kšœ˜Kšœ˜K™—šžœ˜Kšœœ5˜TKšœ œœ-˜CKšœ˜K™—šžœœ œ$˜MK˜š ž œœxœ œœœ˜³KšœœJ˜^šœœ˜šœœœ˜*Kšœœ˜Kšœ˜Kšœ#˜#Kšœ˜—Kšœw˜wšœ+˜+Kšœ"œ ˜4š œœœœ˜8K˜3Kšœ¥˜¥šœKœ˜SKšœs˜sKšœ˜K˜—KšœœœŸ?˜ZKš˜—šœ˜Kšœœœ˜Kšœ œœ˜Kšœœœœ˜šœœœ˜Kšœ œD˜jšœ9œ˜AKšœ˜Kšœœ˜ K˜ Kšœ œœ˜K˜—Kšœ˜—šœœ˜Kšœœ˜Ÿšœ˜Kšœ3˜3Kšœn˜nKšœ˜—šœ˜ Kšœœ8˜YKšœ œœU˜lšœ˜KšœK˜KKšœœ˜"Kšœ†˜†K˜—Kšœ˜——K˜—K˜—šœ˜ Kšœ/˜/Kš œœœ œ4œœœ ˜¥Kšœ˜——Kšœ˜K˜—Kš œœœœRœ˜wKšœ=œœ˜JKšœ?˜?Kš œœœœAœœ˜rKšœ œ˜Kšœ˜K™—šžœœ œ$™MK™šžœ"™2šœgœ™ošœœ™Kšœœ™ KšœO™OK™—šœ™Kšœœ™Kšœœ™Kšœ™Kšœ'™'K™—K™—Kšœ™K™—Kšœœœ™Kšœœ¢œœœœœ?™‘Kšœ œ™Kšœ™K™—š žœœ€œœœ˜¾K˜šžœ"˜0š˜Kšœ:œ˜?šœ+˜+Kšœœ-˜NKšœ œœ[œ˜†šœ˜K˜šžœ!˜/Kšœœ˜+š œ œœ:œ œ˜bšœ(œ˜0Kšœ ˜ Kšœœ˜ Kšœ˜Kšœ˜—Kšœ˜—K˜K˜—Kšœ"œ ˜4Kšœ œ˜'Kš œœœ œœœœ˜9Kšœ œ˜Kšœœœ˜Kšœ(œ2˜`šœœœ˜ KšœK˜KKšœ˜—Kšœ œ˜#Kš œ,œœ$œœœœA˜ÀKšœ(œœ[œ˜ºK˜—K˜—Kšœ^œ˜z—K˜—Kšœ2œœ˜?Kšœ-˜-Kš œœœ6œœ˜PKšœ˜K™—šžœ˜.Kšœœ˜)Kšœœ˜!K˜K˜—šžœ˜2Kšœœ˜)šœ1œ˜9KšœœAœ<œ˜­Kšœ2˜2K˜—K˜K˜—š œ#œœ%œœ œ˜–K˜—šžœœ|œ œ˜µKšœ8œ1œE˜²Kšœ˜K˜—š ž#œœ’œœ'œ˜öKšœËŸX™£šžœœxœœ#˜ÈK˜Kšœœ1˜Ešœ œœ˜Kšœ!˜!šœAœœ˜MKšœœ1œœ˜BKšœ,œ*œœœVœœ˜Çšœœ˜Kšœ?œ˜Dšœ+˜+Kšœ"œ ˜4šœœœ˜K˜šžœ˜3Kšœœ˜Kšœœ˜"š œœ$œœœ˜>Kšœœœ+˜Ašœœ˜Kšœ%˜%Kšœ ˜ Kšœœ˜—š œœœœœ˜(Kšœœœœ˜PKšœ3˜3K˜—Kšœ2˜2K˜—K˜K˜—Kšœ„˜„Kšœ8œœ˜EKšœ˜—K˜—šœ˜ K˜šžœ˜2Kšœ3˜3K˜K˜—Kšœ*˜*Kšœ%œ œ7œU˜ÅKšœ:œœ˜GK˜——K˜—Kšœœ8œœ˜IK˜—K˜K˜—K˜'Kšœ'˜'Kšœ˜K™—š œœœ*œœœ˜lK˜—šžœœ œ]œ2œœœ˜ÞK˜šžœ˜*šœ˜Kšœ˜Kšœ œ œœ ˜2Kšœ˜—K˜K˜—Kšœ œœ˜Kšœ(˜(Kšœœ˜KšœP˜PKšœ œœœj˜„Kšœ8˜8Kš œ2œ œœœT˜´Kšœ˜K™—š žœœ œ]œœ"œK˜K˜šž œœ˜Kšœœœœ&˜OKšœ%˜%Kšœ-˜-K˜—K˜Kšœœ5˜Tšœ œœœ˜1Kšœ.˜.K˜WKšœ œ˜K˜—šœ œœ˜K™šžœ"˜2Kšœ˜Kšœ"˜"Kšœ˜Kšœœ˜Kšœ˜K˜—Kšœœœ˜šœQœ˜YKšœ œ˜ Kšœ#˜#Kšœ˜Kšœ˜Kšœ˜Kšœ?˜?Kšœ,˜,Kšœ˜K˜—K˜—Kšœ˜K˜K˜—š œœœhœœœ˜®K˜—Kšœœœœ˜-Kšœœœ˜;šœœœ˜)Kšœ!œ˜%Kšœ œ ˜-K˜—šžœœœ˜ K˜—šžœœ œ]œ2œœœ˜ßK˜šžœ"˜4Kš œ œœœ œ˜.Kšœœ,œ=˜€šœœœ˜Kšœ@˜@Kšœ-˜-K˜—Kšœœœœœ6œœ˜†šœœœ=˜LKšœ(œœx˜¹Kšœ[œœœ ˜©—Kšœ˜K˜—šžœ"˜3Jš œ œœœ œ˜/Jšœ‡˜‡šœKœ˜SKšœ@˜@Kšœ˜Jšœ`˜`Kšœ5˜5J˜—K˜K˜—šžœœœ+˜aKšœœ4˜Jšœœœ˜Kšœœ˜.Kšœœ=œœ˜NK˜—K˜K˜—Kšœœœœ"˜;Kšœ9˜9KšœJœ˜UKšœœ˜Kšœ˜K™—š œœœœœœ˜YK˜—šžœœ œGœœ*œœœ˜Åšžœ˜2šžœ˜"šžœ#˜3Kšœ!˜!K˜—Kš œœœœ@œD˜¤Kšœœ˜,K˜—K˜(K˜—Kšœ@˜@Kšœ˜K™—š œœœ+œœœ˜mK˜—š žœœ œ1œœœ˜}K˜šž œ˜(šœœ˜Kšœœ9˜BKšœ¢˜¢K˜—K˜K˜—KšœR˜RKšœ˜K™—š žœœ œœ2œœ˜xšœ˜Kšœœ˜Kšœ@œ˜DKšœk˜kKšœ˜—K˜K˜—šž œœ œ œœœœ˜XKšœœœœ1˜Uš œœœœ%œ œ˜QKš œœœ œSœ7˜ÅJšœœ*˜>Kšœ˜—Kšœ˜K™——Kšœ²˜²KšœÀ˜ÀKšœ=˜=Kšœ<˜