DIRECTORY Atom USING [PropList], CD USING [Instance, Error, ErrorCode, lambda, Number, Object, Orientation, Position, Properties, Rect], CDBasics USING [BaseOfRect, Intersect, Intersection, NonEmpty], CDOrient USING [ComposeOrient, DeMapRect, MapRect, original, RectAt], CornerStitching USING [ChangeRect, FuncChangeRect, PerTileChangeProc, Tesselation], SX USING [Circuit, CircuitNode, Constraint, ConstraintResolution, nodeIndex, SpinifexLayerIndex], SXAccess, SXAccessInternal, SXConflicts, SXQuadTree USING [AreaSplit, QuadTree, Rectangle, Rectangles], TerminalIO USING [WriteChar]; SXConflictsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDOrient, CornerStitching, SXAccessInternal, SXAccess, TerminalIO EXPORTS SXConflicts = BEGIN debug: BOOL = FALSE; ThinLimit: CD.Number _ CD.lambda*10; UseLevelOrderHeuristic: PROC [clipRect: CD.Rect, old, new: SXQuadTree.Rectangles] RETURNS [BOOLEAN] = BEGIN RETURN [clipRect.x2 - clipRect.x1 > ThinLimit AND clipRect.y2 - clipRect.y1 > ThinLimit] END; Constraint: TYPE = SX.Constraint; Rectangle: TYPE = SXQuadTree.Rectangle; Node: TYPE = SX.CircuitNode; ComputeConflicts: PUBLIC PROC [ qt: REF SXQuadTree.QuadTree, conflictWorld: REF CornerStitching.Tesselation, layer: SX.SpinifexLayerIndex, cir: REF SX.Circuit] = BEGIN descentDepth: INT _ 1; OccupyByNode: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM a: ATOM => IF a#$Conflict THEN CD.Error[ec: other, explanation: "OccupyByNode: illegal value"]; r: REF Rectangle => IF data#r THEN conflictWorld.ChangeRect[rect, $Conflict]; applRef: SXQuadTree.Rectangles => IF data#applRef.first THEN { conflictWorld.ChangeRect[rect, data]; -- sets the value Flatten [rect, applRef] } ELSE CD.Error[ec: other, explanation: "OccupyByNode: data=applRef.first"]; c: REF Constraint => IF NOT SameConstraints[ ResolveConstraints[c, data, SXAccess.sxTech.constraintResolutions[layer]], data] THEN conflictWorld.ChangeRect[rect, $Conflict]; ENDCASE => IF oldValue#NIL THEN CD.Error[ec: other, explanation: "OccupyByNode: oldValue#NIL"] ELSE conflictWorld.ChangeRect[rect, data]; END; -- OccupyByNode OccupyByConstr: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM a: ATOM => IF a#$Conflict THEN CD.Error[ec: other, explanation: "OccupyByConstr: illegal value"]; r: REF Rectangle => IF NOT SameConstraints[ ResolveConstraints[NARROW[data], r, SXAccess.sxTech.constraintResolutions[layer]], r] THEN conflictWorld.ChangeRect[rect, $Conflict]; applRef: SXQuadTree.Rectangles => { conflictWorld.ChangeRect[rect, data]; Flatten [rect, applRef] }; c: REF Constraint => { resolution: REF ANY = ResolveConstraints[c, data, SXAccess.sxTech.constraintResolutions[layer]]; IF NOT SameConstraints[resolution, c] AND NOT SameConstraints[resolution, data] THEN conflictWorld.ChangeRect[rect, $Conflict] ELSE IF NOT SameConstraints[resolution, c] THEN conflictWorld.ChangeRect[rect, resolution]; }; ENDCASE => IF oldValue#NIL THEN CD.Error[ec: other, explanation: "OccupyByConstr: oldValue#NIL"] ELSE conflictWorld.ChangeRect[rect, data]; END; -- OccupyByConstr OccupyByAppl: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM a: ATOM => IF a#$Conflict THEN CD.Error[ec: other, explanation: "OccupyByAppl: a#$Conflict"]; r: REF Rectangle => { IF NARROW[data, SXQuadTree.Rectangles].first = r THEN CD.Error[ec: other, explanation: "Rectangle has already been processed"]; Flatten [rect, NARROW[data]] }; applRef: SXQuadTree.Rectangles => IF data#applRef THEN IF UseLevelOrderHeuristic[rect, applRef, NARROW[data]] THEN DescendOneLevel [rect, applRef, NARROW[data]] ELSE { conflictWorld.ChangeRect[rect, NIL]; Flatten [rect, applRef]; Flatten [rect, NARROW[data]] }; c: REF Constraint => Flatten [rect, NARROW[data]]; ENDCASE => IF oldValue#NIL THEN CD.Error[ec: other, explanation: "OccupyByAppl: oldValue#NIL"] ELSE conflictWorld.ChangeRect[rect, data]; END; -- OccupyByAppl Flatten: PROC [clipRect: CD.Rect, applRef: SXQuadTree.Rectangles] = BEGIN appl: CD.Instance = NARROW[applRef.first.nodeInformation]; FlattenCell: PROC [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation] = BEGIN MapRect: PROC [inCellRect: CD.Rect] RETURNS [inWorldRect: CD.Rect] = INLINE BEGIN inWorldRect _ CDBasics.Intersection [ CDOrient.MapRect[ itemInCell: inCellRect, cellSize: appl.ob.size, cellInstOrient: orient, cellInstPos: pos], clipRect] END; FlattenTree: PROC [qt: REF SXQuadTree.QuadTree] = BEGIN IF debug THEN TerminalIO.WriteChar['f]; FOR boxes: SXQuadTree.Rectangles _ qt.boxes, boxes.rest WHILE boxes#NIL DO WITH boxes.first.nodeInformation SELECT FROM node: REF Node => { r: CD.Rect = MapRect[boxes.first.interestBound]; IF CDBasics.NonEmpty[r] THEN conflictWorld.FuncChangeRect[r, OccupyByNode, applRef.first] }; constr: REF Constraint => { r: CD.Rect = MapRect[boxes.first.interestBound]; IF CDBasics.NonEmpty[r] THEN conflictWorld.FuncChangeRect[r, OccupyByConstr, constr] }; subAppl: CD.Instance => IF CDBasics.Intersect[boxes.first.interestBound, mappedClip] THEN { FlattenCell [ subAppl, CDBasics.BaseOfRect[CDOrient.MapRect[ itemInCell: CDOrient.RectAt[pos: subAppl.location, size: subAppl.ob.size, orient: subAppl.orientation], cellSize: appl.ob.size, cellInstOrient: orient, cellInstPos: pos]], CDOrient.ComposeOrient[subAppl.orientation, orient]] }; ENDCASE => CD.Error[ec: programmingError, explanation: "Flatten: invalid case"]; ENDLOOP; IF SXAccess.stopFlag^ THEN ERROR ABORTED; IF mappedClip.y2>qt.midY AND qt.subTrees[north]#NIL THEN FlattenTree[qt.subTrees[north]]; IF mappedClip.y1qt.midX AND qt.subTrees[east]#NIL THEN FlattenTree[qt.subTrees[east]]; IF mappedClip.x1 IF a#$Conflict THEN CD.Error[ec: other, explanation: "BidByNode: a#$Conflict"]; r: REF Rectangle => IF data#r THEN CD.Error[ec: other, explanation: "BidByNode: data#r"]; applRef: SXQuadTree.Rectangles => conflictWorld.ChangeRect[rect, data]; c: REF Constraint => conflictWorld.ChangeRect[rect, data]; ENDCASE => CD.Error[ec: programmingError, explanation: "BidByNode: invalid case"]; END; -- BidByNode BidByConstr: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM a: ATOM => IF a#$Conflict THEN CD.Error[ec: other, explanation: "BidByConstr: a#$Conflict"]; r: REF Rectangle => IF new.first#r THEN CD.Error[ec: other, explanation: "BidByConstr: new.first#r"]; applRef: SXQuadTree.Rectangles => IF applRef#new THEN conflictWorld.ChangeRect[rect, data]; c: REF Constraint => { resolution: REF ANY = ResolveConstraints[c, data, SXAccess.sxTech.constraintResolutions[layer]]; IF NOT SameConstraints[resolution, c] THEN conflictWorld.ChangeRect[rect, resolution]; }; ENDCASE => ERROR; END; -- BidByConstr BidByAppl: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM a: ATOM => IF a#$Conflict THEN CD.Error[ec: other, explanation: "BidByAppl: a#$Conflict"]; r: REF Rectangle => IF NARROW[data, SXQuadTree.Rectangles].first#r THEN CD.Error[ec: other, explanation: "BidByAppl: data.first#r"]; applRef: SXQuadTree.Rectangles => IF data#applRef THEN conflictWorld.ChangeRect[rect, data]; c: REF Constraint => conflictWorld.ChangeRect[rect, data]; ENDCASE => ERROR; END; -- BidByAppl DescendCell: PROC [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation] = BEGIN MapRect: PROC [inCellRect: CD.Rect] RETURNS [inWorldRect: CD.Rect] = INLINE BEGIN inWorldRect _ CDBasics.Intersection [ CDOrient.MapRect[ itemInCell: inCellRect, cellSize: appl.ob.size, cellInstOrient: orient, cellInstPos: pos], clipRect] END; -- MapRect DescendTree: PROC [qt: REF SXQuadTree.QuadTree] = BEGIN IF qt=NIL THEN RETURN; FOR boxes: SXQuadTree.Rectangles _ qt.boxes, boxes.rest WHILE boxes#NIL DO WITH boxes.first.nodeInformation SELECT FROM node: REF Node => { r: CD.Rect = MapRect[boxes.first.interestBound]; IF CDBasics.NonEmpty[r] THEN conflictWorld.FuncChangeRect[r, BidByNode, new.first] }; constr: REF Constraint => { r: CD.Rect = MapRect[boxes.first.interestBound]; IF CDBasics.NonEmpty[r] THEN conflictWorld.FuncChangeRect[r, BidByConstr, constr] }; subAppl: CD.Instance => IF CDBasics.Intersect[boxes.first.interestBound, mappedClip] THEN { IF levelCount > 0 THEN DescendCell[ subAppl, CDBasics.BaseOfRect[CDOrient.MapRect[ itemInCell: CDOrient.RectAt[pos: subAppl.location, size: subAppl.ob.size, orient: subAppl.orientation], cellSize: appl.ob.size, cellInstOrient: orient, cellInstPos: pos]], CDOrient.ComposeOrient[subAppl.orientation, orient]] ELSE { r: CD.Rect = MapRect[boxes.first.interestBound]; IF CDBasics.NonEmpty[r] THEN conflictWorld.FuncChangeRect[r, BidByAppl, new] } }; ENDCASE => ERROR; ENDLOOP; IF mappedClip.y2>qt.midY AND qt.subTrees[north]#NIL THEN DescendTree[qt.subTrees[north]]; IF mappedClip.y1qt.midX AND qt.subTrees[east]#NIL THEN DescendTree[qt.subTrees[east]]; IF mappedClip.x1 conflictWorld.FuncChangeRect[boxes.first.interestBound, OccupyByNode, boxes.first]; constr: REF Constraint => conflictWorld.FuncChangeRect[boxes.first.interestBound, OccupyByConstr, constr]; appl: CD.Instance => conflictWorld.FuncChangeRect[boxes.first.interestBound, OccupyByAppl, boxes]; ENDCASE => ERROR; ENDLOOP; FOR quad: SXQuadTree.AreaSplit IN SXQuadTree.AreaSplit DO ComputeConflicts[qt.subTrees[quad], conflictWorld, layer, cir] ENDLOOP; IF descentDepth#1 THEN CD.Error[ec: other, explanation: "ComputeConflicts: descentDepth#1"] END; -- ComputeConflicts SameConstraints: PROC [c1, c2: REF ANY] RETURNS [BOOLEAN] = { IF c1 = c2 THEN RETURN[TRUE]; WITH c1 SELECT FROM con1: REF Constraint => { WITH c2 SELECT FROM con2: REF Constraint => RETURN[con1.name = con2.name]; ENDCASE => RETURN[FALSE]; }; ENDCASE => RETURN[FALSE]; }; ResolveConstraints: PUBLIC PROC [newConstraint: REF Constraint, oldValue: REF ANY, resolution: REF SX.ConstraintResolution] RETURNS [REF ANY] = BEGIN WITH oldValue SELECT FROM oldConstraint: REF Constraint => { specificNode: REF SX.CircuitNode _ NIL; result: REF Constraint _ resolution[newConstraint.index][oldConstraint.index]; IF result=NIL THEN CD.Error[ec~ other, explanation~ "Invalid ConstraintResolution"]; specificNode _ IF newConstraint.specificCorrespondingNode # NIL THEN newConstraint.specificCorrespondingNode ELSE oldConstraint.specificCorrespondingNode; -- Be careful if you have more than one constraint type with a specificCorrespondingNode IF specificNode # NIL THEN { result _ NEW[Constraint _ result^]; result.specificCorrespondingNode _ specificNode}; RETURN [result] }; -- end oldConstraint: REF CircuitConstraint node: REF Node => { result: REF Constraint _ resolution[newConstraint.index][SX.nodeIndex]; IF result=NIL THEN RETURN [node] ELSE { IF newConstraint.specificCorrespondingNode # NIL THEN { result _ NEW[Constraint _ result^]; result.specificCorrespondingNode _ newConstraint.specificCorrespondingNode}; RETURN [result]}; }; rect: REF Rectangle => { result: REF Constraint _ resolution[newConstraint.index][SX.nodeIndex]; IF result=NIL THEN RETURN [rect] ELSE { IF newConstraint.specificCorrespondingNode # NIL THEN { result _ NEW[Constraint _ result^]; result.specificCorrespondingNode _ newConstraint.specificCorrespondingNode}; RETURN [result]}; }; ENDCASE => ERROR; END; -- ResolveConstraints END. œSXConflictsImpl.mesa; Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Written by: Beretta, January 3, 1985 6:23:57 pm PST Last Edited by Mark Shand, March 9, 1985 12:22:24 pm PST Last Edited by: Jacobi, April 8, 1985 10:51:01 am PST Bowers, September 4, 1985 5:40:59 pm PDT Last edited by: gbb July 15, 1985 11:55:10 am PDT This module contains only the procedures ComputeConflicts and ResolveConstraints which previously were in the module SpinifexLayersImpl, which is its only client. The operation was necessary because of storage problems in the compiler. -- Only bother with Level-order Conflict Resolution when the contended region is not too narrow. --Called in the first per layer loop of SpinifexLayersImpl.AnalyzeGeometry. The quad-trees are enumerated and the conflict world is constructed. Each rectangle has an area of interest depending on the material. Constraints do not overlap: they are ordered into the technology dependent part; the larger prevails. Every constraint is represented by a number which is an index in a boolean array to infere whether it is there. -- 3 things are put into the conflictWorld they are: => REF Rectangle: occupied by a node (possibly within a subcell as determined by val.nodeInformation's TYPE, either REF circuitNode or CD.Instance) => REF Constraint: occupied by a constraint or some resolution of constraints such that the resolution at each step was one of the two contending constraints vying for occupancy of the region. => SXQuadTree.Rectangles: Bid for occupancy by a subcell to some unspecified depth. -- In addition conflictWorld will also contain: => ATOM ~ $Conflict being the result of an irresolvable conflict for occupancy and flagging a region as requiring instantiation and analysis. -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] --Subcell which needs to be flattened out: put in node and flatten subcell. --Initially the plane is empty, hence tile=NIL. -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] --Resolve constraints against each other. --Initially the plane is empty, hence tile=NIL. -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] -- If oldValue is a subcell, then rect is the intersection of the subcell oldValue and the cell data. Otherwise it is a conflict, a a rectangle or a constraint. -- Clear present occupant out of region. -- Add flattened rectangles from each cell to region. If subcell of same subcell: already done. --(local of FlattenCell, local of Flatten) --Use quad-tree to filter what has to be flattened. --Situation: two cells overlap. Goal: Try not to flatten unnecessary cells (i.e. which do not have material or constraints in the overlap or interacting material. -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] -- PROC [plane: REF Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] --(local of DescendCell, local of DescendOneLevel) (local of DescendCell, local of DescendOneLevel) -- main of DescendCell -- Main of ComputeConflicts -- The big boxes are inserted first, then the smaller stuff. Having radix sorted the boxes into sub-trees increases locality of reference to the corner stitched data structure. --CornerStitching.FuncChangeRect is for local changes. For each rectangle in the first parameter, the function which is the second parameter is called the third parameter as the function's parameter: --Only the first box is of interest. A list is passed because the type is used as a discriminant to decide: 1. if list then may or may not have actual geometry and needs further discrimination. 2. if ref then cell is known to have geometry there. --Recursive because of quad-trees. -- The consistency rules for SX.ConstraintResolution are non-trivial, the order of application should not be importantthis is the key attribute. -- Check for side effects of returning NEW Constraint!!! -- Bowers September 4, 1985 4:13:08 pm PDT Edited on January 3, 1985 6:23:58 pm PST, by Beretta Created the module taking ComputeConflicts & ResolveConstraints out of SpinifexLayersImpl.mesa. Edited on March 7, 1985 1:21:40 am PST, by Shand Removed unnecessary parameters from Tree enumeration procedures Added Heuristic procedure to override Level-order Conflict Resolution based on value returned by UseLevelOrderHeuristic. changes to: FlattenCell (local of Flatten), DescendTree (local of DescendCell, local of DescendOneLevel), DescendCell (local of DescendOneLevel) changes to: UseLevelOrderHeuristic to choose when to apply Level-order Conflict Resolution, ComputeConflicts, OccupyByAppl in case where region is currently occupied by another cell, either DescendOneLevel, or Flatten., OccupyByAppl, ThinLimit, UseLevelOrderHeuristic, OccupyByAppl, DIRECTORY, FlattenTree (local of FlattenCell, local of Flatten), DescendTree (local of DescendCell, local of DescendOneLevel) Edited on March 6, 1985, by Shand Made Constraint to node conflict detection more uniform so that OccupyByConstr and OccupyByNode implement same approach. changes to: OccupyByConstr $Conflict results only if ResolveConstraints[Constraint, Node] # Node. Edited on March 7, 1985 2:50:27 am PST, by Shand Fixed bug in FlattenTree when calling back to bid for Node. Used to call on subcell's REF Rectangle (boxes.first) rather than topcell's REF Rectangle (applRef.first) changes to: FlattenTree (local of FlattenCell, local of Flatten) case node Edited on March 9, 1985 12:22:24 pm PST, by Shand Changed name of CircuitConstraint in SX to Constraint, added tech parameter to ComputeConflicts, changed ResolveConstraints to deal with new constraint resolution representation. changes to: DIRECTORY, ComputeConflicts, OccupyByNode, ResolveConstraints, node (local of ResolveConstraints), rect (local of ResolveConstraints), ComputeConflicts Edited on April 8, 1985 3:54:18 pm PST, by Jacobi reformatted ΚΡ˜šœ™Icodešœ Οmœ7™BJ™3K™8J™5K™(K™1J™Jšœ(Οnœžœ$Οbœd™λJ™—šΟk ˜ Kšœ œ ˜Kš œ œ_˜gKšœ  œ1˜?Kšœ  œ7˜EKšœ œ>˜SKšœ œY˜aKšœ ˜ Kšœ˜Kšœ ˜ Kšœ  œ.˜>Kšœ  œ ˜—K˜šŸœ œ ˜Kš œP˜WKš œ˜—Kš ˜K˜Kšœ œ œ˜Kšœ  œ  œ ˜$unitš žœ œ  œ( œ œ˜fLš ˜K™`Kš œ( œ'˜XKš œ˜LšœK™K—Lšœ  œ œ ˜!Kšœ  œ˜'Kšœ œ œ ˜šžœ œ œ˜Kšœά™άJšœ œ˜Jšœ œ˜0Jšœ˜Jšœ œ˜Lš ˜L•StartOfExpansiona -- [plane: REF CornerStitching.Tesselation, rect: CD.Rect, oldValue: REF ANY, data: REF ANY] -- šœ œ˜šœ4™4Jšœ“™“Jšœΐ™ΐJšœS™S—šœ/™/Jšœ™—L˜šŸ œ&˜2KšœR™RKš ˜š œ  œ ˜Kš œ œ œ  œ œ>˜_Kšœ œ œ œ+˜Mšœ!˜!K™Kš œ œ˜Kšœ&ΟcΠce˜7Kšœ˜K˜—Kš œ œC˜J—šœ œ˜š œ˜KšœQ ˜UKšœ*˜*——š œ˜ Kšœ/™/Kš œ œ œ<˜SKš œ&˜*——Kš œ‘’ ˜—K˜šŸœ'˜5KšœR™RKš ˜š œ  œ ˜Kš œ œ œ  œ œ@˜ašœ œ ˜š œ˜Kšœ œ= ˜ZKšœ*˜*——šœ#˜#Kšœ%˜%Kšœ˜Kšœ˜—šœ œ˜K™)Kšœ  œ œK˜`š œ$ œ' œ˜UKšœ)˜)—š œ œ$ ˜/Kšœ+˜+—Kšœ˜—š œ˜ Kšœ/™/Kš œ  œ œ œ>˜UKš œ&˜*——Kšœ‘’˜—K˜šŸ œ'˜3KšœR™RKšœ˜Kš œΟeœ£œ$£œ£œ<™ š œ  œ ˜Kš œ œ œ  œ œ<˜]šœ œ˜Kš œ œ( œ œG˜Kšœ œ˜Kšœ˜—šœ"˜"š œ ˜š œ' œ ˜;Kšœ  œ˜-—š œ˜K™(Kšœ œ˜$K™5Kšœ˜Kšœ œ˜K˜——K™)—Kšœ œ œ˜2š œ˜ Kš œ  œ œ œ<˜SKš œ&˜*——Kš œ‘’ ˜—K˜šžœ œ  œ)˜DLš ˜Kšœ œ  œ ˜:K˜š ž œ œ œ œ œ˜RKš ˜K˜š žœ œ œ œ œ ˜EKš œ ˜ šœ%˜%šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ ˜ —Kš œ˜—K˜šž œ œ œ˜2Kš ˜Kšœ*™*Kš œ œ˜'š œ5 œ œ ˜Jš œ œ ˜,šœ œ ˜Kšœ œ+˜0š œ ˜Kšœ<˜<—Kšœ˜—šœ œ˜Kšœ œ+˜0š œ ˜Kšœ7˜7—Kšœ˜—šœ  œ ˜š œ; œ˜Cšœ ˜ Kšœ ˜ šœ%˜%Kšœi˜iKšœ˜Kšœ˜Kšœ˜—Kšœ4˜4—K˜——Kš œ œC˜P—Kš œ˜—L™3Kš œ œ œ œ˜)š œ œ œ ˜8Kšœ ˜ —š œ œ œ ˜8Kšœ ˜ —š œ œ œ ˜7Kšœ˜—š œ œ œ ˜7Kšœ˜—Kš œ‘’ ˜—Lšœ œ˜ Kšœ  œd˜‚KšœT˜Tš œ œ ˜Kšœ˜—Kš œ‘’ ˜—Lšœ2˜2Kš œ‘’˜—K˜šžœ œ  œ*˜MK™’Kš ˜Kšœ  œ˜K˜šŸ œ'˜0KšœR™RKš ˜š œ  œ ˜Kš œ œ œ  œ œ9˜ZKš œ œ œ œ œ4˜YKšœG˜GKšœ œ4˜:Kš œ œE˜R—Kš œ‘’ ˜—K˜šŸ œ&˜1KšœR™RKš ˜š œ  œ ˜Kš œ œ œ  œ œ;˜\Kš œ œ œ  œ œ;˜ešœ"˜"Kš œ  œ&˜9—šœ œ˜Kšœ  œ œM˜`Kš œ$ œ,˜VKšœ˜—Kš œ œ˜—Kš œ‘’ ˜—K˜šŸ œ'˜0KšœR™RKš ˜š œ  œ ˜Kš œ œ œ  œ œ9˜Zšœ œ˜Kš œ œ& œ œ:˜p—šœ"˜"Kš œ œ&˜:—Kšœ œ4˜:Kš œ œ˜—Kš œ‘’ ˜—K˜š ž œ œ œ œ œ˜RKš ˜K˜š žœ œ œ œ œ˜DKš œ ˜ Kšœ2™2šœ%˜%šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ ˜ —Kš œ‘’˜—K˜šž œ œ œ˜2Kš ˜Kšœ0™0Kš œ œ œ œ˜š œ5 œ œ ˜Jš œ œ ˜,šœ œ ˜Kšœ œ+˜0š œ ˜Kšœ5˜5—Kšœ˜—šœ œ˜Kšœ œ+˜0š œ ˜Kšœ4˜4—Kšœ˜—šœ  œ ˜š œ; œ˜Cš œ ˜šœ ˜ Kšœ ˜ šœ%˜%Kšœg˜gKšœ˜Kšœ˜Kšœ˜—Kšœ4˜4——š œ˜Kšœ œ+˜0š œ ˜Kšœ/˜/—Kšœ˜—K˜——Kš œ œ˜—Kš œ˜—š œ œ œ ˜8Kšœ ˜ —š œ œ œ ˜8Kšœ ˜ —š œ œ œ ˜7Kšœ˜—š œ œ œ ˜7Kšœ˜—Kš œ‘’ ˜—K˜Kšœ™Kšœ œ˜ šœ  œ˜)Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—KšœT˜TKšœ˜Kšœ˜Kšœ˜Kš œ‘’ ˜K˜—Lšœ œ  œ˜7Lšœ ˜ Kšœ‘˜˜>J™"—Jš œ˜—Jš œ œ œB˜[Kš œ‘’˜K˜—š žœ œ  œ œ œ œ˜=Kš œ  œ œ œ˜š œ œ œ˜šœ œ˜š œ œ ˜Kšœ œ œ˜7Kš œ œ œ˜—K˜—Kš œ œ œ˜—K˜—˜K˜—šžœ œ œ œ œ œ œ œ œ œ œ˜Kšœ£œ]™‘K™JšŸ8™8Kš ˜š œ  œ ˜šœ œ˜"JšŸ'˜'Kšœ œC˜NJš œ œ œ œ?˜TJšŸ›˜›Jšœ?Ÿœ˜YJšŸ*™*šŸ˜JšŸ#˜#JšŸ1˜1—Jš œ ˜Kšœ‘’(˜.—šœ œ ˜Jšœ œ. œ ˜GKš œ œ œ œ˜ š œ ˜šŸ7˜7KšŸ#˜#KšŸL˜L—Kš œ ˜—Kšœ˜—šœ œ˜Jšœ œ. œ ˜GKš œ œ œ œ˜ š œ ˜šŸ7˜7KšŸ#˜#KšŸL˜L—Kš œ ˜—Kšœ˜—Kš œ œ˜—Kš œ‘’˜K˜K˜—K˜Kš œ˜K˜™4Jšœ£œ£œ ™_—J™™0J™?JšœaΠenœ™xJšœ Οr œ¦ œ1¦ œ™Jš œ ¦œ8¦ œD₯œ₯œ¦Wœ)¦ œ1™˜—™!Jšœ@¦œ¦ œ™xJšœ ¦œG™a—™0Jšœ¦™¦JšœJ™J—™1JšœO¦œ ¦œ7™²Jšœ ¦Cœ¦œ¦™£—™1J™ —J™—…—2Έ\%