1170 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1170 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| Function PSN_Services(@Service, @Params)
 | |
| /***********************************************************************************************************************
 | |
| 
 | |
|     This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
 | |
|     permission from SRP Computer Solutions, Inc.
 | |
| 
 | |
|     Name        :   PSN_Services
 | |
| 
 | |
|     Description :   Handler program for all module related services.
 | |
| 
 | |
|     Notes       :   Service module to support environmental state issues. Environmental refers to the state of the
 | |
|                     operating system, which includes version, client vs. server, and path to critical systems.
 | |
| 
 | |
|     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)
 | |
|         11/30/20    djs     Original programmer.
 | |
| 
 | |
| ***********************************************************************************************************************/
 | |
| 
 | |
| #pragma precomp SRP_PreCompiler
 | |
| 
 | |
| $insert LOGICAL
 | |
| $insert SERVICE_SETUP
 | |
| $insert PROD_SPEC_EQUATES
 | |
| $insert PRS_STAGE_EQUATES
 | |
| $Insert WO_MAT_QA_EQUATES
 | |
| $Insert QA_MET_EQUATES
 | |
| $Insert RDS_TEST_EQUATES
 | |
| $Insert RDS_TEST_PROP_EQUATES
 | |
| $Insert PRS_LAYER_EQU
 | |
| 
 | |
| Options SpecTypes = 'CLEAN', 'SURFSCAN', 'THICK', 'THICKA', 'RES', 'SRES', 'CRES', 'CONC'
 | |
| 
 | |
| Declare function   Database_Services, Psn_Services, obj_Prod_Spec, Error_Services, SRP_JSON, Cust_Epi_Part_Services
 | |
| Declare function   Prod_Ver_Services, PRS_Stage_Services, SRP_Array
 | |
| Declare subroutine Database_Services, Psn_Services, Error_Services, SRP_JSON, Extract_Si_Keys
 | |
| 
 | |
| GoToService else
 | |
|     Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
 | |
| end
 | |
| 
 | |
| Return Response OR ''
 | |
| 
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| // Service Parameter Options
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| Options BOOLEAN     = True$, False$
 | |
| 
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| // Services
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------------------------
 | |
| // InitializeCritParams
 | |
| //
 | |
| //----------------------------------------------------------------------------------------------------------------------
 | |
| Service InitializeCritParams(PSNo)
 | |
|     
 | |
|     PSRec                               = Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
 | |
|     PSRec<PROD_SPEC_CRITICAL_WARP_MAX$> = 100
 | |
|     PSRec<PROD_SPEC_CRITICAL_BOW_MIN$>  = -40
 | |
|     PSRec<PROD_SPEC_CRITICAL_BOW_MAX$>  = 50
 | |
|     Database_Services('WriteDataRow', 'PROD_SPEC', PSNo, PSRec, True$, False$, True$)    
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service GetRecipes(PSNo)
 | |
|     
 | |
|     ErrorMsg = ''
 | |
|     Recipes  = ''
 | |
|     If PSNo NE '' then
 | |
|         If RowExists('PROD_SPEC', PSNo) then
 | |
|             PropKeys       = ''
 | |
|             Extract_Si_Keys('PRS_PROP', 'PS_NO', PSNo, PropKeys)
 | |
|             Recipes        = Xlate('PRS_PROP', PropKeys, 'MET_RECIPE', 'X')
 | |
|             PRSStageKeys   = ''
 | |
|             Extract_Si_Keys('PRS_STAGE', 'PS_NO', PSNo, PRSStageKeys)
 | |
|             Recipes<0, -1> = Xlate('PRS_STAGE', PRSStageKeys, 'MET_RECIPE', 'X')
 | |
|             Recipes<0, -1> = Xlate('PRS_STAGE', PRSStageKeys, 'SURFSCAN_RECIPE', 'X')
 | |
|             Recipes<0, -1> = @VM : Xlate('PRS_STAGE', PRSStageKeys, 'CLEAN_RECIPE', 'X')
 | |
|             Recipes        = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @VM)            
 | |
|         end else
 | |
|             ErrorMsg = 'Error in ':Service:' service. PROD_SPEC record "':PSNo:'" does not exist.'
 | |
|         end
 | |
|     end else
 | |
|         ErrorMsg = 'Error in ':Service:' service. Null PSNo passed into service.'
 | |
|     end
 | |
|     
 | |
|     If ErrorMsg EQ '' then
 | |
|         Response = Recipes
 | |
|     end else
 | |
|         Error_Services('Add', ErrorMsg)
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service GetAllMetrologyRecipes(PSNo, GetSurfscan, GetClean, GetRes, GetThick)
 | |
|     
 | |
|     Recipes = ''
 | |
|     If GetSurfscan EQ '' then GetSurfscan = True$
 | |
|     If GetClean EQ '' then GetClean = True$
 | |
|     If GetRes EQ '' then GetRes = True$
 | |
|     If GetThick EQ '' then GetThick = True$
 | |
|     
 | |
|     If GetSurfscan then Recipes := PSN_Services('GetSurfscanRecipes', PSNo) : @FM
 | |
|     If GetClean then Recipes := PSN_Services('GetCleanRecipes', PSNo) :@FM
 | |
|     If GetRes then Recipes := PSN_Services('GetResRecipes', PSNo) :@FM
 | |
|     If GetThick then Recipes := PSN_Services('GetThicknessRecipes', PSNo)
 | |
|     
 | |
|     Recipes = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @FM) 
 | |
|     Response = Recipes
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service GetSurfscanRecipes(PSNo)
 | |
|     
 | |
|     Recipes = ''
 | |
|     If PSNo NE '' then
 | |
|         If RowExists('PROD_SPEC', PSNo) then
 | |
|             PropKeys       = ''
 | |
|             Extract_Si_Keys('PRS_PROP', 'PS_NO', PSNo, PropKeys)
 | |
|             PRSStageKeys   = ''
 | |
|             Extract_Si_Keys('PRS_STAGE', 'PS_NO', PSNo, PRSStageKeys)
 | |
|             for each PRSStageKey in PRSStageKeys using @VM setting pPos
 | |
|                 Stage = Xlate('PRS_STAGE', PRSStageKey, 'STAGE', 'X')
 | |
|                 TencorRecipes = Xlate('PRS_STAGE', PRSStageKey, 'SURFSCAN_RECIPE', 'X')
 | |
|                 for each Recipe in TencorRecipes using @VM
 | |
|                     ToolClass = 'TENCOR'
 | |
|                     Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage     
 | |
|                 Next TencorRecipe
 | |
|             Next PRSStageKey
 | |
|             Recipes        = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @FM)
 | |
|         end
 | |
|     end
 | |
|     Response = Recipes
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service GetCleanRecipes(PSNo)
 | |
|     
 | |
|     Recipes = ''
 | |
|     If PSNo NE '' then
 | |
|         If RowExists('PROD_SPEC', PSNo) then
 | |
|             PropKeys       = ''
 | |
|             Extract_Si_Keys('PRS_PROP', 'PS_NO', PSNo, PropKeys)
 | |
|             PRSStageKeys   = ''
 | |
|             Extract_Si_Keys('PRS_STAGE', 'PS_NO', PSNo, PRSStageKeys)
 | |
|             for each PRSStageKey in PRSStageKeys using @VM setting pPos
 | |
|                 Stage = Xlate('PRS_STAGE', PRSStageKey, 'STAGE', 'X')
 | |
|                 CleanRecipes = Xlate('PRS_STAGE', PRSStageKey, 'CLEAN_RECIPE', 'X')
 | |
|                 for each Recipe in CleanRecipes using @VM
 | |
|                     ToolClass = 'CLEAN'
 | |
|                     Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage     
 | |
|                 Next TencorRecipe
 | |
|             Next PRSStageKey
 | |
|             Recipes        = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @FM)
 | |
|         end
 | |
|     end
 | |
|     Response = Recipes
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service GetThicknessRecipes(PSNo)
 | |
|     
 | |
|     ErrorMsg = ''
 | |
|     Recipes  = ''
 | |
|     If PSNo NE '' then
 | |
|         If RowExists('PROD_SPEC', PSNo) then
 | |
|             //First get QA Recipes
 | |
|             PropKeys       = ''
 | |
|             Extract_Si_Keys('PRS_PROP', 'PS_NO', PSNo, PropKeys)
 | |
|             Recipes        = ''
 | |
|             PRSStageKeys   = ''
 | |
|             Extract_Si_Keys('PRS_STAGE', 'PS_NO', PSNo, PRSStageKeys)
 | |
|             for each PRSStageKey in PRSStageKeys using @VM setting pPos
 | |
|                 Stage = Xlate('PRS_STAGE', PRSStageKey, 'STAGE', 'X')
 | |
|                 PRSStageRecipes = Xlate('PRS_STAGE', PRSStageKey, 'MET_RECIPE', 'X')
 | |
|                 for each PRSStageRecipe in PRSStageRecipes using @VM setting rPos
 | |
|                     PropType = Xlate('PRS_STAGE', PRSStageKey, 'MET_PROP', 'X')<1, rPos>
 | |
|                     If PropType EQ 'THICK' OR PropType EQ 'THICKA' then
 | |
|                         Recipe = PRSStageRecipe
 | |
|                         ToolClass = 'FTIR'
 | |
|                         Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage 
 | |
|                     end
 | |
|                 Next PRSStageRecipe
 | |
|             Next PRSStageKey
 | |
|             //Next get Rathole recipes
 | |
|             SpecEpiData = XLATE('PROD_SPEC', PSNo, 'SPEC_EPI', 'X')
 | |
|             swap @VM with @FM in SpecEpiData
 | |
|             swap '~' with @VM in SpecEpiData
 | |
|             ThicknessData = SpecEpiData<13>
 | |
|             ToolClass = ThicknessData<1, 1>
 | |
|             Recipe = ThicknessData<1, 3>
 | |
|             Stage = 'RDS_TEST'
 | |
|             If ToolClass EQ 'FTIR' OR ToolClass EQ 'ADE' then
 | |
|                 Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage 
 | |
|             end
 | |
|             // Remove any duplicate entries
 | |
|             Recipes        = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @FM)                 
 | |
|         end else
 | |
|             ErrorMsg = 'Error in ':Service:' service. PROD_SPEC record "':PSNo:'" does not exist.'
 | |
|         end
 | |
|     end else
 | |
|         ErrorMsg = 'Error in ':Service:' service. Null PSNo passed into service.'
 | |
|     end
 | |
|     
 | |
|     If ErrorMsg EQ '' then
 | |
|         Response = Recipes
 | |
|     end else
 | |
|         Error_Services('Add', ErrorMsg)
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service GetResRecipes(PSNo)
 | |
| 
 | |
|     ErrorMsg = ''
 | |
|     Recipes  = ''
 | |
|     If PSNo NE '' then
 | |
|         If RowExists('PROD_SPEC', PSNo) then
 | |
|             //First get QA Recipes
 | |
|             PropKeys       = ''
 | |
|             Extract_Si_Keys('PRS_PROP', 'PS_NO', PSNo, PropKeys)
 | |
|             Recipes        = ''
 | |
|             PRSStageKeys   = ''
 | |
|             Extract_Si_Keys('PRS_STAGE', 'PS_NO', PSNo, PRSStageKeys)
 | |
|             for each PRSStageKey in PRSStageKeys using @VM setting pPos
 | |
|                 Stage = Xlate('PRS_STAGE', PRSStageKey, 'STAGE', 'X')
 | |
|                 PRSStageRecipes = Xlate('PRS_STAGE', PRSStageKey, 'MET_RECIPE', 'X')
 | |
|                 for each PRSStageRecipe in PRSStageRecipes using @VM setting rPos
 | |
|                     PropType = Xlate('PRS_STAGE', PRSStageKey, 'MET_PROP', 'X')<1, rPos>
 | |
|                     ToolClass = Xlate('PRS_STAGE', PRSStageKey, 'MET_TOOL_CLASS', 'X')<1, rPos>
 | |
|                     If PropType EQ 'RES' OR PropType EQ 'SRES' OR PropType EQ 'CRES' OR PropType EQ 'CONC' then
 | |
|                         Recipe = PRSStageRecipe
 | |
|                         ToolClass = ToolClass
 | |
|                         Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage 
 | |
|                     end
 | |
|                 Next PRSStageRecipe
 | |
|             Next PRSStageKey
 | |
|             //Next get Rathole recipes
 | |
|             Stage = 'RDS_TEST'
 | |
|             SpecEpiData = XLATE('PROD_SPEC', PSNo, 'SPEC_EPI', 'X')
 | |
|             swap @VM with @FM in SpecEpiData
 | |
|             swap '~' with @VM in SpecEpiData
 | |
|             ResData1 = SpecEpiData<19>
 | |
|             
 | |
|             If ResData1 NE '' then
 | |
|                 ToolClass = ResData1<1, 1>
 | |
|                 Recipe = ResData1<1, 3>
 | |
|                 Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage 
 | |
|             end
 | |
|             
 | |
|             ResData2 = SpecEpiData<14>
 | |
|             If ResData2 NE '' then
 | |
|                 ToolClass = ResData2<1, 1>
 | |
|                 Recipe = ResData2<1, 3>
 | |
|                 Recipes<-1> = ToolClass : @VM : Recipe : @VM : Stage  
 | |
|             end
 | |
|             
 | |
|             // Remove any duplicate entries
 | |
|             Recipes        = SRP_Array('Clean', Recipes, 'TrimAndMakeUnique', @FM)                 
 | |
|         end else
 | |
|             ErrorMsg = 'Error in ':Service:' service. PROD_SPEC record "':PSNo:'" does not exist.'
 | |
|         end
 | |
|     end else
 | |
|         ErrorMsg = 'Error in ':Service:' service. Null PSNo passed into service.'
 | |
|     end
 | |
|     
 | |
|     If ErrorMsg EQ '' then
 | |
|         Response = Recipes
 | |
|     end else
 | |
|         Error_Services('Add', ErrorMsg)
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| Service CheckPSNStages(PSNo, Stage)
 | |
|     
 | |
|     Begin Case
 | |
|         Case Stage Eq 'PRE'
 | |
|             CleansCheck = Psn_Services('CheckCleansParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             VisualCheck = Psn_Services('CheckVisualParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             
 | |
|         Case  Stage Eq 'LOAD'
 | |
|             InstructionsCheck = Psn_Services('CheckInstructionParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|         Case Stage Eq 'FWI'
 | |
|             VisualCheck = Psn_Services('CheckVisualParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|         Case Stage Eq 'LWI'
 | |
|             VisualCheck = Psn_Services('CheckVisualParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             SurfaceCheck = Psn_Services('CheckSurfaceParms',PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             
 | |
|         Case Stage Eq 'POST'
 | |
|             CleansCheck = Psn_Services('CheckCleansParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             SurfaceCheck = Psn_Services('CheckSurfaceParms',PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|         Case Stage Eq 'QA' OR 'UNLOAD'
 | |
|             QAMetCheck = Psn_Services('CheckQAMetParms', PSNo, Stage)
 | |
|             IF Error_Services('GetMessage') NE '' then
 | |
|                 Return 
 | |
|             end
 | |
|             
 | |
|             
 | |
|     End Case
 | |
|     GoSub CheckAdHoc
 | |
|     Return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service CheckCleansParms(PSNo, Stage)
 | |
| 
 | |
|     Response    = 1
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec    = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
| 
 | |
|     IF StageRec<PRS_STAGE_CLEAN_SIG_REQ$> EQ 1 then
 | |
|         IF StageRec<PRS_STAGE_CLEAN_TOOL$> EQ '' then
 | |
|             FailReason = 'Clean Tool not selected for ' : Stage : ' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return 
 | |
|         end
 | |
|         If StageRec<PRS_STAGE_CLEAN_RECIPE$> EQ '' then
 | |
|             FailReason = 'Clean Recipe not selected for ' : Stage : ' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return 
 | |
|         end
 | |
|     end else
 | |
|         IF Stage EQ 'PRE' OR Stage EQ 'POST' then
 | |
|             FailReason = 'Cleans Signature Required for ' : Stage : ' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return 
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service CheckVisualParms(PSNo, Stage)
 | |
|     
 | |
|     Response    = 1
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec    = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
|     If StageRec<PRS_STAGE_INSP_SIG_REQ$> EQ 1 then
 | |
|         IF StageRec<PRS_STAGE_MICROSCOPE$> EQ 1 then
 | |
|             IF StageRec<PRS_STAGE_LPD$> EQ '' then
 | |
|                 FailReason = 'Frontside LPD limits must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side Scratch Count
 | |
|             IF StageRec<PRS_STAGE_SCRATCHES$> EQ '' then
 | |
|                 FailReason = 'Frontside Scratch Count must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side Scratch Length
 | |
|             IF StageRec<PRS_STAGE_SCRATCH_LEN$> EQ '' then
 | |
|                 FailReason = 'Frontside Scratch Length must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side Pits
 | |
|             IF StageRec<PRS_STAGE_PITS$> EQ '' then
 | |
|                 FailReason = 'Frontside Pits count must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side Mounds
 | |
|             IF StageRec<PRS_STAGE_MOUNDS$> EQ '' then
 | |
|                 FailReason = 'Frontside Mounds count must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side Spots
 | |
|             IF StageRec<PRS_STAGE_SPOTS$> EQ '' then
 | |
|                 FailReason = 'Frontside Spots count must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side FOV
 | |
|             IF StageRec<PRS_STAGE_FOV$> EQ '' then
 | |
|                 Response = 'Frontside FOV must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Front Side BL Defects
 | |
|             IF StageRec<PRS_STAGE_BL_DEFECTS$> EQ '' then
 | |
|                 FailReason = 'Frontside BL Defects must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end 
 | |
|         end else
 | |
|             IF Stage EQ 'PRE' OR Stage EQ 'FWI' OR Stage EQ 'LWI' then
 | |
|                 FailReason = 'Microscope Inspection Required for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             
 | |
|         end
 | |
|         IF StageRec<PRS_STAGE_BRIGHTLIGHT$> EQ 1 then
 | |
|             //Back Side Scratches
 | |
|             IF StageRec<PRS_STAGE_BSIDE_SCRATCHES$> EQ '' then
 | |
|                 FailReason = 'Backside Scratch Count must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             //Back Side Scratch Length
 | |
|             IF StageRec<PRS_STAGE_BSIDE_SCRATCH_LEN$> EQ '' then
 | |
|                 FailReason = 'Backside Scratch Length must be set for ':Stage:' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return
 | |
|             end
 | |
|         end else
 | |
|             IF Stage EQ 'PRE' OR Stage EQ 'FWI' OR Stage EQ 'LWI' then
 | |
|                 FailReason = 'Brightlight Inspection Required for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             
 | |
|         end
 | |
|     end else
 | |
|         
 | |
|         IF Stage EQ 'PRE' OR Stage EQ 'FWI' OR Stage EQ 'LWI' then
 | |
|             FailReason = 'Visual Inspection Signature Required for ' : Stage : ' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return
 | |
|         end
 | |
|     end
 | |
|     return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service CheckInstructionParms(PSNo, Stage)
 | |
|     
 | |
|     Response    = 1
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec    = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
|     //Currently the only place where instruction would be required is the LOAD stage
 | |
|     IF Stage EQ 'LOAD' then
 | |
|         IF StageRec<PRS_STAGE_INST$> EQ '' then
 | |
|             
 | |
|             FailReason = 'Instructions Missing for ':Stage:' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return
 | |
|         end 
 | |
|     end
 | |
|     Return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service CheckSurfaceParms(PSNo, Stage)
 | |
|     
 | |
|     FailReason = 1
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
|     IF StageRec<PRS_STAGE_SURFSCAN_SIG_REQ$> EQ 1 then
 | |
|         SSRecipes = StageRec<PRS_STAGE_SURFSCAN_RECIPE$>
 | |
|         IF SSRecipes NE '' then
 | |
|             For RecipePos = 1 To DCOUNT(SSRecipes, @VM)
 | |
|                 IF StageRec<PRS_STAGE_SURF_DEFECTS$, RecipePos> EQ '' then
 | |
|                     FailReason = 'SurfScan Defect Count must be set for ':Stage:' stage.'
 | |
|                     Error_Services('Add', FailReason)
 | |
|                     return 
 | |
|                 end
 | |
|                 //Surf Haze
 | |
|                 IF StageRec<PRS_STAGE_SURF_HAZE$, RecipePos> EQ '' then
 | |
|                     FailReason = 'SurfScan Haze must be set for ':Stage:' stage.'
 | |
|                     Error_Services('Add', FailReason)
 | |
|                     return 
 | |
|                 end
 | |
|                 //Surf sample qty
 | |
|                 IF StageRec<PRS_STAGE_SS_SAMP_QTY$, RecipePos> EQ '' then
 | |
|                     FailReason = 'SurfScan Cassette Sample Size must be set for ':Stage:' stage.'
 | |
|                     Error_Services('Add', FailReason)
 | |
|                     return 
 | |
|                 end
 | |
|             Next RecipePos
 | |
|             
 | |
|         end else
 | |
|             FailReason = 'No SurfScan Recipe has been set for ' : Stage : 'stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return 
 | |
|         end
 | |
|         
 | |
|     end else
 | |
|         IF Stage EQ 'POST' OR Stage EQ 'LWI' then
 | |
|             FailReason = 'SurfScan signature must be set to "Required" for ' : Stage : 'stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return
 | |
|         end
 | |
|     end
 | |
|     
 | |
|     return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service CheckQAMetParms(PSNo, Stage)
 | |
|     
 | |
|     FailReason = 1
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
|     QAMetTests = StageRec<PRS_STAGE_MET_TEST$>
 | |
|     IF QAMetTests NE '' then
 | |
|         For MetTest = 1 to DCount(QAMetTests, @VM)
 | |
|             IF StageRec<PRS_STAGE_MET_TOOL_CLASS$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Tool class must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_RECIPE$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Tool Recipe must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_RECIPE_PATTERN$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Tool Recipe  Pattern must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_MIN$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Minimum must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_MAX$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Maximum must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_SLOT$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology slot must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_WFR_QTY$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Wafer Quantity must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_INTERVAL$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Wafer Interval must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_START$,MetTest> EQ '' then
 | |
|                 FailReason = 'QA Metrology Start must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end
 | |
|             IF StageRec<PRS_STAGE_MET_PHASE_MIN$,MetTest> EQ '' AND StageRec<PRS_STAGE_MET_TEST$, MetTest> EQ 'CRES' then
 | |
|                 FailReason = 'QA Metrology Phase min must be set for ' : Stage : ' stage.'
 | |
|                 Error_Services('Add', FailReason)
 | |
|                 return 
 | |
|             end    
 | |
|         Next MetTest
 | |
|     end else
 | |
|         IF Stage EQ 'QA' OR Stage EQ 'UNLOAD' then
 | |
|             FailReason = 'No Metrology Tests exist for ' : Stage : ' stage.'
 | |
|             Error_Services('Add', FailReason)
 | |
|             return
 | |
|         end
 | |
|     end
 | |
|     return
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------------------------
 | |
| // UpdateQAMetrologyLimits
 | |
| //
 | |
| // Purpose: Update the specification limits for a particular QA metrology test.
 | |
| //----------------------------------------------------------------------------------------------------------------------
 | |
| Service UpdateQAMetrologyLimits(WOMatQAKey, QAMetStage, QAMetProfile, QAMetSlot)
 | |
|     
 | |
|     TestFound = False$
 | |
|     ErrorMsg  = ''
 | |
|     If ( (WOMatQAKey NE '') and (QAMetStage NE '') and (QAMetProfile NE '') and (QAMetSlot NE '') ) then
 | |
|         // Ensure QAMetProfile is prepended with a '1'.
 | |
|         If QAMetProfile[1, 1] NE 1 then QAMetProfile = 1:QAMetProfile
 | |
|         WOStepKey = Field(WOMatQAKey, '*', 1) : '*1'
 | |
|         PSNo = Xlate('WO_STEP', WOStepKey, 'PROD_SPEC_ID', 'X')
 | |
|         If PSNo NE '' then
 | |
|             PSRec			= Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
 | |
|             If Error_Services('NoError') then
 | |
|                 // Retrieve new QA metrology data from PSN.
 | |
|                 SpecQAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:PSRec)
 | |
|                 If SpecQAMetData NE '' then
 | |
|                     WOMatQARec     = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
 | |
|                     If Error_Services('NoError') then
 | |
|                         RecQAMetStages = WOMatQARec<WO_MAT_QA_STAGE$>
 | |
|                         RecQAMetTests  = WOMatQARec<WO_MAT_QA_PROFILE$>
 | |
|                         RecQAMetSlots  = WOMatQARec<WO_MAT_QA_SLOT$>
 | |
|                         // Locate the desired stage, profile/test, and slot in the record.
 | |
|                         RecPos = ''
 | |
|                         For each RecQAMetStage in RecQAMetStages using @VM setting vPos
 | |
|                             RecQAMetTest = RecQAMetTests<0, vPos>
 | |
|                             RecQAMetSlot = RecQAMetSlots<0, vPos>
 | |
|                             If ( (RecQAMetStage EQ QAMetStage) and (RecQAMetTest EQ QAMetProfile) and (RecQAMetSlot EQ QAMetSlot) ) then
 | |
|                                 // Found the position in the record
 | |
|                                 RecPos = vPos
 | |
|                             end
 | |
|                         Until RecPos
 | |
|                         Next RecQAMetStage
 | |
|                         
 | |
|                         If RecPos then
 | |
|                             // Locate the desired stage, profile/test, and slot in the spec QAMetData structure.
 | |
|                             SpecQAMetStages = SpecQAMetData<COL$QA_MET_STAGE>
 | |
|                             SpecQAMetTests  = SpecQAMetData<COL$QA_MET_TEST>
 | |
|                             SpecQAMetSlots  = SpecQAMetData<COL$QA_MET_SLOT>
 | |
|                             
 | |
|                             For each SpecQAMetStage in SpecQAMetStages using @VM setting vPos
 | |
|                                 SpecQAMetTest    = SpecQAMetTests<0, vPos>
 | |
|                                 SpecQAMetSlot    = SpecQAMetSlots<0, vPos>
 | |
|                                 SpecQAMetProfile = 1:SpecQAMetTest
 | |
|                                 SpecPos          = ''
 | |
|                                 If ( (SpecQAMetStage EQ QAMetStage) and (SpecQAMetProfile EQ QAMetProfile) and (SpecQAMetSlot EQ QAMetSlot) ) then
 | |
|                                     // Found the posotion in the spec QAMetData structure
 | |
|                                     SpecPos = vPos
 | |
|                                 end
 | |
|                             Until SpecPos
 | |
|                             Next SpecQAMetStage
 | |
|                             
 | |
|                             If SpecPos then
 | |
|                                 // Update the limits and recipe
 | |
|                                 WOMatQARec<WO_MAT_QA_RECIPE$, RecPos>         = SpecQAMetData<COL$QA_MET_RECIPE, SpecPos>
 | |
|                                 WOMatQARec<WO_MAT_QA_RECIPE_PATTERN$, RecPos> = SpecQAMetData<COL$QA_MET_RECIPE_PATTERN, SpecPos>
 | |
|                                 WOMatQARec<WO_MAT_QA_MIN$, RecPos>            = SpecQAMetData<COL$QA_MET_MIN, SpecPos>
 | |
|                                 WOMatQARec<WO_MAT_QA_MAX$, RecPos>            = SpecQAMetData<COL$QA_MET_MAX, SpecPos>
 | |
|                                 WOMatQARec<WO_MAT_QA_REACT_SCHED$, RecPos>    = SpecQAMetData<COL$QA_MET_REACT_SCHED, SpecPos>
 | |
|                                 WOMatQARec<WO_MAT_QA_PHASE_MIN$, RecPos>      = SpecQAMetData<COL$QA_MET_PHASE_MIN, SpecPos>
 | |
|                                 Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatQAKey, WOMatQARec, True$, True$, True$)
 | |
|                                 If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
 | |
|                             end else
 | |
|                                 ErrorMsg = 'Failed to find desired stage, test, and slot in spec QAMetData structure.'
 | |
|                             end
 | |
|                         end else
 | |
|                             ErrorMsg = 'Failed to find desired stage, test, and slot in WO_MAT_QA record.'
 | |
|                         end
 | |
|                     end else
 | |
|                         // Error reading WO_MAT_QA record
 | |
|                         ErrorMsg = Error_Services('GetMessage')
 | |
|                     end
 | |
|                 end else
 | |
|                     ErrorMsg = 'Error retrieving QAMetData from obj_Prod_Spec.'
 | |
|                 end
 | |
|             end else
 | |
|                 // Error reading PROD_SPEC record
 | |
|                 ErrorMsg = Error_Services('GetMessage')
 | |
|             end
 | |
|         end else
 | |
|             ErrorMsg = 'Failed to find PSNo in WO_STEP record ':WOStepKey:'.'
 | |
|         end
 | |
|     end else
 | |
|         ErrorMsg = 'Null WOMatQAKey, QAMetStage, QAMetProfile, or QAMetSlot passed into service.'
 | |
|     end
 | |
|     
 | |
|     If ErrorMsg EQ '' then
 | |
|         Response = True$
 | |
|     end else
 | |
|         Response = False$
 | |
|         Error_Services('Add', 'Error in ':Service:' service. ':ErrorMsg)
 | |
|     end
 | |
|     
 | |
| End Service
 | |
| 
 | |
| 
 | |
| Service UpdateAllQAMetrologyLimits(WOMatQAKey)
 | |
|     
 | |
|     ErrorMsg = ''
 | |
|     If WOMatQAKey NE '' then
 | |
|         WOMatQARec  = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
 | |
|         RecStages   = WOMatQARec<WO_MAT_QA_STAGE$>
 | |
|         RecProfiles = WOMatQARec<WO_MAT_QA_PROFILE$>
 | |
|         RecSlots    = WOMatQARec<WO_MAT_QA_SLOT$>
 | |
|         For each RecStage in RecStages using @VM setting vPos
 | |
|             RecProfile = RecProfiles<0, vPos>
 | |
|             RecSlot    = RecSlots<0, vPos>
 | |
|             PSN_Services('UpdateQAMetrologyLimits', WOMatQAKey, RecStage, RecProfile, RecSlot)
 | |
|             If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
 | |
|         Next RecStage
 | |
|     end else
 | |
|         ErrorMsg = 'Null WOMatQAKey passed into service.'
 | |
|     end
 | |
|     
 | |
|     If ErrorMsg EQ '' then
 | |
|         Response = True$
 | |
|     end else
 | |
|         Response = False$
 | |
|         Error_Services('Add', 'Error in ':Service:' service. ':ErrorMsg)
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service UpdateAllQAMetrologyRecord(WOMatQAKey, stageToUpdate)
 | |
| 	
 | |
| 	ErrorMsg = ''
 | |
| 	If WOMatQAKey NE '' then
 | |
| 		WOMatQARec  = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
 | |
| 		WOStepKey = Field(WOMatQAKey, '*', 1) : '*1'
 | |
| 		PSNo = Xlate('WO_STEP', WOStepKey, 'PROD_SPEC_ID', 'X')
 | |
| 		PSRec			= Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
 | |
|         CurrTestCount = DCOUNT(WOMatQARec<1>, @VM)
 | |
| 		SpecQAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:PSRec)
 | |
| 		
 | |
| 		for each SpecTest in SpecQAMetData<1> using @VM setting vPos then
 | |
| 			
 | |
| 			If (WOMatQARec<1,vPos> EQ 'QA' OR WOMatQARec<1,vPos> EQ '') then
 | |
|                 WOMatQARec<1,vPos>  = SpecQAMetData<1,vPos>
 | |
|                 if SpecQAMetData<2,vPos> EQ 'ADE' then SpecQAMetData<2,vPos> = '1ADE'
 | |
|                 if SpecQAMetData<2,vPos> EQ 'THICK_ONLY' then SpecQAMetData<2,vPos> = '1THICK_ONLY'
 | |
|                 if SpecQAMetData<2,vPos> EQ 'CRES' then SpecQAMetData<2,vPos> = '1CRES'
 | |
|                 WOMatQARec<2,vPos>  = SpecQAMetData<2,vPos>
 | |
|                 WOMatQARec<3,vPos>  = SpecQAMetData<3,vPos>
 | |
|                 WOMatQARec<4,vPos>  = SpecQAMetData<4,vPos>
 | |
|                 WOMatQARec<5,vPos>  = SpecQAMetData<5,vPos>
 | |
|                 WOMatQARec<6,vPos>  = SpecQAMetData<6,vPos>
 | |
|                 WOMatQARec<7,vPos>  = SpecQAMetData<7,vPos>
 | |
|                 WOMatQARec<8,vPos>  = SpecQAMetData<8,vPos>
 | |
|                 WOMatQARec<9,vPos>  = SpecQAMetData<9,vPos>
 | |
|                 WOMatQARec<16,vPos> = SpecQAMetData<14,vPos>
 | |
|                 WOMatQARec<26,vPos> = 0
 | |
| 			end
 | |
| 
 | |
| 		Next SpecTest
 | |
| 		
 | |
| 		Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatQAKey, WOMatQARec, True$, True$, True$)
 | |
| 	end else
 | |
| 		ErrorMsg = 'Null WOMatQAKey passed into service.'
 | |
| 	end
 | |
| 	
 | |
| 	If ErrorMsg EQ '' then
 | |
|         Response = True$
 | |
|     end else
 | |
|         Response = False$
 | |
|         Error_Services('Add', 'Error in ':Service:' service. ':ErrorMsg)
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service UpdateRDSMetrologyLimits(RDSNo)
 | |
|     
 | |
|     If RDSNo NE '' then
 | |
|         If RowExists('RDS', RDSNo) then
 | |
|             PSNo        = Xlate('RDS', RDSNo, 'PROD_SPEC_ID', 'X')
 | |
|             If PSNo NE '' then
 | |
|                 RDSTestKeys = Xlate('RDS', RDSNo, 'RDS_TEST_KEYS', 'X')
 | |
|                 If RDSTestKeys NE '' then
 | |
|                     For each RDSTestKey in RDSTestKeys using @VM setting vPos
 | |
|                         // Code below adapted from obj_RDS_Test('Create')
 | |
|                         RDSTestRec = Database_Services('ReadDataRow', 'RDS_TEST', RDSTestKey)
 | |
|                         If Error_Services('NoError') then
 | |
|                             LayerSet   = RDSTestRec<RDS_TEST_LS_ID$>
 | |
|                             Zone       = RDSTestRec<RDS_TEST_ZONE$>
 | |
|                             LayerSpecs = obj_Prod_Spec('GetLayerProp',PSNo:@RM:LayerSet:@RM:1)		;* Last parameter specifies no output conversion on return data
 | |
| 
 | |
|                             LayerSpecs = FIELD(LayerSpecs,@FM,2,99)		;* Returns with the layer set ID in the first field of each line
 | |
| 
 | |
|                             IF Not(Get_Status(errCode)) then
 | |
| 
 | |
|                                 WaferSize		= XLATE( 'PROD_SPEC', PSNo, 'SUB_WAFER_SIZE', 'X' )
 | |
|                                 SubOrientation	= XLATE('PROD_SPEC',PSNo,'SUB_ORIENTATION','X')
 | |
|                                 ResUnits		= LayerSpecs<PRS_LAYER_RES_UNITS$>
 | |
| 
 | |
|                                 ReactorType		= XLATE('PROD_SPEC',PSNo,PROD_SPEC_REACTOR_TYPE$,'X')
 | |
|                                 ThickFilmMet	= XLATE('PROD_SPEC',PSNo,PROD_SPEC_THICKFILM_MET$,'X')			;* Added 1/16/2009 JCH
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_RDS_NO$>				= RDSNo
 | |
|                                 RDSTestRec<RDS_TEST_LS_ID$>					= LayerSet
 | |
|                                 RDSTestRec<RDS_TEST_ZONE$>					= Zone
 | |
|                                 RDSTestRec<RDS_TEST_WAFER_SIZE$>			= WaferSize
 | |
|                                 RDSTestRec<RDS_TEST_SUB_ORIENTATION$>		= SubOrientation
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_DOPANT$>			= LayerSpecs<PRS_LAYER_DOPANT$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RECIPE$>			= LayerSpecs<PRS_LAYER_RECIPE$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RECIPE_NAME$>		= LayerSpecs<PRS_LAYER_RECIPE_NAME$>
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_THICK_MIN$>		= LayerSpecs<PRS_LAYER_THICK_MIN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_THICK_TARGET$>		= LayerSpecs<PRS_LAYER_THICK_TARGET$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_THICK_MAX$>		= LayerSpecs<PRS_LAYER_THICK_MAX$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_THICK_UNITS$>		= LayerSpecs<PRS_LAYER_THICK_UNITS$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RES_MIN$>			= LayerSpecs<PRS_LAYER_RES_MIN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RES_TARGET$>		= LayerSpecs<PRS_LAYER_RES_TARGET$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RES_MAX$>			= LayerSpecs<PRS_LAYER_RES_MAX$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RES_UNITS$>		= LayerSpecs<PRS_LAYER_RES_UNITS$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CON_MIN$>			= LayerSpecs<PRS_LAYER_CONC_MIN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CON_TARGET$>		= LayerSpecs<PRS_LAYER_CONC_TARGET$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CON_MAX$>			= LayerSpecs<PRS_LAYER_CONC_MAX$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CON_UNITS$>		= LayerSpecs<PRS_LAYER_CONC_UNITS$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_STRESS_MIN$>		= LayerSpecs<PRS_LAYER_STRESS_MIN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_STRESS_MAX$>		= LayerSpecs<PRS_LAYER_STRESS_MAX$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_TRANS$>			= LayerSpecs<PRS_LAYER_TRANS_SPEC$>
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CRES_MIN$>			= LayerSpecs<PRS_LAYER_CRES_MIN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CRES_TARGET$>		= LayerSpecs<PRS_LAYER_CRES_TARGET$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CRES_MAX$>			= LayerSpecs<PRS_LAYER_CRES_MAX$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CRES_UNITS$>		= LayerSpecs<PRS_LAYER_CRES_UNITS$>
 | |
| 
 | |
| 
 | |
|                                 FOR A = 11 TO 19
 | |
|                                     RDSTestRec<A> = LayerSpecs<PRS_LAYER_THICK_MEASUREMENT$,A-10>
 | |
|                                 NEXT A
 | |
|                                     
 | |
|                                 FOR A = 24 TO 32
 | |
|                                     RDSTestRec<A> = LayerSpecs<PRS_LAYER_RES_MEASUREMENT$,A-23>
 | |
|                                 NEXT A
 | |
| 
 | |
|                                 FOR A = 37 TO 45
 | |
|                                     RDSTestRec<A> = LayerSpecs<PRS_LAYER_CONC_MEASUREMENT$,A-36>
 | |
|                                 NEXT A
 | |
| 
 | |
|                                 FOR A = 50 to 58
 | |
|                                     RDSTestRec<A> = LayerSpecs<PRS_LAYER_STRESS_MEASUREMENT$,A-49>
 | |
|                                 NEXT A
 | |
| 
 | |
|                                 FOR A = 121 TO 129
 | |
|                                     RDSTestRec<A> = LayerSpecs<PRS_LAYER_CRES_MEASUREMENT$,A-120>
 | |
|                                 NEXT A
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_THICK_MPATTERN$>	= LayerSpecs<PRS_LAYER_THICK_MEASUREMENT$,PRS_MPATTERN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_RES_MPATTERN$>		= LayerSpecs<PRS_LAYER_RES_MEASUREMENT$,PRS_MPATTERN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CON_MPATTERN$>		= LayerSpecs<PRS_LAYER_CONC_MEASUREMENT$,PRS_MPATTERN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_STRESS_MPATTERN$>	= LayerSpecs<PRS_LAYER_STRESS_MEASUREMENT$,PRS_MPATTERN$>
 | |
|                                 RDSTestRec<RDS_TEST_SPEC_CRES_MPATTERN$>	= LayerSpecs<PRS_LAYER_CRES_MEASUREMENT$,PRS_MPATTERN$>
 | |
| 
 | |
| 
 | |
|                                 RDSTestRec<RDS_TEST_REACTOR_TYPE$> = ReactorType
 | |
| 
 | |
|                                 IF ReactorType = 'P' OR ReactorType = 'EPP' OR ThickFilmMet = 1 THEN
 | |
| 
 | |
|                                     SpecMap = XLATE('PROD_SPEC',PSNo,PROD_SPEC_TEST_POINT_MAP$,'X')		;* Added 4/8/2009 JCH new field in PROD_SPEC
 | |
|                                     
 | |
|                                     IF SpecMap NE '' THEN
 | |
|                                     
 | |
|                                         RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = SpecMap
 | |
|                                         
 | |
|                                     END ELSE
 | |
|                                     
 | |
|                                         ;* Added ThickFilmMet check - 1/16/2009 JCH
 | |
|                                     
 | |
|                                         AllTargetThicks = XLATE('PROD_SPEC',PSNo,'THICK_TARGET_ALL','X')
 | |
|                                         TargetCnt = COUNT(AllTargetThicks,@VM) + (AllTargetThicks NE '')
 | |
|                                         
 | |
|                                         BEGIN CASE
 | |
|                                             CASE TargetCnt = 2
 | |
|                                                 CombinedThick = SUM(AllTargetThicks)
 | |
|                                                 
 | |
|                                             CASE TargetCnt = 1 OR TargetCnt = 3
 | |
|                                                 CombinedThick = AllTargetThicks[-1,'B':@VM]
 | |
|                                                 
 | |
|                                         END CASE
 | |
|                                         
 | |
|                                         IF OCONV(CombinedThick,'MD2') > '65.0' THEN
 | |
|                                             RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'FTIR_T'
 | |
|                                         END ELSE
 | |
|                                             RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'FTIR'
 | |
|                                         END
 | |
|                                     END
 | |
|                                         
 | |
|                                 END ELSE
 | |
|                                     RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'ASM17'	;* 17 Point linear test pattern until PROD_SPEC is updated support other types
 | |
|                                 END
 | |
| 
 | |
|                                 Database_Services('WriteDataRow', 'RDS_TEST', RDSTestKey, RDSTestRec)
 | |
|                             end else
 | |
|                                 Error_Services('Add', 'Error in ':Service:' service. Error calling obj_Prod_Spec("GetLayerProp")')
 | |
|                             end
 | |
|                         end
 | |
|                     Next RDSTestKey
 | |
|                 end else
 | |
|                     Error_Services('Add', 'Error in ':Service:' serivce. No RDS_TEST records found for RDS record ':RDSNo:'.')
 | |
|                 end
 | |
|             end else
 | |
|                 Error_Services('Add', 'Error in ':Service:' serivce. Null PSNo returned for RDS record ':RDSNo:'.')
 | |
|             end
 | |
|         end else
 | |
|             Error_Services('Add', 'Error in ':Service:' serivce. RDS record ':RDSNo:' does not exist.')
 | |
|         end
 | |
|     end else
 | |
|         Error_Services('Add', 'Error in ':Service:' serivce. Null RDSNo passed in.')
 | |
|     end
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| Service ConvertRecordToJSON(KeyID, Record, ItemURL)
 | |
|     
 | |
|     jsonRecord    = ''
 | |
| 
 | |
|     If KeyID NE '' then
 | |
| 
 | |
|         If Record EQ '' then Record = Database_Services('ReadDataRow', 'PROD_SPEC', KeyID)
 | |
|         If Error_Services('NoError') then
 | |
|             @DICT    = Database_Services('GetTableHandle', 'DICT.PROD_SPEC')
 | |
|             @ID      = KeyID
 | |
|             @RECORD  = Record
 | |
|             If SRP_JSON(objJSON, 'New', 'Object') then
 | |
|                 
 | |
|                 If SRP_JSON(objProdSpec, 'New', 'Object') then 
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'keyId', @ID)
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'specType', OConv({SPEC_TYPE}, '[SPEC_TYPE_CONV]'))
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'status', OConv({STATUS}, '[PROD_SPEC_STATUS_CONV]'))
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'minutesPerWafer', OConv({MINUTES_PER_WAFER}, 'MD3'))
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'proveInTime', OConv({PROVEIN_MIN}, 'MD3,'))
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'layerType', {LAYER_TYPE})
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'reactorType', OConv({REACTOR_TYPE}, '[REACT_TYPE_CONV,OPSREF]'))
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'susceptorType', {SUSCEPTOR_TYPE})
 | |
|                     SRP_JSON(objProdSpec, 'SetValue', 'tubePressureType', {TUBE_PRESSURE_TYPE})
 | |
|                     ProdVerNos          = {PROD_VER_NO}
 | |
|                     CustEpiKeys         = {CEP_KEYS}
 | |
|                     StageKeys           = {STAGE}
 | |
|                     QAMetStages         = {QA_MET_STAGE}
 | |
|                     QAMetTests          = {QA_MET_TEST}
 | |
|                     QAMetProps          = {QA_MET_PROP}
 | |
|                     QAMetPropDescs      = {QA_MET_PROP_DESC}
 | |
|                     QAMetToolClasses    = {QA_MET_TOOL_CLASS}
 | |
|                     QAMetRecipes        = {QA_MET_RECIPE}
 | |
|                     QAMetRecipePatterns = {QA_MET_RECIPE_PATTERN}
 | |
|                     QAMetMins           = {QA_MET_MIN}
 | |
|                     QAMetMaxes          = {QA_MET_MAX}
 | |
|                     QAPhaseMins         = {QA_MET_PHASE_MIN}
 | |
|                     QAMetSlots          = {QA_MET_SLOT}
 | |
|                     QAMetWfrQtys        = {QA_MET_WFR_QTY}
 | |
|                     QAMetReactScheds    = {QA_MET_REACT_SCHED}
 | |
|                     QAMetIntervals      = {QA_MET_INTERVAL}
 | |
|                     QAMetStarts         = {QA_MET_START}
 | |
|                     QAMetSeqs           = {QA_MET_SEQUENCE}
 | |
|                     
 | |
|                     // Add recipe layer object array
 | |
|                     If SRP_JSON(objLayerArray, 'New', 'Array') then
 | |
|                         LayerNos           = {LAYER_NO}
 | |
|                         LayerIDs           = {LS_ID}
 | |
|                         LayerTypes         = {LS_TYPE}
 | |
|                         LayerRecipes       = {LS_RECIPE}
 | |
|                         LayerDopants       = {LS_DOPANT}
 | |
|                         LayerThickMins     = OConv({LS_THICK_MIN}, '[MET_PROP_CONV,THICK]')
 | |
|                         LayerThickTargets  = OConv({LS_THICK_TARG}, '[MET_PROP_CONV,THICK]')
 | |
|                         LayerThickMaxes    = OConv({LS_THICK_MAX}, '[MET_PROP_CONV,THICK]')
 | |
|                         LayerThickUnits    = {LS_THICK_UNITS}
 | |
|                         LayerThickAMins    = OConv({LS_THICKA_MIN}, '[MET_PROP_CONV,THICKA]')
 | |
|                         LayerThickATargets = OConv({LS_THICKA_TARG}, '[MET_PROP_CONV,THICKA]')
 | |
|                         LayerThickAMaxes   = OConv({LS_THICKA_MAX}, '[MET_PROP_CONV,THICKA]')
 | |
|                         LayerThickAUnits   = {LS_THICKA_UNITS}
 | |
|                         LayerResMins       = OConv({LS_RES_MIN}, '[MET_PROP_CONV,RES]')
 | |
|                         LayerResTargets    = OConv({LS_RES_TARG}, '[MET_PROP_CONV,RES]')
 | |
|                         LayerResMaxes      = OConv({LS_RES_MAX}, '[MET_PROP_CONV,RES]')
 | |
|                         LayerResUnits      = {LS_RES_UNITS}
 | |
|                         LayerSResMins      = OConv({LS_SRES_MIN}, '[MET_PROP_CONV,SRES]')
 | |
|                         LayerSResTargets   = OConv({LS_SRES_TARG}, '[MET_PROP_CONV,SRES]')
 | |
|                         LayerSResMaxes     = OConv({LS_SRES_MAX}, '[MET_PROP_CONV,SRES]')
 | |
|                         LayerSResUnits     = {LS_SRES_UNITS}
 | |
|                         If LayerNos NE '' then
 | |
|                             For each LayerNo in LayerNos using @VM setting vPos
 | |
|                                 If SRP_JSON(objLayer, 'New', 'Object') then
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerNo', layerNo)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerId', LayerIDs<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerType', LayerTypes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerRecipe', LayerRecipes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerDopant', LayerDopants<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickMin', LayerThickMins<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickTarget', LayerThickTargets<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickMax', LayerThickMaxes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickUnits', LayerThickUnits<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickAMin', LayerThickAMins<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickATarget', LayerThickATargets<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickAMaxes', LayerThickAMaxes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerThickAUnits', LayerThickAUnits<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerResMin', LayerResMins<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerResTarget', LayerResTargets<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerResMax', LayerResMaxes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerResUnits', LayerResUnits<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerSResMin', LayerSResMins<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerSResTarget', LayerSResTargets<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerSResMax', LayerSResMaxes<0, vPos>)
 | |
|                                     SRP_JSON(objLayer, 'SetValue', 'layerSResUnits', LayerSResUnits<0, vPos>)
 | |
|                                     SRP_JSON(objLayerArray, 'Add', objLayer)
 | |
|                                     SRP_JSON(objLayer, 'Release')
 | |
|                                 end
 | |
|                             Next LayerNo
 | |
|                         end
 | |
|                         SRP_JSON(objProdSpec, 'Set', 'recipeLayers', objLayerArray)
 | |
|                         SRP_JSON(objLayerArray, 'Release')
 | |
|                     end
 | |
|                     
 | |
|                     // Add Prod Ver object array
 | |
|                     If ProdVerNos NE '' then
 | |
|                         If SRP_JSON(objProdVerArray, 'New', 'Array') then
 | |
|                             For each ProdVerNo in ProdVerNos using @VM
 | |
|                                 ProdVerJSON = Prod_Ver_Services('ConvertRecordToJSON', ProdVerNo)
 | |
|                                 If SRP_JSON(objProdVer, 'Parse', ProdVerJSON) EQ '' then
 | |
|                                     objTemp = SRP_JSON(objProdVer, 'Get', 'prodVer')
 | |
|                                     SRP_JSON(objProdVerArray, 'Add', objTemp)
 | |
|                                     SRP_JSON(objTemp, 'Release')
 | |
|                                     SRP_JSON(objProdVer, 'Release')
 | |
|                                 end
 | |
|                             Next ProdVerNo
 | |
|                             SRP_JSON(objProdSpec, 'Set', 'prodVers', objProdVerArray)
 | |
|                             SRP_JSON(objProdVerArray, 'Release')
 | |
|                         end
 | |
|                     end
 | |
|                     
 | |
|                     // Epi Part object array
 | |
|                     EpiPartNo = {EPI_PART_NO}
 | |
|                     If EpiPartNo NE '' then
 | |
|                         If SRP_JSON(objEpiPart, 'New', 'Object') then
 | |
|                             SRP_JSON(objEpiPart, 'SetValue', 'keyID', EpiPartNo)
 | |
|                             WaferSize = Xlate('EPI_PART', EpiPartNo, 'SUB_WAFER_SIZE', 'X')
 | |
|                             SRP_JSON(objEpiPart, 'SetValue', 'waferSize', WaferSize)
 | |
|                             SRP_JSON(objProdSpec, 'Set', 'epiPart', objEpiPart)
 | |
|                             SRP_JSON(objEpiPart, 'Release')
 | |
|                         end
 | |
|                     end
 | |
|                     
 | |
|                     // Cust Epi Part object array
 | |
|                     If CustEpiKeys NE '' then
 | |
|                         If SRP_JSON(objCustEpiArray, 'New', 'Array') then
 | |
|                             For each CustEpiKey in CustEpiKeys using @VM
 | |
|                                 CustEpiJSON = Cust_Epi_Part_Services('ConvertRecordToJSON', CustEpiKey)
 | |
|                                 If SRP_JSON(objCustEpi, 'Parse', CustEpiJSON) EQ '' then
 | |
|                                     objTemp = SRP_JSON(objCustEpi, 'Get', 'custEpiPart')
 | |
|                                     SRP_JSON(objCustEpiArray, 'Add', objTemp)
 | |
|                                     SRP_JSON(objTemp, 'Release')
 | |
|                                     SRP_JSON(objCustEpi, 'Release')
 | |
|                                 end
 | |
|                             Next CustEpiKey
 | |
|                         end
 | |
|                         SRP_JSON(objProdSpec, 'Set', 'custEpiParts', objCustEpiArray)
 | |
|                         SRP_JSON(objCustEpiArray, 'Release')
 | |
|                     end
 | |
|                     
 | |
|                     // Add PRS Stage (Run Stage) object array
 | |
|                     If StageKeys NE '' then
 | |
|                         If SRP_JSON(objStageArray, 'New', 'Array') then
 | |
|                             For each StageKey in StageKeys using @VM
 | |
|                                 PRSKey       = KeyID:'*':StageKey
 | |
|                                 PRSStageJSON = PRS_Stage_Services('ConvertRecordToJSON', PRSKey)
 | |
|                                 If SRP_JSON(objPRSStage, 'Parse', PRSStageJSON) EQ '' then
 | |
|                                     objTemp = SRP_JSON(objPRSStage, 'Get', 'prsStage')
 | |
|                                     SRP_JSON(objStageArray, 'Add', objTemp)
 | |
|                                     SRP_JSON(objTemp, 'Release')
 | |
|                                     SRP_JSON(objPRSStage, 'Release')
 | |
|                                 end
 | |
|                             Next StageKey
 | |
|                         end
 | |
|                         SRP_JSON(objProdSpec, 'Set', 'prsStages', objStageArray)
 | |
|                         SRP_JSON(objStageArray, 'Release')
 | |
|                     end
 | |
|                     
 | |
|                     SRP_JSON(objJSON, 'Set', 'prodSpec', objProdSpec)
 | |
|                     SRP_JSON(objProdSpec, 'Release')
 | |
|                 end
 | |
|                 
 | |
|                 If itemURL NE '' then
 | |
|                     // The itemURL was passed in so add HAL+JSON properties.
 | |
| 
 | |
|                     // Create the _links property and then all link objects needed for this resource.
 | |
|                     If SRP_JSON(objLinks, 'New', 'Object') then
 | |
|                         // Create a self link.
 | |
|                         If SRP_JSON(objLink, 'New', 'Object') then
 | |
|                             SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String')
 | |
|                             SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String')
 | |
|                             SRP_JSON(objLinks, 'Set', 'self', objLink)
 | |
|                             SRP_JSON(objLink, 'Release')
 | |
|                         end
 | |
|                         SRP_JSON(objJSON, 'Set', '_links', objLinks)
 | |
|                         SRP_JSON(objLinks, 'Release')
 | |
|                     end
 | |
| 
 | |
|                     // Create the _class property for this resource.
 | |
|                     SRP_JSON(objJSON, 'SetValue', '_class', 'resource')
 | |
|                 end
 | |
|                 jsonRecord = SRP_JSON(objJSON, 'Stringify', 'Styled')
 | |
|                 SRP_JSON(objJSON, 'Release')
 | |
|             end else
 | |
|                 Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.')
 | |
|             end
 | |
|         end
 | |
|     end else
 | |
|         Error_Services('Add', 'KeyID argument was missing in the ' : Service : ' service.')
 | |
|     end
 | |
| 
 | |
|     Response    = jsonRecord
 | |
|     
 | |
| end service
 | |
| 
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| // Internal GoSubs
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| * * * * * * 
 | |
| CheckAdHoc:
 | |
| * * * * * *
 | |
|     StageRecKey = PSNo: '*' : Stage
 | |
|     StageRec = XLATE('PRS_STAGE', StageRecKey, '', 'X')
 | |
| 
 | |
|     IF StageRec<PRS_STAGE_CLEAN_SIG_REQ$> EQ 1 then
 | |
|         GoSub   CheckCleansParms
 | |
|         IF Error_Services('GetMessage') NE '' then
 | |
|             Return 
 | |
|         end
 | |
|     end
 | |
|     IF StageRec<PRS_STAGE_INSP_SIG_REQ$> EQ 1 then
 | |
|         GoSub   CheckVisualParms
 | |
|         IF Error_Services('GetMessage') NE '' then
 | |
|             Return 
 | |
|         end
 | |
|     end
 | |
|     IF StageRec<PRS_STAGE_SURFSCAN_SIG_REQ$> EQ 1 then
 | |
|         GoSub   CheckSurfaceParms
 | |
|         IF Error_Services('GetMessage') NE '' then
 | |
|             Return 
 | |
|         end
 | |
|     end
 | |
|     QAMetTests = StageRec<PRS_STAGE_MET_TEST$>
 | |
|     IF QAMetTests<1,1> NE '' then
 | |
|         GoSub   CheckQAMetParms
 | |
|         IF Error_Services('GetMessage') NE '' then
 | |
|             Return 
 | |
|         end
 | |
|     end
 | |
| 
 | |
| return
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |