DIRECTORY Buttons, ChoiceButtons, Containers, EGlas, FS, ICTest, IO, MessageWindow, Rope, Rules, ViewerClasses, ViewerIO, ViewerOps, ViewerTools; ICTestImpl: CEDAR PROGRAM IMPORTS Buttons, 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]; 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. NICTestImpl.mesa Copyright c 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 {p: PROC ~ {h.currentTestProc[h]}; CedarProcess.DoWithPriority[priority: foreground, action: p]}; Κ ›˜codešœ™Kšœ Οmœ1™˜wKšžœ˜—K˜Kšœž˜J˜Jšœž œžœ˜$Jšœž œžœ˜&Jšœž œžœ˜%J˜Jšœžœ˜Jšžœžœž˜Jšœžœ˜$J˜Jšœ žœžœ˜%Jšœžœžœ#˜?Jšœžœžœ˜+Jšœžœžœ/žœ˜TJ˜Jšœ žœΟc&˜BJšœ žœŸ'˜CJšœ žœŸ+˜HJšœžœŸ$˜CJšœžœ Ÿ/˜OJšœ žœ Ÿ.˜MJšœžœ Ÿ/˜OJ˜šΟnœžœ˜š   œžœ žœžœžœ˜6Kšœžœžœžœžœžœžœžœ!˜]Kšœžœ˜Kšœ˜—š   œžœžœžœžœ˜/Kšœ˜Kšœ˜—š  œžœ žœžœžœ˜=Kšœžœ˜Kšœžœžœ˜ šžœžœ˜šžœžœž˜Kšœžœžœžœ˜=š žœžœžœžœžœž˜1Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšžœ žœ˜KšžœEžœ˜R—Kšžœ˜—šžœžœžœ˜šœžœ˜Kšžœžœžœ ˜3—KšžœM˜Ošžœžœ˜Kšœ˜KšžœžœŸ˜DKšœ˜—Kšœ˜—K˜—Kšœ˜—š  œžœ žœžœžœ˜=Kšœžœ˜Kšœžœžœ˜ šžœžœ˜šžœžœž˜Kšœžœžœžœ˜=š žœžœžœžœžœ žœž˜1Kšœžœ˜(Kšœžœ˜(šœžœ˜2Kšžœžœžœ˜,—Kšžœ žœ˜Kšžœ:žœ˜G—Kšžœ˜—šžœžœžœ˜Jšœžœ ˜Kšœžœžœžœ˜dKšžœS˜UK˜—K˜—K˜šžœžœžœ˜K˜Jšœžœ˜šžœžœ˜Kšœ+˜+Kšœ ˜ Kšœ˜K˜—Kšœ˜K•StartOfExpansion3[priority: CedarProcess.Priority, action: PROC]šœžœY™aKšžœžœ˜'K˜—K˜K˜—šžœžœž˜šžœžœ žœžœ˜šžœžœ ž ˜šžœ ˜Kšœžœ˜Kšœžœž ˜#Kšžœ˜—Kšžœ˜—Kšžœ˜——Kšœžœ˜Kšœ˜K˜—š  œ˜!Kšœ žœ ˜šžœžœžœ˜Kšœ žœ ˜Kšœžœžœ˜Kšœ˜Kš žœžœžœžœŸ$˜SK˜Jšœžœ˜(Kšœ ˜ K˜—Kšœ˜K˜—š œ˜ Kšœ žœ ˜Kšœ˜Kšœ˜K˜—š  œ˜"Kšœ žœ ˜Kšœ˜Kšœ˜K˜—š  œ˜!Kšœ žœ ˜Kšœ˜Kšœžœ˜Kšœ˜K˜—š  œ˜$Kšœ žœ ˜Kšœžœ ˜(Kšœžœ˜$Kšœ(žœžœžœ˜`Kšœ˜K˜—š  œ˜%Kšœ žœ ˜Kšœžœ ˜(Kšœžœ˜&Kšœ(žœžœžœ˜aKšœ˜K˜—š  œ˜!Kšœ žœ ˜Kšœ˜Kšœ˜K˜—š œ˜ Kšœ žœ ˜šžœžœžœ˜3Kšœžœ˜(Kšœ ˜ K˜—Kšœ˜K˜—š œžœžœ˜Kšœžœ˜!Kšœ˜Kšœžœ˜!Kšœ˜K˜—š œžœ˜Kšœ žœ(˜6šœ žœ˜%Kšžœžœ#žœ˜NKšžœ˜ —Kšžœžœ˜%Kšœ˜K˜—š œžœ˜Kšžœžœ˜'K˜K˜—š  œž œ˜&šžœž˜Kšœžœ˜ Kšœ žœ˜!Kšœžœ˜%Kšœ žœ˜#Kšžœžœ˜—Kšœ˜K˜—š  œžœžœžœ5žœ˜oJ˜Jšœžœ-˜Ošœ0˜0Jšœ ˜ Jšœ˜Jšœžœ3˜P—Kšžœžœ/˜CJšœ2˜2Kšœ˜Jšœ˜K˜—š  œ˜%Kšœžœ ˜&K˜Kšœžœ ˜(Kšœ žœ ˜Kšœ&žœ žœžœ˜[Kšœ˜Kšœ˜K˜—š œž œžœ'˜UJšœžœžœ˜(Jšœžœ˜8šœžœ(˜?Jšœ˜Jšœ˜Jšœžœ@˜]—Jšœ2˜2šžœžœ˜Jšœ˜Jšœ>˜>J˜—K˜K˜—š  œ˜"Kšœžœ ˜#K˜Kšœžœ ˜(š žœžœžœ+žœžœž˜GKšœ!žœžœžœ˜cKšžœ˜—Kšœ˜Kšœ˜K˜—š  œžœžœžœžœžœž˜ZJ˜Jšœžœ˜Jšœžœ˜Iemphasis˜šœŸœ˜?Jšœ+˜+Jšœžœ˜Jšœ ˜ Jšœ žœ˜—Jšœ`žœ˜J˜Jšœ,˜,JšœBžœžœ˜hšœ.˜.Jšœ˜Jšœ˜Jšœžœ#˜@—J˜Jšœ,˜,JšœFžœžœ˜lšœ-˜-JšœOžœžœ˜‚—J˜Jšœ,˜,JšœBžœžœ˜hJšœžœ$˜§J˜Jšœ,˜,JšœOžœ˜pJšœ}žœ#˜€J˜Jšœ,˜,Jšœ|žœ"˜’J˜Jšœ,˜,Jšœ~žœ,žœ˜΄J˜Jšœ,˜,Jšœžœ&˜«J˜Jšœ,˜,Jšœ‚žœ'˜­J˜Jšœ,˜,Jšœ žœE˜QšœŸ,˜CJšœ5˜5—Jšœ'Ÿ&œ˜NJšœΩžœ žœ˜πJšœ#˜#J˜Jšœ)˜)Jšœ$˜$Jšœ(˜(Jšœ(˜(Jšžœ˜J˜—Jšžœ˜J˜—…—,ˆ;q