<> <> <> <> <> 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; <> 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: REF _ NIL, 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"]; }; <> IsSuffix: PROC [self, suffix: Rope.ROPE] RETURNS [BOOL] ~ { <> 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: BOOL _ TRUE] = { 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.ROPE _ NARROW [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.