COMPILE FUNCTION obj_GaN_Dev(Method,Parms) #pragma precomp SRP_PreCompiler /* GaN Reports 7/26/2016 JCH Initial Coding Methods: GetStatus ;* Returns GaN processing overview status */ DECLARE SUBROUTINE Btree.Extract, Set_Status, Send_Dyn, Btree.Extract, v119, ErrMsg, Database_Services DECLARE FUNCTION obj_React_Run, Database_Services, SRP_Array, Gan_Services $INSERT POPUP_EQUATES $INSERT LOGICAL $INSERT WO_LOG_EQUATES $INSERT REACT_RUN_EQUATES $INSERT RUN_STAGE_EQUATES $INSERT RUN_STAGE_WFR_EQUATES $INSERT TOOL_EQUATES $INSERT TOOL_CLASS_EQUATES $INSERT TOOL_WFR_EQUATES $INSERT LOCATION_EQUATES $INSERT APP_INSERTS $INSERT WO_WFR_EQUATES $INSERT TOOL_ETCH_EQUATES EQU COL$STAGE TO 1 EQU COL$RDS_NO TO 2 EQU COL$GAN_RUN_ID TO 3 EQU COL$EPI_PART_NO TO 4 EQU COL$WAIT_TOOL_TYPE TO 5 EQU COL$WAIT_WFR_QTY TO 6 EQU COL$WAIT_HRS TO 7 EQU COL$WAIT_WFR_ID TO 8 EQU COL$TOOL_ID TO 9 EQU COL$RUN_WFR TO 10 EQU COL$RUN_HRS TO 11 EQU COL$RUN_WFR_ID TO 12 ErrTitle = 'Error in Stored Procedure "obj_GaN"' ErrorMsg = '' ErrCode = '' IF NOT(ASSIGNED(Method)) THEN ErrorMsg = 'Unassigned parameter "Method" passed to subroutine' IF NOT(ASSIGNED(Parms)) THEN Parms = '' IF ErrorMsg NE '' THEN Set_Status(-1,ErrTitle:@SVM:ErrorMsg) RETURN '' END Result = '' BEGIN CASE CASE Method = 'GetStatus' ; GOSUB GetStatus CASE Method = 'ToolWIP' ; GOSUB ToolWIP CASE Otherwise$ ; Null END CASE IF ErrorMsg NE '' THEN Set_Status(-1,ErrTitle:@SVM:ErrorMsg) RETURN '' END RETURN Result * * * * * * * GetStatus: * * * * * * * PopupLiteral = XLATE('SYSREPOSPOPUPS', @APPID<1>:'**':'GAN_WIP_STAGES',PDISPLAY$,'X') CONVERT @VM:@SVM TO @FM:@VM IN PopupLiteral OPEN 'DICT.REACT_RUN' TO DictReactRun ELSE ErrorMsg = 'Unable to open "DICT.REACT_RUN" for Btree.Extract' RETURN END OPEN 'DICT.RUN_STAGE' TO DictRunStage ELSE ErrorMsg = 'Unable to open "DICT.RUN_STAGE" for Btree.Extract' RETURN END OPEN 'DICT.RUN_STAGE_WFR' TO DictRunStageWfr ELSE ErrorMsg = 'Unable to open "DICT.RUN_STAGE_WFR" for Btree.Extract' RETURN END LineCnt = 0 StageCnt = COUNT(PopupLiteral,@FM) + (PopupLiteral NE '') Header = 'Stage':@VM ;* Column headers for export Header := 'RDS No':@VM Header := 'Run ID':@VM Header := 'EPI Part No':@VM Header := 'Tool Class':@VM Header := 'Wait Cnt':@VM Header := 'Wait Hrs':@VM Header := 'Wait Wfr IDs':@VM Header := 'Priority':@VM Header := 'Tool ID':@VM Header := 'Run Cnt':@VM Header := 'Run Hrs':@VM Header := 'Run Wfr IDs':@VM Header := 'Run Priority' LineCnt += 1 Result = Header FOR S = 1 TO StageCnt Stage = PopupLiteral StageDesc = PopupLiteral CharFlag = PopupLiteral ToolClasses = PopupLiteral ToolIDs = '' For each ToolClass in ToolClasses using ',' TempToolIDs = XLATE('TOOL_CLASS', ToolClass, TOOL_CLASS_TOOL$, 'X') ToolIDs = SRP_Array('Join', TempToolIDs, ToolIDs, 'OR', @VM) Next ToolClass StageRdsNos = '' StageWaitIDs = '' StageRunIDs = '' StageToolIDs = '' StageWaitTms = '' StageRunTms = '' StageWaitCnts = '' StageRunCnts = '' * Stages do not have a tool class have their queue ID hardcoded below BEGIN CASE Case Stage _EQC 'ETCH' QInEtchIDs = XLATE('LOCATION','GCH*Q_ETCH',LOCATION_ETCH_ID$,'X') ToolClass = 'G_REACT' Case Stage _EQC 'GROWTH' QInCassIDs = XLATE('LOCATION','GCH*Q_GROWTH',LOCATION_CASS_ID$,'X') ToolClass = 'G_REACT' Case Stage _EQC 'G_RATE' QInWfrIDs = XLATE('LOCATION','GCH*Q_RATE',LOCATION_WFR_ID$,'X') ToolClass = 'G_REACT' Case Stage _EQC 'WET_CLEAN' QInWfrIDs = Xlate('LOCATION','GCH*CLEAN_Q',LOCATION_WFR_ID$,'X') ToolClass = 'GCH*CLEAN_Q' Case Stage _EQC 'SPLIT' QInWfrIDs = XLATE('LOCATION','GCH*SPLIT_Q',LOCATION_WFR_ID$,'X') ToolClass = 'GCH*Q_SP' Case Stage _EQC 'DISP' QInWfrIDs = XLATE('LOCATION','GGR*Q_DISP',LOCATION_WFR_ID$,'X') ToolClass = 'GGR*Q_DISP' Case Stage _EQC 'G_PACK' QInWfrIDs = XLATE('LOCATION','GCH*Q_PACK',LOCATION_WFR_ID$,'X') ToolClass = 'GCH*Q_PACK' Case Stage _EQC 'RETAIN' QInWfrIDs = Xlate('LOCATION','GCH*Q_RETAIN',LOCATION_WFR_ID$,'X') ToolClass = 'GCH*Q_RETAIN' Case Otherwise$ QInWfrIDs = XLATE('TOOL_CLASS',ToolClass,'QIN_WFR_ID','X') END CASE * Collect data from places the wafers are stored in LOCATION (Queues), TOOL_WFR (On Tool * * * * * Wafer Queues (LOCATION table) * * * * * Begin Case Case Stage EQ 'GROWTH' RDSNos = Xlate('WO_MAT', QInCassIDs, 'RDS_NO', 'X') ElapTms = Xlate('WO_MAT', QInCassIDs, 'ELAP_TM', 'X') rCnt = DCount(RdSNos, @VM) FOR R = 1 TO rCnt RDSNo = RDSNos<1,R> ElapTm = ElapTms<1,R> LOCATE RDSNo IN StageRdsNos BY 'AR' USING @VM SETTING Pos ELSE StageWaitCnts = INSERT(StageWaitCnts,1,Pos,0,'') ;* No wafers yet (we are at the cassette level) StageRDSNos = INSERT(StageRDSNos,1,Pos,0,RDSNo) StageWaitIDs = INSERT(StageWaitIDs,1,Pos,0,'') ;* No wafer IDs yet (we are at the cassette level) StageToolIDs = INSERT(StageToolIDs,1,Pos,0,'') ;* Not on a tool this is the Queues StageWaitTms = INSERT(StageWaitTms,1,Pos,0,ElapTm) StageRunTms = INSERT(StageRunTms,1,Pos,0,'') END NEXT R Case Stage EQ 'ETCH' For each QInEtchID in QInEtchIDs using @VM ElapTm = Xlate('GAN_ETCH', QInEtchID, 'ELAP_HOURS', 'X') LOCATE QInEtchID IN StageRDSNos BY 'AR' USING @VM SETTING Pos THEN StageRunCnts<1,Pos> = StageRunCnts<1,Pos> + 1 StageRunIDs = INSERT(StageRunIDs,1,Pos,-1,QInEtchID) END ELSE StageWaitCnts = INSERT(StageWaitCnts,1,Pos,0,'') StageRDSNos = INSERT(StageRDSNos,1,Pos,0, QInEtchID) StageWaitIDs = INSERT(StageWaitIDs,1,Pos,0, '') StageToolIDs = INSERT(StageToolIDs,1,Pos,0,'') ;* Not on a tool this is the Queues StageWaitTms = INSERT(StageWaitTms,1,Pos,0,ElapTm) StageRunTms = INSERT(StageRunTms,1,Pos,0,'') END Next QInEtchID Case Otherwise$ RDSNos = XLATE('WO_WFR',QInWfrIDs,'RDS_NO','X') ;* Wafers in the Queue ElapTms = XLATE('WO_WFR',QInWfrIDs,'ELAP_TM','X') ;* Times since last event rCnt = DCount(QInWfrIDs, @VM) FOR R = 1 TO rCnt RDSNo = RDSNos<1,R> ElapTm = ElapTms<1,R> QInWfrID = QInWfrIDs<1,R> If Stage _EQC 'DISP' then ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec NumWfrsInCass = DCount(InWfrIDs, @VM) NumDispWfrs = 0 For each WOWfrID in InWfrIDs using @VM setting vPos ThisWOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID) LocQs = ThisWOWfrRec Locate 'GGR*Q_DISP' in LocQs using @VM setting vPos then // Wafer has been dispositioned at some point NumDispWfrs += 1 end Next WOWfrID If NumWfrsInCass NE NumDispWfrs then ElapTm = '0.0' end LOCATE RDSNo IN StageRdsNos BY 'AR' USING @VM SETTING Pos THEN StageWaitCnts<1,Pos> = StageWaitCnts<1,Pos> + 1 StageWaitIDs = INSERT(StageWaitIDs,1,Pos,-1,QInWfrID) END ELSE StageWaitCnts = INSERT(StageWaitCnts,1,Pos,0,1) StageRDSNos = INSERT(StageRDSNos,1,Pos,0,RDSNo) StageWaitIDs = INSERT(StageWaitIDs,1,Pos,0,QINWfrID) StageToolIDs = INSERT(StageToolIDs,1,Pos,0,'') ;* Not on a tool this is the Queues StageWaitTms = INSERT(StageWaitTms,1,Pos,0,ElapTm) StageRunTms = INSERT(StageRunTms,1,Pos,0,'') END NEXT R End Case * * * * * Tool Queues * * * * * tCnt = COUNT(ToolIDs,@VM) + (ToolIDs NE '') FOR T = 1 TO tCnt ToolID = ToolIDs<1,T> If Stage NE 'ETCH' then RunWfrIDs = XLATE('TOOL_WFR',ToolID,TOOL_WFR_WFR_ID$,'X') RDSNos = XLATE('WO_WFR',RunWfrIDs,'RDS_NO','X') ElapTms = XLATE('WO_WFR',RunWfrIDs,'ELAP_TM','X') rCnt = DCount(RDSNos, @VM) FOR R = 1 TO rCnt Skip = False$ RDSNo = RDSNos<1,R> ElapTm = ElapTms<1,R> ToolWfrID = RunWfrIDs<1,R> If ( (Stage NE 'G_RDS') and (Stage NE 'GROWTH') and (Stage NE 'G_RATE') ) then WfrID = ToolWfrID Convert '*' to '.' in WfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RDSNo:'*':Stage:'*':WfrID) ToolClass = RunStageWfrRec StageStatus = RunStageWfrRec RunStageID = Gan_Services('GetStageID', '', '', ToolClass) If ( (RunStageID NE Stage) or (StageStatus NE 'START') ) then Skip = True$ end If Skip EQ False$ then If RDSNo NE '' then LOCATE RDSNo IN StageRDSNos BY 'AR' USING @VM SETTING Pos THEN StageRunCnts<1,Pos> = StageRunCnts<1,Pos> + 1 StageRunIDs = INSERT(StageRunIDs,1,Pos,-1,ToolWfrID) Locate ToolID in StageToolIDs using @VM setting tPos else StageToolIDs = INSERT(StageToolIDs,1,Pos,-1,ToolID) end Locate ElapTm in StageRunTms using @VM setting ePos else StageRunTms = INSERT(StageRunTms,1,Pos,0,ElapTm) end END ELSE StageRunCnts = INSERT(StageRunCnts,1,Pos,0,1) StageRDSNos = INSERT(StageRDSNos,1,Pos,0,RDSNo) StageRunIDs = INSERT(StageRunIDs,1,Pos,0,ToolWfrID) StageToolIDs = INSERT(StageToolIDs,1,Pos,0,ToolID) StageWaitTms = INSERT(StageWaitTms,1,Pos,0,'') StageRunTms = INSERT(StageRunTms,1,Pos,0,ElapTm) StageWaitIDs = INSERT(StageWaitIDs,1,Pos,0,'') StageWaitCnts = INSERT(StageWaitCnts,1,Pos,0,'') END end end NEXT R end else // Etch stage RunEtchIDs = XLATE('TOOL_ETCH', ToolID, TOOL_ETCH_ETCH_ID$, 'X') For each ToolEtchID in RunEtchIDs using @VM setting tPos GaNEtchKey = Field(ToolEtchID, '-', 2) ElapTm = XLATE('GAN_ETCH', GaNEtchKey, 'ELAP_HOURS', 'X') LocEvents = XLATE('GAN_ETCH', GaNEtchKey, 'LOC_EVENT', 'X') EtchStartStatus = LocEvents<1,2> EQ 'START' EtchStopStatus = LocEvents<1,3> EQ 'STOP' If (EtchStartStatus EQ True$) and (EtchStopStatus EQ False$) then LOCATE ToolEtchID IN StageRDSNos BY 'AR' USING @VM SETTING Pos THEN StageRunCnts<1,Pos> = StageRunCnts<1,Pos> + 1 StageRunIDs = INSERT(StageRunIDs,1,Pos,-1,ToolEtchID) StageToolIDs = INSERT(StageToolIDs,1,Pos,0,ToolID) StageRunTms = INSERT(StageRunTms,1,Pos,0,ElapTm) END ELSE StageRunCnts = INSERT(StageRunCnts,1,Pos,0,1) StageRDSNos = INSERT(StageRDSNos,1,Pos,0,ToolEtchID) StageRunIDs = INSERT(StageRunIDs,1,Pos,0,ToolEtchID) StageToolIDs = INSERT(StageToolIDs,1,Pos,0,ToolID) StageWaitTms = INSERT(StageWaitTms,1,Pos,0,'') StageRunTms = INSERT(StageRunTms,1,Pos,0,ElapTm) END end Next ToolEtchID end NEXT T * Build the stage lines * * * * * Sort by DSND StageWaitTms SortArray = '' slCnt = DCount(StageRDSNos, @VM) FOR M = 1 TO slCnt SortLine = StageWaitTms<1,M>:@FM SortLine := StageRDSNos<1,M>:@FM SortLine := StageWaitIDs<1,M>:@FM SortLine := StageRunIDs<1,M>:@FM SortLine := StageToolIDs<1,M>:@FM SortLine := StageRunTms<1,M>:@FM SortLine := StageWaitCnts<1,M>:@FM SortLine := StageRunCnts<1,M> SortArray := SortLine:@RM NEXT M a = LEN(SortArray) V119('S','','D','R',SortArray,'') IF Get_Status(errCode) THEN ErrMsg(errCode) END StageWaitTms = '' StageRDSNos = '' StageWaitIDs = '' StargeRunWfrIDs = '' StageToolIDs = '' StageRunTms = '' StageWaitCnts = '' StageRunCnts = '' Line = 0 LOOP SortLine = SortArray[1,@RM] SortArray[1,COL2()] = '' UNTIL SortLine = '' Line += 1 StageWaitTms<1,Line> = SortLine<1> StageRDSNos<1,Line> = SortLine<2> StageWaitIDs<1,Line> = SortLine<3> StageRunIDs<1,Line> = SortLine<4> StageToolIDs<1,Line> = SortLine<5> StageRunTms<1,Line> = SortLine<6> StageWaitCnts<1,Line> = SortLine<7> StageRunCnts<1,Line> = SortLine<8> REPEAT If Stage EQ 'ETCH' then StageLineCnt = DCount(StageRunIDs,@VM) + DCount(StageWaitIDs,@VM) + DCount(StageRDSNos,@VM) Line = Stage:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM ;* Stage on a blank line for separator LineCnt += 1 Result = Line For N = 1 TO StageLineCnt EtchID = StageRunIDs<1,N> WaitWfrIDs = StageWaitIDs<1,N> RunWfrIDs = StageRunIDs<1,N> WaitWfrPri = '' RunWfrPri = '' Line = @VM ;* Place holder Line := @VM ;* RDSNo Line := EtchID:@VM ;* EtchID (from Etch manager) Line := @VM ;* EpiPartNo Line := @VM ;* Run Priority Line := StageWaitCnts<1,N>:@VM ;* Wait Wfr Cnts Line := StageWaitTms<1,N>:@VM ;* Wait Times Line := WaitWfrIDs:@VM ;* Wafer ID Line := StageToolIDs<1,N>:@VM ;* Tool ID Line := @VM ;* Run Wfr Cnts Line := StageRunTms<1,N>:@VM ;* Run Times Line := @VM ;* Run Wfr IDs LineCnt += 1 Result = Line Next N end else StageLineCnt = COUNT(StageRDSNos,@VM) + (StageRDSNos NE '') ;* All the RDS Nos in this stage Line = Stage:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM ;* Stage on a blank line for separator LineCnt += 1 Result = Line For N = 1 TO StageLineCnt RDSNo = StageRDSNos<1,N> RDSRec = XLATE('REACT_RUN',RDSNo,'','X') EpiPartNo = XLATE('WO_LOG',RDSRec,WO_LOG_EPI_PART_NO$,'X') GanRunID = RDSRec RunPri = RDSRec WaitWfrIDs = StageWaitIDs<1,N> RunWfrIDs = StageRunIDs<1,N> IF INDEX(WaitWfrIDs,@SVM,1) THEN WaitWfrIDs = 'Multi' IF INDEX(RunWfrIDs,@SVM,1) THEN RunWfrIDs = 'Multi' Line = @VM ;* Place holder Line := RDSNo:@VM ;* RDSNo Line := GanRunID:@VM ;* GanRunID Line := EpiPartNo:@VM ;* EpiPartNo Line := RunPri:@VM ;* Run Priority Line := StageWaitCnts<1,N>:@VM ;* Wait Wfr Cnts Line := StageWaitTms<1,N>:@VM ;* Wait Times Line := WaitWfrIDs:@VM ;* Wafer I Line := StageToolIDs<1,N>:@VM ;* Tool ID Line := StageRunCnts<1,N>:@VM ;* Run Wfr Cnts Line := StageRunTms<1,N>:@VM ;* Run Times Line := RunWfrIDs:@VM ;* Run Wfr IDs LineCnt += 1 Result = Line NEXT N end NEXT S Database_Services('WriteDataRow', 'APP_INFO', 'GAN_WIP', Result, True$, False$, True$) RETURN * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ToolWIP: * * * * * * * PopupLiteral = XLATE('SYSREPOSPOPUPS', @APPID<1>:'**':'GAN_WIP_STAGES',PDISPLAY$,'X') CONVERT @VM:@SVM TO @FM:@VM IN PopupLiteral OPEN 'DICT.REACT_RUN' TO DictReactRun ELSE ErrorMsg = 'Unable to open "DICT.REACT_RUN" for Btree.Extract' RETURN END OPEN 'DICT.RUN_STAGE' TO DictRunStage ELSE ErrorMsg = 'Unable to open "DICT.RUN_STAGE" for Btree.Extract' RETURN END OPEN 'DICT.RUN_STAGE_WFR' TO DictRunStageWfr ELSE ErrorMsg = 'Unable to open "DICT.RUN_STAGE_WFR" for Btree.Extract' RETURN END LineCnt = 0 StageCnt = COUNT(PopupLiteral,@FM) + (PopupLiteral NE '') Header = 'Stage':@VM ;* Column headers for export Header := 'Runs':@VM Header := 'Tot Runs':@VM Header := 'RDS No':@VM Header := 'EPI Part No':@VM Header := 'Run ID':@VM Header := 'State':@VM Header := 'Wfr Cnt':@VM Header := 'Tool Type':@VM Header := 'Tool ID' LineCnt += 1 Result = Header FOR S = 1 TO StageCnt Stage = PopupLiteral StageDesc = PopupLiteral CharFlag = PopupLiteral ToolClass = PopupLiteral QInWfrIDs = XLATE('TOOL_CLASS',ToolClass,'QIN_WFR_ID','X') RDSNos = XLATE('WO_WFR',QInWfrIDs,'RDS_NO','X') NEXT S RETURN