PipalUIImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Louis Monier January 18, 1988 10:05:47 am PST
Bertrand Serlet May 13, 1988 2:36:54 pm PDT
DIRECTORY
CD, CDBasics, CDCells, CDCellsInteractions, CDDefaultProcs, CDDirectory, CDEnvironment, CDImports, CDInstances, CDOps, CDSatellites, CDSequencer, CDSequencerExtras, CDViewer, CDViewHighlight,
List,
Pipal, PipalCD, PipalInt, PipalIO, PipalMos, PipalOps, PipalUI,
PW, RefTab, SymTab, TerminalIO, ViewerClasses, ViewerOps;
PipalUIImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDCellsInteractions, CDDefaultProcs, CDDirectory, CDEnvironment, CDImports, CDInstances, CDOps, CDSatellites, CDSequencerExtras, CDViewer, CDViewHighlight, List, Pipal, PipalCD, PipalInt, PipalIO, PipalMos, PipalOps, PW, RefTab, SymTab, TerminalIO, ViewerOps
EXPORTS PipalUI
SHARES CDImports =
BEGIN OPEN PipalUI;
Design
stupidCDProps: LIST OF REFLIST [$GeneratorProc, $CDxDrawSymbolics, $layerOfPin, $CDSatellitesGroupId, $CDBringoverLibraryName, $CDSatellitesOGroup, $OwnerDesign, $SatellitesCounter, $FileVersion, $CDSatellitesMax, $WireIconsConvertedFrom23, $FiddleKey];
otherProps: LIST OF REFLIST [$X, $PinOrder, $InstanceName, $DontFlatten, $Export, $MintDiscardMe];
UnknownProp: SIGNAL [key: ATOM, val: REF] = CODE;
DesignRoot: PUBLIC PROC [design: Design] RETURNS [root: Pipal.Object] = {
Each: CDDirectory.EachEntryAction = {
[] ← SymTab.Store[directory, name, PipalCD.CDToPObject[ob]];
};
top: Pipal.Object ← PipalCD.CDToPObject[CDOps.RealTopCell[design]];
satellites: Pipal.Objects ← NIL;
directory: SymTab.Ref ← SymTab.Create[];
FOR props: CD.PropList ← design.properties^, props.rest WHILE props#NIL DO
key: REF ← props.first.key;
val: REF ← props.first.val;
IF ISTYPE [key, ATOM] THEN SELECT TRUE FROM
List.Memb[key, stupidCDProps] => {};
List.Memb[key, otherProps]  =>
top ← Pipal.CreateAnnotation[top, NARROW [key], val];
ENDCASE        => {
SIGNAL UnknownProp[NARROW [key], val];
otherProps← CONS [key, otherProps];
};
ENDLOOP;
FOR list: CD.InstanceList ← CDSatellites.GetSatellites[design], list.rest WHILE list#NIL DO
satellites ← CONS [PipalCD.CDToPInstance[list.first], satellites];
ENDLOOP;
[] ← CDDirectory.Enumerate[design, Each];
root ← PipalIO.CreateDirectory[design.name, PipalMos.CreateStar[top, satellites], directory];
};
Highlight and Viewer
highlightClass: CD.ObjectClass ← PW.RegisterClass[
objectType: $PipalHighlight,
expand: ExpandHighlight,
interestRect: CDDefaultProcs.InterestRect,
drawMe: HighlightDrawMe,
quickDrawMe: HighlightDrawMe,
showMeSelected: CDDefaultProcs.ShowMeSelected
];
Specific REF contains a CD.Object needing to be drawn highlighted.
ExpandHighlight: CDDirectory.ExpandProc = {ERROR};
HighlightDrawMe: CD.DrawProc = {
pr ← NEW [CD.DrawInformation ← pr^];
pr.drawRect ← HighlightDrawRect;
pr.drawChild[pr, NARROW [ob.specific], trans];
};
HighlightDrawRect: CD.DrawRectProc = {
CDDefaultProcs.DrawRect[pr, r, CD.shadeLayer];
};
CreateHighlight: PROC [cdobj: CD.Object] RETURNS [ob: CD.Object] = {
ob ← NEW [CD.ObjectRep ← [
bbox: cdobj.bbox, class: highlightClass, immutable: TRUE, specific: cdobj
]];
};
HighlightDesign: PUBLIC PROC [design: Design, transformation: PipalInt.Transformation ← [], object: Pipal.Object ← NIL, viewer: ViewerClasses.Viewer ← NIL, label: Pipal.ROPENIL, rescale: BOOLTRUE] = {
bbox: CD.Rect;
cdhighlight: CD.Instance;
IF viewer=NIL THEN viewer ← FindViewer[design, label];
IF object=NIL THEN {
CDViewHighlight.ShowInstance[v: viewer, instOrList: NIL];
RETURN;
};
cdhighlight ← CDInstances.NewInst[
CreateHighlight[PipalCD.PToCDObject[object].cdobj],
PipalCD.PToCDTrans[transformation]
];
bbox ← CDInstances.InstRectO[cdhighlight];
CDViewHighlight.ShowInstance[v: viewer, instOrList: cdhighlight];
ViewerOps.OpenIcon[viewer];
IF NOT CDBasics.NonEmpty[bbox] THEN RETURN;
IF CDBasics.NonEmpty[bbox] AND rescale THEN CDViewer.ShowAndScale[viewer, bbox];
CDOps.ImmediateRedraw[design, bbox, FALSE];
};
FindViewer: PUBLIC PROC [design: Design, label: Pipal.ROPENIL] RETURNS [viewer: ViewerClasses.Viewer] = {
viewer ← CDViewer.LastViewer[];
IF CDViewer.DesignOf[viewer]#design THEN {
viewers: CDViewer.ViewerList ← CDViewer.ViewersOf[design];
IF viewers=NIL THEN {
viewer ← CDViewer.CreateViewer[design];
IF label#NIL THEN ViewerOps.SetViewer[viewer: viewer, data: label, op: $Label];
}
ELSE viewer ← viewers.first;
};
};
Selection
SearchDesignRootPath: PRIVATE PROC [design: Design] RETURNS [pushPath: PipalOps.Path] = {
found: BOOL;
root: Pipal.Object ← DesignRoot[design];
top: Pipal.Object ← PipalCD.CDToPObject[CDOps.RealTopCell[design]];
IF top=Pipal.void THEN RETURN [NIL]; -- serious yogourt here if that value gets used! ... Think of all consequences for example in ReplaceInDesign
[pushPath, found] ← PipalOps.FindOpsPath[root, top];
-- We do not deal here with pushed cell path WRONG
IF NOT found THEN ERROR;
};
EnumerateSelectedObjects: PUBLIC PROC [design: Design, each: EachSelectedProc] RETURNS [quit: BOOLFALSE] = {
pushPath: PipalOps.Path;
ThisInstance: CDCells.InstEnumerator = {
path: PipalOps.Path; trans: PipalInt.Transformation; child: Pipal.Object;
subPath: PipalOps.Path; found: BOOL;
cdtrans: CD.Transformation;
IF NOT inst.selected THEN RETURN;
IF design.actual.first.mightReplace=NIL
THEN cdtrans ← inst.trans ELSE {
cdaux: CD.Transformation ← design.actual.first.mightReplace.trans;
cdtrans ← [
CDBasics.DeMapPoint[inst.trans.off, cdaux],
CDBasics.DecomposeOrient[itemInWorld: inst.trans.orient, cellInWorld: cdaux.orient]
];
};
trans ← PipalCD.CDToPTrans[cdtrans]; child ← PipalCD.CDToPObject[inst.ob];
[subPath, found] ← PipalOps.FindIntPath[
[], pushed, -- We do not deal here with pushed cell path WRONG
trans, child
];
IF NOT found THEN ERROR;
path ← PipalOps.ConcatPath[pushPath, subPath];
quit ← each[path, trans, child]
};
pushed: Pipal.Object ← PipalCD.CDToPObject[CDOps.PushedTopCell[design]];
IF pushed=Pipal.void THEN RETURN;
pushPath ← SearchDesignRootPath[design];
quit ← CDCells.EnumerateInstances[CDOps.PushedTopCell[design], ThisInstance];
};
TheSelectedObject: PUBLIC PROC [design: Design] RETURNS [thePath: PipalOps.Path, theTrans: PipalInt.Transformation, theChild: Pipal.Object ← NIL] = {
Each: EachSelectedProc = {
IF theChild=NIL THEN {thePath ← path; theTrans ← trans; theChild ← child} ELSE quit ← TRUE;
};
IF EnumerateSelectedObjects[design, Each] THEN theChild ← NIL;
IF theChild=NIL THEN TerminalIO.PutF["*** Several selected objects: cannot do it.\n"];
};
SelectInstance: PUBLIC PROC [design: Design, transformation: PipalInt.Transformation, object: Pipal.Object] RETURNS [done: BOOL] = {
FOR worldInstances: CD.InstanceList ← design.actual.first.specific.contents, worldInstances.rest UNTIL worldInstances=NIL DO
worldInstance: CD.Instance ← worldInstances.first;
IF SameInstances[
PipalCD.CDToPTrans[worldInstance.trans], PipalCD.CDToPObject[worldInstance.ob],
transformation, object
] THEN {worldInstance.selected ← TRUE; done ← TRUE; EXIT};
REPEAT FINISHED => done ← FALSE;
ENDLOOP;
};
Push
PushInstance: PUBLIC PROC [design: Design, transformation: PipalInt.Transformation, object: Pipal.Object] RETURNS [done: BOOL] = {
FOR worldInstances: CD.InstanceList ← design.actual.first.specific.contents, worldInstances.rest UNTIL worldInstances=NIL DO
worldInstance: CD.Instance ← worldInstances.first;
IF SameInstances[
PipalCD.CDToPTrans[worldInstance.trans], PipalCD.CDToPObject[worldInstance.ob],
transformation, object
] THEN {done ← CDCellsInteractions.PushInCellInstance[design, worldInstance]; EXIT};
REPEAT FINISHED => done ← FALSE;
ENDLOOP;
};
Command Registration
cdCommandDispatch: RefTab.Ref ← RefTab.Create[]; -- maps keys to CommandProcs
cdCommandData: RefTab.Ref ← RefTab.Create[]; -- maps keys to registration data (if any!)
CDCommandDispatcher: PROC [comm: CDSequencer.Command] = {
proc: REF CommandProc ← NARROW [RefTab.Fetch[cdCommandDispatch, comm.key].val];
IF proc=NIL THEN ERROR; -- command not registered!
proc^[
comm.design,
[comm.pos.x, comm.pos.y], [comm.sPos.x, comm.sPos.y],
RefTab.Fetch[cdCommandData, comm.key].val, comm.ref
];
};
RegisterCommand: PUBLIC PROC [key: ATOM, proc: CommandProc, queue, markChanged: BOOLTRUE, data: REFNIL] = {
CDSequencerExtras.RegisterCommand[key, CDCommandDispatcher, NIL, IF queue THEN IF markChanged THEN doQueueAndMark ELSE doQueue ELSE IF markChanged THEN ERROR ELSE dontQueue];
[] ← RefTab.Store[cdCommandDispatch, key, NEW [CommandProc ← proc]];
IF data#NIL THEN [] ← RefTab.Store[cdCommandData, key, data];
};
Object Comparisons
Contains: PUBLIC PROC [object: Pipal.Object, candidateTrans: PipalInt.Transformation, candidateObject: Pipal.Object] RETURNS [BOOL] = {
ContainsChild: PipalInt.EachChildProc = {
IF transformation=candidateTrans AND child=candidateObject THEN RETURN [TRUE];
IF NOT PipalInt.IsInsideRectangle[PipalInt.BBox[child, transformation], PipalInt.BBox[candidateObject, candidateTrans]] THEN RETURN [FALSE];
quit ← PipalInt.HasEnumerate[child] AND PipalInt.Enumerate[child, ContainsChild, transformation];
};
SubCandidateNotContained: PipalInt.EachChildProc = {
quit ← NOT Contains[object, transformation, child];
};
IF ContainsChild[[], object] THEN RETURN [TRUE];
IF NOT PipalInt.HasEnumerate[candidateObject] THEN RETURN [FALSE];
RETURN [NOT PipalInt.Enumerate[candidateObject, SubCandidateNotContained, candidateTrans]];
};
SameInstances: PUBLIC PROC [trans1: PipalInt.Transformation, object1: Pipal.Object, trans2: PipalInt.Transformation, object2: Pipal.Object] RETURNS [BOOL] = {
RETURN [Contains[PipalInt.TransformObject[trans1, object1], trans2, object2] AND Contains[PipalInt.TransformObject[trans2, object2], trans1, object1]];
};
Junk Yard
GetTopInstances: PUBLIC PROC [design: Design] RETURNS [topInstances: TopInstanceLists ← NIL] = {
GetInstances: PROC [design: Design] = {
thisTops: Pipal.Objects ← NIL;
stack: LIST OF CD.PushRec ← NIL;
trail: LIST OF CD.PushRec ← NIL;
FOR stack ← design.actual, stack.rest UNTIL stack.rest=NIL DO
trail ← stack;
ENDLOOP;
thisTops ← LIST [PipalCD.CDToPObject[stack.first.dummyCell.ob]]; -- old code used to be slightly different here! (BS)
IF trail#NIL THEN thisTops ← CONS [PipalCD.CDToPInstance[trail.first.mightReplace], thisTops];
FOR cl: LIST OF CDImports.Cache ← CDImports.GetCacheList[design].list, cl.rest UNTIL cl=NIL DO
IF RefTab.Insert[processedDesigns, cl.first.importee, $Done] THEN GetInstances[cl.first.importee];
ENDLOOP;
topInstances ← CONS[[design, thisTops], topInstances];
};
processedDesigns: RefTab.Ref ← RefTab.Create[];
GetInstances[design];
};
Random
schematicLambda: PUBLIC INTCD.FetchTechnology[$cmosB].lambda;
schematicFudge: PUBLIC INT ← schematicLambda / 2;
FetchKeyLine: PUBLIC PROC [fileName, key: Pipal.ROPE] RETURNS [entry: Pipal.ROPENIL] = {
entry ← CDEnvironment.FetchKeyLine[fileName, key];
};
ExecuteInTerminal: PUBLIC PROC [entry: Pipal.ROPE] = {
[] ← CDEnvironment.StuffToCommandTool[entry];
};
Debug
Draw: PUBLIC PROC [object: Pipal.Object] RETURNS [design: Design] = {
design ← PW.Draw[PipalCD.PToCDObject[object].cdobj];
};
Initialization
END.