Function Disposition_Services(@Service, @Params) /*********************************************************************************************************************** Name : Disposition_Services Description : Handler program for all Disposition services. Notes : Application errors should be logged using the Error Services module. There are a few methodological assumptions built into way errors are managed which are important to understand in order to properly work with Error Services: - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger this will appear backwards since the originating procedure always appears at the bottom of the list and the current routine appears at the top of the list. We are using this orientation because it is common to refer to the process of calling other procedures as 'drilling down'. - The reason for defining the orientation of the call stack is because Error_Services allows for multiple error conditions to be appended to an original error. In most cases this will happen when a procedure at the bottom of the stack generates an error condition and then returns to its calling procedure. This higher level procedure can optionally add more information relevant to itself. This continues as the call stack 'bubbles' its way back to the top to where the originating procedure is waiting. - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus) preserve their error state until explicitly cleared. This can hinder the normal execution of code since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists. Our philosophy is that error conditions should automatically be cleared before a new procedure is executed to avoid this problem. However, the nature of Basic+ does not make this easy to automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our philosophy then it should include a call into the 'Clear' service request at the top of the program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.) - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any error conditions that were set before. Parameters : Service [in] -- Name of the service being requested Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 08/20/20 djs Original programmer. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert SERVICE_SETUP $insert REACT_RUN_EQUATES $insert WO_WFR_EQUATES $insert RUN_STAGE_WFR_EQUATES $insert APP_INSERTS Declare subroutine Error_Services, Database_Services, GaN_Services, Disposition_Services Declare function Database_Services, Error_Services, DateTime, GaN_Services GoToService else Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.') end Return Response else '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Services //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- // AutoDispositionRun // // //---------------------------------------------------------------------------------------------------------------------- Service AutoDispositionRun(RDSNo) If RDSNo NE '' then ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) If Error_Services('NoError') then InWfrIDs = ReactRunRec For each WfrID in InWfrIDs using @VM Disposition_Services('AutoDispositionWfr', WfrID) Next WfrID end end end service //---------------------------------------------------------------------------------------------------------------------- // AutoDispositionWfr // // //---------------------------------------------------------------------------------------------------------------------- Service AutoDispositionWfr(WfrID) RDSNo = Xlate('WO_WFR', WfrID, 'RDS_NO', 'X') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') Begin Case Case TechType EQ 'P' // Production // Update missing and out of spec flags before performing auto disposition. GaN_Services('UpdateDataFlags', RDSNo) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) OrigReactRunRec = ReactRunRec NCRFlags = ReactRunRec InWfrIDs = ReactRunRec DispFlags = ReactRunRec Grades = ReactRunRec Reasons = ReactRunRec CharFlags = ReactRunRec ShipFlags = ReactRunRec CritStages = ReactRunRec WfrStages = ReactRunRec MissingDataFlags = ReactRunRec OutOfSpecFlags = ReactRunRec ValidationDisFlags = ReactRunRec ScrapRDS = ReactRunRec InternalFlags = ReactRunRec ExternalFlags = ReactRunRec CharList = ReactRunRec RDSClosed = ReactRunRec AllWfrsComp = Gan_Services('ReadyToClose', RDSNo) GaNMetStages = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') ANKO = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X') Locate WfrID in InWfrIDs using @VM setting WaferPos then CharFlag = CharFlags<0, WaferPos> If CharFlag EQ True$ then // Characterization disposition logic WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) OrigWOWfrRec = WOWfrRec ShipFlag = ShipFlags<0, WaferPos> NCRNo = Xlate('WO_WFR', WfrID, 'RDS_NCR_NO', 'X') NCRFlag = NCRFlags<0, WaferPos> Grade = WOWfrRec Reason = Reasons<0, WaferPos> CharFlag = CharFlags<0, WaferPos> DispFlag = DispFlags<0, WaferPos> MissingDataValidFlag = ValidationDisFlags<0, WaferPos> DataOutOfSpec = OutOfSpecFlags<0, WaferPos> DataIsMissing = MissingDataFlags<0, WaferPos> InternalFlag = InternalFlags<0, WaferPos> ExternalFlag = ExternalFlags<0, WaferPos> WfrStatus = WOWfrRec MetStatus = GaN_Services('GetMetrologyStatus', WfrID) CharType = GaN_Services('GetCharType', WfrID) WfrIsRunning = GaN_Services('WfrIsRunning', WfrID) If NCRNo NE '' then LossCode = Xlate('NCR', NCRNo, 'LOSS_CODE', 'X') NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X') end else LossCode = '' NCRStatus = '' end If ( ( ( (NCRNo NE '') and (LossCode NE 'G24') ) or (ANKO EQ True$) ) and (RDSClosed NE True$) and ( (Grade EQ 'Prod') or (LossCode NE 'G24') ) and (MetStatus EQ True$) ) then // Retain the wafer if it hasn't been retained yet (the service checks this). Gan_Services('RetainWafer', WfrID) end else Gan_Services('ClearRetainInfo', WfrID) end // Get retain information now in case it has changed by the code block above WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) RetainBox = WOWfrRec RetainSlot = WOWfrRec RetainSig = WOWfrRec If ( (LossCode EQ 'G19') or (LossCode EQ 'G24') ) then ******** External (G19) or Broken (G24) Characterization Wafer ******** InternalFlag = False$ ExternalFlag = (LossCode EQ 'G19') Grade = 'Scrap' ShipFlag = False$ If ANKO EQ True$ then NCRFlag = False$ DispFlag = ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) end else NCRFlag = True$ DispFlag = ( (MetStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) end Begin Case Case MetStatus EQ False$ WfrStatus = 'Metrology is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( (NCRNo EQ '') and (ANKO NE True$) ) WfrStatus = 'Wafer has not been NCRed' // Move wafer to DISP Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) ) WfrStatus = 'NCR has not been closed' // Move wafer to DISP Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case end else ******** Internal Characterization Wafer ******** InternalFlag = True$ ExternalFlag = False$ NCRFlag = False$ // Need to look if another wafer has already been characterized. Locate WfrID in CharList using @VM setting CharIndex then If CharIndex EQ 1 then CharReason = 'Internal Characterization (Primary)' end else CharReason = 'Internal Characterization (Secondary)' end end else CharReason = 'Error' end Reason = CharReason If ( (CharType EQ 'Light') and (NCRNo EQ '') and ( (DataOutOfSpec EQ False$) or (MissingDataValidFlag EQ True$) ) ) then Grade = 'Prod' If ANKO EQ True$ then ShipFlag = False$ end else ShipFlag = True$ end DispFlag = ( ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (NCRNo EQ '') or ( (NCRNo NE '') and (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) ) ) ) end else // Full characterization or metrology failure Grade = 'Scrap' ShipFlag = False$ DispFlag = ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) end Begin Case Case WfrIsRunning EQ True$ // Move wafer to the tool queue it is running on ToolID = GaN_Services('GetWfrRunTool', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) GaN_Services('MoveWfrToQueue', WfrID, ToolID) Case MetStatus EQ False$ WfrStatus = 'Metrology is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue if it isn't already there. Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (CharType EQ 'Light') ) WfrStatus = 'NCR has not been closed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case end NCRFlags<0, WaferPos> = NCRFlag Reasons<0, WaferPos> = Reason DispFlags<0, WaferPos> = DispFlag ShipFlags<0, WaferPos> = ShipFlag InternalFlags<0, WaferPos> = InternalFlag ExternalFlags<0, WaferPos> = ExternalFlag ReactRunRec = NCRFlags ReactRunRec = Reasons ReactRunRec = DispFlags ReactRunRec = ShipFlags ReactRunRec = InternalFlags ReactRunRec = ExternalFlags WOWfrRec = Grade WOWfrRec = RetainBox WOWfrRec = RetainSlot WOWfrRec = WfrStatus If (WOWfrRec NE OrigWOWfrRec) then Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) end end else // Non-characterization disposition logic WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) OrigWOWfrRec = WOWfrRec ShipFlag = ShipFlags<0, WaferPos> NCRNo = WOWfrRec NCRFlag = NCRFlags<0, WaferPos> CharFlag = CharFlags<0, WaferPos> DispFlag = DispFlags<0, WaferPos> Grade = WOWfrRec Reason = Reasons<0, WaferPos> MissingDataValidFlag = ValidationDisFlags<0, WaferPos> DataOutOfSpec = OutOfSpecFlags<0, WaferPos> DataIsMissing = MissingDataFlags<0, WaferPos> WfrStatus = WOWfrRec CriticalFailFlag = WOWfrRec DispStatus = GaN_Services('GetDispStatus', WfrID) If NCRNo NE '' then LossCode = Xlate('NCR', NCRNo, 'LOSS_CODE', 'X') NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X') end else LossCode = '' NCRStatus = '' end // Internal Flag - Non-characterized wafers never considered "Internal" InternalFlag = False$ ExternalFlag = (LossCode EQ 'G19') If ( ( ( (NCRNo NE '') and (LossCode NE 'G24') ) or (ANKO EQ True$) ) and (RDSClosed NE True$) and (CriticalFailFlag NE True$) and (DispStatus EQ True$) ) then // Retain the wafer if it hasn't been retained yet (the service checks this). Gan_Services('RetainWafer', WfrID) end else Gan_Services('ClearRetainInfo', WfrID) end // Get retain information now in case it has changed by the code block above WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) RetainBox = WOWfrRec RetainSlot = WOWfrRec RetainSig = WOWfrRec Begin Case Case CriticalFailFlag EQ True$ // Bow and/or warp critical limit exceeded, so the wafer must be // destroyed to prevent damage to candela tools Grade = 'Scrap' NCRFlag = True$ ShipFlag = False$ DispFlag = ( (NCRNo NE '') and (NCRStatus EQ 'C') ) Reason = 'Bow and/or warp critical limit exceeded' Begin Case Case ( (NCRNo NE '') and (NCRStatus EQ 'C') ) WOWfrRec = 'Ready to close' Case ( (NCRNo NE '') and (NCRStatus NE 'C') ) WOWfrRec = 'NCR must be closed' Case NCRNo EQ '' WOWfrRec = 'Wafer requires an NCR' End Case // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (LossCode EQ 'G19') or (LossCode EQ 'G24') ) ******** External (G19) or Broken (G24) Wafer ******** Grade = 'Scrap' Reason = '' ; // In this case the reason will come from the NCR instead If ANKO EQ True$ then NCRFlag = False$ DispFlag = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) ) end else NCRFlag = True$ DispFlag = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox EQ '') or (RetainSig NE '') ) ) end ShipFlag = False$ Begin Case Case DispStatus EQ False$ WfrStatus = 'Metrology is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case ( (NCRNo EQ '') and (ANKO NE True$) ) WfrStatus = 'Wafer has not been NCRed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) ) WfrStatus = 'NCR has not been closed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case Case ScrapRDS EQ True$ // A characterized wafer has failed, so the entire lot must be scrapped If ANKO EQ True$ then NCRFlag = False$ DispFlag = ( (DispStatus EQ True$) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) ) end else NCRFlag = True$ DispFlag = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) ) end Grade = 'Scrap' Reason = 'Characterization Failure - OOS' // Scrapped lots are not eligible to ship ShipFlag = False$ Begin Case Case DispStatus EQ False$ WfrStatus = 'Disposition stage is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case ( (NCRNo EQ '') and (ANKO NE True$) ) WfrStatus = 'Wafer has not been NCRed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) ) WfrStatus = 'NCR has not been closed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case Case DataOutOfSpec EQ True$ // Data out of spec and the RDS has not been scrapped due to characterization failure If ANKO EQ True$ then NCRFlag = False$ DispFlag = ( (DispStatus EQ True$) and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) end else NCRFlag = True$ DispFlag = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) end Grade = 'Scrap' Reason = 'Metrology Failure - OOS' // Failed wafers are never eligible to ship ShipFlag = False$ Begin Case Case DispStatus EQ False$ WfrStatus = 'Disposition stage is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case ( (NCRNo EQ '') and (ANKO NE True$) ) WfrStatus = 'Wafer has not been NCRed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) ) WfrStatus = 'NCR has not been closed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case Case ( (DataOutOfSpec EQ False$) and (NCRNo NE '') ) // Data within spec, but wafer manually NCRd Grade = 'Scrap' Reason = 'NCR' NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X') DispFlag = ( (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) // NCRd wafers are never eligible to ship ShipFlag = False$ Begin Case Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case NCRStatus NE 'C' WfrStatus = 'NCR has not been closed' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case Case DataOutOfSpec EQ False$ // Data within spec and the RDS has not been scrapped due to characterization failure NCRFlag = False$ If DispStatus EQ True$ then Grade = 'Prod' end else Grade = '' end Reason = '' If ANKO EQ True$ then DispFlag = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) ) ShipFlag = False$ end else DispFlag = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox EQ '') or (RetainSig NE '') ) ) ShipFlag = ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) end Begin Case Case DispStatus EQ False$ WfrStatus = 'Disposition stage is not complete' // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') ) WfrStatus = 'Wafer has not yet been retained' // Move wafer to RETAIN queue Gan_Services('RemoveWfrFromWIP', WfrID) RetainQ = Gan_Services('GetLocQueueID', 'RETAIN') Gan_Services('MoveWfrToQueue', WfrID, RetainQ) Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) ) WfrStatus = 'Metrology data is missing and data validation has not been disabled' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) Case DispFlag EQ True$ WfrStatus = 'Ready to close' // Move wafer to DISP queue Gan_Services('RemoveWfrFromWIP', WfrID) DispQ = Gan_Services('GetLocQueueID', 'DISP') Gan_Services('MoveWfrToQueue', WfrID, DispQ) End Case End Case NCRFlags<0, WaferPos> = NCRFlag Reasons<0, WaferPos> = Reason DispFlags<0, WaferPos> = DispFlag ShipFlags<0, WaferPos> = ShipFlag InternalFlags<0, WaferPos> = InternalFlag ExternalFlags<0, WaferPos> = ExternalFlag ReactRunRec = NCRFlags ReactRunRec = Reasons ReactRunRec = DispFlags ReactRunRec = ShipFlags ReactRunRec = InternalFlags ReactRunRec = ExternalFlags WOWfrRec = Grade WOWfrRec = RetainBox WOWfrRec = RetainSlot WOWfrRec = WfrStatus If (WOWfrRec NE OrigWOWfrRec) then Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) end end end If ReactRunRec NE OrigReactRunRec then Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) end Case TechType EQ 'E' // Engineering Run CurrDTM = DateTime() ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) OrigReactRunRec = ReactRunRec InWfrIDs = ReactRunRec ShipFlags = ReactRunRec RetainFlags = ReactRunRec InternalFlags = ReactRunRec ExternalFlags = ReactRunRec CassDispComp = ReactRunRec WfrsDispReady = ReactRunRec NCRReqFlags = ReactRunRec CharFlags = ReactRunRec Locate WfrID in InWfrIDs using @VM setting WfrIndex then WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) OrigWOWfrRec = WOWfrRec ShipFlag = ShipFlags<0, WfrIndex> RetainFlag = RetainFlags<0, WfrIndex> InternalFlag = InternalFlags<0, WfrIndex> ExternalFlag = ExternalFlags<0, WfrIndex> CharFlag = CharFlags<0, WfrIndex> DispReady = WfrsDispReady<0, WfrIndex> NCRNo = WOWfrRec NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X') CriticalFailFlag = WOWfrRec NCRReq = NCRReqFlags<0, WfrIndex> DestStatus = GaN_Services('GetDestroyedStatus', WfrID) If ( (CharFlag EQ 'DUMMY') or (CharFlag EQ 'EMPTY') ) then DispReady = True$ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady WOWfrRec = 'Ready to close' end If DestStatus EQ True$ then If ( (InternalFlag NE True$) and (ExternalFlag NE True$) ) then // Mark wafer's internal flag. Clear all other flags. ShipFlag = False$ RetainFlag = False$ InternalFlag = True$ ExternalFlag = False$ ShipFlags<0, WfrIndex> = ShipFlag RetainFlags<0, WfrIndex> = RetainFlag InternalFlags<0, WfrIndex> = InternalFlag ExternalFlags<0, WfrIndex> = ExternalFlag ReactRunRec = ShipFlags ReactRunRec = RetainFlags ReactRunRec = InternalFlags ReactRunRec = ExternalFlags end end else // Wafer may have been previously marked as external or internal. Since the destroyed status // is now false clear internal and external flag. InternalFlag = False$ ExternalFlag = False$ InternalFlags<0, WfrIndex> = InternalFlag ExternalFlags<0, WfrIndex> = ExternalFlag ReactRunRec = InternalFlags ReactRunRec = ExternalFlags end MetStatus = GaN_Services('GetMetrologyStatus', WfrID) DispStatus = GaN_Services('GetDispStatus', WfrID) Begin Case Case CriticalFailFlag EQ True$ // Bow and/or warp critical limit exceeded, so the wafer must be // destroyed to prevent damage to candela tools Reason = 'Bow and/or warp critical limit exceeded' Begin Case Case ( (NCRNo NE '') and (NCRStatus EQ 'C') ) WOWfrRec = 'Ready to close' Case ( (NCRNo NE '') and (NCRStatus NE 'C') ) WOWfrRec = 'NCR must be closed' Case NCRNo EQ '' WOWfrRec = 'Wafer requires an NCR' End Case DispReady = ( (NCRNo NE '') and (NCRStatus EQ 'C') ) WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady Case ( (MetStatus EQ True$) or (DispStatus EQ True$) ) // Check Ship, Interal, External, and Retain conditions to determine if wafer should be removed from the WIP FormattedWfrID = WfrID Convert '*' to '.' in FormattedWfrID Begin Case Case ShipFlag EQ True$ GPackQ = GaN_Services('GetLocQueueID', 'G_PACK') ShipID = ReactRunRec RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec If StageStatus _EQC 'INIT' then // Mark DISP stage as complete RunStageWfrRec = @USER4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end Begin Case Case (ShipID EQ '') LocQ = GaN_Services('GetWfrQueue', WfrID) WOWfrRec = 'Wafer needs to be placed in an outbound cassette' If LocQ _EQC GPackQ then // Wafer is being removed from an outbound cassette, so place the wafer back into the G_PACK // queue and reset the G_PACK RUN_STAGE_WFR record to 'INIT'. RunStageWfrKey = RDSNo:'*G_PACK*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec If StageStatus _EQC 'COMP' then RunStageWfrRec = '' RunStageWfrRec = '' RunStageWfrRec = 'INIT' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) Gan_Services('MoveWfrToQueue', WfrID, GPackQ) end end else // Wafer has been marked as shipped in the Disposition Report (Excel spreadsheet), but has // not yet been added to an outbound cassette. Remove the wafer from its current location // (which likely is DISP), then place the wafer in the G_PACK location queue and update // the wafer trace (WO_WFR record). Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, GPackQ) // Update wafer trace (WO_WFR record) LocDTM = WOWfrRec NextPos = DCount(LocDTM, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @USER4 WOWfrRec = 'COMP' WOWfrRec = '' WOWfrRec = GPackQ end Case ( (ShipID NE '') and ( (CassDispComp EQ False$) or (CassDispComp EQ '') ) ) // Wafer is ready for disposition, so mark it as such. Once user marks the cassette // disposition complete, then the wafer will move off the WIP. Move wafer to the G_PACK // location queue if it is not there and update the wafer trace (WO_WFR record). If (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) then LocQ = Gan_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, GPackQ) // Update wafer trace (WO_WFR record) LocDTM = WOWfrRec NextPos = DCount(LocDTM, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @USER4 WOWfrRec = 'G_PACK' WOWfrRec = '' WOWfrRec = GPackQ WOWfrRec = 'Ready to close' DispReady = True$ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady end Case ( (ShipID NE '') and (CassDispComp EQ True$) ) // A ship ID has been added (i.e. the wafer has been placed in an outbound cassette and the // user has marked the cassette disposition as complete, so remove the wafer from the // GaN WIP and mark the G_PACK stage as complete.) RunStageWfrKey = RDSNo:'*G_PACK*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec LocQ = Gan_Services('GetWfrQueue', WfrID) WOWfrRec = 'Run closed' Gan_Services('RemoveWfrFromWIP', WfrID) If StageStatus _EQC 'INIT' then // Mark G_PACK stage as complete RunStageWfrRec = @USER4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end Case Otherwise$ // No action necessary at this time. Null End Case Case RetainFlag EQ True$ RetainSlot = WOWfrRec RetainBox = WOWfrRec RetainSig = WOWfrRec RetainQ = GaN_Services('GetLocQueueID', 'RETAIN') RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec If StageStatus _EQC 'INIT' then // Retain flag has been set and metrology is complete, so mark DISP stage as complete. RunStageWfrRec = @User4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end Begin Case Case ( (RetainSlot EQ '') or (RetainBox EQ '') ) // Wafer needs to go into RETAIN queue until it receives a Retain Slot and Retain Box // If wafer is not at RETAIN, then update wafer trace (WO_WFR record) and move the wafer. WOWfrRec = 'Wafer requires a retain box and retain slot' CurrStage = GaN_Services('GetCurrStage', WfrID) LocQ = GaN_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, RetainQ) If CurrStage NE 'RETAIN' then LocDTM = WOWfrRec NextPos = DCount(LocDTM, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @USER4 WOWfrRec = 'COMP' WOWfrRec = '' WOWfrRec = RetainQ end Case ( (RetainSlot NE '') and (RetainBox NE '') and (CassDispComp NE True$) ) // Wafer is ready for disposition, so mark it as such. Once user marks the cassette // disposition complete, then the wafer will move off the WIP. Move wafer into RETAIN stage // if it is not currently there. This can occur if an RDS is opened after being closed. If ( ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) and (RetainSig NE '') ) then WOWfrRec = 'Ready to close' DispReady = True$ end else WOWfrRec = 'Wafer has not yet been retained' DispReady = False$ end RetainQ = 'GCH*Q_RETAIN' LocQ = Gan_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, RetainQ) LocDTM = WOWfrRec NextPos = DCount(LocDTM, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @USER4 WOWfrRec = 'RETAIN' WOWfrRec = '' WOWfrRec = RetainQ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady Case ( ( (RetainSlot NE '') and (RetainBox NE '') and (RetainSig NE '') ) and (CassDispComp EQ True$) ) // Retain slot and retain box are populated and the user has marked disposition complete -> // mark RETAIN stage complete and remove the wafer from the GaN WIP. RunStageWfrKey = RDSNo:'*RETAIN*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec LocQ = Gan_Services('GetWfrQueue', WfrID) WOWfrRec = 'Run closed' Gan_Services('RemoveWfrFromWIP', WfrID) If StageStatus _EQC 'INIT' then RunStageWfrRec = @User4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end Case Otherwise$ // No action necessary at this time. Null End Case Case InternalFlag EQ True$ Begin Case Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') ) // Wafer is ready for disposition, so mark it as such. Once user marks the cassette // disposition complete, then the wafer will move off the WIP. DispReady = True$ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady WOWfrRec = 'Ready to close' Case CassDispComp EQ True$ // Remove the wafer from the GaN WIP and mark DISP stage as complete. RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec LocQ = GaN_Services('GetWfrQueue', WfrID) WOWfrRec = 'Run closed' Gan_Services('RemoveWfrFromWIP', WfrID) If StageStatus _EQC 'INIT' then // Mark DISP stage as complete RunStageWfrRec = @User4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end End Case Case ExternalFlag EQ True$ Begin Case Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') ) // Check to see if an NCR has been added to this wafer before marking this wafer as ready // to be dispositioned. If ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) then // Wafer is ready for disposition, so mark it as such. Once user marks the cassette // disposition complete, then the wafer will move off the WIP. DispReady = True$ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady WOWfrRec = 'Ready to close' end Case CassDispComp EQ True$ // Remove the wafer from the GaN WIP and mark DISP stage as complete. RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec WOWfrRec = 'Run closed' LocQ = Gan_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) If StageStatus _EQC 'INIT' then // Mark DISP stage as complete RunStageWfrRec = @User4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end End Case Case Otherwise$ // All flags false. Lot aborted or disposition report not found. Begin Case Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') ) // Move wafer to DISP queue if it is not there DispQ = 'GGR*Q_DISP' CurrQ = Gan_Services('GetWfrQueue', WfrID) If CurrQ _NEC DispQ then Gan_Services('RemoveWfrFromWIP', WfrID) Gan_Services('MoveWfrToQueue', WfrID, DispQ) end // Check to see if an NCR has been added to this wafer before marking this wafer as ready // to be dispositioned. If ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) then // Wafer is ready for disposition, so mark it as such. Once user marks the cassette // disposition complete, then the wafer will move off the WIP. DispReady = True$ WfrsDispReady<0, WfrIndex> = DispReady ReactRunRec = WfrsDispReady WOWfrRec = 'Ready to close' end else If NCRReq EQ True$ then WOWfrRec = 'NCR required' end else WOWfrRec = 'Disposition report not found' end end Case CassDispComp EQ True$ // Remove the wafer from the GaN WIP and mark DISP stage as complete. RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec WOWfrRec = 'Run closed' LocQ = GaN_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) If StageStatus _EQC 'INIT' then // Mark DISP stage as complete RunStageWfrRec = @User4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end End Case End Case Case Otherwise$ // Metrology or Disposition not complete WOWfrRec = 'Metrology incomplete' WfrIsRunning = GaN_Services('WfrIsRunning', WfrID) If WfrIsRunning EQ True$ then // Move wafer to the tool queue it is runnig on ToolID = GaN_Services('GetWfrRunTool', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) GaN_Services('MoveWfrToQueue', WfrID, ToolID) end else // Move wafer to next scheduled stage Gan_Services('RemoveWfrFromWIP', WfrID) NextStageID = Gan_Services('GetNextStage', WfrID) NextLocQ = Gan_Services('GetLocQueueID', NextStageID) Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) end End Case If OrigWOWfrRec NE WOWfrRec then Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) end If OrigReactRunRec NE ReactRunRec then Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Case Otherwise$ // Error Null End Case end service //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ClearCursors: For counter = 0 to 8 ClearSelect counter Next counter return