<> <> <> <> <> DIRECTORY CD, CDBasics, CDBasicsInline, CDCells, CDCellsInteractions, CDDirectory, CDEvents, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDViewer, Containers, Core, CoreCDUser, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, ExtractOps, IntHashTable, IO, PW, RefTab, Rope, Sinix, TerminalIO, TiogaButtons, ViewerClasses, ViewerOps; CoreCDUserImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDBasicsInline, CDCells, CDCellsInteractions, CDDirectory, CDEvents, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDViewer, Containers, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, ExtractOps, IntHashTable, IO, PW, RefTab, Rope, TerminalIO, TiogaButtons, ViewerOps EXPORTS CoreCDUser SHARES CDImports = BEGIN OPEN CoreCDUser; CoreCDUserError: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; <> EnumerateSelectedCellTypes: PUBLIC PROC [design: CD.Design, eachRootCellType: EachRootCellTypeProc, mode: Sinix.Mode _ NIL] RETURNS [quit: BOOL _ FALSE] = { originalSelectedInstances: CD.InstanceList _ CDInstances.OnlySelected[CDOps.InstList[design]]; <> <> <> <> <<};>> <> IF originalSelectedInstances=NIL THEN TerminalIO.PutRope["CoreCDUser: Nothing selected\n"] ELSE FOR instances: CD.InstanceList _ originalSelectedInstances, instances.rest WHILE instances#NIL DO thisMode: Sinix.Mode _ IF mode=NIL THEN ExtractOps.GetExtractMode[design, instances.first.ob] ELSE mode; -- JMF: added parameter to GetExtractMode root: Core.CellType _ ExtractOps.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: CD.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]; 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: CD.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: CD.Design] = { design _ NARROW[CoreProperties.GetCellTypeProp[root, designRootCellTypeProp]]; }; SetImporterDesign: PUBLIC PROC [importee: CD.Design, importer: CD.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 IF cl.first.importee#NIL THEN SetImporterDesign[cl.first.importee, importer]; ENDLOOP; }; GetImporterDesign: PUBLIC PROC [importee: CD.Design] RETURNS [importer: CD.Design] = { importer _ NARROW[CDProperties.GetDesignProp[importee, designImporterDesignProp]]; }; SetRootCellTypeDecoration: PUBLIC PROC [root: Core.CellType, decoration: CoreGeometry.Decoration] = { CoreProperties.PutCellTypeProp[root, rootCellTypeDecorationProp, decoration]; }; GetRootCellTypeDecoration: PUBLIC PROC [root: Core.CellType] RETURNS [decoration: CoreGeometry.Decoration] = { decoration _ NARROW[CoreProperties.GetCellTypeProp[root, rootCellTypeDecorationProp]]; }; FindDesignAndDecoration: PROC [root: Core.CellType, design: CD.Design, decoration: CoreGeometry.Decoration] RETURNS [outDesign: CD.Design, outDecoration: CoreGeometry.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: CD.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: CD.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: CD.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: CD.Design] RETURNS [label: Rope.ROPE _ NIL] = { importer: CD.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: CD.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: CD.Design _ NIL, decoration: CoreGeometry.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 ExtractOps.HighlightDesign[design]; ExtractOps.HighlightDesign[design, ExtractOps.HighlightInstance[[CoreGeometry.GetObject[decoration, cell], transform]], viewer, GetDesignLabel[design]]; }; HighlightFlatWire: PUBLIC PROC [root: Core.CellType, flatWire: CoreFlat.FlatWireRec, design: CD.Design _ NIL, decoration: CoreGeometry.Decoration _ NIL, viewer: ViewerClasses.Viewer _ NIL, clearFirst: BOOL _ TRUE] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatWire.flatCell].cellType; instance: CD.Instance _ NEW[CD.InstanceRep]; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, instance.trans] _ FindFlatCellTransform[design, decoration, root, flatWire.flatCell, cell]; PutWireHighlight[decoration, cell]; instance.ob _ NARROW[CoreProperties.GetWireProp[flatWire.wire, wireHighlightProp]]; IF clearFirst THEN ExtractOps.HighlightDesign[design]; ExtractOps.HighlightDesign[design, instance, viewer, GetDesignLabel[design]]; }; ClearHighlight: PUBLIC PROC [root: Core.CellType _ NIL, design: CD.Design _ NIL] = { IF design=NIL THEN { IF root=NIL THEN ERROR CoreCDUserError["Gimme a break!"]; design _ GetRootCellTypeDesign[root]}; ExtractOps.HighlightDesign[design]; RETURN}; FindFlatCellTransform: PROC [design: CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType] RETURNS [cellDesign: CD.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: CD.Design _ NIL, decoration: CoreGeometry.Decoration _ NIL] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatCell].cellType; lastInstance: CD.Instance _ NIL; transform: CD.Transformation _ []; cdInst: CD.Instance; -- JMF : bug fix [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, lastInstance, transform] _ PushToDesire[design, decoration, root, flatCell, cell]; cdInst _ ExtractOps.FindSameInstance[design, lastInstance, transform]; -- JMF IF cdInst#NIL THEN cdInst.selected _ TRUE; -- JMF <> CDOps.Redraw[design]; }; SelectFlatWire: PUBLIC PROC [root: Core.CellType, flatWire: CoreFlat.FlatWireRec, design: CD.Design _ NIL, decoration: CoreGeometry.Decoration _ NIL] = { cell: Core.CellType _ CoreFlat.ResolveFlatCellType[root, flatWire.flatCell].cellType; lastInstance: CD.Instance _ NIL; cdInstance: CD.Instance _ NEW[CD.InstanceRep]; mayBeInst: CD.Instance; -- JMF: bug fix transform: CD.Transformation _ []; [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; [design, lastInstance, transform] _ PushToDesire[design, decoration, root, flatWire.flatCell, cell]; mayBeInst _ ExtractOps.FindSameInstance[design, lastInstance, transform]; -- JMF IF mayBeInst#NIL AND CDCellsInteractions.PushInCellInstance[design, mayBeInst] THEN { SelectParents: PROC [parent: Core.Wire] RETURNS [yes: BOOL _ FALSE] = { TurnOnSelected: CoreGeometry.EachInstanceProc = { mayBeInst: CD.Instance; -- JMF: bug fix cdInstance.ob _ instance.obj; cdInstance.trans _ instance.trans; mayBeInst _ ExtractOps.FindSameInstance[design, cdInstance, transform]; IF mayBeInst#NIL THEN mayBeInst.selected _ TRUE; }; IF parent=flatWire.wire THEN { TurnOnChild: CoreOps.EachWireProc = { [] _ IF public THEN CoreGeometry.EnumeratePins[decoration, wire, TurnOnSelected] ELSE CoreGeometry.EnumerateGeometry[decoration, wire, TurnOnSelected]; }; [] _ CoreOps.VisitWire[parent, TurnOnChild]; yes _ TRUE; } ELSE { FOR wi: NAT IN [0..parent.size) DO IF SelectParents[parent[wi]] THEN { [] _ IF public THEN CoreGeometry.EnumeratePins[decoration, parent, TurnOnSelected] ELSE CoreGeometry.EnumerateGeometry[decoration, parent, TurnOnSelected]; yes _ TRUE; }; ENDLOOP; }; }; public: BOOL _ cell.class#CoreClasses.recordCellClass; transform _ CDBasics.ComposeTransform[lastInstance.trans, transform]; [] _ SelectParents[cell.public]; IF cell.class=CoreClasses.recordCellClass THEN [] _ SelectParents[NARROW[cell.data, CoreClasses.RecordCellType].internal]; CDOps.Redraw[design]; } ELSE ERROR CoreCDUserError["CoreCDUser: Push failed"]; }; PushToDesire: PROC [design: CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType] RETURNS [cellDesign: CD.Design, lastInstance: CD.Instance _ NIL, transform: CD.Transformation _ []] = { 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]; lastInstance _ instanceList.first; instanceList _ instanceList.rest; ExtractOps.PopTop[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 IF ~CDCellsInteractions.PushInCellInstance[cellDesign, ExtractOps.FindSameInstance[cellDesign, il.first, transform]] THEN ERROR CoreCDUserError["CoreCDUser: Push failed"]; transform _ CDBasics.ComposeTransform[il.first.trans, transform]; ENDLOOP; CDOps.DeselectAll[cellDesign]; }; AllTogetherNow: PROC [design: CD.Design, decoration: CoreGeometry.Decoration, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, cell: Core.CellType, eachInstance: PROC [instance: CD.Instance]] RETURNS [cellDesign: CD.Design] = { IF CoreGeometry.HasObject[decoration, cell] THEN { topInstances: ExtractOps.TopInstanceLists _ ExtractOps.GetTopInstances[design]; found: BOOL _ FALSE; [cellDesign, found] _ FindInstances[ObjectTransitiveClosure[topInstances], topInstances, ListObjectsAndTransforms[decoration, root, flatCell], CoreGeometry.GetObject[decoration, cell], eachInstance]; IF NOT found THEN ERROR CoreCDUserError["CoreCDUser: Cell type object is not reachable"]; } ELSE ERROR CoreCDUserError["CoreCDUser: Cell type to be used for selection or highlight has no object"]; }; FindInstances: PROC [closure: RefTab.Ref, instances: ExtractOps.TopInstanceLists, searchList: LIST OF REF ANY, requiredObject: CD.Object, eachInstance: PROC [instance: CD.Instance]] RETURNS [cellDesign: CD.Design, found: BOOL _ FALSE] = { UNTIL searchList=NIL DO FOR designInstances: ExtractOps.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 ExtractOps.SameCDObject[cdObject, coreObject] THEN { reachableFromTop: RefTab.Ref _ NARROW[RefTab.Fetch[closure, cdObject].val]; IF reachableFromTop#NIL AND RefTab.Fetch[reachableFromTop, requiredObject].found THEN { eachInstance[topInstances.first]; DO IF NOT ExtractOps.SameCDObject[cdObject, NARROW[searchList.first]] THEN RETURN; 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 _ ExtractOps.SameCDObject[inst.ob, NARROW[searchList.first]] AND refTrans^=inst.trans; 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 ExtractOps.SameCDObject[inst.ob, NARROW[searchList.first]] THEN { 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: CoreGeometry.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 CoreGeometry.HasObject[decoration, cell] THEN list _ CONS[CoreGeometry.GetObject[decoration, cell], list]; IF instance#NIL AND cell=instance.type AND CoreGeometry.HasTrans[decoration, instance] THEN list _ CONS[NEW[CoreGeometry.Transformation _ CoreGeometry.GetTrans[decoration, instance]], list]; }; ObjectInstanceScan[cell: root, target: flatCellType]; }; transitiveClosureCache: ATOM = $CoreCDUserTransitiveClosureCache; < A is reachable from B. Every object is reachable from itself.>> ObjectTransitiveClosure: PROC [topInstances: ExtractOps.TopInstanceLists] RETURNS [closure: RefTab.Ref] = { ComputeReachableObjects: PROC [design: CD.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: CD.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: ExtractOps.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]; }; }; wireHighlightProp: ATOM _ $CoreCDUserWireHighlight; wireHighlightClass: CD.ObjectClass _ NIL; WireHighlights: TYPE = LIST OF WireHighlight; WireHighlight: TYPE = REF WireHighlightRec; WireHighlightRec: TYPE = RECORD [ public: BOOL _ FALSE, decoration: CoreGeometry.Decoration _ NIL, wire: Core.Wire _ NIL, parents: WireHighlights _ NIL, children: WireHighlights _ NIL, bound: CoreGeometry.Instances _ NIL]; -- transformation from CellInstance, object from bound wire WireHighlightDrawMe: CD.DrawProc = { DrawInstance: CoreGeometry.EachInstanceProc = { cdInstance.ob _ instance.obj; cdInstance.trans _ instance.trans; IF CDBasicsInline.IntersectRI[mapClip, cdInstance] THEN pr.drawChild[pr, cdInstance.ob, CDBasics.ComposeTransform[cdInstance.trans, trans]]; quit _ pr.stopFlag^; }; mapClip: CD.Rect _ CDBasics.DeMapRect[pr.interestClip, trans].itemInCell; cdInstance: CD.Instance _ NEW[CD.InstanceRep]; -- get rid of this by defining CDBasicsInline.IntersectRI that takes a record instead of a ref wh: WireHighlight _ NARROW[ob.specific]; oldRectProc: REF CD.DrawRectProc _ NIL; IF pr.drawRect#WireHighlightDrawRect THEN { oldRectProc _ NEW[CD.DrawRectProc _ pr.drawRect]; pr.drawRect _ WireHighlightDrawRect; CDProperties.PutPRefProp[pr.properties, drawRectProcProp, oldRectProc]; }; EnumerateWireHighlightInstances[wh, DrawInstance]; IF oldRectProc#NIL THEN pr.drawRect _ oldRectProc^; }; EnumerateWireHighlightInstances: PROC [wh: WireHighlight, eachInstance: CoreGeometry.EachInstanceProc] = { EnumerateUpward: PROC [wh: WireHighlight] RETURNS [quit: BOOL _ FALSE] = { IF (IF wh.public THEN CoreGeometry.EnumeratePins[wh.decoration, wh.wire, eachInstance] ELSE CoreGeometry.EnumerateGeometry[wh.decoration, wh.wire, eachInstance]) THEN RETURN [TRUE]; FOR whl: WireHighlights _ wh.parents, whl.rest UNTIL whl=NIL DO IF EnumerateUpward[whl.first] THEN RETURN [TRUE]; ENDLOOP; }; EnumerateDownward: PROC [wh: WireHighlight, bound: BOOL] RETURNS [quit: BOOL _ FALSE] = { IF bound THEN FOR t: CoreGeometry.Instances _ wh.bound, t.rest UNTIL t=NIL DO IF eachInstance[t.first] THEN RETURN; ENDLOOP; FOR whl: WireHighlights _ wh.children, whl.rest UNTIL whl=NIL DO IF (IF wh.public THEN CoreGeometry.EnumeratePins[whl.first.decoration, whl.first.wire, eachInstance] ELSE CoreGeometry.EnumerateGeometry[whl.first.decoration, whl.first.wire, eachInstance]) THEN RETURN [TRUE]; IF EnumerateDownward[whl.first, wh.bound=NIL] THEN RETURN [TRUE]; ENDLOOP; }; IF EnumerateUpward[wh] THEN RETURN; IF EnumerateDownward[wh, TRUE] THEN RETURN; }; drawRectProcProp: Rope.ROPE _ "WireHighlightDrawRectProc"; WireHighlightDrawRect: CD.DrawRectProc = { oldRectProc: REF CD.DrawRectProc _ NARROW[CDProperties.GetPRefProp[pr.properties, drawRectProcProp]]; oldRectProc^[pr, r, CD.shadeLayer]; }; PutWireHighlight: PROC [decoration: CoreGeometry.Decoration, cell: Core.CellType] = { Put: PROC [wire: Core.Wire, parent: WireHighlight _ NIL] RETURNS [wh: WireHighlight] = { object: CD.Object _ NARROW[CoreProperties.GetWireProp[wire, wireHighlightProp]]; IF object=NIL THEN { wh _ NEW[WireHighlightRec]; wh.public _ cell.class#CoreClasses.recordCellClass; wh.decoration _ decoration; wh.wire _ wire; wh.parents _ IF parent=NIL THEN NIL ELSE LIST[parent]; FOR wi: NAT IN [0..wire.size) DO wh.children _ CONS[Put[wire[wi], wh], wh.children]; ENDLOOP; object _ NEW[CD.ObjectRep]; object.class _ wireHighlightClass; object.bbox _ CDBasics.empty; object.specific _ wh; CoreProperties.PutWireProp[wire, wireHighlightProp, object]; } ELSE { wh _ NARROW[object.specific]; IF parent#NIL THEN wh.parents _ CONS[parent, wh.parents]; }; }; PutWireSeq: PROC [wire: Core.Wire] = { FOR wi: NAT IN [0..wire.size) DO [] _ Put[wire[wi]]; ENDLOOP; }; IF CoreProperties.GetCellTypeProp[cell, wireHighlightProp]=NIL THEN { RecomputeBBox: CoreOps.EachWireProc = { ResetBBox: CoreGeometry.EachInstanceProc = { object.bbox _ CDBasics.Surround[object.bbox, CoreGeometry.InlineBBox[instance]]; }; object: CD.Object _ NARROW[CoreProperties.GetWireProp[wire, wireHighlightProp]]; wh: WireHighlight _ NARROW[object.specific]; EnumerateWireHighlightInstances[wh, ResetBBox]; }; PutWireSeq[cell.public]; IF CoreGeometry.HasObject[decoration, cell] AND cell.class=CoreClasses.recordCellClass THEN { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; PutWireSeq[rct.internal]; FOR ii: NAT IN [0..rct.size) DO ci: CoreClasses.CellInstance _ rct[ii]; IF CoreGeometry.HasTrans[decoration, ci] THEN { PutBound: CoreOps.EachWirePairProc = { ao: CD.Object _ NARROW[CoreProperties.GetWireProp[actualWire, wireHighlightProp]]; awh: WireHighlight _ NARROW[ao.specific]; po: CD.Object _ NARROW[CoreProperties.GetWireProp[publicWire, wireHighlightProp]]; awh.bound _ CONS[[po, transform], awh.bound]; }; transform: CoreGeometry.Transformation _ CoreGeometry.GetTrans[decoration, ci]; PutWireHighlight[decoration, ci.type]; [] _ CoreOps.VisitBindingSeq[ci.actual, ci.type.public, PutBound]; }; ENDLOOP; [] _ CoreOps.VisitWireSeq[rct.internal, RecomputeBBox]; }; [] _ CoreOps.VisitWireSeq[cell.public, RecomputeBBox]; CoreProperties.PutCellTypeProp[cell, wireHighlightProp, $Done]; }; }; <> <> ignoreMeProp: PUBLIC ATOM _ $DAUserIgnoreForSelection; -- Fix CellLibraries some day to have this atom correspond to the package in which CoreCDUser is contained. EnumerateSelectedFlatWires: PUBLIC PROC [root: Core.CellType, eachSelectedFlatWire: EachSelectedFlatWireProc, cutSet: CoreFlat.CutSet _ NIL, design: CD.Design _ NIL, decoration: CoreGeometry.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: CD.Design, decoration: CoreGeometry.Decoration, root: Core.Wire, public: BOOL _ FALSE, eachSelectedWire: EachSelectedWireProc] RETURNS [quit: BOOL _ FALSE] = { ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = { ThisWire: CoreOps.EachWireProc = { ThisWireInstance: CoreGeometry.EachInstanceProc = { quit _ instance=selectedInstance; }; match: BOOL _ IF public THEN CoreGeometry.EnumeratePins[decoration, wire, ThisWireInstance] ELSE CoreGeometry.EnumerateGeometry[decoration, wire, ThisWireInstance]; IF match THEN { quit _ eachSelectedWire[wire]; someMatch _ TRUE; }; }; someMatch: BOOL _ FALSE; quit _ CoreOps.VisitWire[root, ThisWire]; IF NOT someMatch AND NOT CDRects.IsBareRect[selectedInstance.obj] THEN { EachFlatInstance: CoreGeometry.EachInstanceProc = { ThisWire: CoreOps.EachWireProc = { ThisWireInstance: CoreGeometry.EachInstanceProc = { quit _ instance=flatInstance; }; match: BOOL _ IF public THEN CoreGeometry.EnumeratePins[decoration, wire, ThisWireInstance] ELSE CoreGeometry.EnumerateGeometry[decoration, wire, ThisWireInstance]; IF match THEN { quit _ eachSelectedWire[wire]; someMatch _ TRUE; }; }; flatInstance: CoreGeometry.Instance _ instance; quit _ CoreOps.VisitWire[root, ThisWire]; }; quit _ CoreGeometry.FlattenInstance[selectedInstance, EachFlatInstance]; }; IF NOT someMatch THEN ERROR CoreCDUserError["CoreCDUser: Some selected instance does not correspond to any wire"]; }; quit _ ExtractOps.EnumerateSelectedInstances[design, ThisSelectedInstance]; }; <<>> EnumerateSelectedFlatCells: PUBLIC PROC [root: Core.CellType, eachSelectedFlatCell: EachSelectedFlatCellProc, cutSet: CoreFlat.CutSet _ NIL, design: CD.Design _ NIL, decoration: CoreGeometry.Decoration _ NIL] RETURNS [quit: BOOL _ FALSE] = { [design, decoration] _ FindDesignAndDecoration[root, design, decoration]; IF design.actual.rest=NIL THEN { ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = { errorMessage: Rope.ROPE _ NIL; flatCellType: CoreFlat.FlatCellTypeRec _ []; cdInstance.trans _ selectedInstance.trans; cdInstance.ob _ selectedInstance.obj; [errorMessage,,flatCellType] _ BuildFlatCell[cell: root, instances: LIST[cdInstance], pushData: pushData]; IF errorMessage#NIL THEN ERROR CoreCDUserError[errorMessage]; quit _ eachSelectedFlatCell[flatCellType] }; cdInstance: CD.Instance _ NEW[CD.InstanceRep]; pushData: DesignPushData _ GetPushData[design, decoration, root, cutSet]; quit _ ExtractOps.EnumerateSelectedInstances[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: CD.Design, decoration: CoreGeometry.Decoration, rct: CoreClasses.RecordCellType, eachSelectedCellInstance: EachSelectedCellInstanceProc] RETURNS [quit: BOOL _ FALSE] = { ThisSelectedInstance: ExtractOps.EachSelectedInstanceProc = { FOR i: NAT IN [0..rct.size) DO IF CoreGeometry.HasTrans[decoration, rct[i]] AND CoreGeometry.HasObject[decoration, rct[i].type] THEN { IF CoreGeometry.GetTrans[decoration, rct[i]]=selectedInstance.trans AND ExtractOps.SameCDObject[selectedInstance.obj, CoreGeometry.GetObject[decoration, rct[i].type]] THEN { quit _ eachSelectedCellInstance[i]; EXIT; }; }; REPEAT FINISHED => ERROR CoreCDUserError["CoreCDUser: Some selected instance does not correspond to any cell type"]; ENDLOOP; }; quit _ ExtractOps.EnumerateSelectedInstances[design, ThisSelectedInstance]; }; <<>> pushDataAtom: ATOM = $CoreCDUserPushData; CellPushData: TYPE = REF CellPushDataRec; CellPushDataRec: TYPE = RECORD [ decoration: CoreGeometry.Decoration _ NIL, root: Core.CellType _ NIL, cutSet: CoreFlat.CutSet _ NIL, selectionData: RefTab.Ref _ NIL, transitiveClosure: RefTab.Ref _ NIL, viewer: ViewerClasses.Viewer _ NIL, doesNotMatterDesign: CD.Design _ NIL, designPushData: LIST OF DesignPushData _ NIL]; DesignPushData: TYPE = REF DesignPushDataRec; DesignPushDataRec: TYPE = RECORD [ design: CD.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: CD.Design _ NIL, pushData: CellPushData _ NIL, resolve: ResolveData _ NIL, instance: NAT _ 0, objects: LIST OF CoreGeometry.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: CD.Design, decoration: CoreGeometry.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["CoreCDUser: The object of the instance at the top of the push stack is not reachable from the root cell type"]; }; GetPushData: PROC [design: CD.Design, decoration: CoreGeometry.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: CD.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: CD.Design, root: Core.CellType, decoration: CoreGeometry.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 CoreGeometry.Object _ instanceData.objects, objects.rest UNTIL objects=NIL DO IF objects.first=object THEN EXIT; REPEAT FINISHED => instanceData.objects _ CONS[object, instanceData.objects]; ENDLOOP; IF cell#NIL THEN FOR cells: LIST OF Core.CellType _ instanceData.cells, cells.rest UNTIL cells=NIL DO IF cells.first=cell THEN EXIT; REPEAT FINISHED => instanceData.cells _ CONS[cell, instanceData.cells]; ENDLOOP; }; 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 CoreGeometry.Object _ instanceData.objects, objects.rest UNTIL objects=NIL DO TerminalIO.PutRopes[" ", PW.Name[objects.first], "\n"]; ENDLOOP; }; }; }; [] _ IntHashTable.Pairs[resolveList.first.instanceData, AddInstanceChoice]; [] _ TiogaButtons.AppendToButton[button: button, rope: Rope.Cat["(", CoreOps.GetCellTypeName[subCellType], ") "], looks: "f"]; ENDLOOP; ENDLOOP; 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: CD.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: CD.Design _ pushData.design; instanceStack: LIST OF CD.Instance _ NIL; pushData.errorMessage _ NIL; pushData.cellPushData.doesNotMatterDesign _ design; IF design.actual.rest=NIL THEN pushData.errorMessage _ "CoreCDUser: 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["CoreCDUser: 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 _ ExtractOps.SameCDObject[instances.first.ob, CoreGeometry.GetObject[pushData.cellPushData.decoration, cell]]; SELECT TRUE FROM matchingObject AND instances.rest=NIL => { cellType _ cell; flatCellType _ flatCell; }; CoreFlat.CutSetMemberResolved[flatCell, instance, cell, pushData.cellPushData.cutSet] => errorMessage _ "CoreCDUser: 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]; possibleInst: CoreGeometry.Instance _ [CoreGeometry.GetObject[pushData.cellPushData.decoration, thisInstance.type], CoreGeometry.GetTrans[pushData.cellPushData.decoration, thisInstance]]; IF ExtractOps.SameCDInstance[instances.rest.first, instances.first.trans, possibleInst] 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 _ "CoreCDUser: 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 _ "CoreCDUser: 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: CoreGeometry.Object _ NIL]; EnumerateLeastCommonObjectAncestors: PROC [design: CD.Design, root: Core.CellType, decoration: CoreGeometry.Decoration, eachLeastCommonAncestor: EachLeastCommonObjectAncestorProc, cutSet: CoreFlat.CutSet _ NIL] RETURNS [transitiveClosure: RefTab.Ref _ NIL] = { ComputeCellObjectDependence: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType, instance: CoreClasses.CellInstance _ NIL] RETURNS [cellObjects: RefTab.Ref] = { cellObjects _ NARROW[RefTab.Fetch[transitiveClosure, cell].val]; IF cellObjects=NIL THEN { cellObjects _ RefTab.Create[]; IF CoreProperties.GetCellTypeProp[cell, ignoreMeProp]=NIL THEN { IF NOT RefTab.Insert[cellObjects, cell, $DependsOn] THEN ERROR; IF cell.class#CoreClasses.transistorCellClass AND CoreGeometry.HasObject[decoration, cell] THEN IF NOT RefTab.Insert[cellObjects, CoreGeometry.GetObject[ decoration, cell], $DependsOn] THEN ERROR; SELECT TRUE FROM CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => NULL; cell.class=CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; rctHasObject: BOOL _ CoreGeometry.HasObject[decoration, cell]; FOR i: NAT IN [0..rct.size) DO InsertRecordSubObject: RefTab.EachPairAction = { subCell: Core.CellType _ NIL; object: CoreGeometry.Object _ NIL; IF NOT RefTab.Insert[cellObjects, key, NEW[NAT _ i]] THEN { firstInstance: REF ANY _ RefTab.Fetch[cellObjects, key].val; ambiguousMultipath: BOOL _ TRUE; WITH key SELECT FROM o: CoreGeometry.Object => { object _ o; IF rctHasObject THEN ambiguousMultipath _ RefTab.Fetch[topObjects, object].found; }; s: Core.CellType => { subCell _ s; ambiguousMultipath _ NOT CoreGeometry.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: ExtractOps.TopInstanceLists _ ExtractOps.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: CD.Design _ NIL, decoration: CoreGeometry.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 _ "CoreCDUser: 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: CD.Design _ NIL, decoration: CoreGeometry.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 _ "CoreCDUser: No cell type(s) found"; EXITS Done => NULL; }; IF errorMsg#NIL THEN TerminalIO.PutRopes[errorMsg, "\n"]; }; <> wireHighlightClass _ CD.FetchObjectClass[wireHighlightProp]; IF wireHighlightClass=NIL THEN wireHighlightClass _ CD.RegisterObjectClass[wireHighlightProp, [drawMe: WireHighlightDrawMe, description: "WireHighlight"]] ELSE wireHighlightClass.drawMe _ WireHighlightDrawMe; CDEvents.RegisterEventProc[event: $AfterPush, proc: PushPop]; CDEvents.RegisterEventProc[event: $AfterPop, proc: PushPop]; END.