DIRECTORY Basics, Convert, FS, GPIB, IMSTester, IO, RefText, Rope; IMSTesterImpl: CEDAR MONITOR IMPORTS Basics, Convert, FS, GPIB, IO, RefText, Rope EXPORTS IMSTester = BEGIN OPEN IMSTester; IMS: GPIB.DeviceAddr = 1; statusIMS: NAT; maxPktSize: NAT = 512; channelsPerGroup: NAT = 32; IMSError: PUBLIC SIGNAL [msg: ROPE] = CODE; checkSyntax: PUBLIC BOOL _ FALSE; stop: PUBLIC BOOL _ FALSE; synOut: IO.STREAM _ NIL; validCycles: Cycle _ 0; --number of valid cycles in IMS memory forceBd, acquireBd, progBd: PACKED ARRAY SlotNumber OF BOOLEAN; Initialize: PUBLIC ENTRY PROC RETURNS [forceBoard, acquireBoard, programable: PACKED ARRAY SlotNumber OF BOOLEAN] = TRUSTED {{ -- the tester ENABLE UNWIND => NULL; rope: ROPE; stop _ FALSE; IF checkSyntax THEN synOut _ FS.StreamOpen["IMSTester.synout", $create] ELSE IF GPIB.InitializeController[] THEN { GPIB.InterfaceClear[]; GPIB.SelectedDeviceClear[IMS]} ELSE {IMSError["GPIB Controller Error!"]; RETURN; }; WriteDevice["INIT"]; --sets IMS modules to power-up condition FOR n: SlotNumber IN SlotNumber DO WriteDevice[IO.PutFR["CON? %g", IO.int[n]]]; rope _ ReadDevice[]; IF rope=NIL THEN { FOR slot: SlotNumber IN SlotNumber DO forceBoard[slot] _ (slot < 8) OR ((slot > 10) AND ((slot MOD 2)=1)); --reflects the current configuration acquireBoard[slot] _ (slot>11) AND ((slot MOD 2)=0); programable[slot] _ slot=7 OR slot=22; ENDLOOP; } ELSE { forceBoard[n] _ Rope.Find[rope, "STM", 0, FALSE]#-1; acquireBoard[n] _ Rope.Find[rope, "ACQ", 0, FALSE]#-1; programable[n] _ Rope.Find[rope, "PGM PGM", 0, FALSE]#-1 }; ENDLOOP; forceBd _ forceBoard; acquireBd _ acquireBoard; progBd _ programable; }}; RunDiagnostics: PUBLIC ENTRY PROC [extended: BOOL _ TRUE] = TRUSTED {{ ENABLE UNWIND => NULL; diagComplete: NAT = 196; IF extended THEN WriteDevice["DIAG ALL, EXT, ONCE"] -- wipes out pattern memory! ELSE WriteDevice["DIAG ALL, NORMAL, ONCE"]; IF NOT checkSyntax THEN UNTIL statusIMS = diagComplete DO statusIMS _ LOOPHOLE[GPIB.SelectedReadSerialPoll[IMS]]; ENDLOOP; WriteDevice["DIAG END"]; }}; DefineGroups: PUBLIC ENTRY PROC [forceGroups: ForceGroups, acquireGroups: AcquireGroups] = { ENABLE UNWIND => NULL; podTiming: PodTiming; sentBanner: BOOL _ FALSE; timingChannel: BOOL _ FALSE; rootName, name: ROPE; length: NAT; FOR fg: ForceGroups _ forceGroups, fg.rest UNTIL fg=NIL DO length _ 0; sentBanner _ FALSE; FOR ptg: PodTimingGroups _ fg.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO podTiming _ ptg.first.podTiming; timingChannel _ podTiming=AT OR podTiming=BT; IF NOT sentBanner THEN { sentBanner _ TRUE; IF timingChannel THEN { WriteDevice[IO.PutFR["RES %g TIM #TXT", IO.rope[fg.first.name]]]; IF fg.first.format#RZ AND fg.first.format#R1 THEN IMSError["Illegal Format for Timing group"]; } ELSE WriteDevice[IO.PutFR["RES %g FOR #TXT", IO.rope[fg.first.name]]]; }; IF NOT forceBd[ptg.first.slot] THEN IMSError[IO.PutFR["No force board in slot %g for Force group %g", IO.int[ptg.first.slot], IO.rope[fg.first.name]]]; IF fg.first.programable AND NOT progBd[ptg.first.slot] THEN IMSError[IO.PutFR["Force board in slot %g for Force group %g is not programable", IO.int[ptg.first.slot], IO.rope[fg.first.name]]]; rootName _ SELECT podTiming FROM A=>"A", B=>"B", AT=>"AT", BT=>"BT", ENDCASE=>ERROR; FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO IF timingChannel AND p.first.channel#0 THEN IMSError["Can only assign channel 0 in A/B timing groups"]; IF (length _ length+1)>channelsPerGroup THEN IMSError[IO.PutFR["Force Group '%g' exceeded %g channels", IO.rope[fg.first.name], IO.int[channelsPerGroup]]]; name _ IF timingChannel THEN rootName ELSE IO.PutFR["%g%g", IO.rope[rootName], IO.int[p.first.channel]]; WriteDevice[IO.PutFR["%g %g %g %g", IO.card[ptg.first.slot], IO.rope[name], IO.rope[p.first.signalName], IO.card[p.first.packagePin]]]; ENDLOOP; ENDLOOP; WriteDevice["RES END"]; DefineParameters[fg: LIST[fg.first]]; ENDLOOP; FOR ag: AcquireGroups _ acquireGroups, ag.rest UNTIL ag=NIL DO length _ 0; WriteDevice[IO.PutFR["RES %g %g #TXT", IO.rope[ag.first.name], IO.rope[IF ag.first.compare THEN "COM" ELSE "ACQ"]]]; FOR ptg: PodTimingGroups _ ag.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO IF NOT acquireBd[ptg.first.slot] THEN IMSError[IO.PutFR["No acquire board in slot %g for Acquire group %g", IO.int[ptg.first.slot], IO.rope[ag.first.name]]]; IF ag.first.programable AND NOT progBd[ptg.first.slot] THEN IMSError[IO.PutFR["Force board in slot %g for Force group %g is not programable", IO.int[ptg.first.slot], IO.rope[ag.first.name]]]; IF ag.first.compare AND NOT forceBd[ptg.first.slot+1] THEN IMSError[IO.PutFR["No force board in slot %g for Compare group %g", IO.int[ptg.first.slot+1], IO.rope[ag.first.name]]]; IF ptg.first.podTiming=AT OR ptg.first.podTiming=BT THEN IMSError["Cannot assign AT or BT in an Acquire group"]; FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO IF (length _ length+1)>channelsPerGroup THEN IMSError[IO.PutFR["Acquire Group '%g' exceeded %g channels", IO.rope[ag.first.name], IO.int[channelsPerGroup]]]; WriteDevice[IO.PutFR["%g %g%g %g %g", IO.card[ptg.first.slot], IO.rope[SELECT ptg.first.podTiming FROM A=>"A", B=>"B", ENDCASE=> ERROR], IO.card[p.first.channel], IO.rope[p.first.signalName], IO.card[p.first.packagePin]]]; ENDLOOP; ENDLOOP; WriteDevice["RES END"]; DefineParameters[ag: LIST[ag.first]]; ENDLOOP; }; RedefineGroups: PUBLIC ENTRY PROC [forceGroups: ForceGroups _ NIL, acquireGroups: AcquireGroups _ NIL] = { DefineParameters[fg: forceGroups, ag: acquireGroups]; }; DefineParameters: PRIVATE INTERNAL PROC [fg: ForceGroups _ NIL, ag: AcquireGroups _ NIL] = { FOR fgl: ForceGroups _ fg, fgl.rest WHILE fgl#NIL DO f: ForceGroup _ fgl.first; WriteDevice[IO.PutFR["FOR %g %g %gns %gns", IO.rope[f.name], IO.rope[SELECT f.format FROM NRZ=>"NRZ", DNRZ=>"DNRZ", RZ=>"RZ", R1=>"R1", RC=>"RC", ENDCASE=>"RI"], IO.int[f.delay], IO.int[f.width]]]; IF f.programable THEN { WriteDevice[IO.PutFR["HID %g %g", IO.rope[f.name], IO.real[f.hiDrive]]]; WriteDevice[IO.PutFR["LOD %g %g", IO.rope[f.name], IO.real[f.loDrive]]]; }; ENDLOOP; FOR agl: AcquireGroups _ ag, agl.rest WHILE agl#NIL DO a: AcquireGroup _ agl.first; WriteDevice[IO.PutFR["SAM %g %gns", IO.rope[a.name], IO.int[a.sample]]]; IF a.programable THEN WriteDevice[IO.PutFR["THR %g %g", IO.rope[a.name], IO.real[a.threshold]]]; ENDLOOP; }; SetCyclePeriod: PUBLIC ENTRY PROC [period: Period] = { ENABLE UNWIND => NULL; WriteDevice[IO.PutFR["CLK INT %gNS", IO.int[period]]]; }; SetIMSMemory: PUBLIC ENTRY PROC [forceGroups: ForceGroups, acquireGroups: AcquireGroups, buffer: Buffer, cycles: Cycle, halt: Cycle, jumps: Jumps _ NIL] = { ENABLE UNWIND => NULL; firstPTG: PodTimingGroup; firstControlBit: BOOL; vector: REF TEXT; bits: LONG CARDINAL; data: Data; validCycles _ cycles; vector _ RefText.ObtainScratch[maxPktSize]; vector.length _ 0; FOR now: Cycle IN [0..cycles) DO --build vector for this cycle IF stop THEN EXIT; vector _ RefText.AppendRope[vector, "MEM "]; vector _ RefText.AppendRope[vector, Convert.RopeFromCard[now]]; vector _ RefText.AppendRope[vector, " \""]; FOR fg: ForceGroups _ forceGroups, fg.rest UNTIL fg=NIL DO bits _ 0; firstPTG _ fg.first.podTimingGroups.first; firstControlBit _ buffer[now][firstPTG.board][(SELECT firstPTG.podTiming FROM A=>0, B=>8, AT=>16, BT=>17 ENDCASE=>ERROR)+firstPTG.pins.first.channel].inhibit; IF ~firstPTG.podTiming=AT AND ~firstPTG.podTiming=BT THEN { vector _ RefText.AppendChar[vector, IF firstControlBit THEN 'i ELSE 'f]; vector _ RefText.AppendChar[vector, ' ]; }; FOR ptg: PodTimingGroups _ fg.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO bits _ bits*2; data _ buffer[now][ptg.first.board][(SELECT ptg.first.podTiming FROM A=>0, B=>8, AT=>16, BT=>17 ENDCASE=>ERROR)+p.first.channel]; IF firstControlBit#data.inhibit THEN IMSError[IO.PutFR["Force group %g is not strictly Force or Inhibit", IO.rope[fg.first.name]]]; IF data.forceData THEN bits _ bits+1; ENDLOOP; ENDLOOP; vector _ Convert.AppendCard[to: vector, from: bits, base: 16, showRadix: FALSE]; vector _ RefText.AppendChar[vector, ' ]; ENDLOOP; FOR ag: AcquireGroups _ acquireGroups, ag.rest UNTIL ag=NIL DO IF ag.first.compare THEN { bits _ 0; firstPTG _ ag.first.podTimingGroups.first; firstControlBit _ buffer[now][firstPTG.board][(SELECT firstPTG.podTiming FROM A=>0, B=>8, AT=>16, BT=>17 ENDCASE=>ERROR)+firstPTG.pins.first.channel].mask; vector _ RefText.AppendChar[vector, IF firstControlBit THEN 'm ELSE 'c]; vector _ RefText.AppendChar[vector, ' ]; FOR ptg: PodTimingGroups _ ag.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO bits _ bits*2; data _ buffer[now][ptg.first.board][(SELECT ptg.first.podTiming FROM A=>0, B=>8, AT=>16, BT=>17 ENDCASE=>ERROR)+p.first.channel]; IF firstControlBit#data.mask THEN IMSError[IO.PutFR["Acquire group %g is not strictly Mask or Compare", IO.rope[ag.first.name]]]; IF data.compareData THEN bits _ bits+1; ENDLOOP; ENDLOOP; vector _ Convert.AppendCard[to: vector, from: bits, base: 16, showRadix: FALSE]; vector _ RefText.AppendChar[vector, ' ]; }; ENDLOOP; FOR l: Jumps _ jumps, l.rest WHILE l#NIL DO IF jumps.first.source=now THEN { IF halt=now THEN IMSError["Cannot Halt and Jump in same cycle!"]; vector _ RefText.AppendTextRope[vector, ": Goto "]; vector _ RefText.AppendRope[vector, IO.PutR1[IO.card[jumps.first.destination]]]; jumps _ jumps.rest; }; ENDLOOP; IF halt=now THEN vector _ RefText.AppendTextRope[vector, ": Halt"]; vector _ RefText.AppendRope[vector, IF checkSyntax THEN "\"\n" ELSE "\"\l"]; IF vector.length>(maxPktSize-100) THEN { --try not to go over maxPktSize WriteDevice[Rope.FromRefText[vector], now=cycles-1]; vector.length _ 0; }; REPEAT FINISHED => IF vector.length#0 THEN WriteDevice[Rope.FromRefText[vector], TRUE]; ENDLOOP; RefText.ReleaseScratch[vector]; }; ErrorCount: PUBLIC ENTRY PROC RETURNS [count: LONG CARDINAL] = { ENABLE UNWIND => NULL; s: IO.STREAM; IF checkSyntax THEN RETURN[0] ELSE { WriteDevice["FAIL?"]; s _ IO.RIS[ReadDevice[]]; IF NOT Rope.Equal[IO.GetTokenRope[s ! IO.EndOfStream => ERROR].token, "FAIL", FALSE] THEN ERROR; RETURN[IO.GetCard[s ! IO.EndOfStream => ERROR]]; }; }; GetErrors: PUBLIC ENTRY PROC [acquireGroups: AcquireGroups, buffer: Buffer, maxErrors: NAT, startCycle: Cycle, lastCycle: Cycle] RETURNS [errors: Errors] = { ENABLE UNWIND => NULL; s: IO.STREAM; err: Errors _ NIL; pinCount: NAT; mask, acquireData: LONG CARDINAL; expectData: Data; errCnt: NAT _ 0; IF validCycles=0 THEN RETURN[NIL]; IF lastCycle > (validCycles-1) THEN lastCycle _ validCycles-1; IF startCycle > (validCycles-1) THEN startCycle _ 0; IF NOT checkSyntax THEN WHILE startCycle <= lastCycle DO WriteDevice[IO.PutFR["FIND? SEQ %g", IO.card[startCycle]]]; s _ IO.RIS[ReadDevice[]]; IF NOT Rope.Equal[IO.GetTokenRope[s ! IO.EndOfStream => ERROR].token, "FIND", FALSE] THEN ERROR; IF NOT Rope.Equal[IO.GetTokenRope[s ! IO.EndOfStream => GOTO finished].token, "SEQ", FALSE] THEN ERROR; startCycle _ IO.GetCard[s ! IO.EndOfStream => ERROR]; IF startCycle>lastCycle THEN GOTO finished; WriteDevice[IO.PutFR["MEM? %g COM", IO.card[startCycle]]]; s _ IO.RIS[ReadDevice[! IO.EndOfStream => ERROR]]; WHILE ([]_s.GetChar[]) # '" DO ENDLOOP; --skip to opening quote FOR ag: AcquireGroups _ acquireGroups, ag.rest UNTIL ag=NIL DO --skip compare data [] _ IO.GetTokenRope[s ! IO.EndOfStream => ERROR]; --gets 'C or 'M designator [] _ IO.GetTokenRope[s ! IO.EndOfStream => ERROR]; --gets data ENDLOOP; FOR ag: AcquireGroups _ acquireGroups, ag.rest UNTIL ag=NIL DO --skip compare data pinCount _ 0; FOR ptg: PodTimingGroups _ ag.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO pinCount _ pinCount+1; ENDLOOP; ENDLOOP; acquireData _ Convert.CardFromRope[IO.GetTokenRope[s ! IO.EndOfStream => ERROR].token, 16]; mask _ Basics.DoubleShift[[lc[1]], pinCount-1].lc; FOR ptg: PodTimingGroups _ ag.first.podTimingGroups, ptg.rest UNTIL ptg=NIL DO FOR p: Pins _ ptg.first.pins, p.rest UNTIL p=NIL DO expectData _ buffer[startCycle][ptg.first.board][(SELECT ptg.first.podTiming FROM A=>0, B=>8, AT=>16, BT=>17 ENDCASE=>ERROR)+p.first.channel]; IF NOT expectData.mask AND XOR[(Basics.DoubleAnd[[lc[acquireData]], [lc[mask]]].lc#0), expectData.compareData] THEN { err _ CONS[[startCycle, ag.first, ptg.first, p.first, expectData.compareData, NOT expectData.compareData], err]; errCnt _ errCnt+1; IF errCnt > maxErrors THEN GOTO finished; }; mask _ Basics.DoubleShift[[lc[mask]], -1].lc; ENDLOOP; ENDLOOP; ENDLOOP; startCycle _ startCycle+1; REPEAT finished => NULL; ENDLOOP; errors _ NIL; FOR l: Errors _ err, l.rest WHILE l#NIL DO --put list in increasing order errors _ CONS[l.first, errors]; ENDLOOP; }; Start: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; WriteDevice["START ALL"] }; Stop: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; WriteDevice["STOP ALL"]; --current test operations IF checkSyntax AND synOut#NIL THEN IO.Close[synOut]; }; Wait: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; WriteDevice["WAIT ALL, 10s"]; }; XOR: PRIVATE INTERNAL PROC [a,b: BOOL] RETURNS [BOOL] = { RETURN[(a AND ~b) OR (~a AND b)] }; GetIMSStatusMsg: PRIVATE INTERNAL PROC RETURNS [msg: ROPE] = TRUSTED {{ errBuf: ROPE; IF checkSyntax THEN RETURN["GetIMSStatusMsg: No Status Message in Simulation."]; statusIMS _ LOOPHOLE[GPIB.SelectedReadSerialPoll[IMS]]; GPIB.WriteDevice[IMS, "Err?\l"]; errBuf_ GPIB.ReadDevice[IMS]; errBuf _ Rope.Substr[errBuf, Rope.Length["error \""], Rope.Length[errBuf]-3]; msg _ IO.PutFR["SRQ: %g; Error: %g", IO.card[statusIMS], IO.rope[errBuf]]; }}; WriteDevice: PRIVATE INTERNAL PROC [msg: ROPE, hold: BOOL _ TRUE] = TRUSTED {{ IF synOut=NIL THEN synOut _ FS.StreamOpen["IMSTester.synout", $create]; --check for NIL IF checkSyntax THEN synOut.PutF["%g\n", IO.rope[msg] ! IO.Error => {synOut _ FS.StreamOpen["IMSTester.synout", $create]; RETRY}] --handle the non-NIL but closed case ELSE GPIB.WriteDeviceBuffered[IMS, Rope.Concat[msg, "\l"], hold]; }}; ReadDevice: PRIVATE INTERNAL PROC RETURNS [memState: ROPE] = TRUSTED {{ IF NOT checkSyntax THEN RETURN[GPIB.ReadDevice[IMS]]; }}; END. τIMSTesterImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Gasbarro December 9, 1985 12:46:42 pm PST Last Edited by: Neil Gunther December 18, 1985 3:00:10 pm PST Last Edited by: Gasbarro May 8, 1986 10:06:23 am PDT -- Globals -- -- What about looping? Use IMSCommander for serious interrogation. --store diag results, someday(sigh!) WriteDevice[IO.PutFR["RAD %g BIN", IO.rope[f.name]]]; WriteDevice[IO.PutFR["RAD %g BIN", IO.rope[a.name]]]; Starts looking for errors at startCycle and continues until "maxErrors" errors are found or lastCycle is reached. IM$: find? seq 0 "" "???e" find (Seq 2,...) IM$: mem? 2 COM mem 2,Compare,"C 0000 M 00 C 00 C 00000002 FFFF 00 00 FFFFFFFF"," e" -- for HALT to be executed or timeout Κί– "cedar" style˜codešœ™Kšœ Οmœ1™šœž œ žœžœ˜?K˜—š Οn œžœ)ž œ žœžœžœ  ˜ŒKšžœ˜Kšœžœ˜ Kšœžœ˜ šžœ žœ žœ(˜Gšžœžœžœžœ˜+Jšžœ˜Jšžœ˜Jšžœ%˜)Jšž˜Jšœ˜——Jšœ (˜=šžœžœ ž˜"Kšœ žœžœ ˜,Kšœ˜šžœžœžœ˜šžœžœ ž˜%Kšœžœžœžœ  $˜jKšœžœžœ˜4Kšœžœ ˜&—Kšžœ˜Kšœžœ˜Kšœ*žœ˜4Kšœ,žœ˜6Kšœ0žœ˜9K˜—Kšžœ˜—JšœE˜EK˜K˜—š ‘œžœ žœžœžœ˜FKšœB™BKšžœ˜Kšœžœ˜šžœ ž˜Kšœ# ˜?—Kšžœ(˜,šžœžœ žœ˜šžœž˜!Kšœ žœžœžœ˜7Kšœ$™$Kšžœ˜——Kšœ˜K˜K˜—š‘ œžœ=˜\Kšžœ˜Kšœ˜Kšœ žœžœ˜Kšœžœžœ˜Kšœžœ˜Kšœžœ˜ šžœ(žœžœž˜:Kšœžœ˜šžœ;žœžœžœ˜OKšœ ˜ Kšœžœžœ žœ˜-šžœžœ žœ˜Kšœ žœ˜šžœžœ˜Kšœ žœžœ˜AKšžœžœžœžœ-˜^Kšœžœ žœžœ˜H—K˜—Kš žœžœžœ žœ7žœžœ˜—Kšžœžœžœžœ žœGžœžœ˜ΏKš œ žœ žœžœžœžœžœ˜Tšžœ"žœžœž˜3Kšžœžœžœ=˜hKšžœ&žœ žœ0žœ1˜›Kš œžœžœ žœžœžœžœ˜hKš œ žœžœžœ žœžœ˜‡Kšžœ˜—Kšžœ˜—Kšœ˜Kšœžœ ˜%Kšžœ˜ K˜—šžœ,žœžœž˜>Kšœ ˜ Kš œ žœžœžœžœžœžœ ˜tšžœ;žœžœžœ˜OKšžœžœžœx˜Kšžœžœžœžœ„˜ΏKšžœžœžœžœ žœ9žœžœ˜²Kš žœžœžœžœžœ8˜pšžœ"žœžœž˜3Kšžœ&žœ žœ2žœ1˜Kšœ žœžœžœžœžœžœžœžœžœžœ˜ήKšžœ˜—Kšžœ˜—Kšœ˜Kšœžœ ˜%Kšžœ˜ —K˜K˜—š ‘œžœžœžœžœ!žœ˜jKšœ5˜5K˜K˜—š ‘œžœžœžœžœžœ˜\šžœ!žœžœž˜4Kšœ˜Kšœ žœžœžœžœ žœžœ žœ žœžœžœ žœžœ˜ΕKšœ žœžœ™5šžœžœ˜Kšœ žœžœžœ˜HKšœ žœžœžœ˜HK˜—Kšžœ˜—šžœ#žœžœž˜6Kšœ˜Kšœ žœžœžœ˜HKšœ žœžœ™5Kš žœžœ žœžœžœ˜`Kšžœ˜—K˜K˜—š‘œžœ˜7Kšžœ˜Kšœ žœžœ˜6K˜K˜—š‘ œžœužœ˜œKšžœ˜Kšœ˜Kšœžœ˜Kšœžœ˜Kšœžœžœ˜Kšœ ˜ K˜Kšœ+˜+Kšœ˜šžœ žœ žœ ˜>Kšžœžœžœ˜Kšœ,˜,Kšœ?˜?Kšœ+˜+šžœ(žœžœž˜:Kšœ ˜ Kšœ*˜*Kš œ/žœžœ žœžœžœžœ'˜žš žœžœžœžœžœ˜;Kšœ$žœžœžœ˜HKšœ(˜(K˜—šžœ;žœžœžœ˜Ošžœ"žœžœž˜3Kšœ˜Kš œ%žœžœ žœžœžœžœ˜Kšžœžœ žœ:žœ˜ƒKšžœžœ˜%Kšžœ˜—Kšžœ˜—KšœIžœ˜PKšœ(˜(Kšžœ˜—šžœ,žœžœž˜>šžœžœ˜Kšœ ˜ Kšœ*˜*Kš œ/žœžœ žœžœžœžœ$˜›Kšœ$žœžœžœ˜HKšœ(˜(šžœ;žœžœžœ˜Ošžœ"žœžœž˜3Kšœ˜Kš œ%žœžœ žœžœžœžœ˜Kšžœžœ žœ;žœ˜Kšžœžœ˜'Kšžœ˜—Kšžœ˜—KšœIžœ˜PKšœ(˜(K˜—Kšžœ˜—šžœžœžœž˜+šžœžœ˜ Kšžœ žœΟzœ˜AKšœ3˜3Kšœ$žœžœ!˜PKšœ˜Kšœ˜—Kšžœ˜—Kšžœ žœ3˜CKšœ$žœ žœžœ ˜Lšžœ žœ ˜HKšœ4˜4K˜Kšœ˜—šž˜Kšžœžœžœ'žœ˜P—Kšžœ˜—Kšœ˜Kšœ˜K˜—š ‘ œžœžœžœžœ ž œ˜@Kšžœ˜Kšœžœžœ˜ šžœ žœžœžœ˜$Kšœ˜Kšœžœžœ˜Kšžœžœ žœžœžœžœžœžœ˜`Kšžœžœ žœžœ˜0Kšœ˜—K˜K˜—š‘ œžœ;žœ'žœ˜Kšœq™qKšžœ˜Kšœžœžœ˜ Kšœžœ˜Kšœ žœ˜Kšœžœžœ˜!K˜Kšœžœ˜Kšžœžœžœžœ˜"Kšžœžœ˜>Kšžœžœ˜4š žœžœ žœžœž˜8KšΠbfΟf™Kš€™Kšœ žœžœ˜Kšžœ˜—š žœ,žœžœžœ ˜RKšœ ˜ šžœ;žœžœžœ˜Ošžœ"žœžœž˜3K˜Kšžœ˜—Kšžœ˜—Kšœ#žœžœžœ ˜[Kšœ2˜2šžœ;žœžœžœ˜Ošžœ"žœžœž˜3Kš œ2žœžœ žœžœžœžœ˜Žš žœžœžœžœQžœ˜uKšœžœEžœ˜qKšœ˜Kšžœžœžœ ˜)Kšœ˜—Kšœ-˜-Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšœ˜Kšž˜Kšœ žœ˜Kšžœ˜—Kšœ žœ˜ š žœžœžœžœ ˜IKšœ žœ˜Kšžœ˜—K˜K˜—š‘œžœ˜Kšžœ˜Kšœ˜Kšœ˜K˜—š‘œžœ˜Kšžœ˜Kšœ ˜2Kš žœ žœžœžœžœ˜4Kšœ˜K˜—š‘œžœ˜Kš œ ™%Kšžœ˜Kšœ˜Kšœ˜K˜—š ‘œžœžœžœžœ˜9Kšžœžœžœžœ˜ Kšœ˜K˜—š ‘œžœžœžœžœ˜GKšœžœ˜ Kšžœ žœžœ6˜PKšœ žœžœ˜7Kšžœ˜ Kšœžœ˜KšœM˜MJšœžœžœžœ˜JK˜K˜—š‘ œžœž œžœžœžœžœ˜NKš žœžœžœ žœ* ˜Wšžœ žœžœ ˜5Kšœžœžœ*žœ $˜pKšžœžœžœ ˜A—K˜K˜K˜—š ‘ œžœž œžœ žœžœ˜GKš žœžœ ž œžœ žœ˜6K˜—K˜Kšžœ˜K˜—…—7TL'