DIRECTORY Arbiter, BitOps, CedarProcess, Core, CoreFlat, CoreProperties, IO, MTSVector, Ports, Random, Rosemary, RosemaryUser; ArbSysTests: CEDAR PROGRAM IMPORTS BitOps, CedarProcess, CoreFlat, CoreProperties, IO, MTSVector, Ports, Random, Rosemary, RosemaryUser EXPORTS Arbiter = BEGIN OPEN Arbiter; State: TYPE = REF StateRec _ NIL; StateRec: TYPE = RECORD [ tester: RosemaryUser.Tester _ NIL, simulation: Rosemary.Simulation _ NIL, cellType: Core.CellType _ NIL, capture: MTSVector.Capture _ NIL, testCycles: INT _ 100000, p: Ports.Port _ NIL, eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL_FALSE, checkPorts: BOOL_TRUE]_NIL, cycle, patchState: INT _ -1, noteBusBusyLast: INT _ -1, forceStop, forceBusy: BOOL _ FALSE, nRequestOuts, nGrants, nHiPGrants, nLongGrants, ArbReqs, DBus, nOwnerOuts, nBOwnerIn, nOwnerIns, nSharedOuts, nBShareds, nSharedIns, nSStopOuts, nBSStops, nSStopIns, nStopAct, SlotNos, nDHybridSels, DBdSels, nDynaBusBusy, nHolding, nBusyOuts, nBusyIn, Ck, TIOBus, --RecAdj, --TRec2v, TInv: NAT _ 0, arbs: ARRAY Arbiters OF REF _ ALL[NIL], devs: ARRAY Arbiters OF ARRAY Devices OF REF _ ALL[ALL[NIL]] ]; lastState: State _ NIL; rand: Random.RandomStream _ Random.Create[]; NewState: PROC [ cellType: Core.CellType, p: Ports.Port, eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL _ FALSE, checkPorts: BOOL _ TRUE]] RETURNS [ st: State ] = { GetState: PROC [ instName: IO.ROPE ] RETURNS [ ref: REF ] = { ref _ Rosemary.GetState[ st.tester.display.simulation, NEW[CoreFlat.FlatCellTypeRec _ CoreFlat.ParseCellTypePath[st.cellType, instName]] ] }; lastState _ st _ NEW[StateRec _ [tester: NARROW[CoreProperties.GetProp[cellType.properties, $Tester]] ]]; st.simulation _ st.tester.display.simulation; st.cellType _ st.tester.display.cellType; st.p _ p; TRUSTED { st.eval _ eval }; [st.nRequestOuts, st.nGrants, st.nHiPGrants, st.nLongGrants, st.ArbReqs] _ Ports.PortIndexes [st.cellType.public, "nRequestOuts", "nGrants", "nHiPGrants", "nLongGrants", "ArbReqs"]; [st.DBus] _ Ports.PortIndexes[st.cellType.public, "DBus"]; [st.SlotNos, st.nDHybridSels, st.DBdSels] _ Ports.PortIndexes[st.cellType.public, "SlotNos", "nDHybridSels", "DBdSels"]; [st.nOwnerOuts, st.nBOwnerIn, st.nOwnerIns] _ Ports.PortIndexes[st.cellType.public, "nOwnerOuts", "nBOwnerIn", "nOwnerIns"]; [st.nSharedOuts, st.nBShareds, st.nSharedIns] _ Ports.PortIndexes[st.cellType.public, "nSharedOuts", "nBShareds", "nSharedIns"]; [st.nSStopOuts, st.nBSStops, st.nSStopIns, st.nStopAct] _ Ports.PortIndexes[st.cellType.public, "nSStopOuts", "nBSStops", "nSStopIns", "nStopAct"]; [st.nDynaBusBusy, st.nHolding, st.nBusyOuts, st.nBusyIn, st.Ck] _ Ports.PortIndexes[st.cellType.public, "nDynaBusBusy", "nHolding", "nBusyOuts", "nBusyIn", "Ck"]; [st.TIOBus, --st.RecAdj, -- st.TRec2v, st.TInv] _ Ports.PortIndexes[st.cellType.public, "TIOBus", --"RecAdj", --"TRec2v", "TInv"]; FOR a: Arbiters IN Arbiters DO FOR d: Devices IN Devices DO st.devs[a][d] _ GetState[IO.PutFR["/Arb%dReq%d", IO.int[a], IO.int[d]]]; ENDLOOP; ENDLOOP}; WhoAmI: PROC [ ref: REF ] RETURNS [ name: IO.ROPE ] = { FOR a: Arbiters IN Arbiters DO IF ref = lastState.arbs[a] THEN RETURN[IO.PutFR["Arbiter %d", IO.int[a]]]; FOR d: Devices IN Devices DO IF ref = lastState.devs[a][d] THEN RETURN[IO.PutFR["Device %d of arbiter %d", IO.int[d], IO.int[a]]] ENDLOOP ENDLOOP; name _ "Darned if I know!"}; extraResetCycles: NAT _ 1; nCheckBits: NAT _ 5; shouldMaskRev1Bug: BOOL _ FALSE; RunTest: PROC [ st: State, initializeAll: BOOL _ FALSE ] = { PipeDepth: NAT = 10; Eval: PROC [ ignoreX: BOOL _ FALSE ] = { ENABLE Rosemary.Stop => IF ignoreX AND (reason = $BoolWireHasX) THEN RESUME ELSE REJECT; MTSVector.EvalAndCapture[st.capture, st.eval, FALSE]; }; EvalIgnoreX: PROC = {Eval[ignoreX: TRUE]}; ReallyRunTest: PROC = { OrPorts: TYPE = {owner, shared, stop}; OrPipeEnt: TYPE = RECORD [ A: ARRAY Arbiters OF BOOL _ ALL[FALSE], inD: BOOL _ FALSE ]; OrPortParts: TYPE = RECORD [ outD, A, inD: NAT, pipe: ARRAY [0..PipeDepth) OF OrPipeEnt _ ALL[] ]; orPortState: ARRAY OrPorts OF OrPortParts _ [ owner: [outD: st.nOwnerOuts, A: st.nBOwnerIn, inD: st.nOwnerIns], shared: [outD: st.nSharedOuts, A: st.nBShareds, inD: st.nSharedIns], stop: [outD: st.nSStopOuts, A: st.nBSStops, inD: st.nSStopIns]]; DoClk: PROC [ cycles: INT _ 1, ignoreX: BOOL _ FALSE ] = { FOR i: INT IN [0..cycles) DO IgnoreOrPorts[]; MaskBug[]; st.p[st.Ck].b _ FALSE; Eval[ignoreX]; PredictOrPorts[]; st.p[st.Ck].b _ TRUE; Eval[ignoreX]; st.cycle _ st.cycle+1; ENDLOOP}; DoClkIgnoreX: PROC [ cycles: INT _ 1 ] = {DoClk[cycles, TRUE]}; DAShift: PROC [ val: BitOps.BitWord ] = { st.p[st.DBus][DAddress].b _ TRUE; EvalIgnoreX[]; DDShift[16, val]; st.p[st.DBus][DAddress].b _ FALSE; EvalIgnoreX[]}; DDShift: PROC [ size: [1..16], val: BitOps.BitWord ] = { FOR i: NAT IN [0..size) DO st.p[st.DBus][DSerialIn].b _ BitOps.EBFW[val, i, size]; st.p[st.DBus][DShiftCK].b _ FALSE; EvalIgnoreX[]; st.p[st.DBus][DShiftCK].b _ TRUE; EvalIgnoreX[]; ENDLOOP}; DDShiftCheck: PROC [ size: [1..16], valIn: BitOps.BitWord, valOut: BitOps.BitWord ] = { FOR i: NAT IN [0..size) DO st.p[st.DBus][DSerialIn].b _ BitOps.EBFW[valIn, i, size]; st.p[st.DBus][DShiftCK].b _ FALSE; st.p[st.DBus][DSerialOut].b _ BitOps.EBFW[valOut, i, size]; st.p[st.DBus][DSerialOut].d _ expect; EvalIgnoreX[]; st.p[st.DBus][DSerialOut].d _ none; st.p[st.DBus][DShiftCK].b _ TRUE; EvalIgnoreX[]; ENDLOOP}; IgnoreOrPorts: PROC = { FOR port: OrPorts IN [owner..owner] DO FOR dev: Devices IN Devices DO FOR arb: Arbiters IN Arbiters DO st.p[orPortState[port].outD][arb].d _ inspect; st.p[orPortState[port].inD][arb].d _ none; ENDLOOP; st.p[orPortState[port].A].d _ none ENDLOOP ENDLOOP; FOR port: OrPorts IN [shared..stop] DO FOR arb: Arbiters IN Arbiters DO FOR dev: Devices IN Devices DO st.p[orPortState[port].outD][arb][dev].d _ inspect; ENDLOOP; st.p[orPortState[port].A][arb].d _ none; st.p[orPortState[port].inD][arb].d _ none ENDLOOP ENDLOOP}; MaskBug: PROC = { k: INT _ st.cycle+PipeDepth; SELECT TRUE FROM k <= 2*PipeDepth => st.patchState _ 0; (st.patchState = 0) AND orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 1; shouldMaskRev1Bug AND (st.patchState = 1) AND st.p[st.nBusyIn].b => st.patchState _ 2; shouldMaskRev1Bug AND st.patchState IN [2..7] => st.patchState _ st.patchState+1; shouldMaskRev1Bug AND (st.patchState = 8) AND NOT orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 0; NOT shouldMaskRev1Bug AND (st.patchState = 1) AND NOT orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 0; ENDCASE => NULL; st.p[st.nStopAct].b _ NOT (st.forceStop OR (st.patchState > 0)); IF NOT st.p[st.nStopAct].b THEN st.noteBusBusyLast _ st.cycle+6; st.p[st.nBusyOuts][maxArbiters].d _ drive; st.p[st.nBusyOuts][maxArbiters].b _ (st.patchState <= 2); IF st.forceBusy OR (st.cycle < st.noteBusBusyLast) THEN { st.p[st.nDynaBusBusy].d _ drive; st.p[st.nDynaBusBusy].b _ FALSE} ELSE st.p[st.nDynaBusBusy].d _ none}; PredictOrPorts: PROC = { k: INT _ st.cycle+PipeDepth; FOR port: OrPorts IN [owner..owner] DO orOutD: BOOL _ FALSE; orA: BOOL _ orPortState[port].pipe[(k-1) MOD PipeDepth].inD; orInD: BOOL _ orPortState[port].pipe[(k-3) MOD PipeDepth].inD; FOR arb: Arbiters IN Arbiters DO orOutD _ orOutD OR NOT st.p[orPortState[port].outD][arb].b; IF k > 2*PipeDepth THEN { st.p[orPortState[port].inD][arb].d _ expect; st.p[orPortState[port].inD][arb].b _ NOT orInD} ENDLOOP; IF k > 2*PipeDepth THEN { st.p[orPortState[port].A].d _ expect; st.p[orPortState[port].A].b _ NOT orA}; orPortState[port].pipe[k MOD PipeDepth].inD _ orOutD ENDLOOP; FOR port: OrPorts IN [shared..stop] DO orOutD: BOOL _ FALSE; FOR arb: Arbiters IN Arbiters DO orOutDA: BOOL _ FALSE; FOR dev: Devices IN Devices DO orOutDA _ orOutDA OR NOT st.p[orPortState[port].outD][arb][dev].b ENDLOOP; orPortState[port].pipe[k MOD PipeDepth].A[arb] _ orOutDA; orOutD _ orOutD OR orOutDA; IF k > 2*PipeDepth THEN { st.p[orPortState[port].A][arb].d _ expect; st.p[orPortState[port].A][arb].b _ NOT orPortState[port].pipe[(k-1) MOD PipeDepth].A[arb]; st.p[orPortState[port].inD][arb].d _ expect; st.p[orPortState[port].inD][arb].b _ NOT orPortState[port].pipe[(k-3) MOD PipeDepth].inD} ENDLOOP; orPortState[port].pipe[k MOD PipeDepth].inD _ orOutD ENDLOOP}; dBusInits: Arbiter.DBusInitList _ NARROW[ CoreProperties.GetProp[st.cellType.properties, $DBusInits]]; st.p[st.nStopAct].d _ drive; FOR i: NAT IN (DSerialOut..DShiftCK] DO st.p[st.DBus][i].d _ drive; st.p[st.DBus][i].b _ FALSE ENDLOOP; st.p[st.DBus][DSerialOut].d _ none; FOR a: Arbiters IN Arbiters DO st.p[st.SlotNos][a].c _ 8H+a ENDLOOP; st.p[st.DBus][DExecute].b _ FALSE; st.p[st.DBus][nDFreeze].b _ TRUE; st.p[st.DBus][nDReset].b _ FALSE; st.p[st.DBus][DSerialIn].b _ FALSE; st.p[st.DBus][DShiftCK].b _ FALSE; st.p[st.DBus][DAddress].b _ FALSE; st.p[st.DBus][DSerialOut].b _ TRUE; st.p[st.DBus][DSerialOut].d _ driveWeak; FOR i: NAT IN [0..6) DO st.p[st.TIOBus][i].d _ driveStrong; -- we really don't care about this bus st.p[st.TIOBus][i].b _ FALSE ENDLOOP; FOR i: NAT IN [0..2) DO st.p[st.TRec2v][i].d _ drive; st.p[st.TRec2v][i].b _ TRUE ENDLOOP; st.p[st.TRec2v][2].d _ expect; st.p[st.TRec2v][2].b _ NOT st.p[st.TRec2v][0].b; st.p[st.TInv][0].d _ drive; st.p[st.TInv][0].b _ FALSE; st.p[st.TInv][1].d _ expect; st.p[st.TInv][1].b _ NOT st.p[st.TInv][0].b; st.cycle _ 0; st.noteBusBusyLast _ -1; st.forceStop _ TRUE; st.forceBusy _ TRUE; -- no starvation errors yet DoClkIgnoreX[6]; -- allow some X's to relax out st.forceStop _ FALSE; -- release Stop while holding Reset st.p[st.DBus][DShiftCK].b _ TRUE; DoClkIgnoreX[6]; -- allow more X's to relax out IF st.cycle > st.testCycles THEN RETURN; IF dBusInits # NIL THEN { checkBits: Ports.BoolSequence _ NEW[Ports.BoolSequenceRec[nCheckBits]]; a: Arbiters _ 0; DAShift[08000H+1000H*a]; -- check signature DDShiftCheck[16, 0, 5041H]; DAShift[08000H+1000H*a+2]; -- load arbiter number DDShift[4, 2*a+1]; -- decoded hybrid select DAShift[08000H+1000H*a+300H]; -- address hybrid 3 st.p[st.nDHybridSels][a].d _ expect; st.p[st.nDHybridSels][a].c _ 01FH-4; -- decoded EvalIgnoreX[]; st.p[st.nDHybridSels][a].d _ none; DAShift[08000H+1000H*a+2]; -- load arbiter number DDShift[4, 2*a]; -- now encoded DAShift[08000H+1000H*a+300H]; -- address hybrid 3 st.p[st.nDHybridSels][a].d _ expect; st.p[st.nDHybridSels][a].c _ 01FH-6; -- encoded, 5 bits EvalIgnoreX[]; st.p[st.nDHybridSels][a].d _ none; DAShift[08000H+1000H*a+400H]; -- address hybrid 4 DDShift[1, 0]; -- load BdVersion shadow DAShift[08000H+1000H*a+3H]; -- read the board version DDShiftCheck[2, 0, 2]; FOR dbir: LIST OF REF ANY _ dBusInits, dbir.rest WHILE dbir#NIL DO WITH dbir.first SELECT FROM dbi: REF DBusInitItem => { DAShift[08000H+dbi.addr]; -- load DBus destination number FOR i: NAT IN [0..dbi.bits.size+checkBits.size) DO outVal: [0..2); cbi: INT = i - dbi.bits.size; IF i < checkBits.size THEN { outVal _ rand.ChooseInt[max: 1]; checkBits[i] _ (outVal > 0) } ELSE outVal _ (IF dbi.bits[i-checkBits.size] THEN 1 ELSE 0); IF cbi < 0 THEN DDShift[1, outVal] ELSE DDShiftCheck[1, outVal, (IF checkBits[cbi] THEN 1 ELSE 0)] ENDLOOP }; ENDCASE => ERROR ENDLOOP }; st.forceStop _ TRUE; DoClkIgnoreX[10]; -- allow more X's to relax out st.forceStop _ FALSE; DoClkIgnoreX[10]; -- allow final X's to relax out DoClk[extraResetCycles]; -- see if any X's left st.forceStop _ TRUE; -- assert Stop, this terminates Arbiter's reset DoClk[6]; st.p[st.DBus][nDReset].b _ TRUE; -- release Reset, this terminates everybody else's reset st.p[st.DBus][nDFreeze].b _ TRUE; -- release Freeze, whatever that means DoClk[5]; st.forceStop _ FALSE; -- release Stop, begin arbitration DoClk[15]; st.forceBusy _ FALSE; -- allow starvation errors DoClk[st.testCycles - 1166]}; -- 1166 to init CedarProcess.DoWithPriority[priority: background, action: ReallyRunTest]}; simHighProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; simMediumProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; simLowProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; normalProb: ProbabilitiesRec _ [request: ALL[400], hold: 1000, stop: 1000, owner: 1000, shared: 1000]; zeroProb: ProbabilitiesRec _ [request: ALL[10000000], hold: never, stop: never, owner: never, shared: never]; higherProb: ProbabilitiesRec _ [request: ALL[30], hold: 100, stop: 100, owner: 100, shared: 100]; evenHigherProb: ProbabilitiesRec _ [request: ALL[10], hold: 100, stop: 100, owner: 100, shared: 100]; userProb: ProbabilitiesRec _ normalProb; GeneralArbSysTest: PROC [cellType: Core.CellType, p: Ports.Port, Eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL _ FALSE, checkPorts: BOOL _ TRUE], high, med, low: ProbabilitiesRec, captureVectors: BOOL _ FALSE, testCycles: INT _ 100000] = { st: State = NewState[cellType, p, Eval]; st.testCycles _ testCycles; FOR a: Arbiters IN Arbiters DO FOR d: Devices IN Devices DO rs: REF RequesterStateRec = NARROW[st.devs[a][d]]; rs.probs _ (SELECT TRUE FROM (a = 0) AND (d = 0) => simHighProb, (a = 0) => simMediumProb, ENDCASE => simLowProb) ENDLOOP ENDLOOP; simHighProb^ _ high; simMediumProb^ _ med; simLowProb^ _ low; IF captureVectors THEN st.capture _ MTSVector.CreateCapture[cellType]; RunTest[st, FALSE]; MTSVector.CloseCapture[st.capture]}; Test1Arb1Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, evenHigherProb, zeroProb, zeroProb, FALSE, 100000]}; Test1Arb8Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, FALSE, 100000]}; Test8Arb8Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, FALSE, 100000]}; Test1Arb8Req10: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, TRUE, 10]}; Test1Arb8Req2000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, TRUE, 2000]}; Test8Arb8ReqVec2000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, TRUE, 2000]}; Test8Arb8ReqVec10000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, TRUE, 10000]}; GetSystemTests: PUBLIC PROC RETURNS [listOfTests: LIST OF IO.ROPE] = { listOfTests _ LIST[ "Test1Arb1Req", "Test1Arb8Req", "Test8Arb8Req", "Test1Arb8Req10", "Test1Arb8Req2000", "Test8Arb8ReqVec2000", "Test8Arb8ReqVec10000" ]}; RosemaryUser.RegisterTestProc["Test1Arb1Req", Test1Arb1Req]; RosemaryUser.RegisterTestProc["Test1Arb8Req", Test1Arb8Req]; RosemaryUser.RegisterTestProc["Test8Arb8Req", Test8Arb8Req]; RosemaryUser.RegisterTestProc["Test1Arb8Req10", Test1Arb8Req10]; RosemaryUser.RegisterTestProc["Test1Arb8Req2000", Test1Arb8Req2000]; RosemaryUser.RegisterTestProc["Test8Arb8ReqVec2000", Test8Arb8ReqVec2000]; RosemaryUser.RegisterTestProc["Test8Arb8ReqVec10000", Test8Arb8ReqVec10000]; END. –ArbSysTests.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: McCreight September 27, 1988 3:10:40 pm PDT Jean-Marc Frailong October 4, 1988 11:51:04 am PDT Don Curry September 7, 1988 11:15:00 am PDT December 31, 1987 4:04:24 pm PST -- In ArbNov87A, the first fabrication of the Arbiter, there is a bug in the handling of nStopAct. The bug manifests itself as simultaneous grants from two arbiters when nStopAct is released. The problem is that nStopAct inhibits local grants, but part of the Arbiter's logic believes that system-wide grants are happening anyway. Approximately two cycles after the first erroneous "system-wide grant", if the grant was made at priority level 0 or 1 the grantee arbiter will compute the internal signal NoHold4 differently from the other arbiters. Then, assuming that there are other requests pending and BusyIn is not aserted, the grantee arbiter will assume a second erroneous "system-wide grant" while the other arbiters will not (until one cycle later, when conditions may have changed). This one cycle of difference allows the arbiters to get out of synchronization, a sure prescription for disaster later on. The code below incorporates the following patch: When nStopAct asserts, we wait thereafter until BusyIn deasserts for one cycle. Then we assert BusyIn for a minimum of five cycles, or until nStopAct deasserts, whichever is longer. ..indexes in cellType.public st.arbs[a] _ GetState[IO.PutFR["/Arb%d/ArbiterTop", IO.int[a]]]; -- until I figure out how to do this .... Glue logic to mask the bug in ArbNov87A: st.p[st.RecAdj].d _ drive; st.p[st.RecAdj].b _ TRUE; Check out the two ways of doing hybrid select: decoded and encoded ... assert Stop. This causes LclGrant4 to become FALSE, and begins clearing X's out of the ArbReq and Grant paths. ... release Stop. This applies a final reset to the Arbiter's input counters and the rover pointers. Κ˜šœ™Jšœ<™˜>Jšœ!˜!Jšœ#˜#Jšœ*˜*Jšœ˜Jšœ/˜/Jšœžœœ˜*Jšœ™—Jš œœ œœœœ˜'Jšœœ œœ œœœœœ˜?J˜—Jšœœ˜šœ-˜-J˜—šžœœ˜Jšœ˜Jšœ˜šœœ œœ œœœœ˜SJšœ˜—š žœœ œœœœ˜=˜J˜šœ˜J˜7———šœœ ˜Jšœ œ:˜I—J˜-J˜)J˜ Jšœ˜šœ\˜\JšœX˜X—Jšœ:˜:šœQ˜QJšœ&˜&—šœS˜SJšœ(˜(—šœU˜UJšœ*˜*—šœ_˜_Jšœ3˜3—šœg˜gJšœ:˜:—šœW˜WJšœ*˜*—šœ œ ˜šœœœ ™@JšŸ)™)—šœ œ ˜Jšœœœ œ ˜HJšœ˜—Jšœ˜ —J˜—š žœœœœ œœ˜7šœ œ ˜Jš œœœœœ ˜Jšœ œ ˜Jšœœœœ"œ œ œœ˜u——J˜J˜—Jšœœ˜Jšœœ˜šœœœ˜ J˜—šžœœœœ˜šœœ ˜ Jšœœœ%˜;šœœ˜Jšœ,˜,Jšœ%œœ˜8——šœœ˜Jšœ%˜%Jšœœ˜'—Jšœœœ˜=—šœœ˜&Jšœœœ˜šœœ ˜ Jšœ œœ˜šœœ ˜Jšœœœ*œ˜J—Jšœœ˜9Jšœœ ˜šœœ˜Jšœ*˜*Jšœ#œœ˜ZJšœ,˜,Jšœ%œœœ˜b——Jšœœœ˜>——šœ"œ˜)Jšœ=˜=—Jšœ˜šœœœ˜'Jšœ˜Jšœœœ˜#—Jšœ#˜#šœ œ ˜Jšœœ˜%—Jšœœ˜"Jšœœ˜!Jšœœ˜!Jšœœ˜#Jšœœ˜"Jšœœ˜"Jšœœ˜#Jšœ(˜(šœœœ˜Jšœ$Ÿ&˜JJšœœœ˜%—šœœœ˜Jšœ˜Jšœœœ˜$—Jšœ˜Jšœœ˜0Jšœ™Jšœœ™Jšœ˜Jšœœ˜Jšœ˜Jšœœ˜,J˜J˜ J˜Jšœœ˜JšœœŸ˜0J˜JšœŸ˜/JšœœŸ#˜9Jšœœ˜!JšœŸ˜/J˜Jšœœœ˜(šœ œœ˜Jšœ œ$˜GJšœ˜JšœŸ˜+Jšœ˜J™BJšœŸ˜1JšœŸ˜+JšœŸ˜1Jšœ$˜$Jšœ%Ÿ ˜/J˜Jšœ"˜"JšœŸ˜1JšœŸ˜JšœŸ˜1Jšœ$˜$Jšœ%Ÿ˜7J˜Jšœ"˜"JšœŸ˜1JšœŸ˜'JšœŸ˜5Jšœ˜J˜šœœœœœœœ˜Bšœ œ˜šœœ˜JšœŸ˜9šœœœ#˜2Jšœ˜Jšœœ˜šœœ˜Jšœ ˜ Jšœ˜—Jšœ œœœ˜