DIRECTORY CD, CDBasics, CDCells, CDProperties, CDRects, CDSymbolicObjects, Convert, Core, CoreGeometry, CoreOps, GC, GCPrivate, HashTable, IP, IPCTG, IPTop, PWPins, PWRoute, Rope, Route, RTBasic, RTStructure, Sinix, SinixOps; GCDetailRouteImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDProperties, CDRects, CDSymbolicObjects, Convert, CoreGeometry, CoreOps, GC, GCPrivate, HashTable, IPCTG, RTBasic, PWPins, PWRoute, Rope, RTStructure, Sinix, SinixOps EXPORTS GCPrivate = { KeyFromProperty: PWRoute.MakeTabKeyProc ~ { ref: REF _ CDProperties.GetInstanceProp[pinInst, GCPrivate.nameProp]; tabIndex _ IF ref = NIL THEN CDSymbolicObjects.GetName[pinInst] ELSE NARROW[ref]; }; DoDetailRoute: PUBLIC PROC [context: GC.Context] RETURNS [result: GC.Result] = { MakeChannel: GCPrivate.EachChannelAction ~ { technologyKey: ATOM _ NARROW[context.rules.technology, CD.Technology].key; trunkLayer: Rope.ROPE _ IF channel.direction = horizontal THEN context.rules.horizLayer ELSE context.rules.vertLayer; branchLayer: Rope.ROPE _ IF channel.direction = horizontal THEN context.rules.vertLayer ELSE context.rules.horizLayer; routerParams: PWRoute.RouterParams _ NEW[PWRoute.RouterParamsRec _ [trunkLayer: trunkLayer, branchLayer: branchLayer, technologyKey: technologyKey, makeTabKeyProc: KeyFromProperty, signalBreakAtExit: FALSE, signalSinglePinNets: FALSE, viaTable: table]]; GCPrivate.AssignCoordinates[context]; SELECT TRUE FROM channel.ch = bottomChannel => { channel.topOrRightShell _ MakeSide[context, channel, top, TRUE]; channel.bottomOrLeftShell _ MakeSide[context, channel, bottom, FALSE]}; channel.ch = rightChannel => { channel.bottomOrLeftShell _ MakeSide[context, channel, left, TRUE]; channel.topOrRightShell _ MakeSide[context, channel, right, FALSE]}; channel.ch = topChannel => { channel.bottomOrLeftShell _ MakeSide[context, channel, bottom, TRUE]; channel.topOrRightShell _ MakeSide[context, channel, top, FALSE]}; channel.ch = leftChannel => { channel.topOrRightShell _ MakeSide[context, channel, right, TRUE]; channel.bottomOrLeftShell _ MakeSide[context, channel, left, FALSE]}; ENDCASE => { channel.bottomOrLeftShell _ MakeSide[context, channel, ChanSide[channel, bottom], TRUE]; channel.topOrRightShell _ MakeSide[context, channel, ChanSide[channel, top], TRUE]}; channel.bottomOrLeftExitShell _ MakeEnd[context, channel, ChanSide[channel, left]]; channel.topOrRightExitShell _ MakeEnd[context, channel, ChanSide[channel, right]]; channel.result _ PWRoute.DoRoute[channel.bottomOrLeftShell, channel.topOrRightShell, channel.bottomOrLeftExitShell, channel.topOrRightExitShell, routerParams, channel.direction # horizontal, channel]; channel.cdObject _ PWRoute.GetRouting[channel.result, NIL]; channel.width _ IF channel.direction = horizontal THEN CDBasics.SizeOfRect[channel.result.routingRect].y ELSE CDBasics.SizeOfRect[channel.result.routingRect].x; channel.chanShell _ BuildChannelShell[context, channel]; IPCTG.SetWidth[channel.ch, channel.width]}; IncludeChannel: GCPrivate.EachChannelAction ~ { IF channel.cdObject # NIL THEN { chanInst: CD.Instance; chanInst _ GCPrivate.IncludeOb[cell: object, ob: channel.cdObject, position: channel.position]; CDProperties.PutInstanceProp[chanInst, $InstanceName, Rope.Cat["Channel", channel.name]]}; SELECT TRUE FROM channel.ch = bottomChannel => { topPos: CD.Position _ [channel.position.x, channel.position.y + channel.width]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: topPos]}; channel.ch = rightChannel => { bottomPos: CD.Position _ [channel.position.x - CD.InterestSize[channel.bottomOrLeftShell].x, channel.position.y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: bottomPos]}; channel.ch = topChannel => { bottomPos: CD.Position _ [channel.position.x, channel.position.y - CD.InterestSize[channel.bottomOrLeftShell].y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: bottomPos]}; channel.ch = leftChannel => { topPos: CD.Position _ [channel.position.x + channel.width, channel.position.y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: topPos]}; ENDCASE => { topPos: CD.Position _ IF channel.direction = horizontal THEN [channel.position.x, channel.position.y + channel.width] ELSE [channel.position.x + channel.width, channel.position.y]; bottomPos: CD.Position _ IF channel.direction = horizontal THEN [channel.position.x, channel.position.y - CD.InterestSize[channel.bottomOrLeftShell].y] ELSE [channel.position.x - CD.InterestSize[channel.bottomOrLeftShell].x, channel.position.y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: topPos]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: bottomPos]}}; IncludeInstance: RTStructure.EachInstanceAction ~ { IF instance.object.cdObject # NIL THEN { cdInst: CD.Instance _ GCPrivate.IncludeOb[cell: object, ob: instance.object.cdObject, position: instance.position, orientation: instance.orientation]; CDProperties.PutInstanceProp[cdInst, $InstanceName, instance.name]}}; topology: IPTop.Ref _ NARROW[context.topology]; bottomChannel, rightChannel, topChannel, leftChannel: IPCTG.Channel; object: CD.Object _ CDCells.CreateEmptyCell[]; table: HashTable.Table _ IF context.parms.viaTable # NIL THEN context.parms.viaTable ELSE HashTable.Create[equal: EqualProc, hash: HashProc]; [bottomChannel, rightChannel, topChannel, leftChannel] _ IPCTG.GetBoundingChannels[topology.ctg]; [] _ GCPrivate.EnumerateChannelsInTopologicalOrder[context, MakeChannel]; GCPrivate.AssignCoordinates[context]; [] _ GCPrivate.EnumerateChannelsInTopologicalOrder[context, IncludeChannel]; [] _ RTStructure.EnumerateInstances[context.structure, IncludeInstance]; RTBasic.RepositionCell[object]; RTBasic.SetCDCellName[object, context.name]; result _ NEW[GC.ResultRec _ [context: context, object: object]]}; MakeSide: PROC [context: GC.Context, channel: GCPrivate.Channel, side: RTBasic.Side, internal: BOOLEAN] RETURNS [shell: CD.Object _ CDCells.CreateEmptyCell[]] ~ { DoExternalPins: IPCTG.EachComponentAction ~ { IF co # NIL THEN { EachInstancePin: RTStructure.EachInstancePinAction ~ { EachPhysicalPin: RTStructure.EachPhysicalPinAction ~ { IF pPin.side = otherSide AND internal OR pPin.side = side AND ~internal THEN { netDesc: GCPrivate.NetDesc _ NARROW[HashTable.Fetch[channel.connections, iPin.net].value]; phyPin: GCPrivate.PhyPinDesc _ NEW[GCPrivate.PhyPinDescRec _ [instance, iPin.oPin, pPin]]; tabIndex: Rope.ROPE _ IF GCPrivate.PinOnList[netDesc, phyPin] THEN iPin.net.name ELSE Rope.Cat[iPin.net.name, "@", instance.name, "@", Convert.RopeFromInt[pPin.range.min]]; maxWidth _ MAX[maxWidth, IncludePin[NEW[GCPrivate.PhyPinDescRec _ [instance, iPin.oPin, pPin]], iPin.net.name, tabIndex, side, pinWidth, lower, upper, shell]]}}; IF ExternalNet[context, iPin.net.name] THEN [] _ RTStructure.EnumeratePhysicalPins[iPin.oPin, EachPhysicalPin]}; instance: RTStructure.Instance _ NARROW[co.any]; [] _ RTStructure.EnumerateInstancePins[instance, EachInstancePin]}}; EachNet: HashTable.EachPairAction ~ { netDesc: GCPrivate.NetDesc _ NARROW[value]; FOR list: LIST OF GCPrivate.PhyPinDesc _ netDesc.pinList, list.rest WHILE list # NIL DO net: RTStructure.Net _ NARROW[key]; exteriorPublic: BOOLEAN _ IPCTG.IsBoundingChannel[topology.ctg, channel.ch] AND ExternalNet[context, net.name]; -- public pins (on next higher cell) are already included IF list.first.pPin.side = otherSide AND ~exteriorPublic THEN maxWidth _ MAX[maxWidth, IncludePin[list.first, net.name, net.name, side, pinWidth, lower, upper, shell]]; ENDLOOP; }; DoChannelIntersection: IPCTG.EachIntersectionAction ~ { EachExit: PWPins.InstanceEnumerator ~ { netName: Rope.ROPE _ CDSymbolicObjects.GetName[inst]; pinSide: RTBasic.Side _ RTStructure.FromSideToSide[PWPins.GetSide[otherChannel.chanShell, inst].side]; IF (internal AND pinSide = otherSide) OR (~internal AND ExternalNet[context, netName] AND pinSide = side) THEN { range: RTStructure.Range _ RTStructure.CoordsAlongSide[inst, otherChannel.chanShell, otherSide]; layer: CD.Layer _ CDSymbolicObjects.GetLayer[inst]; pinOb: CD.Object _ CDSymbolicObjects.CreateSegment[range.max - range.min, pinWidth]; pinLoc: CD.Position _ SELECT side FROM top => [otherChannel.position.x + range.min, upper.q], left => [lower.q - pinWidth, otherChannel.position.y + range.min], bottom => [otherChannel.position.x + range.min, lower.q - pinWidth], right => [upper.q, otherChannel.position.y + range.min], ENDCASE => GC.Error[programmingError, "Call maintainer"]; pinInst: CD.Instance _ GCPrivate.IncludeOb[shell, pinOb, pinLoc, SideToOrientation[side]]; CDSymbolicObjects.SetName[pinInst, netName]; CDSymbolicObjects.SetLayer[pinInst, layer]; }}; otherChannel: GCPrivate.Channel _ NARROW[i.ch.any]; IF otherChannel.chanShell # NIL THEN [] _ PWPins.EnumerateEdgePins[otherChannel.chanShell, EachExit]}; rect: CD.Rect; pinWidth: INT _ IF channel.direction = horizontal THEN context.rules.horizRules.branchWidth ELSE context.rules.vertRules.branchWidth; maxWidth: INT _ pinWidth; otherSide: RTBasic.Side _ RTBasic.OtherSide[side]; name: Rope.ROPE _ Rope.Cat[context.name, "Channel", channel.name, RTBasic.sideName[side]]; bottomOrLeft: BOOLEAN _ side = bottom OR side = left; topOrRight: BOOLEAN _ ~bottomOrLeft; polarity: IP.PolarityTypes _ IF (internal AND bottomOrLeft) OR (~internal AND topOrRight) THEN neg ELSE pos; lower: RTBasic.PQPos _ GCPrivate.LowerChannelPQ[channel]; upper: RTBasic.PQPos _ GCPrivate.UpperChannelPQ[channel]; topology: IPTop.Ref _ NARROW[context.topology]; IF IPCTG.IsBoundingChannel[topology.ctg, channel.ch] THEN [] _ IPCTG.Components[channel.ch, polarity, DoExternalPins]; [] _ HashTable.Pairs[channel.connections, EachNet]; [] _ IPCTG.Intersections[channel.ch, polarity, DoChannelIntersection]; IF channel.lowerIntType = inverted THEN [] _ DoChannelIntersection[IPCTG.End[channel.ch, neg]]; IF channel.upperIntType = inverted THEN [] _ DoChannelIntersection[IPCTG.End[channel.ch, pos]]; rect _ SELECT side FROM bottom => [lower.p, lower.q - maxWidth, upper.p, lower.q], right => [upper.q, lower.p, upper.q + maxWidth, upper.p], top => [lower.p, upper.q, upper.p, upper.q + maxWidth], left => [lower.q - maxWidth, lower.p, lower.q, upper.p], ENDCASE => GC.Error[programmingError, "Call maintainer"]; CDCells.SetInterestRect[design: NIL, cell: shell, r: rect]; -- set interestRect of shell RTBasic.SetCDCellName[shell, name]; RTBasic.RepositionCell[shell]; }; MakeEnd: PROC [context: GC.Context, channel: GCPrivate.Channel, side: RTBasic.Side] RETURNS [shell: CD.Object _ NIL] ~ { EachNet: HashTable.EachPairAction ~ { netDesc: GCPrivate.NetDesc _ NARROW[value]; net: RTStructure.Net _ NARROW[key]; publicNet: BOOLEAN _ RTStructure.IsPublic[net]; needsExit: BOOLEAN _ (side = bottom OR side = left) AND netDesc.bottomOrLeftExit OR (side = top OR side = right) AND netDesc.topOrRightExit; IF needsExit AND (ordinaryIntersection OR publicNet) THEN { width: INT _ IF context.structure.netWidth = NIL THEN pinWidth ELSE MAX[pinWidth, context.structure.netWidth[net, context.structure, channel.direction, NIL]]; pinOb: CD.Object _ CDSymbolicObjects.CreateSegment[width, pinWidth]; pinLoc: CD.Position _ SELECT side FROM top => [last, 0], left => [pinWidth, last], bottom => [last, pinWidth], right => [0, last], ENDCASE => GC.Error[programmingError, "Call maintainer"]; pinInst: CD.Instance _ GCPrivate.IncludeOb[shell, pinOb, pinLoc, SideToOrientation[side]]; CDSymbolicObjects.SetLayer[pinInst, layer]; CDSymbolicObjects.SetName[pinInst, net.name]; last _ last + width + pinWidth}; }; ordinaryIntersection: BOOLEAN _ (channel.lowerIntType = normal AND (side = left OR side = bottom)) OR (channel.upperIntType = normal AND (side = right OR side = top)); otherSide: RTBasic.Side _ RTBasic.OtherSide[side]; name: Rope.ROPE _ Rope.Cat[context.name, "/Channel:", channel.name, RTBasic.sideName[side]]; layer: CD.Layer; pinWidth, last: INT; rect: CD.Rect; shell _ CDCells.CreateEmptyCell[]; IF channel.direction = horizontal THEN { layer _ context.rules.horizRules.trunkLayer; last _ pinWidth _ context.rules.horizRules.trunkWidth} ELSE { layer _ context.rules.vertRules.trunkLayer; last _ pinWidth _ context.rules.vertRules.trunkWidth}; [] _ HashTable.Pairs[channel.connections, EachNet]; rect _ SELECT side FROM bottom, top => [0, 0, last, 2*pinWidth], left, right => [0, 0, 2*pinWidth, last], ENDCASE => GC.Error[programmingError, "Call maintainer"]; CDCells.SetInterestRect[design: NIL, cell: shell, r: rect]; -- set interestRect of cell RTBasic.SetCDCellName[shell, name]; RTBasic.RepositionCell[shell]}; SideToOrientation: PROC [side: RTBasic.Side] RETURNS [orientation: CD.Orientation] ~ { orientation _ SELECT side FROM top => CDSymbolicObjects.OrientFromDirection[south], left => CDSymbolicObjects.OrientFromDirection[east], bottom => CDSymbolicObjects.OrientFromDirection[north], right => CDSymbolicObjects.OrientFromDirection[west], ENDCASE => GC.Error[programmingError, "Call maintainer"]}; ChanSide: PROC [channel: GCPrivate.Channel, side: RTBasic.Side] RETURNS [sideToUse: RTBasic.Side] ~ { sideToUse _ IF channel.direction = horizontal THEN side ELSE SELECT side FROM bottom => left, right => top, top => right, left => bottom, ENDCASE => GC.Error[programmingError, "Call maintainer"]}; ExternalNet: PROC [context: GC.Context, netName: Rope.ROPE] RETURNS [isExternal: BOOLEAN _ FALSE] ~ { EachInstancePin: RTStructure.EachInstancePinAction ~ { quit _ Rope.Equal[netName, iPin.net.name]}; IF context.structure.outerInstance # NIL THEN isExternal _ RTStructure.EnumerateInstancePins[context.structure.outerInstance, EachInstancePin]}; IncludePin: PROC [phyPin: GCPrivate.PhyPinDesc, name, tabIndex: Rope.ROPE, side: RTBasic.Side, pinWidth: INT, lower, upper: RTBasic.PQPos, shell: CD.Object] RETURNS[width: INT]~ { instance: RTStructure.Instance _ phyPin.instance; pPin: RTStructure.PhysicalPin _ phyPin.pPin; range: RTStructure.Range _ RTStructure.TranslateRange[instance, pPin]; rangeSize: INT _ range.max - range.min; pinOb: CD.Object _ CDSymbolicObjects.CreateSegment[rangeSize, pinWidth]; wireLoc, wireSize, pinLoc: CD.Position; pinInst: CD.Instance; SELECT side FROM top => { width _ instance.position.y - upper.q + pPin.depth; wireSize _ [rangeSize, width]; wireLoc _ [range.min, upper.q]; pinLoc _ [range.min, upper.q]; }; left => { sidePos: INT _ instance.position.x + CD.InterestSize[instance.object.cdObject].x; width _ lower.q - sidePos + pPin.depth; wireSize _ [width, rangeSize]; wireLoc _ [sidePos - pPin.depth, range.min]; pinLoc _ [lower.q - pinWidth, range.min]; }; bottom => { sidePos: INT _ instance.position.y + CD.InterestSize[instance.object.cdObject].y; width _ lower.q - sidePos + pPin.depth; wireSize _ [rangeSize, width]; wireLoc _ [range.min, sidePos - pPin.depth]; pinLoc _ [range.min, lower.q - pinWidth]; }; right => { width _ instance.position.x - upper.q + pPin.depth; wireSize _ [width, rangeSize]; wireLoc _ [upper.q, range.min]; pinLoc _ [upper.q, range.min]; }; ENDCASE; IF width # 0 THEN { wire: CD.Object _ CDRects.CreateRect[wireSize, pPin.layer]; [] _ GCPrivate.IncludeOb[cell: shell, ob: wire, position: wireLoc]}; pinInst _ GCPrivate.IncludeOb[shell, pinOb, pinLoc, SideToOrientation[side]]; CDSymbolicObjects.SetName[pinInst, name]; CDSymbolicObjects.SetLayer[pinInst, pPin.layer]; CDProperties.PutInstanceProp[pinInst, GCPrivate.nameProp, tabIndex]}; BuildChannelShell: PROC [context: GC.Context, channel: GCPrivate.Channel] RETURNS [shell: CD.Object _ CDCells.CreateEmptyCell[]] ~ { ChanPublics: CoreGeometry.EachWirePinProc ~ { name: Rope.ROPE _ CoreOps.GetShortWireName[wire]; SELECT side FROM bottom => AddPinToShell[object: shell, name: name, denotes: [rect.x1+min, rect.y1, rect.x1+max, rect.y1+depth], layer: layer]; right => AddPinToShell[object: shell, name: name, denotes: [rect.x2-depth, rect.y1+min, rect.x2, rect.y1+max], layer: layer]; top => AddPinToShell[object: shell, name: name, denotes: [rect.x1+min, rect.y2-depth, rect.x1+max, rect.y2], layer: layer]; left => AddPinToShell[object: shell, name: name, denotes: [rect.x1, rect.y1+min, rect.x1+depth, rect.y1+max], layer: layer]; ENDCASE}; mode: Sinix.Mode = SinixOps.GetExtractMode[context.rules.technology]; cellType: Core.CellType _ NARROW [Sinix.Extract[channel.cdObject, mode].result]; depth: Route.Number _ context.rules.horizRules.trunkWidth; rect: CD.Rect _ CD.InterestRect[channel.cdObject]; [] _ CoreGeometry.EnumerateNonOverlappingSides[mode.decoration, cellType, ChanPublics]; CDCells.SetInterestRect[design: NIL, cell: shell, r: rect]; RTBasic.RepositionCell[shell]}; AddPinToShell: PROC [object: CD.Object, name: Rope.ROPE, denotes: CD.Rect, layer: CD.Layer] ~ { pin: CD.Object _ CDSymbolicObjects.CreatePin[CDBasics.SizeOfRect[denotes]]; pinInstance: CD.Instance _ GCPrivate.IncludeOb[cell: object, ob: pin, position: CDBasics.BaseOfRect[denotes], orientation: original]; CDSymbolicObjects.SetName[pinInstance, name]; CDSymbolicObjects.SetLayer[pinInstance, layer]}; EqualProc: PROC [k1, k2: HashTable.Key] RETURNS [eq: BOOL] = { p1: Route.Position _ NARROW[k1, REF Route.Position]^; p2: Route.Position _ NARROW[k2, REF Route.Position]^; eq _ p1.x = p2.x AND p1.y = p2.y}; HashProc: PROC [k: HashTable.Key] RETURNS [hash: CARDINAL] = { size: Route.Position _ NARROW[k, REF Route.Position]^; hash _ size.x + size.y}; }. VGCDetailRouteImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bryan Preas, February 19, 1987 9:06:53 pm PST PROC[pinInst: CD.Instance, context: REF ANY _ NIL] RETURNS [tabIndex: ROPE]; Determine actual wiring paths. PROC[context: GC.Context, channel: Channel] RETURNS [quit: BOOLEAN _ FALSE]; construct a channel PROC[context: GC.Context, channel: Channel] RETURNS [quit: BOOLEAN _ FALSE]; Include a previously routed channel into the object being constructed first the channel RTBasic.SetCDCellName[channel.cdObject, Rope.Cat[context.name, "Channel", channel.name]]; next include the cells containing the wires to get from the channel edges to cells PROC [key: Key, instance: Instance] RETURNS [quit: BOOLEAN _ FALSE]; include an instance in the object being constructed construct a shell for the side of a channel PROC [key: Key, instance: Instance, iPin: InstancePin] RETURNS [quit: BOOLEAN _ FALSE]; PROC [oPin: ObjectPin, pPin: PhysicalPin] RETURNS [quit: BOOLEAN _ FALSE]; PROC[i: Intersection] RETURNS[quit: BOOL _ FALSE]; [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] construct the end object of a channel PROC [key: Key, value: Value] RETURNS [quit: BOOLEAN _ FALSE]; translate a side to an orientation determine if the net corresponds to a public wire PROC [key: Key, instance: Instance, iPin: InstancePin] RETURNS [quit: BOOLEAN _ FALSE]; include a pin in a shell; also extend a wire if necessary build a PWPins shell for the channel PROC [wire: Wire, min, max: INT, side: Side, layer: CD.Layer] RETURNS [quit: BOOL _ FALSE]; add decoration for public; wire is an unbound wire Κ5– "cedar" style˜codešœ™Kšœ Οmœ1™˜Ζšžœ˜K˜—K˜šŸœ˜+Kšžœ žœžœžœžœžœ žœ™LKšœžœ=˜EKšœ žœžœžœ#˜?Kšžœžœ˜K˜K˜—š Ÿ œžœžœ žœ žœ žœ ˜Pšœ™K™—šŸ œ!˜,š žœ žœžœžœžœ™LKšœ™K˜—Kšœžœžœžœ˜JKš œžœžœ žœžœ˜uKš œžœžœ žœžœ˜vKšœ%žœ žœžœ˜ύKšœ%˜%šžœžœž˜šœ˜Kšœ:žœ˜@Kšœ?žœ˜G—šœ˜Kšœ=žœ˜CKšœ<žœ˜D—šœ˜Kšœ?žœ˜EKšœ:žœ˜B—šœ˜Kšœ<žœ˜BKšœ=žœ˜E—šžœ˜ KšœRžœ˜XKšœNžœ˜U——KšœS˜SKšœR˜RKšœΘ˜ΘKšœ6žœ˜;šœžœ žœ2˜hKšžœ3˜7—Kšœ8˜8Kšžœ&˜+K˜—šŸœ!˜/š žœ žœžœžœžœ™LKšœE™EK˜—Kšœ™šžœžœžœ˜ Kšœ žœ ˜Kšœ_˜_KšœY™YKšœZ˜Z—K˜KšœR™Ršžœžœž˜šœ˜KšœžœE˜OKšœX˜X—šœ˜Kšœ žœ"žœ@˜qKšœ]˜]—šœ˜Kšœ žœ6žœ,˜qKšœ]˜]—šœ˜KšœžœE˜OKšœX˜X—šžœ˜ šœžœ žœ žœ9˜uKšžœ;˜?—š œ žœ žœ žœ+žœ+˜—Kšžœžœ@˜^—KšœW˜WKšœ^˜^——K˜—šŸœ$˜3šžœ žœžœžœ™DKšœ3™3—šžœžœžœ˜(KšœžœŒ˜–KšœE˜E—K˜—Kšœžœ˜/Kšœ6žœ ˜DKšœžœ$˜.Kš œžœžœžœžœ4˜Kšœ9žœ#˜aK˜IKšœ%˜%K˜LKšœH˜HKšœ˜Kšœ,˜,Kšœ žœžœ2˜AK˜—š Ÿœžœ žœDžœžœ žœ(˜’Kšœ+™+K˜šŸœžœ˜-šžœžœžœ˜K˜šŸœ'˜6Kšžœ3žœžœžœ™WšŸœ'˜6Kšžœ&žœžœžœ™Jš žœžœ žœžœ žœ˜NKšœžœ7˜ZKšœžœ8˜Zšœžœžœ&žœ˜CKšœ ˜ KšžœW˜[—Kšœ žœžœz˜‘—K˜—šžœ%ž˜+KšœD˜D—K˜—Kšœ"žœ ˜1KšœD˜D—K˜—šŸœ˜%Kšœžœ˜+š žœžœžœ3žœžœž˜WKšœžœ˜#Kšœžœžœ-žœ!Οc9˜©šžœ"žœž˜K˜Kšœžœ˜+Kšœžœ˜#Kšœ žœ˜/Kš œ žœžœžœžœ žœžœ˜Œšžœ žœžœ žœ˜;š œžœžœžœžœ ˜>KšžœžœQžœ˜_—Kšœžœ;˜Dšœžœ žœž˜&Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ,˜9—Kšœ žœO˜ZKšœ+˜+Kšœ-˜-Kšœ ˜ —K˜K˜—Kš œžœ"žœžœžœ žœžœ˜§Kšœ2˜2Kšœ žœM˜\Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜Kšœ"˜"šžœ žœ˜(Kšœ,˜,Kšœ6˜6—šžœ˜Kšœ+˜+Kšœ6˜6K˜—Kšœ3˜3šœžœž˜Kšœ(˜(Kšœ(˜(Kšžœžœ,˜9—Kšœ žœ ˜WKšœ#˜#Kšœ˜K˜—šŸœžœžœžœ˜VKšœ"™"K˜šœžœž˜Kšœ4˜4Kšœ4˜4Kšœ7˜7Kšœ5˜5Kšžœžœ-˜:—K˜—šŸœžœ2žœ˜ešœ žœ žœ˜7šžœžœž˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšžœžœ-˜:——K˜—šŸ œžœ žœžœžœžœžœ˜eKšœ1™1K˜šŸœ'˜6Kšžœ3žœžœžœ™WKšœ+˜+K˜—šžœ$žœž˜.Kšœb˜b—K˜—šŸ œžœ5žœ žœ&žœ žœžœ˜³Kšœ9™9K˜Kšœ1˜1Kšœ,˜,KšœF˜FKšœ žœ˜'Kšœžœ?˜HKšœžœ ˜'Kšœ žœ ˜šžœž˜šœ˜Kšœ3˜3Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœ ˜ Kšœ žœžœ*˜QKšœ'˜'Kšœ˜Kšœ,˜,Kšœ)˜)Kšœ˜—šœ ˜ Kšœ žœžœ*˜QKšœ'˜'Kšœ˜Kšœ,˜,Kšœ)˜)Kšœ˜—šœ ˜ Kšœ3˜3Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜—šžœ žœ˜Kšœžœ3˜;KšœD˜D—KšœM˜MKšœ)˜)Kšœ0˜0KšœE˜EK˜—š Ÿœžœ žœ&žœ žœ(˜„Kšœ$™$K˜šŸ œ"˜-Kš žœžœžœžœžœžœ™[Kšœ2™2Kšœ žœ"˜1šžœž˜Kšœ~˜~Kšœ}˜}Kšœ{˜{Kšœ|˜|Kšžœ˜ —K˜—JšœE˜EJšœžœ0˜PKšœ:˜:Kšœžœžœ ˜2KšœW˜WKšœ žœ˜;Kšœ˜K˜—š Ÿ œžœ žœžœ žœžœ ˜_K˜KšœžœD˜KKšœ žœv˜…Kšœ-˜-Kšœ0˜0K˜—šŸ œžœžœžœ˜>Kšœžœžœ˜5Kšœžœžœ˜5Kšœžœ˜"K˜—šŸœžœžœžœ˜>Kšœžœžœ˜6Kšœ˜—Kšœ˜—K˜K˜K˜K˜—…—D"Y­