IMSTesterImpl.mesa
Copyright © 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 February 13, 1987 6:20:01 pm PST
Don Curry February 17, 1987 10:35:00 am PST
DIRECTORY
Basics, CommandTool, Convert, FS, GPIB, IMSTester, IO, MessageWindow, RefText, Rope, RopeList;
IMSTesterImpl: CEDAR MONITOR
IMPORTS Basics, Convert, CommandTool, FS, GPIB, IO, MessageWindow, RefText, Rope, RopeList
EXPORTS IMSTester = BEGIN OPEN IMSTester;
IMS: GPIB.DeviceAddr = 1;
statusIMS: NAT;
maxPktSize: NAT = 512;
channelsPerGroup: NAT = 32;
IMSError: PUBLIC SIGNAL [msg: ROPE] = CODE;
-- Globals --
checkSyntax: PUBLIC BOOLFALSE;
stop: BOOLFALSE;
logFile: ROPE ← "IMSTester.log";
synOut: IO.STREAMNIL;
validCycles: Cycle ← 0; --number of valid cycles in IMS memory
forceBd, acquireBd, progBd: PACKED ARRAY SlotNumber OF BOOLEAN;
Initialize: PUBLIC ENTRY PROC [wDir: ROPE] RETURNS [forceBoard, acquireBoard, programable: PACKED ARRAY SlotNumber OF BOOLEAN] = { -- the tester
ENABLE UNWIND => NULL;
ReallyInitialize: INTERNAL PROC RETURNS [forceBoard, acquireBoard, programable: PACKED ARRAY SlotNumber OF BOOLEAN] ~ TRUSTED {{
rope: ROPE;
stop ← FALSE;
IF NOT checkSyntax THEN
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 < 9) OR ((slot > 10) AND ((slot MOD 2)=1)); --reflects the current configuration
acquireBoard[slot] ← (slot>11) AND ((slot MOD 2)=0);
programable[slot] ← slot=21 OR slot=20;
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;
}};
logFile ← Rope.Concat[wDir, "IMSTester.log"];
[forceBoard, acquireBoard, programable] ← ReallyInitialize[];
};
RunDiagnostics: PUBLIC ENTRY PROC [extended: BOOLTRUE] = TRUSTED {{
-- What about looping? Use IMSCommander for serious interrogation.
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]];
--store diag results, someday(sigh!)
ENDLOOP;
WriteDevice["DIAG END"];
}};
DefineGroups: PUBLIC ENTRY PROC [forceGroups: ForceGroups, acquireGroups: AcquireGroups] = {
ENABLE UNWIND => NULL;
ReallyDefineGroups: INTERNAL PROC [forceGroups: ForceGroups, acquireGroups: AcquireGroups] ~ {
podTiming: PodTiming;
sentBanner: BOOLFALSE;
timingChannel: BOOLFALSE;
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;
};
ReallyDefineGroups[forceGroups, acquireGroups];
};
RedefineGroups: PUBLIC ENTRY PROC [forceGroups: ForceGroups ← NIL, acquireGroups: AcquireGroups ← NIL] = {
ENABLE UNWIND => NULL;
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]]];
WriteDevice[IO.PutFR["RAD %g BIN", IO.rope[f.name]]];
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]]];
WriteDevice[IO.PutFR["RAD %g BIN", IO.rope[a.name]]];
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, start: Cycle, halt: Cycle, jumps: Jumps ← NIL] = {
ENABLE UNWIND => NULL;
ReallySetIMSMemory: INTERNAL PROC [forceGroups: ForceGroups, acquireGroups: AcquireGroups, buffer: Buffer, cycles: Cycle, start: Cycle, halt: Cycle, jumps: Jumps ← NIL] ~ {
firstPTG: PodTimingGroup;
firstControlBit: BOOL;
vector: REF TEXT;
bits: LONG CARDINAL;
data: Data;
cycAdd: Cycle ← start;
validCycles ← cycles;
vector ← RefText.ObtainScratch[maxPktSize];
vector.length ← 0;
FOR bufAdd: Cycle IN [0..cycles) DO --build vector for this cycle
IF stop THEN {stop ← FALSE; EXIT};
vector ← RefText.AppendRope[vector, "MEM "];
vector ← RefText.AppendRope[vector, Convert.RopeFromCard[cycAdd]];
vector ← RefText.AppendRope[vector, " \""];
FOR fg: ForceGroups ← forceGroups, fg.rest UNTIL fg=NIL DO
bits ← 0;
firstPTG ← fg.first.podTimingGroups.first;
firstControlBit ← buffer[bufAdd][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[bufAdd][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[Rope.Cat[
IO.PutFR["Force group %g is not strictly Force or Inhibit. Cycle: %g, force board: %g, byte: ", IO.rope[fg.first.name], IO.int[bufAdd], IO.int[ptg.first.board]],
SELECT ptg.first.podTiming FROM A=>"A", B=>"B", AT=>"AT", BT=>"BT" ENDCASE=>ERROR,
IO.PutFR[", channel: %g is %g.", IO.int[p.first.channel], IO.rope[IF data.inhibit THEN "inhibit" ELSE "force"]]]];
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[bufAdd][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[bufAdd][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[Rope.Cat[
IO.PutFR["Acquire group %g is not strictly Mask or Compare. Cycle: %g, acquire board: %g, byte: ", IO.rope[ag.first.name], IO.int[bufAdd], IO.int[ptg.first.board]],
SELECT ptg.first.podTiming FROM A=>"A", B=>"B", AT=>"AT", BT=>"BT" ENDCASE=>ERROR,
IO.PutFR[", channel: %g is %g.", IO.int[p.first.channel], IO.rope[IF data.mask THEN "mask" ELSE "compare"]]]];
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=cycAdd THEN {
IF halt=cycAdd 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=cycAdd 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], cycAdd=cycles-1];
vector.length ← 0;
};
cycAdd ← cycAdd+1;
REPEAT
FINISHED => IF vector.length#0 THEN WriteDevice[Rope.FromRefText[vector], TRUE];
ENDLOOP;
RefText.ReleaseScratch[vector];
};
ReallySetIMSMemory [forceGroups, acquireGroups, buffer, cycles, start, halt, jumps];
};
ErrorCount: PUBLIC ENTRY PROC RETURNS [count: LONG CARDINAL] = {
ENABLE UNWIND => NULL;
s: IO.STREAM;
WriteDevice["FAIL?"];
IF checkSyntax THEN RETURN[0] ELSE {
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, testStart, testEnd, startCycle, cyclesJumped: Cycle] RETURNS [errors: Errors] = {
ENABLE UNWIND => NULL;
ReallyGetErrors: INTERNAL PROC [acquireGroups: AcquireGroups, buffer: Buffer, testStart, testEnd, startCycle, cyclesJumped: Cycle] RETURNS [errors: Errors] ~ {
s: IO.STREAM;
pinCount: NAT;
mask, acquireData: LONG CARDINAL;
expectData: Data;
err: Errors ← NIL;
errorCycle: Cycle;
IF checkSyntax THEN RETURN [NIL];
errorCycle ← FindNextError[startCycle];
IF errorCycle>testEnd THEN RETURN [NIL];
IM$: mem? 2 COM
mem 2,Compare,"C 0000 M 00 C 00 C 00000002 FFFF 00 00 FFFFFFFF"," e"
WriteDevice[IO.PutFR["MEM? %g COM", IO.card[errorCycle-cyclesJumped]]];
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]; --skips 'C or 'M designator
[] ← IO.GetTokenRope[s ! IO.EndOfStream => ERROR]; --skips data
ENDLOOP;
FOR ag: AcquireGroups ← acquireGroups, ag.rest UNTIL ag=NIL DO
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[errorCycle-testStart][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
(Basics.DoubleAnd[[lc[acquireData]], [lc[mask]]].lc#0) # expectData.compareData
THEN {
err ← CONS[[errorCycle, ag.first, ptg.first, p.first, expectData.compareData, NOT expectData.compareData], err];
};
mask ← Basics.DoubleShift[[lc[mask]], -1].lc;
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR l: Errors ← err, l.rest WHILE l#NIL DO --put list in increasing order
errors ← CONS[l.first, errors];
ENDLOOP;
};
RETURN[ReallyGetErrors[acquireGroups, buffer, testStart, testEnd, startCycle, cyclesJumped]];
};
GetRawErrors: PUBLIC ENTRY PROC [out: IO.STREAM, forceGroups: ForceGroups, acquireGroups: AcquireGroups, testEnd, startCycle, cyclesJumped: Cycle] RETURNS [valid: BOOL, errorCycle: Cycle ← 0] = {
***This is a work around for an IMS firmware bug in V1.1A. When a test is run by jumping to a start address from location zero the acquired data is read in cycle-cyclesJumped.***
ENABLE UNWIND => NULL;
IF checkSyntax THEN RETURN [FALSE];
errorCycle ← FindNextError[startCycle];
IF errorCycle>testEnd THEN RETURN [FALSE];
ReallyGetMemory[out, errorCycle, forceGroups, acquireGroups, cyclesJumped];
RETURN[TRUE, errorCycle];
};
GetMemory: PUBLIC ENTRY PROC [out: IO.STREAM, cycle: Cycle, forceGroups: ForceGroups, acquireGroups: AcquireGroups, cyclesJumped: Cycle] = {
ENABLE UNWIND => NULL;
ReallyGetMemory[out, cycle, forceGroups, acquireGroups, cyclesJumped];
};
ReallyGetMemory: PRIVATE INTERNAL PROC [out: IO.STREAM, cycle: Cycle, forceGroups: ForceGroups, acquireGroups: AcquireGroups, cyclesJumped: Cycle] = {
s: IO.STREAM;
dataTokens, compTokens: LIST OF ROPE ← NIL;
IM$: mem? 2 COM
mem 2,Compare,"C 0000 M 00 C 00 C 00000002 FFFF 00 00 FFFFFFFF"," e"
IM$: mem? 1
mem 1,"I 0 I 0 I 00000000 I 0 M 0 M 000 M 00000000 M 00 1 3FF FFFFFFFF 7F"
WriteDevice[IO.PutFR["MEM? %g", IO.int[cycle]]];
IF checkSyntax THEN RETURN;
s ← IO.RIS[ReadDevice[! IO.EndOfStream => ERROR]];
WHILE ([]←s.GetChar[]) # '" DO ENDLOOP; --skip to opening quote
IO.PutF[out, "Mem %g, ", IO.int[cycle]];
FOR fg: ForceGroups ← forceGroups, fg.rest UNTIL fg=NIL DO
pt: PodTiming ← fg.first.podTimingGroups.first.podTiming;
IO.PutRope[out, IF pt=A OR pt=B THEN IO.GetTokenRope[s ! IO.EndOfStream => ERROR].token ELSE ""]; --gets 'F or 'I designator if there is one
IO.PutChar[out, ' ];
IO.PutRope[out, IO.GetTokenRope[s ! IO.EndOfStream => ERROR].token]; --gets force data
IO.PutChar[out, ' ];
ENDLOOP;
IO.PutChar[out, '\n ];
FOR ag: AcquireGroups ← acquireGroups, ag.rest UNTIL ag=NIL DO
compTokens ← CONS[IO.GetTokenRope[s].token, compTokens];
dataTokens ← CONS[IO.GetTokenRope[s].token, dataTokens];
out.PutF["%g %g ", IO.rope[compTokens.first], IO.rope[dataTokens.first]] ENDLOOP;
IO.PutChar[out, '\n ];
compTokens ← RopeList.Reverse[compTokens];
dataTokens ← RopeList.Reverse[dataTokens];
WriteDevice[IO.PutFR["MEM? %g COM", IO.int[cycle-cyclesJumped]]];
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
[] ← IO.GetTokenRope[s]; [] ← IO.GetTokenRope[s] ENDLOOP;
FOR rl: LIST OF ROPE ← compTokens, rl.rest UNTIL rl=NIL DO
tRope: ROPEIO.GetTokenRope[s].token;
rRope: ROPE ← dataTokens.first; dataTokens ← dataTokens.rest;
IO.PutRope[out, " "];
IF Rope.Equal[rRope, tRope] OR Rope.Equal[rl.first, "M"]
THEN IO.PutRope[out, tRope]
ELSE FOR i: INT IN [0..Rope.Length[tRope]) DO
rc: CHAR ← Rope.Fetch[rRope, i];
tc: CHAR ← Rope.Fetch[tRope, i];
IF rc # tc AND IO.GetInfo[out].class=$ViewersOutput
THEN IO.PutF[out, "%l%g%l", IO.char['b], IO.char[tc], IO.char['B]]
ELSE IO.PutF[out, "%g", IO.char[tc]] ENDLOOP;
out.PutChar[' ]; ENDLOOP;
WHILE ~s.EndOf[] DO
token: ROPE;
IO.PutChar[out, ' ];
token ← IO.GetTokenRope[s ! IO.EndOfStream => EXIT].token;
SELECT TRUE FROM
Rope.Equal[token, """"] => token ← "";
Rope.Equal[token, "e"] => token ← "<ERROR>";
ENDCASE => NULL;
IO.PutRope[out, token];
ENDLOOP;
IO.PutChar[out, '\n ];
};
Upload: PUBLIC ENTRY PROC [fName: ROPE] ~ {
s: IO.STREAM;
s ← FS.StreamOpen[fileName: fName, accessOptions: $create, wDir: CommandTool.CurrentWorkingDirectory[] ! FS.Error => {Message[IO.PutFR["Trouble opening: %g", IO.rope[fName]]]; CONTINUE}];
IF s=NIL THEN RETURN;
WriteDevice["SET?"];
IO.Put[s, IO.rope[ReadDevice[]]];
WriteDevice["BSET?"];
IO.Put[s, IO.rope[ReadDevice[]]];
IO.Close[s];
};
Download: PUBLIC ENTRY PROC [fName: ROPE] ~ {
s: IO.STREAM;
done: BOOLFALSE;
nBytesRead: NAT ← 0;
rt: REF TEXT ← RefText.ObtainScratch[maxPktSize];
s ← FS.StreamOpen[fileName: fName, wDir: CommandTool.CurrentWorkingDirectory[] ! FS.Error => {Message[IO.PutFR["File: %g not found", IO.rope[fName]]]; CONTINUE}];
IF s=NIL THEN RETURN;
DO
nBytesRead ← IO.GetBlock[s, rt ! IO.EndOfStream => {done ← TRUE; CONTINUE}];
IF nBytesRead=0 THEN EXIT;
WriteDevice[Rope.FromRefText[rt], done, ""];
IF done THEN EXIT;
ENDLOOP;
RefText.ReleaseScratch[rt];
IO.Close[s];
};
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 = {
-- for HALT to be executed or timeout
ENABLE UNWIND => NULL;
WriteDevice["WAIT ALL, 10s"];
};
Abort: PUBLIC ENTRY PROC = {
ENABLE UNWIND => NULL;
stop ← TRUE;
};
FindNextError: PRIVATE INTERNAL PROC [startCycle: Cycle] RETURNS [errorCycle: Cycle] = {
IM$: find? seq 0 "" "???e"
find (Seq 2,...)
s: IO.STREAM;
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;
errorCycle ← IO.GetCard[s ! IO.EndOfStream => ERROR];
EXITS
finished => errorCycle ← LAST[Cycle];
};
Message: PRIVATE INTERNAL PROC [rope: ROPE] = {
MessageWindow.Append[rope, TRUE];
MessageWindow.Blink[];
MessageWindow.Append[rope, TRUE];
};
GetIMSStatusMsg: PRIVATE INTERNAL PROC RETURNS [msg: ROPE] = TRUSTED {{
errBuf: ROPE;
end: BOOL;
IF checkSyntax THEN RETURN["GetIMSStatusMsg: No Status Message in Simulation."];
statusIMS ← LOOPHOLE[GPIB.SelectedReadSerialPoll[IMS]];
GPIB.WriteDevice[IMS, "Err?\l"];
[errBuf, end] ← GPIB.ReadDevice[IMS];
IF NOT end THEN ERROR; --shouldn't get long ropes here
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: BOOLTRUE, term: ROPE ← "\l"] = TRUSTED {{
IF checkSyntax THEN {
IF synOut=NIL THEN synOut ← FS.StreamOpen[logFile, $create]; --check for NIL
synOut.PutF["%g\n", IO.rope[msg]
! IO.Error => {synOut ← FS.StreamOpen[logFile, $create]; RETRY}] --file could be closed
} ELSE GPIB.WriteDeviceBuffered[IMS, Rope.Concat[msg, term], hold];
}};
ReadDevice: PRIVATE INTERNAL PROC RETURNS [msg: ROPE] = TRUSTED {{
r: ROPE; end: BOOLFALSE;
msg ← NIL;
IF checkSyntax THEN RETURN[NIL] ELSE WHILE NOT end DO
[r, end] ← GPIB.ReadDevice[IMS];
msg ← Rope.Concat[msg, r];
ENDLOOP;
}};
END.