<> <> <> <> 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; <> 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 }; SearchChild: 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 => { <> 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.