SpinifexHighlightNodeImpl.mesa
Copyright © 1984 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
DIRECTORY
TerminalIO USING [WriteRope],
CD USING [highLightShade, LevelKey, Design, DesignPosition, ApplicationList, ApplicationPtr, Level, DrawProc, NewNullDeviceDrawRef, DrawRef, DrawRectProc, original, Rect, Orientation],
CDOps USING [IncludeApplication, RemoveApplication],
CDApplications USING [NewApplicationI],
CDRects USING [CreateBareRect],
CDProperties USING [GetProp, GetPropFromObject],
CDInline USING [Extend, ToRect, SizeOfRect, BaseOfRect, universe],
CDOrient USING [DeMapRect, MapRect, ComposeOrient, DecomposeOrient, MapPosition, RectAt],
CDDirectory USING [Name],
Atom USING [GetPName, GetPropFromList],
Rope USING [Cat],
RefTab USING [Pairs, EachPairAction],
SpinifexCircuit USING [Circuit, CircuitNode, TechHandle, MapRec, SpinifexLayerIndex, FindRootNode, EnumerateGeometry, Dimension, PerRectProc, MergeRecList, SignalName],
SpinifexAtoms USING [spinifex, SignalName],
SpinifexCellPredicates USING [IsLogicalCell],
CornerStitching USING [Tesselation, NewTesselation, ChangeRect, EnumerateArea, PerTileProc, Area],
SpinifexHighlightNode
;
SpinifexHighlightNodeImpl:
CEDAR
PROGRAM
IMPORTS TerminalIO, CD, CDOps, CDApplications, CDRects, CDProperties, CDInline, CDOrient, CDDirectory, Atom, Rope, RefTab, SpinifexCircuit, SpinifexAtoms, SpinifexCellPredicates, CornerStitching
EXPORTS SpinifexHighlightNode
~ BEGIN
Circuit: TYPE ~ SpinifexCircuit.Circuit;
HighlightNode:
PUBLIC
PROCEDURE [design:
CD.Design, pos:
CD.DesignPosition, lev:
CD.Level] ~ {
techProp: REF ANY;
-- Check that this technology can be analyzed.
IF design.technology =
NIL
THEN
TerminalIO.WriteRope[" Design does not specify a technology.\n"]
ELSE IF (techProp ← CDProperties.GetProp[from~design.technology, prop~SpinifexAtoms.spinifex]) =
NIL
THEN
TerminalIO.WriteRope[ Rope.Cat[ " \"", design.technology.name, "\" technology lacks analysis capability.\n"]]
ELSE WITH techProp
SELECT FROM
tpOK:
REF SpinifexCircuit.TechHandle => {
FOR mapList:
LIST
OF SpinifexCircuit.MapRec ← tpOK.cdLayerMapping[lev], mapList.rest
WHILE mapList #
NIL
DO
IF mapList.first.value =
NIL THEN {
rootCir: REF Circuit ~ NARROW[CDProperties.GetPropFromObject[ from~design.actual.first.dummyCell.ob, prop~SpinifexAtoms.spinifex]]; -- OK if NIL!
data: REF SearchData ← NEW[SearchData ← [level~ lev, nodeLayer~ mapList.first.spinifexLayer, tech~ tpOK, rootCir~ rootCir, cir~ rootCir]];
GoForIt[data, design, pos];
RETURN
};
REPEAT
FINISHED => {
TerminalIO.WriteRope[ Rope.Cat[ " \"", Atom.GetPName[CD.LevelKey[lev]], "\" is not a conducting layer.\n"]];
RETURN
}
ENDLOOP;
};
ENDCASE => TerminalIO.WriteRope[ Rope.Cat[ " \"", design.technology.name, "\" technology capability is invalid.\n"]];
ERROR ABORTED
};
GoForIt:
PROCEDURE [sd:
REF SearchData, design:
CD.Design, pos:
CD.DesignPosition] ~ {
AddSplodge: CornerStitching.PerTileProc
--
[tile: TilePtr, data: REF ANY] -- ~ {
PaintRect: CD.Rect ~ CDOrient.MapRect[tile.Area, sd.rootSize, sd.rootOrient, sd.rootPos];
CDOps.IncludeApplication[design, CDApplications.NewApplicationI[ob~ CDRects.CreateBareRect[CDInline.SizeOfRect[PaintRect], CD.highLightShade], location~ CDInline.BaseOfRect[PaintRect], orientation~ CD.original]];
};
dr: CD.DrawRef ~ CD.NewNullDeviceDrawRef[design];
nodeGeom: REF CornerStitching.Tesselation;
Delete old highlighting.
dr.drawChild ← FindHighlights;
dr.drawRect ← dr.saveRect ← Oops;
dr.devicePrivate ← NIL;
design.actual.first.dummyCell.ob.p.drawMe[design.actual.first.dummyCell, [0,0], CD.original, dr];
FOR dQ:
LIST
OF
CD.ApplicationPtr ←
NARROW[dr.devicePrivate], dQ.rest
WHILE dQ #
NIL
DO
CDOps.RemoveApplication[ design, dQ.first];
ENDLOOP;
dr.drawChild ← CompensateDummyCell;
dr.drawRect ← dr.saveRect ← 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.worldClip ← CDInline.Extend[CDInline.ToRect[pos, pos], 1];
design.actual.first.dummyCell.ob.p.drawMe[design.actual.first.dummyCell, [0,0], CD.original, dr];
IF sd.node =
NIL
THEN {
TerminalIO.WriteRope[ Rope.Cat[ " Failed to find geometry on level: \"", Atom.GetPName[CD.LevelKey[sd.level]], "\" at indicated point.\n"]];
RETURN
};
[sd.node, sd.applChain] ← sd.rootCir.FindRootNode[sd.node, sd.applChain];
WITH sd.node.properties.GetPropFromList[ SpinifexAtoms.SignalName]
SELECT
FROM
sig:
REF SpinifexCircuit.SignalName => {
TerminalIO.WriteRope[Rope.Cat[" Highlighting: ", sig.name,".\n"]]
};
ENDCASE => {
TerminalIO.WriteRope[" Highlighting node.\n"]
};
IF sd.applChain #
NIL
THEN
sd.cir ← NARROW[CDProperties.GetPropFromObject[ from~sd.applChain.first.ob, prop~SpinifexAtoms.spinifex]]
ELSE
sd.cir ← sd.rootCir;
nodeGeom ← CornerStitching.NewTesselation[];
Paint[sd, nodeGeom];
[] ← nodeGeom.EnumerateArea[CDInline.universe, AddSplodge];
};
FindHighlights:
CD.DrawProc
--
[aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: REF CD.DrawInformation] -- ~ {
SELECT aptr.ob.p.objectType
FROM
$Rect, $SaveRect =>
IF aptr.ob.level =
CD.highLightShade
THEN {
DelQ: LIST OF CD.ApplicationPtr ~ NARROW[ pr.devicePrivate];
pr.devicePrivate ← NARROW[ CONS[aptr, DelQ], LIST OF CD.ApplicationPtr];
};
ENDCASE => NULL;
};
Oops: CD.DrawRectProc ~ { ERROR };
SearchData:
TYPE ~
RECORD [
level: CD.Level,
nodeLayer: SpinifexCircuit.SpinifexLayerIndex,
tech: REF SpinifexCircuit.TechHandle,
rootCir: REF Circuit,
cir: REF Circuit,
node: REF SpinifexCircuit.CircuitNode ← NIL,
applChain: LIST OF CD.ApplicationPtr ← NIL,
pushSize: CD.DesignPosition ← [0,0],
pushPos: CD.DesignPosition ← [0,0],
pushOrient: CD.Orientation ← CD.original,
rootSize: CD.DesignPosition ← [0,0],
rootPos: CD.DesignPosition ← [0,0],
rootOrient: CD.Orientation ← CD.original
];
CompensateDummyCell:
CD.DrawProc
--
[aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: REF CD.DrawInformation] -- ~ {
data: REF SearchData ~ NARROW[pr.devicePrivate];
oldClip: CD.Rect ~ pr.worldClip;
pr.drawChild ← SearchChild;
pr.worldClip ← CDOrient.DeMapRect[itemInWorld~ oldClip, cellSize~ data.pushSize, cellInstOrient~ data.pushOrient, cellInstPos~ data.pushPos];
pos ← CDInline.BaseOfRect[CDOrient.DeMapRect[CDOrient.RectAt[pos~ pos, size~ aptr.ob.size, orient~ orient], data.pushSize, data.pushOrient, data.pushPos]];
orient ← CDOrient.DecomposeOrient[orient, data.pushOrient];
SearchChild[aptr, pos, orient, pr];
pr.worldClip ← oldClip;
pr.drawChild ← CompensateDummyCell
};
Search
Child:
CD.DrawProc
--
[aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: REF CD.DrawInformation] -- ~ {
WITH CDProperties.GetPropFromObject[ from~aptr.ob, prop~SpinifexAtoms.spinifex]
SELECT FROM
subcircuit:
REF Circuit => {
This object is a logical subcircuit.
data: REF SearchData ~ NARROW[pr.devicePrivate];
oldClip: CD.Rect ~ pr.worldClip;
cir: REF Circuit ~ data.cir;
root: REF Circuit ~ data.rootCir;
appl: CD.ApplicationPtr;
oldChain: LIST OF CD.ApplicationPtr ~ data.applChain;
data.cir ← subcircuit;
IF data.rootCir =
NIL
THEN {
data.rootCir ← subcircuit;
data.rootSize ← aptr.ob.size;
data.rootPos ← CDOrient.MapPosition[CDOrient.RectAt[ pos~ pos, size~ data.rootSize, orient~ orient], data.pushSize, data.pushOrient, data.pushPos];
data.rootOrient ← CDOrient.ComposeOrient[orient, data.pushOrient]
};
pr.worldClip ← CDOrient.DeMapRect[itemInWorld~ oldClip, cellSize~ aptr.ob.size, cellInstOrient~ orient, cellInstPos~ pos];
IF cir #
NIL
THEN {
FOR aList:
CD.ApplicationList ← cir.subcircuits, aList.rest
WHILE aList #
NIL
DO
appl ← aList.first;
IF appl.location = pos AND appl.orientation = orient AND appl.ob = aptr.ob THEN EXIT;
REPEAT
FINISHED => {
ERROR
};
ENDLOOP;
data.applChain ← CONS[appl, data.applChain];
};
aptr.ob.p.drawMe[aptr, [0,0], CD.original, pr];
IF cir # NIL THEN data.cir ← cir;
IF pr.stopFlag^ =
FALSE
THEN {
data.applChain ← oldChain;
data.rootCir ← root
};
pr.worldClip ← oldClip
};
ENDCASE => {
data: REF SearchData ~ NARROW[pr.devicePrivate];
IF SpinifexCellPredicates.IsLogicalCell[aptr.ob]
AND data.cir #
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat[ " Cell \"", CDDirectory.Name[aptr.ob], "\" has not been extracted.\n"]];
ERROR ABORTED
};
aptr.ob.p.drawMe[aptr, pos, orient, pr]
}
};
CheckRect:
CD.DrawRectProc
--
[r: DesignRect, l: Level, pr: DrawRef] -- ~ {
IF l =
NARROW[pr.devicePrivate,
REF SearchData].level
THEN {
SearchNode: SpinifexCircuit.PerRectProc
--
[r: REF Rectangle, data: REF ANY] -- ~ {
WITH r.nodeInformation
SELECT
FROM
n: REF SpinifexCircuit.CircuitNode => sData.node ← n;
ENDCASE;
pr.stopFlag^ ← TRUE
};
sData: REF SearchData ~ NARROW[pr.devicePrivate];
IF sData.cir =
NIL
THEN {
TerminalIO.WriteRope[" Design has not been analyzed.\n"];
ERROR ABORTED
};
sData.cir.EnumerateGeometry[sData.nodeLayer, pr.worldClip, SearchNode, NIL]
}
};
Paint:
PROCEDURE [data:
REF SearchData, protoPaint:
REF CornerStitching.Tesselation] ~ {
Compose:
PROCEDURE [pos:
CD.DesignPosition, orient:
CD.Orientation, size:
CD.DesignPosition, applChain:
LIST
OF
CD.ApplicationPtr]
RETURNS [combPos:
CD.DesignPosition, combOrient:
CD.Orientation] ~ {
IF applChain.rest #
NIL
THEN {
[pos, orient] ← Compose[pos, orient, applChain.rest.first.ob.size, applChain.rest];
combPos ← CDOrient.MapPosition[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 ← CDOrient.MapPosition[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]
}
};
PerCell:
PROCEDURE [circuit:
REF Circuit, node:
REF SpinifexCircuit.CircuitNode, pos:
CD.DesignPosition, orient:
CD.Orientation, size:
CD.DesignPosition] ~ {
PaintNode: SpinifexCircuit.PerRectProc
--
[r: REF Rectangle, data: REF ANY] -- ~ {
IF r.nodeInformation = data
THEN {
newR: CD.Rect ~ CDOrient.MapRect[ itemInCell~ r.Dimension, cellSize~ size, cellInstOrient~ orient, cellInstPos~ pos];
protoPaint.ChangeRect[newR, SpinifexAtoms.spinifex]
}
};
SearchForPortConnection: RefTab.EachPairAction
-- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] -- ~ {
FOR ml: SpinifexCircuit.MergeRecList ←
NARROW[val], ml.rest
WHILE ml #
NIL
DO
IF ml.first.becomes = node
THEN {
applChain: LIST OF CD.ApplicationPtr ~ ml.first.applChain;
subCircuit: REF Circuit ~ NARROW[CDProperties.GetPropFromObject[ from~ applChain.first.ob, prop~ SpinifexAtoms.spinifex]];
subnode: REF SpinifexCircuit.CircuitNode ~ NARROW[key];
subPos: CD.DesignPosition;
subOrient: CD.Orientation;
[subPos, subOrient] ← Compose[pos, orient, size, applChain];
PerCell[ subCircuit, subnode, subPos, subOrient, applChain.first.ob.size];
}
ENDLOOP;
RETURN [FALSE]
};
FOR layer: SpinifexCircuit.SpinifexLayerIndex
IN [0..data.tech.numSpinifexLayers)
DO
circuit.EnumerateGeometry[layer, CDInline.universe, PaintNode, node]
ENDLOOP;
IF circuit.mergeDirectory #
NIL
THEN
[] ← circuit.mergeDirectory.Pairs[SearchForPortConnection]
};
pos: CD.DesignPosition ← [0,0];
orient: CD.Orientation ← CD.original;
ac: LIST OF CD.ApplicationPtr ~ data.applChain;
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.