<> <> <> 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]; <<-- fixed edge rate, square wave output, 5V, 0V, output on>> 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.