DIRECTORY Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, Commander, Core, CoreClasses, CoreCreate, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph, TerminalIO; PWCoreImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph, TerminalIO EXPORTS PWCore SHARES CDCells, CDDirectory = BEGIN OPEN PWCore; VisitAtomicPairs: PROC [wire1, wire2: Wire, eachPair: PROC [Wire, Wire]] = { VisitInternal: PROC [wire1, wire2: Wire] = { IF wire1.size#wire2.size THEN ERROR; IF wire1.size=0 THEN eachPair[wire1, wire2] ELSE FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP; }; IF wire1.size#wire2.size THEN ERROR; FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP; }; Signal: PUBLIC SIGNAL [cellType: CellType] = CODE; Error: PUBLIC ERROR [type: ATOM, message: ROPE, cellType: CellType] = CODE; PinsCorrespondingToSeveralPublics: PUBLIC SIGNAL [cellType: CellType, obj: Object, publics: Wires, geometry: CoreGeometry.Instances] = CODE; NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE _ NIL] = CODE; layoutAtomsTable: HashTable.Table _ HashTable.Create[]; LayoutAtomData: TYPE = REF LayoutAtomDataRec; LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc, attributesProc: AttributesProc _ NIL]; RegisterLayoutAtom: PUBLIC PROC [layoutAtom: ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] RETURNS [sameAtom: ATOM] = { sameAtom _ layoutAtom; IF ~HashTable.Store[layoutAtomsTable, layoutAtom, NEW [LayoutAtomDataRec _ [layoutProc: layoutProc, decorateProc: decorateProc, attributesProc: attributesProc]]] THEN TerminalIO.PutF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]; }; GetLayoutAtomData: PROC [layoutAtom: ATOM] RETURNS [layoutAtomData: LayoutAtomData] = { layoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; IF layoutAtomData#NIL THEN RETURN; CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"]; layoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; }; GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc _ NIL, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] = { layoutAtomData: LayoutAtomData _ GetLayoutAtomData[layoutAtom]; IF layoutAtomData=NIL THEN RETURN; layoutProc _ layoutAtomData.layoutProc; decorateProc _ layoutAtomData.decorateProc; attributesProc _ layoutAtomData.attributesProc; }; layoutAtomProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$Layout]; GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOM _ NIL] = { layoutAtom _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]]; IF layoutAtom#NIL THEN RETURN; layoutAtom _ NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]; }; FakeExtract: Sinix.ExtractProc = {result _ CDProperties.GetObjectProp[obj, $PWCoreCellType]}; SmashPins: PROC [wire: Wire] = {CoreGeometry.PutPins[extractMode.decoration, wire, NIL]}; CopyDecorations: PROC [to, from: CellType, obj: Object] = { CopyPins: PROC [toWire, fromWire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, fromWire] THEN SIGNAL NoPinsOnAtomicPublic[from, obj, fromWire, CoreOps.GetFullWireName[from.public, fromWire]]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, toWire, fromWire]; }; CoreOps.VisitRootAtomics[to.public, SmashPins]; VisitAtomicPairs[to.public, from.public, CopyPins]; }; layoutProp: PRIVATE ATOM _ CoreProperties.RegisterProperty[$PWCoreLayout]; Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutProp]]; IF obj#NIL THEN RETURN; BEGIN layoutAtom: ATOM _ GetLayoutAtom[cellType]; layoutAtomData: LayoutAtomData; layoutData: LayoutData; layoutCellType: CellType; IF layoutAtom=NIL THEN IF cellType.class.recast=NIL THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType] ELSE { recasted: CellType = CoreOps.Recast[cellType]; obj _ Layout[recasted]; CopyDecorations[cellType, recasted, obj]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; RETURN; }; layoutAtomData _ GetLayoutAtomData[layoutAtom]; IF layoutAtomData=NIL THEN ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType]; IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType]; obj _ layoutAtomData.layoutProc[cellType]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; layoutData _ NEW [LayoutDataRec _ [cellType: cellType, obj: obj, mode: extractMode]]; layoutCellType _ CoreOps.CreateCellType[class: layoutClass, public: CoreOps.CopyWire[cellType.public], data: layoutData]; IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; CopyDecorations[layoutCellType, cellType, obj]; CoreGeometry.PutObject[extractMode.decoration, layoutCellType, obj]; obj _ PWObjects.CreateIndirect[obj]; CDProperties.PutObjectProp[obj, $PWCoreCellType, layoutCellType]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]; IF Sinix.Extract[obj, extractMode].result#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; IF CorrespondingCellType[obj]#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; END; }; FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = { cellType _ NARROW [Sinix.Extract[obj, extractMode].result]; SetLayoutAndDecoration[cellType, obj]; }; extractMode: PUBLIC Sinix.Mode _ SinixOps.GetExtractMode[$cmosB]; maskSuffix: PUBLIC ROPE _ ".mask"; GetAndAddSuffix: PROC [source: CD.Design, name: ROPE] RETURNS [obj: Object] = { obj _ PW.Get[source, IO.PutR[IO.rope[name], IO.rope[maskSuffix]]]; }; Get: LayoutProc = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; obj _ GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]; }; GetAndFlatten: LayoutProc = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; obj _ PW.Flatten[GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]]; }; Value: LayoutProc = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]]; }; DecorateValue: PUBLIC DecorateProc = { extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: HashTable.Table _ HashTable.Create[extractedCT.public.size]; FindInExtractedPublic: CoreOps.EachWireProc = { FOR names: LIST OF ROPE _ CoreOps.GetFullWireNames[cellType.public, wire], names.rest WHILE names#NIL DO name: ROPE _ names.first; extractedWire: Wire _ CoreOps.FindWire[extractedCT.public, name]; previousSourceWire: Wire _ NARROW [HashTable.Fetch[extractedToSource, extractedWire].value]; IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP; IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], CoreGeometry.GetPins[extractMode.decoration, extractedWire]]; IF NOT CoreGeometry.HasPins[extractMode.decoration, extractedWire] THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, wire, extractedWire]; [] _ HashTable.Store[extractedToSource, extractedWire, wire]; ENDLOOP; }; CoreOps.VisitRootAtomics[cellType.public, SmashPins]; [] _ CoreOps.VisitWire[cellType.public, FindInExtractedPublic]; }; AttributeX: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInX]}; AttributeY: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInY]}; AbutX: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT DECREASING IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListX[subObjects]; }; AbutY: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT DECREASING IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListY[subObjects]; }; ReverseAbutX: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListX[subObjects]; }; ReverseAbutY: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListY[subObjects]; }; ArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutX]; obj _ Layout[recasted]; }; ArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutY]; obj _ Layout[recasted]; }; ReverseArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutX]; obj _ Layout[recasted]; }; ReverseArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutY]; obj _ Layout[recasted]; }; Recast: LayoutProc = { obj _ Layout[CoreOps.Recast[cellType]]; }; DecorateAbut: PUBLIC PROC [cellType: CellType, obj: Object, sort: SortProc] = { InsertInst: CDCells.InstEnumerator = { IF inst.trans.orient#original THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable to objects expanding into cells without rotation", cellType]; sorted _ CONS [inst, sorted]; }; CompareInst: GList.CompareProc = { inst1: CD.Instance = NARROW [ref1]; inst2: CD.Instance = NARROW [ref2]; RETURN [IF sort[ObjectBase[inst1.ob, inst1.trans], ObjectBase[inst2.ob, inst2.trans]] THEN less ELSE greater]; }; sorted: LIST OF CD.Instance; recordData: CoreClasses.RecordCellType _ NARROW [cellType.data]; WHILE obj.class#CDCells.pCellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; [] _ CDCells.EnumerateInstances[obj, InsertInst]; sorted _ NARROW [GList.Sort[sorted, CompareInst]]; FOR i: NAT IN [0 .. recordData.size) DO CoreGeometry.PutTrans[extractMode.decoration, recordData[i], sorted.first.trans]; sorted _ sorted.rest; ENDLOOP; IF sorted#NIL THEN ERROR Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; DecorateAbutX: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, SortInX]; }; DecorateAbutY: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, SortInY]; }; DecorateReverseAbutX: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, ReverseSortInX]; }; DecorateReverseAbutY: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, ReverseSortInY]; }; DecorateRecasted: PUBLIC DecorateProc = { CopyDecorations[cellType, CoreOps.Recast[cellType], obj]; }; Rotated: PROC [cellType: CellType] RETURNS [rotatedCT: CellType] = { rct: CoreClasses.RecordCellType; IF cellType.class#CoreClasses.recordCellClass THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rct _ NARROW [cellType.data]; IF rct.size#1 THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rotatedCT _ rct[0].type; }; FlipX: LayoutProc = {obj _ PW.FlipX[Layout[Rotated[cellType]]]}; FlipY: LayoutProc = {obj _ PW.FlipY[Layout[Rotated[cellType]]]}; Rot90: LayoutProc = {obj _ PW.Rot90[Layout[Rotated[cellType]]]}; Rot180: LayoutProc = {obj _ PW.Rot180[Layout[Rotated[cellType]]]}; Rot270: LayoutProc = {obj _ PW.Rot270[Layout[Rotated[cellType]]]}; DecorateRotated: PUBLIC DecorateProc = { rotatedCT: CellType = Rotated[cellType]; trans: CoreGeometry.Transformation; DecorateUniqueInst: CDCells.InstEnumerator = {trans _ inst.trans}; WHILE obj.class#CDCells.pCellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; IF CDCells.CountInstances[obj]#1 THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType]; [] _ CDCells.EnumerateInstances[obj, DecorateUniqueInst]; CoreGeometry.PutTrans[extractMode.decoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; SortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.xpos2.x]}; ReverseSortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y>pos2.y]}; ObjectBase: PROC [obj: CD.Object, trans: CoreGeometry.Transformation] RETURNS [pos: CD.Position] = { pos _ CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[obj], trans]]; }; InstanceBase: PROC [decoration: CoreGeometry.Decoration, cellType: CellType, trans: CoreGeometry.Transformation] RETURNS [pos: CD.Position] = { pos _ ObjectBase[CoreGeometry.GetObject[decoration, cellType], trans]; }; SortInstances: PUBLIC PROC [decoration: CoreGeometry.Decoration, cellType: CellType, sort: SortProc] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; FOR i: NAT IN [0 .. data.size-1) DO FOR j: NAT IN (i .. data.size) DO IF ~sort[ InstanceBase[decoration, data[i].type, CoreGeometry.GetTrans[decoration, data[i]]], InstanceBase[decoration, data[j].type, CoreGeometry.GetTrans[decoration, data[j]]] ] THEN { w: CoreClasses.CellInstance _ data[i]; data[i] _ data[j]; data[j] _ w; }; ENDLOOP; ENDLOOP; }; DecorateFlatten: PUBLIC PROC [cellType: CellType, obj: Object, sort: PROC [CD.Position, CD.Position] RETURNS [BOOL]] = { ir: CD.Rect _ CD.InterestRect[obj]; extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: HashTable.Table _ HashTable.Create[CoreOps.WireBits[extractedCT.public]]; -- table of publics of extracted to publics of source extractedCTData: CoreClasses.RecordCellType _ NARROW [extractedCT.data]; cellTypeData: CoreClasses.RecordCellType _ NARROW [cellType.data]; positionnedInstances: LIST OF PositionnedInstance; positionnedWires: LIST OF PositionnedWire; DecorateActual: PROC [bindings: HashTable.Table, sourceActual, deepPublic: Wire] = { wireBind: CoreFlat.FlatWire _ NARROW [HashTable.Fetch[bindings, deepPublic].value]; -- bindings=NIL would mean that extractedCT is a leaf, which is impossible extractedActual: Wire; wire: Wire; FOR i: NAT IN [0 .. sourceActual.size) DO DecorateActual[bindings, sourceActual[i], deepPublic[i]] ENDLOOP; IF deepPublic.size#0 THEN RETURN; IF wireBind=NIL THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- something is really wrong! IF wireBind.flatCell#[] THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- a deep internal wire extractedActual _ wireBind.wire; IF sourceActual.size#extractedActual.size THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; wire _ NARROW [HashTable.Fetch[extractedToSource, extractedActual].value]; IF wire=sourceActual THEN RETURN; IF wire#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [wire, sourceActual], CoreGeometry.GetPins[extractMode.decoration, extractedActual]]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, sourceActual, extractedActual]; [] _ HashTable.Insert[extractedToSource, extractedActual, sourceActual]; }; [positionnedInstances, positionnedWires] _ GetPositionnedInstances[extractedCT, sort]; IF cellTypeData.size#GList.Length[positionnedInstances] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between extracted layout (%g instances) and source description (%g instances)", IO.int[GList.Length[positionnedInstances]], IO.int[cellTypeData.size]], cellType]; CoreOps.VisitRootAtomics[cellType.public, SmashPins]; FOR i: NAT IN [0 .. cellTypeData.size) DO positionnedInstance: PositionnedInstance = positionnedInstances.first; cell: CellType = positionnedInstance.cell; sourceCellType: CellType = NARROW [cell.data, LayoutData].cellType; IF Layout[cellTypeData[i].type]#Layout[sourceCellType] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between the %gth instance of the extracted layout and the %gth instance of the source description: cellTypes are different", IO.int[i], IO.int[i]], cellType]; CoreGeometry.PutTrans[extractMode.decoration, cellTypeData[i], positionnedInstance.trans]; IF ~ CoreOps.CorrectConform[cellTypeData[i].actual, cell.public] THEN ERROR Error[$InternalBug, "Call Implementor!", cellType]; FOR j: NAT IN [0 .. cell.public.size) DO DecorateActual[positionnedInstance.bindings, cellTypeData[i].actual[j], cell.public[j]]; ENDLOOP; positionnedInstances _ positionnedInstances.rest; ENDLOOP; WHILE positionnedWires#NIL DO AddExtraPins: CoreGeometry.EachInstanceProc = { IF CoreGeometry.TransfedNotAtEdge[positionnedWire.trans, ir, instance] THEN RETURN; CoreGeometry.PutPins[ extractMode.decoration, source, CONS [CoreGeometry.Transform[positionnedWire.trans, instance], CoreGeometry.GetPins[extractMode.decoration, source]] ]; }; positionnedWire: PositionnedWire = positionnedWires.first; wire: Wire = positionnedWire.wire; flatWire: CoreFlat.FlatWireRec = positionnedWire.flatWire; name: ROPE = CoreOps.GetShortWireName[wire]; source: Wire _ NARROW [HashTable.Fetch[extractedToSource, flatWire.wire].value]; IF flatWire.flatCell#[] THEN ERROR Error[$InternalBug, "Call implementor!", cellType]; -- not yet implemented if it is not part of the internal of extractedCT IF source=NIL THEN source _ CoreOps.FindWire[cellTypeData.internal, name]; IF source=NIL THEN SIGNAL Signal[cellType]; IF source#NIL AND CoreOps.RecursiveMember[cellType.public, source] THEN [] _ CoreGeometry.EnumerateGeometry[extractMode.decoration, wire, AddExtraPins]; positionnedWires _ positionnedWires.rest; ENDLOOP; }; PositionnedInstance: TYPE = REF PositionnedInstanceRec; PositionnedInstanceRec: TYPE = RECORD [ cell: CellType, -- flat CT (of class layoutClass) flatCell: CoreFlat.FlatCellTypeRec, bindings: CoreFlat.Bindings, -- [public of cellType -> CoreFlat.WireBind] trans: CoreGeometry.Transformation ]; PositionnedWire: TYPE = REF PositionnedWireRec; PositionnedWireRec: TYPE = RECORD [ wire: Wire, flatWire: CoreFlat.FlatWireRec, trans: CoreGeometry.Transformation ]; GetPositionnedInstances: PROC [extractedCT: CellType, sort: SortProc] RETURNS [positionnedInstances: LIST OF PositionnedInstance _ NIL, positionnedWires: LIST OF PositionnedWire _ NIL] = { Leaf: CoreGeometry.LeafProc = {RETURN [cellType.class=layoutClass]}; EachFlatWire: CoreGeometry.EachFlatWireProc = { positionnedWires _ CONS [ NEW [PositionnedWireRec _ [wire: wire, flatWire: flatWire, trans: trans]], positionnedWires]; }; EachFlatCell: CoreGeometry.EachFlatCellProc = { positionnedInstances _ CONS [ NEW [PositionnedInstanceRec _ [ cell: cell, flatCell: flatCell, bindings: bindings, trans: trans ]], positionnedInstances]; }; Compare: GList.CompareProc = { pi1: PositionnedInstance = NARROW [ref1]; pi2: PositionnedInstance = NARROW [ref2]; RETURN [IF sort[InstanceBase[extractMode.decoration, pi1.cell, pi1.trans], InstanceBase[extractMode.decoration, pi2.cell, pi2.trans]] THEN less ELSE greater]; }; CoreGeometry.EnumerateFlatGeometry[decoration: extractMode.decoration, root: extractedCT, leafProc: Leaf, eachFlatWire: EachFlatWire, eachFlatCell: EachFlatCell]; positionnedInstances _ NARROW [GList.Sort[positionnedInstances, Compare]]; }; SetLayout: PUBLIC PROC [cellType: CellType, layoutAtom: ATOM, userDataProp: ATOM _ NIL, userData: REF _ NIL] = { CoreProperties.PutCellTypeProp[cellType, layoutAtomProp, layoutAtom]; IF userDataProp#NIL THEN CoreProperties.PutCellTypeProp[cellType, userDataProp, userData]; }; RotateCellType: PUBLIC PROC [rotatedCellType: CellType, orientation: ATOM] RETURNS [cellType: CellType] = { public: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size]; internal: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size]; FOR i: NAT IN [0 .. rotatedCellType.public.size) DO new: Wire = CoreOps.CopyWire[rotatedCellType.public[i]]; public[i] _ internal[i] _ new; ENDLOOP; cellType _ CoreClasses.CreateRecordCell[public: public, internal: internal, instances: LIST [CoreClasses.CreateInstance[actual: internal, type: rotatedCellType]]]; SetLayout[cellType, orientation]; }; AbutCell: PUBLIC PROC [public: Wire, abutInstances: LIST OF AbutInstance, inX: BOOL, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType] = { positionnedInstances: LIST OF PositionnedInstance _ NIL; ObjectsFromAbutInstances: PROC [abutInstances: LIST OF AbutInstance] RETURNS [LIST OF Object] = { IF abutInstances=NIL THEN RETURN [NIL]; BEGIN obj: Object _ abutInstances.first.object; -- to allow 2 instances of the same object to have different bindings ct: CellType _ FromLayoutWithoutPublic[obj]; RETURN [CONS [Layout[ct], ObjectsFromAbutInstances[abutInstances.rest]]]; END; }; RegisterExtractedToSource: PROC [extracted, source: Wire, checkPins: BOOL] = { prevAct: Wire _ NARROW [HashTable.Fetch[extractedToSource, extracted].value]; IF extracted.size#source.size THEN ERROR Error[$CallerBug, "Extracted wire and truth public do not have same structure. You may call implementor for help!", extractedCT]; FOR i: NAT IN [0 .. extracted.size) DO RegisterExtractedToSource[extracted[i], source[i], checkPins] ENDLOOP; IF prevAct=source THEN RETURN; IF prevAct#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[extractedCT, obj, LIST [prevAct, source], CoreGeometry.GetPins[extractMode.decoration, extracted]]; [] _ HashTable.Store[extractedToSource, extracted, source]; IF source.size#0 THEN RETURN; IF checkPins AND NOT CoreGeometry.HasPins[extractMode.decoration, extracted] THEN IF checkPins THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, extracted] ELSE RETURN; -- sub-public should have pins! CoreGeometry.AddIndirectLazyPins[extractMode.decoration, source, extracted]; }; Replace: PROC [extractedWire: Wire] RETURNS [wire: Wire] = { wire _ NARROW [HashTable.Fetch[extractedToSource, extractedWire].value]; IF wire#NIL THEN RETURN; wire _ CoreOps.CreateWires[size: extractedWire.size]; internals _ CONS [wire, internals]; FOR i: NAT IN [0 .. extractedWire.size) DO wire[i] _ Replace[extractedWire[i]]; ENDLOOP; RegisterExtractedToSource[extractedWire, wire, FALSE]; }; CheckPinsNonNil: PROC [wire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, wire] THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, wire, "Some atomic publics have no associated geometry, probably because you forgot to specify in each abutInstance the sub-public bound to it."]; }; internals: Wires _ LIST [public]; instances: LIST OF CoreClasses.CellInstance; obj: Object _ (IF inX THEN PW.AbutListX ELSE PW.AbutListY)[ObjectsFromAbutInstances[abutInstances]]; extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedData: CoreClasses.RecordCellType _ NARROW [extractedCT.data]; extractedToSource: HashTable.Table _ HashTable.Create[CoreOps.WireBits[public]]; i: NAT _ 0; CoreOps.VisitRootAtomics[public, SmashPins]; SortInstances[extractMode.decoration, extractedCT, IF inX THEN SortInX ELSE SortInY]; FOR list: LIST OF AbutInstance _ abutInstances, list.rest WHILE list#NIL DO instance: CoreClasses.CellInstance = extractedData[i]; FOR pas: LIST OF CoreCreate.PA _ list.first.pas, pas.rest WHILE pas#NIL DO pub: Wire = CoreCreate.FindWire[instance.type.public, pas.first.public]; act: Wire = CoreCreate.FindWire[public, pas.first.actual]; IF pub=NIL THEN ERROR Error[$CallerBug, "Some public specified in some PA in your call to AbutCell is not really a public of the cellTYpe. You may call the maintainor of this package for help!", extractedCT]; IF act=NIL THEN ERROR Error[$CallerBug, "Call implementor for help!", extractedCT]; RegisterExtractedToSource[CoreClasses.CorrespondingActual[instance, pub], act, TRUE]; ENDLOOP; i _ i + 1; ENDLOOP; IF i#extractedData.size THEN Error[$CallerBug, "Call implementor for help!", extractedCT]; CoreOps.VisitRootAtomics[public, CheckPinsNonNil]; FOR i: NAT DECREASING IN [0 .. extractedData.size) DO actual: Wire _ CoreOps.CreateWires[size: extractedData[i].actual.size]; FOR j: NAT IN [0 .. extractedData[i].actual.size) DO actual[j] _ Replace[extractedData[i].actual[j]]; ENDLOOP; instances _ CONS [CoreClasses.CreateInstance[actual: actual, type: extractedData[i].type, props: extractedData[i].properties], instances]; ENDLOOP; recordCell _ CoreClasses.CreateRecordCell[public, CoreOps.CreateWire[internals], instances, name, props]; SetLayoutAndDecoration[recordCell, obj]; }; Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOL _ FALSE] = { name: ROPE _ CoreOps.GetCellTypeName[cellType]; layout: CD.Object _ Layout[cellType]; layoutFileName: ROPE _ Rope.Cat[name, "Layout"]; shellFileName: ROPE _ Rope.Cat[name, "Shell"]; layoutDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; shellDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; shell: CD.Object; TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]]; [] _ CoreIO.ReportSaveCellType[cellType]; TerminalIO.PutF["Making shell for cell %g ...\n", IO.rope[name]]; shell _ CoreGeometry.CreateShell[extractMode.decoration, cellType, withCuteFonts]; shellDesign.name _ shellFileName; [] _ CDDirectory.Include[shellDesign, shell, name]; CDOps.IncludeObjectI[shellDesign, shell]; TerminalIO.PutF["Storing Shell for cell %g ...\n", IO.rope[name]]; [] _ CDIO.WriteDesign[shellDesign, shellFileName]; layoutDesign.name _ layoutFileName; layout _ PWObjects.CreateCell[LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name]; [] _ CDDirectory.Include[layoutDesign, layout, name]; CDOps.IncludeObjectI[layoutDesign, layout]; TerminalIO.PutF["Storing Layout for cell %g ...\n", IO.rope[name]]; [] _ CDIO.WriteDesign[layoutDesign, layoutFileName]; TerminalIO.PutF["... layout checkpoint stored in %g.core, %gLayout.dale and %gShell.dale\n", IO.rope[name], IO.rope[name], IO.rope[name]]; }; Retrieve: PUBLIC PROC [name: ROPE] RETURNS [cellType: CellType] = { TerminalIO.PutF["Retrieving the Core for cell %g ...\n", IO.rope[name]]; cellType _ CoreIO.RestoreCellType[name]; TerminalIO.PutF["... core retrieved in %g.core ...\n", IO.rope[name]]; }; layoutClass: PUBLIC Core.CellClass _ NEW [Core.CellClassRec _ [name: "Layout", recast: RecastLayout]]; RecastLayout: Core.RecastProc = { FillTable: PROC [extractedWire: Wire] = { FillTableInternal: PROC [sourcePublic, newPublic: Wire] = { prevSource: Wire; sourcePins: CoreGeometry.Instances _ CoreGeometry.GetPins[data.mode.decoration, sourcePublic]; CoreGeometry.PutPins[data.mode.decoration, sourcePublic, sourcePins]; -- to avoid all that lazyness IF NOT CoreGeometry.TouchListList[sourcePins, extractedPins] THEN RETURN; prevSource _ NARROW [HashTable.Fetch[table, extractedWire].value]; IF prevSource#NIL AND prevSource#newPublic THEN SIGNAL PinsCorrespondingToSeveralPublics[data.cellType, data.obj, LIST [prevSource, sourcePublic], extractedPins]; [] _ HashTable.Store[table, extractedWire, newPublic]; [] _ HashTable.Store[extractedToSource, extractedWire, sourcePublic]; }; extractedPins: CoreGeometry.Instances _ CoreGeometry.GetPins[data.mode.decoration, extractedWire]; VisitAtomicPairs[data.cellType.public, public, FillTableInternal]; }; recordData: CoreClasses.RecordCellType; data: LayoutData _ NARROW [me.data]; extractedCT: CellType _ NARROW [Sinix.Extract[data.obj, data.mode].result]; public: Wire = CoreOps.CopyWire[me.public]; table: HashTable.Table _ HashTable.Create[]; extractedToSource: HashTable.Table _ HashTable.Create[]; CoreOps.VisitRootAtomics[extractedCT.public, FillTable]; new _ CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: Rope.Cat["LayoutRecastOf", CoreOps.GetCellTypeName[data.cellType]]]; recordData _ NARROW [new.data]; IF recordData.size#1 THEN ERROR Error[$InternalBug, "Internal invariant failed", data.cellType]; CoreProperties.PutCellTypeProp[extractedCT, $ExtractedToSource, extractedToSource]; CoreGeometry.PutTrans[data.mode.decoration, recordData[0], []]; }; LayoutCellTypeInfo: PUBLIC PROC [layoutCellType: CellType] RETURNS [obj: Object, sourceCellType, extractedCellType: CellType, extractedToSource: HashTable.Table] = { data: LayoutData _ NARROW [layoutCellType.data]; obj _ data.obj; sourceCellType _ data.cellType; extractedCellType _ NARROW [CoreOps.Recast[layoutCellType].data, CoreClasses.RecordCellType][0].type; extractedToSource _ NARROW [CoreProperties.GetCellTypeProp[extractedCellType, $ExtractedToSource]]; }; CorrespondingCellType: PUBLIC PROC [obj: Object] RETURNS [layoutCellType: CellType _ NIL] = { IF CDProperties.GetObjectProp[obj, extractMode.extractProcProp]=$FakeExtract THEN layoutCellType _ NARROW [CDProperties.GetObjectProp[obj, $PWCoreCellType]]; }; WriteLayoutCache: CoreIO.PropWriteProc = {CoreGeometryBackdoor.WriteObject[h, NARROW [value]]}; ReadLayoutCache: CoreIO.PropReadProc = {value _ CoreGeometryBackdoor.ReadObject[h]}; [] _ CoreIO.RegisterProperty[layoutProp, WriteLayoutCache, ReadLayoutCache]; Sinix.RegisterExtractProc[$FakeExtract, FakeExtract]; [] _ RegisterLayoutAtom[$Get, Get, DecorateValue]; [] _ RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue]; [] _ RegisterLayoutAtom[$Value, Value, DecorateValue]; [] _ RegisterLayoutAtom[$ValueNoDecorate, Value]; [] _ RegisterLayoutAtom[$AbutListXNoDecorate, AbutX]; [] _ RegisterLayoutAtom[$AbutListYNoDecorate, AbutY]; [] _ RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutX]; [] _ RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutY]; [] _ RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbutX]; [] _ RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbutY]; [] _ RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX, AttributeX]; [] _ RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY, AttributeY]; [] _ RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX, AttributeX]; [] _ RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY, AttributeY]; [] _ RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$Recast, Recast, DecorateRecasted]; [] _ RegisterLayoutAtom[$FlipX, FlipX, DecorateRotated]; [] _ RegisterLayoutAtom[$FlipY, FlipY, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot90, Rot90, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot180, Rot180, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot270, Rot270, DecorateRotated]; END. PWCoreImpl.mesa Copyright c 1985, 1987 by Xerox Corporation. All rights reserved. Louis Monier May 17, 1986 1:35:25 pm PDT Bertrand Serlet March 16, 1987 11:05:11 pm PST Barth, April 22, 1986 7:30:28 pm PST Spreitzer, April 11, 1986 10:52:25 am PST Last Edited by: Louis Monier April 19, 1987 7:59:37 pm PDT Last edited by: Christian Jacobi, January 9, 1987 12:16:44 pm PST Soon in Core ? Exceptions LayoutAtomsTable Primitives copies decorations from from to to We check that the public of the source and the public of the recasted layout are similar, and we copy properties from one to the other cache on CellTypes We compute the attributes (if any) Now the layout We decorate temporarily for lazy decorations Now we decorate the source cellType We check those decorations, and we decorate layoutCellType. We need to do that in order to be able to return layoutCellType as the result of the extraction. We make an indirect object to allow the same layout to be returned on 2 different calls of Layout Consistency check Global Variable $Get, $GetAndFlatten, $Value and $ValueNoDecorate Abuts, Arrays and Recast We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location Rotations Help for writing DecorateProcs We copy the pins for all publics. For now, we only do it for wires which have the same name as some internal of cellType. All this code stinks .... The following lines are to pass PWCoreRoute test All this code stinks .... If source is NIL, crash! If it is an internal only, let's forget it! positionnedInstances is the sorted list of all instances that have associated layout. positionnedWires is the list of all wires having their own geometry. Short cut Tentative help for regular structures We check now that every atomic public has pins We replace the actuals Saving "Checkpoints" Core Shell Layout Backdoor for clients such as PWCoreLichen Registering layoutAtoms Κˆ˜™Icodešœ Οmœ7™BK™(K™.K™$K™)K™:K™A—J˜šΟk ˜ Kšœ˜KšžœY˜[K˜ KšœJ˜JK˜$Kšœžœ˜Kšžœ˜Kšœ˜Kšœ$˜$—K˜šΠbn œžœž˜KšžœžœΙžœžœ>˜Kšžœ˜Kšžœ˜Kšžœžœ˜—head™šΟnœžœ žœ˜Lš  œžœ˜,Kšžœžœžœ˜$šžœ˜Kšžœ˜Kš žœžœžœžœžœ#žœ˜R—K˜—Kšžœžœžœ˜$Kš žœžœžœžœ#žœ˜MK˜——™ š œžœžœžœ˜2J˜—š  œžœžœžœ žœžœ˜KJ˜—š !œžœžœWžœ˜ŒJ˜—Jš  œžœžœ:žœžœžœ˜p—šœ™Jšœ7˜7J˜Kšœžœžœ˜-KšœžœžœWžœ˜|K˜š œžœžœžœ7žœ#žœžœ žœ˜―Kšœ˜šžœ0žœm˜’Kšžœžœ5žœ˜^—K˜K˜—š œžœžœžœ%˜WKšœžœ7˜NKšžœžœž ˜"Kšœ7žœ ˜FKšœžœ7˜NK˜K˜—š œžœžœžœžœžœžœ#žœ˜¬Kšœ?˜?Kšžœžœžœžœ˜"Kšœ(˜(Kšœ,˜,Kšœ/˜/K˜——šœ ™ šœžœžœ,˜GJ˜—š   œžœžœžœžœžœ˜TKšœ žœ<˜OKšžœ žœžœžœ˜Kšœ žœC˜VK˜K˜—š  œR˜]K˜—š  œžœDžœ˜YK˜—Kšœ"™"š œžœ&˜;š œžœ˜+šžœžœ8˜>Jšžœžœ[˜f—JšœK˜KK˜—Kšœ†™†Kšœ/˜/Kšœ3˜3K˜K˜—šœ Πbkœžœ3˜KJšΟc™K˜—š œžœžœžœ˜BKšœžœ8˜DKšžœžœžœžœ˜šž˜Kšœ žœ˜+Kšœ˜Kšœ˜K˜šžœ žœ˜šžœžœžœ˜"KšžœžœU˜_šžœ˜Kšœ.˜.Kšœ˜Kšœ)˜)Kšœ>˜>Kšžœ˜K˜———Kšœ/˜/Kš žœžœžœžœžœ0žœ˜ŠK™"Kšžœžœžœ)˜RK™Kšœ*˜*K™,Kšœ>˜>Kšœ žœF˜VKšœy˜yKšœ#™#Kšžœžœžœ,˜SKšœ™Kšœ/˜/KšœD˜DKšœa™aKšœ$˜$KšœA˜AKšœK˜KKšœ>˜>Kšœ:˜:Jšœ™Jšžœ7žœžœ<˜Kšžœ+žœžœ=˜tKšžœ˜—Kšœ˜—K˜š œžœžœžœ˜SJšœ žœ*˜;Kšœ&˜&K˜——™Jšœ žœ.˜A—šœ1™1šœ žœžœ ˜"J˜—š  œžœ žœžœžœ˜OJš œžœ žœžœ žœ˜BJ˜J˜—šŸœ˜Kšœžœ žœA˜[JšœA˜AK˜K˜—š  œ˜Kšœžœ žœA˜[JšœžœE˜MK˜K˜—š œ˜Kšœžœ:˜FK˜K˜—š  œžœ˜&Jšœžœ*˜HJšœO˜OšŸœ˜/š žœžœžœžœ?žœžœž˜hKšœžœ˜KšœA˜AKšœžœ;˜\Kš žœžœžœžœžœ˜7Kš žœžœžœžœžœ2žœZ˜Ρšžœžœ=˜CJšžœžœ:˜E—JšœN˜NKšœ=˜=Kšžœ˜—J˜—Kšœ5˜5Jšœ?˜?Kšœ˜——™š  œN˜XK˜—š  œN˜XK˜—šŸœ˜Kšœ#žœ˜:Kšœ žœžœ žœ˜!š žœžœž œžœž˜,Kšœ žœ$˜5Kšžœ˜—Jšœžœ˜K˜K˜—šŸœ˜Kšœ#žœ˜:Kšœ žœžœ žœ˜!š žœžœž œžœž˜,Kšœ žœ$˜5Kšžœ˜—Jšœžœ˜K˜K˜—šŸ œ˜Kšœ#žœ˜:Kšœ žœžœ žœ˜!šžœžœžœž˜!Kšœ žœ$˜5Kšžœ˜—Jšœžœ˜K˜K˜—šŸ œ˜Kšœ#žœ˜:Kšœ žœžœ žœ˜!šžœžœžœž˜!Kšœ žœ$˜5Kšžœ˜—Jšœžœ˜K˜K˜—šŸœ˜Kšœ.˜.Kšœ7˜7K˜K˜—šŸœ˜Kšœ.˜.Kšœ7˜7K˜K˜—šŸ œ˜Kšœ.˜.Kšœ>˜>K˜K˜—šŸ œ˜Kšœ.˜.Kšœ>˜>K˜K˜—šŸœ˜Kšœ'˜'K˜K˜—š  œžœžœ6˜Oš  œ˜&Kšžœžœžœq˜™Kšœ žœ˜K˜—š  œ˜"Jšœžœ žœ˜#Jšœžœ žœ˜#šžœžœL˜VJšžœžœ ˜—J˜—Kšœžœžœ ˜Jšœ)žœ˜@Kšžœžœ#žœ˜PKšœ1˜1Kšœ žœ#˜2Jšœd™dšžœžœžœž˜'JšœQ˜QJšœ˜Jšžœ˜—Jšžœžœžœžœs˜‹JšœAžœ˜WK˜K˜—š  œžœ˜&Kšœ%˜%Kšœ˜K˜—š  œžœ˜&Kšœ%˜%Kšœ˜K˜—š œžœ˜-Kšœ,˜,Kšœ˜K˜—š œžœ˜-Kšœ,˜,Kšœ˜K˜—šŸœžœ˜)Kšœ9˜9Kšœ˜——™ š œžœžœ˜DJšœ ˜ Jšžœ,žœžœZ˜’Jšœžœ˜Jšžœ žœžœZ˜rJšœ˜J˜K˜—šŸœžœ#˜@K˜—šŸœžœ#˜@K˜—šŸœžœ#˜@K˜—šŸœžœ$˜BK˜—šŸœžœ$˜BK˜—šŸœžœ˜(Jšœ(˜(Kšœ#˜#Kš œ0˜BKšžœžœ#žœ˜PKšžœžœžœ‡˜²Kšœ9˜9Kšœ.žœ8˜lKšœAžœ˜WK˜——™Kš œžœžœžœ žœžœžœ˜YKš œžœžœžœ žœžœžœ˜YKš œžœžœžœ žœžœžœ˜`š œžœžœžœ žœžœžœ˜`K˜—š   œžœžœ-žœžœ˜dKšœ+žœ˜IK˜K˜—š  œžœ_žœžœ˜KšœF˜FK˜K˜—š  œžœžœN˜hKšœ#žœ˜:šžœžœžœž˜#šžœžœžœž˜!šžœ˜ KšœT˜TKšœR˜RKšœžœ˜Kšœ'˜'Kšœ˜Kšœ˜—Kšžœ˜—Kšžœ˜—K˜K˜—š œžœžœ)žœžœ žœ žœžœ˜xJšœžœžœ˜#Jšœžœ*˜HKšœ]’5˜’Kšœ.žœ˜HKšœ+žœ˜BKšœžœžœ˜2Kšœžœžœ˜*š œžœ@˜TJšœžœ0’J˜žJšœ˜Kšœ ˜ Kš žœžœžœžœ:žœ˜kKšžœžœžœ˜!Kš žœ žœžœžœ=’˜tKšžœžœžœ=’˜vJšœ ˜ Kšžœ(žœžœ<˜pKšœžœ=˜JKšžœžœžœ˜!Kš žœžœžœžœ2žœV˜£JšœX˜XKšœH˜HK˜—KšœV˜VKš žœ6žœžœžœažœ*žœ$˜ŠKšœ5˜5šžœžœžœž˜)KšœF˜FKšœ*˜*Kšœžœ"˜CKš žœ5žœžœžœŽžœ žœ˜…KšœZ˜ZKšžœ?žœžœ4˜šžœžœžœž˜(KšœX˜XKšžœ˜—Kšœ1˜1Kšžœ˜—Kšœz™zKšœ™šžœžœž˜š  œ#˜/KšžœEžœžœ˜Sšœ˜Jšœ ˜ Jšžœp˜tJšœ˜—K˜—Kšœ:˜:Kšœ"˜"Kšœ:˜:Kšœžœ"˜,Kšœžœ;˜PKšžœžœžœ5’G˜žK™0Kšœ™Kšžœžœžœ8˜JKšœ™Kšžœžœžœžœ˜+Kšœ+™+Kšžœžœžœ2žœQ˜˜Kšœ)˜)Kšžœ˜—K˜K˜—Kšœžœžœ˜7šœžœžœ˜'Kšœ’!˜3Kšœ#˜#Kšœ’-˜KKšœ"˜"K˜K˜—Kšœžœžœ˜/šœžœžœ˜#Jšœ ˜ Kšœ˜Kšœ"˜"K˜K˜—KšœU™UKšœE™Eš œžœ)žœžœžœžœžœžœžœ˜ΌJš œžœ˜Dš  œ#˜/šœžœ˜JšžœH˜KJšœ˜—J˜—š  œ#˜/šœžœ˜šžœ˜Jšœ@˜@Jšœ˜—Jšœ˜—J˜—š œ˜Jšœžœ˜)Jšœžœ˜)šžœžœ|˜†Jšžœžœ ˜—J˜—Jšœ’˜’Kšœžœ-˜JK˜——™ š  œžœžœ"žœžœžœ žœžœ˜pKšœE˜EKšžœžœžœB˜ZKšœ˜K˜—š  œžœžœ*žœžœ˜kKšœF˜FKšœH˜Hšžœžœžœ$ž˜3Kšœ8˜8Kšœ˜Kšžœ˜—K•StartOfExpansion`[actual: Core.Wire, type: Core.CellType, name: ROPE _ NIL, props: Core.Properties _ NIL]šœWžœH˜£Kšœ!˜!K˜——™%š œžœžœžœžœžœžœžœžœžœ˜’Kšœžœžœžœ˜8š œžœžœžœžœžœžœ ˜aKš žœžœžœžœžœ˜'šž˜Kšœ*’E˜oKšœ,˜,Kšžœžœ=˜IKšžœ˜—K˜—š œžœ&žœ˜NKšœžœ7˜MKšžœžœžœƒ˜«Kš žœžœžœžœ?žœ˜mKšžœžœžœ˜Kš žœ žœžœžœ5žœN˜‘Kšœ;˜;Kšžœžœžœ˜šžœ žœžœ9˜MJš žœžœ žœžœ3žœžœ’˜|—JšœL˜LK˜—š œžœžœ˜˜SJšœOžœ˜UKšžœ˜—K˜ Kšžœ˜—Kšžœžœ>˜ZKšœ.™.Kšœ2˜2J™š žœžœž œžœž˜5JšœG˜Gšžœžœžœ%ž˜4Jšœ0˜0Jšžœ˜—Jšœ žœz˜ŠJšžœ˜—Jšœi˜iKšœ(˜(K˜——™š  œžœžœ%žœžœ˜HJšœžœ%˜/Kšœžœ˜%Jšœžœ˜0Jšœžœ˜.Jšœžœžœ˜IJšœ žœžœ˜HJšœžœ˜JšΟb™Jšœ5žœ ˜DJšœ)˜)Jš£™Jšœ2žœ ˜AJšœR˜RKšœ!˜!Kšœ3˜3Kšœ)˜)Jšœ3žœ ˜BKšœžœ)˜2Kš£™Kšœ#˜#Kšœžœ žœ˜aKšœ5˜5Kšœ+˜+Jšœ4žœ ˜CKšœžœ+˜4Kšœ]žœ žœ žœ ˜ŠJ˜J˜—š  œžœžœžœžœ˜CJšœ9žœ ˜HJšœ(˜(Kšœ7žœ ˜FJ˜——™)šœ žœžœ>˜fJ˜—š  œ˜!š  œžœ˜)š œžœ$˜;J˜Jšœ^˜^JšœF’˜cJšžœžœ7žœžœ˜IJšœ žœ/˜BJš žœ žœžœžœžœ<žœ,˜’Jšœ6˜6JšœE˜EJ˜—Jšœb˜bJšœB˜BJ˜—J˜'Jšœžœ ˜$Jšœžœ-˜KJšœ+˜+Jšœ,˜,Jšœ8˜8Jšœ8˜8Jšœ­˜­Jšœ žœ ˜KšžœžœžœB˜aJšœS˜SJšœ?˜?J˜J˜—š œžœžœžœc˜₯Jšœžœ˜0Jšœ˜Jšœ˜JšœžœK˜eJšœžœI˜cJ˜J˜—š  œžœžœžœžœ˜]šžœK˜MKšžœžœ4˜P—K˜——š œ™Jš œ>žœ ˜_Jš œE˜TšœL˜LJ˜—Jšœ5˜5J˜Jšœ2˜2JšœF˜FJšœ6˜6Jšœ1˜1Jšœ5˜5Jšœ5˜5Jšœ9˜9Jšœ9˜9JšœN˜NJšœN˜NJšœB˜BJšœB˜BJšœW˜WJšœW˜WJšœ;˜;Jšœ;˜;JšœI˜IJšœI˜IJšœ;˜;Jšœ8˜8Jšœ8˜8Jšœ8˜8Jšœ:˜:Jšœ:˜:—J˜Kšžœ˜K™—…—{$ž<