DIRECTORY CD, CDBasics, CDDirectory, CDErrors, CDObjectProcs, CDOrient, CDPinObjects, CDProperties, CDRects, Core, CoreOps, CoreProperties, CoreRecord, PWPins, RefTab, Rope, Sinix, SinixBridge; TimValuesImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDDirectory, CDErrors, CDObjectProcs, CDOrient, CDPinObjects, CDProperties, CDRects, Core, CoreOps, CoreProperties, CoreRecord, PWPins, RefTab, Rope, SinixBridge EXPORTS Sinix = BEGIN OPEN Sinix; debug: BOOL _ TRUE; MakeInterval: PUBLIC PROC [min, max: INT] RETURNS [interval: Interval] = { interval _ NEW [IntervalRec _ [min, max]]; }; MakeCutValue: PUBLIC PROC [tcut: INT, before, after: Value] RETURNS [cutValue: CutValue] = { cutValue _ NEW [CutValueRec _ [tcut, before, after]]; }; Add: PUBLIC PROC [value1, value2: Value] RETURNS [result: VALUE] = { WITH value1 SELECT FROM refInt1: Interval => WITH value2 SELECT FROM refInt2: Interval => RETURN [MakeInterval[refInt1.min+refInt2.min, refInt1.max+refInt2.max]]; cutValue2: CutValue => RETURN [MakeCutValue[cutValue2.tcut, Add[value1, cutValue2.before], Add[value1, cutValue2.after]]]; ENDCASE => ERROR; cutValue1: CutValue => WITH value2 SELECT FROM refInt2: Interval => RETURN [MakeCutValue[cutValue1.tcut, Add[value2, cutValue1.before], Add[value2, cutValue1.after]]]; cutValue2: CutValue => IF cutValue1.tcut=cutValue2.tcut THEN RETURN [MakeCutValue[cutValue1.tcut, Add[cutValue1.before, cutValue2.before], Add[cutValue1.after, cutValue2.after]]] ELSE IF cutValue1.tcut ERROR; ENDCASE => ERROR; }; touchProcProp: ATOM; Touch: TouchProc; PutObjectPropOnCellType: PUBLIC PROC [cellType: Core.CellType, obj: CD.Object] = { cellType.properties _ CoreProperties.PutProp[cellType.properties, sinixObjectProp, obj]; }; GetObjectPropFromCellType: PUBLIC PROC [cellType: Core.CellType] RETURNS [obj: CD.Object] = { obj _ NARROW [CoreProperties.GetProp[cellType.properties, sinixObjectProp]]; }; AppendWireGeometryPropOnWire: PUBLIC PROC [wire: Core.Wire, geometry: LIST OF CD.Instance] = { WHILE geometry#NIL DO AddWireGeometryPropOnWire[wire, geometry.first]; geometry _ geometry.rest; ENDLOOP; }; AddWireGeometryPropOnWire: PUBLIC PROC [wire: Core.Wire, cdInstance: CD.Instance] = { PutWireGeometryPropOnWire[wire, CONS [cdInstance, GetWireGeometryPropFromWire[wire]]]; }; PutWireGeometryPropOnWire: PUBLIC PROC [wire: Core.Wire, geometry: LIST OF CD.Instance] = { wire.properties _ CoreProperties.PutProp[wire.properties, sinixWireGeometryProp, geometry]; }; GetWireGeometryPropFromWire: PUBLIC PROC [wire: Core.Wire] RETURNS [geometry: LIST OF CD.Instance] = { geometry _ NARROW[CoreProperties.GetProp[wire.properties, sinixWireGeometryProp]]; }; PutInstancePropOnInstance: PUBLIC PROC [cellInstance: CoreRecord.CellInstance, cdInstance: CD.Instance] = { cellInstance.properties _ CoreProperties.PutProp[cellInstance.properties, sinixInstanceProp, cdInstance]; }; GetInstancePropFromInstance: PUBLIC PROC [cellInstance: CoreRecord.CellInstance] RETURNS [cdInstance: CD.Instance] = { cdInstance _ NARROW [CoreProperties.GetProp[cellInstance.properties, sinixInstanceProp]]; }; Root: PROC [table: RefTab.Ref, wire: Core.Wire] RETURNS [newWire: Core.Wire] = { newWire _ NARROW [RefTab.Fetch[table, wire].val]; IF newWire=NIL THEN RETURN[wire]; newWire _ Root[table, newWire]; [] _ RefTab.Replace[table, wire, newWire]; }; Fusion: PROC [table: RefTab.Ref, wire: Core.Wire] = { geometry: LIST OF CD.Instance _ GetWireGeometryPropFromWire[wire]; EachWire: RefTab.EachPairAction = { rootWire: Core.Wire _ Root[table, NARROW[key]]; rootGeometry: LIST OF CD.Instance _ GetWireGeometryPropFromWire[rootWire]; quit _ FALSE; IF rootWire=wire OR ~TouchInstances[rootGeometry, geometry] THEN RETURN; AppendWireGeometryPropOnWire[wire, rootGeometry]; SELECT TRUE FROM rootWire.name=NIL => {}; wire.name=NIL => wire.name _ rootWire.name; Rope.Equal[rootWire.name, wire.name] => {}; ENDCASE => ERROR; -- different names on the same net (probably 2 pins of different nets connected together) [] _ RefTab.Store[table, rootWire, wire]; }; [] _ RefTab.Pairs[table, EachWire]; [] _ RefTab.Store[table, wire, NIL]; }; TableToWire: PROC [table: RefTab.Ref] RETURNS [wire: Core.Wire] = { EachWire: RefTab.EachPairAction = { quit _ FALSE; wire.elements[index] _ NARROW[key]; index _ index + 1; }; size: NAT _ RefTab.GetSize[table]; index: NAT _ 0; wire _ NEW [Core.WireRec _ [name: "Bidon", structure: record, elements: NEW [Core.WireSequenceRec[size]]]]; [] _ RefTab.Pairs[table, EachWire]; }; Member: PROC [wires: LIST OF Core.Wire, wire: Core.Wire] RETURNS [BOOL] = { WHILE wires#NIL DO IF wires.first=wire THEN RETURN [TRUE]; wires _ wires.rest ENDLOOP; RETURN [FALSE]; }; extractObjProcProp: PUBLIC ATOM _ $ExtractObjProc; ExtractObj: PUBLIC ExtractObjProc = { refProc: REF ExtractObjProc; name: ROPE _ CDDirectory.Name[obj]; IF name#NIL THEN cellType _ CoreOps.FetchCellType[coreDesign, name]; IF cellType#NIL THEN RETURN; refProc _ NARROW [CDProperties.GetPropFromObject[obj, extractObjProcProp]]; IF refProc=NIL THEN refProc _ NARROW [CDObjectProcs.FetchFurther[obj.class, extractObjProcProp]]; [cellType, nbErrors] _ (IF refProc=NIL THEN DefaultExtractObj ELSE refProc^)[coreDesign, cdDesign, obj]; IF cellType=NIL THEN RETURN; cellType.name _ name; cellType.properties _ CoreProperties.PutProp[cellType.properties, sinixObjectProp, obj]; IF name#NIL AND CDDirectory.Fetch[cdDesign, name].found THEN CoreOps.InsertCellType[coreDesign, cellType]; }; DefaultExtractObj: PUBLIC ExtractObjProc = { obj _ CDDirectory.ExpandHard[obj, NIL, NIL]; IF obj=NIL THEN ERROR; RETURN ExtractObj[coreDesign, cdDesign, obj]; }; AtomicExtractObj: PUBLIC ExtractObjProc = { subWire: Core.Wire _ NEW [Core.WireRec]; wire: Core.Wire _ NEW [Core.WireRec _ [structure: record, elements: NEW [Core.WireSequenceRec[1]]]]; AddWireGeometryPropOnWire[subWire, NEW [CD.InstanceRep _ [ob: obj]]]; wire.elements[0] _ subWire; cellType _ NEW[Core.CellTypeRec _ [class: CoreRecord.recordCellClass, publicWire: wire, data: NEW[CoreRecord.RecordCellTypeRec _ [internalWire: wire]]]]; }; PinExtractObj: ExtractObjProc = { RETURN [NIL]; }; CellExtractObj: ExtractObjProc = { cellPtr: CD.CellPtr _ NARROW [obj.specificRef]; currentWires: RefTab.Ref _ RefTab.Create[]; realPublicWire: RefTab.Ref _ RefTab.Create[]; realInternalWires: RefTab.Ref _ RefTab.Create[]; currentInstances: LIST OF CoreRecord.CellInstance _ NIL; cellTypeData: CoreRecord.RecordCellType; FOR instances: LIST OF CD.Instance _ cellPtr.contents, instances.rest WHILE instances#NIL DO cdInstance: CD.Instance _ instances.first; subCellType: Core.CellType; subErrors: INT; subPublics: Core.WireSequence; size: NAT; actualWire: Core.Wire; instance: CoreRecord.CellInstance; [subCellType, subErrors] _ ExtractObj[coreDesign, cdDesign, cdInstance.ob]; nbErrors _ nbErrors + subErrors; IF subCellType=NIL THEN LOOP; -- Symbolic object such as a pin subPublics _ subCellType.publicWire.elements; size _ subPublics.size; actualWire _ NEW [Core.WireRec _ [name: "Bidon", structure: record, elements: NEW [Core.WireSequenceRec[size]]]]; instance _ NEW [CoreRecord.CellInstanceRec _ [actualWire: actualWire, type: subCellType]]; instance.properties _ CoreProperties.PutProp[instance.properties, sinixInstanceProp, cdInstance]; currentInstances _ CONS [instance, currentInstances]; FOR i: NAT IN [0 .. size) DO subPublic: Core.Wire _ subPublics[i]; newActual: Core.Wire _ NEW [Core.WireRec]; IF GetWireGeometryPropFromWire[subPublic]=NIL THEN {} -- that means a non-connected subPublic ELSE AddWireGeometryPropOnWire[newActual, NEW [CD.InstanceRep _ [ob: SinixBridge.WireToObjectBridge[cdInstance.ob, subPublic], location: cdInstance.location, orientation: cdInstance.orientation]]]; Fusion[currentWires, newActual]; actualWire.elements[i] _ newActual; ENDLOOP; ENDLOOP; BEGIN ComputeRealWire: RefTab.EachPairAction = { rootWire: Core.Wire _ Root[currentWires, NARROW[key]]; quit _ FALSE; [] _ RefTab.Store[realInternalWires, rootWire, NIL]; }; [] _ RefTab.Pairs[currentWires, ComputeRealWire]; END; BEGIN EachPin: PWPins.InstanceEnumerator = { pinName: ROPE _ CDPinObjects.GetName[inst]; geometry: LIST OF CD.Instance _ LIST [inst]; lastRootWire: Core.Wire _ NIL; EachWire: RefTab.EachPairAction = { wire: Core.Wire _ NARROW[key]; quit _ FALSE; IF ~TouchInstances[GetWireGeometryPropFromWire[wire], geometry] THEN RETURN; IF lastRootWire#NIL THEN ERROR; -- 2 different nets touched by the same pin lastRootWire _ wire; IF wire.name=NIL OR Rope.Equal[wire.name, pinName] THEN wire.name _ pinName ELSE { [] _ CDErrors.IncludeMessage[cdDesign, obj, RectAt[inst], Rope.Cat["Different names on the same net (probably 2 pins of different nets connected together): ", wire.name, pinName]]; nbErrors _ nbErrors+1; }; }; [] _ RefTab.Pairs[realInternalWires, EachWire]; IF lastRootWire=NIL THEN ERROR; -- pin touches no net [] _ RefTab.Store[realPublicWire, lastRootWire, NIL]; }; [] _ PWPins.EnumerateEdgePins[obj, EachPin]; END; cellTypeData _ NEW [CoreRecord.RecordCellTypeRec _ [internalWire: TableToWire[realInternalWires]]]; cellType _ NEW [Core.CellTypeRec _ [ class: CoreRecord.recordCellClass, publicWire: TableToWire[realPublicWire], data: cellTypeData]]; WHILE currentInstances#NIL DO instance: CoreRecord.CellInstance _ currentInstances.first; actualWire: Core.Wire _ instance.actualWire; FOR i: NAT IN [0 .. actualWire.elements.size) DO wire: Core.Wire _ Root[currentWires, actualWire.elements[i]]; IF ~RefTab.Fetch[realInternalWires, wire].found THEN ERROR; -- BUG! actualWire.elements[i] _ wire; ENDLOOP; cellTypeData.instances _ CONS [instance, cellTypeData.instances]; currentInstances _ currentInstances.rest; ENDLOOP; }; touchProcProp: PUBLIC ATOM _ $TouchProc; Touch: PUBLIC TouchProc = { refProc: REF TouchProc; IF ~CDBasics.Intersect[RectAt[instance1], RectAt[instance2]] THEN RETURN; refProc _ NARROW [CDProperties.GetPropFromObject[instance1.ob, touchProcProp]]; IF refProc=NIL THEN refProc _ NARROW [CDObjectProcs.FetchFurther[instance1.ob.class, touchProcProp]]; yes _ (IF refProc=NIL THEN DefaultTouchProc ELSE refProc^)[instance1, instance2]; }; DefaultTouchProc: TouchProc = { instance1 _ NEW [CD.InstanceRep _ [ ob: CDDirectory.ExpandHard[instance1.ob, NIL, NIL], location: instance1.location, orientation: instance1.orientation ]]; IF instance1.ob=NIL THEN ERROR; RETURN [Touch[instance1, instance2]]; }; PinTouchProc: TouchProc = { RETURN [TouchRect[instance2, RectAt[instance1], CDPinObjects.GetLayer[instance1]]]; }; RectTouchProc: TouchProc = { RETURN [TouchRect[instance2, RectAt[instance1], instance1.ob.layer]]; }; CellTouchProc: TouchProc = { cellPtr: CD.CellPtr _ NARROW [instance1.ob.specificRef]; FOR instances: LIST OF CD.Instance _ cellPtr.contents, instances.rest WHILE instances#NIL DO IF Touch[Transform[instance1, instances.first], instance2] THEN RETURN [TRUE]; ENDLOOP; RETURN [FALSE]; }; RectAt: PUBLIC PROC [instance: CD.Instance] RETURNS [rect: CD.Rect] = { rect _ CDOrient.RectAt[instance.location, instance.ob.size, instance.orientation]; }; IRectAt: PUBLIC PROC [instance: CD.Instance] RETURNS [rect: CD.Rect] = { rect _ CDOrient.MapRect[CD.InterestRect[instance.ob], instance.ob.size, instance.orientation, instance.location]; }; TouchRect: PUBLIC PROC [instance: CD.Instance, rect: CD.Rect, layer: CD.Layer] RETURNS [yes: BOOL _ FALSE] = { rectInstance: CD.Instance; IF ~CDBasics.Intersect[RectAt[instance], rect] THEN RETURN; IF instance.ob.class.objectType=$Rect THEN RETURN [instance.ob.layer=layer]; rectInstance _ NEW [CD.InstanceRep _ [ ob: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], location: CDBasics.BaseOfRect[rect] ]]; yes _ Touch[instance, rectInstance]; }; Transform: PROC [transformation, instance: CD.Instance] RETURNS [result: CD.Instance] = { RETURN [ NEW [CD.InstanceRep _ [ ob: instance.ob, location: CDBasics.BaseOfRect[CDOrient.MapRect[ itemInCell: RectAt[instance], cellSize: transformation.ob.size, cellInstOrient: transformation.orientation, cellInstPos: transformation.location ]], orientation: CDOrient.ComposeOrient[itemOrientInCell: instance.orientation, cellOrientInWorld: transformation.orientation] ]]]; }; TransformList: PROC [transformation: CD.Instance, instances: LIST OF CD.Instance] RETURNS [result: LIST OF CD.Instance _ NIL] = { WHILE instances#NIL DO result _ CONS [Transform[transformation, instances.first], result]; instances _ instances.rest; ENDLOOP; }; TouchInstances: PROC [instances1, instances2: LIST OF CD.Instance] RETURNS [yes: BOOL _ FALSE] = { FOR list1: LIST OF CD.Instance _ instances1, list1.rest WHILE list1#NIL DO FOR list2: LIST OF CD.Instance _ instances2, list2.rest WHILE list2#NIL DO IF Touch[list1.first, list2.first] THEN RETURN [TRUE]; ENDLOOP; ENDLOOP; }; BEGIN ENABLE { CD.Error => IF debug AND ec=doubleRegistration THEN CONTINUE ELSE ERROR; Core.StructureError => IF debug AND type=DuplicateName THEN RESUME ELSE ERROR; }; CoreProperties.RegisterProperty[sinixObjectProp]; CoreProperties.RegisterProperty[sinixWireGeometryProp]; CoreProperties.RegisterProperty[sinixInstanceProp]; [] _ CDProperties.RegisterProperty[extractObjProcProp, $Sinix]; CDObjectProcs.RegisterFurther[extractObjProcProp]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$PinOb0], extractObjProcProp, NEW [ExtractObjProc _ PinExtractObj]]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$Rect], extractObjProcProp, NEW [ExtractObjProc _ AtomicExtractObj]]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$Cell], extractObjProcProp, NEW [ExtractObjProc _ CellExtractObj]]; [] _ CDProperties.RegisterProperty[touchProcProp, $Sinix]; CDObjectProcs.RegisterFurther[touchProcProp]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$PinOb0], touchProcProp, NEW [TouchProc _ PinTouchProc]]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$Rect], touchProcProp, NEW [TouchProc _ RectTouchProc]]; CDObjectProcs.StoreFurther[CD.FetchObjectClass[$Cell], touchProcProp, NEW [TouchProc _ CellTouchProc]]; END; END. ¦TimValuesImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet September 11, 1985 11:09:10 am PDT Bertrand Serlet September 11, 1985 12:00:30 pm PDT ToDo: ERROR -> Signals; Name of the atoms for CD.FetchObjectClass $Transistor Use instanceName property and SignalName (???) non connected actualWire (that is a problem for transistors) Commenting object PROCS Speed Hack for Rect Naming wires to avoid problems when printing name: "Bidon" Utilities Utilities Usual Operations TouchProcs are put on property on each class of object that does not use the default (default is expand). It is also possible to have that properties on an object. The callable function Touch is soforth programmed in an Object Oriented manner. Operations for an easy management of those properties Internal utilities The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] Extraction we fill the actual compute now the realInternalWires [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] compute now the realPublicWire by enumerating the pins [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] we build the CellType IF GetWireGeometryPropFromWire[wire]=NIL THEN ERROR; -- non connected actualWire (that is a problem for transistors) Geometry Primitives Geometry Utilities Initialization Public Core Properties CD Properties CDObjectProcs.StoreFurther[CD.FetchObjectClass[$Transistor], extractObjProcProp, NEW [ExtractObjProc _ TransistorExtractObj]]; Êÿ– "cedar" style˜codešœ™Kšœ Ïmœ1™ -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœ žœžœžœ.˜BšŸœ˜#JšÐck:™:Jšœ"žœ˜/Jšœžœžœžœ2˜JJšœžœ˜ Jšžœžœ)žœžœ˜HJšœ1˜1šžœžœž˜Jšœžœ ˜Jšœ žœ%˜2Jšœ+˜+Jšžœ žœÏcY˜t—Jšœ)˜)J˜—Jšœ#˜#Jšœžœ˜$J˜—J˜š  œžœžœ˜C–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šŸœ˜#Jš¡:™:Jšœžœ˜ Jšœžœ˜#Jšœ˜J˜—Jšœžœ˜"Jšœžœ˜Jšœžœ>žœ ˜kJšœ#˜#J˜—J˜š  œžœ žœžœžœžœ˜KJšžœžœžœžœžœžœžœžœ˜VJšžœžœ˜J˜——™ Jšœžœžœ˜2J˜šŸ œžœ˜%Jšœ žœ˜Jšœžœ˜#Jšžœžœžœ4˜DJšžœ žœžœžœ˜Jšœ žœ;˜KJšžœ žœžœ žœ=˜aJš œžœ žœžœžœ&˜hJšžœ žœžœžœ˜Jšœ˜JšœX˜XJšžœžœžœ)žœ.˜jJ˜—J˜šŸœžœ˜,Jšœ"žœžœ˜,Jšžœžœžœžœ˜Jšžœ'˜-J˜—J˜šŸœžœ˜+Jšœžœ˜(Jšœžœ/žœ˜dJšœ#žœžœ˜EJšœ˜Jšœ žœPžœ8˜™J˜—J˜šŸ œ˜!Jšžœžœ˜ J˜—J˜šŸœ˜"J˜Jšœ žœ žœ˜/Jšœ+˜+Jšœ-˜-Jšœ0˜0Jšœžœžœžœ˜8Jšœ(˜(š žœ žœžœžœ-žœ žœž˜\Jšœ žœ˜*Jšœ˜Jšœ žœ˜Jšœ˜Jšœžœ˜ Jšœ˜Jšœ"˜"JšœK˜KJšœ ˜ Jš žœ žœžœžœ¢ ˜>Jšœ-˜-Jšœ˜Jšœ žœ>žœ ˜qJšœ žœL˜ZJšœa˜aJšœžœ˜5Jšœ™šžœžœžœ ž˜Jšœ%˜%Jšœžœ˜*šžœ(žœ˜.Jšžœ¢'˜/Jšžœ&žœžœ”˜Å—Jšœ ˜ Jšœ#˜#Jšžœ˜—Jšžœ˜—Jšœ!™!šž˜–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šŸœ˜*Jš¡:™:Jšœ)žœ˜6Jšœžœ˜ Jšœ/žœ˜4J˜—Jšœ1˜1Jšžœ˜—Jšœ6™6šž˜–4 -- [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE]šŸœ˜&Jš¡0™0Jšœ žœ˜+J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]š œ žœžœžœ žœ˜,Jšœžœ˜šŸœ˜#Jš¡:™:Jšœžœ˜Jšœžœ˜ Jšžœ>žœžœ˜LJš žœžœžœžœ¢+˜KJšœ˜š žœ žœžœ žœžœ˜RJšœ´˜´Jšœ˜J˜—J˜—Jšœ/˜/Jš žœžœžœžœ¢˜5Jšœ0žœ˜5J˜—Jšœ,˜,Jšžœ˜—Jšœ™JšœžœQ˜cšœ žœ˜$Jšœ#˜#Jšœ)˜)Jšœ˜—šžœžœž˜Jšœ;˜;Jšœ,˜,šžœžœžœ!ž˜0Jšœ=˜=Jš žœ#žœžœžœ¢?™tJšžœ.žœžœ¢˜CJšœ˜Jšžœ˜—Jšœžœ$˜AJšœ)˜)Jšžœ˜—J˜——™Jšœžœžœ˜(J˜šŸœžœ˜Jšœ žœ ˜Jšžœ;žœžœ˜IJšœ žœ?˜OJšžœ žœžœ žœA˜eJš œžœ žœžœžœ!˜QJ˜—J˜šŸœ˜šœ žœžœ˜#Jšœ)žœžœ˜4Jšœ@˜@Jšœ˜—Jšžœžœžœžœ˜Jšžœ˜%J˜—J˜šŸ œ˜JšžœM˜SJ˜—J˜šŸ œ˜Jšžœ?˜EJ˜—J˜šŸ œ˜Jšœ žœ žœ˜8š žœ žœžœžœ-žœ žœž˜\Jšžœ9žœžœžœ˜NJšžœ˜—Jšžœžœ˜J˜——™š  œžœžœ žœ žœžœ ˜GJšœR˜RJ˜—J˜š  œžœžœ žœ žœžœ ˜HJšœžœW˜qJ˜—J™šÐbn œžœžœ žœžœžœžœžœžœ˜nJšœžœ ˜Jšžœ-žœžœ˜;Jšžœ$žœžœ˜Lšœžœžœ˜&Jšœ:˜:Jšœ#˜#Jšœ˜—Jšœ$˜$J˜—J˜š   œžœžœ žœ žœ˜Yšžœ˜šžœžœ˜Jšœ˜šœ/˜/Jšœ˜Jšœ"˜"Jšœ,˜,Jšœ$˜$Jšœ˜—Jšœz˜zJšœ˜——J˜—J˜š  œžœžœžœžœžœ žœ žœžœžœ žœ˜šžœ žœžœ˜Jšœ žœ7˜DJšœ˜Jšžœ˜—J˜—J˜š œžœžœžœžœ žœžœžœ˜bš žœžœžœžœ#žœžœž˜Jš žœžœžœžœ#žœžœž˜JJšžœ!žœžœžœ˜6Jšžœ˜—Jšžœ˜—J˜——šœ™Kšž˜šžœ˜ Kšžœ žœžœžœžœžœžœ˜HKš œžœžœžœžœžœžœ˜NK˜—K˜™Kšœ1˜1Kšœ7˜7Kšœ3˜3—K™J™™ Kšœ?˜?KšŸ2˜2Kšœžœ0žœ#˜sKšœžœ4žœ*™~Kšœžœ.žœ&˜tKšœžœ.žœ$˜rK˜Kšœ:˜:KšŸ-˜-Kšœžœ+žœ˜hKšœžœ)žœ˜gKšœžœ)žœ˜g—K˜Kšžœ˜—Kšžœ˜K˜——…—7°OU