DIRECTORY CD, CDBasics, CDBasicsInline, CDCells, CDCellsInteractions, CDDirectory, CDEvents, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDViewer, Containers, Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, IntHashTable, IO, PipalCore, PipalCoreCDUser, PipalExtractOps, PipalSinix, PW, RefTab, Rope, TerminalIO, TiogaButtons, ViewerClasses, ViewerOps; PipalCoreCDUserImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDBasicsInline, CDCells, CDCellsInteractions, CDDirectory, CDEvents, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDViewer, Containers, CoreClasses, CoreFlat, CoreOps, CoreProperties, IntHashTable, IO, PipalCore, PipalExtractOps, PW, RefTab, Rope, TerminalIO, TiogaButtons, ViewerOps EXPORTS PipalCoreCDUser SHARES CDImports = BEGIN OPEN PipalCoreCDUser; CoreCDUserError: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; EnumerateSelectedCellTypes: PUBLIC PROC [design: PipalUI.Design, eachRootCellType: EachRootCellTypeProc, mode: PipalSinix.Mode _ NIL] RETURNS [quit: BOOL _ FALSE] = { originalSelectedInstances: CD.InstanceList _ CDInstances.OnlySelected[CDOps.InstList[design]]; IF originalSelectedInstances=NIL THEN TerminalIO.PutRope["PipalCoreCDUser: Nothing selected\n"] ELSE FOR instances: CD.InstanceList _ originalSelectedInstances, instances.rest WHILE instances#NIL DO thisMode: PipalSinix.Mode _ IF mode=NIL THEN PipalExtractOps.GetExtractMode[instances.first.ob] ELSE mode; -- JMF: added parameter to GetExtractMode root: Core.CellType _ PipalExtractOps.ExtractCDInstanceCellTypeAndReport[instances.first, design, thisMode]; IF root#NIL THEN { SetDesignRootCellType[design, root]; SetRootCellTypeDecoration[root, thisMode.decoration]; IF (quit _ eachRootCellType[root]) THEN EXIT; }; ENDLOOP; }; designRootCellTypeProp: ATOM = $CoreCDUserDesignRootCellType; designImporterDesignProp: ATOM = $CoreCDUserDesignImporterDesign; rootCellTypeDecorationProp: ATOM = $CoreCDUserRootCellTypeDecoration; SetDesignRootCellType: PUBLIC PROC [design: PipalUI.Design, root: Core.CellType] = { CDProperties.PutDesignProp[design, designRootCellTypeProp, root]; CDProperties.PutDesignProp[design, designImporterDesignProp, NIL]; FOR cl: LIST OF CDImports.Cache _ CDImports.GetCacheList[design].list, cl.rest UNTIL cl=NIL DO IF cl.first.importee#NIL THEN SetImporterDesign[cl.first.importee, design]; -- JMF: Beware ENDLOOP; CoreProperties.PutCellTypeProp[root, designRootCellTypeProp, design]; CDProperties.PutDesignProp[design, transitiveClosureCache, NIL]; -- this should be done on pop which selects replace or new or during edit at top level but I don't know of any CD facilities to do so SetImporterLabels[design]; }; GetDesignRootCellType: PUBLIC PROC [design: PipalUI.Design] RETURNS [root: Core.CellType] = { IF GetImporterDesign[design]#NIL THEN design _ GetImporterDesign[design]; root _ NARROW[CDProperties.GetDesignProp[design, designRootCellTypeProp]]; }; GetRootCellTypeDesign: PUBLIC PROC [root: Core.CellType] RETURNS [design: PipalUI.Design] = { design _ NARROW[CoreProperties.GetCellTypeProp[root, designRootCellTypeProp]]; }; SetImporterDesign: PUBLIC PROC [importee: PipalUI.Design, importer: PipalUI.Design] = { CDProperties.PutDesignProp[importee, designRootCellTypeProp, NIL]; CDProperties.PutDesignProp[importee, designImporterDesignProp, importer]; SetImporteeLabels[importee]; FOR cl: LIST OF CDImports.Cache _ CDImports.GetCacheList[importee].list, cl.rest UNTIL cl=NIL DO SetImporterDesign[cl.first.importee, importer]; ENDLOOP; }; GetImporterDesign: PUBLIC PROC [importee: PipalUI.Design] RETURNS [importer: PipalUI.Design] = { importer _ NARROW[CDProperties.GetDesignProp[importee, designImporterDesignProp]]; }; SetRootCellTypeDecoration: PUBLIC PROC [root: Core.CellType, decoration: PipalCore.Decoration] = { CoreProperties.PutCellTypeProp[root, rootCellTypeDecorationProp, decoration]; }; GetRootCellTypeDecoration: PUBLIC PROC [root: Core.CellType] RETURNS [decoration: PipalCore.Decoration] = { decoration _ NARROW[CoreProperties.GetCellTypeProp[root, rootCellTypeDecorationProp]]; }; FindDesignAndDecoration: PROC [root: Core.CellType, design: PipalUI.Design, decoration: PipalCore.Decoration] RETURNS [outDesign: PipalUI.Design, outDecoration: PipalCore.Decoration] = { outDesign _ IF design=NIL THEN GetRootCellTypeDesign[root] ELSE design; IF outDesign=NIL THEN ERROR CoreCDUserError["No design associated with root cell type"]; outDecoration _ IF decoration=NIL THEN GetRootCellTypeDecoration[root] ELSE decoration; IF outDecoration=NIL THEN ERROR CoreCDUserError["No decoration associated with root cell type"]; }; SetImporterLabels: PROC [importer: PipalUI.Design] = { label: Rope.ROPE _ GetImporterLabel[importer]; FOR viewers: CDViewer.ViewerList _ CDViewer.ViewersOf[importer], viewers.rest UNTIL viewers=NIL DO ViewerOps.SetViewer[viewer: viewers.first, data: label, op: $Label]; ENDLOOP; }; GetImporterLabel: PROC [importer: PipalUI.Design] RETURNS [label: Rope.ROPE _ NIL] = { root: Core.CellType _ GetDesignRootCellType[importer]; IF root#NIL THEN { rootName: Rope.ROPE _ CoreOps.GetCellTypeName[root]; IF rootName=NIL THEN rootName _ ""; label _ Rope.Cat[importer.name, ": ", rootName]; }; }; SetImporteeLabels: PROC [importee: PipalUI.Design] = { label: Rope.ROPE _ GetImporteeLabel[importee]; FOR viewers: CDViewer.ViewerList _ CDViewer.ViewersOf[importee], viewers.rest UNTIL viewers=NIL DO ViewerOps.SetViewer[viewer: viewers.first, data: label, op: $Label]; ENDLOOP; }; GetImporteeLabel: PROC [importee: PipalUI.Design] RETURNS [label: Rope.ROPE _ NIL] = { importer: PipalUI.Design _ GetImporterDesign[importee]; IF importer#NIL THEN { importerLabel: Rope.ROPE _ GetImporterLabel[importer]; IF importerLabel#NIL THEN label _ Rope.Cat[importee.name, " -> ", importerLabel]; }; }; GetDesignLabel: PUBLIC PROC [design: PipalUI.Design] RETURNS [label: Rope.ROPE _ NIL] = { label _ IF GetImporterDesign[design]=NIL THEN GetImporterLabel[design] ELSE GetImporteeLabel[design]; }; HighlightFlatCellType: PUBLIC PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL, viewer: ViewerClasses.Viewer _ NIL, clearFirst: BOOL _ TRUE] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatCell].cellType; transform: CD.Transformation _ []; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, transform] _ FindFlatCellTransform[design, decoration, root, flatCell, cell]; IF clearFirst THEN PipalUI.HighlightDesign[design]; PipalUI.HighlightDesign[design, transform, PipalCore.GetObject[decoration, cell], viewer, GetDesignLabel[design]]; }; HighlightFlatWire: PUBLIC PROC [root: Core.CellType, flatWire: CoreFlat.FlatWireRec, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL, viewer: ViewerClasses.Viewer _ NIL, clearFirst: BOOL _ TRUE] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatWire.flatCell].cellType; trans: Pipal.Transformation; object: Pipal.Object; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, trans] _ FindFlatCellTransform[design, decoration, root, flatWire.flatCell, cell]; IF clearFirst THEN PipalUI.HighlightDesign[design]; PipalUI.HighlightDesign[design, trans, PipalCore.GetAllGeometry[decoration, cell, flatWire.wire], viewer, GetDesignLabel[design]]; }; FindFlatCellTransform: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType] RETURNS [cellDesign: PipalUI.Design, transform: CD.Transformation _ []] = { EachCDInstance: PROC [instance: CD.Instance] = { transform _ CDBasics.ComposeTransform[instance.trans, transform]; }; cellDesign _ AllTogetherNow[design, decoration, root, flatCell, cell, EachCDInstance]; }; SelectFlatCellType: PUBLIC PROC [root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatCell].cellType; trans: Pipal.Transformation; lastObject: Pipal.Object; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, trans, lastObject] _ PushToDesire[design, decoration, root, flatCell, cell]; IF PipalUI.SelectInstance[design, trans, lastObject] THEN CDOps.Redraw[design]; -- ERROR if not done? (BS) }; SelectFlatWire: PUBLIC PROC [root: Core.CellType, flatWire: CoreFlat.FlatWireRec, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatWire.flatCell].cellType; trans: Pipal.Transformation; lastObject: Pipal.Object; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, trans, lastObject] _ PushToDesire[design, decoration, root, flatWire.flatCell, cell]; IF PipalUI.PushInstance[design, trans, lastObject] THEN { SelectParents: PROC [parent: Core.Wire] RETURNS [yes: BOOL _ FALSE] = { TurnOnSelected: PipalInt.EachChildProc = { [] _ PipalUI.SelectInstance[design, PipalInt.Compose[transform, transformation], child]; }; TurnOnWire: CoreOps.EachWireProc = { [] _ PipalMos.EnumerateAtomic[IF public THEN PipalCore.GetPort[decoration, wire] ELSE PipalCore.GetGeometry[decoration, wire], TurnOnSelected]; yes _ TRUE; }; IF parent=flatWire.wire THEN [] _ CoreOps.VisitWire[parent, TurnOnWire]; ELSE FOR wi: NAT IN [0 .. parent.size) DO IF SelectParents[parent[wi]] THEN [] _ TurnOnWire[parent]; ENDLOOP; }; public: BOOL _ cell.class#CoreClasses.recordCellClass; [] _ SelectParents[cell.public]; IF cell.class=CoreClasses.recordCellClass THEN [] _ SelectParents[NARROW[cell.data, CoreClasses.RecordCellType].internal]; CDOps.Redraw[design]; } ELSE ERROR CoreCDUserError["PipalCoreCDUser: Push failed"]; }; PushToDesire: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType] RETURNS [cellDesign: PipalUI.Design, trans: Pipal.Transformation _ [], lastObject: Pipal.Object] = { EachCDInstance: PROC [instance: CD.Instance] = { instanceList _ CONS[instance, instanceList]; }; instanceList: LIST OF CD.Instance _ NIL; reversed: LIST OF CD.Instance _ NIL; cellDesign _ AllTogetherNow[design, decoration, root, flatCell, cell, EachCDInstance]; lastObject _ instanceList.first; -- needs CDToP! instanceList _ instanceList.rest; CDCellsInteractions.PopToTopLevel[cellDesign]; FOR il: LIST OF CD.Instance _ instanceList, il.rest UNTIL il=NIL DO reversed _ CONS[il.first, reversed]; ENDLOOP; FOR il: LIST OF CD.Instance _ reversed, il.rest UNTIL il=NIL DO trans _ PipalInt.Compose[trans, il.first.trans]; -- needs CDToP! IF NOT PipalUI.PushInstance[cellDesign, trans, il.first.ob]] THEN ERROR CoreCDUserError["PipalCoreCDUser: Push failed"]; ENDLOOP; CDOps.DeselectAll[cellDesign]; }; AllTogetherNow: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType, eachInstance: PROC [instance: CD.Instance]] RETURNS [cellDesign: PipalUI.Design] = { IF PipalCore.HasObject[decoration, cell] THEN { topInstances: PipalUI.TopInstanceLists _ PipalUI.GetTopInstances[design]; found: BOOL _ FALSE; [cellDesign, found] _ FindInstances[ObjectTransitiveClosure[topInstances], topInstances, ListObjectsAndTransforms[decoration, root, flatCell], PipalCore.GetObject[decoration, cell], eachInstance]; IF NOT found THEN ERROR CoreCDUserError["PipalCoreCDUser: Cell type object is not reachable"]; } ELSE ERROR CoreCDUserError["PipalCoreCDUser: Cell type to be used for selection or highlight has no object"]; }; FindInstances: PROC [closure: RefTab.Ref, instances: PipalUI.TopInstanceLists, searchList: LIST OF REF ANY, requiredObject: CD.Object, eachInstance: PROC [instance: CD.Instance]] RETURNS [cellDesign: PipalUI.Design, found: BOOL _ FALSE] = { UNTIL searchList=NIL DO FOR designInstances: PipalUI.TopInstanceLists _ instances, designInstances.rest UNTIL designInstances=NIL DO cellDesign _ designInstances.first.design; FOR topInstances: CD.InstanceList _ designInstances.first.instances, topInstances.rest UNTIL topInstances=NIL DO cdObject: CD.Object _ topInstances.first.ob; coreObject: CD.Object _ NARROW[searchList.first]; IF cdObject=coreObject THEN { -- BS: test used to be more sophisticated! reachableFromTop: RefTab.Ref _ NARROW[RefTab.Fetch[closure, cdObject].val]; IF reachableFromTop#NIL AND RefTab.Fetch[reachableFromTop, requiredObject].found THEN { eachInstance[topInstances.first]; DO IF cdObject#NARROW[searchList.first] THEN RETURN; -- BS: test used to be more sophisticated! IF searchList.rest=NIL THEN EXIT; searchList _ searchList.rest; UNTIL CDCells.IsCell[cdObject] DO IF NOT cdObject.class.composed THEN RETURN; cdObject _ CDDirectory.Expand1[cdObject].new; ENDLOOP; WITH searchList.first SELECT FROM refTrans: REF CD.Transformation => { Check: CDCells.InstEnumerator = { quit _ inst.ob=NARROW[searchList.first] AND refTrans^=inst.trans; -- BS: test used to be more sophisticated! IF quit THEN { eachInstance[inst]; cdObject _ inst.ob; }; }; searchList _ searchList.rest; IF searchList=NIL OR NOT CDCells.EnumerateInstances[cdObject, Check] THEN RETURN; }; coreObject: CD.Object => { One: CDCells.InstEnumerator = { IF inst.ob=NARROW[searchList.first] THEN { -- BS: test used to be more sophisticated! quit _ oneFound; oneFound _ TRUE; eachInstance[inst]; cdObject _ inst.ob; }; }; oneFound: BOOL _ FALSE; IF CDCells.EnumerateInstances[cdObject, One] THEN RETURN; }; ENDCASE; ENDLOOP; found _ TRUE; RETURN; }; }; ENDLOOP; ENDLOOP; searchList _ searchList.rest; IF searchList#NIL AND ISTYPE[searchList.first, REF CD.Transformation] THEN searchList _ searchList.rest; ENDLOOP; }; ListObjectsAndTransforms: PROC [decoration: PipalCore.Decoration, root: Core.CellType, flatCellType: CoreFlat.FlatCellTypeRec] RETURNS [list: LIST OF REF ANY _ NIL]= { ObjectInstanceScan: CoreFlat.UnboundFlatCellProc = { CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, ObjectInstanceScan]; IF PipalCore.HasObject[decoration, cell] THEN list _ CONS[PipalCore.GetObject[decoration, cell], list]; IF instance#NIL AND cell=instance.type AND PipalCore.HasTrans[decoration, instance] THEN list _ CONS[NEW[PipalCore.Transformation _ PipalCore.GetTrans[decoration, instance]], list]; }; ObjectInstanceScan[cell: root, target: flatCellType]; }; transitiveClosureCache: ATOM = $CoreCDUserTransitiveClosureCache; ObjectTransitiveClosure: PROC [topInstances: PipalUI.TopInstanceLists] RETURNS [closure: RefTab.Ref] = { ComputeReachableObjects: PROC [design: PipalUI.Design, object: CD.Object] RETURNS [objects: RefTab.Ref _ NIL] = { objects _ NARROW[RefTab.Fetch[closure, object].val]; IF objects=NIL AND NOT CDRects.IsSimpleRect[object] THEN { objects _ RefTab.Create[]; IF NOT RefTab.Insert[objects, object, design] THEN ERROR; IF object.class.composed THEN { CombineObjects: PROC [subDesign: PipalUI.Design, subObject: CD.Object] = { InsertObject: RefTab.EachPairAction = { [] _ RefTab.Insert[objects, key, val]; }; subObjects: RefTab.Ref _ ComputeReachableObjects[subDesign, subObject]; IF subObjects#NIL THEN [] _ RefTab.Pairs[subObjects, InsertObject]; }; IF CDCells.IsCell[object] THEN { InsertInstances: CDCells.InstEnumerator = { CombineObjects[design, inst.ob]; }; [] _ CDCells.EnumerateInstances[object, InsertInstances]; } ELSE CombineObjects[IF CDImports.IsImport[object] THEN NARROW[object.specific, CDImports.ImportSpecific].boundDesign ELSE design, CDDirectory.Expand1[object].new]; }; IF NOT RefTab.Insert[closure, object, objects] THEN ERROR; }; }; closure _ NARROW[CDProperties.GetDesignProp[topInstances.first.design, transitiveClosureCache]]; IF closure=NIL THEN { closure _ RefTab.Create[]; FOR designs: PipalUI.TopInstanceLists _ topInstances, designs.rest UNTIL designs=NIL DO FOR designTopInstances: CD.InstanceList _ designs.first.instances, designTopInstances.rest UNTIL designTopInstances=NIL DO [] _ ComputeReachableObjects[designs.first.design, designTopInstances.first.ob]; ENDLOOP; ENDLOOP; CDProperties.PutDesignProp[topInstances.first.design, transitiveClosureCache, closure]; }; }; ignoreMeProp: PUBLIC ATOM _ $DAUserIgnoreForSelection; -- Fix CellLibraries some day to have this atom correspond to the package in which PipalCoreCDUser is contained. EnumerateSelectedFlatWires: PUBLIC PROC [root: Core.CellType, eachSelectedFlatWire: EachSelectedFlatWireProc, cutSet: CoreFlat.CutSet _ NIL, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] RETURNS [quit: BOOL _ FALSE] = { ThisSelectedWire: EachSelectedWireProc = { quit _ eachSelectedFlatWire[[ flatCell: flatCell, wireRoot: IF publicWire THEN public ELSE internal, wire: selectedWire]]; }; publicWire: BOOL _ FALSE; cellType: Core.CellType _ NIL; flatCell: CoreFlat.FlatCellTypeRec _ []; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [cellType, flatCell] _ FlatCellTypeFromPushed[design, decoration, root, cutSet]; publicWire _ cellType.class#CoreClasses.recordCellClass; quit _ EnumerateSelectedWires[design, decoration, IF publicWire THEN cellType.public ELSE NARROW[cellType.data, CoreClasses.RecordCellType].internal, publicWire, ThisSelectedWire]; }; EachSelectedWireProc: TYPE = PROC [selectedWire: Core.Wire] RETURNS [quit: BOOL _ FALSE]; EnumerateSelectedWires: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.Wire, public: BOOL _ FALSE, eachSelectedWire: EachSelectedWireProc] RETURNS [quit: BOOL _ FALSE] = { ThisSelectedInstance: PipalInt.EachChildProc = { ThisWire: CoreOps.EachWireProc = { IF NOT PipalUI.Contains[IF public THEN PipalCore.GetPort[decoration, wire] ELSE PipalCore.Getgeometry[decoration, wire], transformation, child] THEN RETURN; quit _ eachSelectedWire[wire]; someMatch _ TRUE; }; someMatch: BOOL _ FALSE; quit _ CoreOps.VisitWire[root, ThisWire]; IF NOT someMatch THEN ERROR CoreCDUserError["PipalCoreCDUser: Some selected instance does not correspond to any wire"]; }; quit _ PipalUI.EnumerateSelectedObjects[design, ThisSelectedInstance]; }; EnumerateSelectedFlatCells: PUBLIC PROC [root: Core.CellType, eachSelectedFlatCell: EachSelectedFlatCellProc, cutSet: CoreFlat.CutSet _ NIL, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] RETURNS [quit: BOOL _ FALSE] = { [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; IF design.actual.rest=NIL THEN { ThisSelectedInstance: PipalUI.EachSelectedProc = { errorMessage: Rope.ROPE _ NIL; flatCellType: CoreFlat.FlatCellTypeRec _ []; [errorMessage,,flatCellType] _ BuildFlatCell[cell: root, instances: LIST[object], pushData: pushData]; IF errorMessage#NIL THEN ERROR CoreCDUserError[errorMessage]; quit _ eachSelectedFlatCell[flatCellType] }; pushData: DesignPushData _ GetPushData[design, decoration, root, cutSet]; quit _ PipalUI.EnumerateSelectedObjects[design, ThisSelectedInstance]; } ELSE { SelectedCellType: EachSelectedCellInstanceProc = { quit _ eachSelectedFlatCell[[CoreFlat.ExtendPath[flatCell.path, selectedCellInstance, rct], 0]]; }; cellType: Core.CellType _ NIL; flatCell: CoreFlat.FlatCellTypeRec _ []; rct: CoreClasses.RecordCellType _ NIL; [cellType, flatCell] _ FlatCellTypeFromPushed[design, decoration, root, cutSet]; rct _ NARROW[cellType.data]; -- All pushed in objects must be record cells so this must succeed quit _ EnumerateSelectedCellInstances[design, decoration, rct, SelectedCellType]; }; }; EachSelectedCellInstanceProc: TYPE = PROC [selectedCellInstance: NAT] RETURNS [quit: BOOL _ FALSE]; EnumerateSelectedCellInstances: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, rct: CoreClasses.RecordCellType, eachSelectedCellInstance: EachSelectedCellInstanceProc] RETURNS [quit: BOOL _ FALSE] = { ThisSelectedInstance: PipalExtractOps.EachSelectedProc = { FOR i: NAT IN [0..rct.size) DO IF PipalCore.HasTrans[decoration, rct[i]] AND PipalCore.HasObject[decoration, rct[i].type] AND PipalUI.SameInstances[PipalCore.GetTrans[decoration, rct[i]], PipalCore.GetObject[decoration, rct[i].type], transformation, object] THEN { quit _ eachSelectedCellInstance[i]; EXIT; }; REPEAT FINISHED => ERROR CoreCDUserError["PipalCoreCDUser: Some selected instance does not correspond to any cell type"]; ENDLOOP; }; quit _ PipalUI.EnumerateSelectedObjects[design, ThisSelectedInstance]; }; pushDataAtom: ATOM = $CoreCDUserPushData; CellPushData: TYPE = REF CellPushDataRec; CellPushDataRec: TYPE = RECORD [ decoration: PipalCore.Decoration _ NIL, root: Core.CellType _ NIL, cutSet: CoreFlat.CutSet _ NIL, selectionData: RefTab.Ref _ NIL, transitiveClosure: RefTab.Ref _ NIL, viewer: ViewerClasses.Viewer _ NIL, doesNotMatterDesign: PipalUI.Design _ NIL, designPushData: LIST OF DesignPushData _ NIL]; DesignPushData: TYPE = REF DesignPushDataRec; DesignPushDataRec: TYPE = RECORD [ design: PipalUI.Design _ NIL, cellPushData: CellPushData _ NIL, cellType: Core.CellType _ NIL, flatCellType: CoreFlat.FlatCellTypeRec _ [], errorMessage: Rope.ROPE _ NIL]; ResolveData: TYPE = REF ResolveDataRec; ResolveDataRec: TYPE = RECORD [ cell: Core.CellType _ NIL, instanceData: IntHashTable.Table _ NIL, feedBackButton: TiogaButtons.TiogaButton _ NIL, selectedInstance: NAT _ 0, doesNotMatter: BOOL _ TRUE, struckOut: BOOL _ FALSE]; InstanceData: TYPE = REF InstanceDataRec; InstanceDataRec: TYPE = RECORD [ design: PipalUI.Design _ NIL, pushData: CellPushData _ NIL, resolve: ResolveData _ NIL, instance: NAT _ 0, objects: LIST OF PipalCore.Object _ NIL, -- only needed for debug cells: LIST OF Core.CellType _ NIL, -- only needed for debug button: TiogaButtons.TiogaButton _ NIL]; pushDebug: BOOL _ FALSE; FlatCellTypeFromPushed: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet _ NIL] RETURNS [pushedCellType: Core.CellType _ NIL, pushedFlatCellType: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] = { pushData: DesignPushData _ GetPushData[design, decoration, root, cutSet]; IF pushData.errorMessage#NIL THEN ERROR CoreCDUserError[pushData.errorMessage]; pushedCellType _ pushData.cellType; pushedFlatCellType _ pushData.flatCellType; IF pushedCellType=NIL THEN ERROR CoreCDUserError["PipalCoreCDUser: The object of the instance at the top of the push stack is not reachable from the root cell type"]; }; GetPushData: PROC [design: PipalUI.Design, decoration: PipalCore.Decoration, root: Core.CellType, cutSet: CoreFlat.CutSet _ NIL] RETURNS [pushData: DesignPushData] = { pushData _ NARROW[CDProperties.GetDesignProp[design, pushDataAtom]]; IF pushData=NIL OR (pushData#NIL AND (pushData.cellPushData.root#root OR pushData.cellPushData.decoration#decoration)) THEN { cellPushData: CellPushData _ NARROW[CoreProperties.GetCellTypeProp[root, pushDataAtom]]; IF cellPushData=NIL OR (cellPushData#NIL AND (cellPushData.root#root OR cellPushData.decoration#decoration)) THEN { IF pushData#NIL AND pushData.cellPushData.viewer#NIL THEN ViewerOps.DestroyViewer[pushData.cellPushData.viewer]; cellPushData _ CreatePushData[design, root, decoration, cutSet]; CoreProperties.PutCellTypeProp[root, pushDataAtom, cellPushData]; }; pushData _ CreateDesignPushData[design, cellPushData]; RecomputePushedCellType[pushData]; } ELSE IF pushData.cellPushData.doesNotMatterDesign#design THEN RecomputePushedCellType[pushData]; }; CreateDesignPushData: PROC [design: PipalUI.Design, cellPushData: CellPushData] RETURNS [pushData: DesignPushData] = { pushData _ NEW[DesignPushDataRec]; pushData.design _ design; pushData.cellPushData _ cellPushData; cellPushData.designPushData _ CONS[pushData, cellPushData.designPushData]; CDProperties.PutDesignProp[design, pushDataAtom, pushData]; }; CreatePushData: PROC [design: PipalUI.Design, root: Core.CellType, decoration: PipalCore.Decoration, cutSet: CoreFlat.CutSet _ NIL] RETURNS [pushData: CellPushData] = { RecordEachAncestor: EachLeastCommonObjectAncestorProc = { resolveData: ResolveData _ NARROW[RefTab.Fetch[pushData.selectionData, ancestor].val]; instanceData: InstanceData _ NIL; IF resolveData=NIL THEN { resolveData _ NEW[ResolveDataRec]; IF NOT RefTab.Insert[pushData.selectionData, ancestor, resolveData] THEN ERROR; resolveData.cell _ ancestor; resolvers _ CONS[resolveData, resolvers]; resolveData.instanceData _ IntHashTable.Create[]; }; instanceData _ NARROW[IntHashTable.Fetch[resolveData.instanceData, instance].value]; IF instanceData=NIL THEN { instanceData _ NEW[InstanceDataRec]; instanceData.design _ design; instanceData.pushData _ pushData; instanceData.resolve _ resolveData; instanceData.instance _ instance; IF NOT IntHashTable.Insert[resolveData.instanceData, instance, instanceData] THEN ERROR; }; IF object#NIL THEN FOR objects: LIST OF PipalCore.Object _ instanceData.objects, objects.rest UNTIL objects=NIL DO IF objects.first=object THEN EXIT; REPEAT FINISHED => instanceData.objects _ CONS[object, instanceData.objects]; ENDLOOP; IF cell#NIL THEN FOR cells: LIST OF Core.CellType _ instanceData.cells, cells.rest UNTIL cells=NIL DO IF cells.first=cell THEN EXIT; REPEAT FINISHED => instanceData.cells _ CONS[cell, instanceData.cells]; ENDLOOP; }; resolvers: LIST OF ResolveData _ NIL; pushData _ NEW[CellPushDataRec]; pushData.decoration _ decoration; pushData.root _ root; pushData.cutSet _ cutSet; pushData.selectionData _ RefTab.Create[]; pushData.transitiveClosure _ EnumerateLeastCommonObjectAncestors[design, root, decoration, RecordEachAncestor, cutSet]; IF resolvers#NIL THEN { externalViewer: ViewerClasses.Viewer _ Containers.Create[[ -- JMF: TiogaButtons hack name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"], scrollable: FALSE, iconic: TRUE, column: left]]; viewer: ViewerClasses.Viewer _ TiogaButtons.CreateViewer[[ -- JMF: TiogaButtons hack name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"], column: left, border: FALSE, parent: externalViewer]]; pushData.viewer _ viewer; Containers.ChildXBound[externalViewer, viewer]; Containers.ChildYBound[externalViewer, viewer]; FOR resolveList: LIST OF ResolveData _ resolvers, resolveList.rest UNTIL resolveList=NIL DO FindType: IntHashTable.EachPairAction = { IF RefTab.Insert[x: finishedSubCells, key: data[key].type, val: $Finished] THEN { subCellType _ data[key].type; quit _ TRUE; }; }; data: CoreClasses.RecordCellType _ NARROW[resolveList.first.cell.data]; subCellType: Core.CellType _ NIL; resolveName: Rope.ROPE _ CoreOps.GetCellTypeName[resolveList.first.cell]; button: TiogaButtons.TiogaButton _ TiogaButtons.CreateButton[viewer: viewer, rope: Rope.Cat[resolveName, ": "], looks: "f"]; finishedSubCells: RefTab.Ref _ RefTab.Create[]; firstChoice: BOOL _ TRUE; IF pushDebug THEN TerminalIO.PutRopes[resolveName, "\n"]; resolveList.first.feedBackButton _ button; WHILE IntHashTable.Pairs[resolveList.first.instanceData, FindType] DO AddInstanceChoice: IntHashTable.EachPairAction = { IF data[key].type=subCellType THEN { instanceData: InstanceData _ NARROW[value]; instanceName: Rope.ROPE _ CoreClasses.GetCellInstanceName[data[key]]; instanceData.button _ TiogaButtons.AppendToButton[button: button, rope: IF instanceName=NIL THEN IO.PutFR["%g", IO.int[key]] ELSE instanceName, looks: "f", proc: RecordInstanceNumber, clientData: instanceData, fork: FALSE]; [] _ TiogaButtons.AppendToButton[button: button, rope: " "]; IF firstChoice THEN { SetInstanceNumber[instanceData]; firstChoice _ FALSE; }; IF pushDebug THEN { TerminalIO.PutRopes[" ", IO.PutFR["%g(%g)", IO.int[key], IO.rope[CoreOps.GetCellTypeName[data[key].type]]], "\n"]; TerminalIO.PutRope[" Cells:\n"]; FOR cells: LIST OF Core.CellType _ instanceData.cells, cells.rest UNTIL cells=NIL DO TerminalIO.PutRopes[" ", CoreOps.GetCellTypeName[cells.first], "\n"]; ENDLOOP; TerminalIO.PutRope[" Objects:\n"]; FOR objects: LIST OF PipalCore.Object _ instanceData.objects, objects.rest UNTIL objects=NIL DO TerminalIO.PutRopes[" ", PW.Name[objects.first], "\n"]; ENDLOOP; }; }; }; [] _ IntHashTable.Pairs[resolveList.first.instanceData, AddInstanceChoice]; [] _ TiogaButtons.AppendToButton[button: button, rope: Rope.Cat["(", CoreOps.GetCellTypeName[subCellType], ") "], looks: "f"]; ENDLOOP; ENDLOOP; ViewerOps.OpenIcon[externalViewer]; -- JMF: TiogaButtoms hack }; }; RecordInstanceNumber: TiogaButtons.TiogaButtonProc = { instanceData: InstanceData _ NARROW[clientData]; oldInstanceData: InstanceData _ NARROW[IntHashTable.Fetch[table: instanceData.resolve.instanceData, key: instanceData.resolve.selectedInstance].value]; pushData: DesignPushData _ NARROW[CDProperties.GetDesignProp[ instanceData.pushData.doesNotMatterDesign, pushDataAtom]]; TiogaButtons.ChangeButtonLooks[oldInstanceData.button, NIL, "i"]; SetInstanceNumber[instanceData]; FOR dpd: LIST OF DesignPushData _ instanceData.pushData.designPushData, dpd.rest UNTIL dpd=NIL DO IF dpd.first#pushData THEN RecomputePushedCellType[dpd.first]; ENDLOOP; RecomputePushedCellType[pushData]; }; SetInstanceNumber: PROC [instanceData: InstanceData] = { instanceData.resolve.selectedInstance _ instanceData.instance; TiogaButtons.ChangeButtonLooks[instanceData.button, "i"]; instanceData _ instanceData; }; PushPop: CDEvents.EventProc = { pushData: DesignPushData _ NARROW[CDProperties.GetDesignProp[design, pushDataAtom]]; importerDesign: PipalUI.Design _ GetImporterDesign[design]; IF importerDesign#NIL THEN { importerPushData: DesignPushData _ NARROW[CDProperties.GetDesignProp[importerDesign, pushDataAtom]]; IF importerPushData#NIL AND pushData=NIL THEN pushData _ CreateDesignPushData[design, importerPushData.cellPushData]; }; IF pushData#NIL THEN RecomputePushedCellType[pushData]; }; RecomputePushedCellType: PROC [pushData: DesignPushData] = { design: PipalUI.Design _ pushData.design; instanceStack: LIST OF CD.Instance _ NIL; pushData.errorMessage _ NIL; pushData.cellPushData.doesNotMatterDesign _ design; IF design.actual.rest=NIL THEN pushData.errorMessage _ "PipalCoreCDUser: No currently pushed-in cell." ELSE { FOR stack: LIST OF CD.PushRec _ design.actual, stack.rest WHILE stack.rest#NIL DO IF stack.first.specific.changed THEN { pushData.errorMessage _ IO.PutFR["PipalCoreCDUser: Impossible to unwind stack, cell %g has been changed and not saved.", IO.rope[PW.Name[stack.first.mightReplace.ob]]]; EXIT; }; instanceStack _ CONS[stack.first.mightReplace, instanceStack]; ENDLOOP; IF pushData.errorMessage=NIL THEN { IF RefTab.Pairs[pushData.cellPushData.selectionData, SetDoesNotMatter] THEN ERROR; [pushData.errorMessage, pushData.cellType, pushData.flatCellType] _ BuildFlatCell[cell: pushData.cellPushData.root, instances: instanceStack, pushData: pushData]; IF pushData.errorMessage=NIL THEN IF RefTab.Pairs[pushData.cellPushData.selectionData, DisplayDoesNotMatter] THEN ERROR; }; }; }; BuildFlatCell: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType, instance: CoreClasses.CellInstance _ NIL, instances: LIST OF CD.Instance, pushData: DesignPushData] RETURNS [errorMessage: Rope.ROPE _ NIL, cellType: Core.CellType, flatCellType: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] = { matchingObject: BOOL _ instances.first.ob=PipalCore.GetObject[pushData.cellPushData.decoration, cell]; -- BS: test used to be more sophisticated! SELECT TRUE FROM matchingObject AND instances.rest=NIL => { cellType _ cell; flatCellType _ flatCell; }; CoreFlat.CutSetMemberResolved[flatCell, instance, cell, pushData.cellPushData.cutSet] => errorMessage _ "PipalCoreCDUser: No such cell above current cut set"; cell.class=CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; IF matchingObject THEN FOR inst: NAT IN [0..rct.size) DO thisInstance: CoreClasses.CellInstance _ rct[inst]; IF PipalUI.SameInstances[ instances.first.trans, instances.rest.first, PipalCore.GetTrans[pushData.cellPushData.decoration, thisInstance], PipalCore.GetObject[pushData.cellPushData.decoration, thisInstance.type] ] THEN { [errorMessage, cellType, flatCellType] _ BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances.rest, pushData]; EXIT; }; REPEAT FINISHED => ERROR; -- record cell with CD object and next instance does not match? ENDLOOP ELSE { cdObject: CD.Object _ instances.first.ob; found: BOOL _ FALSE; multiple: BOOL _ FALSE; inst: NAT _ LAST[NAT]; WHILE CDImports.IsImport[cdObject] DO cdObject _ CDDirectory.Expand1[cdObject].new ENDLOOP; FOR i: NAT IN [0..rct.size) DO subCellTable: RefTab.Ref _ NARROW[RefTab.Fetch[ pushData.cellPushData.transitiveClosure, rct[i].type].val]; IF RefTab.Fetch[subCellTable, cdObject].found THEN { multiple _ found; found _ TRUE; inst _ i; IF multiple THEN EXIT; }; ENDLOOP; SELECT TRUE FROM NOT found => errorMessage _ "PipalCoreCDUser: Cell cannot be reached with current selection viewer settings or selection viewer cannot disambiguate this object"; NOT multiple => { thisInstance: CoreClasses.CellInstance _ rct[inst]; [errorMessage, cellType, flatCellType] _ BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, inst, rct], 0], thisInstance, instances, pushData]; }; ENDCASE => { resolveData: ResolveData _ NARROW[RefTab.Fetch[pushData.cellPushData.selectionData, cell].val]; IF resolveData=NIL THEN errorMessage _ "PipalCoreCDUser: Cannot disambiguate this object" ELSE { thisInstance: CoreClasses.CellInstance _ rct[resolveData.selectedInstance]; resolveData.doesNotMatter _ FALSE; [errorMessage, cellType, flatCellType] _ BuildFlatCell[thisInstance.type, [CoreFlat.ExtendPath[flatCell.path, resolveData.selectedInstance, rct], 0], thisInstance, instances, pushData]; }; }; }; }; ENDCASE => { thisCell: Core.CellType _ CoreOps.Recast[cell]; [errorMessage, cellType, flatCellType] _ BuildFlatCell[thisCell, IF thisCell=cell THEN flatCell ELSE [flatCell.path, flatCell.recastCount+1], instance, IF matchingObject THEN instances.rest ELSE instances, pushData]; }; }; SetDoesNotMatter: RefTab.EachPairAction = { resolveData: ResolveData _ NARROW[val]; resolveData.doesNotMatter _ TRUE; }; DisplayDoesNotMatter: RefTab.EachPairAction = { resolveData: ResolveData _ NARROW[val]; IF resolveData.doesNotMatter#resolveData.struckOut THEN { IF resolveData.doesNotMatter THEN TiogaButtons.ChangeButtonLooks[resolveData.feedBackButton, "y"] ELSE TiogaButtons.ChangeButtonLooks[resolveData.feedBackButton, NIL, "y"]; resolveData.struckOut _ resolveData.doesNotMatter; }; }; EachLeastCommonObjectAncestorProc: TYPE = PROC [ancestor: Core.CellType, instance: NAT, cell: Core.CellType _ NIL, object: PipalCore.Object _ NIL]; EnumerateLeastCommonObjectAncestors: PROC [design: PipalUI.Design, root: Core.CellType, decoration: PipalCore.Decoration, eachLeastCommonAncestor: EachLeastCommonObjectAncestorProc, cutSet: CoreFlat.CutSet _ NIL] RETURNS [transitiveClosure: RefTab.Ref _ NIL] = { ComputeCellObjectDependence: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType, instance: CoreClasses.CellInstance _ NIL] RETURNS [cellObjects: RefTab.Ref] = { cellObjects _ NARROW[RefTab.Fetch[transitiveClosure, cell].val]; IF cellObjects=NIL THEN { cellObjects _ RefTab.Create[]; IF CoreProperties.GetCellTypeProp[cell, ignoreMeProp]=NIL THEN { IF NOT RefTab.Insert[cellObjects, cell, $DependsOn] THEN ERROR; IF cell.class#CoreClasses.transistorCellClass AND PipalCore.HasObject[decoration, cell] THEN IF NOT RefTab.Insert[cellObjects, PipalCore.GetObject[ decoration, cell], $DependsOn] THEN ERROR; SELECT TRUE FROM CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => NULL; cell.class=CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; rctHasObject: BOOL _ PipalCore.HasObject[decoration, cell]; FOR i: NAT IN [0..rct.size) DO InsertRecordSubObject: RefTab.EachPairAction = { subCell: Core.CellType _ NIL; object: PipalCore.Object _ NIL; IF NOT RefTab.Insert[cellObjects, key, NEW[NAT _ i]] THEN { firstInstance: REF ANY _ RefTab.Fetch[cellObjects, key].val; ambiguousMultipath: BOOL _ TRUE; WITH key SELECT FROM o: PipalCore.Object => { object _ o; IF rctHasObject THEN ambiguousMultipath _ RefTab.Fetch[topObjects, object].found; }; s: Core.CellType => { subCell _ s; ambiguousMultipath _ NOT PipalCore.HasObject[decoration, subCell]; }; ENDCASE => ERROR; IF ambiguousMultipath THEN { IF ISTYPE[firstInstance, REF NAT] THEN { eachLeastCommonAncestor[cell, NARROW[firstInstance, REF NAT]^, subCell, object]; [] _ RefTab.Store[cellObjects, key, $DependsOn]; }; eachLeastCommonAncestor[cell, i, subCell, object]; }; }; }; subCellObjects: RefTab.Ref _ ComputeCellObjectDependence[rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]]; IF RefTab.Pairs[subCellObjects, InsertRecordSubObject] THEN ERROR; ENDLOOP; }; ENDCASE => { InsertOtherSubObject: RefTab.EachPairAction = { [] _ RefTab.Store[cellObjects, key, $DependsOn]; }; new: Core.CellType _ CoreOps.Recast[cell]; recastCellObjects: RefTab.Ref _ IF cell=new THEN ComputeCellObjectDependence[cell, flatCell, instance] ELSE ComputeCellObjectDependence[new, [flatCell.path, flatCell.recastCount+1], instance]; IF RefTab.Pairs[recastCellObjects, InsertOtherSubObject] THEN ERROR; }; }; IF NOT RefTab.Insert[transitiveClosure, cell, cellObjects] THEN ERROR; }; }; topObjects: RefTab.Ref _ RefTab.Create[]; FOR ti: PipalUI.TopInstanceLists _ PipalUI.GetTopInstances[design], ti.rest UNTIL ti=NIL DO FOR il: CD.InstanceList _ ti.first.instances, il.rest UNTIL il=NIL DO [] _ RefTab.Insert[topObjects, il.first.ob, $TopLevelInstance]; ENDLOOP; ENDLOOP; transitiveClosure _ RefTab.Create[]; [] _ ComputeCellObjectDependence[root]; }; DoForSelectedFlatWires: PUBLIC PROC [root: Core.CellType, action: SelectedFlatWireActionProc, cutSet: CoreFlat.CutSet _ NIL, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] = { errorMsg: Rope.ROPE; { ENABLE { CoreCDUserError => {errorMsg _ msg; GOTO Done}; 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 { action[flatWireRef]; someValueFound _ TRUE; }; }; someValueFound: BOOL _ FALSE; enumeratedWires: RefTab.Ref _ RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; [] _ EnumerateSelectedFlatWires[root, DoAValue, cutSet, design, decoration]; IF NOT someValueFound THEN errorMsg _ "PipalCoreCDUser: No wire(s) found."; EXITS Done => NULL; }; IF errorMsg#NIL THEN TerminalIO.PutRopes[errorMsg, "\n"]; }; DoForSelectedFlatCells: PUBLIC PROC [root: Core.CellType, action: SelectedFlatCellActionProc, cutSet: CoreFlat.CutSet _ NIL, design: PipalUI.Design _ NIL, decoration: PipalCore.Decoration _ NIL] = { errorMsg: Rope.ROPE; { ENABLE { CoreCDUserError => {errorMsg _ msg; GOTO Done}; CoreFlat.PathError => {errorMsg _ msg; GOTO Done}; }; DoAValue: EachSelectedFlatCellProc = { flatCellTypeRef: CoreFlat.FlatCellType _ NEW[CoreFlat.FlatCellTypeRec]; flatCellTypeRef^ _ selectedFlatCell; action[flatCellTypeRef]; someValueFound _ TRUE; }; someValueFound: BOOL _ FALSE; [] _ EnumerateSelectedFlatCells[root, DoAValue, cutSet, design, decoration]; IF NOT someValueFound THEN errorMsg _ "PipalCoreCDUser: No cell type(s) found"; EXITS Done => NULL; }; IF errorMsg#NIL THEN TerminalIO.PutRopes[errorMsg, "\n"]; }; CDEvents.RegisterEventProc[event: $AfterPush, proc: PushPop]; CDEvents.RegisterEventProc[event: $AfterPop, proc: PushPop]; END. ÒPipalCoreCDUserImpl.mesa Copyright Ó 1987, 1988 by Xerox Corporation. All rights reserved. Barth, February 16, 1988 4:33:50 pm PST Jean-Marc Frailong December 14, 1987 4:30:14 pm PST Last tweaked by Mike Spreitzer on February 17, 1988 9:01:31 am PST Bertrand Serlet May 12, 1988 0:06:44 am PDT Context Core To CD no ERROR if not done, because it might be a wire icon. All this code stinks. There should be a simpler way (BS) Computes all objects reachable from the passed instance list. If this is the list of top level instances in the design then these are the objects which have top level instances, i.e. they are displayed in the design. closure maps objects to RefTab which then maps objects to their containing design (which may be NIL if an import is not yet bound). To pose the question "is A reachable from B" hash into closure with B and then hash into the resulting table with A. found => A is reachable from B. Every object is reachable from itself. CD To Core Basic Operations There used to be some code for object which do not directly end up as decorations (such as well contacts). Of course this might now be bogus, since those objects are split directly after the CD -> Pipal conversion viewer: ViewerClasses.Viewer _ TiogaButtons.CreateViewer[[ -- JMF: TiogaButtons hack name: Rope.Cat[CoreOps.GetCellTypeName[root], " Selection"], iconic: FALSE, column: left]]; pushData.viewer _ viewer; 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. Command Utilities Start Code Ê$¥˜code– "Cedar" stylešœ™K– "Cedar" style™BKšœ$Ïk™'Kšœ0™3Kšœ?™BK™+K˜—š ˜ Kšœáœ˜çKšœ9˜9KšœC˜EK˜—šÏnœœ˜"KšœœÛœœ3˜ºKšœ˜Kšœ ˜Kšœœœ˜K˜—Kš žœœœ œœ˜7head™šžœœœ œBœœœœ˜¦KšœœA˜^Kšœœœ:˜_š œœ œ:œ œ˜fKš œœœœ4œÏcÐbcŸ#˜”Kšœl˜lšœœœ˜Kšœ$˜$Kšœ5˜5Kšœ!œœ˜-K˜—Kšœ˜—K˜K˜—Kšœœ!˜=Kšœœ#˜Ašœœ%˜EK˜—šžœœœ œ˜TJšœA˜AJšœ=œ˜Bš œœœ@œœ˜^Kš œœœ/Ÿ Ÿ˜ZKšœ˜—KšœE˜EKšœ;œŸ…˜ÇKšœ˜K˜K˜—š žœœœ œœ˜]Kšœœœ$˜IKšœœ=˜JK˜K˜—š žœœœœ œ˜]Kšœ œ?˜NK˜K˜—š žœœœ œ œ˜WJšœ=œ˜BJšœI˜IKšœ˜š œœœBœœ˜`Kšœ/˜/Kšœ˜—K˜K˜—š žœœœ œœ œ˜`Kšœ œA˜RK˜K˜—šžœœœ<˜bKšœM˜MKšœ˜K˜—šžœœœœ'˜kKšœ œC˜VK˜K˜—š žœœœ$œ œ*˜ºKš œ œœœœ˜GKšœ œœœ=˜XKš œœ œœ!œ ˜WKšœœœœA˜`K˜K˜—šžœœ œ˜6Kšœ œ˜.šœKœ œ˜bKšœD˜DKšœ˜—K˜K˜—š žœœ œœœœ˜VKšœ6˜6šœœœ˜Kšœœ!˜4Kšœ œœ˜,Kšœ0˜0K˜—K˜K˜—šžœœ œ˜6Kšœ œ˜.šœKœ œ˜bKšœD˜DKšœ˜—K˜K˜—š žœœ œœœœ˜VKšœ œ˜7šœ œœ˜Kšœœ˜6Kšœœœ8˜QK˜—K˜K˜—šžœœœ œœœœ˜YKš œœœœœ˜eK˜K˜——šœ™ šžœœœCœœ%œ!œœœ˜ãKšœL˜LKšœ œ˜"KšœI˜IKšœV˜VKšœ3˜3Kšœr˜rK˜K˜—šžœœœ?œœ%œ!œœœ˜ÛKšœU˜UJ˜J˜KšœI˜IKšœ[˜[Kšœ œ!˜3Kšœ‚˜‚K˜K˜—š žœœ œrœœ œ˜ðšžœœ œ˜0KšœA˜AK˜—KšœV˜VK˜K˜—š žœœœCœœ%œ˜£KšœL˜LKšœ6˜6KšœI˜IKšœU˜UKšœ ÏbœœŸ˜jK˜K˜—š žœœœ?œœ%œ˜›KšœU˜UKšœ6˜6KšœI˜IKšœ^˜^šœ ¡œœ˜9š ž œœœœœ˜Gšžœ˜*Kšœ6™6Kšœ$¡2œ˜YK˜—šž œ˜$Kšœœœ%œ:˜Kšœœ˜ K˜—Kšœ9™9šœ˜Kšœ,˜0š œœœœ˜)Kšœœ˜:Kšœ˜——K˜—Kšœœ*˜6Kšœ ˜ Kšœ(œœ2˜zKšœ˜K˜—Kšœœ1˜;K˜K˜—š ž œœ œrœœA˜€šžœœ œ˜0Kšœœ˜,K˜—Kš œœœœ œ˜(Kš œ œœœ œ˜$KšœV˜VKš¡! ˜0K˜!Kšœ.˜.š œœœœ"œœ˜CKšœ œ˜$Kšœ˜—š œœœœœœ˜?Kšœ ¡ ˜@Kš œœ"¡œœœ1˜xKšœ˜—Kšœ˜K˜K˜—šžœœ œ€œ œ œœ˜òšœ'œ˜/KšœI˜IKšœœœ˜KšœÅ˜ÅKšœœœœG˜^K˜—Kšœœc˜mK˜K˜—šž œœHœœœœœœ œ œœ œœ˜ðšœ œ˜šœMœœ˜lKšœ*˜*š œœCœœ˜pKšœ œ ˜,Kšœ œ œ˜1šœ¡œ¡ œœ-˜HKšœœ&˜Kšœœœ6œ˜WKšœ!˜!š˜Kš œ¡œÐbk¡œœœ,˜\Kšœœœœ˜!Kšœ˜šœ˜!Kšœœœœ˜+Kšœ-˜-Kšœ˜—šœœ˜!šœ œœ˜$šžœ˜!Kšœ¡œ¢¡œœA˜lšœœ˜Kšœ˜Kšœ˜K˜—K˜—Kšœ˜Kš œ œœœ-œœ˜QK˜—šœ œ ˜šžœ˜š œ¡œ¢¡œœ-˜UKšœ˜Kšœ œ˜Kšœ˜Kšœ˜K˜—K˜—Kšœ œœ˜Kšœ+œœ˜9K˜—Kšœ˜—Kšœ˜—Kšœœ˜ Kšœ˜K˜—K˜—Kšœ˜—Kšœ˜—Kšœ˜Kšœ œœœœœœ˜hKšœ˜—K˜K˜—šžœœaœœœœœœ˜§šžœ"˜4Kšœt˜tKšœ'œœ.˜gKšœ œœœ*œœœM˜µK˜—Kšœ5˜5K˜K˜—šœœ%˜AK˜—Kšœ»œß™šžœœ*œ˜hš žœœ œ œ œœ˜qKšœ œ$˜4š œ œœœœ˜:Kšœ˜Kšœœ(œœ˜9šœœ˜šžœœ œ œ ˜Jšž œ˜'Kšœ&˜&K˜—KšœG˜GKšœ œœ-˜CK˜—šœœ˜ šžœ˜+Kšœ ˜ Kšœ˜—Kšœ9˜9K˜—Kš œœœœ8œ*˜£K˜—Kšœœ)œœ˜:K˜—K˜—Kšœ œP˜`šœ œœ˜Kšœ˜šœ@œ œ˜Wš œœAœœ˜zKšœP˜PKšœ˜—Kšœ˜—KšœW˜WK˜—K˜K˜——šœ™ ™KšœœœŸp˜¨K˜šžœœœaœ œœ%œœœœ˜óšžœ˜*šœ˜Kšœ˜Kšœ œ œœ ˜2Kšœ˜—K˜—Kšœ œœ˜Kšœœ˜Kšœ(˜(KšœI˜IKšœP˜PKšœ8˜8Kš œ2œ œœœT˜´K˜K˜—š œœœœœœ˜YK˜—šžœœ œ=œœ*œœœ˜Çšžœ˜0šžœ˜"Kšœœœ%œM˜œKšœ˜Kšœ œ˜K˜—Kšœ œœ˜K˜)KšœÖ™ÖKšœœ œœ\˜wK˜—Kšœžœ˜FKšœ˜K™—šžœœœaœ œœ%œœœœ˜óKšœI˜Išœœœ˜ šžœ˜2Kšœœœ˜Kšœ,˜,KšœDœ¡œ˜fKšœœœœ˜=Kšœ)˜)K˜—KšœI˜IKšœžœ˜FK˜—šœ˜šžœ"˜2Kšœ`˜`K˜—Kšœœ˜Kšœ(˜(Kšœ"œ˜&KšœP˜PKšœœŸB˜`KšœQ˜QK˜—K˜K˜—š œœœœœœœ˜cK˜—š žœœ œ}œœœ˜Ùšžœ&˜:šœœœ˜šœË¡œ˜éKšœ#˜#Kšœ˜Kšœ˜—Kšœœœa˜yKšœ˜—K˜—Kšœžœ˜FKšœ˜K™—Jšœœ˜)J˜Jšœœœ˜)šœœœ˜ Jšœ#œ˜'Jšœœ˜Jšœœ˜Jšœœ˜ Jšœ œ˜$Jšœœ˜#Jšœœœ˜*Jšœœœœ˜.—J˜Jšœœœ˜-šœœœ˜"Jšœœœ˜Jšœœ˜!Jšœœ˜Jšœ,˜,Jšœœœ˜J˜—Jšœ œœ˜'šœœœ˜Jšœœ˜Jšœ#œ˜'Jšœ+œ˜/Jšœœ˜Jšœœœ˜Jšœ œœ˜J˜—Jšœœœ˜)šœœœ˜ Jšœœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œœœŸ˜BJšœœœœŸ˜=Jšœ#œ˜(J˜—šœ œœ˜J˜—š žœœ œSœœ"œK˜ƒKšœI˜IKšœœœœ(˜OKšœ#˜#Kšœ+˜+Kšœœœœ†˜¦K˜K˜—š ž œœ œSœœ˜§Kšœ œ3˜Dšœ œœ œœ"œ/œ˜}Kšœœ5˜Xšœœœœœœ&œ˜sKš œ œœœœ7˜pKšœ@˜@KšœA˜AK˜—Kšœ6˜6Kšœ"˜"K˜—Kšœœ2œ#˜`K˜K˜—šžœœ œœ˜vKšœ œ˜"Kšœ˜Kšœ%˜%Kšœœ(˜JKšœ;˜;K˜K˜—š žœœ œSœœ˜¨K˜šžœ'˜9Kšœœ5˜VKšœœ˜!šœ œœ˜Kšœœ˜"Kšœœ>œœ˜OKšœ˜Kšœ œ˜)Kšœ1˜1K˜—Kšœœ?˜Tšœœœ˜Kšœœ˜$Kšœ˜Kšœ!˜!Kšœ#˜#Kšœ!˜!KšœœGœœ˜XK˜—šœœœœ œœ7œ œ˜rKšœœœ˜"Kšœœœ˜MKšœ˜—šœœœœœœ0œœ˜eKšœœœ˜Kšœœœ˜GKšœ˜—K˜K˜—Kšœ œœœ˜%Kšœ œ˜ Kšœ!˜!Kšœ˜Kšœ˜Kšœ)˜)Kšœw˜wšœ œœ˜šœ;Ÿ Ÿ˜TKšœ<˜˜EK˜šžœ!˜2šœœ˜$Kšœœ˜+Kšœœ.˜EKšœHœœœœ œ œWœ˜ßKšœ<˜<šœ œ˜Kšœ ˜ Kšœœ˜K˜—šœ œ˜Kšœœœ œ7˜sKšœ#˜#š œœœ0œœ˜TKšœJ˜JKšœ˜—Kšœ%˜%š œ œœ7œ œ˜_Kšœœ˜Kšœ˜—Kšœ"˜"Kšœ˜K™—šžœœ!˜8Kšœ>˜>Kšœ9˜9Kšœ˜Kšœ˜K™—šžœ˜Kšœœ3˜TKšœœ˜;šœœœ˜Kšœ#œ;˜dKš œœœ œœH˜uK˜—Kšœ œœ#˜7Kšœ˜K™—šžœœ˜Kšœ˜—šœœœ˜#KšœEœœ˜RKšœ¢˜¢Kš œœœœIœœ˜xK˜—K˜—Kšœ˜K˜—šž œœxœ œœœ%œœœ^˜ÎKšœœ¡œ¡:œ-˜‘šœœ˜šœœœ˜*Kšœ˜Kšœ˜Kšœ˜—KšœŸ˜Ÿšœ+˜+Kšœ"œ ˜4š œœœœœ˜8K˜3šœ˜Kš¡˜Kš¡˜KšœD˜DKšœH˜HKšœœ˜Kšœ¦˜¦Kšœ˜K˜—KšœœœŸ?˜ZKš˜—šœ˜Kšœ œ˜)Kšœœœ˜Kšœ œœ˜Kšœœœœ˜Kšœœ.œ˜[šœœœ˜KšœœJ˜kšœ,œ˜4Kšœ˜Kšœœ˜ K˜ Kšœ œœ˜K˜—Kšœ˜—šœœ˜Kšœž˜¡šœ˜Kšœ3˜3Kšœ¡˜¡Kšœ˜—šœ˜ Kšœœ>˜_Kšœ œœC˜Zšœ˜KšœK˜KKšœœ˜"Kšœ¹˜¹K˜—Kšœ˜——K˜—K˜—šœ˜ Kšœ/˜/Kš œAœœ œ4œœœ˜ØKšœ˜——Kšœ˜K˜—šžœ˜+Kšœœ˜'Kšœœ˜!K˜K˜—šžœ˜/Kšœœ˜'šœ1œ˜9KšœœAœ<œ˜­Kšœ2˜2K˜—K˜K˜—Kšœ˜œœ™ K™š œ#œœ%œœœ˜“K˜—š ž#œœ œœœ"œ˜†šžœœxœœ˜ÃKšœœ,˜@šœ œœ˜Kšœ˜šœ4œœ˜@Kšœœ.œœ˜?Kšœ,œ'œœœPœœ˜¾šœœ˜KšœCœ˜Hšœ+˜+Kšœ"œ ˜4Kšœœ)˜;šœœœ˜šžœ˜0Kšœœ˜Kšœœ˜š œœ!œœœ˜;Kšœœœ&˜