RoseHighlightInCD.mesa
Last Edited by: Spreitzer, September 4, 1985 0:14:42 am PDT
DIRECTORY Asserting, CD, CDCells, CDDirectory, CDInstances, CDOps, CDSequencer, CDViewer, D2Basic, Graphs, IO, MessageWindow, Real, Rope, RoseCreate, RoseDisplayInsides, RoseTypes, SXHighlightNode;
RoseHighlightInCD: CEDAR PROGRAM
IMPORTS Asserting, CDCells, CDDirectory, CDInstances, CDOps, CDSequencer, CDViewer, IO, MessageWindow, Real, Rope, RoseCreate, SXHighlightNode
EXPORTS RoseDisplayInsides
=BEGIN OPEN RoseTypes;
Complain: ERROR [msg: ROPE] = CODE;
Transform: TYPE = RECORD [dxdx, dxdy, dx, dydx, dydy, dy: REAL];
layerTableSize: NAT = 5;
layerTable: ARRAY [0 .. layerTableSize) OF RECORD [strKey: ATOM, cdLayer: CD.Layer] = [
[$nDiffusion, 7--ndif--],
[$pDiffusion, 12--pdif--],
[$Poly, 6--pol--],
[$Metal, 8--met--],
[$Metal2, 15--met2--]
];
HighlightNode: PUBLIC PROC [edge: Graphs.Edge, data: REF ANY] --Graphs.EdgeConsumerProc-- = {
ENABLE Complain => {MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; CONTINUE};
WITH edge.otherSide.rep SELECT FROM
ne: RoseDisplayInsides.NodeElt => Highlight[ne.node];
ENDCASE => Complain["Can only highlight a Node"];
};
Highlighting: TYPE = REF HighlightingRep;
HighlightingRep: TYPE = RECORD [
node: Node,
cdDesign: CD.Design,
loc: CD.Position ← [0, 0],
cdLayer: CD.Layer ← CD.backGround
];
hl: Highlighting;
Doit: PROC [CDSequencer.Command] = {
ENABLE Complain => {MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; CONTINUE};
PushTo[hl.cdDesign, hl.node.cellIn.parent];
SXHighlightNode.HighlightNode[design: hl.cdDesign, pos: hl.loc, lev: hl.cdLayer];
};
Highlight: PROC [node: Node] = {
sim: Simulation ← node.strIn.sim;
designName: ROPENARROW[Asserting.FnVal[$DesignName, node.other]];
hl ← NEW [HighlightingRep ← [node: node, cdDesign: CDViewer.FindDesign[designName]]];
IF hl.cdDesign = NIL THEN Complain[IO.PutFR["No such design as %g", IO.refAny[designName]]];
[hl.loc, hl.cdLayer] ← UpLoc[node, 1];
IF node.cellIn = NIL THEN ERROR;
IF node.cellIn.parent = NIL THEN Complain["Too shallow"];
CDSequencer.ExecuteProc[design: hl.cdDesign, proc: Doit];
};
UpLoc: PROC [node: Node, levels: INT] RETURNS [loc: CD.Position, lev: CD.Layer] = {
locHint: LORA ← Asserting.FnVals[$locHint, node.other];
layerAtom: ATOM;
cell: Cell;
IF locHint = NIL THEN Complain["No location hint"];
loc.x ← Real.RoundLI[ToReal[locHint.first]*CD.lambda];
loc.y ← Real.RoundLI[ToReal[locHint.rest.first]*CD.lambda];
layerAtom ← NARROW[locHint.rest.rest.first];
FOR i: INT IN [0 .. layerTableSize) DO
IF layerTable[i].strKey = layerAtom THEN {lev ← layerTable[i].cdLayer; EXIT};
REPEAT
FINISHED => Complain[IO.PutFR["Layer %g unrecognized", IO.atom[layerAtom]]];
ENDLOOP;
cell ← node.cellIn;
FOR i: INT IN [1 .. levels] DO
ct: CellType ← cell.type;
toParent: Transform ← GetInstanceTransform[cell];
loc ← TransformPos[toParent, loc];
cell ← cell.parent;
ENDLOOP;
cell ← cell;
};
GetInstanceTransform: PROC [cell: Cell] RETURNS [it: Transform] = {
t6: LORA ← Asserting.FnVals[$t6, cell.other];
IF t6 = NIL THEN Complain[IO.PutFR["No instance transform for %g", IO.rope[RoseCreate.LongCellName[cell]]]];
it.dxdx ← ToReal[t6.first];
it.dxdy ← ToReal[t6.rest.first];
it.dx ← ToReal[t6.rest.rest.first]*CD.lambda;
it.dydx ← ToReal[t6.rest.rest.rest.first];
it.dydy ← ToReal[t6.rest.rest.rest.rest.first];
it.dy ← ToReal[t6.rest.rest.rest.rest.rest.first]*CD.lambda;
};
GetInstanceBounds: PROC [cell: Cell] RETURNS [bounds: CD.Rect] = {
typeBounds: CD.Rect;
it: Transform ← GetInstanceTransform[cell];
bb: LORA ← Asserting.FnVals[$bb, cell.type.other];
IF bb = NIL THEN Complain[IO.PutFR["No bounding box for %g", IO.rope[cell.type.name]]];
typeBounds.x1 ← Real.RoundLI[ToReal[bb.first]*CD.lambda];
typeBounds.y1 ← Real.RoundLI[ToReal[bb.rest.first]*CD.lambda];
typeBounds.x2 ← Real.RoundLI[ToReal[bb.rest.rest.first]*CD.lambda];
typeBounds.y2 ← Real.RoundLI[ToReal[bb.rest.rest.rest.first]*CD.lambda];
bounds ← TransformRect[it, typeBounds];
};
ToInt: PROC [ra: REF ANY] RETURNS [i: INT] = {
WITH ra SELECT FROM
ri: REF INT => i ← ri^;
ENDCASE => Complain[IO.PutFR["Not INT: %g", IO.refAny[ra]]];
};
ToReal: PROC [ra: REF ANY] RETURNS [r: REAL] = {
WITH ra SELECT FROM
ri: REF INT => r ← ri^;
rr: REF REAL => r ← rr^;
ENDCASE => Complain[IO.PutFR["Not REAL: %g", IO.refAny[ra]]];
};
TransformPos: PROC [t: Transform, p: CD.Position] RETURNS [tp: CD.Position] = {
tp.x ← Real.RoundLI[t.dxdx*p.x + t.dxdy*p.y + t.dx];
tp.y ← Real.RoundLI[t.dydx*p.x + t.dydy*p.y + t.dy];
};
TransformRect: PROC [t: Transform, r: CD.Rect] RETURNS [tr: CD.Rect] = {
Maxin: PROC [x, y: CD.Number] = {
p: CD.Position ← TransformPos[t, [x, y]];
tr.x1 ← MIN[tr.x1, p.x];
tr.y1 ← MIN[tr.y1, p.y];
tr.x2 ← MAX[tr.x2, p.x];
tr.y2 ← MAX[tr.y2, p.y];
};
[[tr.x1, tr.y1]] ← [[tr.x2, tr.y2]] ← TransformPos[t, [r.x1, r.y1]];
Maxin[r.x1, r.y2];
Maxin[r.x2, r.y1];
Maxin[r.x2, r.y2];
};
CellList: TYPE = LIST OF Cell;
PushTo: PROC [design: CD.Design, cell: Cell] = {
path: CellList ← NIL;
AtTop: PROC RETURNS [atTop: BOOL] =
{atTop ← Rope.Equal[CDDirectory.Name[design.actual.first.dummyCell.ob], path.first.type.name]};
IF NOT InCD[cell] THEN ERROR;
FOR cur: Cell ← cell, cur.parent WHILE InCD[cur] DO
path ← CONS[cur, path];
ENDLOOP;
Pop tward path.first
WHILE design.actual.rest # NIL AND NOT AtTop[] DO
IF NOT CDCells.PopFromCell[design] THEN Complain["Couldn't pop"];
ENDLOOP;
IF NOT AtTop[] THEN Complain[IO.PutFR["Couldn't pop to %g", IO.rope[RoseCreate.LongCellName[path.first]]]];
FOR path ← path, path.rest WHILE path.rest # NIL DO
PushStep[design, path.first, path.rest.first];
ENDLOOP;
cell ← cell;
};
InCD: PROC [cell: Cell] RETURNS [in: BOOL] =
{in ← Asserting.FnVals[$scale, cell.type.other] # NIL};
PushStep: PROC [design: CD.Design, parent, child: Cell] = {
childBounds: CD.Rect ← GetInstanceBounds[child];
toPush: CD.Instance ← NIL;
count: INT ← 0;
FOR al: CD.InstanceList ← CDOps.InstList[design], al.rest WHILE al # NIL DO
i: CD.Instance = al.first;
this: BOOL = CDInstances.InstRectI[i] = childBounds;
IF this THEN {toPush ← i; count ← count + 1};
ENDLOOP;
IF count # 1 THEN Complain[IO.PutFR["%g child (named %g, at %g) of %g", IO.rope[IF count = 0 THEN "Couldn't find any" ELSE "Found more than one"], IO.refAny[child.name], IO.rope[FmtRect[childBounds]], IO.rope[RoseCreate.LongCellName[parent]]]];
IF NOT CDCells.PushInCellInstance[design, toPush] THEN Complain[IO.PutFR["Couldn't push into %g", IO.rope[RoseCreate.LongCellName[child]]]];
};
FmtRect: PROC [r: CD.Rect] RETURNS [rope: ROPE] = {
rope ← IO.PutFR["[%g, %g, %g, %g]", IO.int[r.x1], IO.int[r.y1], IO.int[r.x2], IO.int[r.y2]];
};
END.