DIRECTORY BitOps, CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDEvents, CDImports, CDOps, CDProperties, CDSequencer, CDViewer, Core, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, IntHashTable, IO, Ports, PW, RefTab, Rope, Rosemary, RosemaryUser, Sisyph, TerminalIO, TiogaButtons, ViewerClasses, ViewerOps; SchematicSimulation: CEDAR PROGRAM IMPORTS BitOps, CDBasics, CDCells, CDCommandOps, CDDirectory, CDEvents, CDImports, CDOps, CDProperties, CDSequencer, CDViewer, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, IntHashTable, IO, Ports, PW, RefTab, 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]]]]; }; 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]; GetRoseDisplay: PROC [command: CDSequencer.Command] RETURNS [display: RosemaryUser.RoseDisplay _ NIL] ~ { viewer: ViewerClasses.Viewer = CDViewer.GetViewer[command]; display2: RosemaryUser.RoseDisplay = NARROW [CDProperties.GetDesignProp[command.design, $DAUserRoseDisplay]]; IF viewer#NIL THEN display _ NARROW [ViewerOps.FetchProp[viewer, $DAUserRoseDisplay]]; IF display=NIL THEN display _ display2; }; 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 RefTab.Insert[x: enumeratedWires, key: flatWireRef, val: $Enumerated] THEN { errorMsg _ action[display, flatWireRef]; someValueFound _ TRUE; quit _ errorMsg#NIL; }; }; display: RosemaryUser.RoseDisplay = GetRoseDisplay[command]; someValueFound: BOOL _ FALSE; enumeratedWires: RefTab.Ref _ RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; IF display=NIL THEN errorMsg _ "*** No simulation active on this design/viewer." ELSE { -- normal case [] _ 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"]; }; ViewerForImportedDesign: PROC [root, import: CD.Design, display: RosemaryUser.RoseDisplay] RETURNS [viewer: ViewerClasses.Viewer _ NIL] ~ { EachCDViewer: ViewerOps.EnumProc ~ { -- find an already present viewer IF CDViewer.DesignOf[v]#import THEN RETURN; IF display=ViewerOps.FetchProp[v, $DAUserRoseDisplay] THEN viewer _ v; }; ViewerOps.EnumerateViewers[EachCDViewer]; -- find an already correct viewer IF viewer#NIL THEN RETURN; -- found it viewer _ CDViewer.CreateViewer[import, FALSE]; -- create the viewer ViewerOps.AddProp[viewer, $DAUserRoseDisplay, display]; -- add magic property }; FindRootDesign: PROC [display: RosemaryUser.RoseDisplay] RETURNS [root: CD.Design] ~ { EachCDViewer: ViewerOps.EnumProc ~ { -- find simulation source design design: CD.Design = CDViewer.DesignOf[v]; IF design=NIL THEN RETURN; IF display=CDProperties.GetDesignProp[design, $DAUserRoseDisplay] THEN root _ design; }; root _ NIL; IF display#NIL THEN ViewerOps.EnumerateViewers[EachCDViewer]; }; GetIconFor: PROC [design: CD.Design, name: Rope.ROPE] RETURNS [target: Rope.ROPE] ~ { obj: CD.Object = CDDirectory.Fetch[design, name]; IF obj=NIL THEN RETURN [NIL]; target _ NARROW[CDProperties.GetProp[obj, $IconFor]]; IF target=NIL THEN target _ name; }; PopViewerForImport: PROC [command: CDSequencer.Command] ~ { multiple: BOOL; err: Rope.ROPE _ NIL; instance: CD.Instance; display: RosemaryUser.RoseDisplay = GetRoseDisplay[command]; rootDesign: CD.Design = FindRootDesign[display]; specific: CDImports.ImportSpecific; importedDesign: CD.Design; [instance, multiple] _ CDOps.SelectedInstance[command.design]; SELECT TRUE FROM multiple => err _ "Multiple selections"; instance=NIL => err _ "No selection"; display=NIL => err _ "No active simulation in this design"; rootDesign=NIL => err _ "Initial simulation design destroyed"; NOT CDImports.IsImport[instance.ob] => err _ "Not an import"; ENDCASE => { -- normal case (well, almost) specific _ NARROW[instance.ob.specific]; importedDesign _ specific.boundDesign; IF importedDesign=NIL THEN err _ "Import not bound yet"; }; IF err#NIL THEN {TerminalIO.PutF["\n** %g. No action.\n", IO.rope[err]]; RETURN}; CDSequencer.ExecuteCommand[comm: NEW [CDSequencer.CommandRec _ [ key: $PushNamed, design: importedDesign, ref: ViewerForImportedDesign[rootDesign, importedDesign, display], data: GetIconFor[importedDesign, specific.objectName]]]]; -- Beuark !!! }; 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: RefTab.Ref _ NIL, transitiveClosure: RefTab.Ref _ 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: RefTab.Ref _ NIL, transitiveClosure: RefTab.Ref _ NIL] = { RecordEachAncestor: EachLeastCommonObjectAncestorProc = { resolveData: ResolveData _ NARROW[RefTab.Fetch[selectionData, ancestor].val]; instanceData: InstanceData _ NIL; IF resolveData=NIL THEN { resolveData _ NEW[ResolveDataRec]; IF NOT RefTab.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 _ RefTab.Create[]; transitiveClosure _ EnumerateLeastCommonObjectAncestors[root, decoration, RecordEachAncestor, cutSet]; 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 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[" ", 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; }; 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: RefTab.Ref _ NARROW[RefTab.Fetch[ pushedData.transitiveClosure, rct[i].type].val]; IF RefTab.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[RefTab.Fetch[pushedData.selectionData, cell].val]; 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 RefTab.Pairs[pushedData.selectionData, SetDoesNotMatter] THEN ERROR; BuildFlatCell[cell: pushedData.root, instances: instanceStack]; IF pushedData.errorMessage=NIL THEN IF RefTab.Pairs[pushedData.selectionData, DisplayDoesNotMatter] THEN ERROR; EXITS Quit => NULL; }; FilterUsingSelectionData: PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, selectionData: RefTab.Ref, instanceSelections: RefTab.Ref] RETURNS [pass: BOOL _ FALSE] = { CheckSelection: CoreFlat.UnboundFlatCellProc = { SELECT TRUE FROM CoreFlat.FlatCellTypeEqualRec[flatCell, target] => pass _ TRUE; cell.class=CoreClasses.recordCellClass => { resolveData: ResolveData _ NARROW[RefTab.Fetch[selectionData, cell].val]; 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[RefTab.Fetch[instanceSelections, cell].val]; 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 RefTab.Pairs[selectionData, SetDoesNotMatter] THEN ERROR; CheckSelection[cell: root, target: flatCell]; IF pass THEN IF RefTab.Pairs[selectionData, DisplayDoesNotMatter] THEN ERROR; }; 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; }; }; 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: 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, $DAUserIgnoreForSelection]=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 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: 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; 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]; [] _ 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; }; }; transitiveClosure _ RefTab.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: RefTab.Ref] 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[RefTab.Fetch[instanceSelections, parent].val]; IF selectionData=NIL THEN { selectionData _ NEW[InstanceSelectionDataRec]; IF NOT RefTab.Insert[instanceSelections, parent, selectionData] THEN ERROR; }; }; instanceStack: LIST OF CD.Instance _ UnwindCDStack[design]; instanceSelections: RefTab.Ref _ RefTab.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[PW.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]; CDCommandOps.RegisterWithMenu[menu: $OtherProgramMenu, entry: "Pop viewer for import", key: $DAUserSchematicSimulationPopViewer, proc: PopViewerForImport, 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, April 2, 1987 12:16:42 pm PST Last Edited by: Gasbarro June 22, 1987 6:08:27 pm PDT Louis Monier October 1, 1987 8:42:22 pm PDT DAUser Principles CD designs from which a simulation has been started have a DAUserRoseDisplay property pointing to the RosemaryUser.Display. CD Viewers created as windows on imported designs carry the DAUserRoseDisplay property. Initial design viewers do not have the property, and imported designs do not have the property either. Respect this rule if you want to keep alive... CD access to Rosemary values Lookup on the viewer first, on the design then. Pushing into imported designs for Rosemary access Get a viewer pointing onto the imported design for the specified simulation. If creating a new viewer is required, prefix the CD caption with prefix. It is not possible to modify the viewer name on the fly as it is recomputed dynamically by CDVPrivateImpl... viewer.name _ Rope.Cat[root.name, ":", CoreOps.GetCellTypeName[display.cellType], "<-", viewer.name]; -- prefix caption ViewerOps.PaintViewer[viewer, caption, FALSE, NIL]; -- and repaint its caption Locate the design from which a simulation was initiated Return schematic name if any, or return initial name Get a Read-only Viewer pointing to the implementation of a given import and push into the schematic, or the icon if no schematic. 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 RefTab which then maps Object or CellType to $DependsOn or REF NAT. Κ@˜code– "Cedar" stylešœ™K– "Cedar" style™˜>šœœ˜Kšœ(˜(Kšœ œ˜%Kšœœ0˜;Kšœ œ0˜>Kšœ:˜=šœ ˜*Kšœ œ˜(Kšœ&˜&Kšœœœ˜8Kšœ˜——Kš œœœ+œ œ˜Qšœ!œ˜@Kšœ˜Kšœ˜Kšœ7‘ œ˜BKšœ:  ˜G—K˜———šž™Jšœ œœ˜'šœœœ˜Jšœœ˜Jšœ#œ˜'Jšœ+œ˜/Jšœœ˜Jšœœ˜Jšœ œœ˜J˜—Jšœœœ˜)šœœœ˜ Jšœœ œ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œœœ K˜xJšœœœœ ˜=Jšœ#œ˜(J˜—Jšœœ˜)Jšœ œœ˜%šœœœ˜Jšœ"œ˜&Jšœ&œ˜*Jšœœ˜Jšœœ˜Jšœœ˜ Jšœ œ˜$Jšœœ˜Jšœ,˜,Jšœœœ˜J˜—šžœœ œuœœœ"œ˜σK˜šžœ'˜9Kšœœ,˜MKšœœ˜!šœ œœ˜Kšœœ˜"Kšœœ5œœ˜FKšœ˜Kšœ œ˜)Kšœ1˜1K˜—Kšœœ?˜Tšœœœ˜Kšœœ˜$Kšœ˜Kšœ%˜%Kšœ#˜#Kšœ!˜!KšœœGœœ˜XK˜—šœœœœ œœ:œ œ˜uKšœœœ˜"Kšœœœ˜MKšœ˜—šœœœœœœ0œœ˜eKšœœœ˜Kšœœœ˜GKšœ˜—K˜K˜—šœ<˜˜EK˜šžœ!˜2šœœ˜$Kšœœ˜+Kšœœ.˜EKšœHœœœœ œ œWœ˜ίKšœ<˜<šœ œ˜Kšœ ˜ Kšœœ˜K˜—šœ œ˜Kšœœœ œ7˜sKšœ#˜#š œœœ0œœ˜TKšœJ˜JKšœ˜—Kšœ%˜%š œ œœ:œ œ˜bKšœœ˜˜>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šœœ?˜`šœ6œ˜>Kšœ˜Kšœœ˜ K˜ Kšœ œœ˜K˜—Kšœ˜—šœœ˜Kšœœ˜Ÿšœ˜Kšœ3˜3Kšœn˜nKšœ˜—šœ˜ Kšœœ3˜TKšœ œœU˜lšœ˜KšœK˜KKšœœ˜"Kšœ†˜†K˜—Kšœ˜——K˜—K˜—šœ˜ Kšœ/˜/Kš œœœ œ4œœœ ˜₯Kšœ˜——Kšœ˜K˜—Kš œœœœRœ˜wKšœ:œœ˜GKšœ?˜?Kš œœœœ>œœ˜oKšœ œ˜Kšœ˜K™—šžœœ œ$™MK™šžœ"™2šœgœ™ošœœ™Kšœœ™ KšœO™OK™—šœ™Kšœœ™Kšœœ™Kšœ™Kšœ'™'K™—K™—Kšœ™K™—Kšœœœ™Kšœœ’œœœœœ?™‘Kšœ œ™Kšœ™K™—š žœœvœœœ˜΄K˜šžœ"˜0š˜Kšœ:œ˜?šœ+˜+Kšœœ(˜IKšœ œœ[œ˜†šœ˜K˜šžœ!˜/Kšœœ˜+š œ œœ:œ œ˜bšœ(œ˜0Kšœ ˜ Kšœœ˜ Kšœ˜Kšœ˜—Kšœ˜—K˜K˜—Kšœ"œ ˜4Kšœ œ˜'Kš œœœ œœœœ˜9Kšœ œ˜Kšœœœ˜Kšœ(œ-˜[šœœœ˜ KšœK˜KKšœ˜—Kšœ œ˜#Kš œ,œœ$œœœœA˜ΐKšœ(œœ[œ˜ΊK˜—K˜—Kšœ^œ˜z—K˜—Kšœ/œœ˜Kšœ˜—Kšœ˜K™——Kšœ²˜²Kšœΐ˜ΐKšœ«˜«Kšœ=˜=Kšœ<˜