DIRECTORY AMTypes USING [TV, TVEqual], AMBridge USING [SomeRefFromTV, TVForFrame, TVForReferent], AMModel USING [Context], AMModelBridge USING [ContextForFrame], CD, CDCells, CDDirectory, CDInstances, CDLayers, CDPinObjects, CDProperties, CDRects, CDSatellites, CDSymbolicObjects, CDTexts, CMosB, Core, CoreClasses, CoreOps, CoreProperties, IO, Interpreter USING [Evaluate], List, PrincOpsUtils, PW, PWPins, Rope, Sinix, Sisyph, SymTab, TerminalIO; SisyphImpl: CEDAR PROGRAM IMPORTS AMBridge, AMModelBridge, AMTypes, CDCells, CDDirectory, CDInstances, CDLayers, CDPinObjects, CDProperties, CDRects, CDSatellites, CDTexts, CMosB, CoreClasses, CoreOps, CoreProperties, Interpreter, IO, List, PrincOpsUtils, PW, PWPins, Rope, Sinix, SymTab, TerminalIO EXPORTS Sisyph SHARES CDCells, CDPinObjects, CDRects, CDTexts = BEGIN OPEN Sisyph; expressionsProp: PUBLIC ATOM _ $SisyphExpressions; designRope: PUBLIC ROPE _ "design"; iconCoreRope: PUBLIC ROPE _ "iconCore"; wireCoreRope: PUBLIC ROPE _ "wireCore"; nameRope: PUBLIC ROPE _ "name"; globalNamesRope: PUBLIC ROPE _ "globalNames"; corePropsRope: PUBLIC ROPE _ "coreProps"; iconicProp: PUBLIC ATOM _ PW.RegisterProp[$SisyphIcon, TRUE]; iconicCell: PUBLIC ATOM _ $SisyphIconicCell; iconicWire: PUBLIC ATOM _ $SisyphIconicWire; extractProcProp: PUBLIC ATOM _ PW.RegisterProp[$SisyphExtractProcProp, TRUE]; ignoreMeProp: PUBLIC ATOM _ $SisyphIgnoreMe; cachedResultProp: PUBLIC ATOM _ PW.RegisterProp[$SisyphCachedResult, FALSE, TRUE]; defaultGlobalNames: PUBLIC LIST OF ROPE _ LIST["Vdd", "Gnd"]; Cache: TYPE = REF CacheRec; CacheRec: TYPE = RECORD [ cx: Context _ NIL, cellType: CellType _ NIL, wire: Wire _ NIL, category: ATOM _ $Device ]; ExtractSchematic: PUBLIC Sinix.ExtractProc = BEGIN inheritedContext: Context _ NARROW [userData]; iconType: ATOM _ NARROW [CDProperties.GetPropFromObject[obj, iconicProp]]; cachedResult: Cache _ NARROW [CDProperties.GetPropFromObject[obj, cachedResultProp]]; cx: Context _ Copy[inheritedContext]; props: Core.Properties; InitLocalVariables[cx]; EvaluateExpressions[cx, obj, properties]; props _ GetCoreProps[cx]; IF cachedResult#NIL AND Equal[cx, cachedResult.cx] THEN { cellType _ cachedResult.cellType; wire _ cachedResult.wire; category _ cachedResult.category; TerminalIO.WriteF["Using cached result for cell %g\n", IO.rope[CDDirectory.Name[obj]]]; RETURN }; SELECT TRUE FROM iconType=NIL => { globalWires: Wires _ GlobalWires[cx]; [cellType, wire, category] _ Sinix.ExtractCell[obj, extractProcProp, properties, cx]; ProcessGlobalWires[cellType, globalWires]; IF props#NIL THEN cellType.properties _ PutCoreProps[cellType.properties, props] }; iconType=iconicCell => { cellType _ ExtractIcon[obj, cx]; wire _ NIL; category _ $Device; IF props#NIL THEN cellType.properties _ PutCoreProps[cellType.properties, props] }; iconType=iconicWire => { cellType _ NIL; wire _ ExtractWireIcon[obj, cx]; category _ $Wire; IF props#NIL THEN wire.properties _ PutCoreProps[wire.properties, props] }; ENDCASE => ERROR; cachedResult _ NEW[CacheRec _ [cx: cx, cellType: cellType, wire: wire, category: category]]; CDProperties.PutPropOnObject[obj, cachedResultProp, cachedResult]; END; ExtractWire: PUBLIC Sinix.ExtractProc = BEGIN inheritedContext: Context _ NARROW [userData]; cx: Context _ Copy[inheritedContext]; name: ROPE; props: Core.Properties; IF obj.class#CDRects.bareRectClass THEN ERROR; IF obj.layer#CMosB.comment THEN ERROR; InitLocalVariables[cx]; EvaluateExpressions[cx, obj, properties]; wire _ GetWireCore[cx]; name _ GetName[cx]; props _ GetCoreProps[cx]; IF wire=NIL THEN wire _ CoreOps.CreateWire[name: name]; Sinix.AddPinsProp[wire, PWPins.NewInstance[obj]]; IF props#NIL THEN wire.properties _ PutCoreProps[wire.properties, props]; category _ $Wire; END; ExtractSchematicByName: PUBLIC PROC [name: ROPE, cx: Context] RETURNS [CellType] = BEGIN design: CD.Design _ GetDesign[cx]; RETURN [ ExtractSchematic[ obj: CDDirectory.Fetch[design, name].object, extractProcProp: extractProcProp, userData: cx ].cellType ]; END; IsResultExpression: PUBLIC PROC [expr: ROPE] RETURNS [BOOL] = { RETURN [Rope.Match["*iconCore*_*", expr] OR Rope.Match["*wireCore*_*", expr]] }; ExtractNull: Sinix.ExtractProc = { category _ $Null; }; ExtractIcon: PROC [icon: Object, cx: Context] RETURNS [cellType: CellType] = BEGIN iconCT: CellType; ProcessEachIconPublic: CoreOps.EachWireProc = { DecoratePublic[cellType.public, wire]; }; MarkInvisibleInstances[icon]; iconCT _ Sinix.ExtractCell[icon, extractProcProp, NIL, cx].cellType; cellType _ GetIconCore[cx]; IF cellType=NIL THEN { cellType _ CoreOps.CreateCellType[class: CoreClasses.unspecifiedCellClass, public: iconCT.public, name: CDDirectory.Name[icon]]; } ELSE { cellType _ CoreClasses.CreateIdentity[cellType: cellType, name: CDDirectory.Name[icon]]; }; IF ~CheckAndDecorate[iconCT.public, cellType.public, GlobalWires[cx]] THEN { TerminalIO.WriteF["\n** Error: drawn public and result public for cell icon %g don't conform\n", IO.rope[CDDirectory.Name[icon]]]; TerminalIO.WriteF["Drawn public is:"]; CoreOps.PrintWire[iconCT.public, TerminalIO.TOS[]]; TerminalIO.WriteF["\n\nResult public is:"]; CoreOps.PrintWire[cellType.public, TerminalIO.TOS[]]; ERROR } END; ExtractWireIcon: PROC [icon: Object, cx: Context] RETURNS [result: Wire] = BEGIN iconCT: CellType; iconWire: Wire; ProcessEachIconPublic: CoreOps.EachWireProc = { DecoratePublic[result, wire]; }; MarkInvisibleInstances[icon]; iconCT _ Sinix.ExtractCell[icon, extractProcProp, NIL, cx].cellType; iconWire _ iconCT.public[0]; result _ GetWireCore[cx]; IF result=NIL THEN ERROR; IF ~CheckAndDecorate[iconWire, result] THEN { TerminalIO.WriteF["\n** Error: drawn wire and result wire for wire icon %g don't conform\n", IO.rope[CDDirectory.Name[icon]]]; TerminalIO.WriteF["Drawn wire is:"]; CoreOps.PrintWire[iconWire, TerminalIO.TOS[]]; TerminalIO.WriteF["\n\nResult wire is:"]; CoreOps.PrintWire[result, TerminalIO.TOS[]]; ERROR } END; InitLocalVariables: PUBLIC PROC [cx: Context] = BEGIN IF cx=NIL THEN ERROR; Store[cx, wireCoreRope, NEW [Wire _ NIL]]; Store[cx, iconCoreRope, NEW [CellType _ NIL]]; Store[cx, nameRope, NEW [ROPE _ NIL]]; Store[cx, corePropsRope, NEW [Core.Properties _ NIL]] END; Create: PUBLIC PROC [design: CD.Design, globalNames: LIST OF ROPE _ defaultGlobalNames] RETURNS [cx: Context] = BEGIN cx _ SymTab.Create[]; Store[cx, designRope, NEW [CD.Design _ design]]; Store[cx, globalNamesRope, NEW [LIST OF ROPE _ globalNames]]; InitLocalVariables[cx]; END; Copy: PUBLIC PROC [cx: Context] RETURNS [newCx: Context] = BEGIN CopyItem: SymTab.EachPairAction = { [] _ SymTab.Store[newCx, key, val]; quit _ FALSE; }; IF cx=NIL THEN ERROR; newCx _ SymTab.Create[]; [] _ SymTab.Pairs[cx, CopyItem]; END; Store: PUBLIC PROC [cx: Context, var: ROPE, value: REF _ NIL] = BEGIN [] _ SymTab.Store[cx, var, TVFromRef[value]]; END; Eval: PUBLIC PROC [cx: Context, expr: ROPE, cedarCx: AMModel.Context _ NIL] = TRUSTED BEGIN 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 ERROR; END; Equal: PROC [cx1, cx2: Context] RETURNS [BOOL] = { IsASubset: PROC [a, b: Context] RETURNS [result: BOOL] = { CheckExistenceInb: SymTab.EachPairAction = { found: BOOL; bVal: SymTab.Val; [found, bVal] _ SymTab.Fetch[b, key]; IF ~found THEN {result _ FALSE; RETURN}; IF ~AMTypes.TVEqual[bVal, val] THEN result _ FALSE; }; result _ TRUE; [] _ SymTab.Pairs[a, CheckExistenceInb] }; IF SymTab.GetSize[cx1]#SymTab.GetSize[cx2] THEN RETURN [FALSE]; IF IsASubset[cx1, cx2] AND IsASubset[cx2, cx1] THEN RETURN [TRUE] ELSE RETURN [FALSE] }; EvaluateExpressions: PROC [cx: Context, obj: CD.Object, propList: CD.PropList] = { objArgs: LIST OF ROPE _ NARROW[CDProperties.GetPropFromObject[obj, expressionsProp]]; instArgs: LIST OF ROPE _ NARROW[CDProperties.GetPropFromList[propList, expressionsProp]]; satArgs: LIST OF ROPE _ CDSatellites.GetSatelliteRopes[propList]; result: ROPE _ NIL; WHILE objArgs#NIL DO IF IsResultExpression[objArgs.first] THEN result _ objArgs.first ELSE Eval[cx, objArgs.first]; objArgs _ objArgs.rest ENDLOOP; WHILE instArgs#NIL DO IF IsResultExpression[instArgs.first] THEN result _ instArgs.first ELSE Eval[cx, instArgs.first]; instArgs _ instArgs.rest ENDLOOP; WHILE satArgs#NIL DO SELECT TRUE FROM Rope.Find[s1: satArgs.first, s2: "_"] # -1 => IF IsResultExpression[satArgs.first] THEN result _ satArgs.first ELSE Eval[cx, satArgs.first]; Rope.Find[s1: satArgs.first, s2: ":"] # -1 => { atomRope: ROPE _ Rope.Substr[satArgs.first, 0, Rope.Find[s1: satArgs.first, s2: ":"]]; valueRope: ROPE _ Rope.Substr[satArgs.first, 1+Rope.Find[s1: satArgs.first, s2: ":"]]; satArgs.first _ Rope.Cat["coreProps _ CoreProperties.PutProp[coreProps, $", atomRope, ", ", valueRope, "]"]; Eval[cx, satArgs.first] }; ENDCASE => Store[cx, nameRope, NEW [ROPE _ satArgs.first]]; satArgs _ satArgs.rest; ENDLOOP; IF result#NIL THEN Eval[cx, result]; }; DecoratePublic: PROC [public, iconWire: Wire] = BEGIN iconWireNames: LIST OF ROPE _ CoreOps.GetFullWireNames[iconWire]; iconWirePinList: LIST OF CD.Instance; matchingWires: Wires _ NIL; FindWireWithMatchingName: CoreOps.EachWireProc = { FOR l: LIST OF ROPE _ iconWireNames, l.rest WHILE l#NIL DO IF CoreOps.IsFullWireName[wire, l.first] THEN {matchingWires _ CONS [wire, matchingWires]; RETURN} ENDLOOP; IF iconWireNames=NIL AND CoreOps.IsFullWireName[wire, NIL] THEN matchingWires _ CONS [wire, matchingWires]; }; [] _ CoreOps.VisitWire[public, FindWireWithMatchingName]; IF matchingWires=NIL THEN ERROR; -- no public wire with this name IF matchingWires.rest#NIL THEN ERROR; -- multiple public wires with this name iconWirePinList _ NARROW [CoreProperties.GetWireProp[iconWire, Sinix.pinsProp]]; CoreProperties.PutWireProp[matchingWires.first, Sinix.pinsProp, iconWirePinList]; END; CheckWireForMatchingWire: PROC [in, wire: Wire, globalWires: Wires _ NIL] = { inNames: LIST OF ROPE _ CoreOps.GetFullWireNames[in]; FOR nl: LIST OF ROPE _ inNames, nl.rest WHILE nl#NIL DO IF FindGlobalWire[nl.first, globalWires]#NIL AND Sinix.GetPinsProp[in]=NIL THEN RETURN; ENDLOOP; FOR nl: LIST OF ROPE _ inNames, nl.rest WHILE nl#NIL DO IF FindWire[nl.first, wire]#NIL THEN RETURN; ENDLOOP; IF inNames=NIL AND FindWire[NIL, wire]#NIL THEN RETURN; IF in.size=0 THEN ERROR ELSE FOR i: NAT IN [0..in.size) DO CheckWireForMatchingWire[in[i], wire, globalWires]; ENDLOOP; }; CheckAndDecorate: PROC [dp, rp: Wire, globalWires: Wires _ NIL] RETURNS [BOOL]= { dpInterfaceGeometry: LIST OF CD.Instance; loraSize: NAT; WireToLORA: PROC [wire: Wire, stripGlobalWires: BOOL] RETURNS [lora: List.LORA] = { lora _ NIL; loraSize _ 0; FOR i: NAT IN [0..wire.size) DO name: ROPE _ CoreOps.GetShortWireName[wire.elements[i]]; IF stripGlobalWires AND FindGlobalWire[name, globalWires]#NIL THEN LOOP; lora _ CONS [wire.elements[i], lora]; loraSize _ loraSize+1 ENDLOOP; }; CompareWires: List.CompareProc = { w1: Wire _ NARROW [ref1]; w2: Wire _ NARROW [ref2]; RETURN [Rope.Compare[CoreOps.GetShortWireName[w1], CoreOps.GetShortWireName[w2]]] }; IF ~Rope.Equal[CoreOps.GetShortWireName[dp], CoreOps.GetShortWireName[rp]] THEN RETURN [FALSE]; IF dp.size > 0 THEN { dpElements: List.LORA _ List.Sort[WireToLORA[dp, FALSE], CompareWires]; rpElements: List.LORA _ List.Sort[WireToLORA[rp, TRUE], CompareWires]; IF dp.size#loraSize THEN RETURN [FALSE]; FOR i: NAT IN [0..dp.size) DO dpWire: Wire _ NARROW [dpElements.first]; rpWire: Wire _ NARROW [rpElements.first]; IF ~CheckAndDecorate[dpWire, rpWire] THEN RETURN [FALSE]; dpElements _ dpElements.rest; rpElements _ rpElements.rest ENDLOOP; }; dpInterfaceGeometry _ NARROW [CoreProperties.GetWireProp[dp, Sinix.pinsProp]]; CoreProperties.PutWireProp[rp, Sinix.pinsProp, dpInterfaceGeometry]; RETURN [TRUE]; }; MarkInvisibleInstances: PROC [obj: Object] = { cellPtr: CD.CellPtr _ NARROW[obj.specificRef]; FOR l: LIST OF CD.Instance _ cellPtr.contents, l.rest WHILE l#NIL DO IF CDProperties.GetPropFromList[l.first.properties, ignoreMeProp]#NIL THEN CDProperties.PutProp[l.first, extractProcProp, NEW[Sinix.ExtractProc _ ExtractNull]] ENDLOOP; }; ProcessGlobalWires: PROC [cellType: CellType, globalWires: Wires] = BEGIN recordCell: CoreClasses.RecordCellType _ NARROW[cellType.data]; toBeMadePublic: Wires _ NIL; toBeDeleted: Wires _ NIL; NewActual: PROC [instActual, instPublic: Wire] RETURNS [Wire] = BEGIN instActualGeometry: LIST OF CD.Instance _ NARROW [CoreProperties.GetWireProp[instActual, Sinix.wireGeometryProp]]; IF instActual.size#instPublic.size THEN ERROR; FOR i: NAT IN [0..instActual.size) DO instActual[i] _ NewActual[instActual[i], instPublic[i]]; ENDLOOP; FOR nl: LIST OF ROPE _ CoreOps.GetFullWireNames[instPublic], nl.rest WHILE nl#NIL DO globalWithInstPublicName: Wire _ FindGlobalWire[nl.first, globalWires]; internalWithInstPublicName: Wire _ FindWire[nl.first, recordCell.internal]; publicWithInstPublicName: Wire _ FindWire[nl.first, cellType.public]; IF instActualGeometry=NIL AND globalWithInstPublicName#NIL THEN { IF publicWithInstPublicName=NIL THEN { IF internalWithInstPublicName#NIL THEN { toBeMadePublic _ CONS [internalWithInstPublicName, toBeMadePublic]; toBeDeleted _ CONS[instActual, toBeDeleted]; RETURN [internalWithInstPublicName] } ELSE { toBeMadePublic _ CONS [globalWithInstPublicName, toBeMadePublic]; recordCell.internal _ GrowWire[recordCell.internal, LIST [globalWithInstPublicName]]; toBeDeleted _ CONS[instActual, toBeDeleted]; RETURN [globalWithInstPublicName] } } ELSE { toBeDeleted _ CONS[instActual, toBeDeleted]; RETURN [publicWithInstPublicName] } }; ENDLOOP; RETURN [instActual] END; CheckIfWireIsToBeMadePublic: CoreOps.EachWireProc = BEGIN FOR nl: LIST OF ROPE _ CoreOps.GetFullWireNames[wire], nl.rest WHILE nl#NIL DO IF FindGlobalWire[nl.first, globalWires]#NIL AND FindWire[nl.first, cellType.public]=NIL THEN {toBeMadePublic _ CONS [wire, toBeMadePublic]; RETURN} ENDLOOP; END; FOR i: NAT IN [0..recordCell.size) DO inst: CoreClasses.CellInstance _ recordCell.instances[i]; inst.actual _ NewActual[inst.actual, inst.type.public]; ENDLOOP; FOR l: Wires _ toBeDeleted, l.rest WHILE l#NIL DO recordCell.internal _ DeleteWire[l.first, recordCell.internal]; ENDLOOP; [] _ CoreOps.VisitWire[recordCell.internal, CheckIfWireIsToBeMadePublic]; toBeMadePublic _ RemoveDuplicates[toBeMadePublic]; FOR w: Wires _ toBeMadePublic, w.rest WHILE w#NIL DO CoreProperties.PutWireProp[w.first, Sinix.pinsProp, NIL] ENDLOOP; cellType.public _ GrowWire[cellType.public, toBeMadePublic]; END; RemoveDuplicates: PROC [wires: Wires] RETURNS [result: Wires] = BEGIN result _ NIL; FOR w: Wires _ wires, w.rest WHILE w#NIL DO found: BOOL _ FALSE; FOR r: Wires _ result, r.rest WHILE r#NIL DO IF w.first=r.first THEN {found _ TRUE; EXIT} ENDLOOP; IF ~found THEN result _ CONS [w.first, result]; ENDLOOP; END; DeleteWire: PROC [victim, from: Wire] RETURNS [result: Wire] = BEGIN survivors: Wires _ NIL; IF from=victim THEN RETURN[NIL]; IF from.size=0 THEN RETURN [from]; FOR i: NAT DECREASING IN [0..from.size) DO subResult: Wire _ DeleteWire[victim, from[i]]; IF subResult#NIL THEN survivors _ CONS [subResult, survivors]; ENDLOOP; result _ CoreOps.CreateWire[elements: survivors, props: from.properties]; END; FindGlobalWire: PROC [name: ROPE, globalWires: Wires] RETURNS [Wire _ NIL] = BEGIN FOR l: Wires _ globalWires, l.rest WHILE l#NIL DO IF Rope.Equal[name, CoreOps.GetShortWireName[l.first]] THEN RETURN [l.first]; ENDLOOP; END; FindWire: PROC [name: ROPE, w: Wire] RETURNS [result: Wire _ NIL] = BEGIN ForEachWire: CoreOps.EachWireProc = { IF CoreOps.IsFullWireName[wire, name] THEN {result _ wire; quit _ TRUE} }; [] _ CoreOps.VisitWire[w, ForEachWire] END; GlobalWires: PROC [cx: Context] RETURNS [wires: Wires _ NIL] = BEGIN globalNames: LIST OF ROPE _ GetGlobalNames[cx]; FOR names: LIST OF ROPE _ globalNames, names.rest WHILE names#NIL DO wires _ CONS[CoreOps.CreateWire[name: names.first], wires]; ENDLOOP; END; GrowWire: PROC [wire: Wire, newWires: Wires] RETURNS [result: Wire] = BEGIN resultSize: NAT _ wire.size; FOR w: Wires _ newWires, w.rest WHILE w#NIL DO resultSize _ resultSize+1 ENDLOOP; result _ CoreOps.CreateWires[resultSize, CoreOps.GetShortWireName[wire], wire.properties]; FOR i: NAT IN [0..wire.size) DO result[i] _ wire[i] ENDLOOP; FOR i: NAT IN [wire.size..resultSize) DO result[i] _ newWires.first; newWires _ newWires.rest; ENDLOOP; result _ CoreOps.SetFullWireNames[result]; END; TouchRect: Sinix.TouchProc = { IF instance2.ob.class#CDRects.bareRectClass THEN RETURN [Sinix.TouchRectObject[instance2, CDInstances.InstRectO[instance1], instance1.ob.layer, compareLayers]]; IF ~SilTouchRect[CDInstances.InstRectO[instance1], CDInstances.InstRectO[instance2]] THEN RETURN; RETURN [~compareLayers OR CDLayers.AbstractToPaint[instance1.ob.layer]=CDLayers.AbstractToPaint[instance2.ob.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: 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 }; GetIconCore: PROC [cx: Context] RETURNS [Core.CellType] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, iconCoreRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Core.CellType]^] ELSE ERROR }; GetWireCore: PROC [cx: Context] RETURNS [Core.Wire] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, wireCoreRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF Core.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 }; GetGlobalNames: PROC [cx: Context] RETURNS [LIST OF ROPE] = { found: BOOL; ref: SymTab.Val; [found, ref] _ SymTab.Fetch[cx, globalNamesRope]; IF found THEN RETURN [NARROW [RefFromTV[ref], REF LIST OF ROPE]^] ELSE ERROR }; GetDesign: 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 }; 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]]; }; 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]; }; CDProperties.PutProp[CDCells.cellClass, extractProcProp, NEW [Sinix.ExtractProc _ ExtractSchematic]]; CDProperties.PutProp[CDCells.cellClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchCell]]; CDProperties.PutProp[CDPinObjects.pinObjectsClass, extractProcProp, NEW [Sinix.ExtractProc _ Sinix.ExtractPin]]; CDProperties.PutProp[CDPinObjects.pinObjectsClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchPin]]; CDProperties.PutProp[CDRects.bareRectClass, extractProcProp, NEW [Sinix.ExtractProc _ ExtractWire]]; CDProperties.PutProp[CDRects.bareRectClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ TouchRect]]; CDProperties.PutProp[CDTexts.textClass, extractProcProp, NEW [Sinix.ExtractProc _ ExtractNull]]; END. #ΌSisyphImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Created by Pradeep Sindhu and Bertrand Serlet, December 3, 1985 0:03:15 am PST Pradeep Sindhu February 4, 1986 4:06:39 pm PST Barth, January 13, 1986 3:35:49 pm PST Design A CD instance is represented by the tuple , where obj is the object corresponding to the instance, and propList is the property list of the instance. An instance may have arguments that control the result of the extraction. These arguments may appear in any one of three places: (1) as "satellites" (or text objects) attatched to the instance, (2) as text inside the instance property $SisyphArguments, or (3) as text inside the object property $SisyphArguments. Extraction begins at the top-level procedure ExtractSchematic. Extract schematic first evaluates the arguments of the object passed to it, and then calls Sinix.Extract, ExtractIcon, or ExtractWireIcon, depending on the Sisyph type of the object passed to it. Evaluation proceeds in an environment consisiting of a Sisyph context and an interpreter context. The Sisyph context is simply a SymTab containing pairs, while the interpreter context is the local frame of the caller of Eval. The evaluation always looks first at the Sisyph context and then at the interpreter context. Note that the interpreter context includes in it a definition of all variables that are visible (statically) from within Eval, and all global frames and interface records currently loaded in the Cedar world. During extraction certain global names are treated specially. When a wire with its full name equal to one of the global names is encountered, the wire is promoted to be a public of the cellType in which it lies. When this cellType, say A, is used within another cellType, say B, the same global name also gets promoted to be a public of B. This promotion continues till a cellType is encountered in which a piece of geometry with the global name as its name touches the interest rect of the object corresponding to the cellType. The global names are kept as a list of rope in the Sisyph variable globalNames. Global wires are restricted to be atomic. The following two invariants are checked when constructing a CellType C for an Iconic Cell IC. (1) For each symbolic object (pin) inside IC there must be a wire in C.public one of whose full names is the same as the symbolic object's name. (2) C.public must satisfy the property P(w): the wire w has a symbolic object (pin) in IC whose name is the same as one of w's full names, or each of w's sons satisfies P. The following two invariants are checked when constructing a wire W for an Iconic Wire IW. (1) For each symbolic object (pin) inside IW there must be a wire in W one of whose full names is the same as the symbolic object's name. (2) W must satisfy the property P(w): the wire w has a symbolic object (pin) in IC whose name is the same as one of w's full names, or each of w's sons satisfies P. Extraction This is the top-level extract proc. It evaluates the arguments to the schematic and then calls either ExtractIcon or Sinix.ExtractCell to do its job. This proc is called for cell icons. If a core definition is found then it is returned, otherwise a core cell of class Unspecified is returned. Note that CDSymbolicObjects.EnumerateSymbolicObs enumerates all instances not just the ones on the interest rect, so pins internal to the icon will also count. OldExtractIcon: PROC [icon: Object, cx: Context] RETURNS [cellType: CellType] = BEGIN iconPins: LIST OF CD.Instance _ NIL; ProcessEachSymbInst: CDSymbolicObjects.InstEnumerator = { OldDecoratePublic[cellType.public, inst]; iconPins _ CONS[inst, iconPins]; }; cellType _ GetIconCore[cx]; IF cellType=NIL THEN { wires: Wires _ NIL; CreateWireForEachSymbInst: CDSymbolicObjects.InstEnumerator = { name: ROPE _ CDSymbolicObjects.GetName[inst]; FOR wl: Wires _ wires, wl.rest WHILE wl#NIL DO IF CoreOps.IsFullWireName[wl.first, name] THEN RETURN; ENDLOOP; wires _ CONS [CoreOps.CreateWire[name: name], wires]; }; [] _ CDSymbolicObjects.EnumerateSymbolicObs[icon, CreateWireForEachSymbInst]; cellType _ CoreOps.CreateCellType[class: CoreClasses.unspecifiedCellClass, public: CoreOps.CreateWire[wires], name: CDDirectory.Name[icon]]; } ELSE { cellType _ CoreClasses.CreateIdentity[cellType: cellType, name: CDDirectory.Name[icon]]; }; [] _ CDSymbolicObjects.EnumerateSymbolicObs[icon, ProcessEachSymbInst]; CheckWireForMatchingSymbInst[cellType.public, iconPins, GlobalWires[cx]]; END; This proc is called for cell icons. If a core definition is found then it is returned, otherwise a core cell of class Unspecified is returned. Compute core for the schematic [] _ CoreOps.VisitWire[iconCT.public, ProcessEachIconPublic]; CheckWireForMatchingWire[cellType.public, iconCT.public, GlobalWires[cx]]; This proc is called for wire icons. If a core definition is found it is returned, otherwise an error is signalled. As for cell icons, pins provide the attatchment points to the wire. Note that CDSymbolicObjects.EnumerateSymbolicObs enumerates all instances not just the ones on the interest rect, so pins internal to the icon also count. OldExtractWireIcon: PROC [icon: Object, cx: Context] RETURNS [wire: Wire] = BEGIN iconPins: LIST OF CD.Instance _ NIL; ProcessEachSymbInst: CDSymbolicObjects.InstEnumerator = { OldDecoratePublic[wire, inst]; iconPins _ CONS[inst, iconPins]; }; wire _ GetWireCore[cx]; IF wire=NIL THEN ERROR; wire _ CoreOps.SetFullWireNames[wire]; [] _ CDSymbolicObjects.EnumerateSymbolicObs[icon, ProcessEachSymbInst]; CheckWireForMatchingSymbInst[wire, iconPins]; END; This proc is called for wire icons. If a core definition is found it is returned, otherwise an error is signalled. As for cell icons, pins provide the attatchment points to the wire. CoreProperties.PutWireProp[iconWire, $CoreFullWireName, NIL]; iconWire _ CoreOps.SetFullWireNames[iconWire]; result _ CoreOps.SetFullWireNames[result]; [] _ CoreOps.VisitWire[iconWire, ProcessEachIconPublic]; CheckWireForMatchingWire[result, iconWire]; Context Handling Procedures Private Procedures The order of evaluation is: (1) expressions specified in expressionsProp property of object; (2) arguments specified in expressionsProp property of instance; (3) arguments specified in satellites of instance. Thus satellites take precedence over instance property exprs, which take precedence over object property exprs. The evaluation is performed in two passes: the second pass handles expressions of the form "wireCore _" and "iconCore _", while the first pass handles all others. When evaluating satellite exprs, an expression containing "_" is evaluated, an expression containing a ":" is assumed to be a property, while all other expressions are assumed to be a name. Finds the wire in public that has the same full name as inst and puts inst as the pinsProp on that wire. There must be exactly one such wire, or there is an error. OldDecoratePublic: PROC [public: Wire, inst: CD.Instance] = BEGIN pinName: ROPE _ CDSymbolicObjects.GetName[inst]; matchingWires: Wires _ NIL; FindWireWithMatchingName: CoreOps.EachWireProc = { IF CoreOps.IsFullWireName[wire, pinName] THEN matchingWires _ CONS [wire, matchingWires]; }; [] _ CoreOps.VisitWire[public, FindWireWithMatchingName]; IF matchingWires=NIL THEN ERROR; -- no public wire with this name IF matchingWires.rest#NIL THEN ERROR; -- multiple public wires with this name Sinix.AddPinPropOnWire[matchingWires.first, inst]; END; Finds the wire in public that has the same full name as iconWire and puts the pinsProp of iconWire onto the pinsProp of the wire found. There must be exactly one such wire, or there is an error. CheckWireForMatchingSymbInst: PROC [wire: Wire, symbInstList: LIST OF CD.Instance, globalWires: Wires _ NIL] = { If wire is promotable to public then a matching symbinst isn't necessary FOR nl: LIST OF ROPE _ CoreOps.GetFullWireNames[wire], nl.rest WHILE nl#NIL DO IF FindGlobalWire[nl.first, globalWires]#NIL AND CoreProperties.GetWireProp[wire, Sinix.pinsProp]=NIL THEN RETURN; ENDLOOP; FOR l: LIST OF CD.Instance _ symbInstList, l.rest WHILE l#NIL DO IF CoreOps.IsFullWireName[wire, CDSymbolicObjects.GetName[l.first]] THEN RETURN; ENDLOOP; IF wire.size=0 THEN ERROR ELSE FOR i: NAT IN [0..wire.size) DO CheckWireForMatchingSymbInst[wire[i], symbInstList, globalWires]; ENDLOOP; }; If in is promotable to public then a matching symbinst isn't necessary This proc causes global wires to be promoted to the public of cellType. The implementation is tricky, so don't mess with it unless you know what you're doing. For each instance check if any part of its actual should be promoted Delete toBeDeleted wires from the internal Check if any part of the internal of cellType should be promoted Remove Sinix.pinsProp from all wires to be made public Returns the wire in globalWires that has name as a short name; Note that this assumes global wires are atomic. Returns the wire contained in w that has name as one of its full names. Grow wire by adding in the wires from newWires to the top level of wire. Module Initialization Κ*˜šœ™Jšœ Οmœ1™JšœA™AJšžœ™—Jšœ™—J˜š’œžœ'žœ˜MJšœ žœžœžœ ˜5J™Fš žœžœžœžœžœžœž˜7Jš žœ'žœžœžœžœžœ˜WJšžœ˜—š žœžœžœžœžœžœž˜7Jšžœžœžœžœ˜,Jšžœ˜—Jšžœ žœžœ žœžœžœžœ˜7šžœ žœžœžœžœžœžœž˜:Jšœ3˜3Jšžœ˜—Jšœ˜—J˜š Πbnœžœ%žœžœžœ˜QKšœžœžœžœ ˜)Kšœ žœ˜š ’ œžœ žœžœ žœ˜SKšœžœ˜šžœžœžœž˜Kšœžœ.˜8Kš žœžœ#žœžœžœ˜HKšœžœ0˜;Kšžœ˜—K˜—š‘ œ˜"Kšœ žœ˜Kšœ žœ˜JšžœK˜QK˜—šžœH˜JKšžœžœžœ˜—šžœ žœ˜Kšœžœžœ˜GKšœžœžœ˜FK˜Kšžœžœžœžœ˜(šžœžœžœž˜Kšœžœ˜)Kšœžœ˜)Kšžœ#žœžœžœ˜9K˜K˜Kšžœ˜—K˜—Kšœžœ2˜NKšœD˜DKšžœžœ˜K˜K˜—J˜š’œžœ˜.Jšœ žœ žœ˜.J˜š žœžœžœžœ%žœžœž˜Dšžœ@ž˜EJšžœ0žœ"˜Y—Jšžœ˜—J˜—J˜J™Ÿš’œžœ,ž˜IJšœ)žœ˜?Jšœžœ˜Jšœžœ˜š’ œžœ žœ ž˜EJš œžœžœžœ žœB˜rJ˜Jšžœ!žœžœ˜.šžœžœžœž˜%Jšœ8˜8Jšžœ˜—J˜š žœžœžœžœ1žœžœž˜TJšœG˜GJšœK˜KJšœE˜EJ˜š žœžœžœžœžœ˜Ašžœž˜šžœ˜šžœž˜!šžœ˜Jšœžœ.˜CJšœžœ˜,Jšžœ˜#Jšœ˜—šžœ˜Jšœžœ,˜AJšœ4žœ˜UJšœžœ˜,Jšžœ˜!Jšœ˜——J˜—šžœ˜Jšœžœ˜,Jšžœ˜!J˜——Jšœ˜—Jšžœ˜—Jšžœ ˜Jšžœ˜—šœ4ž˜9š žœžœžœžœ+žœžœž˜Nšžœ'žœžœ%ž˜XJšžœžœžœ˜;—Jšžœ˜—Jšžœ˜—J˜J™Dšžœžœžœž˜%J˜9Jšœ7˜7Jšžœ˜—J™*šžœ žœžœž˜1J˜?Jšžœ˜—J™@JšœI˜IJ˜2J™6šžœ#žœžœž˜4Jšœ4žœ˜8Jšžœ˜—J˜Jšžœ˜—JšœI˜IJšžœ˜—K˜J™nš ’œžœžœžœ žœž˜Ršžœ žœžœž˜1Jšžœ5žœžœ ˜MJšžœ˜—Jšžœ˜—J˜J™Gš ’œžœžœ žœžœž˜Iš‘ œ˜%Jšžœ$žœžœ˜GJšœ˜—Jšœ&˜&Jšžœ˜—J˜š ’ œžœžœžœž˜DJšœ žœžœžœ˜/š žœžœžœžœžœžœž˜DJšœžœ/˜;Jšžœ˜—Jšžœ˜—J™J™Hš’œžœžœž˜KJšœ žœ ˜šžœžœžœž˜.Jšœ˜Jšžœ˜—JšœZ˜ZJš žœžœžœžœžœ˜<šžœžœžœž˜(Jšœ5˜5Jšžœ˜—J˜*Jšžœ˜—K˜šœ˜Jšžœ*žœžœi˜ JšžœSžœžœ˜aJšžœžœ\˜uJšœ˜—J˜š ’ œžœ žœžœžœžœ˜>š ’ œžœžœ žœžœžœ˜QJšžœžœ˜/J˜—J˜š ’œžœžœ žœžœžœ˜Nšžœžœžœž˜AJšœžœžœ˜9—J˜—J˜Jšžœ)žœ%žœ(žœ%˜©Jšœ˜—K˜š’ œžœžœ˜>Kšœžœ˜ Kšœ˜Kšœ/˜/šžœ˜Kšžœžœžœžœ˜;Kšžœž˜ —K˜—K˜š’ œžœžœ˜;Kšœžœ˜ Kšœ˜Kšœ.˜.šžœ˜Kšžœžœžœžœ˜9Kšžœž˜ —K˜—K˜š’ œžœžœ˜7Kšœžœ˜ Kšœ˜Kšœ.˜.šžœ˜Kšžœžœžœžœ ˜5Kšžœž˜ —K˜—K˜š’œžœžœžœ˜.Kšœžœ˜ Kšœ˜Kšœ*˜*šžœ˜Kš žœžœžœžœžœ˜0Kšžœž˜ —K˜—K˜š ’œžœžœžœžœžœ˜=Kšœžœ˜ Kšœ˜Kšœ1˜1šžœ˜Kšžœžœžœžœžœžœžœ˜8Kšžœž˜ —K˜—K˜š’ œžœžœžœ ˜5Kšœžœ˜ Kšœ˜Kšœ,˜,šžœ˜Kš žœžœžœžœžœ ˜5Kšžœž˜ —K˜K˜—š ’ œžœžœžœžœ˜+Kš žœžœžœžœžœ˜Kš žœžœžœžœžœ˜(Kšžœžœ˜.Kšœ˜—J˜š ’ œžœžœžœ žœžœ˜;Kšžœ˜%Kšœ˜—K˜š’ œžœžœ˜Sš ’œžœžœžœžœ˜,K˜-K˜—K˜ K˜(Kšœ˜—K˜—™Kšœ9žœ)˜eKšœ=žœ&˜fKšœDžœ)˜pKšœHžœ%˜pKšœ=žœ$˜dKšœAžœ ˜dšœ9žœ$˜`K˜—Jšžœ˜——…—NŽt