<> <> <> <> <> <> <> <> DIRECTORY AMTypes USING [Copy, TV, TVEqual], AMBridge USING [SomeRefFromTV, TVForFrame, TVForReferent], AMModel USING [Context], AMModelBridge USING [ContextForFrame], CD, CDCells, CDDirectory, CDImports, CDImportsBackdoor, CDLayers, CDProperties, CDRects, CDRemote, CDSatellites, CDSequencer, CDSymbolicObjects, CDTexts, Core, CoreClasses, CoreOps, CoreProperties, CoreGeometry, HashTable, IO, Interpreter USING [Evaluate], PrincOpsUtils, PWObjects, Rope, RopeList, Sinix, Sisyph, SymTab, TerminalIO; SisyphImpl: CEDAR PROGRAM IMPORTS AMBridge, AMModelBridge, AMTypes, CDCells, CDDirectory, CDImports, CDImportsBackdoor, CDLayers, CDProperties, CDRects, CDRemote, CDSatellites, CDSequencer, CDTexts, CoreClasses, CoreOps, CoreProperties, CoreGeometry, HashTable, Interpreter, IO, PrincOpsUtils, PWObjects, Rope, RopeList, Sinix, SymTab, TerminalIO EXPORTS Sisyph SHARES CDCells, CDImports, CDRects, CDRemote, CDTexts, Sinix = BEGIN OPEN Sisyph; <> expressionsProp: PUBLIC ATOM _ PWObjects.RegisterProp[$SisyphExpressions, TRUE]; designRope: PRIVATE ROPE _ "design"; <> cellIconRope: PUBLIC ROPE _ "cI"; wireIconRope: PUBLIC ROPE _ "wI"; wireRope: PUBLIC ROPE _ "wire"; nameRope: PUBLIC ROPE _ "name"; globalNamesRope: PRIVATE ROPE _ "globalNames"; <> corePropsRope: PUBLIC ROPE _ "coreProps"; coreInstPropsRope: PUBLIC ROPE _ "coreInstProps"; cdObjRope: PRIVATE ROPE _ "cdObj"; <> localVariablesRopes: ROPES = LIST ["&", cellIconRope, wireIconRope, nameRope, wireRope, corePropsRope, coreInstPropsRope]; ignoreMeProp: PRIVATE ATOM _ PWObjects.RegisterProp[$SisyphIgnoreMe, TRUE]; <> parmNamesProp: PUBLIC ATOM _ PWObjects.RegisterProp[$SisyphParmNames, TRUE]; defaultGlobalNames: PUBLIC ROPES _ LIST ["Vdd", "Gnd"]; mode: PUBLIC Sinix.Mode _ NEW [Sinix.ModeRec _ [ extractProcProp: PWObjects.RegisterProp[$SisyphExtractProc, TRUE], decoration: CoreGeometry.CreateDecoration["Sisyph"], equalProc: ResultEqual, instanceLayer: Sinix.DefaultInstanceLayer, userData: DefaultUserData, fusionByName: schematics, touchProc: Touch ]]; <> <> ExtractSchematic: Sinix.ExtractProc = { cx: Context; coreProps: Core.Properties; resultRope: ROPE; [cx, resultRope] _ EvaluateParameters[userData, obj, properties, IsResultExpression]; EvaluateResult[cx, resultRope]; coreProps _ GetCoreProps[cx]; props _ GetCoreInstProps[cx]; SELECT TRUE FROM Rope.Match["*cI*_*", resultRope] => { cellType: CellType _ ExtractCellIcon[obj, cx]; cellType.properties _ PutCoreProps[cellType.properties, coreProps]; result _ cellType; }; Rope.Match["*wI*_*", resultRope] => { wire: Wire _ ExtractWireIcon[obj, cx]; wire.properties _ PutCoreProps[wire.properties, coreProps]; result _ wire; }; Rope.Match["*wire*_*", resultRope] => ERROR; ENDCASE => { name: ROPE _ GetName[cx]; cellType: CellType; [result, props] _ Sinix.ExtractCell[obj, mode, properties, cx]; cellType _ NARROW [result]; ProcessGlobalNames[cellType, cx]; IF name=NIL THEN name _ CDNameToCTName[CDDirectory.Name[obj], ".sch"]; cellType _ CoreOps.SetCellTypeName[cellType, name]; cellType.properties _ PutCoreProps[cellType.properties, coreProps]; }; }; ExtractWire: Sinix.ExtractProc = { wire: Wire; cx: Context; name: ROPE; resultRope: ROPE; coreInstProps: Core.Properties; IF obj.class#CDRects.bareRectClass THEN ERROR; IF obj.layer#CD.commentLayer THEN ERROR; <> <> [cx, resultRope] _ EvaluateParameters[userData, obj, properties, IsResultExpression]; EvaluateResult[cx, resultRope]; wire _ GetWireCore[cx]; name _ GetName[cx]; coreInstProps _ GetCoreInstProps[cx]; IF wire=NIL THEN wire _ CoreOps.CreateWire[name: name]; CoreGeometry.PutPins[mode.decoration, wire, LIST [[obj]]]; wire.properties _ PutCoreProps[wire.properties, coreInstProps]; result _ wire; }; <<>> ExtractImport: Sinix.ExtractProc = { cx: Context = NARROW [userData]; design: CD.Design _ GetDesign[cx]; import: CDImports.ImportSpecific = NARROW [obj.specific]; importDesign: CD.Design; importObj: CD.Object; CDSequencer.CheckAborted[design]; importDesign _ CDRemote.FetchDesign[design, import.designName]; IF import.boundInstance=NIL OR importDesign=NIL THEN { -- try to load the missing design loaded: BOOL = CDImportsBackdoor.LoadDesign[into: design, importeeName: import.designName, overload: true, allowConflicts: interactive, useCache: TRUE]; IF NOT loaded THEN { -- loading failed TerminalIO.PutF["*** Error: Cannot load import %g[%g] which is unbound.\n", IO.rope[import.objectName], IO.rope[import.designName]]; ERROR; }; importDesign _ CDRemote.FetchDesign[design, import.designName]; IF import.boundInstance=NIL THEN { -- Object not bound yet TerminalIO.PutF["*** Error: Object %g[%g] is unbound within %g.\n", IO.rope[import.objectName], IO.rope[import.designName], IO.rope[design.name]]; ERROR; }; IF importDesign=NIL THEN { -- can't find the design in the cache TerminalIO.PutF["*** Error: Cannot reach design %g from design %g.\n", IO.rope[import.designName], IO.rope[design.name]]; ERROR; }; }; importObj _ import.boundInstance.ob; RETURN Sinix.Extract[obj: importObj, mode: mode, properties: properties, userData: Create[importDesign, cx]]; }; ES, ExtractSchematicByName: PUBLIC PROC [name: ROPE, cx: Context] RETURNS [CellType] = { design: CD.Design = GetDesign[cx]; obj: CD.Object = CDDirectory.Fetch[design, name].object; IF obj=NIL THEN {TerminalIO.PutF["*** Error: ES cannot find object '%g' in design '%g'.\n", IO.rope[name], IO.rope[design.name]]; ERROR}; RETURN [NARROW [Sinix.Extract[obj: obj, mode: mode, properties: NIL, userData: cx].result]]; }; <> ExtractCellIcon: PROC [icon: CD.Object, cx: Context] RETURNS [cellType: CellType] = { SmashPins: CoreOps.EachWireProc = {CoreGeometry.PutPins[mode.decoration, wire, NIL]}; iconCT: CellType; name: ROPE; iconCT _ NARROW [Sinix.ExtractCell[icon, mode, NIL, cx].result]; <> cellType _ GetCellIconCore[cx]; name _ GetName[cx]; IF cellType=NIL THEN { IF name=NIL THEN name _ CDNameToCTName[CDDirectory.Name[icon], ".icon"]; cellType _ CoreOps.CreateCellType[class: CoreClasses.unspecifiedCellClass, public: iconCT.public, name: name]; } ELSE { IF name=NIL THEN name _ CoreOps.GetCellTypeName[cellType]; IF name=NIL THEN name _ CDNameToCTName[CDDirectory.Name[icon], ".icon"]; cellType _ CreateIcon[cellType: cellType, name: name]; }; <> [] _ CoreOps.VisitWireSeq[cellType.public, SmashPins]; CoreGeometry.PutObject[mode.decoration, cellType, icon]; <> IF NOT CheckAndDecorate[icon, iconCT.public, cellType.public, GetGlobalNames[cx]] THEN { TerminalIO.PutF["*** Error: icon public and schematic public for cell icon %g do NOT conform\n", IO.rope[CDDirectory.Name[icon]]]; TerminalIO.PutF["Icon public is:"]; CoreOps.PrintWire[wire: iconCT.public, out: TerminalIO.CreateStream[], level: LAST [NAT]]; TerminalIO.PutF["\nSchematic public is:"]; CoreOps.PrintWire[wire: cellType.public, out: TerminalIO.CreateStream[], level: LAST [NAT]]; TerminalIO.PutF["\n"]; ERROR } }; <> ExtractWireIcon: PROC [icon: CD.Object, cx: Context] RETURNS [result: Wire] = { iconCT: CellType _ NARROW [Sinix.ExtractCell[icon, mode, NIL, cx].result]; result _ GetWireIconCore[cx]; IF result=NIL THEN ERROR; <<>> <> IF iconCT.public.size=1 THEN { <> CoreGeometry.PutPins[mode.decoration, result, CoreGeometry.GetPins[mode.decoration, iconCT.public[0]]]; RETURN; }; IF ~CheckAndDecorate[icon, iconCT.public, CoreOps.CreateWire[LIST [result]]] THEN { TerminalIO.PutF["*** Error: icon wire and result wire for wire icon %g don't conform\n", IO.rope[CDDirectory.Name[icon]]]; TerminalIO.PutF["Icon wire is:"]; CoreOps.PrintWire[wire: iconCT.public, out: TerminalIO.CreateStream[], level: LAST [NAT]]; TerminalIO.PutF["\nResult wire is:"]; CoreOps.PrintWire[wire: result, out: TerminalIO.CreateStream[], level: LAST [NAT]]; TerminalIO.PutF["\n"]; ERROR } }; <> InitLocalVariables: PUBLIC PROC [cx: Context, obj: CD.Object] = { IF cx=NIL THEN ERROR; Store[cx, cellIconRope, NEW [CellType _ NIL]]; Store[cx, wireIconRope, NEW [Wire _ NIL]]; Store[cx, wireRope, NEW [Wire _ NIL]]; Store[cx, nameRope, NEW [ROPE _ NIL]]; Store[cx, corePropsRope, NEW [Core.Properties _ NIL]]; Store[cx, coreInstPropsRope, NEW [Core.Properties _ NIL]]; Store[cx, cdObjRope, NEW [CD.Object _ obj]] }; Create: PUBLIC PROC [design: CD.Design, previousCx: Context _ NIL] RETURNS [cx: Context] = { cx _ IF previousCx=NIL THEN SymTab.Create[] ELSE Copy[previousCx]; Store[cx, designRope, NEW [CD.Design _ design]]; Insert[cx, globalNamesRope, NEW [ROPES _ defaultGlobalNames]]; Store[cx, "&", NEW [INT _ 0]]; FOR exprs: ROPES _ NARROW [CDProperties.GetDesignProp[design, expressionsProp]], exprs.rest WHILE exprs#NIL DO Eval[cx, exprs.first]; ENDLOOP; FOR satellites: ROPES _ CDSatellites.GetSatelliteRopes[design], satellites.rest WHILE satellites#NIL DO Eval[cx, satellites.first]; ENDLOOP; InitLocalVariables[cx, NIL]; }; Copy: PUBLIC PROC [cx: Context] RETURNS [newCx: Context] = { CopyItem: SymTab.EachPairAction = { tv: AMTypes.TV _ NARROW[val]; [] _ SymTab.Store[newCx, key, AMTypes.Copy[tv]]; quit _ FALSE; }; IF cx=NIL THEN ERROR; newCx _ SymTab.Create[]; [] _ SymTab.Pairs[cx, CopyItem]; }; Store: PUBLIC PROC [cx: Context, var: ROPE, value: REF _ NIL] = { [] _ SymTab.Store[cx, var, TVFromRef[value]]; }; Insert: PUBLIC PROC [cx: Context, var: ROPE, value: REF _ NIL] = { [] _ SymTab.Insert[cx, var, TVFromRef[value]]; }; FetchInt: PUBLIC PROC [cx: Context, var: ROPE] RETURNS [found: BOOL, value: INT] = { ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, var]; IF NOT found THEN RETURN; value _ NARROW [RefFromTV[ref], REF INT]^; }; Eval: PUBLIC PROC [cx: Context, expr: ROPE, cedarCx: AMModel.Context _ NIL] = TRUSTED { result: AMTypes.TV; errorRope: ROPE; noResult: BOOL; IF cedarCx=NIL THEN cedarCx _ AMModelBridge.ContextForFrame[ AMBridge.TVForFrame[ PrincOpsUtils.GetReturnFrame[] ] ]; [result, errorRope, noResult] _ Interpreter.Evaluate[rope: expr, context: cedarCx, symTab: cx]; IF errorRope=NIL THEN RETURN; SIGNAL InterpreterError[cx, expr, errorRope]; ERROR; }; ContextEqual: PROC [cx1, cx2: Context, parmNames: ROPES] RETURNS [BOOL] = { <> IsDifferent: PROC [a, b: Context] RETURNS [BOOL] = { CheckAbsentInb: SymTab.EachPairAction = { found: BOOL; bVal: SymTab.Val; <<>> <> IF RopeList.Memb[localVariablesRopes, key] THEN RETURN [FALSE]; <> IF parmNames#NIL AND NOT RopeList.Memb[parmNames, key] THEN RETURN [FALSE]; <> [found, bVal] _ SymTab.Fetch[b, key]; IF ~found THEN RETURN [TRUE]; IF TVEqual[bVal, val] THEN RETURN [FALSE]; RETURN [TRUE]; }; RETURN [SymTab.Pairs[a, CheckAbsentInb]]; }; RETURN [cx1=cx2 OR (NOT IsDifferent[cx1, cx2] AND NOT IsDifferent[cx2, cx1])] }; ResultEqual: PROC [obj: CD.Object, p1: CD.PropList, ud1: REF, p2: CD.PropList, ud2: REF] RETURNS [BOOL] = { cx1: Context _ NARROW [ud1]; cx2: Context _ NARROW [ud2]; instArgs1: ROPES _ NARROW [CDProperties.GetListProp[p1, expressionsProp]]; satArgs1: ROPES _ NARROW [CDProperties.GetListProp[p1, Sinix.satellitesProp]]; instArgs2: ROPES _ NARROW [CDProperties.GetListProp[p2, expressionsProp]]; satArgs2: ROPES _ NARROW [CDProperties.GetListProp[p2, Sinix.satellitesProp]]; parmNames: ROPES _ NARROW [CDProperties.GetObjectProp[obj, parmNamesProp]]; <> IF parmNames#NIL AND Rope.Equal[parmNames.first, "0"] THEN RETURN [TRUE]; RETURN [EqualRopes[instArgs1, instArgs2] AND EqualRopes[satArgs1, satArgs2] AND ContextEqual[cx1, cx2, parmNames]]; }; <> iconClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Icon", recast: RecastIcon, layersProps: TRUE]], PrintIcon]; CreateIcon: PUBLIC PROC [cellType: CellType, name: ROPE _ NIL, props: Core.Properties _ NIL] RETURNS [icon: CellType] = { icon _ CoreOps.CreateCellType[ class: iconClass, public: CoreOps.CopyWire[cellType.public], data: cellType, name: name, props: props]; }; RecastIcon: Core.RecastProc = {new _ NARROW [me.data]}; PrintIcon: CoreOps.PrintClassProc = { ct: CellType _ NARROW [data]; CoreOps.PrintIndent[indent, out]; out.PutF["Icon of `%g':\n", IO.rope[CoreOps.GetCellTypeName[ct]]]; CoreOps.PrintCellType[cellType: ct, out: out, indent: indent, level: level]; }; <> EqualRopes: PUBLIC PROC [ropes1, ropes2: ROPES] RETURNS [BOOL] = { FOR r1: ROPES _ ropes1, r1.rest WHILE r1#NIL DO IF NOT RopeList.Memb[ropes2, r1.first] THEN RETURN [FALSE]; ENDLOOP; FOR r2: ROPES _ ropes2, r2.rest WHILE r2#NIL DO IF NOT RopeList.Memb[ropes1, r2.first] THEN RETURN [FALSE]; ENDLOOP; RETURN [TRUE]; }; Cons: PUBLIC PROC [r: ROPE, lor: ROPES] RETURNS [ROPES] = { RETURN [CONS [r, lor]]; }; List: PUBLIC PROC [r1, r2, r3, r4, r5, r6: ROPE _ NIL] RETURNS [lor: ROPES _ NIL] = { IF r6#NIL THEN lor _ CONS [r6, lor]; IF r5#NIL THEN lor _ CONS [r5, lor]; IF r4#NIL THEN lor _ CONS [r4, lor]; IF r3#NIL THEN lor _ CONS [r3, lor]; IF r2#NIL THEN lor _ CONS [r2, lor]; IF r1#NIL THEN lor _ CONS [r1, lor]; }; <> EvaluateResult: PROC [cx: Context, resultRope: ROPE] = { IF resultRope=NIL THEN RETURN; <> IF Rope.Match["cI _ ES[\"*\", cx]", resultRope] THEN { pos1: INT _ Rope.Find[s1: resultRope, s2: "\""]; pos2: INT _ Rope.Find[s1: resultRope, s2: "\"", pos1: pos1+1]; name: ROPE _ Rope.Substr[resultRope, pos1+1, pos2-pos1-1]; Store[cx, cellIconRope, NEW [CellType _ ES[name, cx]]]; RETURN }; Eval[cx, resultRope]; }; CheckAndDecorate: PROC [icon: CD.Object, drawnPublic, resultPublic: Wire, globalNames: ROPES _ NIL] RETURNS [ok: BOOL _ TRUE] = { iconName: ROPE = CDDirectory.Name[icon]; resultToDrawn: HashTable.Table _ HashTable.Create[]; -- associates resultPublic to drawnPublic <> FOR i: NAT IN [0 .. drawnPublic.size) DO EachResultWire: CoreOps.EachWireProc = { resultName: ROPE _ CoreOps.GetShortWireName[wire]; IF NOT Rope.Equal[resultName, drawnName] THEN RETURN; IF wire=resultWire THEN RETURN; IF resultWire#NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has a wire %g whose name appears more than once in the schematic\n", IO.rope[iconName], IO.rope[drawnName]]; quit _ TRUE; ok _ FALSE; RETURN}; resultWire _ wire; }; drawnWire: Wire _ drawnPublic[i]; drawnName: ROPE _ CoreOps.GetShortWireName[drawnWire]; resultWire: Wire _ NIL; IF drawnName=NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has an unnamed wire\n", IO.rope[iconName]]; ok _ FALSE; LOOP}; IF CoreOps.VisitWire[resultPublic, EachResultWire] THEN LOOP; IF resultWire=NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has wire %g that doesn't correspond to any wire in the schematic\n", IO.rope[iconName], IO.rope[drawnName]]; ok _ FALSE; LOOP}; <> CoreGeometry.PutPins[mode.decoration, resultWire, CoreGeometry.GetPins[mode.decoration, drawnWire]]; [] _ HashTable.Store[resultToDrawn, resultWire, drawnWire]; ENDLOOP; <> FOR i: NAT IN [0 .. resultPublic.size) DO resultWire: Wire _ resultPublic[i]; resultName: ROPE _ CoreOps.GetShortWireName[resultWire]; drawnWire: Wire _ NARROW [HashTable.Fetch[resultToDrawn, resultWire].value]; IF resultName=NIL THEN LOOP; IF drawnWire#NIL THEN LOOP; IF RopeList.Memb[globalNames, resultName] THEN LOOP; TerminalIO.PutF["*** Warning in Cell %g: schematic has wire %g that corresponds to no wire in the drawn Icon\n", IO.rope[iconName], IO.rope[resultName]]; ENDLOOP; }; <> <> <> <> <> <> <> <> <> <<}>> <<};>> <> <<[] _ CDDirectory.Enumerate[design, MarkForEachCell];>> <<};>> <<>> ProcessGlobalName: PROC [record: CellType, name: ROPE] = { globals: Wires; ReplaceSeq: PROC [old: WireSeq] RETURNS [new: WireSeq] = { new _ old; FOR i: NAT IN [0 .. old.size) DO new[i] _ Replace[old[i]] ENDLOOP; }; Replace: PROC [old: Wire] RETURNS [new: Wire] = { IF old.size#0 THEN RETURN [ReplaceSeq[old]]; RETURN [IF CoreOps.Member[globals, old] THEN global ELSE old]; }; ReplaceAndCleanSeq: PROC [old: WireSeq] RETURNS [new: WireSeq] = { news: Wires _ LIST [global]; FOR i: NAT IN [0 .. old.size) DO new _ Replace[old[i]]; IF NOT CoreOps.Member[news, new] THEN news _ CONS [new, news]; ENDLOOP; new _ CoreOps.CreateWire[news]; }; InsertGlobal: PROC [wire: Wire] = { IF wire.size#0 THEN SIGNAL GlobalNonAtomic[record, name, wire]; IF NOT CoreOps.Member[globals, wire] THEN globals _ CONS [wire, globals]; }; FindGlobals: CoreOps.EachWirePairProc = { actualName: ROPE = CoreOps.GetShortWireName[actualWire]; publicName: ROPE = CoreOps.GetShortWireName[publicWire]; IF NOT Rope.Equal[publicName, name] THEN RETURN; -- not a sub global candidate IF actualName=NIL OR Rope.Equal[actualName, name] THEN InsertGlobal[actualWire]; }; FindWire: CoreOps.EachWireProc = { IF Rope.Equal[CoreOps.GetShortWireName[wire], name] THEN InsertGlobal[wire]; }; rct: CoreClasses.RecordCellType = NARROW [record.data]; global: Wire; FOR i: NAT IN [0..rct.size) DO [] _ CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, FindGlobals]; ENDLOOP; [] _ CoreOps.VisitWireSeq[rct.internal, FindWire]; IF globals=NIL THEN RETURN; global _ CoreOps.SetShortWireName[globals.first, name]; globals _ globals.rest; record.public _ ReplaceAndCleanSeq[record.public]; rct.internal _ ReplaceAndCleanSeq[rct.internal]; FOR i: NAT IN [0..rct.size) DO rct[i].actual _ ReplaceSeq[rct[i].actual] ENDLOOP; WHILE globals#NIL DO Sinix.FuseProperties[mode, globals.first, global, CoreOps.GetCellTypeName[record]]; globals _ globals.rest; ENDLOOP; }; Touch: CoreGeometry.TouchProc = { IF instance1.obj.class#CDRects.bareRectClass OR instance2.obj.class#CDRects.bareRectClass THEN ERROR; -- the only thing we know is Rectangles! IF ~SilTouchRect[CoreGeometry.InlineBBox[instance1], CoreGeometry.InlineBBox[instance2]] THEN RETURN; <> RETURN [CDLayers.AbstractToPaint[instance1.obj.layer]=CDLayers.AbstractToPaint[instance2.obj.layer]]; }; SilTouchRect: PROC [r1, r2: CD.Rect] RETURNS [BOOL] = INLINE { Intersect: PROC [i1min, i1max, i2min, i2max: CD.Number] RETURNS [BOOL] = INLINE { RETURN [(i1max >= i2min) AND (i2max >= i1min)]; }; Adjoin: PROC [i1min, i1max, i2min, i2max: CD.Number] RETURNS [BOOL] = INLINE { RETURN [(i2min >= i1min AND i2min <= i1max AND i2max >= i1max) OR (i1min >= i2min AND i1min <= i2max AND i1max >= i2max)]; }; RETURN [(Intersect[r1.x1, r1.x2, r2.x1, r2.x2] AND Adjoin[r1.y1, r1.y2, r2.y1, r2.y2]) OR (Intersect[r1.y1, r1.y2, r2.y1, r2.y2] AND Adjoin[r1.x1, r1.x2, r2.x1, r2.x2])] }; GetCoreProps: PUBLIC PROC [cx: Context] RETURNS [Core.Properties] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, corePropsRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Core.Properties]^] ELSE ERROR }; GetCoreInstProps: PUBLIC PROC [cx: Context] RETURNS [Core.Properties] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, coreInstPropsRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Core.Properties]^] ELSE ERROR }; GetCellIconCore: PROC [cx: Context] RETURNS [Core.CellType] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, cellIconRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Core.CellType]^] ELSE ERROR }; GetWireIconCore: PROC [cx: Context] RETURNS [Wire] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, wireIconRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Wire]^] ELSE ERROR }; GetWireCore: PROC [cx: Context] RETURNS [Wire] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, wireRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Wire]^] ELSE ERROR }; GetName: PROC [cx: Context] RETURNS [ROPE] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, nameRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF ROPE]^] ELSE ERROR }; GetDesign: PUBLIC PROC [cx: Context] RETURNS [CD.Design] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, designRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF CD.Design]^] ELSE ERROR }; GetGlobalNames: PUBLIC PROC [cx: Context] RETURNS [ROPES] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, globalNamesRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF ROPES]^] ELSE ERROR }; GetCDObj: PUBLIC PROC [cx: Context] RETURNS [CD.Object] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, cdObjRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF CD.Object]^] ELSE ERROR }; RefFromTV: PROC [tv: REF] RETURNS [REF] = { IF tv=NIL THEN RETURN [NIL]; IF ~ISTYPE [tv, AMTypes.TV] THEN ERROR; TRUSTED {RETURN [AMBridge.SomeRefFromTV[tv]]}; }; TVFromRef: PROC [ref: REF] RETURNS [AMTypes.TV] = TRUSTED { RETURN [AMBridge.TVForReferent[ref]]; }; TVEqual: PROC [tv1, tv2: REF] RETURNS [BOOL] = { IF AMTypes.TVEqual[tv1, tv2] THEN RETURN [TRUE]; WITH RefFromTV[tv1] SELECT FROM rr1: REF ROPES => WITH RefFromTV[tv2] SELECT FROM rr2: REF ROPES => RETURN [EqualRopes[rr1^, rr2^]]; ENDCASE => RETURN [FALSE]; <> ENDCASE => RETURN [FALSE]; }; PutCoreProps: PROC [onto, from: Core.Properties] RETURNS [new: Core.Properties] = { PutProp: PROC [prop: ATOM, val: REF ANY] = { new _ CoreProperties.PutProp[new, prop, val]; }; new _ onto; CoreProperties.Enumerate[from, PutProp]; }; CDNameToCTName: PROC [cdName, dropPart: ROPE] RETURNS [ctName: ROPE] = { ctName _ Rope.Substr[cdName, 0, Rope.Index[cdName, 0, dropPart]]; }; DefaultUserData: PROC [design: CD.Design] RETURNS [REF] ~ { RETURN [Create[design]]; }; <> GlobalNonAtomic: PUBLIC SIGNAL [record: CellType, name: ROPE, wire: Wire] = CODE; InterpreterError: PUBLIC SIGNAL [cx: Context, expr, errorRope: ROPE] = CODE; <> IsResultExpression: PUBLIC PROC [expr: ROPE] RETURNS [BOOL] = { RETURN [ Rope.Match["*cI*_*", expr] OR Rope.Match["*wI*_*", expr] OR Rope.Match["*wire*_*", expr] ] }; EvaluateParameters: PUBLIC PROC [userData: REF, obj: CD.Object, properties: CD.PropList, isResultExpression: PROC [ROPE] RETURNS [BOOL]] RETURNS [cx: Context, resultRope: ROPE _ NIL] = { EvalExprs: PROC [exprs: ROPES, inst: BOOL] = { tempResult: ROPE _ NIL; WHILE exprs#NIL DO expr: ROPE _ exprs.first; SELECT TRUE FROM isResultExpression[expr] => { IF tempResult#NIL THEN {TerminalIO.PutF["*** Error: multiple result expressions encountered: '%g' and '%g'.\n", IO.rope[expr], IO.rope[tempResult]]; ERROR}; tempResult _ expr; }; inst AND Rope.Match["*name*_*", expr] => { expr _ Rope.Replace[expr, Rope.Find[expr, "name"], 4, "&"]; Eval[cx, expr]; Store[cx, coreInstPropsRope, NEW [Core.Properties _ CoreProperties.PutProp[GetCoreInstProps[cx], CoreOps.nameProp, NARROW [RefFromTV[SymTab.Fetch[cx, "&"].val], REF ROPE]^]]]; }; Rope.Find[s1: expr, s2: "_"] # -1 AND Rope.Index[s1: expr, s2: "_"] Eval[cx, expr]; Rope.Find[s1: expr, s2: ":"] # -1 => { atomRope: ROPE _ Rope.Substr[expr, 0, Rope.Find[s1: expr, s2: ":"]]; valueRope: ROPE _ Rope.Substr[expr, 1+Rope.Find[s1: expr, s2: ":"]]; IF inst THEN expr _ Rope.Cat["coreInstProps _ CoreProperties.PutProp[coreInstProps, $", atomRope, ", ", valueRope, "]"] ELSE expr _ Rope.Cat["coreProps _ CoreProperties.PutProp[coreProps, $", atomRope, ", ", valueRope, "]"]; Eval[cx, expr] }; inst => { previousProps: Core.Properties _ GetCoreInstProps[cx]; previousName: ROPE _ NARROW [CoreProperties.GetProp[previousProps, CoreOps.nameProp]]; IF previousName#NIL AND NOT Rope.Equal[previousName, expr] THEN { TerminalIO.PutF["*** Error in object '%g': Conflicting names '%g' and '%g' [probably two satellites].\n", IO.rope[CDDirectory.Name[obj]], IO.rope[previousName], IO.rope[expr]]; ERROR; }; Store[cx, coreInstPropsRope, NEW [Core.Properties _ CoreProperties.PutProp[previousProps, CoreOps.nameProp, expr]]]; }; ENDCASE => Store[cx, nameRope, NEW [ROPE _ expr]]; exprs _ exprs.rest; ENDLOOP; IF tempResult#NIL THEN resultRope _ tempResult; }; cx _ Copy[NARROW [userData]]; CDSequencer.CheckAborted[GetDesign[cx]]; InitLocalVariables[cx, obj]; EvalExprs[NARROW [CDProperties.GetObjectProp[obj, expressionsProp]], FALSE]; EvalExprs[NARROW [CDProperties.GetObjectProp[obj, Sinix.satellitesProp]], FALSE]; EvalExprs[NARROW [CDProperties.GetListProp[properties, expressionsProp]], TRUE]; EvalExprs[NARROW [CDProperties.GetListProp[properties, Sinix.satellitesProp]], TRUE]; }; ProcessGlobalNames: PUBLIC PROC [record: CellType, cx: Context] = { FOR names: ROPES _ GetGlobalNames[cx], names.rest WHILE names#NIL DO ProcessGlobalName[record, names.first]; ENDLOOP; }; <> Sinix.RegisterExtractProc[$SisyphExtractSchematic, ExtractSchematic]; Sinix.RegisterExtractProc[$SisyphExtractWire, ExtractWire]; Sinix.RegisterExtractProc[$SisyphExtractImport, ExtractImport]; CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $SisyphExtractSchematic]; CDProperties.PutProp[CDRects.bareRectClass, mode.extractProcProp, $SisyphExtractWire]; CDProperties.PutProp[CDTexts.rigidTextClass, mode.extractProcProp, $ExtractNull]; CDProperties.PutProp[CDTexts.flipTextClass, mode.extractProcProp, $ExtractNull]; CDProperties.PutProp[CDImports.importsClass, mode.extractProcProp, $SisyphExtractImport]; <> END. <> <> <> <<>>