CDExtraCommands.mesa (part of ChipNDale)
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 11, 1983 3:42 pm
Last Edited by: Christian Jacobi, March 26, 1987 11:22:30 am PST
DIRECTORY
Atom,
CD,
CDBasics,
CDCommandOps,
CDDirectory,
CDInstances,
CDLayers,
CDIO,
CDOps,
CDPanel,
CDProperties,
CDRects,
CDSequencer,
CDSymbolicObjects,
CDTexts,
CDValue,
CDViewer,
CDVArrow,
IO,
ProcessProps,
Rope,
TiogaMenuOps,
TerminalIO,
ViewerClasses USING [Viewer],
ViewerOps;
CDExtraCommands:
CEDAR
PROGRAM
IMPORTS Atom, CD, CDBasics, CDCommandOps, CDDirectory, CDInstances, CDIO, CDLayers, CDOps, CDPanel, CDProperties, CDRects, CDSequencer, CDSymbolicObjects, CDTexts, CDValue, CDVArrow, CDViewer, IO, ProcessProps, TiogaMenuOps, TerminalIO, ViewerOps =
BEGIN
WithWDir:
PROC [wDir: Rope.
ROPE, proc:
PROC] = {
ProcessProps.AddPropList[
propList: Atom.PutPropOnList[NIL, $WorkingDirectory, wDir],
inner: proc
];
};
HelpComm:
PROC [comm: CDSequencer.Command] = {
Do:
PROC [] = {
v: ViewerClasses.Viewer ← TiogaMenuOps.Open["CDCrib.tioga"];
IF v#NIL THEN ViewerOps.OpenIcon[v];
};
WithWDir[CDIO.GetWorkingDirectory[NIL], Do];
TerminalIO.PutRope["for more documentation, open also\n ChipNDaleIntroduction.tioga\n ChipNDaleDoc.tioga\n ChipNDaleToolsDoc.tioga\n"];
};
CoordinatesCommand:
PROC [comm: CDSequencer.Command] = {
WriteInLambda:
PROC [n:
CD.Number] = {
TerminalIO.PutRope[CDOps.LambdaRope[n, lambda]]
};
lambda: INT ← comm.design.technology.lambda;
TerminalIO.PutRope["coordinates [\024]"]; -- \024 prints as greek lambda
TerminalIO.PutRope[" down: ("];
WriteInLambda[comm.sPos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.sPos.y];
TerminalIO.PutRope[") up: ("];
WriteInLambda[comm.pos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.pos.y];
TerminalIO.PutRope[") dist: ("];
WriteInLambda[comm.pos.x-comm.sPos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.pos.y-comm.sPos.y];
TerminalIO.PutRope[")\n"];
};
SetArrow:
PROC [comm: CDSequencer.Command] = {
WriteInLambda:
PROC [n:
CD.Number] = {
TerminalIO.PutRope[CDOps.LambdaRope[n, lambda]]
};
lambda: INT ← comm.design.technology.lambda;
TerminalIO.PutRope["set arrow at ("];
WriteInLambda[comm.pos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.pos.y];
TerminalIO.PutRope[")\024\n"];
CDVArrow.ShowArrow[comm.design, comm.pos];
};
RemoveArrow:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["remove arrow\n"];
CDVArrow.RemoveArrow[comm.design];
};
ArrowInformation:
PROC [comm: CDSequencer.Command] = {
WriteInLambda:
PROC [n:
CD.Number] = {
TerminalIO.PutRope[CDOps.LambdaRope[n, lambda]]
};
lambda: INT ← comm.design.technology.lambda;
WITH CDValue.Fetch[comm.design, $arrow, design]
SELECT
FROM
rp:
REF
CD.Position => {
TerminalIO.PutRope[" arrow at: ("];
WriteInLambda[rp.x];
TerminalIO.PutRope[","];
WriteInLambda[rp.y];
TerminalIO.PutRope[") up: ("];
WriteInLambda[comm.pos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.pos.y];
TerminalIO.PutRope[") dist: ("];
WriteInLambda[rp.x-comm.pos.x];
TerminalIO.PutRope[","];
WriteInLambda[rp.y-comm.pos.y];
TerminalIO.PutRope[")\n"];
}
ENDCASE => NULL;
};
OrientationRope:
PROC [orient:
CD.Orientation]
RETURNS [Rope.
ROPE] = {
RETURN [
SELECT orient
FROM
original => "original",
mirrorX => "mirrorX",
rotate90 => "rotate90",
rotate90X => "rotate90X",
rotate180 => "rotate180",
rotate180X => "rotate180X",
rotate270 => "rotate270",
rotate270X => "rotate270X",
ENDCASE => ERROR
]
};
StatisticCommand:
PROC [comm: CDSequencer.Command] = {
lambda: INT ← comm.design.technology.lambda;
countTot, countSel, countInvis: INT ← 0;
isDesign: BOOL ← FALSE;
rect: CD.Rect ← CDBasics.universe;
v: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
inst: CD.Instance;
TerminalIO.PutRope["statistic "];
IF v#NIL THEN rect ← CDViewer.VisibleRect[v];
IF ~CDBasics.NonEmpty[rect] THEN rect ← CDBasics.universe;
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
countTot ← countTot+1;
IF l.first.selected
THEN {
IF ~CDBasics.Intersect[rect, CDInstances.InstRectI[l.first]] THEN countInvis ← countInvis+1;
countSel ← countSel+1;
inst ← l.first
}
ENDLOOP;
TerminalIO.PutF["%g objects; %g selected\n", IO.int[countTot], IO.int[countSel]];
IF countSel=1
THEN {
verbosity: INT ← 5;
TerminalIO.PutRope[CDOps.InstRope[inst, comm.design, verbosity]];
IF verbosity>0
THEN {
ir: CD.Position ← CD.InterestSize[inst.ob];
\024 prints as greek lambda
TerminalIO.PutF[" at: (%g,%g)\024",
[rope[CDOps.LambdaRope[inst.trans.off.x, lambda]]],
[rope[CDOps.LambdaRope[inst.trans.off.y, lambda]]]
];
TerminalIO.PutF[" i-size: (%g,%g)\024",
[rope[CDOps.LambdaRope[ir.x, lambda]]], [rope[CDOps.LambdaRope[ir.y, lambda]]]
];
WITH inst.ob.specific
SELECT
FROM
tp: CDTexts.TextSpecific =>
IF tp.cdFont#
NIL
THEN
TerminalIO.PutF[" [Font: %g, scale:%g\024]",
[rope[tp.cdFont.supposedName]],
[rope[CDOps.LambdaRope[tp.cdFont.scaleI, lambda]]] --need technology for lambda
];
cp:
CD.CellSpecific =>
TerminalIO.PutRope[IF cp.specifiedIr THEN " interest rect explicite" ELSE " interest rect defaulted"];
ENDCASE => NULL;
TerminalIO.PutRopes[" orientation: ", OrientationRope[inst.trans.orient]];
IF inst.ob.class.composed
AND ~CDDirectory.IsIncluded[comm.design, inst.ob]
THEN
TerminalIO.PutRope[" not included in directory"]
};
TerminalIO.PutRope["\n"];
};
ArrowInformation[comm];
IF countInvis#0
THEN
TerminalIO.PutF1[" ** %g invisible selected object(s)\n", [integer[countInvis]]];
};
AddSelectLayer:
PROC [comm: CDSequencer.Command] = {
n: INT ← 0;
layer: CD.Layer ← CDLayers.CurrentLayer[comm.design];
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.ob.layer=layer
THEN {
n ← n+1;
IF ~l.first.selected
THEN {
l.first.selected ← TRUE;
CDOps.RedrawInstance[comm.design, l.first, FALSE];
}
}
ENDLOOP;
TerminalIO.PutF["select all %g objects: (%g)\n", [rope[CDOps.LayerRope[layer]]], [integer[n]]];
};
ChangeLayerComm:
PROC [comm: CDSequencer.Command] = {
n: INT ← 0;
layer: CD.Layer ← CDLayers.CurrentLayer[comm.design];
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.selected
AND l.first.ob.class.newLayer#
NIL
THEN {
CDOps.RedrawInstance[comm.design, l.first];
IF l.first.ob.class.newLayer[l.first, layer] THEN n ← n+1;
CDOps.RedrawInstance[comm.design, l.first, FALSE];
}
ENDLOOP;
TerminalIO.PutF["changed layer to %g (%g)\n", IO.rope[CDOps.LayerRope[layer]], IO.int[n]];
};
GetWidthLayerCommand:
PROC [comm: CDSequencer.Command] = {
inst: CD.Instance = CDOps.TheInstance[comm.design, "set default layer and width"];
IF inst#
NIL
THEN {
done: BOOL ← FALSE;
layer: CD.Layer = inst.ob.layer;
IF CDProperties.GetLayerProp[layer, $DontUse]=
NIL
THEN
IF CDTexts.IsText[inst.ob]
OR
CD.LayerTechnology[layer]#
NIL
OR (
CD.LayerTechnology[layer]=
NIL
AND CDLayers.Kind[layer]=paint)
THEN {
IF layer#
CD.undefLayer
AND layer#
CD.shadeLayer
AND layer#
CD.backgroundLayer
AND layer#
CD.backgroundLayer
AND layer#
CD.outlineLayer
AND layer#
CD.selectionLayer
THEN {
sz: CD.Position ← CD.InterestSize[inst.ob];
w: CD.Number ← IF inst.ob.class.wireTyped THEN sz.x ELSE MIN[sz.x, sz.y];
done ← TRUE;
CDLayers.SetLayerWidth[comm.design, layer, w];
CDLayers.SetCurrentLayer[comm.design, layer];
TerminalIO.PutF[" %g (%g)\n",
[rope[CDOps.LayerRope[layer]]],
[rope[CDOps.LambdaRope[w, comm.design.technology.lambda]]]
];
}
};
IF ~done THEN TerminalIO.PutRope[" not done\n"];
}
};
GetLayerCommand:
PROC [comm: CDSequencer.Command] = {
inst: CD.Instance = CDOps.TheInstance[comm.design, "set default layer"];
IF inst#
NIL
THEN {
done: BOOL ← FALSE;
layer: CD.Layer = inst.ob.layer;
IF CDProperties.GetLayerProp[layer, $DontUse]=
NIL
THEN
IF CDTexts.IsText[inst.ob]
OR
CD.LayerTechnology[layer]#
NIL
OR (
CD.LayerTechnology[layer]=
NIL
AND CDLayers.Kind[layer]=paint)
THEN {
IF layer#
CD.undefLayer
AND layer#
CD.shadeLayer
AND layer#
CD.backgroundLayer
AND layer#
CD.backgroundLayer
AND layer#
CD.outlineLayer
AND layer#
CD.selectionLayer
THEN {
done ← TRUE;
TerminalIO.PutRopes[" ", CDOps.LayerRope[layer], "\n"];
CDLayers.SetCurrentLayer[comm.design, layer];
}
};
IF ~done THEN TerminalIO.PutRope[" not done\n"];
}
};
GetWidthCommand:
PROC [comm: CDSequencer.Command] = {
w: CD.Number ← 0;
layer: CD.Layer ← CDLayers.CurrentLayer[comm.design];
inst: CD.Instance = CDOps.TheInstance[comm.design, "set default width"];
IF inst#
NIL
THEN {
sz: CD.Position ← CD.InterestSize[inst.ob];
IF inst.ob.class.wireTyped THEN w ← sz.x ELSE w ← MIN[sz.x, sz.y];
};
CDLayers.SetLayerWidth[comm.design, layer, w];
TerminalIO.PutF[" width for %g set to %g\n",
[rope[CDOps.LayerRope[layer]]],
[rope[CDOps.LambdaRope[w, comm.design.technology.lambda]]]
];
};
IncreaseByWidthComm:
PROC [comm: CDSequencer.Command] = {
cnt: INT ← 0;
TerminalIO.PutRope["increase wire length by width: "];
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.selected
AND l.first.ob.class.wireTyped
AND ~l.first.ob.class.symbolic
THEN {
oldSize: CD.Position ← CD.InterestSize[l.first.ob];
newSize: CD.Position ← [x: oldSize.x, y: oldSize.y+oldSize.x];
newOb: CD.Object ← CDRects.CreateRect[newSize, l.first.ob.layer];
IF newOb#
NIL
THEN {
CDOps.RedrawInstance[comm.design, l.first, TRUE];
l.first.ob ← newOb;
cnt ← cnt+1;
--this orientation busines makes sure the instance is grown at the top or the right edge
SELECT l.first.trans.orient
FROM
original, mirrorX, rotate270, rotate90X => {};
rotate90, rotate270X => l.first.trans.off.x ← l.first.trans.off.x+oldSize.x;
rotate180, rotate180X => l.first.trans.off.y ← l.first.trans.off.y+oldSize.x;
ENDCASE => {};
CDOps.RedrawInstance[comm.design, l.first];
};
};
ENDLOOP;
TerminalIO.PutF1[" %g objects\n", IO.int[cnt]];
};
ShowErrorComm:
PROCEDURE [comm: CDSequencer.Command] = {
applList: CD.InstanceList = CDOps.InstList[comm.design];
foundSome: BOOL ← FALSE;
TerminalIO.PutRope[ "show error "];
FOR a:
CD.InstanceList ← applList, a.rest
WHILE a#
NIL
DO
IF a.first.ob.layer=
CD.errorLayer
THEN {
inst: CD.Instance = a.first;
foundSome ← TRUE;
IF ~inst.selected
THEN {
eRect: CD.Rect = CDInstances.InstRectI[inst];
inst.selected ← TRUE;
CDOps.Redraw[comm.design, eRect, FALSE];
TerminalIO.PutRopes[CDOps.InstRope[inst], "\n"];
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf[comm], vl.rest
WHILE vl#
NIL
DO
CDViewer.ShowAndScale[viewer: vl.first, rect: CDBasics.Extend[eRect, 30*comm.design.technology.lambda] ];
ENDLOOP;
CDOps.ReOrderInstance[comm.design, inst];
EXIT
}
};
REPEAT
FINISHED =>
IF foundSome THEN TerminalIO.PutRope["all errors in this cell are already selected\n"]
ELSE TerminalIO.PutRope[ "no errors in this cell\n"]
ENDLOOP;
};
SelectAllErrorsComm:
PROC [comm: CDSequencer.Command] = {
cnt: INT ← 0;
CDOps.DeselectAll[comm.design];
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.ob.layer=
CD.errorLayer
THEN {
cnt ← cnt+1;
l.first.selected ← TRUE;
CDOps.RedrawInstance[comm.design, l.first, FALSE]
}
ENDLOOP;
TerminalIO.PutF["%g error(s) selected\n", IO.int[cnt]];
};
MakePinComm:
PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE;
r: CD.Rect = CDBasics.ToRect[comm.pos, comm.sPos];
inst: CD.Instance;
layer: CD.Layer ← CDLayers.CurrentLayer[comm.design];
layer ← CDLayers.AbstractToPaint[layer];
TerminalIO.PutRopes["draw Pin (", CDOps.LayerRope[layer], ")\n"];
name ← TerminalIO.RequestRope[" type name of pin: "];
inst ← CDSymbolicObjects.CreateSymInst[denotes: r, layer: layer, name: name];
CDOps.IncludeInstance[comm.design, inst];
};
MakeSegmentComm:
PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE;
r: CD.Rect = CDBasics.ToRect[comm.pos, comm.sPos];
inst: CD.Instance;
layer: CD.Layer ← CDLayers.CurrentLayer[comm.design];
TerminalIO.PutRopes["draw Segment (", CDOps.LayerRope[layer], ")\n"];
layer ← CDLayers.AbstractToPaint[layer];
name ← TerminalIO.RequestRope[" type name of segment: "];
inst ← CDSymbolicObjects.CreateSymInst[denotes: [x1: r.x1, x2: r.x2, y1: r.y1, y2: r.y1], layer: layer, name: name];
CDOps.IncludeInstance[comm.design, inst];
};
MakeMarkComm:
PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE; inst: CD.Instance;
r: CD.Rect = CDBasics.RectAt[comm.pos, [0, 0]];
TerminalIO.PutRope["draw mark object\n"];
name ← TerminalIO.RequestRope[" type name of mark: "];
inst ← CDSymbolicObjects.CreateSymInst[denotes: r, name: name];
CDOps.IncludeInstance[comm.design, inst];
};
CDSequencer.ImplementCommand[$GetLayer, GetLayerCommand,, doQueue];
CDSequencer.ImplementCommand[$GetWidth, GetWidthCommand,, doQueue];
CDSequencer.ImplementCommand[$GetWidthLayer, GetWidthLayerCommand,, doQueue];
CDSequencer.ImplementCommand[$AddSelectLayer, AddSelectLayer,, doQueue];
CDSequencer.ImplementCommand[$Coordinates, CoordinatesCommand,, doQueue];
CDSequencer.ImplementCommand[$Statistic, StatisticCommand,, doQueue];
CDSequencer.ImplementCommand[$SetArrow, SetArrow,, doQueue];
CDSequencer.ImplementCommand[$RemoveArrow, RemoveArrow,, doQueue];
CDSequencer.ImplementCommand[$IncreaseByWidth, IncreaseByWidthComm];
CDSequencer.ImplementCommand[$ChangeLayerS, ChangeLayerComm];
CDSequencer.ImplementCommand[$Help, HelpComm,, dontQueue];
CDSequencer.ImplementCommand[$DrawMark, MakeMarkComm];
CDSequencer.ImplementCommand[$DrawPin, MakePinComm];
CDSequencer.ImplementCommand[$DrawSegment, MakeSegmentComm];
CDCommandOps.RegisterCurrentLayerCommand[key: $LayerComment, layer: CD.commentLayer];
CDCommandOps.RegisterCurrentLayerCommand[key: $LayerGreen, layer: CD.FetchLayer[NIL, $green], w: -2];
CDCommandOps.RegisterCurrentLayerCommand[key: $LayerYellow, layer: CD.FetchLayer[NIL, $yellow], w: -2];
CDCommandOps.RegisterCurrentLayerCommand[key: $LayerRed, layer: CD.FetchLayer[NIL, $red], w: -2];
CDCommandOps.RegisterCurrentLayerCommand[key: $LayerBlue, layer: CD.FetchLayer[NIL, $blue], w: -2];
CDSequencer.ImplementCommand[$ShowErrors, ShowErrorComm,, doQueue];
CDSequencer.ImplementCommand[$SelectAllErrors, SelectAllErrorsComm,, doQueue];
CDPanel.Button[button: [text: "menu"], command: $GlobalMenu, topLine: TRUE];
CDPanel.Button[button: [text: "help"], command: $Help, topLine: TRUE];
END.