<> <> <> <> <> <> DIRECTORY Atom USING [GetPropFromList], CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, highLightShade, Instance, InstanceList, Layer, Orientation, original, Position, Rect], CDBasics USING [BaseOfRect, Extend, SizeOfRect, ToRect, universe], CDDirectory USING [Name], CDInstances USING [NewInstance], CDOps USING [LayerName], CDOrient USING [ComposeOrient, DecomposeOrient, DeMapRect, MapRect, RectAt], CDProperties USING [GetProp], CDRects USING [CreateBareRect], CDViewer USING [ViewerList, ViewersOf], CDViewHighlight USING [ShowInstance], CornerStitching, RefTab USING [EachPairAction, Pairs], Rope USING [Cat], SX, SXAccessInternal, SXAtoms USING [SignalName, spinifex], SXHighlightNode, SXQuadTree USING [Dimension, Enumerate, PerRectProc], TerminalIO USING [WriteRope]; SXHighlightNodeImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDDirectory, CDInstances, CDOps, CDOrient, CDProperties, CDRects, CDViewer, CDViewHighlight, CornerStitching, RefTab, Rope, SX, SXAccessInternal, SXAtoms, SXQuadTree, TerminalIO EXPORTS SXHighlightNode = BEGIN <> <> <> <> <> <<];>> <> <> <> <> <> <> <> <> <> <<]>> <> <> <> <> <> <> <> <<}>> <> <> <> <> RemoveHighlightNode: PUBLIC PROC [design: CD.Design] = BEGIN vl: CDViewer.ViewerList _ CDViewer.ViewersOf[design]; FOR list: CDViewer.ViewerList _ vl, list.rest WHILE list#NIL DO CDViewHighlight.ShowInstance[list.first, NIL, TRUE, $SX]; ENDLOOP; END; -- RemoveHighlightNode IncludeHighLight: PROC [design: CD.Design, rect: CD.Rect] = BEGIN vl: CDViewer.ViewerList _ CDViewer.ViewersOf[design]; app: CD.Instance = CDInstances.NewInstance[ ob: CDRects.CreateBareRect[CDBasics.SizeOfRect[rect], CD.highLightShade], location: CDBasics.BaseOfRect[rect] ]; FOR list: CDViewer.ViewerList _ vl, list.rest WHILE list#NIL DO CDViewHighlight.ShowInstance[list.first, app, FALSE, $SX]; ENDLOOP; END; -- IncludeHighLight HighlightNode: PUBLIC PROC [design: CD.Design, pos: CD.Position, lev: CD.Layer] = BEGIN WITH CDProperties.GetProp[design.technology, SXAtoms.spinifex] SELECT FROM tpOK: REF SX.TechHandle => { FOR mapList: LIST OF SX.MapRec _ tpOK.cdLayerMapping[lev], mapList.rest WHILE mapList#NIL DO IF mapList.first.value = NIL THEN { rootCir: REF SX.Circuit = SXAccessInternal.GetSXData[design.actual.first.dummyCell.ob].circuit; <> data: REF SearchData _ NEW[SearchData _ [ layer: lev, nodeLayer: mapList.first.spinifexLayer, tech: tpOK, rootCir: rootCir, cir: rootCir ]]; GoForIt[data, design, pos]; RETURN }; REPEAT FINISHED => { TerminalIO.WriteRope[Rope.Cat[" ", CDOps.LayerName[lev], " is not conducting\n"]]; RETURN } ENDLOOP; }; ENDCASE => TerminalIO.WriteRope["technology does not support spinifex\n"]; END; -- HighlightNode GoForIt: PROC [sd: REF SearchData, design: CD.Design, pos: CD.Position] = BEGIN AddSplodge: CornerStitching.PerTileProc = <<--[tile: TilePtr, data: REF ANY] -- >> BEGIN rect: CD.Rect = CDOrient.MapRect[tile.Area, sd.rootSize, sd.rootOrient, sd.rootPos]; IncludeHighLight[design, rect]; END; dr: CD.DrawRef = CD.CreateDrawRef[design]; nodeGeom: REF CornerStitching.Tesselation; RemoveHighlightNode[design]; dr.drawChild _ CompensateDummyCell; -- Used for outermost cell only, dr.drawChild set to SearchChild for recursive calls inside CompensateDummyCell. dr.drawRect _ CheckRect; dr.devicePrivate _ sd; IF design.actual.first.mightReplace#NIL THEN { sd.rootSize _ sd.pushSize _ design.actual.first.mightReplace.ob.size; sd.rootPos _ sd.pushPos _ design.actual.first.mightReplace.location; sd.rootOrient _ sd.pushOrient _ design.actual.first.mightReplace.orientation }; dr.interestClip _ CDBasics.Extend[CDBasics.ToRect[pos, pos], 1]; <<-- find the node we wish to highlight.>> design.actual.first.dummyCell.ob.class.drawMe[design.actual.first.dummyCell, [0,0], CD.original, dr]; IF sd.node = NIL THEN { TerminalIO.WriteRope[ Rope.Cat[ " Failed to find geometry on layer: \"", CDOps.LayerName[sd.layer], "\" at indicated point.\n"]]; RETURN }; <<-- find the highest layer node to which the node we wish to highlight is merged.>> [sd.node, sd.applChain] _ sd.rootCir.FindRootNode[sd.node, sd.applChain]; WITH sd.node.properties.GetPropFromList[SXAtoms.SignalName] SELECT FROM sig: REF SX.SignalName => { TerminalIO.WriteRope[Rope.Cat[" Highlighting: ", sig.name,".\n"]] }; ENDCASE => { TerminalIO.WriteRope[" Highlighting node.\n"] }; IF sd.applChain#NIL THEN -- Node appeared on some subcircuit, rather than root. sd.cir _ SXAccessInternal.GetSXData[sd.applChain.first.ob].circuit ELSE sd.cir _ sd.rootCir; <<-- find all rectangles connected to the high-layer node.>> nodeGeom _ CornerStitching.NewTesselation[]; Paint[sd, nodeGeom]; <<-- add rectangles to the currently pushed ChipNDale cell which cover all the rectangles in the highlighted node.>> [] _ nodeGeom.EnumerateArea[CDBasics.universe, AddSplodge]; END; -- GoForIt SearchData: TYPE = RECORD [ layer: CD.Layer, nodeLayer: SX.SpinifexLayerIndex, tech: REF SX.TechHandle, rootCir: REF SX.Circuit, -- Highest Spinifex SX.Circuit found in application chain. cir: REF SX.Circuit, node: REF SX.CircuitNode _ NIL, applChain: LIST OF CD.Instance _ NIL, pushSize: CD.Position _ [0,0], pushPos: CD.Position _ [0,0], pushOrient: CD.Orientation _ CD.original, rootSize: CD.Position _ [0,0], rootPos: CD.Position _ [0,0], rootOrient: CD.Orientation _ CD.original ]; CompensateDummyCell: CD.DrawProc = <<-- PROC [aptr: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: REF CD.DrawInformation] >> BEGIN data: REF SearchData = NARROW[pr.devicePrivate]; oldClip: CD.Rect = pr.interestClip; pr.drawChild _ SearchChild; <<-- For outermost cell transforms must be precompensated for transform compositions which occur in DrawMe. In subcells such precompensation is not required.>> pr.interestClip _ CDOrient.DeMapRect[itemInWorld: oldClip, cellSize: data.pushSize, cellInstOrient: data.pushOrient, cellInstPos: data.pushPos]; pos _ CDBasics.BaseOfRect[CDOrient.DeMapRect[ CDOrient.RectAt[pos: pos, size: inst.ob.size, orient: orient], data.pushSize, data.pushOrient, data.pushPos ]]; orient _ CDOrient.DecomposeOrient[orient, data.pushOrient]; <<-- Now really start searching.>> SearchChild[inst, pos, orient, pr]; pr.interestClip _ oldClip; pr.drawChild _ CompensateDummyCell END; -- CompensateDummyCell SearchChild: CD.DrawProc = <<--PROC [aptr: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: REF CD.DrawInformation] >> BEGIN sx: REF SX.LogicalCell = SXAccessInternal.GetSXData[inst.ob]; IF sx#NIL AND sx.circuit#NIL AND sx.analysisState=useCircuit THEN { <<--This object is a logical subcircuit.>> subcircuit: REF SX.Circuit _ sx.circuit; data: REF SearchData = NARROW[pr.devicePrivate]; oldClip: CD.Rect = pr.interestClip; cir: REF SX.Circuit = data.cir; root: REF SX.Circuit = data.rootCir; appl: CD.Instance; oldChain: LIST OF CD.Instance = data.applChain; data.cir _ subcircuit; IF data.rootCir = NIL THEN { data.rootCir _ subcircuit; data.rootSize _ inst.ob.size; data.rootPos _ CDBasics.BaseOfRect[CDOrient.MapRect[ CDOrient.RectAt[pos: pos, size: data.rootSize, orient: orient], data.pushSize, data.pushOrient, data.pushPos ]]; data.rootOrient _ CDOrient.ComposeOrient[orient, data.pushOrient] }; pr.interestClip _ CDOrient.DeMapRect[ itemInWorld: oldClip, cellSize: inst.ob.size, cellInstOrient: orient, cellInstPos: pos ]; IF cir # NIL THEN { FOR aList: CD.InstanceList _ cir.subcircuits, aList.rest WHILE aList # NIL DO appl _ aList.first; IF appl.location=pos AND appl.orientation=orient AND appl.ob=inst.ob THEN EXIT; REPEAT FINISHED => { ERROR }; ENDLOOP; data.applChain _ CONS[appl, data.applChain]; }; inst.ob.class.drawMe[inst, [0,0], CD.original, pr]; IF cir # NIL THEN data.cir _ cir; IF pr.stopFlag^ = FALSE THEN { data.applChain _ oldChain; data.rootCir _ root }; pr.interestClip _ oldClip } ELSE { data: REF SearchData = NARROW[pr.devicePrivate]; sx: REF SX.LogicalCell = SXAccessInternal.GetSXData[inst.ob]; IF sx#NIL AND sx.analysisState=notYetDone AND data.cir#NIL THEN { TerminalIO.WriteRope[Rope.Cat[" ", CDDirectory.Name[inst.ob], " has not been extracted\n"]]; ERROR ABORTED }; inst.ob.class.drawMe[inst, pos, orient, pr] } END; -- SearchChild CheckRect: CD.DrawRectProc = <<--PROC[r: Rect, l: Layer, pr: DrawRef] -- >> BEGIN IF l = NARROW[pr.devicePrivate, REF SearchData].layer THEN { SearchNode: SXQuadTree.PerRectProc = <<--PROC[r: REF Rectangle, data: REF ANY] -- >> BEGIN WITH r.nodeInformation SELECT FROM n: REF SX.CircuitNode => sData.node _ n; -- XXX FIX HERE, pr.stopFlag should be set only if node is found. ENDCASE; pr.stopFlag^ _ TRUE END; -- SearchNode sData: REF SearchData = NARROW[pr.devicePrivate]; IF sData.cir = NIL THEN { TerminalIO.WriteRope[" design has not been analyzed.\n"]; ERROR ABORTED }; SXQuadTree.Enumerate [quadTree: sData.cir.spinifexLayers[sData.nodeLayer], clipRect: pr.interestClip, PerRect: SearchNode] } END; -- CheckRect Paint: PROC [data: REF SearchData, protoPaint: REF CornerStitching.Tesselation] = BEGIN Compose: PROC [pos: CD.Position, orient: CD.Orientation, size: CD.Position, applChain: LIST OF CD.Instance] RETURNS [combPos: CD.Position, combOrient: CD.Orientation] = BEGIN IF applChain.rest # NIL THEN { [pos, orient] _ Compose[pos, orient, applChain.rest.first.ob.size, applChain.rest]; combPos _ CDBasics.BaseOfRect[CDOrient.MapRect[ CDOrient.RectAt[ pos: applChain.first.location, size: applChain.first.ob.size, orient: applChain.first.orientation ], applChain.rest.first.ob.size, orient, pos ]]; combOrient _ CDOrient.ComposeOrient[applChain.first.orientation, orient] } ELSE { combPos _ CDBasics.BaseOfRect[CDOrient.MapRect[ CDOrient.RectAt[ pos: applChain.first.location, size: applChain.first.ob.size, orient: applChain.first.orientation ], size, orient, pos ]]; combOrient _ CDOrient.ComposeOrient[applChain.first.orientation, orient] } END; -- Compose PerCell: PROC [circuit: REF SX.Circuit, node: REF SX.CircuitNode, pos: CD.Position, orient: CD.Orientation, size: CD.Position] = BEGIN PaintNode: SXQuadTree.PerRectProc = -- PROC [r: REF Rectangle, data: REF ANY] -- BEGIN IF r.nodeInformation=data THEN { newR: CD.Rect = CDOrient.MapRect[ itemInCell: SXQuadTree.Dimension [r], cellSize: size, cellInstOrient: orient, cellInstPos: pos ]; protoPaint.ChangeRect[newR, SXAtoms.spinifex] } END; -- PaintNode SearchForPortConnection: RefTab.EachPairAction = <<--PROC[key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] -- >> BEGIN FOR ml: SX.MergeRecList _ NARROW[val], ml.rest WHILE ml # NIL DO IF ml.first.becomes = node THEN { applChain: LIST OF CD.Instance = ml.first.applChain; subCircuit: REF SX.Circuit = SXAccessInternal.GetSXData[applChain.first.ob].circuit; subnode: REF SX.CircuitNode = NARROW[key]; subPos: CD.Position; subOrient: CD.Orientation; [subPos, subOrient] _ Compose[pos, orient, size, applChain]; PerCell[subCircuit, subnode, subPos, subOrient, applChain.first.ob.size]; } ENDLOOP; RETURN [FALSE] END; -- SearchForPortConnection FOR layer: SX.SpinifexLayerIndex IN [0..data.tech.numSpinifexLayers) DO SXQuadTree.Enumerate [quadTree: circuit.spinifexLayers[layer], clipRect: CDBasics.universe, PerRect: PaintNode, data: node] ENDLOOP; IF circuit.mergeDirectory#NIL THEN [] _ circuit.mergeDirectory.Pairs[SearchForPortConnection] END; -- PerCell pos: CD.Position _ [0,0]; orient: CD.Orientation _ CD.original; ac: LIST OF CD.Instance = data.applChain; -- list of cells down to the node. IF ac#NIL THEN [pos, orient] _ Compose[pos, orient, [0,0], ac]; PerCell[data.cir, data.node, pos, orient, IF ac = NIL THEN [0,0] ELSE ac.first.ob.size] END; -- Paint END. <<>> <> <> <> <> <> <> <> <> <> <> <> <<>> <<>>