DIRECTORY Basics, BitOps, CommandTool, FS, GPIB, IO, Process, Rope, TerminalIO, XBus; TRTestChip: CEDAR PROGRAM IMPORTS Basics, BitOps, CommandTool, FS, GPIB, IO, Process, Rope, TerminalIO, XBus ~ BEGIN ROPE: TYPE = Rope.ROPE; BITSHIFT: PROC [value: WORD, count: INTEGER] RETURNS [WORD] = Basics.BITSHIFT; BITAND: Basics.BitOp = Basics.BITAND; BITOR: Basics.BitOp = Basics.BITOR; BITXOR: Basics.BitOp = Basics.BITXOR; BITNOT: PROC [WORD] RETURNS [WORD] = Basics.BITNOT; Log2: PROC [n: INT] RETURNS [INT] = BitOps.Log2; Timing: TYPE = {Sample, Width, Delay}; PEReg: TYPE = [0..16); PEData: TYPE = [0..1024); Ram: TYPE = {VRam, HRam, ERam, CRam}; Channel: TYPE = [0..16); VRamAdd: TYPE = [0..1024); HalfClocks: TYPE = [0..20); InvStages: TYPE = [0..20); EdgeC: TYPE = [0..4); EdgeF: TYPE = [0..6); Delay: TYPE = [0..475); --nS Width: TYPE = [5..475); --nS Sample: TYPE = [0..480); --nS Period: TYPE = [30..480); --nS NSec: TYPE = CARDINAL; ClockDivisor: TYPE = {one, two, four, eight}; Phase: TYPE = {Even, Odd}; Edge: TYPE = {Leading, Trailing}; Transition: TYPE = {Up, Down}; Format: TYPE = {NRZ, RZ, RO, RC, RT}; DataPattern: TYPE = {p00, p11, p01, p10}; clock8112: GPIB.DeviceAddr = 12; fineMap: ARRAY EdgeF OF [0..16) = [4, 2, 12, 10, 1, 9]; baseAdd: LONG POINTER = LOOPHOLE[LONG[4000h]]; gClkPeriod: Period _ 50; --nS gClkDivisor: ClockDivisor _ one; gClockCtl: CARDINAL _ 0; gDebug: BOOL _ FALSE; gRamDebug: BOOL _ FALSE; gCycOffset: NSec _ 0; pause: NAT _ 100; pinElecBase: CARDINAL ~ 000h; -- up to 17Fh dsr0: CARDINAL ~ 000h; dsr1: CARDINAL ~ 001h; invCh0: CARDINAL ~ 002h; invCh1: CARDINAL ~ 003h; invCh2: CARDINAL ~ 004h; risingEdge: CARDINAL ~ 005h; fallingEdge: CARDINAL ~ 006h; ioCtl: CARDINAL ~ 007h; format: CARDINAL ~ 00fh; decompBase: CARDINAL ~ 180h; -- up to 1FFh writeLoopAdd: CARDINAL ~ 180h; writeEndAdd: CARDINAL ~ 181h; writeExtRamAdd: CARDINAL ~ 182h; writeExtRamCtl: CARDINAL ~ 183h; ramWD0: CARDINAL ~ 184h; ramWD1: CARDINAL ~ 185h; ramWD2: CARDINAL ~ 186h; ramWD3: CARDINAL ~ 187h; dramCtl: CARDINAL ~ 188h; readDebug: CARDINAL ~ 180h; readVRamAdd: CARDINAL ~ 181h; readHRamAdd: CARDINAL ~ 182h; readCmd: CARDINAL ~ 183h; ramRD0 : CARDINAL ~ 184h; ramRD1 : CARDINAL ~ 185h; ramRD2 : CARDINAL ~ 186h; ramRD3 : CARDINAL ~ 187h; extCtlBase: CARDINAL ~ 200h; -- up to 3FFh clkCtl: CARDINAL ~ 200h; refDelay: CARDINAL ~ 201h; phaseComp: CARDINAL ~ 001h; sampleLate: CARDINAL ~ 002h; analogSample: CARDINAL ~ 004h; ttlMode: CARDINAL ~ 008h; selLateData: CARDINAL ~ 010h; nrz: CARDINAL ~ 001h; rz: CARDINAL ~ 002h; ro: CARDINAL ~ 004h; rc: CARDINAL ~ 008h; rt: CARDINAL ~ 010h; writeCRam: CARDINAL ~ 101h; writeERam: CARDINAL ~ 102h; writeHRam: CARDINAL ~ 104h; writeVRam: CARDINAL ~ 108h; readCRam: CARDINAL ~ 110h; readERam: CARDINAL ~ 120h; readHRam: CARDINAL ~ 140h; readVRam: CARDINAL ~ 180h; extRamAccess: CARDINAL ~ 100h; vramBypass: CARDINAL ~ 200h; resetMinus1: CARDINAL ~ 001h; wrHRamLow: CARDINAL ~ 002h; wrHRamHigh: CARDINAL ~ 004h; fetchCmd: CARDINAL ~ 008h; prefetch: CARDINAL ~ 010h; error: CARDINAL ~ 020h; InitSystem: PROC ~ { IF gDebug THEN TerminalIO.PutRope["\nInit\n"]; InitGPIBDevices[]; SetRefDelayAbs[0]; CBusWrite[clkCtl, 0]; gClockCtl _ 0; SetClock[100]; }; Reset: PROC ~ { IF gDebug THEN TerminalIO.PutRope["Reset\n"]; StartCtl[FALSE, FALSE, FALSE]; CBusWrite[writeLoopAdd, 0]; CBusWrite[writeEndAdd, 0]; CBusWrite[writeExtRamCtl, 0]; StartCtl[FALSE, FALSE, TRUE]; StartCtl[FALSE, FALSE, FALSE]; }; RZDemo: PROC [lastChan: Channel] ~ { SetClock[200]; FindTZero[]; FOR ch: Channel IN [0..lastChan] DO RZMode[ch, ch*10, 20]; ENDLOOP; }; FindTZero: PROC ~ { biggest: Channel _ 0; new: NSec _ 0; gCycOffset _ 0; ClearAllPE[]; SetDataPattern[p10]; FOR ch: Channel IN Channel DO SetFormat[ch, RZ]; ForcePulseHigh[ch]; new _ MAX[FindOutputEdge[ch, Even, Up], FindOutputEdge[ch, Odd, Down]]; IF new>gCycOffset THEN {gCycOffset _ new; biggest _ ch}; ENDLOOP; TerminalIO.PutF["Cycle Start Offset = %g, chan: %g\n", IO.int[gCycOffset], IO.int[biggest]]; }; NRZMode: PROC [ch: Channel, delay: Delay] ~ { dhc, whc: HalfClocks _ 0; dis, wis: InvStages _ 0; delayFix: NAT _ 0; TerminalIO.PutF["Chan: %g, NRZ, Delay: %g\n", IO.int[ch], IO.int[delay]]; [dhc, dis] _ CalibrateDL[ch, Delay, delay]; [whc, wis] _ CalibrateDL[ch, Width, delay+20]; --doesn't matter how wide MakePulse[ch, NRZ, dhc, dis, whc, wis]; DO WHILE HoneEdge[ch, Leading, Even, Up, delay, p10] DO IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, NRZ, dhc, dis, whc, wis]; ENDLOOP; IF HoneEdge[ch, Leading, Odd, Up, delay, p01] THEN { IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, NRZ, dhc, dis, whc, wis]; LOOP; }; EXIT; ENDLOOP; SetDataPattern[p10]; --Display the result SetRefDelay[0]; }; RZMode: PROC [ch: Channel, delay: Delay, width: Width] ~ { dhc, whc: HalfClocks _ 0; dis, wis: InvStages _ 0; delayFix, widthFix: NAT _ 0; TerminalIO.PutF["Chan: %g, RZ, Delay: %g, Width: %g\n", IO.int[ch], IO.int[delay], IO.int[width]]; [dhc, dis] _ CalibrateDL[ch, Delay, delay]; [whc, wis] _ CalibrateDL[ch, Width, delay+width]; MakePulse[ch, RZ, dhc, dis, whc, wis]; DO WHILE HoneEdge[ch, Leading, Even, Up, delay, p10] DO IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, RZ, dhc, dis, whc, wis]; ENDLOOP; WHILE HoneEdge[ch, Trailing, Even, Down, delay+width, p10] DO IF (widthFix _ widthFix+1) > 7 THEN ERROR; [whc, wis] _ CalibrateDL[ch, Width, delay+width-widthFix]; MakePulse[ch, RZ, dhc, dis, whc, wis]; ENDLOOP; IF HoneEdge[ch, Leading, Odd, Up, delay, p01] THEN { IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, RZ, dhc, dis, whc, wis]; LOOP; }; IF HoneEdge[ch, Trailing, Odd, Down, delay+width, p01] THEN { IF (widthFix _ widthFix+1) > 7 THEN ERROR; [whc, wis] _ CalibrateDL[ch, Width, delay+width-widthFix]; MakePulse[ch, RZ, dhc, dis, whc, wis]; LOOP; }; EXIT; ENDLOOP; SetDataPattern[p11]; --Display the result SetRefDelay[0]; }; ROMode: PROC [ch: Channel, delay: Delay, width: Width] ~ { dhc, whc: HalfClocks _ 0; dis, wis: InvStages _ 0; delayFix, widthFix: NAT _ 0; TerminalIO.PutF["Chan: %g, RO, Delay: %g, Width: %g\n", IO.int[ch], IO.int[delay], IO.int[width]]; [dhc, dis] _ CalibrateDL[ch, Delay, delay]; [whc, wis] _ CalibrateDL[ch, Width, delay+width]; MakePulse[ch, RO, dhc, dis, whc, wis]; DO WHILE HoneEdge[ch, Leading, Even, Down, delay, p01] DO IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, RO, dhc, dis, whc, wis]; ENDLOOP; WHILE HoneEdge[ch, Trailing, Even, Up, delay+width, p01] DO IF (widthFix _ widthFix+1) > 7 THEN ERROR; [whc, wis] _ CalibrateDL[ch, Width, delay+width-widthFix]; MakePulse[ch, RO, dhc, dis, whc, wis]; ENDLOOP; IF HoneEdge[ch, Leading, Odd, Down, delay, p10] THEN { IF (delayFix _ delayFix+1) > 7 THEN ERROR; [dhc, dis] _ CalibrateDL[ch, Delay, delay-delayFix]; MakePulse[ch, RO, dhc, dis, whc, wis]; LOOP; }; IF HoneEdge[ch, Trailing, Odd, Up, delay+width, p10] THEN { IF (widthFix _ widthFix+1) > 7 THEN ERROR; [whc, wis] _ CalibrateDL[ch, Width, delay+width-widthFix]; MakePulse[ch, RO, dhc, dis, whc, wis]; LOOP; }; EXIT; ENDLOOP; SetDataPattern[p00]; --Display the result SetRefDelay[0]; }; RTMode: PROC [ch: Channel, delay: Delay, width: Width] ~ { RZMode[ch, delay, width]; SetFormat[ch, RT]; }; RCMode: PROC [ch: Channel, delay: Delay, width: Width] ~ { RZMode[ch, delay, width]; SetFormat[ch, RC]; }; MakePulse: PROC [ch: Channel, f: Format, dhc: HalfClocks, dis: InvStages, whc: HalfClocks, wis: InvStages] ~ { SetFormat[ch, f]; SetTimingChan[ch, Delay, dhc, dis]; SetTimingChan[ch, Width, whc, wis]; }; FindHC: PROC [ch: Channel, tg: Timing, t: Transition, start: HalfClocks _ 0] RETURNS [hc: HalfClocks _ 0] ~ { SetTimingChan[ch, tg, 0, 0]; hc _ start; WHILE NOT EdgeIsEarly[ch, t] DO SetTimingChan[ch, tg, (hc_hc+1), 0]; ENDLOOP; WHILE EdgeIsEarly[ch, t] DO SetTimingChan[ch, tg, (hc_hc+1), 0]; ENDLOOP; }; FindIS: PROC [ch: Channel, tg: Timing, hc: HalfClocks, t: Transition] RETURNS [is: InvStages _ 0]~ { SetTimingChan[ch, tg, hc, 0]; WHILE EdgeIsEarly[ch, t] DO SetTimingChan[ch, tg, hc, (is_is+1)]; ENDLOOP; }; CalibrateDL: PROC [ch: Channel, tg: Timing, ns: NSec] RETURNS [hc: HalfClocks, is: InvStages] ~ { Cal: PROC [t: Transition] RETURNS [hc: HalfClocks _ 0, is: InvStages _ 0] ~ { IF (hc _ FindHC[ch, tg, t]) = 0 THEN hc _ FindHC[ch, tg, t, 1]; hc _ hc-1; IF (is _ FindIS[ch, tg, hc, t]) = 0 THEN IF hc#0 THEN { hc _ hc-1; is _ FindIS[ch, tg, hc, t]; } ELSE { hc _ FindHC[ch, tg, t, 2]-1; is _ FindIS[ch, tg, hc, t]; IF is=0 THEN ERROR; }; is_is-1; SetTimingChan[ch, tg, hc, is]; }; hce, hco: HalfClocks; ise, iso: InvStages; SetRefPhase[Even]; SetDataPattern[p11]; SetFormat[ch, RZ]; IF tg=Delay THEN SetDelayPassThru[ch] ELSE SetWidthPassThru[ch]; SetRefDelay[ns]; [hce, ise] _ Cal[Up]; SetRefPhase[Odd]; [hco, iso] _ Cal[Down]; [hc, is] _ MinDelay[hce, ise, hco, iso]; IF gDebug THEN TerminalIO.PutF["Half Clocks: %g, Inv Stages: %g\n", IO.int[hc], IO.int[is]]; }; HoneEdge: PROC [ch: Channel, e: Edge, p: Phase, t: Transition, ns: NSec, pat: DataPattern] RETURNS [tooLate: BOOL _ FALSE] ~ { ec: EdgeC _ 0; SetRefPhase[p]; SetRefDelay[ns]; SetDataPattern[pat]; FOR i: NAT IN EdgeC DO TweakEdge[ch, e, p, (ec _ i), 0]; Process.PauseMsec[pause]; IF NOT EdgeIsEarly[ch, t] THEN EXIT; ENDLOOP; IF ec#0 THEN TweakEdge[ch, e, p, (ec _ ec-1), 0] ELSE { TerminalIO.PutF["Too early\n"]; RETURN[TRUE]; }; FOR i: NAT IN EdgeF DO TweakEdge[ch, e, p, ec, i]; Process.PauseMsec[pause]; IF NOT EdgeIsEarly[ch, t] THEN GOTO foundIt; REPEAT foundIt => {TerminalIO.PutF[" %g %g EdgeC: %g, EdgeF: %g\n", IO.rope[IF e=Leading THEN "Leading" ELSE "Trailing"], IO.rope[IF p=Even THEN "Even" ELSE "Odd"], IO.int[ec], IO.int[i]]}; FINISHED => TerminalIO.PutF["Exceeded range\n"]; ENDLOOP; }; TweakEdge: PROCEDURE [ch: Channel, e: Edge, p: Phase, ec: EdgeC, ef: EdgeF] = { PEWrite[ch, IF p=Odd THEN risingEdge ELSE fallingEdge, MapEdge[ec, ef], IF e=Leading THEN Delay ELSE Width]; }; ClearAllPE: PROC ~ { FOR c: Channel IN Channel DO ClearPEChan[c]; ENDLOOP; }; ClearPEChan: PROC [c: Channel] ~ { FOR t: Timing IN Timing DO SetTimingChan[c, t, 0, 0]; ENDLOOP; PEWrite[c, ioCtl, 0]; PEWrite[c, format, nrz]; }; WhichRamRope: PROC [which: Ram] RETURNS [r: ROPE] ~ { SELECT which FROM VRam => r _ "VRam"; HRam => r _ "HRam"; ERam => r _ "ERam"; CRam => r _ "CRam"; ENDCASE => ERROR; }; MinDelay: PROC [hc0: HalfClocks, is0: InvStages, hc1: HalfClocks, is1: InvStages] RETURNS [hs: HalfClocks, is: InvStages] ~ { SELECT TRUE FROM hc0>hc1 => RETURN[hc1, is1]; hc0 RETURN[hc0, is0]; hc0=hc1 AND is0>is1 => RETURN[hc1, is1]; hc0=hc1 AND is0 RETURN[hc0, is0]; ENDCASE => RETURN[hc0, is0]; }; SetTimingChan: PROC [chan: Channel, timing: Timing, halfClocks: HalfClocks, invStages: InvStages, upEdgeC: EdgeC _ 0, upEdgeF: EdgeF _ 0, dnEdgeC: EdgeC _ 0, dnEdgeF: EdgeF _ 0] ~ { PEWrite[chan, dsr0, DSR[halfClocks].high, timing]; PEWrite[chan, dsr1, DSR[halfClocks].low, timing]; PEWrite[chan, invCh0, IC[invStages, FALSE, FALSE].high, timing]; PEWrite[chan, invCh1, IC[invStages, FALSE, FALSE].mid, timing]; PEWrite[chan, invCh2, IC[invStages, FALSE, FALSE].low, timing]; PEWrite[chan, risingEdge, MapEdge[upEdgeC, upEdgeF], timing]; PEWrite[chan, fallingEdge, MapEdge[dnEdgeC, dnEdgeF], timing]; }; DSR: PROC [halfClocks: HalfClocks] RETURNS [high, low: CARDINAL] ~ { c: BitOps.BitDWord _ 0; c _ BitOps.IBID[TRUE, c, halfClocks/2, 12]; c _ BitOps.IBID[TRUE, c, IF (halfClocks MOD 2)=0 THEN 10 ELSE 11, 12]; high _ BitOps.ECFD[c, 0, 8, 12]; low _ BITSHIFT[BitOps.ECFD[c, 8, 4, 12], 4]; --left justify result }; IC: PROC [invStages: InvStages, forceH, forceL: BOOL] RETURNS [high, mid, low: CARDINAL] ~ { c: BitOps.BitDWord _ 0; c _ BitOps.IBID[TRUE, c, invStages, 22]; IF forceL THEN c _ BitOps.IBID[TRUE, c, 20, 22]; IF forceH THEN c _ BitOps.IBID[TRUE, c, 21, 22]; high _ BitOps.ECFD[c, 0, 8, 22]; mid _ BitOps.ECFD[c, 8, 8, 22]; low _ BITSHIFT[BitOps.ECFD[c, 16, 6, 22], 2]; --left justify result }; MapEdge: PROC [edgeC: EdgeC, edgeF: EdgeF] RETURNS [CARDINAL] ~ { RETURN[BITOR[BITSHIFT[80h, -edgeC], fineMap[edgeF]]]; }; RamWrite: PROC [which: Ram, add: [0..1023], d0, d1, d2, d3: [0..1023]] ~ { IF gRamDebug THEN TerminalIO.PutRope[IO.PutFLR["Write %g Add: %x, Data: %x, %x, %x, %x\n", LIST[IO.rope[ SELECT which FROM VRam => "VRam", HRam => "HRam", ERam => "ERam", CRam => "CRam", ENDCASE => ERROR], IO.card[add], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; CBusWrite[writeExtRamAdd, add]; LoadRamWD[d0, d1, d2, d3]; CBusWrite[writeExtRamCtl, extRamAccess]; CBusWrite[writeExtRamCtl, SELECT which FROM VRam => writeVRam, HRam => writeHRam, ERam => writeERam, CRam => writeCRam, ENDCASE => ERROR]; CBusWrite[writeExtRamCtl, extRamAccess]; CBusWrite[writeExtRamCtl, 0]; }; RamRead: PROC [which: Ram, add: [0..1023]] RETURNS [d0, d1, d2, d3: [0..1023]] ~ { CBusWrite[writeExtRamAdd, add]; CBusWrite[writeExtRamCtl, extRamAccess]; CBusWrite[writeExtRamCtl, SELECT which FROM VRam => readVRam, HRam => readHRam, ERam => readERam, CRam => readCRam, ENDCASE => ERROR]; [d0, d1, d2, d3] _ FetchRamRD[]; CBusWrite[writeExtRamCtl, 0]; IF gRamDebug THEN TerminalIO.PutRope[IO.PutFLR["Read %g Add: %x, Data: %x, %x, %x, %x\n", LIST[IO.rope[ SELECT which FROM VRam => "VRam", HRam => "HRam", ERam => "ERam", CRam => "CRam", ENDCASE => ERROR], IO.card[add], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; }; LoadRamWD: PROC [d0, d1, d2, d3: [0..1023]] ~ { CBusWrite[ramWD0, d0]; CBusWrite[ramWD1, d1]; CBusWrite[ramWD2, d2]; CBusWrite[ramWD3, d3]; }; FetchRamRD: PROC RETURNS [d0, d1, d2, d3: [0..1023]] ~ { d0 _ CBusRead[ramRD0]; d1 _ CBusRead[ramRD1]; d2 _ CBusRead[ramRD2]; d3 _ CBusRead[ramRD3]; }; InitGPIBDevices: PROC ~ TRUSTED { IF ~GPIB.InitializeController[] THEN ERROR; GPIB.InterfaceClear[]; GPIB.SelectedDeviceClear[clock8112]; GPIB.SelectedRemoteEnable[clock8112]; WriteGPIB[clock8112, "W1 DTY 50% HIL -0.5V LOL -2.0V D0"]; }; ForcePulseHigh: PROC [ch: Channel] = { SetTimingChan[ch, Delay, 0, 0]; SetTimingChan[ch, Width, 0, 0]; PEWrite[ch, invCh0, 0, Delay]; PEWrite[ch, invCh2, IC[0, TRUE, FALSE].low, Delay]; PEWrite[ch, invCh0, 0, Width]; PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Width]; }; ForcePulseLow: PROC [ch: Channel] = { SetTimingChan[ch, Delay, 0, 0]; SetTimingChan[ch, Width, 0, 0]; PEWrite[ch, invCh0, 0, Delay]; PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Delay]; PEWrite[ch, invCh0, 0, Width]; PEWrite[ch, invCh2, IC[0, TRUE, FALSE].low, Width]; }; SetDelayPassThru: PROC [ch: Channel] ~ { IF gDebug THEN TerminalIO.PutF["Set Delay pass thru\n"]; SetTimingChan[ch, Delay, 0, 0]; SetTimingChan[ch, Width, 0, 0]; PEWrite[ch, invCh2, IC[0, FALSE, FALSE].low, Delay]; PEWrite[ch, invCh0, 0, Width]; PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Width]; }; SetWidthPassThru: PROC [ch: Channel] ~ { IF gDebug THEN TerminalIO.PutF["Set Width pass thru\n"]; SetTimingChan[ch, Delay, 0, 0]; SetTimingChan[ch, Width, 0, 0]; PEWrite[ch, invCh0, 0, Delay]; PEWrite[ch, invCh2, IC[0, FALSE, TRUE].low, Delay]; PEWrite[ch, invCh2, IC[0, FALSE, FALSE].low, Width]; }; SetDataPattern: PROC [dp: DataPattern] ~ { Reset[]; IF gDebug THEN TerminalIO.PutF["Set pattern: %g\n", IO.rope[SELECT dp FROM p00 => "00", p01 => "01", p10 => "10", p11 => "11", ENDCASE => ERROR]]; RamWrite[CRam, 0, 03Fh, 3FFh, 0h, 0h]; --mask: FFFF, inhibit: 0000 SELECT dp FROM p00 => { RamWrite[VRam, 0, 2h, 0h, 0h, 0h]; --Lit 2, 00, 00, 00 RamWrite[VRam, 1, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0 RamWrite[VRam, 2, 2h, 0h, 0h, 0h]; --Lit 2, 00, 00, 00 RamWrite[VRam, 3, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0 }; p01 => { RamWrite[VRam, 0, 2h, 0h, 0h, 3Fh]; --Lit 2, 00, 00, 3f RamWrite[VRam, 1, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0 RamWrite[VRam, 2, 2h, 0h, 0h, 3Fh]; --Lit 2, 00, 00, 3f RamWrite[VRam, 3, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0 }; p10 => { RamWrite[VRam, 0, 2h, 3Fh, 3FFh, 0h]; --Lit 2, 3f, 3FF, 00 RamWrite[VRam, 1, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0 RamWrite[VRam, 2, 2h, 3Fh, 3FFh, 0h]; --Lit 2, 3f, 3FF, 00 RamWrite[VRam, 3, 0h, 080h, 080h, 080h]; -- 00,Cpy 2@0,Cpy 2@0,Cpy 2@0 }; p11 => { RamWrite[VRam, 0, 2h, 3Fh, 3FFh, 3Fh]; --Lit 2, 3f, 3FF, 3f RamWrite[VRam, 1, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0 RamWrite[VRam, 2, 2h, 3Fh, 3FFh, 3Fh]; --Lit 2, 3f, 3FF, 3f RamWrite[VRam, 3, 3FFh, 080h, 080h, 080h]; -- 3FF,Cpy 2@0,Cpy 2@0,Cpy 2@0 }; ENDCASE => ERROR; CBusWrite[writeLoopAdd, 0]; CBusWrite[writeEndAdd, 3]; StartCtl[TRUE, TRUE, FALSE]; }; FindOutputEdge: PROC [ch: Channel, p: Phase, t: Transition] RETURNS [time: NSec _ 0] ~ { SetRefPhase[p]; SetRefDelayAbs[time]; WHILE NOT EdgeIsEarly[ch, t] DO SetRefDelayAbs[(time _ time+1)]; ENDLOOP; }; EdgeIsEarly: PROCEDURE [ch: Channel, t: Transition] RETURNS [BOOL] = { trueCount, falseCount: NAT _ 0; FOR i: NAT IN [0..7) DO IF (t=Down) = (BITAND[PERead[ch, ioCtl], phaseComp]#0) THEN trueCount _ trueCount+1 ELSE falseCount _ falseCount + 1; ENDLOOP; IF gDebug THEN TerminalIO.PutF[" %g/%g ", IO.card[trueCount], IO.card[falseCount]]; RETURN[trueCount>falseCount]; }; SetFormat: PROC [ch: Channel, f: Format] = { PEWrite[ch, format, SELECT f FROM NRZ => nrz, RZ => rz, RO => ro, RC=> rc, RT => rt, ENDCASE => ERROR]; IF gDebug THEN TerminalIO.PutF["Set format: %g\n", IO.rope[SELECT f FROM NRZ => "NRZ", RZ => "RZ", RO => "RO", RC=> "RC", RT => "RT", ENDCASE => ERROR]] }; SetTTLLevels: PROC [ch: Channel, b: BOOL] = { PEWrite[ch, ioCtl, BitOps.IBIW[b, PERead[ch, ioCtl], 1, 5]]; }; SetRefDelayAbs: PROC [d: Delay] ~ { CBusWrite[refDelay, d]; IF gDebug THEN TerminalIO.PutF["Ref clock delay: %g\n", IO.card[d]]; }; SetRefDelay: PROC [d: Delay] ~ { SetRefDelayAbs[d+gCycOffset]; }; SetClock: PROC [period: Period] ~ { divisor: ClockDivisor; SELECT TRUE FROM period IN [30..70) => {divisor _ one; gClkPeriod _ period}; period IN [70..140) => {divisor _ two; gClkPeriod _ (period+1)/2}; period IN [140..280) => {divisor _ four; gClkPeriod _ (period+2)/4}; period IN [280..560) => {divisor _ eight; gClkPeriod _ (period+4)/8}; ENDCASE => ERROR; SetClockDivisor[divisor]; WriteGPIB[clock8112, IO.PutFR["PER %gNS", IO.card[gClkPeriod]]]; IF gDebug THEN TerminalIO.PutF["Set clock to %g ns\n", IO.card[period]] }; StartCtl: PROC [start, loop, reset: BOOL _ FALSE] ~ { gClockCtl _ BitOps.IBIW[start, gClockCtl, 5, 8]; gClockCtl _ BitOps.IBIW[loop, gClockCtl, 4, 8]; gClockCtl _ BitOps.IBIW[reset, gClockCtl, 0, 8]; CBusWrite[clkCtl, gClockCtl]; }; SetRefPhase: PROC [p: Phase] ~ { gClockCtl _ BitOps.IBIW[p=Even, gClockCtl, 2, 8]; CBusWrite[clkCtl, gClockCtl]; IF gDebug THEN TerminalIO.PutF["Set reference phase %g\n", IO.rope[IF p=Even THEN "Even" ELSE "Odd"]] }; SetClockDivisor: PROC [cd: ClockDivisor] ~ { gClockCtl _ BitOps.ICIW[ORD[cd], gClockCtl, 6, 2, 8]; CBusWrite[clkCtl, gClockCtl]; gClkDivisor _ cd; }; PEWrite: PROC [chan: Channel, reg: PEReg, data: PEData, timing: Timing _ Sample] ~ { CBusWrite[(chan*24)+(timing.ORD*8)+reg, data]; }; PERead: PROC [chan: Channel, reg: PEReg, timing: Timing _ Sample] RETURNS [data: PEData] ~ { data _ BITAND[CBusRead[(chan*24)+(timing.ORD*8)+reg], 0FFh]; --PE only uses 8 bits }; CBusRead: PROC [add: [0..1023]] RETURNS [data: [0..1023]] ~ { data _ XBus.IORead[baseAdd + add*2]; }; CBusWrite: PROC [add: [0..1023], data: [0..1023]] ~ { XBus.IOWrite[baseAdd + add*2, data]; }; WriteGPIB: PROCEDURE [device: GPIB.DeviceAddr, msg: Rope.ROPE] = TRUSTED { GPIB.WriteDevice[device, Rope.Concat[msg, "\n\l"]]; }; add: NAT _ 4; loop: NAT _ 1; data: CARDINAL _ 03FFh; VRamTest: PROC = { FOR j: NAT IN [0..add) DO RamWrite[VRam, j, j, j, j, j]; ENDLOOP; FOR i: NAT IN [0..loop) DO FOR j: NAT IN [0..add) DO RamWrite[VRam, 128+j, data, data, data, data]; [] _ RamRead[VRam, 128+j]; ENDLOOP; ENDLOOP; gRamDebug _ TRUE; FOR j: NAT IN [0..add) DO [] _ RamRead[VRam, j]; ENDLOOP; FOR j: NAT IN [0..add) DO [] _ RamRead[VRam,128+j]; ENDLOOP; gRamDebug _ FALSE; }; RAMWriteReadTest: PROC ~ { TerminalIO.PutRope["\n***RAM Write/Read Test***\n"]; Reset[]; RAMTest[HRam, 32]; RAMTest[CRam, 16]; RAMTest[ERam, 16]; RAMTest[VRam, 1024]; }; RAMTest: PROC [which: Ram, size: NAT, start: NAT _ 0] = { d0, d1, d2, d3: [0..1023] _ 0; FOR i: NAT IN [start..start+size) DO RamWrite[which, i, 2A0h, 2A1h, 2A2h, 2A3h]; ENDLOOP; Process.PauseMsec[pause]; FOR i: NAT IN [start..start+size) DO [d0, d1, d2, d3] _ RamRead[which, i]; IF d0#2A0h OR d1#2A1h OR d2#2A2h OR d3#2A3h THEN TerminalIO.PutRope[IO.PutFLR["ERROR Pass1: %g add: %g, data: %x %x %x %x\n", LIST[IO.rope[WhichRamRope[which]], IO.card[i], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; RamWrite[which, i, 150h, 151h, 152h, 153h]; ENDLOOP; Process.PauseMsec[pause]; FOR i: NAT IN [start..start+size) DO [d0, d1, d2, d3] _ RamRead[which, i]; IF d0#150h OR d1#151h OR d2#152h OR d3#153h THEN TerminalIO.PutRope[IO.PutFLR["ERROR Pass 2: %g add: %g, data: %x %x %x %x\n", LIST[IO.rope[WhichRamRope[which]], IO.card[i], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; ENDLOOP; }; Test: PROC = { RegWriteReadTest[]; RAMWriteReadTest[]; }; VRead: PROC [start, end: NAT] ~ { d0, d1, d2, d3: [0..1023] _ 0; FOR i:NAT IN [start..end) DO [d0, d1, d2, d3] _ RamRead[VRam, i]; TerminalIO.PutRope[IO.PutFR["%x %x %x %x\n", IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]; ENDLOOP; TerminalIO.PutRope["\n"]; }; VReadLoop: PROC [start, end: NAT] ~ { DO FOR i:NAT IN [start..end) DO [] _ RamRead[VRam, i]; ENDLOOP; Process.CheckForAbort[]; ENDLOOP; }; VWrite: PROC [start, end: NAT, data: NAT] ~ { FOR i:NAT IN [start..end) DO RamWrite[VRam, i, data, data, data, data]; ENDLOOP; }; VWriteLoop: PROC [start, end, data: NAT] ~ { DO VWrite[start, end, data]; Process.CheckForAbort[]; ENDLOOP; }; DecompSpeedTest: PROC ~ { Reset[]; RamWrite[HRam, 1, 0, 0, 03fh, 03ffh]; RamWrite[CRam, 0, 03Fh, 3FFh, 0h, 0h]; --mask: FFFF, inhibit: 0000 CBusWrite[writeEndAdd, 0]; CBusWrite[writeExtRamCtl, vramBypass]; LoadRamWD[042h, 043h, 042h, 043h]; --Cpy:1@2, Cpy:1@3, Cpy:1@2, Cpy:1@3 StartCtl[TRUE, TRUE, FALSE]; }; BypassLoopTest: PROC ~ { d0, d1, d2, d3: NAT; TerminalIO.PutRope["\n***Bypass Loop Test***\n"]; Reset[]; CBusWrite[writeEndAdd, 0]; CBusWrite[writeExtRamCtl, vramBypass]; LoadRamWD[1h, 155h, 155h, 03C0h]; --Lit:1; 155h 155h; Cpy:15@0 StartCtl[TRUE, TRUE, FALSE]; StartCtl[FALSE, FALSE, FALSE]; FOR i: NAT IN [0..32) DO [d0, d1, d2, d3] _ RamRead[HRam, i]; IF d0#155h OR d1#155h OR d2#155h OR d3#155h THEN TerminalIO.PutRope[IO.PutFLR["ERROR Pass 1: HRam add: %g, data: %x %x %x %x\n", LIST[IO.card[i], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; ENDLOOP; LoadRamWD[1h, 2AAh, 2AAh, 03C0h]; --Lit:1; 2AAh 2AAh; Cpy:15@0 StartCtl[TRUE, TRUE, FALSE]; StartCtl[FALSE, FALSE, FALSE]; FOR i: NAT IN [0..32) DO [d0, d1, d2, d3] _ RamRead[HRam, i]; IF d0#155h OR d1#155h OR d2#155h OR d3#155h THEN TerminalIO.PutRope[IO.PutFLR["ERROR Pass 2: HRam add: %g, data: %x %x %x %x\n", LIST[IO.card[i], IO.card[d0], IO.card[d1], IO.card[d2], IO.card[d3]]]]; ENDLOOP; }; RegWriteReadTest: PROC [a: CARDINAL _ 02AAh, b: CARDINAL _ 0155h] ~ { ErrMsg: PROC [c: Channel, r: PEReg, t: Timing, x, y, z: PEData] ~ { TerminalIO.PutRope[IO.PutFLR["Chan: %g, Reg: %g, %g, expected: %x, got: %x, xor: %x\n", LIST[IO.card[c], IO.card[r], IO.rope[SELECT t FROM Sample => "Sample", Delay=> "Delay", Width => "Width", ENDCASE => ERROR], IO.card[x], IO.card[y], IO.card[z]]]]; }; map: ARRAY [0..7) OF CARDINAL _ [0FFh, 0F0h, 0FFh, 0FFh, 0FCh, 0FFh, 0FFh]; y, exp: CARDINAL _ 0; TerminalIO.PutRope["\n***Register Write/Read Test***\n"]; Reset[]; FOR p: NAT IN [0..7) DO FOR c: Channel IN Channel DO FOR t: Timing IN Timing DO PEWrite[c, p, a, t]; exp _ BITAND[a, map[p]]; IF (y _ BITAND[PERead[c, p, t], map[p]])#exp THEN ErrMsg[c, p, t, exp, y, BITXOR[y, exp]]; PEWrite[c, p, b, t]; exp _ BITAND[b, map[p]]; IF (y _ BITAND[PERead[c, p, t], map[p]])#exp THEN ErrMsg[c, p, t, exp, y, BITXOR[y, exp]]; ENDLOOP; ENDLOOP; ENDLOOP; }; VRamLoopTest: PROC ~ { b: BOOL _ gRamDebug; TerminalIO.PutRope["\n***VRam Loop Test***\n"]; Reset[]; FOR c: Channel IN Channel DO SetTimingChan[c, Delay, 2, 0, 0, 0, 0, 0]; SetTimingChan[c, Width, 4, 0, 0, 0, 0, 0]; SetTimingChan[c, Sample, 0, 0, 0, 0, 0, 0]; PEWrite[c, ioCtl, 0]; PEWrite[c, format, rz]; ENDLOOP; RamWrite[CRam, 0, 01Fh, 3FFh, 000h, 0h]; --mask: 7FFF, inhibit: 0000 RamWrite[VRam, 0, 5h, 0h, 0h, 20h]; --Lit 5, 0000, 20 RamWrite[VRam, 1, 1h, 0h, 2h, 20h]; -- 01, 0002, 20 RamWrite[VRam, 2, 3h, 0h, 4h, 140h]; -- 03, 0004, Cpy 5@0 RamWrite[VRam, 3, 1h, 0h, 3FFh, 140h]; --Lit 1, 03FF, Cpy 5@0 FOR i:NAT IN [0..16) DO RamWrite[ERam, i, 0, 0, 0, 0] ENDLOOP; CBusWrite[writeEndAdd, 03h]; CBusWrite[writeLoopAdd, 0h]; StartCtl[TRUE, TRUE, FALSE]; [] _ TerminalIO.RequestRope["Type CR to quit: "]; StartCtl[FALSE, FALSE, FALSE]; gRamDebug _ TRUE; FOR i: NAT IN [0..32) DO [] _ RamRead[HRam, i ! ABORTED => gRamDebug _ b] ENDLOOP; FOR i: NAT IN [0..16) DO [] _ RamRead[ERam, i ! ABORTED => gRamDebug _ b] ENDLOOP; gRamDebug _ b; }; FromFileTest: PROC [fileName: ROPE _ "AChip3.force"] ~ { GetData: PROC RETURNS [lastAdd: VRamAdd] ~ { FOR add: NAT IN VRamAdd DO RamWrite[VRam, add, LOOPHOLE[IO.GetHWord[compStream ! IO.EndOfStream => GOTO huh]], LOOPHOLE[IO.GetHWord[compStream ! IO.EndOfStream => GOTO huh]], LOOPHOLE[IO.GetHWord[compStream ! IO.EndOfStream => GOTO huh]], LOOPHOLE[IO.GetHWord[compStream ! IO.EndOfStream => GOTO done]] ]; REPEAT huh => { TerminalIO.PutRope["\n ***Huh? Unexpected eof in compressed input stream, STREAM TRUCATED***"]; lastAdd _ add-1; }; done => {lastAdd _ add}; FINISHED => {TerminalIO.PutRope["\n ***Compressed input stream too long, STREAM TRUCATED***"]; lastAdd _ add }; ENDLOOP; }; InitChan: PROC [ch: Channel] ~ { SetTimingChan[ch, Delay, 6, 0, 0, 0, 0, 0]; SetTimingChan[ch, Width, 10, 0, 0, 0, 0, 0]; SetTimingChan[ch, Sample, 8, 0, 0, 0, 0, 0]; PEWrite[ch, ioCtl, 0]; PEWrite[ch, format, nrz]; }; sourceStream: IO.STREAM _ FS.StreamOpen[fileName: Rope.Concat[fileName, ".bin"], wDir: CommandTool.CurrentWorkingDirectory[], streamOptions: FS.binaryStreamOptions]; compStream: IO.STREAM _ FS.StreamOpen[fileName: Rope.Concat[fileName, ".bin.com"], wDir: CommandTool.CurrentWorkingDirectory[], streamOptions: FS.binaryStreamOptions]; TerminalIO.PutRope[IO.PutFR["\n***Vectors from file: %g***\n", IO.rope[fileName]]]; FOR i: NAT IN Channel DO InitChan[i]; ENDLOOP; RamWrite[CRam, 0, 03Fh, 3FFh, 000h, 0h];--mask: FFFF, inhibit: 0000 CBusWrite[writeLoopAdd, 0h]; CBusWrite[writeEndAdd, GetData[]]; StartCtl[TRUE]; StartCtl[FALSE]; IO.Close[sourceStream]; IO.Close[compStream]; }; END. "TRTestChip.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Last Edited by: Gasbarro September 16, 1988 2:40:19 pm PDT Constants and Types Globals CBus Addresses Pin Electronics Each DUT pin Each Timing Generator (Sample, Width, Delay) Decompressor Ref Clock Generator (on Multibus card) ioCtl Register Bits format Register Bits writeExtRamCtl Register Bits readDebug Register Bits In RZ mode force the output of the pulse generator high so that only the transitions resulting from changes in the data pipeline are observed. Skew RefCk to measure the time when the data transition occurs. Measure both rising and falling edges and call the greater of the two times the beginning of the cycle. -- fixed edge rate, square wave output, 5V, 0V, output on To write the ioCtl and Format registers, use default: timing _ Sample since these regs are not asociated with any particular timing chain To read the ioCtl and Format registers, use default: timing _ Sample since these regs are not asociated with any particular timing chain Κ#ο˜šœ™Icodešœ<™˜GKšœœ"˜8Kšœ˜—Kšœ\˜\K˜K˜—šžœœ ˜-Kšœ˜Kšœ˜Kšœ œ˜K˜Kšœ.œ œ ˜IKšœ+˜+Kšœ/ ˜HKšœœ˜'K˜š˜šœ-˜4Kšœœœ˜*Kšœ4˜4Kšœœ˜'Kšœ˜—K˜šœ,œ˜4Kšœœœ˜*Kšœ4˜4Kšœœ˜'Kšœ˜K˜—Kšœ˜Kšœ˜—K˜Kšœ ˜)Kšœ˜K˜K˜—šžœœ.˜:Kšœ˜Kšœ˜Kšœœ˜K˜Kšœ8œ œ œ ˜bKšœ+˜+Kšœ1˜1Kšœœ˜&K˜š˜šœ-˜4Kšœœœ˜*Kšœ4˜4Kšœœ˜&Kšœ˜—K˜šœ6˜=Kšœœœ˜*Kšœ:˜:Kšœœ˜&Kšœ˜—K˜šœ,œ˜4Kšœœœ˜*Kšœ4˜4Kšœœ˜&Kšœ˜K˜—K˜šœ5œ˜=Kšœœœ˜*Kšœ:˜:Kšœœ˜&Kšœ˜K˜—Kšœ˜Kšœ˜—K˜Kšœ ˜)Kšœ˜K˜K˜—šžœœ.˜:Kšœ˜Kšœ˜Kšœœ˜K˜Kšœ8œ œ œ ˜bKšœ+˜+Kšœ1˜1Kšœœ˜&š˜šœ/˜6Kšœœœ˜*Kšœ4˜4Kšœœ˜&Kšœ˜—K˜šœ4˜;Kšœœœ˜*Kšœ:˜:Kšœœ˜&Kšœ˜—K˜šœ.œ˜6Kšœœœ˜*Kšœ4˜4Kšœœ˜&Kšœ˜K˜—K˜šœ3œ˜;Kšœœœ˜*Kšœ:˜:Kšœœ˜&Kšœ˜K˜—Kšœ˜Kšœ˜—K˜Kšœ ˜)Kšœ˜K˜K˜—šžœœ.˜:Kšœ˜K˜K˜K˜—šžœœ.˜:Kšœ˜K˜K˜K˜—šž œœ_˜nK˜Kšœ#˜#Kšœ#˜#K˜K˜—šžœœAœ˜mKšœ˜Kšœ ˜ šœœ˜Kšœ$˜$Kšœ˜—šœ˜Kšœ$˜$Kšœ˜—K˜K˜—šžœœ:œ˜dKšœ˜šœ˜Kšœ%˜%Kšœ˜—K˜K˜—šž œœ%œ$˜ašžœœœ,˜MKšœœ˜?Kšœ ˜ šœ"˜)šœœ˜Kšœ ˜ Kšœ˜Kšœœ˜Kšœ˜Kšœ˜Kšœœœ˜K˜——Kšœ˜Kšœ˜K˜K˜—Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜Kšœ œœ˜@Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ(˜(Kšœœ6œ œ ˜\K˜K˜—šžœœMœ  œ˜~Kšœ˜Kšœ˜Kšœ˜Kšœ˜šœœœ˜Kšœ!˜!K˜Kšœœœœ˜$Kšœ˜—šœœ%œ˜7Kšœ˜Kšœœ˜ K˜—šœœœ˜K•StartOfExpansionV[es: TOCTest.EdgeStep, e: TOCTest.Edge, p: TOCTest.Phase, ch: TOCTest.Channel]šœ˜K˜Kšœœœœ ˜,š˜šœ=˜=Kšœœ œ œ ˜5Kšœœœœ˜*Kšœ œ ˜—Kšœ(˜0—Kšœ˜—K˜K˜—šž œ œ;˜OKš œ œœ œœ œœ˜lJ˜J˜—šž œœ˜šœ œ ˜Kšœ˜Kšœ˜—K˜K˜—šž œœ˜"šœ œ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜K˜K˜—šž œœœœ˜5šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜—K˜K˜—šžœœDœ$˜}šœœ˜Kšœ œ ˜Kšœ œ ˜Kšœœ œ ˜(Kšœœ œ ˜(Kšœœ ˜—K˜K˜—šž œœ’˜΅Kšœ2˜2Kšœ1˜1Kšœœ œœ˜@Kšœœ œœ˜?Kšœœ œœ˜?Kšœ=˜=Kšœ>˜>K˜K˜—šžœœœ œ˜DKšœ˜Kšœ œœ˜+Kš œ œœœ œœœ ˜FKšœœ˜ Kšœœœ ˜CK˜K˜—š žœœ(œœœ˜\Kšœ˜Kšœ œœ˜(Kšœœ œœ ˜0Kšœœ œœ ˜0Kšœœ˜ Kšœ œ˜Kšœœœ ˜DK˜K˜—šžœœœœ˜AKšœœœ ˜5K˜K˜—šžœœ<˜Jš œ œœ4œœ˜hšœ˜K˜K˜K˜K˜Kšœœ˜—Kš œ œ œ œ œ ˜D—Kšœ˜Kšœ˜Kšœ(˜(šœœ˜+Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜—Kšœ(˜(Kšœ˜K˜K˜—šžœœœ ˜RKšœ˜Kšœ(˜(šœœ˜+Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜—Jšœ ˜ Kšœ˜šœZœœ˜gšœ˜K˜K˜K˜K˜Kšœœ˜—Kš œ œ œ œ œ ˜D—K˜K˜—šž œœ ˜/Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜—šž œœœ ˜8Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜—šžœœœ˜!Kšœœœœ˜+Kšœ˜Kšœ ˜$Kšœ!˜%Kš 9™9Kšœ:˜:K˜K˜—šžœœ˜&Kšœ˜Kšœ˜Jšœ˜Jšœœœœ˜3Jšœ˜Jšœœœœ˜3J˜J˜—šž œœ˜%Kšœ˜Kšœ˜Jšœ˜Jšœœœœ˜3Jšœ˜Jšœœœœ˜3J˜J˜—šžœœ˜(Kšœœ*˜8Kšœ˜Kšœ˜Jšœœœœ˜4Jšœ˜Jšœœœœ˜3Kšœ˜K˜—šžœœ˜(Kšœœ*˜8Kšœ˜Kšœ˜Jšœ˜Jšœœœœ˜3Jšœœœœ˜4Kšœ˜K˜—šžœœ˜*J˜Jšœœ&œœœ5œœ˜’KšΟf*Πcf˜Fšœ˜˜Kš’J˜JKš’J˜JKš’J˜JKš’J˜JKšœ˜—˜Kš’J˜JKš’J˜JKš’J˜JKš’J˜JKšœ˜—˜Kš’J˜JKš’J˜JKš’J˜JKš’J˜JK˜—˜Kš’J˜JKš’J˜JKš’J˜JKš’J˜JK˜—Kšœœ˜—Kšœ˜Kšœ˜Kšœ œœœ˜K˜K˜—šžœœ(œ˜XKšœ˜Kšœ˜šœœ˜Kšœ ˜ Kšœ˜—K˜K˜—šž œ œœœ˜FJšœœ˜šœœœ˜šœ œ"œ˜SKšœ˜!—Kšœ˜—Jšœœœœ˜SJšœ˜J˜J˜—šž œœ˜,Jšœœœœ œœœœœœ˜gKšœœ%œœœœ œ œ œ œ œœ˜˜J˜J˜—šž œœœ˜-Jšœ<˜J˜Jšœ˜Jšœ˜J˜Jšœ œœœ˜Jšœ1˜1Jšœ œœœ˜K˜Kšœ œ˜Kš œœœ œœœ˜RKš œœœ œœœ˜RK˜K˜K˜—šž œœ œ˜8šžœœœ˜,šœœœ ˜š’˜Kš œœœœ’˜?Kš œœœœ’˜?Kš œœœœ’˜?Kšœœœœ˜?K˜—š˜šœ˜Kšœ`˜`Kšœ ’œ˜K˜—Kšœ’œ˜šœW˜_Kšœ ’˜ Kšœ˜——Kšœ˜—K˜K˜—šžœœ˜ Kšœ+˜+Kšœ,˜,Kšœ,˜,Kšœ˜Kšœ˜Kšœ˜—K˜Kšœœœœ‰˜₯Kšœ œœœ˜§K˜Kšœœ*œ˜Sšœœœ ˜Kšœ ˜ Kšœ˜—š’*£˜EK˜—Jšœ˜Jšœ"˜"Kšœ œ˜Kšœ œ˜Kšœ˜Kšœ˜K˜K˜J˜—Kšœ˜Jšž˜—…—iή‘ο