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.
ROPE ←
NIL] = {
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.
ROPE ←
NIL] = {
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.
ROPE ←
NIL] = {
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.
ROPE ←
NIL]
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:
REF ←
NIL, 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:
BOOL ←
FALSE] = {
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.