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:
BOOLEAN ←
FALSE] = {
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:
BOOLEAN ←
FALSE] = {
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:
BOOLEAN ←
FALSE] = {
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: BOOLEAN ← FALSE;
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.