|
@@ -138,7 +138,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private List<ModuleName> _waitPreCleanPMs = new List<ModuleName>();
|
|
|
private List<ModuleName> _waitPostCleanPMs = new List<ModuleName>();
|
|
|
- private List<ModuleName> _waitWTWCleanPMs = new List<ModuleName>();
|
|
|
+ private Dictionary<ModuleName, string> _waitWTWCleanPMs = new Dictionary<ModuleName, string>();
|
|
|
|
|
|
private List<Guid> _lstReturnWafers = new List<Guid>();
|
|
|
|
|
@@ -220,6 +220,9 @@ namespace Venus_RT.Modules
|
|
|
if (param.ContainsKey("LotId"))
|
|
|
lotId = (string)param["LotId"];
|
|
|
|
|
|
+ string preCleanRecipe = param.ContainsKey("PreCleanRecipeName") ? (string)param["PreCleanRecipeName"] : string.Empty;
|
|
|
+ string postCleanRecipe = param.ContainsKey("PostCleanRecipeName") ? (string)param["PostCleanRecipeName"] : string.Empty;
|
|
|
+
|
|
|
if (slotSequence.Length != SC.GetValue<int>("EFEM.LoadPort.SlotNumber"))
|
|
|
{
|
|
|
LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, $"slot sequence parameter not valid, length is {slotSequence.Length}, should be {SC.GetValue<int>("EFEM.LoadPort.SlotNumber")}");
|
|
@@ -262,6 +265,8 @@ namespace Venus_RT.Modules
|
|
|
cj.LotWafers = new List<WaferInfo>();
|
|
|
cj.SetState(EnumControlJobState.WaitingForStart);
|
|
|
cj.JetState = EnumJetCtrlJobState.Created;
|
|
|
+ cj.PreJobClean = preCleanRecipe;
|
|
|
+ cj.PostJobClean = postCleanRecipe;
|
|
|
|
|
|
Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
|
|
|
Dictionary<string, List<Tuple<ModuleName, int>>> seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
|
|
@@ -553,6 +558,10 @@ namespace Venus_RT.Modules
|
|
|
_movingItems.Clear();
|
|
|
_efemMovingItems.Clear();
|
|
|
|
|
|
+ _waitPreCleanPMs.Clear();
|
|
|
+ _waitPostCleanPMs.Clear();
|
|
|
+ _waitWTWCleanPMs.Clear();
|
|
|
+
|
|
|
_vacMoveFinishTrig.RST = true;
|
|
|
_atmMoveFinishTrig.RST = true;
|
|
|
|
|
@@ -999,7 +1008,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
|
|
|
// check whether match swap pattern
|
|
|
- if (inCount == 0 && !IsPMNeedWTWClean(slot.Key.Module))
|
|
|
+ if (inCount == 0 && !IsPMWaferNeedWTWClean(slot.Key.Module, out string wtwClean))
|
|
|
{
|
|
|
int swapCount = 0;
|
|
|
var in_slots = SearchWaitInSlots(slot.Key.Module);
|
|
@@ -1076,7 +1085,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
|
|
|
// check whether match swap pattern
|
|
|
- if (inCount == 0 && !IsPMNeedWTWClean(slot.Key.Module))
|
|
|
+ if (inCount == 0 && !IsPMWaferNeedWTWClean(slot.Key.Module, out string wtwClean))
|
|
|
{
|
|
|
int swapCount = 0;
|
|
|
var in_slots = SearchWaitInSlots(slot.Key.Module);
|
|
@@ -1216,7 +1225,7 @@ namespace Venus_RT.Modules
|
|
|
if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(mod.Key))
|
|
|
{
|
|
|
if ((WaferManager.Instance.CheckNoWafer(mod.Key, 0) && !_movingItems.Exists(item => item.DestinationModule == mod.Key)) ||
|
|
|
- (WaferManager.Instance.CheckHasWafer(mod.Key, 0) && _movingItems.Exists(item => item.SourceModule == mod.Key) && !_movingItems.Exists(item => item.DestinationModule == mod.Key) && !IsPMNeedWTWClean(mod.Key)))
|
|
|
+ (WaferManager.Instance.CheckHasWafer(mod.Key, 0) && _movingItems.Exists(item => item.SourceModule == mod.Key) && !_movingItems.Exists(item => item.DestinationModule == mod.Key) && !IsPMWaferNeedWTWClean(mod.Key, out string wtwClean)))
|
|
|
{
|
|
|
inSlot.Module = mod.Key;
|
|
|
inSlot.Slot = 0;
|
|
@@ -1456,12 +1465,9 @@ namespace Venus_RT.Modules
|
|
|
break;
|
|
|
case MovingStatus.Processing:
|
|
|
{
|
|
|
- var pmScheduler = _vacSchedulers[mod.Key] as SchedulerPM;
|
|
|
- string WTWCleanRecipe = string.Empty;
|
|
|
- var wtwJob = _lstControlJobs.Find(cj => cj.JetState == EnumJetCtrlJobState.Processing && IsCtrlJobNeedWTWClean(cj, mod.Key, out WTWCleanRecipe) && !IsAllJobWaferProcessedOrProcessing(cj));
|
|
|
- if (wtwJob != null && WTWCleanRecipe.Length > 0)
|
|
|
+ if (IsPMWaferNeedWTWClean(mod.Key, out string WTWCleanRecipe))
|
|
|
{
|
|
|
- _waitWTWCleanPMs.Add(mod.Key);
|
|
|
+ _waitWTWCleanPMs.Add(mod.Key, WTWCleanRecipe);
|
|
|
}
|
|
|
|
|
|
mod.Value.MovingStatus = MovingStatus.Idle;
|
|
@@ -1478,11 +1484,15 @@ namespace Venus_RT.Modules
|
|
|
var pmScheduler = _vacSchedulers[mod.Key] as SchedulerPM;
|
|
|
if (IsPMKeepEmpty(mod.Key))
|
|
|
{
|
|
|
- if (_waitPreCleanPMs.Contains(mod.Key))
|
|
|
+ if (_waitWTWCleanPMs.ContainsKey(mod.Key))
|
|
|
+ {
|
|
|
+ mod.Value.MovingStatus = MovingStatus.WaitWTWClean;
|
|
|
+ }
|
|
|
+ else if (_waitPreCleanPMs.Contains(mod.Key))
|
|
|
{
|
|
|
mod.Value.MovingStatus = MovingStatus.WaitPreJobClean;
|
|
|
}
|
|
|
- else if (_lstControlJobs.FindIndex(cj => cj.JetState == EnumJetCtrlJobState.PostJobClean) != -1 && _waitPostCleanPMs.Contains(mod.Key))
|
|
|
+ else if (_waitPostCleanPMs.Contains(mod.Key))
|
|
|
{
|
|
|
mod.Value.MovingStatus = MovingStatus.WaitPostJobClean;
|
|
|
}
|
|
@@ -1533,11 +1543,10 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
mod.Value.MovingStatus = MovingStatus.Idle;
|
|
|
var pmScheduler = _vacSchedulers[mod.Key] as SchedulerPM;
|
|
|
- if (IsPMKeepEmpty(mod.Key) && _waitWTWCleanPMs.Contains(mod.Key))
|
|
|
+ if (IsPMKeepEmpty(mod.Key) && _waitWTWCleanPMs.ContainsKey(mod.Key))
|
|
|
{
|
|
|
- string WTWCleanRecipe = string.Empty;
|
|
|
- var wtwJob = _lstControlJobs.Find(cj => cj.JetState == EnumJetCtrlJobState.Processing && IsCtrlJobNeedWTWClean(cj, mod.Key, out WTWCleanRecipe) && !IsAllJobWaferProcessedOrProcessing(cj));
|
|
|
- if (wtwJob != null && WTWCleanRecipe.Length > 0)
|
|
|
+ string WTWCleanRecipe = _waitWTWCleanPMs[mod.Key].Trim();
|
|
|
+ if (WTWCleanRecipe.Length > 0)
|
|
|
{
|
|
|
if (pmScheduler.RunJobCleanTask(WTWCleanRecipe))
|
|
|
{
|
|
@@ -1891,7 +1900,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (cj.JetState == EnumJetCtrlJobState.PreJobClean && _waitPreCleanPMs.Contains(pm))
|
|
|
{
|
|
|
- preCleanRecipe = GetFirstProcessJob(cj).Sequence.PreCleanRecipe;
|
|
|
+ preCleanRecipe = cj.PreJobClean;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
@@ -1906,7 +1915,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (cj.JetState == EnumJetCtrlJobState.PostJobClean && _waitPostCleanPMs.Contains(pm))
|
|
|
{
|
|
|
- postCleanRecipe = GetFirstProcessJob(cj).Sequence.PostCleanRecipe;
|
|
|
+ postCleanRecipe = cj.PostJobClean;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
@@ -1914,20 +1923,6 @@ namespace Venus_RT.Modules
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- private bool IsWTWJobCleanPending(ModuleName pm, out string wtwCleanRecipe)
|
|
|
- {
|
|
|
- wtwCleanRecipe = string.Empty;
|
|
|
- foreach (var cj in _lstControlJobs)
|
|
|
- {
|
|
|
- if (cj.JetState == EnumJetCtrlJobState.Processing && _waitWTWCleanPMs.Contains(pm))
|
|
|
- {
|
|
|
- wtwCleanRecipe = GetFirstProcessJob(cj).Sequence.WTWCleanRecipe;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
|
|
|
private (int processed, int unprocessed, int empty) GetLLProcessStatusCount(ModuleName ll)
|
|
|
{
|
|
@@ -2119,9 +2114,6 @@ namespace Venus_RT.Modules
|
|
|
if (!wafer.IsEmpty && wafer.NextSequenceStep == 0)
|
|
|
{
|
|
|
inSlots.Add(pjSlotWafer.Item2);
|
|
|
-
|
|
|
- if (inSlots.Count >= 2)
|
|
|
- return inSlots;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2131,7 +2123,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return inSlots;
|
|
|
+ return inSlots.OrderBy(item => item).Take(2).ToList();
|
|
|
}
|
|
|
|
|
|
private bool ProcessAlignerEFEMRobotTask(ModuleName aligner)
|
|
@@ -2522,13 +2514,13 @@ namespace Venus_RT.Modules
|
|
|
var curItem = _movingItems.Find(item => item.DestinationModule == tar.Key.Module && item.DestinationSlot == tar.Key.Slot);
|
|
|
if (ModuleHelper.IsPm(curItem.SourceModule) && _movingItems.FindIndex(item => item.DestinationModule == curItem.SourceModule) == -1)
|
|
|
{
|
|
|
- if (_waitPostCleanPMs.Contains(curItem.SourceModule))
|
|
|
+ if (_waitWTWCleanPMs.ContainsKey(curItem.SourceModule))
|
|
|
{
|
|
|
- _vacModules[curItem.SourceModule].MovingStatus = MovingStatus.WaitPostJobClean;
|
|
|
+ _vacModules[curItem.SourceModule].MovingStatus = MovingStatus.WaitWTWClean;
|
|
|
}
|
|
|
- else if (_waitWTWCleanPMs.Contains(curItem.SourceModule))
|
|
|
+ else if (_waitPostCleanPMs.Contains(curItem.SourceModule))
|
|
|
{
|
|
|
- _vacModules[curItem.SourceModule].MovingStatus = MovingStatus.WaitWTWClean;
|
|
|
+ _vacModules[curItem.SourceModule].MovingStatus = MovingStatus.WaitPostJobClean;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2934,11 +2926,7 @@ namespace Venus_RT.Modules
|
|
|
foreach (var pjSlotWafer in pj.SlotWafers)
|
|
|
{
|
|
|
WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
|
|
- if (!wafer.IsEmpty && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null
|
|
|
- && !IsWaferNeedGotoModule(wafer, ModuleName.PMA)
|
|
|
- && !IsWaferNeedGotoModule(wafer, ModuleName.PMB)
|
|
|
- && !IsWaferNeedGotoModule(wafer, ModuleName.PMC)
|
|
|
- && !IsWaferNeedGotoModule(wafer, ModuleName.PMD))
|
|
|
+ if (!wafer.IsEmpty && wafer.ProcessState == EnumWaferProcessStatus.Completed)
|
|
|
countProcessed++;
|
|
|
}
|
|
|
|
|
@@ -3119,63 +3107,41 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private bool IsCtrlJobNeedPreClean(ControlJobInfo cj)
|
|
|
{
|
|
|
- if (cj.ProcessJobNameList.Count != 1)
|
|
|
- return false;
|
|
|
-
|
|
|
- var processJob = _lstProcessJobs.Find(pj => pj.Name == cj.ProcessJobNameList.First());
|
|
|
- if (processJob == null || processJob.Sequence == null || processJob.Sequence.PreCleanRecipe == null)
|
|
|
- return false;
|
|
|
-
|
|
|
- return processJob.Sequence.PreCleanRecipe.Trim().Length > 0;
|
|
|
+ return cj.PreJobClean.Trim().Length > 0;
|
|
|
}
|
|
|
|
|
|
private bool IsCtrlJobNeedPostClean(ControlJobInfo cj)
|
|
|
{
|
|
|
- if (cj.ProcessJobNameList.Count != 1)
|
|
|
- return false;
|
|
|
-
|
|
|
- var processJob = _lstProcessJobs.Find(pj => pj.Name == cj.ProcessJobNameList.First());
|
|
|
- if (processJob == null || processJob.Sequence == null || processJob.Sequence.PostCleanRecipe == null)
|
|
|
- return false;
|
|
|
-
|
|
|
- return processJob.Sequence.PostCleanRecipe.Trim().Length > 0;
|
|
|
- }
|
|
|
-
|
|
|
- private bool IsPMNeedWTWClean(ModuleName pm)
|
|
|
- {
|
|
|
- foreach(var cj in _lstControlJobs)
|
|
|
- {
|
|
|
- if(IsCtrlJobNeedWTWClean(cj, pm, out string wtwClean))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
+ return cj.PostJobClean.Trim().Length > 0;
|
|
|
}
|
|
|
|
|
|
- private bool IsCtrlJobNeedWTWClean(ControlJobInfo cj, ModuleName pm, out string WTWCleanRecipe)
|
|
|
+ private bool IsPMWaferNeedWTWClean(ModuleName pm, out string WTWCleanRecipe)
|
|
|
{
|
|
|
WTWCleanRecipe = string.Empty;
|
|
|
- if (cj.ProcessJobNameList.Count != 1)
|
|
|
- return false;
|
|
|
-
|
|
|
- var processJob = _lstProcessJobs.Find(pj => pj.Name == cj.ProcessJobNameList.First());
|
|
|
- if (processJob == null || processJob.Sequence == null || processJob.Sequence.WTWCleanRecipe == null)
|
|
|
+ var wafer = WaferManager.Instance.GetWafer(pm, 0);
|
|
|
+ if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.WTWCleanRecipe.Trim().Length == 0)
|
|
|
return false;
|
|
|
|
|
|
- WTWCleanRecipe = processJob.Sequence.WTWCleanRecipe.Trim();
|
|
|
- return processJob.Sequence.PMs.Contains(pm) && WTWCleanRecipe.Length > 0;
|
|
|
+ WTWCleanRecipe = wafer.ProcessJob.Sequence.WTWCleanRecipe;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
private List<ModuleName> GetWaitPreCleanPMsByCtrlJob(ControlJobInfo cj)
|
|
|
{
|
|
|
- if (cj.ProcessJobNameList.Count != 1)
|
|
|
- return new List<ModuleName>();
|
|
|
-
|
|
|
- var processJob = _lstProcessJobs.Find(pj => pj.Name == cj.ProcessJobNameList.First());
|
|
|
+ var pmlist = new List<ModuleName>();
|
|
|
+ foreach(var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ if(pj.ControlJobName == cj.Name)
|
|
|
+ {
|
|
|
+ foreach(var pm in pj.Sequence.PMs)
|
|
|
+ {
|
|
|
+ if (!pmlist.Contains(pm))
|
|
|
+ pmlist.Add(pm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return processJob.Sequence.PMs;
|
|
|
+ return pmlist;
|
|
|
}
|
|
|
|
|
|
private static WaferInfo GetCloneWafer(ModuleName mod, int slot)
|