ExtractOpsImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Barth, October 14, 1987 4:14:55 pm PDT
Jean-Marc Frailong December 7, 1987 4:56:27 pm PST
DIRECTORY CD, CDBasics, CDCells, CDCellsInteractions, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDProperties, CDRects, CDSatellites, CDViewer, CDViewHighlight, Core, CoreGeometry, CoreOps, ExtractOps, IO, PW, RefTab, Rope, Sinix, SinixCMosB, Sisyph, TerminalIO, ViewerClasses, ViewerOps;
ExtractOpsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDCellsInteractions, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDProperties, CDRects, CDSatellites, CDViewer, CDViewHighlight, CoreGeometry, CoreOps, IO, PW, RefTab, Rope, Sinix, SinixCMosB, Sisyph, TerminalIO, ViewerOps
EXPORTS ExtractOps
SHARES CDImports, SinixCMosB
= BEGIN OPEN ExtractOps;
HighlightInstance: PUBLIC PROC [instance: CoreGeometry.Instance] RETURNS [hinstance: CD.Instance] = {
hinstance ← CDInstances.NewInst[
CDRects.CreateRect[CD.InterestSize[instance.obj], CD.shadeLayer],
[CDBasics.MapPoint[CD.InterestBase[instance.obj], instance.trans], instance.trans.orient]
];
};
HighlightInstanceList: PUBLIC PROC [instances: CoreGeometry.Instances] RETURNS [hinstances: CD.InstanceList ← NIL] = {
WHILE instances#NIL DO
hinstances ← CONS [HighlightInstance[instances.first], hinstances];
instances ← instances.rest;
ENDLOOP;
};
HighlightDesign: PUBLIC PROC [design: CD.Design, highlight: CD.Instance ← NIL, viewer: ViewerClasses.Viewer ← NIL, label: Rope.ROPENIL] = {
bbox: CD.Rect ← IF highlight=NIL THEN [0, 0, 0, 0] ELSE CDInstances.InstRectO[highlight];
DoHighlightDesign[design, highlight, bbox, viewer, label];
};
HighlightDesignList: PUBLIC PROC [design: CD.Design, highlight: CD.InstanceList ← NIL, viewer: ViewerClasses.Viewer ← NIL, label: Rope.ROPENIL] = {
bbox: CD.Rect ← CDInstances.BoundingRectO[highlight];
DoHighlightDesign[design, highlight, bbox, viewer, label];
};
DoHighlightDesign: PROC [design: CD.Design, highlight: REF, bbox: CD.Rect, viewer: ViewerClasses.Viewer ← NIL, label: Rope.ROPENIL] = {
IF viewer=NIL THEN viewer ← FindViewer[design, label];
CDViewHighlight.ShowInstance[v: viewer, instOrList: highlight];
IF highlight#NIL THEN {
ViewerOps.OpenIcon[viewer];
IF CDBasics.NonEmpty[bbox] THEN CDViewer.ShowPosition[viewer, [bbox.x1, bbox.y1]];
CDOps.ImmediateRedraw[design, bbox, FALSE];
};
};
FindViewer: PUBLIC PROC [design: CD.Design, label: Rope.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;
};
};
ExtractCDInstance: PUBLIC PROC [instance: CD.Instance, design: CD.Design, mode: Sinix.Mode] RETURNS [result: REF, props: Core.Properties] = {
userData: REF = IF mode.userData#NIL THEN mode.userData[design] ELSE NIL;
[] ← CDSatellites.GetSatellites[design]; -- enforces the strong invariant in object, one level deep
CDProperties.PutInstanceProp[instance, Sinix.satellitesProp, CDSatellites.GetSatelliteRopes[instance]];
[result, props] ← Sinix.Extract[obj: instance.ob, mode: mode, properties: instance.properties, userData: userData];
};
ExtractCDInstanceAndReport: PUBLIC PROC [instance: CD.Instance, design: CD.Design, mode: Sinix.Mode] RETURNS [result: REFNIL, props: Core.Properties ← NIL] = {
[result, props] ← ExtractCDInstance[instance, design, mode !
Sinix.FusionPropMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
IF prop=CoreOps.nameProp
THEN TerminalIO.PutF["*** Two wires that do not have the same name are fused: %g and %g.\n", IO.rope[NARROW [value1]], IO.rope[NARROW [value2]]]
ELSE TerminalIO.PutF["*** Two wires that do not have the same %g property value are fused: %g and %g.\n", IO.atom[prop], IO.refAny[value1], IO.refAny[value2]];
GOTO Failed;
};
Sinix.FusionStructureMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n *** Two wires with mismatching structures are fused: ", IO.rope[name]];
CoreOps.Print[wire1, TerminalIO.TOS[]];
TerminalIO.PutF["\nand: "];
CoreOps.Print[wire2, TerminalIO.TOS[]];
TerminalIO.PutF["\n.\n"];
HighLightWireGeometry[design, mode, name, LIST [wire1, wire2]];
GOTO Failed;
};
Sinix.StructureMismatch => {
TerminalIO.PutF["CoreCDUser: Extraction failed in cell %g.\n CoreCDUser: Actual: ", IO.rope[name]];
CoreOps.Print[actual, TerminalIO.TOS[]];
TerminalIO.PutF["\nand subPublic: "];
CoreOps.Print[subPublic, TerminalIO.TOS[]];
TerminalIO.PutF["\nhave mismatching structures for the index %g.\n", IO.int[index]];
HighLightWireGeometry[design, mode, name, LIST [actual]];
GOTO Failed;
};
Sinix.FusionByNameMismatch => {
TerminalIO.PutF["CoreCDUser: Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF["CoreCDUser: Fusion by name problem: %g.\n", IO.rope[msg]];
HighLightWireGeometry[design, mode, name, LIST [wire]];
GOTO Failed;
};
Sinix.StructuralLoop => {
TerminalIO.PutF["CoreCDUser: Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF["CoreCDUser: Probably a structural loop in wire: %g.\n", IO.rope[CoreOps.GetShortWireName[wire]]];
HighLightWireGeometry[design, mode, name, LIST [wire]]; -- be careful not to be recursive!
GOTO Failed;
};
];
EXITS Failed => NULL;
};
HighLightWireGeometry: PROC [design: CD.Design, mode: Sinix.Mode, name: Rope.ROPE, wires: LIST OF Core.Wire] = {
IF name=NIL THEN RETURN; -- no highlight done
to be replaced by a PushByName one day
FOR insts: CD.InstanceList ← CDOps.InstList[design], insts.rest WHILE insts#NIL DO
AddGeometry: PROC [w: Core.Wire] = {
IF CoreOps.Member[ws, w] THEN RETURN; -- to avoid infinite recursion, for example
ws ← CONS [w, ws];
FOR gs: CoreGeometry.Instances ← CoreGeometry.GetGeometry[mode.decoration, w], gs.rest WHILE gs#NIL DO
IF NOT CoreGeometry.Intersect[CD.InterestRect[insts.first.ob], gs.first] THEN LOOP;
geometry ← CONS [CoreGeometry.Transform[insts.first.trans, gs.first], geometry];
ENDLOOP;
FOR i: NAT IN [0 .. w.size) DO AddGeometry[w[i]] ENDLOOP;
};
geometry: CoreGeometry.Instances ← NIL;
ws: LIST OF Core.Wire ← NIL;
IF NOT Rope.Equal[PW.Name[insts.first.ob], name] THEN LOOP;
WHILE wires#NIL DO AddGeometry[wires.first]; wires ← wires.rest ENDLOOP;
IF geometry=NIL THEN RETURN;
HighlightDesignList[design, HighlightInstanceList[geometry]];
TerminalIO.PutF["Highlight of the culprits done.\n"];
ENDLOOP;
};
ExtractCDInstanceCellTypeAndReport: PUBLIC PROC [instance: CD.Instance, design: CD.Design, mode: Sinix.Mode] RETURNS [root: Core.CellType ← NIL] = {
result: REF ANY ← ExtractCDInstanceAndReport[instance, design, mode].result;
IF ISTYPE[result, Core.CellType] THEN root ← NARROW[result]
ELSE TerminalIO.PutRope["CoreCDUser: CD instance extracts to something other than a Core cell type"];
};
EnumerateSelectedInstances: PUBLIC PROC [design: CD.Design, eachInstance: EachSelectedInstanceProc] RETURNS [quit: BOOLFALSE] = {
ThisInstance: CDCells.InstEnumerator = {
IF inst.selected THEN {
IF design.actual.first.mightReplace=NIL THEN quit ← eachInstance[[inst.ob]]
ELSE {
trans: CD.Transformation ← design.actual.first.mightReplace.trans;
quit ← eachInstance[[inst.ob, [CDBasics.DeMapPoint[inst.trans.off, trans], CDBasics.DecomposeOrient[itemInWorld: inst.trans.orient, cellInWorld: trans.orient]]]];
};
};
};
quit ← CDCells.EnumerateInstances[design.actual.first.dummyCell.ob, ThisInstance];
};
SameCDInstance: PUBLIC PROC [cdInstance: CD.Instance, cdInstanceTrans: CD.Transformation, coreInstance: CoreGeometry.Instance] RETURNS [BOOL] = {
RETURN [
SameCDObject[cdInstance.ob, coreInstance.obj] AND
CDBasics.DeMapPoint[cdInstance.trans.off, cdInstanceTrans]=coreInstance.trans.off AND
CDBasics.DecomposeOrient[itemInWorld: cdInstance.trans.orient, cellInWorld: cdInstanceTrans.orient]=coreInstance.trans.orient
];
};
SameCDObject: PUBLIC PROC [cdObject, coreObject: CD.Object] RETURNS [BOOL] = {
DO
IF cdObject=coreObject THEN RETURN[TRUE];
IF CDCells.IsCell[cdObject] OR NOT cdObject.class.composed THEN RETURN[FALSE];
cdObject ← CDDirectory.Expand1[cdObject].new;
ENDLOOP;
};
IsSchematic: PUBLIC PROC [design: CD.Design, object: CD.Object] RETURNS [BOOL] = {
The design is passed only to recover the name ...
IsSuffix: PROC [self, suffix: Rope.ROPE] RETURNS [BOOL] ~ {
Return TRUE iff self ends with suffix
startFrom: INT = Rope.Length[self]-Rope.Length[suffix];
IF startFrom<0 THEN RETURN [FALSE]; -- suffix longer than self
RETURN [Rope.Run[s1: self, pos1: startFrom, s2: suffix, pos2: 0]=Rope.Length[suffix]];
};
name: Rope.ROPE = CDDirectory.Name[object, design];
SELECT TRUE FROM
IsSuffix[name, ".sch"] => RETURN [TRUE];
IsSuffix[name, ".icon"] => RETURN [TRUE];
IsSuffix[name, ".mask"] => RETURN [FALSE];
ENDCASE => { -- general case, take an educated guess based on non-comment layers
Answer: TYPE = {yes, no, dontknow};
Schema: PROC [object: CD.Object] RETURNS [answer: Answer ← dontknow] = {
SELECT TRUE FROM
CDRects.IsSimpleRect[object] => SELECT TRUE FROM
CD.LayerTechnology[object.layer]#NIL => answer ← no; -- definitely layout
CDLayers.Kind[object.layer]=paint => answer ← yes; -- definitely schematic
ENDCASE => answer ← dontknow; -- some highlight or similar funny layer
CDCells.IsCell[object] => {
EachInstance: CDCells.InstEnumerator = {
answer ← Schema[inst.ob];
quit ← answer#dontknow;
};
IF RefTab.Fetch[visitedCells, object].found THEN answer ← dontknow
ELSE {
IF NOT RefTab.Insert[visitedCells, object, NIL] THEN ERROR;
[] ← CDCells.EnumerateInstances[object, EachInstance];
};
};
object.class.composed => answer ← Schema[CDDirectory.Expand1[object].new];
ENDCASE => answer ← dontknow;
};
visitedCells: RefTab.Ref ← RefTab.Create[];
RETURN[NOT Schema[object]=no];
};
};
GetExtractMode: PUBLIC PROC [design: CD.Design, object: CD.Object] RETURNS [mode: Sinix.Mode] = {
mode ← IF IsSchematic[design, object] THEN Sisyph.mode ELSE SinixCMosB.mode;
};
PopTop: PUBLIC PROC [design: CD.Design] = {
WHILE CDCells.IsPushedIn[design] DO
[] ← CDCellsInteractions.PopFromCell[design, interactive];
ENDLOOP;
};
GetTopInstances: PUBLIC PROC [design: CD.Design] RETURNS [topInstances: TopInstanceLists ← NIL] = {
GetInstances: PROC [design: CD.Design] = {
theseInstances: CD.InstanceList ← 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;
theseInstances ← stack.first.specific.contents;
IF trail#NIL THEN theseInstances ← CONS [trail.first.mightReplace, theseInstances];
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, theseInstances], topInstances];
};
processedDesigns: RefTab.Ref ← RefTab.Create[];
GetInstances[design];
};
FindSameInstance: PUBLIC PROC [design: CD.Design, cellInstance: CD.Instance, cellTransform: CD.Transformation] RETURNS [worldInstance: CD.Instance] = {
cellInstanceTransform: CD.Transformation ← CDBasics.ComposeTransform[cellInstance.trans, cellTransform];
FOR worldInstances: CD.InstanceList ← design.actual.first.specific.contents, worldInstances.rest UNTIL worldInstances=NIL DO
IF worldInstances.first.ob=cellInstance.ob AND worldInstances.first.trans=cellInstanceTransform THEN {
worldInstance ← worldInstances.first;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
};
END.