SXHighlightNodeImpl.mesa
Copyright © 1984, 1985, 1987 by Xerox Corporation. All rights reserved.
Written by: Mark Shand, August 8, 1984 11:39:46 am PDT
Last edited by: Shand, September 3, 1984 5:51:16 am PDT
Last edited by: Christian Jacobi, July 25, 1985 3:22:38 pm PDT
Last edited by: Christian Jacobi, February 24, 1987 1:11:07 pm PST
Last edited by: gbb June 6, 1986 2:41:28 pm PDT
DIRECTORY
CD,
CDBasics,
CDInstances USING [NewInst],
CDOps USING [LayerRope],
CDProperties USING [GetProp],
CDRects USING [CreateBareRect],
CDViewer USING [ViewerList, ViewersOf],
CDViewHighlight USING [ShowInstance],
CStitching,
Properties USING [GetProp],
RefTab USING [EachPairAction, Pairs],
Rope USING [Cat],
SX,
SXAccessInternal,
SXAtoms USING [SignalName, spinifex],
SXHighlightNode,
SXQuadTree USING [Dimension, Enumerate, PerRectProc],
TerminalIO USING [PutRope, PutRopes];
SXHighlightNodeImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDInstances, CDOps, CDProperties, CDRects, CDViewer, CDViewHighlight, CStitching, Properties, 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.NewInst [
ob: CDRects.CreateBareRect [CDBasics.SizeOfRect[rect], CD.shadeLayer],
trans: [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.GetLogicalCell[design.actual.first.dummyCell.ob].circuit;
OK if NIL!
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.PutRope [Rope.Cat[" ", CDOps.LayerRope[lev], " is not conducting\n"]];
RETURN
}
ENDLOOP;
};
ENDCASE => TerminalIO.PutRope ["technology does not support Spinifex\n"];
END; -- HighlightNode
GoForIt: PROC [sd: REF SearchData, design: CD.Design, pos: CD.Position] = BEGIN
AddSplodge: CStitching.TileProc = BEGIN
[tile: TilePtr, data: REF ANY]
rect: CD.Rect = CDBasics.MapRect[tile.Area, sd.rootTrans];
IncludeHighLight [design, rect];
END;
dr: CD.DrawRef = CD.CreateDrawRef [[]];
nodeGeom: CStitching.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.pushTrans ← sd.rootTrans ← design.actual.first.mightReplace.trans
};
dr.interestClip ← CDBasics.Extend [CDBasics.ToRect[pos, pos], 1];
find the node we wish to highlight.
CD.DrawOb[dr, design.actual.first.dummyCell.ob];
IF sd.node = NIL THEN {
TerminalIO.PutRope [Rope.Cat[ " Failed to find geometry on layer \"", CDOps.LayerRope[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 Properties.GetProp [sd.node.properties, SXAtoms.SignalName] SELECT FROM
sig: REF SX.SignalName => {
TerminalIO.PutRope [Rope.Cat [" Highlighting: ", sig.name,".\n"]]
};
ENDCASE => {
TerminalIO.PutRope [" Highlighting node.\n"]
};
IF sd.applChain#NIL THEN-- Node appeared on some subcircuit, rather than root.
sd.cir ← SXAccessInternal.GetLogicalCell[sd.applChain.first.ob].circuit
ELSE
sd.cir ← sd.rootCir;
find all rectangles connected to the high-layer node.
nodeGeom ← CStitching.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,
pushTrans: CD.Transformation ← [],
rootTrans: CD.Transformation ← []
];
CompensateDummyCell: CD.DrawProc = 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 ← CDBasics.DeMapRect[itemInWorld: oldClip, cellInWorld: data.pushTrans];
trans ← CDBasics.DecomposeTransform [itemInWorld: trans, cellInWorld: data.pushTrans];
Now really start searching.
SearchChild [pr, ob, trans, NIL];
pr.interestClip ← oldClip;
pr.drawChild ← CompensateDummyCell
END; -- CompensateDummyCell
SearchChild: CD.DrawProc = BEGIN
sx: REF SX.LogicalCell = SXAccessInternal.GetLogicalCell[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.rootTrans ← CDBasics.ComposeTransform[itemInCell: trans, cellInWorld: data.pushTrans];
};
pr.interestClip ← CDBasics.DeMapRect [
itemInWorld: oldClip,
cellInWorld: trans];
IF cir # NIL THEN {
FOR aList: CD.InstanceList ← cir.subcircuits, aList.rest WHILE aList # NIL DO
appl ← aList.first;
IF appl.trans=trans AND appl.ob=ob THEN EXIT;
REPEAT FINISHED => {ERROR};
ENDLOOP;
data.applChain ← CONS [appl, data.applChain];
};
CD.DrawOb[pr, ob];
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.GetLogicalCell [ob];
IF sx#NIL AND sx.analysisState=notYetDone AND data.cir#NIL THEN {
TerminalIO.PutRopes[" ", CD.Describe[ob, NIL, NIL], " has not been extracted\n"];
ERROR ABORTED
};
CD.DrawOb[pr, ob, trans, readOnlyInstProps];
}
END; -- SearchChild
CheckRect: CD.DrawRectProc = BEGIN
PROC[r: Rect, l: Layer, pr: DrawRef]
IF l = NARROW[pr.devicePrivate, REF SearchData].layer THEN {
SearchNode: SXQuadTree.PerRectProc = BEGIN
PROC[r: REF Rectangle, data: REF ANY]
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.PutRope [" 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: CStitching.Tesselation] = BEGIN
Compose: PROC [trans: CD.Transformation, applChain: LIST OF CD.Instance] RETURNS [comb: CD.Transformation] = BEGIN
IF applChain.rest # NIL THEN {
[comb] ← Compose [trans, applChain.rest];
comb ← CDBasics.ComposeTransform[itemInCell: applChain.first.trans, cellInWorld: trans];
}
ELSE {
comb ← CDBasics.ComposeTransform[itemInCell: applChain.first.trans, cellInWorld: trans];
}
END; -- Compose
PerCell: PROC [circuit: REF SX.Circuit, node: REF SX.CircuitNode, trans: CD.Transformation] = BEGIN
PaintNode: SXQuadTree.PerRectProc = BEGIN
PROC [r: REF Rectangle, data: REF ANY]
IF r.nodeInformation=data THEN {
newR: CD.Rect = CDBasics.MapRect [
itemInCell: SXQuadTree.Dimension [r],
cellInWorld: trans];
protoPaint.ChangeRect [newR, SXAtoms.spinifex]
}
END; -- PaintNode
SearchForPortConnection: RefTab.EachPairAction = BEGIN
PROC[key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]
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.GetLogicalCell[applChain.first.ob].circuit;
subnode: REF SX.CircuitNode = NARROW [key];
subTrans: CD.Transformation ← Compose [trans, applChain];
PerCell [subCircuit, subnode, subTrans];
}
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
trans: CD.Transformation ← [];
ac: LIST OF CD.Instance = data.applChain; -- list of cells down to the node.
IF ac#NIL THEN [trans] ← Compose [trans, ac];
PerCell [data.cir, data.node, trans]
END; -- Paint
END.
Edited on March 4, 1985 4:23:17 pm PST, by Jacobi
removing errors reprogrammed, without using drawprocs
Edited on March 5, 1985 8:59:52 am PST, by Jacobi
made readable
Edited on April 8, 1985 2:51:21 pm PST, by Jacobi
use of SXAccessInternal instead of properties; SpinifexCellPredicate removed
Edited on May 6, 1985 11:26:55 am PDT, by Beretta
Converted to ChipNDale CD20
Edited on July 25, 1985 3:20:45 pm PDT, by Jacobi
Use of CDViewHighlight instead of changing the design
I don't like the loop over all viewers, but I don't want to change the interface and can't know which is the right viewer...