SXHighlightNodeImpl.mesa
Copyright © 1984, 1985 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: Jacobi, July 25, 1985 3:22:38 pm PDT
Last edited by: gbb July 26, 1985 1:37:51 pm PDT
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
IncludeHighLight: PROC [design: CD.Design, rect: CD.Rect] =
BEGIN
app: CD.Instance = CDInstances.NewInstance[
ob: CDRects.CreateBareRect[CDBasics.SizeOfRect[rect], CD.highLightShade],
location: CDBasics.BaseOfRect[rect]
];
CDOps.IncludeInstance[design, app];
CDProperties.PutPropOnInstance[app, $highLightNode, $highLightNode];
END; -- IncludeHighLight
RemoveHighlightNode: PUBLIC PROC [design: CD.Design] =
BEGIN
IsHighLight: PROC [app: CD.Instance] RETURNS [BOOL] =
INLINE BEGIN
RETURN [app=NIL OR
CDProperties.GetPropFromInstance[app, $highLightNode]=$highLightNode
]
END;
al: CD.InstanceList ← CONS[NEW[CD.InstanceRep], CDOps.InstList[design]];
list: CD.InstanceList ← al;
WHILE list.rest#NIL DO
IF IsHighLight[list.rest.first] THEN {
CDOps.DelayedRedraw[design, CDInstances.InstRectO[list.rest.first]];
list.rest ← list.rest.rest
}
ELSE list ← list.rest
ENDLOOP;
CDOps.SetInstList[design, al.rest];
END; -- RemoveHighlightNode
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;
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.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.
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...