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.EachSelectedObjectProc = { 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.EachSelectedInstanceProc = { 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 April 25, 1988 0:22:12 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šœ3œŸ˜jK˜K˜—š žœœœ?œœ%œ˜›KšœU˜UKšœ6˜6KšœI˜IKšœ^˜^šœ3œ˜9š ž œœœœœ˜Gšžœ˜*Kšœ6™6KšœY˜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šΟb! ˜0K˜!Kšœ.˜.š œœœœ"œœ˜CKšœ œ˜$Kšœ˜—š œœœœœœ˜?Kšœ ‘ ˜@Kšœœ7œœ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šœœœ˜ šžœ$˜8Kšœœœ˜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˜—š žœœ œ}œœœ˜Ωšžœ.˜Bšœœœ˜šœ(œ.œ…œ˜ι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šœœœ&˜