PipalExtractOpsImpl.mesa
Copyright Ó 1987, 1988 by Xerox Corporation. All rights reserved.
Barth, October 14, 1987 4:14:55 pm PDT
Jean-Marc Frailong December 9, 1987 7:27:00 pm PST
Bertrand Serlet April 30, 1988 7:01:01 pm PDT
DIRECTORY
Core, CoreOps, IO,
Pipal, PipalCore, PipalExtractOps, PipalInt, PipalMos, PipalSinix, PipalSisyph, PipalUI,
RefTab, Rope, TerminalIO;
PipalExtractOpsImpl: CEDAR PROGRAM
IMPORTS CoreOps, IO, Pipal, PipalCore, PipalInt, PipalMos, PipalSinix, PipalSisyph, PipalUI, RefTab, Rope, TerminalIO
EXPORTS PipalExtractOps
= BEGIN OPEN PipalExtractOps;
Extraction Conveniences
ExtractTopObject: PUBLIC PROC [object: Pipal.Object, mode: PipalSinix.Mode] RETURNS [result: REF, props: Core.Properties] = {
context: PipalSinix.Context ← SELECT mode FROM
PipalSinix.layoutMode  => NIL,
PipalSinix.schematicsMode => PipalSisyph.CreateContext[],
ENDCASE   => ERROR;
[result, props] ← PipalSinix.Extract[object, mode, context];
};
ExtractTopObjectAndReport: PUBLIC PROC [object: Pipal.Object, mode: PipalSinix.Mode] RETURNS [result: REFNIL, props: Core.Properties ← NIL] = {
[result, props] ← ExtractTopObject[object, mode !
PipalSinix.FusionPropMismatch => {
cellDesign: PipalUI.Design ← PipalUI.Draw[object];
TerminalIO.PutF["*** Extraction failed in cell.\n"];
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;
};
PipalSinix.FusionStructureMismatch => {
cellDesign: PipalUI.Design ← PipalUI.Draw[object];
TerminalIO.PutF["*** Extraction failed in cell.\n *** Two wires with mismatching structures are fused: "];
CoreOps.Print[wire1, TerminalIO.TOS[]];
TerminalIO.PutF["\nand: "];
CoreOps.Print[wire2, TerminalIO.TOS[]];
TerminalIO.PutF["\n.\n"];
HighLightWireGeometry[cellDesign, mode, LIST [wire1, wire2]];
GOTO Failed;
};
PipalSinix.StructureMismatch => {
cellDesign: PipalUI.Design ← PipalUI.Draw[object];
TerminalIO.PutF["*** Extraction failed in cell.\n Actual: "];
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[cellDesign, mode, LIST [actual]];
GOTO Failed;
};
PipalSinix.FusionByNameMismatch => {
cellDesign: PipalUI.Design ← PipalUI.Draw[object];
TerminalIO.PutF["*** Extraction failed in cell.\nFusion by name problem: %g.\n", IO.rope[msg]];
HighLightWireGeometry[cellDesign, mode, LIST [wire]];
GOTO Failed;
};
PipalSinix.StructuralLoop => {
cellDesign: PipalUI.Design ← PipalUI.Draw[object];
TerminalIO.PutF["*** Extraction failed in cell.\nProbably a structural loop in wire: %g.\n", IO.rope[CoreOps.GetShortWireName[wire]]];
HighLightWireGeometry[cellDesign, mode, LIST [wire]]; -- be careful not to be recursive!
GOTO Failed;
};
];
EXITS Failed => NULL;
};
HighLightWireGeometry: PROC [design: PipalUI.Design, mode: PipalSinix.Mode, wires: LIST OF Core.Wire] = {
highlights: Pipal.Objects ← NIL;
ws: LIST OF Core.Wire ← NIL;
AddGeometry: PROC [w: Core.Wire] = {
IF CoreOps.Member[ws, w] THEN RETURN; -- to avoid infinite recursion, for example
ws ← CONS [w, ws];
highlights ← CONS [PipalCore.GetGeometry[mode.decoration, w], highlights];
FOR i: NAT IN [0 .. w.size) DO AddGeometry[w[i]] ENDLOOP;
};
WHILE wires#NIL DO AddGeometry[wires.first]; wires ← wires.rest ENDLOOP;
PipalUI.HighlightDesign[design, [], Pipal.CreateOv[highlights]];
TerminalIO.PutF[IF highlights=NIL THEN "Sorry, no highlight possible" ELSE "Highlight of the culprits done.\n"];
};
ExtractTopObjectToCellTypeAndReport: PUBLIC PROC [object: Pipal.Object, mode: PipalSinix.Mode] RETURNS [root: Core.CellType ← NIL] = {
result: REF ANY ← ExtractTopObjectAndReport[object, mode].result;
IF ISTYPE[result, Core.CellType] THEN root ← NARROW [result]
ELSE TerminalIO.PutRope["*** Object extracts to something other than a Core cell type"];
};
Mode Heuristics
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]];
};
IsSchematic: PUBLIC PROC [object: Pipal.Object] RETURNS [schematic: BOOLTRUE] = {
Schema: PipalInt.EachChildProc = {
WITH child SELECT FROM
box: PipalMos.Box => {quit ← TRUE; schematic ← PipalMos.IsSchematicLayer[box.layer]};
marker: PipalMos.Marker => {quit ← TRUE; schematic ← PipalMos.IsSchematicLayer[marker.layer]};
annotation: Pipal.Annotation => {
SELECT annotation.key FROM
PipalMos.atomicProp, PipalMos.biAtomicProp, PipalMos.transistorProp => {
quit ← TRUE; schematic ← FALSE;
};
Pipal.nameProp => {
name: Pipal.ROPENARROW [annotation.value];
SELECT TRUE FROM
IsSuffix[name, ".sch"] => {quit ← TRUE; schematic ← TRUE};
IsSuffix[name, ".icon"] => {quit ← TRUE; schematic ← TRUE};
IsSuffix[name, ".pict"] => {quit ← TRUE; schematic ← TRUE};
IsSuffix[name, ".mask"] => {quit ← TRUE; schematic ← FALSE};
ENDCASE => quit ← Schema[[], annotation.child];
};
ENDCASE => quit ← Schema[[], annotation.child];
};
ENDCASE  => {
IF NOT PipalInt.HasEnumerate[child] THEN RETURN;
IF RefTab.Fetch[visitedCells, object].found THEN RETURN;
[] ← RefTab.Store[visitedCells, object, NIL];
quit ← PipalInt.Enumerate[child, Schema];
};
};
visitedCells: RefTab.Ref ← RefTab.Create[];
[] ← Schema[[], object];
};
GetExtractMode: PUBLIC PROC [object: Pipal.Object] RETURNS [mode: PipalSinix.Mode] = {
mode ← IF IsSchematic[object] THEN PipalSinix.layoutMode ELSE PipalSinix.schematicsMode;
};
END.