|
@@ -542,6 +542,9 @@ namespace Venus_RT.Modules
|
|
|
private void epilogue()
|
|
|
{
|
|
|
CheckWaferArrived();
|
|
|
+
|
|
|
+ UpdateProcessJobStatus();
|
|
|
+ UpdateControlJobStatus();
|
|
|
StartNewJob();
|
|
|
}
|
|
|
|
|
@@ -1587,6 +1590,217 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private static bool IsWaferNeedGotoModule(WaferInfo wafer, ModuleName module)
|
|
|
+ {
|
|
|
+ if (wafer.IsEmpty)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
|
|
|
+ {
|
|
|
+ if (wafer.ProcessJob.Sequence.Steps[i].StepModules
|
|
|
+ .Contains(module))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ private bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < pj.SlotWafers.Count; ++i)
|
|
|
+ {
|
|
|
+ WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
|
|
|
+ if (wafer.IsEmpty)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (checkAllProcessed && IsWaferNeedGotoModule(wafer, ModuleName.PMA) || IsWaferNeedGotoModule(wafer, ModuleName.PMB))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void UpdateProcessJobStatus()
|
|
|
+ {
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ if (pj.State == EnumProcessJobState.Processing)
|
|
|
+ {
|
|
|
+ if (CheckAllWaferReturned(pj, true))
|
|
|
+ {
|
|
|
+ pj.SetState(EnumProcessJobState.ProcessingComplete);
|
|
|
+ JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (pj.State == EnumProcessJobState.Stopping)
|
|
|
+ {
|
|
|
+ if (CheckAllWaferReturned(pj, false))
|
|
|
+ {
|
|
|
+ pj.SetState(EnumProcessJobState.ProcessingComplete);
|
|
|
+ JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CompleteJobClean(ControlJobInfo cj)
|
|
|
+ {
|
|
|
+ List<SchedulerPM> pms = GetPmNeeded(cj);
|
|
|
+ foreach (var pm in pms)
|
|
|
+ {
|
|
|
+ pm.CompleteJobClean();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void UpdateControlJobStatus()
|
|
|
+ {
|
|
|
+ if (_lstControlJobs.Count == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ //if (_curAction.state != ActionState.Done)
|
|
|
+ // return;
|
|
|
+
|
|
|
+ bool allControlJobComplete = true;
|
|
|
+ List<ControlJobInfo> cjRemoveList = new List<ControlJobInfo>();
|
|
|
+ foreach (var cj in _lstControlJobs)
|
|
|
+ {
|
|
|
+ if (!Singleton<TransferModule>.Instance.GetScheduler(ModuleHelper.Converter(cj.Module)).IsAvailable)
|
|
|
+ {
|
|
|
+ allControlJobComplete = false;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (cj.State == EnumControlJobState.Executing)
|
|
|
+ {
|
|
|
+ bool allPjCompleted = true;
|
|
|
+ foreach (var pjName in cj.ProcessJobNameList)
|
|
|
+ {
|
|
|
+ var pj = _lstProcessJobs.Find(x => x.Name == pjName);
|
|
|
+ if (pj == null)
|
|
|
+ {
|
|
|
+ LOG.Write( eEvent.ERR_ROUTER, ModuleName.System, $"Not find pj named {pjName} in {cj.Name}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
|
|
|
+ {
|
|
|
+ allPjCompleted = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (allPjCompleted)
|
|
|
+ {
|
|
|
+ pj.SlotWafers.ForEach(p => {
|
|
|
+ if (ModuleHelper.IsLoadPort(p.Item1))
|
|
|
+ {
|
|
|
+ allPjCompleted = allPjCompleted && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(p.Item1.ToString()), p.Item2);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (allPjCompleted)
|
|
|
+ {
|
|
|
+ cj.SetState(EnumControlJobState.Completed);
|
|
|
+ cj.EndTime = DateTime.Now;
|
|
|
+
|
|
|
+ if (!(_isCycleMode && _cycledCount + 1 < _cycleSetPoint))
|
|
|
+ {
|
|
|
+ CompleteJobClean(cj);
|
|
|
+ }
|
|
|
+
|
|
|
+ _faCallback.JobFinished(cj, GetFirstProcessJob(cj));
|
|
|
+ _dbCallback.LotFinished(cj);
|
|
|
+
|
|
|
+ if (!(_isCycleMode && _cycledCount < _cycleSetPoint))
|
|
|
+ (Singleton<TransferModule>.Instance.GetScheduler(ModuleHelper.Converter(cj.Module)) as SchedulerLoadPort).NoteJobComplete();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ LoadportCassetteState state = (LoadportCassetteState)DATA.Poll($"{cj.Module}.CassetteState");
|
|
|
+ if (cj.State == EnumControlJobState.Completed && state != LoadportCassetteState.Normal)
|
|
|
+ {
|
|
|
+ cjRemoveList.Add(cj);
|
|
|
+ }
|
|
|
+
|
|
|
+ allControlJobComplete = allControlJobComplete && cj.State == EnumControlJobState.Completed;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_isCycleMode && _cycledCount < (_isCycleMode ? _cycleSetPoint : 0))
|
|
|
+ {
|
|
|
+ int countPerCycle = 0;
|
|
|
+ int countProcessed = 0;
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ foreach (var pjSlotWafer in pj.SlotWafers)
|
|
|
+ {
|
|
|
+ countPerCycle++;
|
|
|
+ WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
|
|
+ if (!wafer.IsEmpty && !IsWaferNeedGotoModule(wafer, ModuleName.PMA) && !IsWaferNeedGotoModule(wafer, ModuleName.PMB))
|
|
|
+ countProcessed++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _cycledWafer = _cycledCount * countPerCycle + countProcessed;
|
|
|
+
|
|
|
+ if (allControlJobComplete)
|
|
|
+ {
|
|
|
+ _cycledCount++;
|
|
|
+
|
|
|
+ if (_cycledCount < _cycleSetPoint)
|
|
|
+ {
|
|
|
+ foreach (var cj in _lstControlJobs)
|
|
|
+ {
|
|
|
+ cj.SetState(EnumControlJobState.Executing);
|
|
|
+
|
|
|
+ cj.LotInnerId = Guid.NewGuid();
|
|
|
+
|
|
|
+ _dbCallback.LotCreated(cj);
|
|
|
+ }
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ pj.SetState(EnumProcessJobState.Queued);
|
|
|
+ pj.InnerId = Guid.NewGuid();
|
|
|
+ foreach (var pjSlotWafer in pj.SlotWafers)
|
|
|
+ {
|
|
|
+ WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
|
|
+
|
|
|
+ wafer.ProcessJob = null;
|
|
|
+ wafer.NextSequenceStep = 0;
|
|
|
+ wafer.ProcessState = EnumWaferProcessStatus.Idle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ _cycleState = RState.End;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var cj in cjRemoveList)
|
|
|
+ {
|
|
|
+ List<ProcessJobInfo> pjRemoveList = new List<ProcessJobInfo>();
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ if (pj.ControlJobName == cj.Name)
|
|
|
+ pjRemoveList.Add(pj);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var pj in pjRemoveList)
|
|
|
+ {
|
|
|
+ _lstProcessJobs.Remove(pj);
|
|
|
+ }
|
|
|
+
|
|
|
+ _lstControlJobs.Remove(cj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
#endregion
|
|
|
}
|
|
|
}
|