ICTestImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by: Gasbarro September 18, 1985 2:57:39 pm PDT
Last Edited by: Gasbarro November 8, 1985 1:15:11 pm PST
Barth, September 27, 1985 5:23:15 pm PDT
DIRECTORY
Buttons, CedarProcess, ChoiceButtons, Containers, EGlas, FS, ICTest, IO, MessageWindow, Rope, Rules, ViewerClasses, ViewerIO, ViewerOps, ViewerTools;
ICTestImpl: CEDAR PROGRAM
IMPORTS Buttons, CedarProcess, ChoiceButtons, Containers, EGlas, FS, IO, MessageWindow, Rope, Rules, ViewerIO, ViewerOps, ViewerTools
EXPORTS ICTest
= BEGIN
AbortDieSignal: PUBLIC ERROR = CODE;
AbortWaferSignal: PUBLIC ERROR = CODE;
InterruptSignal: PUBLIC ERROR = CODE;
Handle: TYPE = ICTest.Handle;
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
TestHandle: TYPE = REF TestHandleRec;
TestHandleRec: TYPE = RECORD[h: Handle, proc: ICTest.TestProc];
ControlHandle: TYPE = REF ControlHandleRec;
ControlHandleRec: TYPE = RECORD[h: Handle, proc: ICTest.ControlProc, control: BOOL];
entryHeight: CARDINAL = 15; -- how tall to make each line of items
entryVSpace: CARDINAL = 8;  -- vertical leading space between lines
entryHSpace: CARDINAL = 10;  -- horizontal space between items in a line
pointsPerInch: CARDINAL = 72;  -- horizontal space for text strings
secondColumn: CARDINAL = 2*72; -- horizontal space to second column of buttons
thirdColumn: CARDINAL = 4*72; -- horizontal space to third column of buttons
fourthColumn: CARDINAL = 6*72; -- horizontal space to fourth column of buttons
DoTest: PROC [h: Handle] = {
NextToken: PROC [h: Handle] RETURNS [s: IO.STREAM] = {
s ← IF h.backupToken # NIL THEN h.backupToken ELSE IO.RIS[IO.GetTokenRope[h.inStream].token];
h.backupToken ← NIL;
};
BackupToken: PROC [s: IO.STREAM] RETURNS [] = {
h.backupToken ← s;
};
NextRun: PROC [h: Handle] RETURNS [done: BOOLEANFALSE] = {
c: CHAR;
s: IO.STREAM;
IF h.stop # interrupt THEN {
WHILE NOT done DO
s ← NextToken[h ! IO.EndOfStream => {done ← TRUE; CONTINUE}];
IF NOT done THEN SELECT (c ← IO.PeekChar[s]) FROM
'r, 'R => EXIT;
'w, 'W => NULL;
'd, 'D => NULL;
IN ['0..'9] => NULL;
ENDCASE => {Message["Error: Bad token in data file, aborting test"]; done ← TRUE};
ENDLOOP;
IF NOT done THEN {
ViewerTools.SetContents[h.run, IO.GetTokenRope[NextToken[h !
IO.EndOfStream => {done ← TRUE; CONTINUE}]].token];
IO.PutF[h.viewerout, "\nRun %g", IO.rope[ViewerTools.GetContents[h.run]]];
};
IF done THEN {
IO.Close[h.inStream];
h.testInProgress ← FALSE;
};
};
};
NextWafer: PROC [h: Handle] RETURNS [done: BOOLEANFALSE] = {
c: CHAR;
s: IO.STREAM;
IF h.stop # interrupt THEN {
WHILE NOT done DO
s ← NextToken[h ! IO.EndOfStream => {done ← TRUE; CONTINUE}];
IF NOT done THEN SELECT (c ← IO.PeekChar[s]) FROM
'r, 'R => {done ← TRUE; BackupToken[s]};
'w, 'W => EXIT;
'd, 'D => NULL;
IN ['0..'9] => NULL;
ENDCASE => {Message["Error: Bad token in data file, aborting test"]; done ← TRUE};
ENDLOOP;
IF NOT done THEN {
ViewerTools.SetContents[h.wafer, IO.GetTokenRope[NextToken[h !
IO.EndOfStream => {done ← TRUE; CONTINUE}]].token];
IO.PutF[h.viewerout, "\nWafer %g ", IO.rope[ViewerTools.GetContents[h.wafer]]];
IF h.enableStepper THEN {
EGlas.LampOn[];
IF h.testInProgress THEN EGlas.Load[]; --don't load wafer first time
} ;
};
};
};
NextDie: PROC [h: Handle] RETURNS [done: BOOLEANFALSE] = {
c: CHAR;
s: IO.STREAM;
IF h.stop # interrupt THEN {
WHILE NOT done DO
s ← NextToken[h ! IO.EndOfStream => {done ← TRUE; CONTINUE}];
IF NOT done THEN SELECT (c ← IO.PeekChar[s]) FROM
'r, 'R => {done ← TRUE; BackupToken[s]};
'w, 'W => {done ← TRUE; BackupToken[s]};
'd, 'D => h.currentDie.y ← IO.GetInt[NextToken[h !
IO.EndOfStream => {done ← TRUE; CONTINUE}]];
IN ['0..'9] => EXIT;
ENDCASE => {Message["Error in data file, aborting test"]; done ← TRUE};
ENDLOOP;
IF NOT done THEN {
h.currentDie.x ← IO.GetInt[s];
ViewerTools.SetContents[h.die, IO.PutFR["(%g,%g)", IO.int[h.currentDie.x], IO.int[h.currentDie.y]]];
IO.PutF[h.viewerout, "Die (%g,%g) ", IO.int[h.currentDie.x], IO.int[h.currentDie.y]];
};
};
IF NOT done THEN {
h.stop ← dont;
h.testInProgress ← TRUE;
IF h.enableStepper THEN {
EGlas.Seek[h.currentDie.x, h.currentDie.y];
EGlas.ZUp[];
EGlas.LampOff[];
};
h.currentTestProc[h];
{p: PROC ~ {h.currentTestProc[h]}; CedarProcess.DoWithPriority[priority: foreground, action: p]};
IF h.enableStepper THEN EGlas.LampOn[];
};
};
IF h.inStream # NIL THEN
DO IF NextRun[h] THEN EXIT;
DO IF NextWafer[h] THEN EXIT;
DO IF NextDie[h !
AbortDieSignal => CONTINUE;
AbortWaferSignal => EXIT] THEN EXIT
ENDLOOP;
ENDLOOP;
ENDLOOP;
h.testInProgress ← FALSE;
};
StartTest: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
IF NOT h.testInProgress THEN {
h: Handle ← NARROW[clientData];
done: BOOLEANFALSE;
h.stop ← dont;
IF h.inStream # NIL THEN IO.Close[h.inStream]; --just in case last test was aborted
Init[h];
DoTest[h ! InterruptSignal => CONTINUE];
Cleanup[h];
};
};
AbortDie: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
h.stop ← abortDie;
};
AbortWafer: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
h.stop ← abortWafer;
};
AbortTest: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
h.stop ← interrupt;
h.testInProgress ← FALSE;
};
EnableTester: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
selectedButton: Viewer ← NARROW[parent];
h.enableTester ← NOT h.enableTester;
Buttons.SetDisplayStyle[selectedButton, IF h.enableTester THEN $BlackOnGrey ELSE $BlackOnWhite];
};
EnableStepper: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
selectedButton: Viewer ← NARROW[parent];
h.enableStepper ← NOT h.enableStepper;
Buttons.SetDisplayStyle[selectedButton, IF h.enableStepper THEN $BlackOnGrey ELSE $BlackOnWhite];
};
Interrupt: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
h.stop ← interrupt;
};
Continue: Buttons.ButtonProc = {
h: Handle ← NARROW[clientData];
IF h.testInProgress AND (h.stop = interrupt) THEN {
DoTest[h ! InterruptSignal => CONTINUE];
Cleanup[h];
};
};
Message: PROC [rope: ROPE] = {
MessageWindow.Append[rope, TRUE];
MessageWindow.Blink[];
MessageWindow.Append[rope, TRUE];
};
Init: PROC[h: Handle] = {
filename: ROPE ← ViewerTools.GetContents[h.waferFile];
h.inStream ← FS.StreamOpen[filename !
FS.Error => {Message[IO.PutFR["Wafer file: %g not found", IO.rope[filename]]];
CONTINUE}];
IF h.enableStepper THEN EGlas.Init[];
};
Cleanup: PROC [h: Handle] = {
IF h.enableStepper THEN EGlas.LampOn[];
};
CheckStop: PUBLIC PROC [h: Handle] = {
SELECT h.stop FROM
dont => NULL;
abortDie => ERROR AbortDieSignal;
abortWafer => ERROR AbortWaferSignal;
interrupt => ERROR InterruptSignal;
ENDCASE => ERROR;
};
PutUpControlButton: PUBLIC PROC [buttonName: ROPE, proc: ICTest.ControlProc, h: Handle, initialState: BOOL] = {
button: Buttons.Button;
controlHandle: ControlHandle ← NEW[ControlHandleRec ← [h, proc, initialState]];
button ← Buttons.Create[info: [name: buttonName,
wx: fourthColumn, wy: h.cHeight,
ww: 0,wh: entryHeight,
parent: h.outer, border: TRUE], clientData: controlHandle, proc: ControlButton];
IF initialState THEN Buttons.SetDisplayStyle[button, $BlackOnGrey];
h.cHeight ← h.cHeight + entryHeight + entryVSpace;
proc[h, initialState];
};
ControlButton: Buttons.ButtonProc = {
c: ControlHandle ← NARROW[clientData];
h: Handle ← c.h;
selectedButton: Viewer ← NARROW[parent];
c.control ← NOT c.control;
Buttons.SetDisplayStyle[selectedButton, IF c.control THEN $BlackOnGrey ELSE $BlackOnWhite];
c.proc[h, c.control];
};
PutUpTestButton: PUBLIC PROC [buttonName: ROPE, proc: ICTest.TestProc, h: Handle] = {
first: BOOLEAN ← h.testButtonList = NIL;
testHandle: TestHandle ← NEW[TestHandleRec ← [h, proc]];
h.testButtonList ← CONS[Buttons.Create[info: [name: buttonName,
wx: thirdColumn, wy: h.tHeight,
ww: 0,wh: entryHeight,
parent: h.outer, border: TRUE], clientData: testHandle, proc: TestButton], h.testButtonList];
h.tHeight ← h.tHeight + entryHeight + entryVSpace;
IF first THEN {
h.currentTestProc ← proc;
Buttons.SetDisplayStyle[h.testButtonList.first, $BlackOnGrey];
};
};
TestButton: Buttons.ButtonProc = {
t: TestHandle ← NARROW[clientData];
h: Handle ← t.h;
selectedButton: Viewer ← NARROW[parent];
FOR l: LIST OF Buttons.Button ← h.testButtonList, l.rest WHILE l#NIL DO
Buttons.SetDisplayStyle[l.first, IF l.first = selectedButton THEN $BlackOnGrey ELSE $BlackOnWhite];
ENDLOOP;
h.currentTestProc ← t.proc;
};
MakeICTestTool: PUBLIC PROC [name: ROPE, maxButtons: CARDINAL] RETURNS [h: Handle] = BEGIN
rule: Rules.Rule;
height: CARDINAL ← entryVSpace;
h ← NEW[ICTest.ICTestRec];
h.outer ← Containers.Create[[-- construct the outer container  
name: Rope.Concat["IC Test Tool - ", name],
iconic: FALSE,
column: left,
scrollable: FALSE ]];
h.waferFile ← ChoiceButtons.BuildTextPrompt[h.outer, 0, height, "Wafer File:", "SingleDie.dat", NIL, 7*pointsPerInch].textViewer;
height ← height + entryHeight + entryVSpace;
h.run ← ChoiceButtons.BuildTextPrompt[h.outer, 0, height, "Run:", NIL, NIL, 1*pointsPerInch].textViewer;
[] ← Buttons.Create[info: [name: "Start Test",
wx: secondColumn, wy: height,
ww: 0,wh: entryHeight,
parent: h.outer, border: TRUE], clientData: h, proc: StartTest];
height ← height + entryHeight + entryVSpace;
h.wafer ← ChoiceButtons.BuildTextPrompt[h.outer, 0, height, "Wafer:", NIL, NIL, 1*pointsPerInch].textViewer;
[] ← Buttons.Create[info: [name: "Abort Die",
wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, fork: FALSE, proc: AbortDie];
height ← height + entryHeight + entryVSpace;
h.die ← ChoiceButtons.BuildTextPrompt[h.outer, 0, height, "Die:", NIL, NIL, 1*pointsPerInch].textViewer;
[] ← Buttons.Create[info: [name: "Abort Wafer", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: AbortWafer];
height ← height + entryHeight + entryVSpace;
h.clock ← ChoiceButtons.BuildTextPrompt[h.outer, 0, height, "Clock:", "8 MHz", NIL, 1*pointsPerInch].textViewer;
[] ← Buttons.Create[info: [name: "Interrupt", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: Interrupt];
height ← height + entryHeight + entryVSpace;
[] ← Buttons.Create[info: [name: "Continue", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: Continue];
height ← height + entryHeight + entryVSpace;
[] ← Buttons.Create[info: [name: "Abort Test", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: AbortTest, guarded: TRUE];
height ← height + entryHeight + entryVSpace;
[] ← Buttons.Create[info: [name: "Enable Tester", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: EnableTester];
height ← height + entryHeight + entryVSpace;
[] ← Buttons.Create[info: [name: "Enable Stepper", wx: secondColumn, wy: height, ww: 0, wh: entryHeight, parent: h.outer, border: TRUE], clientData: h, proc: EnableStepper];
height ← height + entryHeight + entryVSpace;
height ← MAX[height, ((maxButtons+1)*(entryHeight + entryVSpace) + entryVSpace)];
rule ← Rules.Create[ [ -- create a bar to separate sections 1 and 2
parent: h.outer, wy: height, ww: h.outer.cw, wh: 2]];
Containers.ChildXBound[h.outer, rule]; -- constrain rule to be width of parent
[ , h.viewerout] ← ViewerIO.CreateViewerStreams[name: "ICTestTypescript", viewer:ViewerOps.CreateViewer[flavor: $TypeScript, info:[parent: h.outer, wy: height+2, ww: 7*pointsPerInch, wh: 56 * entryHeight, scrollable: TRUE, border: FALSE]]];
height ← height + 10 * entryHeight;
ViewerOps.SetOpenHeight[h.outer, height];
ViewerOps.PaintViewer[h.outer, all];
h.tHeight ← entryHeight + 2*entryVSpace;
h.cHeight ← entryHeight + 2*entryVSpace;
END;
END.