|
@@ -37,11 +37,12 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
class VenusPMTask : ModuleTask
|
|
|
{
|
|
|
- enum RecipeJobType
|
|
|
+ public enum RecipeJobType
|
|
|
{
|
|
|
PreClean,
|
|
|
Process,
|
|
|
PostClean,
|
|
|
+ WtwClean,
|
|
|
}
|
|
|
|
|
|
public override int TimeToReady
|
|
@@ -54,6 +55,7 @@ namespace Venus_RT.Modules
|
|
|
case ModuleStatus.IdleClean:
|
|
|
case ModuleStatus.PreJobClean:
|
|
|
case ModuleStatus.PostJobClean:
|
|
|
+ case ModuleStatus.WTWClean:
|
|
|
case ModuleStatus.Processing:
|
|
|
{
|
|
|
return Scheduler.IsAvailable ? 0 : (Scheduler.TimeToReady + 500) / 1000;
|
|
@@ -110,7 +112,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- LOG.Write(eEvent.WARN_ROUTER, Module, $"Run Prejob clean recipe{_runingWaferTask.Value.First().Value} failed");
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"Run Prejob clean recipe {_runingWaferTask.Value.First().Value} failed");
|
|
|
TryDequeueRuningTask(Status);
|
|
|
Status = ModuleStatus.Idle;
|
|
|
}
|
|
@@ -143,7 +145,24 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- LOG.Write(eEvent.WARN_ROUTER, Module, $"Run Postjob clean recipe{_runingWaferTask.Value.First().Value} failed");
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"Run Postjob clean recipe {_runingWaferTask.Value.First().Value} failed");
|
|
|
+ TryDequeueRuningTask(Status);
|
|
|
+ Status = ModuleStatus.Idle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case RecipeJobType.WtwClean:
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckNoWafer(Module, 0))
|
|
|
+ {
|
|
|
+ if (_pmScheduler.RunJobCleanTask(_runingWaferTask.Value.First().Value))
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.StartWTWClean;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"Run WTW clean recipe {_runingWaferTask.Value.First().Value} failed");
|
|
|
TryDequeueRuningTask(Status);
|
|
|
Status = ModuleStatus.Idle;
|
|
|
}
|
|
@@ -180,12 +199,8 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
break;
|
|
|
case ModuleStatus.PreJobClean:
|
|
|
- {
|
|
|
- TryDequeueRuningTask(Status);
|
|
|
- Status = ModuleStatus.Idle;
|
|
|
- }
|
|
|
- break;
|
|
|
case ModuleStatus.PostJobClean:
|
|
|
+ case ModuleStatus.WTWClean:
|
|
|
{
|
|
|
TryDequeueRuningTask(Status);
|
|
|
Status = ModuleStatus.Idle;
|
|
@@ -222,6 +237,9 @@ namespace Venus_RT.Modules
|
|
|
case ModuleStatus.StartPostJobClean:
|
|
|
Status = ModuleStatus.PostJobClean;
|
|
|
break;
|
|
|
+ case ModuleStatus.StartWTWClean:
|
|
|
+ Status = ModuleStatus.WTWClean;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -257,13 +275,18 @@ namespace Venus_RT.Modules
|
|
|
bMatch = true;
|
|
|
}
|
|
|
break;
|
|
|
- case ModuleStatus.WaitPreJobClean:
|
|
|
- _runingWaferTask.Value.Dequeue();
|
|
|
+ case ModuleStatus.WTWClean:
|
|
|
+ if(_runingWaferTask.Value.First().Key == RecipeJobType.WtwClean)
|
|
|
+ {
|
|
|
+ _runingWaferTask.Value.Dequeue();
|
|
|
+ bMatch = true;
|
|
|
+ }
|
|
|
break;
|
|
|
+ case ModuleStatus.WaitPreJobClean:
|
|
|
case ModuleStatus.WaitProcess:
|
|
|
- _runingWaferTask.Value.Dequeue();
|
|
|
- break;
|
|
|
case ModuleStatus.WaitPostJobClean:
|
|
|
+ case ModuleStatus.WaitWTWClean:
|
|
|
+ case ModuleStatus.Idle:
|
|
|
_runingWaferTask.Value.Dequeue();
|
|
|
break;
|
|
|
}
|
|
@@ -272,7 +295,7 @@ namespace Venus_RT.Modules
|
|
|
if(!bMatch)
|
|
|
{
|
|
|
string runingTask = _runingWaferTask.Value.Count > 0 ? _runingWaferTask.Value.First().ToString() : "Empty";
|
|
|
- LOG.Write(eEvent.WARN_ROUTER, Module, $"PM Status: {status}, runing task : {runingTask}");
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"TryDequeueRuningTask() failed, PM Status: {status}, runing task : {runingTask}");
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -288,36 +311,63 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
public void SubscribeWaferTask(WaferTask waferTask)
|
|
|
{
|
|
|
- var venusWaferTask = waferTask as VenusWaferTask;
|
|
|
var waferRecipes = new Queue<KeyValuePair<RecipeJobType, string>>();
|
|
|
- if (!string.IsNullOrWhiteSpace(venusWaferTask.preCleanRecipe))
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(waferTask.processRecipe))
|
|
|
{
|
|
|
- waferRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(RecipeJobType.PreClean, venusWaferTask.preCleanRecipe));
|
|
|
+ waferRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(RecipeJobType.Process, waferTask.processRecipe));
|
|
|
}
|
|
|
|
|
|
- if (!string.IsNullOrWhiteSpace(venusWaferTask.processRecipe))
|
|
|
+ if (!string.IsNullOrWhiteSpace(waferTask.wtwCleanRecipe))
|
|
|
{
|
|
|
- waferRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(RecipeJobType.Process, venusWaferTask.processRecipe));
|
|
|
+ waferRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(RecipeJobType.WtwClean, waferTask.wtwCleanRecipe));
|
|
|
}
|
|
|
|
|
|
- if (!string.IsNullOrWhiteSpace(venusWaferTask.postCleanRecipe))
|
|
|
+ if(_runingWaferTask.Key == waferTask.waferId || _pendingWaferTasks.ToList().Exists(kv => kv.Key == waferTask.waferId))
|
|
|
{
|
|
|
- waferRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(RecipeJobType.PostClean, venusWaferTask.postCleanRecipe));
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"wafer {waferTask.sourceMod}.{waferTask.sourceSlot + 1} already subscribe job task.");
|
|
|
}
|
|
|
+ else if (_runingWaferTask.Key == Guid.Empty || _runingWaferTask.Value.Count == 0)
|
|
|
+ {
|
|
|
+ _runingWaferTask = new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(waferTask.waferId, waferRecipes);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _pendingWaferTasks.Enqueue(new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(waferTask.waferId, waferRecipes));
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if(_runingWaferTask.Key == venusWaferTask.waferId || _pendingWaferTasks.ToList().Exists(kv => kv.Key == venusWaferTask.waferId))
|
|
|
+ public void SubscribeLotCleanTask(ControlJobInfo cj, RecipeJobType cleanType)
|
|
|
+ {
|
|
|
+ var lotCleanRecipes = new Queue<KeyValuePair<RecipeJobType, string>>();
|
|
|
+
|
|
|
+ if(cleanType == RecipeJobType.PreClean && !string.IsNullOrWhiteSpace(cj.PreJobClean))
|
|
|
{
|
|
|
- LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, $"wafer {venusWaferTask.sourceMod}.{venusWaferTask.sourceSlot + 1} already subscribe job task.");
|
|
|
+ lotCleanRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(cleanType, cj.PreJobClean));
|
|
|
+ }
|
|
|
+ else if(cleanType == RecipeJobType.PostClean && !string.IsNullOrWhiteSpace (cj.PostJobClean))
|
|
|
+ {
|
|
|
+ lotCleanRecipes.Enqueue(new KeyValuePair<RecipeJobType, string>(cleanType, cj.PostJobClean));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_runingWaferTask.Key == cj.InnerId && _runingWaferTask.Value.ToList().Exists(pv => pv.Key == cleanType)) || _pendingWaferTasks.ToList().Exists(task => task.Key == cj.InnerId && task.Value.ToList().Exists(pv => pv.Key == cleanType)))
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"Control job {cj.Name} already subscribe {cleanType} task.");
|
|
|
}
|
|
|
else if (_runingWaferTask.Key == Guid.Empty || _runingWaferTask.Value.Count == 0)
|
|
|
{
|
|
|
- _runingWaferTask = new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(venusWaferTask.waferId, waferRecipes);
|
|
|
+ _runingWaferTask = new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(cj.InnerId, lotCleanRecipes);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _pendingWaferTasks.Enqueue(new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(venusWaferTask.waferId, waferRecipes));
|
|
|
+ _pendingWaferTasks.Enqueue(new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(cj.InnerId, lotCleanRecipes));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
public bool ReadyMoveIn(WaferTask wafer)
|
|
|
{
|
|
|
return _runingWaferTask.Key == wafer.waferId && _runingWaferTask.Value.Count > 0 && _runingWaferTask.Value.First().Key == RecipeJobType.Process;
|
|
@@ -331,8 +381,6 @@ namespace Venus_RT.Modules
|
|
|
_pendingWaferTasks.Clear();
|
|
|
_runingWaferTask = new KeyValuePair<Guid, Queue<KeyValuePair<RecipeJobType, string>>>(Guid.Empty, new Queue<KeyValuePair<RecipeJobType, string>>());
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
class PreAlignTask : ModuleTask
|
|
@@ -380,31 +428,6 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public class VenusWaferTask : WaferTask
|
|
|
- {
|
|
|
- public string preCleanRecipe { get; }
|
|
|
- public string postCleanRecipe { get; }
|
|
|
- public VenusWaferTask(ModuleName source,
|
|
|
- int srcSlot,
|
|
|
- ModuleName dest,
|
|
|
- int dstSlot,
|
|
|
- float temp,
|
|
|
- Guid waferID,
|
|
|
- string recipeName,
|
|
|
- string wtwClean,
|
|
|
- SequenceLLInOutPath inOutPath,
|
|
|
- int LLDelay,
|
|
|
- bool needAlign
|
|
|
- //string preClean,
|
|
|
- //string postClean
|
|
|
- )
|
|
|
- : base(source, srcSlot, dest, dstSlot, temp, waferID, recipeName, wtwClean, inOutPath, LLDelay, needAlign)
|
|
|
- {
|
|
|
- //preCleanRecipe = preClean;
|
|
|
- //postCleanRecipe = postClean;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
class VenusTMRobotTask : ModuleTask
|
|
|
{
|
|
|
public VenusTMRobotTask(ModuleName mod) : base(mod) { }
|
|
@@ -422,7 +445,7 @@ namespace Venus_RT.Modules
|
|
|
private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
|
|
|
private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
|
|
|
|
|
|
- private List<VenusWaferTask> _lstWaferTasks = new List<VenusWaferTask>();
|
|
|
+ private List<WaferTask> _lstWaferTasks = new List<WaferTask>();
|
|
|
private Dictionary<ModuleName, ModuleTask> _dictModuleTask = new Dictionary<ModuleName, ModuleTask>();
|
|
|
private Queue<WaferInfo> _qeReturnWafers = new Queue<WaferInfo>();
|
|
|
|
|
@@ -1623,6 +1646,17 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
if (IsAllProcessJobComplete(runingjob))
|
|
|
{
|
|
|
+ // subscribe clean task
|
|
|
+ var PMs = GetWaitPreCleanPMsByCtrlJob(runingjob);
|
|
|
+ foreach (var pm in PMs)
|
|
|
+ {
|
|
|
+ var pmTask = _dictModuleTask[pm] as VenusPMTask;
|
|
|
+ if (pmTask != null && pmTask.Scheduler.IsOnline)
|
|
|
+ {
|
|
|
+ pmTask.SubscribeLotCleanTask(runingjob, VenusPMTask.RecipeJobType.PostClean);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
runingjob.SetState(EnumControlJobState.Completed);
|
|
|
runingjob.EndTime = DateTime.Now;
|
|
|
|
|
@@ -1642,6 +1676,17 @@ namespace Venus_RT.Modules
|
|
|
if (runingJobs.Count == 0 || (runingJobs.Count == 1 && IsAllJobWaferProcessedOrProcessing(runingJobs.First())))
|
|
|
{
|
|
|
ActiveControlJob(pendingJobs.First());
|
|
|
+
|
|
|
+ // subscribe clean task
|
|
|
+ var PMs = GetWaitPreCleanPMsByCtrlJob(pendingJobs.First());
|
|
|
+ foreach (var pm in PMs)
|
|
|
+ {
|
|
|
+ var pmTask = _dictModuleTask[pm] as VenusPMTask;
|
|
|
+ if (pmTask != null && pmTask.Scheduler.IsOnline)
|
|
|
+ {
|
|
|
+ pmTask.SubscribeLotCleanTask(pendingJobs.First(), VenusPMTask.RecipeJobType.PreClean);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1882,20 +1927,17 @@ namespace Venus_RT.Modules
|
|
|
temperature = temp;
|
|
|
}
|
|
|
|
|
|
- var waferTask = new VenusWaferTask((ModuleName)wafer.OriginStation,
|
|
|
+ var waferTask = new WaferTask((ModuleName)wafer.OriginStation,
|
|
|
wafer.OriginSlot,
|
|
|
pm,
|
|
|
0,
|
|
|
temperature,
|
|
|
wafer.InnerId,
|
|
|
recipeName,
|
|
|
- String.Empty,
|
|
|
+ wafer.ProcessJob.Sequence.WTWCleanRecipe,
|
|
|
wafer.ProcessJob.Sequence.LLInOutPath,
|
|
|
wafer.ProcessJob.Sequence.LLDelayTime,
|
|
|
- IsSequenceNeedAlign(wafer.ProcessJob.Sequence)
|
|
|
- //wafer.ProcessJob.Sequence.PreWaferCleanRecipe, // pre clean
|
|
|
- //wafer.ProcessJob.Sequence.PostWaferCleanRecipe
|
|
|
- ); // post clean
|
|
|
+ IsSequenceNeedAlign(wafer.ProcessJob.Sequence)); // post clean
|
|
|
|
|
|
waferTask.OnWaferArrived += WaferArrived;
|
|
|
waferTask.OnWaferLeaved += WaferLeaved;
|
|
@@ -1997,6 +2039,25 @@ namespace Venus_RT.Modules
|
|
|
reason = "";
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ private List<ModuleName> GetWaitPreCleanPMsByCtrlJob(ControlJobInfo cj)
|
|
|
+ {
|
|
|
+ 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 pmlist;
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
}
|
|
|
}
|