DIRECTORY CD, CDBasics, CDInstances, CDProperties, CDRects, CDRoutingObjects, CDSimpleRules, CMosB, Core, CoreClasses, CoreCreate, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PW, PWCore, Rope, Route, Sisyph, SymTab, TerminalIO; CoreRouteExtend: CEDAR PROGRAM IMPORTS CD, CDBasics, CDInstances, CDProperties, CDRects, CDRoutingObjects, CDSimpleRules, CMosB, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PW, PWCore, Rope, Sisyph, SymTab, TerminalIO = BEGIN ExtendForm: TYPE = REF ExtendFormAry; ExtendFormAry: TYPE = RECORD[ vert: CD.Layer _ CD.commentLayer, sameLayers: BOOL _ TRUE, ary: ARRAY Side OF ExtendFormRec ]; ExtendFormRec: TYPE = RECORD[ pins: WirePins _ NIL, min: INT _ LAST[INT], max: INT _ FIRST[INT], width: INT _ 0, wires: Wires _ NIL, buses: Wires _ NIL, busLo: Wires _ NIL, busHi: Wires _ NIL]; BusRec: TYPE = RECORD[ loc: INT _ 0, width: INT _ 0, min: INT _ LAST[INT], max: INT _ FIRST[INT]]; Wires: TYPE = Core.Wires; WirePin: TYPE = CoreRoute.WirePin; WirePins: TYPE = CoreRoute.WirePins; Side: TYPE = CoreGeometry.Side; extendFormProp: ATOM = $ExtendForm; verticalMetalProp: ATOM = $VerticalMetal; changeLayersProp: ATOM = $ChangeLayers; wireWidthProp: ATOM = $w; technologyKey: ATOM = $cmosB; lambda: INT _ CDSimpleRules.GetTechnology[technologyKey].lambda; L4: INT _ 4*lambda; layDeco: CoreGeometry.Decoration _ PWCore.extractMode.decoration; schDeco: CoreGeometry.Decoration _ Sisyph.mode.decoration; sideProp: ARRAY Side OF ATOM _ [bottom: $Bottom, top: $Top, left: $Left, right: $Right]; sizeProp: ARRAY Side OF ATOM _ [bottom: $SizeY, top: $SizeY, left: $SizeX, right: $SizeX]; Attribute: PWCore.AttributesProc = { SchSideWires: PROC[side: Side, min: INT _ FIRST[INT], max: INT _ LAST[INT]] RETURNS [wires: Core.Wires] = {RETURN[CoreRoute.OrderedAtomicSchWires[cellType, side, min, max]]}; AddTopOrBottomEnds: PROC[topBot, ltRt: Side] = { buses: Wires _ IF topBot=top THEN form.ary[ltRt].busHi ELSE form.ary[ltRt].busLo; IF form.ary[topBot].width=0 THEN RETURN; FOR buses _ buses, buses.rest WHILE buses#NIL DO rec: REF BusRec _ EnsureBusSideRec[buses.first, ltRt]; loc: INT _ IF ltRt=left THEN 0 - rec.width - rec.loc ELSE subSize.x + rec.loc; pin: WirePin _ [buses.first, loc, loc+rec.width, form.vert]; form.ary[topBot].pins _ CONS[pin, form.ary[topBot].pins]; ENDLOOP}; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; form: ExtendForm _ NEW[ExtendFormAry _[vert:CD.commentLayer]]; subInst: CoreCreate.CellInstance _ data[0]; subObj: CD.Object _ PWCore.Layout[subInst.type]; subSize: CD.Position _ CD.InterestSize[subObj]; globals: Wires _ CoreRoute.GlobalWires[cellType]; pIR: CD.Rect _ CD.InterestRect[CoreGeometry.GetObject[schDeco, cellType]]; cIR: CD.Rect _ CoreRoute.SchMappedIR[subInst]; form.ary[left].busLo _ SchSideWires[bottom, , cIR.x1-pIR.x1 ]; form.ary[left].busHi _ SchSideWires[top, , cIR.x1-pIR.x1 ]; form.ary[right].busLo _ SchSideWires[bottom, cIR.x2-pIR.x1, ]; form.ary[right].busHi _ SchSideWires[top, cIR.x2-pIR.x1, ]; form.ary[bottom].busLo _ SchSideWires[left, , cIR.y1-pIR.y1 ]; form.ary[bottom].busHi _ SchSideWires[right, , cIR.y1-pIR.y1 ]; form.ary[top].busLo _ SchSideWires[left, cIR.y2-pIR.y1, ]; form.ary[top].busHi _ SchSideWires[right, cIR.y2-pIR.y1, ]; form.vert _ CoreRoute.GetCellTypePropLayer[cellType, verticalMetalProp].layer; form.sameLayers _ CoreProperties.GetCellTypeProp[cellType, changeLayersProp]=NIL; FOR side: Side IN Side DO min: INT _ IF LeftRight[side] THEN cIR.y1-pIR.y1 ELSE cIR.x1-pIR.x1; max: INT _ IF LeftRight[side] THEN cIR.y2-pIR.y1 ELSE cIR.x2-pIR.x1; wires: Wires _ CoreRoute.OrderedAtomicSchWires[cellType, side, min, max]; form.ary[side].wires _ wires; form.ary[side].buses _ MergeOrderedWires[form.ary[side].busLo, form.ary[side].busHi]; FOR buses: Wires _ form.ary[side].buses, buses.rest WHILE buses#NIL DO rec: REF BusRec _ EnsureBusSideRec[buses.first, side]; wires _ CONS[buses.first, wires] ENDLOOP; form.ary[side].pins _ CoreRoute.FilteredInstanceLayoutPins[subInst, side]; form.ary[side].pins _ CoreRoute.FilterPins[form.ary[side].pins, wires, globals]; IF ~form.sameLayers AND form.ary[side].buses#NIL AND form.ary[side].buses.rest#NIL THEN ERROR; ENDLOOP; FOR side: Side IN Side DO VertLayer: PROC[sideLayer: CD.Layer] RETURNS[vertLayer: CD.Layer] = {RETURN [IF LeftRight[side] # form.sameLayers THEN sideLayer ELSE OtherLayer[sideLayer]]}; w: INT _ GetSideExtention[cellType, side]; strangeLayerFound: BOOL _ FALSE; IF w=0 AND form.sameLayers THEN LOOP; IF ~form.sameLayers THEN AdjustPins345[form.ary[side].pins]; -- 3, 4, 5 => 4 lambda FOR pins: WirePins _ form.ary[side].pins, pins.rest WHILE pins#NIL DO pin: WirePin _ pins.first; sideLayer: CD.Layer _ pin.layer; busRec: REF BusRec _ ExistingBusSideRec[pin.wire, side]; IF NOT MetLayer[sideLayer] THEN { IF NOT strangeLayerFound THEN TerminalIO.PutF["*** %g side of %g has strange pin layer.\n", IO.rope[SideNm[side]], IO.rope[CoreOps.GetCellTypeName[cellType]]]; strangeLayerFound _ TRUE} ELSE { IF form.vert=CD.commentLayer OR form.vert=VertLayer[sideLayer] THEN form.vert _ VertLayer[sideLayer] ELSE TerminalIO.PutF["*** %g side of %g has inconsistent pin layer.\n", IO.rope[SideNm[side]], IO.rope[CoreOps.GetCellTypeName[cellType]]]; IF busRec#NIL THEN busRec.width _ MAX[busRec.width, pin.max-pin.min]}; ENDLOOP ENDLOOP; IF NOT MetLayer[form.vert] THEN ERROR; FOR side: Side IN Side DO FOR buses: Wires _ form.ary[side].buses, buses.rest WHILE buses#NIL DO w: REF INT _ NARROW[CoreProperties.GetWireProp[buses.first, wireWidthProp]]; rec: REF BusRec _ EnsureBusSideRec[buses.first, side]; rec.width _ IF w#NIL THEN w^*lambda ELSE 4*lambda ENDLOOP ENDLOOP; FOR side: Side IN Side DO w: INT _ GetSideExtention[cellType, side]; buses: Wires _ form.ary[side].buses; IF side=left OR side=bottom THEN buses _ CoreOps.Reverse[buses]; form.ary[side].width _ IF ~form.sameLayers THEN 3*L4 ELSE IF form.ary[side].buses=NIL THEN 0 ELSE L4; FOR buses _ buses, buses.rest WHILE buses#NIL DO rec: REF BusRec _ EnsureBusSideRec[buses.first, side]; rec.loc _ form.ary[side].width; form.ary[side].width _ form.ary[side].width + rec.width + L4 ENDLOOP; IF w#0 THEN { size: INT _ w*lambda; IF size < form.ary[side].width THEN TerminalIO.PutF["*** Warning: %g side Extend of %g Needs %g but was specified as %g.", IO.rope[SideNm[side]], IO.rope[name], IO.int[form.ary[side].width/lambda], IO.int[w]] ELSE form.ary[side].width_size}; form.ary[side].min _ 0; form.ary[side].max _ IF LeftRight[side] THEN subSize.y ELSE subSize.x; ENDLOOP; IF form.ary[top].width#0 THEN { form.ary[top].min _ form.ary[top].min - form.ary[left].width; form.ary[top].max _ form.ary[top].max + form.ary[right].width}; IF form.ary[bottom].width#0 THEN { form.ary[bottom].min _ form.ary[bottom].min - form.ary[left].width; form.ary[bottom].max _ form.ary[bottom].max + form.ary[right].width}; AddTopOrBottomEnds[top, left]; AddTopOrBottomEnds[top, right]; AddTopOrBottomEnds[bottom, left]; AddTopOrBottomEnds[bottom, right]; FOR side: Side IN Side DO IF form.ary[side].width=0 THEN LOOP; FOR pins: WirePins _ form.ary[side].pins, pins.rest WHILE pins#NIL DO pin: WirePin _ pins.first; busRec: REF BusRec _ ExistingBusSideRec[pin.wire, side]; IF NOT MetLayer[pin.layer] THEN LOOP; IF busRec#NIL THEN { busRec.min _ MIN[busRec.min, pin.min]; busRec.max _ MAX[busRec.max, pin.max]} ENDLOOP ENDLOOP; FOR side: Side IN Side DO FOR buses: Wires _ form.ary[side].busLo, buses.rest WHILE buses#NIL DO EnsureBusSideRec[buses.first, side].min _ form.ary[side].min ENDLOOP; FOR buses: Wires _ form.ary[side].busHi, buses.rest WHILE buses#NIL DO EnsureBusSideRec[buses.first, side].max _ form.ary[side].max ENDLOOP ENDLOOP; CoreRoute.FlushSchPinCache[subInst.type]; CoreRoute.FlushLayPinCache[subInst.type]; CoreProperties.PutCellTypeProp[cellType, extendFormProp, form]; ShowExtendForm[cellType]}; Layout: PWCore.LayoutProc = { name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; form: ExtendForm _ NARROW[ CoreProperties.GetCellTypeProp[cellType, extendFormProp]]; resultIR: CD.Rect; subObj: CD.Object _ PWCore.Layout[data[0].type]; subSize: CD.Position _ CD.InterestSize[subObj]; cdInstances: CD.InstanceList _ LIST [CDInstances.NewInst[ ob: subObj, trans: [CDBasics.NegOffset[CD.InterestBase[subObj]]] ]]; FOR side: Side IN Side DO AddRect: PROC [wire: Core.Wire, size: CD.Position, lay: CD.Layer, off, min: INT] = { rect: CD.Object; IF ~LeftRight[side] THEN size _ [size.y, size.x]; rect _ CDRects.CreateRect[size, lay]; AddPositionedObject[wire, rect, off, min]}; AddVias: PROC [wire: Core.Wire, size: CD.Position, off, min: INT] = { vias: CD.Object _ IF LeftRight[side] THEN Vias[size.x, size.y] ELSE Vias[size.y, size.x]; AddPositionedObject[wire, vias, off, min]}; AddPositionedObject: PROC[wire: Core.Wire, obj: CD.Object, off, min: INT] = { label: Route.Label _ CoreRoute.LabelInternal[data.internal, wire]; pos: REF LIST OF CDRoutingObjects.PlacedObject _ NARROW[SymTab.Fetch[nodes, label].val]; szX: INT _ CD.InterestSize[obj].x; szY: INT _ CD.InterestSize[obj].y; po: CDRoutingObjects.PlacedObject _ SELECT side FROM top => [obj, [min, off ]], bottom => [obj, [min, width-off-szY ]], right => [obj, [off, min ]], left => [obj, [width-off-szX, min ]] ENDCASE=>ERROR; IF pos=NIL THEN { pos _ NEW[LIST OF CDRoutingObjects.PlacedObject _ NIL]; []_SymTab.Store[nodes, label, pos]}; pos^ _ CONS[po, pos^]}; nodes: SymTab.Ref _ SymTab.Create[]; width: INT _ form.ary[side].width; fMin: INT _ form.ary[side].min; fMax: INT _ form.ary[side].max; routingIR: CD.Rect _ SELECT side FROM left => [0, fMin, width, fMax], right => [0, fMin, width, fMax], top => [fMin, 0, fMax, width], bottom => [fMin, 0, fMax, width], ENDCASE => ERROR; routingPos: CD.Position _ SELECT side FROM left => [-width, 0], right => [subSize.x, 0], top => [0, subSize.y], bottom => [0, -width], ENDCASE => ERROR; trunk: CD.Layer _ IF LeftRight[side] THEN form.vert ELSE OtherLayer[form.vert]; branch: CD.Layer _ OtherLayer[trunk]; srcLay: CD.Layer _ IF form.sameLayers THEN branch ELSE trunk; oneBus: BOOL _ NOT form.sameLayers; -- later we can count SELECT side FROM left => resultIR.x1 _ routingPos.x; right => resultIR.x2 _ routingPos.x + width; top => resultIR.y2 _ routingPos.y + width; bottom => resultIR.y1 _ routingPos.y; ENDCASE => ERROR; IF width=0 OR form.ary[side].pins=NIL THEN LOOP; FOR pins: WirePins _ form.ary[side].pins, pins.rest WHILE pins#NIL DO pin: WirePin _ pins.first; size: INT _ pin.max - pin.min; busRec: REF BusRec _ ExistingBusSideRec[pin.wire, side]; corner: BOOL _ ~LeftRight[side] AND (pin.min < 0 OR pin.max > subSize.x); extend: BOOL _ CoreOps.Member[form.ary[side].wires, pin.wire]; IF NOT MetLayer[pin.layer] THEN LOOP; IF corner THEN { AddRect[pin.wire, [width, size], branch, 0, pin.min]; IF busRec#NIL THEN AddVias[pin.wire,[busRec.width, size], busRec.loc, pin.min]} ELSE IF busRec=NIL THEN SELECT TRUE FROM pin.layer=branch => AddRect[pin.wire, [width, size], pin.layer, 0, pin.min]; NOT form.sameLayers => { AddRect[pin.wire, [2*L4, size], pin.layer, 0, pin.min]; AddVias[pin.wire, [L4, size], L4, pin.min]; AddRect[pin.wire, [width-L4, size], branch, L4, pin.min]}; ENDCASE -- skip pin ELSE IF oneBus OR pin.layer=branch THEN { AddRect[pin.wire, [busRec.loc, size], pin.layer, 0, pin.min]; IF pin.layer#trunk OR extend THEN AddVias[pin.wire, [busRec.width, size], busRec.loc, pin.min]; IF extend THEN AddRect[pin.wire, [width - busRec.loc, size], branch, busRec.loc, pin.min]}; ENDLOOP; FOR buses: Wires _ form.ary[side].buses, buses.rest WHILE buses#NIL DO rec: REF BusRec _ EnsureBusSideRec[buses.first, side]; size: CD.Position _ [rec.width, rec.max-rec.min]; AddRect[buses.first, size, trunk, rec.loc, rec.min] ENDLOOP; cdInstances _ CONS [ CDInstances.NewInst[ ob: CDRoutingObjects.CreateRoutingObject[ nodes: CDRoutingObjects.CreateNodes[nodes], ir: routingIR], trans: [routingPos]], cdInstances]; ENDLOOP; obj _ PW.CreateCell[instances: cdInstances, ir: resultIR, name: name.Cat[".mask"] ]}; Decorate: PWCore.DecorateProc = { WireToLabels: PROC [wire: Core.Wire] RETURNS [labels: LIST OF Route.Label _ NIL] = {RETURN[LIST [CoreRoute.LabelInternal[data.internal, wire]]]}; data: CoreClasses.RecordCellType _ NARROW [cellType.data]; CoreRoute.DecorateRoutedArea[cellType: cellType, obj: obj, wireToLabels: WireToLabels]}; EnsureBusSideRec: PROC[wire: Core.Wire, side: Side] RETURNS[busRec: REF BusRec] = { busRec _ ExistingBusSideRec[wire, side]; IF busRec=NIL THEN { busRec _ NEW[BusRec _ [0, 0, LAST[INT], FIRST[INT]]]; []_CoreProperties.PutWireProp[wire, sideProp[side], busRec]}}; ExistingBusSideRec: PROC[wire: Core.Wire, side: Side] RETURNS[busRec: REF BusRec] = {RETURN[NARROW[CoreProperties.GetWireProp[wire, sideProp[side]]]]}; GetSideExtention: PROC[cellType: Core.CellType, side: Side] RETURNS[extention: INT] = { LoSize: PROC[dif: INT] RETURNS[INT] = {RETURN[dif/2]}; HiSize: PROC[dif: INT] RETURNS[INT] = {RETURN[dif - LoSize[dif]]}; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; inSize: CD.Position _ CD.InterestSize[PWCore.Layout[data[0].type]]; sizeProp: ATOM _ SELECT side FROM left, right => $XSize, ENDCASE => $YSize; sizeRef: REF INT _ NARROW[CoreProperties.GetCellTypeProp[cellType, sizeProp]]; sideRef: REF INT _ NARROW[CoreProperties.GetCellTypeProp[cellType, sideProp[side]]]; extention _ IF sideRef#NIL THEN sideRef^ ELSE IF sizeRef=NIL THEN 0 ELSE SELECT side FROM left => LoSize[MAX[0, sizeRef^ - inSize.x/lambda]], right => HiSize[MAX[0, sizeRef^ - inSize.x/lambda]], top => HiSize[MAX[0, sizeRef^ - inSize.y/lambda]], bottom => LoSize[MAX[0, sizeRef^ - inSize.y/lambda]], ENDCASE => ERROR}; Adjust345: PROC[min, max: INT] RETURNS[minn, maxx: INT] = { minn _ min; maxx _ max; IF max-min IN (0..5*lambda] THEN { minn _ (min+max)/2 - 2*lambda; maxx _ (min+max)/2 + 2*lambda} }; AdjustPins345: PROC[pins: WirePins] = { FOR pins _ pins, pins.rest WHILE pins#NIL DO [pins.first.min, pins.first.max] _ Adjust345[pins.first.min, pins.first.max] ENDLOOP}; LeftRight: PROC[side: Side] RETURNS[leftRight: BOOL] = {RETURN[side=left OR side=right]}; MergeOrderedWires: PROC[a, b: Core.Wires] RETURNS[merge: Core.Wires] = { DO SELECT TRUE FROM a=NIL AND b=NIL => EXIT; a=NIL => {merge_CONS[b.first, merge]; b_b.rest}; b=NIL => {merge_CONS[a.first, merge]; a_a.rest}; a.first=b.first => {merge_CONS[a.first, merge]; a_a.rest; b_b.rest}; CoreOps.Member[b, a.first] => {merge_CONS[b.first, merge]; b_b.rest}; ENDCASE => {merge_CONS[a.first, merge]; a_a.rest}; ENDLOOP; RETURN[CoreOps.Reverse[merge]]}; OtherLayer: PROC[lay: CD.Layer] RETURNS[CD.Layer] = {RETURN[IF lay=CMosB.met THEN CMosB.met2 ELSE CMosB.met]}; MetLayer: PROC[layer: CD.Layer] RETURNS[isMetal1or2: BOOL] = {RETURN[layer=CMosB.met OR layer=CMosB.met2]}; ShowExtendForm: PROC[cellType: Core.CellType] = { name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; form: ExtendForm _ NARROW[CoreProperties.GetCellTypeProp[cellType, extendFormProp]]; tos: IO.STREAM _ TerminalIO.TOS[]; tos.PutF["Extend Layout: %g\n", IO.rope[name] ]; tos.PutF[" Left: %g\n", IO.int[form.ary[left].width]]; tos.PutF[" Right: %g\n", IO.int[form.ary[right].width]]; tos.PutF[" Top: %g\n", IO.int[form.ary[top].width]]; tos.PutF[" Bottom: %g\n", IO.int[form.ary[bottom].width]]}; SideNm: ARRAY Side OF IO.ROPE _ [bottom: "Bottom", top: "Top", left: "Left", right: "Right"]; viaTab: SymTab.Ref _ SymTab.Create[]; Vias: PROC[sizex, sizey: INT] RETURNS[obj: CD.Object] = { Bias: PROC[s: INT] RETURNS[bias:INT] = {RETURN[(s+d-((s+d)/(3*d))*3*d)/2]}; node: IO.ROPE _ "node"; insts: CD.InstanceList _ NIL; name: IO.ROPE _ IO.PutFR["Vias%gx%gy", IO.int[sizex], IO.int[sizey]]; via: CD.Object _ CDSimpleRules.Contact[technologyKey, CMosB.met, CMosB.met2]; d: INT _ L4/2; obj _ NARROW[SymTab.Fetch[viaTab, name].val]; IF obj#NIL THEN RETURN[obj]; FOR x: INT _ Bias[sizex], x + 3*d WHILE x <= sizex-(2*d) DO FOR y: INT _ Bias[sizey], y + 3*d WHILE y <= sizey-(2*d) DO insts _ CONS[NEW[CD.InstanceRep _ [via, [[x, y]]]], insts]; CDProperties.PutProp[insts.first, $SignalName, node] ENDLOOP ENDLOOP; IF insts=NIL THEN ERROR; insts _ CONS[NEW[CD.InstanceRep _ [CDRects.CreateRect[[sizex, sizey], CMosB.met]]], insts]; CDProperties.PutProp[insts.first, $SignalName, node]; insts _ CONS[NEW[CD.InstanceRep _ [CDRects.CreateRect[[sizex, sizey], CMosB.met2]]],insts]; CDProperties.PutProp[insts.first, $SignalName, node]; obj _ PW.CreateCell[instances: insts, name: name, ir: [0, 0, sizex, sizey]]; []_SymTab.Store[viaTab, name, obj]}; [] _ PWCore.RegisterLayoutAtom[$ExtendX, Layout, Decorate, Attribute]; END. CoreRouteExtend.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Don Curry August 25, 1988 4:52:28 pm PDT Types and constants Attribute, Layout and Decorate Procs can't do changelayers with more than one bus Compute busWidths and VertLayer Override bus width if wire has wireWidthProp Compute side widths and bus locs Extend top and bottom routing cells Add Top and Bottom Ends Compute busMins, busMaxs Extend buses to ends of routing cells Build routing objects. Add Trunks Auxillary procedures Register layout atoms Κ€˜šœ™Icode™˜Z—™$šž œ˜$šž œœœœœœœœ˜Kšœ˜Jšœœ=˜D——šžœœ˜0šœœ ˜Jšœ˜Jšœ˜—Jšœœœ˜(šœœœ˜0Jšœœ.˜6Jš œœœ œœ˜NJšœ<˜˜>Jšœ?˜?Jšœ=˜=Jšœ?˜?Jšœ@˜@Jšœ<˜Jšœ!˜%šœB˜GJšœœ*˜C——Jšœœœœ!˜F——Jšœœ˜——Jšœœœœ˜&JšŸ,™,šœ œ˜šœ1œœ˜FJšœœœœ9˜NJšœœ.˜6Jš œ œœœ œ œœ˜B——JšŸ ™ šœ œ˜Jšœœžœ˜+Jšœ$˜$Jšœ œ œ ˜@šœœ˜*Jšœœœœœœœœ˜:—šœœœ˜0Jšœœ.˜6Jšœ˜Jšœ:œœ˜E—šœœ˜ Jšœœ ˜šœ˜šœY˜]Jšœ˜Jšœ ˜Jšœ"˜$Jšœ˜ —Jšœ˜ ——Jšœ˜Jšœœœ œ ˜FJšœ˜—JšŸ#™#šœœ˜ Jšœ@˜@JšœB˜B—šœœ˜#JšœD˜DJšœF˜F—JšŸ™Jšœ˜Jšœ ˜ Jšœ!˜!Jšœ"˜"JšŸ™šœ œ˜Jšœœœ˜$šœ1œœ˜EJšœ˜Jšœ œ žœ˜9Jšœœœœ˜%šœœœ˜Jšœœ˜(Jšœœœœ˜9———JšŸ%™%šœ œ˜šœ1œœ˜FJšœ=œ˜E—šœ1œœ˜FJšœ=œœ˜M——Jšœ)˜)Jšœ)˜)Jšœ?˜?Jšœ˜J˜—šžœ˜Jšœœœ)˜7Jšœ$œ˜:šœœ˜Jšœ:˜:—Jšœ œ˜Jšœœ)˜3Jšœ œœ˜1šœ œœ˜9Jšœ'œ˜D—JšŸ™šœ œ˜šžœ˜ šœœœœ˜FJšœœ˜Jšœœ˜1Jšœ%˜%Jšœ+˜+——šžœ˜ šœœœ˜7šœœ œ˜$Jšœ˜Jšœ˜—Jšœ+˜+——šžœœœœ˜MJšœB˜Bšœœœœ ˜0Jšœ!˜'—Jšœœœ˜"Jšœœœ˜"šœ$œ˜4Jšœ!˜!Jšœ*˜*Jšœ$˜$Jšœ)œœ˜8—šœœœ˜Jš œœœœ!œ˜7Jšœ$˜$—Jšœœ ˜—Jšœ%˜%Jšœœ˜"Jšœœ˜ Jšœœ˜ šœ œœ˜%Jšœ ˜ Jšœ!˜!Jšœ˜Jšœ!˜!Jšœœ˜—šœ œ œ˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜—Jš œœ œœ œ˜PJšœœ˜%Jš œœ œœœ˜=Jšœœœ ˜:šœ˜Jšœ$˜$Jšœ-˜-Jšœ+˜+Jšœ%˜%Jšœœ˜—Jš œ œœœœ˜0šœ1œœ˜EJšœ˜Jšœœ˜!Jšœœ-˜8Jšœœœœ˜KJšœœ4˜@Jšœœœœ˜%šœ˜ šœ˜Jšœ8˜8Jšœœœ=˜O—šœœ˜šœœœ˜šœ˜Jšœ:˜:—šœ˜Jšœœ"˜9Jšœœœ ˜0Jšœœœ ˜:—Jšœ  ˜—šœœœœ˜)JšœA˜Ašœœ˜!JšœA˜A—šœ˜JšœL˜L————Jšœ˜—JšŸ ™ šœ1œœ˜FJšœœ.˜6Jšœœ)˜1Jšœ4œ˜<—šœœ˜šœ˜šœ)˜)Jšœ+˜+Jšœ˜—Jšœ˜—Jšœ ˜ —Jšœ˜—JšœœM˜UJ˜—šžœ˜!š ž œœœ œœœ˜RJšœœœ2˜>—Jšœ#œ˜:JšœX˜X——™šžœœœ œ ˜SJšœ žœ ˜(šœœœ˜Jš œ œœœœœ˜5Jšœ>˜>—J˜—šžœœœ œ ˜SJšœœœ5˜CJ˜—šžœœ&œ œ˜WJš žœœœœœœ ˜7Jš žœœœœœœ˜CJšœ$œ˜:Jšœœ œ+˜CJš œ œœœœ ˜LJšœ œœœ5˜NJšœ œœœ;˜Tšœ œ ˜Jšœ ˜ šœœ ˜Jšœ˜šœœ˜Jšœ žœœ!˜4Jšœ žœœ!˜5Jšœžœœ!˜3Jšœ žœœ!˜5Jšœœ˜———J˜—š ž œœ œœ œ˜@J˜šœ œœ˜"Jšœ˜Jšœ!˜!—J˜—šž œœ˜'šœœœ˜,JšœMœ˜V—J˜—šž œœœ œ˜=Jšœœ œ˜"J˜—šžœœœ˜Hš˜šœœ˜Jš œœœœœ˜Jšœœœ˜9Jšœœœ˜6Jšœœ&˜HJšœ%œ˜HJšœœ˜7—Jš˜—Jšœ˜ J˜—š ž œœœ œœ ˜7Jš œœœœ œ ˜:J˜—š žœœœœœ˜