DIRECTORY Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, Commander, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, IO, PW, PWCore, RefTab, Rope, Sinix, SinixOps, Sisyph, TerminalIO; PWCoreImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, RefTab, IO, PW, PWCore, Rope, Sinix, SinixOps, Sisyph, TerminalIO EXPORTS PWCore SHARES CDCells, CDDirectory = BEGIN OPEN PWCore; 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: RefTab.Ref _ RefTab.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 ~RefTab.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 [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; IF layoutAtomData#NIL THEN RETURN; CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"]; layoutAtomData _ NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; }; 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.InheritCellTypeProp[cellType, layoutAtomProp]]; }; 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.PutIndirectsLazyPins[extractMode.decoration, toWire, LIST [fromWire]]; -- replaced AddIndirectLazyPins by PutIndirectsLazyPins on August 15, 1988 12:14:12 pm PDT [BS] }; CoreOps.VisitAtomicPairs[to.public, from.public, CopyPins]; }; CheckDecorations: PROC [ct: CellType, obj: Object] = { CheckPins: PROC [wire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, wire] THEN SIGNAL NoPinsOnAtomicPublic[ct, obj, wire, CoreOps.GetFullWireName[ct.public, wire]]; }; CoreOps.VisitRootAtomics[ct.public, CheckPins]; }; fromPWCoreProp: PRIVATE ATOM _ $FromPWCoreLayout; -- on CD.Objects FromPWCoreRecord: TYPE = RECORD [int: INT]; SetFromPWCore: PRIVATE PROC [cellType: CellType] = { obj: CD.Object _ CoreGeometry.GetObject[extractMode.decoration, cellType]; int: INT _ LOOPHOLE [cellType]; IF CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work! CDProperties.PutObjectProp[obj, fromPWCoreProp, NEW [FromPWCoreRecord _ [int]]]; }; Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = { layoutAtom: ATOM; layoutAtomData: LayoutAtomData; obj _ CoreGeometry.GetObject[extractMode.decoration, cellType]; IF obj#NIL THEN RETURN; layoutAtom _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]]; IF layoutAtom=NIL THEN layoutAtom _ NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]; IF layoutAtom=NIL AND cellType.class.recast=NIL THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType]; layoutAtomData _ GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE 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]; PW.SetName[obj, CoreOps.GetCellTypeName[cellType]]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; CheckDecorations[cellType, obj]; SetFromPWCore[cellType]; }; GetPWCoreExtractedCTKey: PUBLIC PROC [extractedCT: CellType] RETURNS [key: INT _ 0] = { obj: CD.Object _ CoreGeometry.GetObject[extractMode.decoration, extractedCT]; ref: REF FromPWCoreRecord _ NARROW [CDProperties.GetObjectProp[obj, fromPWCoreProp]]; IF ref#NIL THEN key _ ref.int; }; IsPWCoreGenerated: PUBLIC PROC [obj: Object] RETURNS [BOOL] = { RETURN [CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL]; }; FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = { cellType _ NARROW [Sinix.Extract[obj, extractMode].result]; IF IsPWCoreGenerated[obj] THEN RETURN; -- done twice! SetLayoutAndDecoration[cellType, obj]; CheckDecorations[cellType, obj]; SetFromPWCore[cellType]; }; extractMode: PUBLIC Sinix.Mode _ SinixOps.GetExtractMode[$cmosB]; maskSuffix: PUBLIC ROPE _ ".mask"; GetAndAddSuffix: PROC [cellType: CellType] RETURNS [obj: Object] = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; obj _ PW.Get[source, IO.PutR[IO.rope[CoreOps.GetCellTypeName[cellType]], IO.rope[maskSuffix]]]; }; Get: LayoutProc = { obj _ PW.CreateIndirect[GetAndAddSuffix[cellType]]; }; GetAndFlatten: LayoutProc = { obj _ PW.Flatten[GetAndAddSuffix[cellType]]; }; Value: LayoutProc = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]]; }; DecorateValue: PUBLIC DecorateProc = { extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: RefTab.Ref _ RefTab.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 [RefTab.Fetch[extractedToSource, extractedWire].val]; 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]; [] _ RefTab.Store[extractedToSource, extractedWire, wire]; ENDLOOP; }; [] _ CoreOps.VisitWire[cellType.public, FindInExtractedPublic]; }; sisyphFudge: INT _ CD.FetchTechnology[$cmosB].lambda/2; -- Not very clean here! AttributeAbutXorY: AttributesProc = { ambiguous, inX: BOOL; [ambiguous, inX] _ InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge]; IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType]; SortInstances[Sisyph.mode.decoration, cellType, IF inX THEN SortInX ELSE SortInY]; }; LayoutAbutXorY: LayoutProc = { obj _ (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN AbutX ELSE AbutY)[cellType]; }; DecorateAbutXorY: DecorateProc = { (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN DecorateAbutX ELSE DecorateAbutY)[cellType, obj]; }; 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]; }; AbutFlipXAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, TRUE]}; AbutFlipYAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, FALSE]}; AbutFlipAndDecorate: PROC [cellType: CellType, inX: BOOL] RETURNS [obj: Object] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; flip: BOOL _ FALSE; -- indicates polarity of the coming flip instances: CD.InstanceList _ NIL; -- instances for constructing the cell layout0: CD.Object _ Layout[data[0].type]; isize0: CD.Position _ CD.InterestSize[layout0]; pos: CD.Position _ [0, 0]; -- position (in ir coordonnates) of the coming cell FOR i: NAT IN [0 .. data.size) DO orientation: CD.Orientation _ IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE original; layout: CD.Object _ Layout[data[i].type]; ir: CD.Rect = CDBasics.MapRect[CD.InterestRect[layout], [[0, 0], orientation]]; isize: CD.Position _ CDBasics.SizeOfRect[ir]; trans: CD.Transformation = [CDBasics.SubPoints[pos, CDBasics.BaseOfRect[ir]], orientation]; -- translation, in the CD coordonnate system IF NOT (IF inX THEN isize.y=isize0.y ELSE isize.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX instances _ CONS [CDInstances.NewInst[layout, trans], instances]; CoreGeometry.PutTrans[extractMode.decoration, data[i], trans]; IF inX THEN pos.x _ pos.x + isize.x ELSE pos.y _ pos.y + isize.y; flip _ NOT flip; ENDLOOP; obj _ PW.CreateCell[instances: instances]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; 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 _ PW.CreateIndirect[Layout[recasted]]; }; ArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ArrayFlipX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipX]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ArrayFlipY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ReverseArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutX]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ReverseArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; Recast: LayoutProc = { obj _ PW.CreateIndirect[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.Expand1[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; }; LayoutRotated: LayoutProc = { orientation: CD.Orientation _ SELECT GetLayoutAtom[cellType] FROM $FlipX => mirrorX, $FlipY => rotate180X, $Rot90 => rotate90, $Rot90X => rotate90X, $Rot180 => rotate180, $Rot180X => rotate180X, $Rot270 => rotate270, $Rot270X => rotate270X, ENDCASE => ERROR; obj _ PW.CreateRotation[Layout[Rotated[cellType]], orientation]; }; DecorateRotated: PUBLIC DecorateProc = { rotatedCT: CellType = Rotated[cellType]; trans: CoreGeometry.Transformation; DecorateUniqueInst: CDCells.InstEnumerator = {trans _ inst.trans}; WHILE obj.class#CDCells.pCellClass DO obj _ CDDirectory.Expand1[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]; }; InstancesInXOrY: PUBLIC PROC [decoration: CoreGeometry.Decoration, record: CellType, fudge: INT _ 0] RETURNS [ambiguous, inX: BOOL] = { data: CoreClasses.RecordCellType _ NARROW [record.data]; overlappingInX, overlappingInY: BOOL _ FALSE; FOR i: NAT IN [0 .. data.size-1) DO rect1: CD.Rect _ CDBasics.MapRect[ CD.InterestRect[CoreGeometry.GetObject[decoration, data[i].type]], CoreGeometry.GetTrans[decoration, data[i]] ]; FOR j: NAT IN (i .. data.size) DO rect2: CD.Rect _ CDBasics.MapRect[ CD.InterestRect[CoreGeometry.GetObject[decoration, data[j].type]], CoreGeometry.GetTrans[decoration, data[j]] ]; IF rect1.x1+fudge™A—J˜š ˜ Kšœ˜Kšœ>œ˜[K˜ Kšœ>˜>K˜Kšœœ˜ Kšœ ˜ Kšœ˜Kšœ$˜$—K˜šΠbn œœ˜Kš œœ>œbœœ3˜νKšœ˜Kšœ˜Kšœœ˜—head™ šΟnœœœœ˜2J˜—š Ÿœœœœ œœ˜KJ˜—šŸ!œœœWœ˜ŒJ˜—Jš Ÿœœœ:œœœ˜p—šœ™Jšœ/˜/J˜Kšœœœ˜-KšœœœWœ˜|K˜šŸœœœœ7œ#œœ œ˜―Kšœ˜šœ-œm˜ŸKšœEœ˜^—K˜K˜—šŸœœœœ%˜WKšœœ2˜IKšœœœœ˜"Kšœ7œ ˜FKšœœ2˜IK˜K˜—šŸœœœœœœœ#œ˜¬Kšœ?˜?Kšœœœœ˜"Kšœ(˜(Kšœ,˜,Kšœ/˜/K˜——šœ ™ šœœœ,˜GJ˜—š Ÿ œœœœœœ˜TKšœ œ@˜SK˜K˜—Kšœ"™"šŸœœ&˜;šŸœœ˜+šœœ8˜>Jšœœ[˜f—JšœBœΟc_˜³K˜—Kšœ†™†Kšœ;˜;K˜K˜—Kšœ'™'šŸœœ ˜6šŸ œœ˜ šœœ4œ˜?JšœO˜U—K˜—Kšœ/˜/K˜K˜—JšœΠbkœœ ˜BJšœœœœ˜+šŸ œœœ˜4KšœœC˜JKšœœœ ˜Kšœ1œœ h˜ΆKšœ0œ˜PK˜J˜—šŸœœœœ˜BKšœ œ˜Kšœ˜Kšœ?˜?Kšœœœœ˜Kšœ œ<˜Ošœ œœ˜Kšœ œC˜V—š œ œœœœ˜5KšœV˜[—Kš œ#œ œœ œ ˜Sšœœœ˜Kšœœ0œ˜o—K™"Kšœœœ)˜RK™Kšœ*˜*Kšœ1˜3K™ Kšœ>˜>Kšœ#™#Kšœœœ,˜SKšœ™Kšœ ˜ Kšœ!™!Kšœ˜Kšœ˜—K˜š Ÿœœœœœ ˜WKšœœF˜MKšœœœ3˜UKšœœœ˜J˜J˜—š Ÿœœœœœ˜?Jšœ2œ˜=J˜J˜—šŸœœœœ˜SJšœ œ*˜;Kšœœœ ˜5Kšœ&˜&Kšœ ˜ Kšœ˜K˜——™Jšœ œ.˜A—šœ1™1šœ œœ ˜"J˜—šŸœœœ˜DKšœœ œA˜[JšœLœ™PJš œœ œœ*œ˜_J˜J˜—K™>K™ζšžœ˜Jšœœ+˜3K˜K˜—šŸ œ˜Jšœœ$˜,K˜K˜—šŸœ˜Kšœœ:˜FK˜K˜—šŸ œœ˜&Jšœœ*˜HJšœG˜Gšžœ˜/š œœœœ?œœ˜hKšœœ˜KšœA˜AKšœœ6˜WKš œœœœœ˜7Kš œœœœœ2œZ˜Ρšœœ=˜CJšœœ:˜E—JšœN˜NKšœ:˜:Kšœ˜—J˜—Jšœ?˜?Kšœ˜——™šœ œœ# ˜OK˜—šŸœ˜%Kšœœ˜KšœR˜RKšœ œœV˜mKšœ0œœ œ ˜RKšœ˜K˜—šŸœ˜KšœœDœœ˜nK˜K˜—šŸœ˜"KšœœDœœ˜}K˜K˜—šŸ œN˜XK˜—šŸ œN˜XK˜—šŸœ˜Kšœ#œ˜:Kšœ œœ œ˜!š œœ œœ˜,Kšœ œ$˜5Kšœ˜—Jšœœ˜K˜K˜—šŸœ˜Kšœ#œ˜:Kšœ œœ œ˜!š œœ œœ˜,Kšœ œ$˜5Kšœ˜—Jšœœ˜K˜K˜—šŸœ4œ˜OK˜—šŸœ4œ˜PK˜—šŸœœœœ˜SKšœ#œ˜:Kšœœœ (˜˜>Jšœœœ˜AKšœœ˜Kšœ˜—Jšœœ#˜+JšœAœ˜WK˜K˜—šŸ œ˜Kšœ#œ˜:Kšœ œœ œ˜!šœœœ˜!Kšœ œ$˜5Kšœ˜—Jšœœ˜K˜K˜—šŸ œ˜Kšœ#œ˜:Kšœ œœ œ˜!šœœœ˜!Kšœ œ$˜5Kšœ˜—Jšœœ˜K˜K˜—šžœ˜Kšœ.˜.Kšœ&œ"˜JK˜K˜—šžœ˜Kšœ.˜.Kšœ&œ"˜JK˜K˜—šž œ˜Kšœ.˜.Kšœ*œ"˜NK˜K˜—šž œ˜Kšœ.˜.Kšœ*œ"˜NK˜K˜—šž œ˜Kšœ.˜.Kšœ-œ"˜QK˜K˜—šž œ˜Kšœ.˜.Kšœ-œ"˜QK˜K˜—šžœ˜Kšœœ2˜:K˜K˜—šŸ œœœ6˜OšŸ œ˜&Kšœœœq˜™Kšœ œ˜K˜—šŸ œ˜"Jšœœ œ˜#Jšœœ œ˜#šœœL˜VJšœœ ˜—J˜—Kšœœœœ ˜Jšœ)œ˜@Kšœœ$œ˜QKšœ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˜—šŸ œ˜šœ œœ˜AJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜—Jšœœ8˜@Jšœ˜K˜—šžœœ˜(Jšœ(˜(Kšœ#˜#KšŸœ0˜BKšœG™GKšœœ$œ˜QKšœœœ‡˜²Kšœ9˜9Kšœ.œ8˜lKšœAœ˜WK˜——™KšŸœœœœ œœœ˜YKšŸœœœœ œœœ˜YKšŸœœœœ œœœ˜`šŸœœœœ œœœ˜`K˜—š Ÿ œœœ-œœ˜dKšœ+œ˜IK˜K˜—šŸ œœ_œœ˜KšœF˜FK˜K˜—š Ÿœœœ@œœœ˜‡Kšœ#œ˜8Kšœ œœ˜-šœœœ˜#šœœ˜"JšœA˜CJšœ*˜*J˜—šœœœ˜!šœœ˜"JšœA˜CJšœ*˜*J˜—Kšœœœœ˜RKšœœœœ˜RKšœ˜—Kšœ˜—Kšœ*˜*Kšœ˜K˜K˜—šŸ œœœN˜hKšœ#œ˜:šœœœ˜#šœœœ˜!šœ˜ KšœT˜TKšœR˜RKšœœ˜Kšœ'˜'Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—K˜——™ šŸ œœœ"œœœ œœ˜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šœ™šŸœœ œ œ ˜DšŸ œ ˜*šœœ˜Kšœ œ ˜/Kšœœœœ˜Kšœœ-˜:Kšœœœœ˜Kšœ™Kš œ.œœœœœ˜UKšœ+œ˜1K˜—K˜—Jšœ:˜:Jšœ˜J˜—š Ÿœœœ%œœ˜HJšœœ%˜/Jšœ (˜?Jšœ5œ ˜DJšœ)˜)Jšœ$˜$Jšœ˜šœR˜RJšœ œ œ ˜-—Jšœ˜—J˜š Ÿ œœœ%œœ˜MJšœœ%˜/Jšœœ˜.Jšœ œœ˜HJšœœ˜Jšœ6œ ˜EJšœR˜RJšœ!˜!Jšœ3˜3Jšœ.˜.Jšœœ)˜2Jšœ/˜/Jšœ ˜"J˜—šŸ œœœ˜1Jšœœ%˜/Jšœœ˜0Jšœœœ˜IJšœœ˜%Jšœ7œ ˜FJšœ#˜#šœ œ ˜Jšœœ œ*˜Q—JšœB˜BJšœ0˜0Jšœ.˜.Jšœœ+˜4Jšœ0˜0Jšœ ˜"J˜—šŸœœœœœœœ˜ašŸœœ"˜0šœœ?˜EJšœœm˜x—JšœIœ ˜ZK˜—Kšœ˜Kšœ˜Kšœ(œ ˜7Jšœ(˜(Kšœ'œ ˜6Kšœ˜Kšœœœœ˜#Kšœ+˜+K˜!Kšœ<˜