DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOrient, CDProperties, Commander, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, CoreProperties, CoreGeometry, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph; PWCoreImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CoreClasses, CoreCreate, CoreOps, CoreProperties, CoreGeometry, GList, HashTable, IO, PW, PWObjects, Rope, Sinix, SinixOps, Sisyph 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; }; SmashProps: CoreOps.EachWireProc = { name: ROPE = CoreOps.GetShortWireName[wire]; wire.properties _ NIL; [] _ CoreOps.SetShortWireName[wire, name]; }; CopyWire: PROC [old: Wire] RETURNS [new: Wire] = { new _ CoreOps.CopyWire[old]; [] _ CoreOps.VisitWire[new, SmashProps]; }; 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: LIST OF CD.Instance] = CODE; NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE _ NIL] = CODE; NoInterestRectDecoration: PUBLIC SIGNAL [cellType: CellType, obj: Object] = 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 PW.WriteF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]; }; GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc _ NIL, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] = { layoutAtomData: LayoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; 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]]; }; layoutProp: PRIVATE ATOM _ CoreProperties.RegisterProperty[$PWCoreLayout]; -- cache on CellTypes 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]; CoreGeometry.PutIR[extractMode.decoration, to, CD.InterestRect[obj]]; VisitAtomicPairs[to.public, from.public, CopyPins]; }; 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]; RETURN; }; layoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; 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]; layoutData _ NEW [LayoutDataRec _ [cellType: cellType, obj: obj, mode: extractMode]]; layoutCellType _ CoreOps.CreateCellType[class: layoutClass, public: CopyWire[cellType.public], data: layoutData]; IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; IF NOT CoreGeometry.HasIR[extractMode.decoration, cellType] OR CoreGeometry.GetIR[extractMode.decoration, cellType]#CD.InterestRect[obj] THEN SIGNAL NoInterestRectDecoration[cellType, obj]; CopyDecorations[layoutCellType, cellType, obj]; obj _ PWObjects.CreateIndirect[obj]; CDProperties.PutObjectProp[obj, $PWCoreCellType, layoutCellType]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]; IF CoreOps.GetCellTypeName[cellType]#NIL AND CDDirectory.Name[obj]=NIL THEN NARROW [obj.class.directoryProcs, REF CDDirectory.DirectoryProcs].setName[obj, CoreOps.GetCellTypeName[cellType]]; 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; }; InterestRect: PUBLIC PROC [cellType: CellType] RETURNS [ir: CD.Rect] = { IF NOT CoreGeometry.HasIR[extractMode.decoration, cellType] THEN [] _ Layout[cellType]; ir _ CoreGeometry.GetIR[extractMode.decoration, cellType]; }; 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]; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; [] _ 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] = { InsertInOrder: PROC [element: CD.Instance, sorted: LIST OF CD.Instance] RETURNS [new: LIST OF CD.Instance] = { IF element.orientation#0 THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable for CD Cells without rotations", cellType]; IF sorted=NIL THEN RETURN [LIST [element]]; IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[element]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first]]] THEN RETURN [CONS [element, sorted]]; RETURN [CONS [sorted.first, InsertInOrder[element, sorted.rest]]]; }; SetLazyPins: PROC [wire: Wire] = {CoreGeometry.PutRecordLazyPins[extractMode.decoration, wire, cellType]}; instances: LIST OF CD.Instance; recordData: CoreClasses.RecordCellType _ NARROW [cellType.data]; WHILE obj.class#CDCells.cellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; FOR list: LIST OF CD.Instance _ NARROW [obj.specificRef, CD.CellPtr].contents, list.rest WHILE list#NIL DO instances _ InsertInOrder[list.first, instances]; ENDLOOP; FOR i: NAT IN [0 .. recordData.size) DO CoreGeometry.PutTransf[extractMode.decoration, recordData[i], instances.first]; instances _ instances.rest; ENDLOOP; IF instances#NIL THEN ERROR Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType]; CoreOps.VisitRootAtomics[cellType.public, SetLazyPins]; }; 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; IF NOT CoreOps.CorrectConform[cellType.public, rotatedCT.public] THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; }; 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]; transf: CD.Instance; CopyPinsFromRotated: PROC [wire1, wire2: Wire] = { CoreGeometry.PutTransfWireIRLazyPins[ decoration: extractMode.decoration, public: wire1, indirect: wire2, transf: transf, ir: ir ]; }; instances: LIST OF CD.Instance; ir: CD.Rect = CD.InterestRect[obj]; WHILE obj.class#CDCells.cellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; CoreGeometry.PutIR[extractMode.decoration, cellType, ir]; instances _ NARROW [obj.specificRef, CD.CellPtr].contents; IF instances=NIL OR instances.rest#NIL THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType]; transf _ instances.first; VisitAtomicPairs[cellType.public, rotatedCT.public, CopyPinsFromRotated]; }; 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]}; InstanceLocation: PROC [decoration: CoreGeometry.Decoration, cellInst: CoreClasses.CellInstance] RETURNS [location: CD.Position] = { location _ CDBasics.BaseOfRect[CDInstances.InstRectO[CoreGeometry.GetTransf[decoration, cellInst]]]; }; 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[InstanceLocation[decoration, data[i]], InstanceLocation[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]; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; 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.PutTransf[extractMode.decoration, cellTypeData[i], positionnedInstance.transf]; 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 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 FOR list: LIST OF CD.Instance _ positionnedWire.geometry, list.rest WHILE list#NIL DO IF NOT CoreGeometry.AtEdge[ir, list.first] THEN LOOP; CoreGeometry.PutPins[ extractMode.decoration, source, CONS [list.first, CoreGeometry.GetPins[extractMode.decoration, source]] ]; ENDLOOP; 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] transf: CD.Instance ]; PositionnedWire: TYPE = REF PositionnedWireRec; PositionnedWireRec: TYPE = RECORD [ wire: Wire, flatWire: CoreFlat.FlatWireRec, geometry: LIST OF CD.Instance ]; GetPositionnedInstances: PROC [extractedCT: CellType, sort: SortProc] RETURNS [positionnedInstances: LIST OF PositionnedInstance _ NIL, positionnedWires: LIST OF PositionnedWire _ NIL] = { InsertInOrdered: PROC [element: PositionnedInstance, sorted: LIST OF PositionnedInstance] RETURNS [new: LIST OF PositionnedInstance] = { IF sorted=NIL THEN RETURN [LIST [element]]; IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[element.transf]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first.transf]]] THEN RETURN [CONS [element, sorted]]; RETURN [CONS [sorted.first, InsertInOrdered[element, sorted.rest]]]; }; Leaf: CoreGeometry.LeafProc = {RETURN [cellType.class=layoutClass]}; EachFlatWire: CoreGeometry.EachFlatWireProc = { positionnedWires _ CONS [ NEW [PositionnedWireRec _ [wire: wire, flatWire: flatWire, geometry: geometry]], positionnedWires]; }; EachFlatCell: CoreGeometry.EachFlatCellProc = { positionnedInstances _ CONS [ NEW [PositionnedInstanceRec _ [ cell: cell, flatCell: flatCell, bindings: bindings, transf: transf ]], positionnedInstances]; }; Compare: GList.CompareProc = { pi1: PositionnedInstance = NARROW [ref1]; pi2: PositionnedInstance = NARROW [ref2]; RETURN [IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[pi1.transf]], CDBasics.BaseOfRect[CDInstances.InstRectO[pi2.transf]]] 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]; }; SetLayoutAndDecoration: PUBLIC PROC [cellType: CellType, layout: CD.Object] = { SetLayout[cellType, $ValueNoDecorate, $PWCoreValue, layout]; }; 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 = 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]; CoreGeometry.PutIR[extractMode.decoration, recordCell, CD.InterestRect[obj]]; SetLayoutAndDecoration[recordCell, obj]; }; AbutList: PUBLIC PROC [cellTypes: LIST OF CellType, inX: BOOL] RETURNS [recordCell: CellType] = { lobj: LIST OF CD.Object _ NIL; WHILE cellTypes#NIL DO ct: CellType _ cellTypes.first; obj: CD.Object _ CDCells.CreateEmptyCell[]; CDCells.SetInterestRect[obj, InterestRect[ct]]; CDProperties.PutObjectProp[obj, $PWCoreCellType, ct]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; lobj _ CONS [obj, lobj]; cellTypes _ cellTypes.rest; ENDLOOP; recordCell _ NARROW [Sinix.Extract[(IF inX THEN PW.AbutListX ELSE PW.AbutListY)[PW.Reverse[lobj]], extractMode].result]; SetLayout[recordCell, IF inX THEN $AbutListXNoDecorate ELSE $AbutListYNoDecorate]; }; 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: LIST OF CD.Instance _ 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: LIST OF CD.Instance _ 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 = 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.PutTransf[data.mode.decoration, recordData[0], CDInstances.NewInst[data.obj]]; }; 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]]; }; 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 by Xerox Corporation. All rights reserved. Louis Monier May 17, 1986 1:35:25 pm PDT Bertrand Serlet November 7, 1986 5:22:24 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 October 20, 1986 3:30:17 pm PDT 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 We compute the attributes (if any) Now the layout Now we decorate the source cellType We decorate layoutCellType with the same decorations, and on the way check those decorations 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 transf, so that the Lazy GetPins can find the location Rotations 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 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 line is 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 Backdoor for clients such as PWCoreLichen Registering layoutAtoms สฎ˜™Icodešœ ฯmœ1™Jšžœžœ[˜f—JšœK˜KK˜—Kšœ†™†Kšœ/˜/Kšœ/žœ˜EKšœ3˜3K˜K˜—š œžœžœžœ˜BKšœžœ8˜DKšžœžœžœžœ˜šž˜Kšœ žœ˜+Kšœ˜Kšœ˜K˜šžœ žœ˜šžœžœžœ˜"KšžœžœU˜_šžœ˜Kšœ.˜.Kšœ˜Kšœ)˜)Kšžœ˜K˜———Kšœžœ7˜NKš žœžœžœžœžœ0žœ˜ŠK™"Kšžœžœžœ)˜RK™Kšœ*˜*Kšœ žœF˜VKšœq˜qKšœ#™#Kšžœžœžœ,˜SKšœ\™\Kš žœžœ6žœ6žœžœžœ)˜ฝKšœ/˜/Kšœa™aKšœ$˜$KšœA˜AKšœK˜KKšœ:˜:Jšžœ#žœžœžœžœžœžœM˜พJšœ™Jšžœ7žœžœ<˜Kšžœ+žœžœ=˜tKšžœ˜—Kšœ˜—K˜š   œžœžœžœžœ ˜HJšžœžœ6žœ˜WJšœ:˜:J˜J™—š œžœžœžœ˜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˜5Kšœ5žœ˜KJšœ?˜?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š  œžœ žœžœžœžœ žœžœžœžœ˜nKšžœžœžœ_˜‚Kš žœžœžœžœžœ ˜+Kšžœužœžœžœ˜œKšžœžœ6˜BK˜—Kš  œžœY˜jKšœ žœžœžœ ˜Jšœ)žœ˜@Kšžœžœ#žœ˜OKšœ5žœ˜Kšžœžœžœžœ žœžœžœžœž˜jKšœ1˜1Kšžœ˜—Jšœe™ešžœžœžœž˜'JšœO˜OJšœ˜Jšžœ˜—Jšžœ žœžœžœs˜ŽJšœ7˜7K˜K˜—š  œžœ˜&Kšœ%˜%Kšœ˜K˜—š  œžœ˜&Kšœ%˜%Kšœ˜K˜—š œžœ˜-Kšœ,˜,Kšœ˜K˜—š œžœ˜-Kšœ,˜,Kšœ˜K˜—šŸœžœ˜)Kšœ9˜9Kšœ˜——™ š œžœžœ˜DJšœ ˜ Jšžœ,žœžœZ˜’Jšœžœ˜Jšžœ žœžœZ˜rJšœ˜Jšžœžœ;žœžœZ˜ฅJ˜K˜—šŸœžœ#˜@K˜—šŸœžœ#˜@K˜—šŸœžœ#˜@K˜—šŸœžœ$˜BK˜—šŸœžœ$˜BK˜—šŸœžœ˜(Jšœ(˜(Kšœžœ ˜š œžœ˜2šœ%˜%KšœZ˜ZKšœ˜—K˜—Kšœ žœžœžœ ˜Kšœžœžœ˜#Kšžœžœ#žœ˜OKšœ9˜9Kšœ žœžœ˜:Kš žœ žœžœžœžœžœ‡˜ธJšœ˜Kšœ†™†KšœI˜IK˜——™Kš œžœžœžœ žœžœžœ˜YKš œžœžœžœ žœžœžœ˜YKš œžœžœžœ žœžœžœ˜`š œžœžœžœ žœžœžœ˜`K˜—š œžœKžœ žœ˜„Kšœd˜dK˜K˜—š  œžœžœN˜hKšœ#žœ˜:šžœžœžœž˜#šžœžœžœž˜!šžœUžœ˜]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šœ5žœ˜KKš žœ6žœžœžœažœ*žœ$˜ŠKšœ5˜5šžœžœžœž˜)KšœF˜FKšœ*˜*Kšœžœ"˜CKš žœ5žœžœžœŽžœ žœ˜…Kšœ\˜\Kšžœ?žœžœ4˜šžœžœžœž˜(KšœX˜XKšžœ˜—Kšœ1˜1Kšžœ˜—Kšœz™zKšœ™šžœžœž˜Kšœ:˜:Kšœ"˜"Kšœ:˜:Kšœžœ"˜,Kšœžœ;˜PKšžœžœžœ5ขG˜žK™.Kšœ™Kšžœžœžœ8˜JKšœ™Kšžœžœžœžœ˜+Kšœ+™+šžœžœžœ2žœžœžœžœžœ0žœžœž˜Jšžœžœ%žœžœ˜5šœ˜Jšœ ˜ JšžœC˜GJšœ˜—Kšžœ˜—Kšœ)˜)Kšžœ˜—K˜K˜—Kšœžœžœ˜7šœžœžœ˜'Kšœข!˜3Kšœ#˜#Kšœข-˜KKšœžœ ˜K˜K˜—Kšœžœžœ˜/šœžœžœ˜#Jšœ ˜ Kšœ˜Kšœ žœžœžœ ˜K˜K˜—KšœU™UKšœE™Eš œžœ)žœžœžœžœžœžœžœ˜ผš œžœ(žœžœžœžœžœ˜ˆKš žœžœžœžœžœ ˜+Kšžœƒžœžœžœ˜ชKšžœžœ8˜DK˜—Jš œžœ˜Dš  œ#˜/šœžœ˜JšžœN˜QJšœ˜—J˜—š  œ#˜/šœžœ˜šžœ˜JšœB˜BJšœ˜—Jšœ˜—J˜—š œ˜Jšœžœ˜)Jšœžœ˜)Jšžœžœvžœžœ ˜˜J˜—Jšœข˜ขKšœžœ-˜JK˜——™ š  œžœžœ"žœžœžœ žœžœ˜pKšœE˜EKšžœžœžœB˜ZKšœ˜K˜—š œžœžœžœ ˜OKšœ<˜˜SJšœOžœ˜UKšžœ˜—K˜ Kšžœ˜—Kšžœžœ>˜ZKšœ.™.Kšœ2˜2J™š žœžœž œžœž˜5JšœG˜Gšžœžœžœ%ž˜4Jšœ0˜0Jšžœ˜—Jšœ žœz˜ŠJšžœ˜—Jšœi˜iKšœ7žœ˜MKšœ(˜(K˜K˜—š œžœžœ žœžœžœžœ˜aJš œžœžœžœ žœ˜šžœ žœž˜Jšœ˜Jšœžœ$˜+Jšœ/˜/Jšœ5˜5JšœK˜KJšœžœ ˜Jšœ˜Jšžœ˜—Jšœ žœžœžœžœ žœžœ žœ&˜xJšœžœžœžœ˜RK˜——™)šœ žœžœ>˜fJ˜—š  œ˜!š  œžœ˜)š œžœ$˜;J˜Jšœ žœžœžœE˜[JšœFข˜cJšžœžœ7žœžœ˜IJšœ žœ/˜BJš žœ žœžœžœžœ<žœ,˜ขJšœ6˜6JšœE˜EJ˜—JšœžœžœžœF˜_Jšœ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šžœKžœžœ4˜K˜——š œ™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™—…—{~ŸV