|
@@ -47,6 +47,7 @@ namespace Venus_RT.Modules
|
|
|
public string wtwCleanRecipe { get; }
|
|
|
public float temperature { get; }
|
|
|
public Guid waferId { get; }
|
|
|
+ public Guid lotId { get; }
|
|
|
public int elapseTime { get { return (int)(DateTime.Now - _scheduledTime).TotalSeconds; } }
|
|
|
public int llDelayTime { get; }
|
|
|
public RState pressureStatus { get; private set; }
|
|
@@ -89,7 +90,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private DateTime _scheduledTime;
|
|
|
|
|
|
- public WaferTask(ModuleName source, int srcSlot, ModuleName dest, int dstSlot, float temp, Guid waferID, string recipeName, string wtwClean, SequenceLLInOutPath inOutPath, int LLDelay, bool needAlign)
|
|
|
+ public WaferTask(ModuleName source, int srcSlot, ModuleName dest, int dstSlot, float temp, Guid waferID, Guid lotID, string recipeName, string wtwClean, SequenceLLInOutPath inOutPath, int LLDelay, bool needAlign)
|
|
|
{
|
|
|
sourceMod = currentMod = nextMod = routedMod = source;
|
|
|
sourceSlot = currentSlot = nextSlot = routedSlot = srcSlot;
|
|
@@ -99,6 +100,7 @@ namespace Venus_RT.Modules
|
|
|
hand = Hand.None;
|
|
|
temperature = temp;
|
|
|
waferId = waferID;
|
|
|
+ lotId = lotID;
|
|
|
processRecipe = recipeName;
|
|
|
wtwCleanRecipe = wtwClean;
|
|
|
llInOutPath = inOutPath;
|
|
@@ -349,6 +351,8 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public bool HasPendingCleanTask => _pendingCleanTask.Count > 0;
|
|
|
+
|
|
|
private WaferTask _wafer;
|
|
|
private SchedulerPM _pmScheduler => Scheduler as SchedulerPM;
|
|
|
|
|
@@ -556,7 +560,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
public override void WaferLeaved(WaferTask wafer, int slot)
|
|
|
{
|
|
|
- if(!string.IsNullOrWhiteSpace(_wafer.wtwCleanRecipe.Trim()))
|
|
|
+ if(!string.IsNullOrWhiteSpace(_wafer.wtwCleanRecipe.Trim()) && (_pendingCleanTask.Count == 0 || _pendingCleanTask.First() != CleanType.PostJobClean))
|
|
|
{
|
|
|
Status = ModuleStatus.WaitWTWClean;
|
|
|
_wtwCleanRecipe = _wafer.wtwCleanRecipe;
|
|
@@ -581,6 +585,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
_preJobCleanRecipe = preJobClean;
|
|
|
_pendingCleanTask.Enqueue(CleanType.PreJobClean);
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, Module, $"Invoke preClean {preJobClean}");
|
|
|
}
|
|
|
|
|
|
public bool IsPreJobCleanDone()
|
|
@@ -592,6 +597,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
_postJobCleanRecipe = postJobClean;
|
|
|
_pendingCleanTask.Enqueue(CleanType.PostJobClean);
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, Module, $"Invoke postClean {postJobClean}");
|
|
|
}
|
|
|
|
|
|
public bool IsPostJobCleanDone()
|
|
@@ -839,6 +845,28 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
return RState.Running;
|
|
|
}
|
|
|
+
|
|
|
+ public int Distance
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ switch(Status)
|
|
|
+ {
|
|
|
+ case ModuleStatus.Idle:
|
|
|
+ return Scheduler.IsVac ? 1 : Scheduler.IsAtm ? 7 : 5;
|
|
|
+ case ModuleStatus.StartPump:
|
|
|
+ case ModuleStatus.Pumping:
|
|
|
+ return 3;
|
|
|
+ case ModuleStatus.StartCooling:
|
|
|
+ case ModuleStatus.Cooling:
|
|
|
+ case ModuleStatus.StartVent:
|
|
|
+ case ModuleStatus.Venting:
|
|
|
+ return 9;
|
|
|
+ default:
|
|
|
+ return 5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
enum LLSlotInOutOpt
|
|
@@ -888,7 +916,9 @@ namespace Venus_RT.Modules
|
|
|
private Dictionary<ModuleName, int> _lpCycleCount = new Dictionary<ModuleName, int> { { ModuleName.LP1, 0 }, { ModuleName.LP2, 0 }, { ModuleName.LP3, 0 } };
|
|
|
private Dictionary<ModuleName, int> _lpCycleSP = new Dictionary<ModuleName, int> { { ModuleName.LP1, 1 }, { ModuleName.LP2, 1 }, { ModuleName.LP3, 1 } };
|
|
|
private Dictionary<ModuleName, float> _lpThroughput = new Dictionary<ModuleName, float>{ {ModuleName.LP1, 0}, { ModuleName.LP2, 0}, { ModuleName.LP3, 0} };
|
|
|
- private Dictionary<ModuleName, Stopwatch> _lpCycleWatch = new Dictionary<ModuleName, Stopwatch> { { ModuleName.LP1, new Stopwatch() }, { ModuleName.LP2, new Stopwatch()}, { ModuleName.LP3, new Stopwatch()} };
|
|
|
+ private Dictionary<ModuleName, Stopwatch> _lpCycleWatch = new Dictionary<ModuleName, Stopwatch> { { ModuleName.LP1, new Stopwatch() }, { ModuleName.LP2, new Stopwatch()}, { ModuleName.LP3, new Stopwatch()} };
|
|
|
+ private Dictionary<ModuleName, List<Guid>> _preLotCleanMarks = new Dictionary<ModuleName, List<Guid>>();
|
|
|
+ private Dictionary<ModuleName, List<Guid>> _postLotCleanMarks = new Dictionary<ModuleName, List<Guid>>();
|
|
|
|
|
|
private Stopwatch _cycleWatch = new Stopwatch();
|
|
|
|
|
@@ -1482,6 +1512,16 @@ namespace Venus_RT.Modules
|
|
|
_loadportControlJobDic[key] = null;
|
|
|
}
|
|
|
|
|
|
+ foreach(var preLot in _preLotCleanMarks)
|
|
|
+ {
|
|
|
+ preLot.Value.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach(var postLot in _postLotCleanMarks)
|
|
|
+ {
|
|
|
+ postLot.Value.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
_lstWaferTasks.Clear();
|
|
|
_qeWaitInWafers.Clear();
|
|
|
_tmSchdActions.Clear();
|
|
@@ -1625,6 +1665,8 @@ namespace Venus_RT.Modules
|
|
|
if(ModuleHelper.IsPm(module))
|
|
|
{
|
|
|
_dictModuleTask[module] = new PMTask(module);
|
|
|
+ _preLotCleanMarks[module] = new List<Guid>();
|
|
|
+ _postLotCleanMarks[module] = new List<Guid>();
|
|
|
}
|
|
|
else if (ModuleHelper.IsLoadLock(module))
|
|
|
{
|
|
@@ -1665,6 +1707,7 @@ namespace Venus_RT.Modules
|
|
|
UpdateControlJobStatus();
|
|
|
UpdateLLInOutPathProperty();
|
|
|
PrepareLLPressure();
|
|
|
+ RunLotCleanTasks();
|
|
|
|
|
|
CreateNewWaferTask();
|
|
|
_lstWaferTasks.RemoveAll(item => ModuleHelper.IsLoadPort(item.destMod) && ModuleHelper.IsLoadPort(item.currentMod) && item.pressureStatus == RState.End);
|
|
@@ -1855,9 +1898,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (_qePollingJobs.First() == cj)
|
|
|
{
|
|
|
- if ( !cj.LotWafers.Exists(wafer => !wafer.IsEmpty && wafer.NextSequenceStep == 0) &&
|
|
|
- ( (!IsCtrlJobNeedPostClean(cj) && !_lstWaferTasks.Exists(wt => !string.IsNullOrEmpty(wt.wtwCleanRecipe) && (_qePollingJobs.Count <= 1 || !IsCtrlJobNeedPreClean(_qePollingJobs.ElementAt(1)))) ) ||
|
|
|
- (IsAllProcessJobComplete(cj) && IsPostJobCleanDone(cj))))
|
|
|
+ if ( !cj.LotWafers.Exists(wafer => !wafer.IsEmpty && wafer.NextSequenceStep == 0) && (IsAllJobWaferProcessedOrProcessing(cj) || IsAllProcessJobComplete(cj)))
|
|
|
{
|
|
|
_qePollingJobs.Dequeue();
|
|
|
_qePollingJobs.Enqueue(cj);
|
|
@@ -1865,69 +1906,16 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
switch (cj.JetState)
|
|
|
{
|
|
|
case EnumJetCtrlJobState.Quequed:
|
|
|
{
|
|
|
- if(IsCtrlJobNeedPreClean(cj))
|
|
|
- {
|
|
|
- cj.JetState = EnumJetCtrlJobState.PreJobClean;
|
|
|
-
|
|
|
- var PMs = GetWaitPreCleanPMsByCtrlJob(cj);
|
|
|
- foreach (var pm in PMs)
|
|
|
- {
|
|
|
- var pmTask = _dictModuleTask[pm] as PMTask;
|
|
|
- if (pmTask != null && pmTask.Scheduler.IsOnline)
|
|
|
- {
|
|
|
- pmTask.InvokePreJobClean(cj.PreJobClean);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ActiveControlJob(cj);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case EnumJetCtrlJobState.PreJobClean:
|
|
|
- {
|
|
|
- if (IsPreJobCleanDone(cj))
|
|
|
- {
|
|
|
- ActiveControlJob(cj);
|
|
|
- }
|
|
|
+ ActiveControlJob(cj);
|
|
|
}
|
|
|
break;
|
|
|
case EnumJetCtrlJobState.Processing:
|
|
|
{
|
|
|
- if (IsCtrlJobNeedPostClean(cj))
|
|
|
- {
|
|
|
- if (IsAllJobWaferProcessedOrProcessing(cj))
|
|
|
- {
|
|
|
- cj.JetState = EnumJetCtrlJobState.PostJobClean;
|
|
|
- var PMs = GetWaitPreCleanPMsByCtrlJob(cj);
|
|
|
- foreach (var pm in PMs)
|
|
|
- {
|
|
|
- var pmTask = _dictModuleTask[pm] as PMTask;
|
|
|
- if (pmTask != null && pmTask.Scheduler.IsOnline)
|
|
|
- {
|
|
|
- pmTask.InvokePostJobClean(cj.PostJobClean);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (IsAllProcessJobComplete(cj))
|
|
|
- {
|
|
|
- cj.JetState = EnumJetCtrlJobState.Completed;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case EnumJetCtrlJobState.PostJobClean:
|
|
|
- {
|
|
|
- if (IsPostJobCleanDone(cj))
|
|
|
+ if (IsAllProcessJobComplete(cj))
|
|
|
{
|
|
|
cj.JetState = EnumJetCtrlJobState.Completed;
|
|
|
}
|
|
@@ -1988,6 +1976,18 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if(pj.ControlJobName == cj.Name)
|
|
|
{
|
|
|
+ foreach(var marks in _preLotCleanMarks)
|
|
|
+ {
|
|
|
+ if (marks.Value.Contains(pj.InnerId))
|
|
|
+ marks.Value.Remove(pj.InnerId);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach(var marks in _postLotCleanMarks)
|
|
|
+ {
|
|
|
+ if (marks.Value.Contains(pj.InnerId))
|
|
|
+ marks.Value.Remove(pj.InnerId);
|
|
|
+ }
|
|
|
+
|
|
|
pj.SetState(EnumProcessJobState.Queued);
|
|
|
pj.InnerId = Guid.NewGuid();
|
|
|
foreach (var pjSlotWafer in pj.SlotWafers)
|
|
@@ -2103,14 +2103,6 @@ namespace Venus_RT.Modules
|
|
|
cj.JetState == EnumJetCtrlJobState.PostJobClean;
|
|
|
}
|
|
|
|
|
|
- private bool IsCtrlJobEndingState(ControlJobInfo cj)
|
|
|
- {
|
|
|
- return cj.JetState == EnumJetCtrlJobState.PostJobClean ||
|
|
|
- (cj.JetState == EnumJetCtrlJobState.Processing
|
|
|
- && IsAllJobWaferProcessedOrProcessing(cj)
|
|
|
- && !IsCtrlJobNeedPostClean(cj));
|
|
|
- }
|
|
|
-
|
|
|
private bool IsCtrlJobNeedPreClean(ControlJobInfo cj)
|
|
|
{
|
|
|
return !string.IsNullOrWhiteSpace(cj.PreJobClean);
|
|
@@ -2359,6 +2351,7 @@ namespace Venus_RT.Modules
|
|
|
0,
|
|
|
temperature,
|
|
|
wafer.InnerId,
|
|
|
+ wafer.ProcessJob.InnerId,
|
|
|
recipeName,
|
|
|
wafer.ProcessJob.Sequence.GetWTWCleanRecipe(pm),
|
|
|
wafer.ProcessJob.Sequence.LLInOutPath,
|
|
@@ -2371,7 +2364,7 @@ namespace Venus_RT.Modules
|
|
|
_lstWaferTasks.Add(waferTask);
|
|
|
_qeWaitInWafers.Enqueue(wafer.InnerId);
|
|
|
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, waferTask.sourceMod, $"Routing wafer: {waferTask.sourceMod}.{waferTask.sourceSlot + 1} to {pm}");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, waferTask.sourceMod, $"Routing wafer: {waferTask.sourceMod}.{waferTask.sourceSlot + 1} to {pm}");
|
|
|
}
|
|
|
|
|
|
private void ReDispatchBlockingWafers()
|
|
@@ -2699,7 +2692,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (ExchangeWaferWithLL(outLL))
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady}");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady}");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -2711,7 +2704,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (ForwardATMWafers(inLL))
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
+ ////LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -2722,7 +2715,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (ForwardATMWafers(inLL))
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -2733,7 +2726,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (ExchangeWaferWithLL(inLL))
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady}");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -3370,6 +3363,20 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private bool HasPendingCleanTask()
|
|
|
+ {
|
|
|
+ foreach( var mod in _dictModuleTask)
|
|
|
+ {
|
|
|
+ if(ModuleHelper.IsPm(mod.Key) && mod.Value.Scheduler.IsOnline)
|
|
|
+ {
|
|
|
+ if ((mod.Value as PMTask).HasPendingCleanTask)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
private void Routing2SlotVacSystem()
|
|
|
{
|
|
|
var robotWafers = _lstWaferTasks.Where(wafer => ModuleHelper.IsTMRobot(wafer.currentMod)).OrderBy(wafer => TimeForNextModuleReady(wafer)).ToList();
|
|
@@ -3388,7 +3395,7 @@ namespace Venus_RT.Modules
|
|
|
#region special routing pattern
|
|
|
if (_specialRoutingPattern != SpecialRoutingPattern.Disable)
|
|
|
{
|
|
|
- if(_specialRoutingPattern == SpecialRoutingPattern.LongTimeRecipe && freeHands.Count == 2)
|
|
|
+ if(_specialRoutingPattern == SpecialRoutingPattern.LongTimeRecipe && freeHands.Count == 2 && !HasPendingCleanTask())
|
|
|
{
|
|
|
if(_dictModuleTask.Where(mod => ModuleHelper.IsPm(mod.Key) && !mod.Value.HasWafer && mod.Value.Scheduler.IsOnline).Count() == 0 && inLLWaferStatus.inSlot.Count > 0)
|
|
|
{
|
|
@@ -3396,6 +3403,11 @@ namespace Venus_RT.Modules
|
|
|
if(readyOutPMs.Count > 0 && inLLModule.ReayForTMInTime(5) && _lstWaferTasks.Exists(wt => wt.currentMod == inLL && readyOutPMs.Exists(kv => kv.Key == wt.destMod)))
|
|
|
{
|
|
|
var llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && wt.destMod == readyOutPMs.First().Key);
|
|
|
+ if(llWafer == null)
|
|
|
+ {
|
|
|
+ llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && readyOutPMs.Exists( pm => pm.Key == wt.destMod && pm.Value.TimeToReady < 5));
|
|
|
+ }
|
|
|
+
|
|
|
if(llWafer != null)
|
|
|
{
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, llWafer.currentSlot, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]) });
|
|
@@ -3435,13 +3447,13 @@ namespace Venus_RT.Modules
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(pm.Key, 0, ModuleName.TMRobot, (int)freeHands[pickCount], freeHands[pickCount]) });
|
|
|
placeActions.Add(new MoveItem(ModuleName.TMRobot, (int)freeHands[pickCount], outLL, outLLWaferStatus.emptySlot[pickCount], freeHands[pickCount]));
|
|
|
pickCount++;
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, pm.Key, $"{pm.Key} will be ready in {pm.Value.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, pm.Key, $"{pm.Key} will be ready in {pm.Value.TimeToReady} seconds");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (pickCount > 0)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(placeActions);
|
|
|
return;
|
|
|
}
|
|
@@ -3462,7 +3474,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
if(pickActions.Count > 0)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(pickActions);
|
|
|
return;
|
|
|
}
|
|
@@ -3473,7 +3485,7 @@ namespace Venus_RT.Modules
|
|
|
#region special routing pattern
|
|
|
if (_specialRoutingPattern != SpecialRoutingPattern.Disable)
|
|
|
{
|
|
|
- if (_specialRoutingPattern == SpecialRoutingPattern.LongTimeRecipe && _tmRobotSingleArmOption == 0)
|
|
|
+ if (_specialRoutingPattern == SpecialRoutingPattern.LongTimeRecipe && _tmRobotSingleArmOption == 0 && !HasPendingCleanTask())
|
|
|
{
|
|
|
if(_dictModuleTask.Where(mod => ModuleHelper.IsPm(mod.Key) && !mod.Value.HasWafer && mod.Value.Scheduler.IsOnline).Count() == 0 && ModuleHelper.IsLoadPort(robotWafers[0].destMod))
|
|
|
{
|
|
@@ -3495,24 +3507,35 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (_dictModuleTask[robotWafer.destMod].TimeToReady < 5)
|
|
|
{
|
|
|
- if (_dictModuleTask[robotWafer.destMod].HasWafer)
|
|
|
+ var pmWafer = _lstWaferTasks.Find(wt => wt.currentMod == robotWafer.destMod);
|
|
|
+ if (_dictModuleTask[robotWafer.destMod].HasWafer && pmWafer != null)
|
|
|
{
|
|
|
// PM Swap
|
|
|
if (freeHands.Count > 0)
|
|
|
{
|
|
|
- var pmActions = new List<MoveItem>
|
|
|
+
|
|
|
+ if (string.IsNullOrWhiteSpace(pmWafer.wtwCleanRecipe) && !(_dictModuleTask[pmWafer.currentMod] as PMTask).HasPendingCleanTask)
|
|
|
{
|
|
|
- new MoveItem(robotWafer.destMod, 0, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]),
|
|
|
- new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot)
|
|
|
- };
|
|
|
- _tmSchdActions.Enqueue(pmActions);
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, robotWafer.destMod, $"{robotWafer.destMod} will be ready in {_dictModuleTask[robotWafer.destMod].TimeToReady} seconds");
|
|
|
- return;
|
|
|
+ var pmActions = new List<MoveItem>
|
|
|
+ {
|
|
|
+ new MoveItem(robotWafer.destMod, 0, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]),
|
|
|
+ new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot)
|
|
|
+ };
|
|
|
+ _tmSchdActions.Enqueue(pmActions);
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, robotWafer.destMod, $"{robotWafer.destMod} will be ready in {_dictModuleTask[robotWafer.destMod].TimeToReady} seconds");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(robotWafer.destMod, 0, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, robotWafer.destMod, $"{robotWafer.destMod} will be ready in {_dictModuleTask[robotWafer.destMod].TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, robotWafer.destMod, $"{robotWafer.destMod} will be ready in {_dictModuleTask[robotWafer.destMod].TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot) });
|
|
|
return;
|
|
|
}
|
|
@@ -3525,8 +3548,8 @@ namespace Venus_RT.Modules
|
|
|
var readyOutWafer = _lstWaferTasks.Find(wt => ModuleHelper.IsPm(wt.currentMod) && ModuleHelper.IsLoadPort(wt.destMod));
|
|
|
if (readyOutWafer != null && _dictModuleTask[readyOutWafer.currentMod].TimeToReady < 5)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, readyOutWafer.currentMod, $"{readyOutWafer.currentMod} will be ready in {_dictModuleTask[readyOutWafer.currentMod].TimeToReady} seconds");
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, readyOutWafer.currentMod, $"{readyOutWafer.currentMod} will be ready in {_dictModuleTask[readyOutWafer.currentMod].TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(readyOutWafer.currentMod, 0, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]) });
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)freeHands[0], outLL, outLLWaferStatus.emptySlot[0], freeHands[0]) });
|
|
|
return;
|
|
@@ -3540,8 +3563,8 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (!_dictModuleTask[inWafer.destMod].HasWafer && _dictModuleTask[inWafer.destMod].TimeToReady < 10)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inWafer.destMod, $"{inWafer.destMod} will be ready in {_dictModuleTask[inWafer.destMod].TimeToReady} seconds");
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inWafer.destMod, $"{inWafer.destMod} will be ready in {_dictModuleTask[inWafer.destMod].TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, inWafer.currentSlot, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]) });
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)freeHands[0], inWafer.destMod, 0, freeHands[0]) });
|
|
|
return;
|
|
@@ -3577,14 +3600,14 @@ namespace Venus_RT.Modules
|
|
|
new MoveItem(ModuleName.TMRobot, 1, outLL, 1, Hand.Blade2)
|
|
|
};
|
|
|
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(doublePlace);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(outLLWaferStatus.emptySlot.Count > 0)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, outLL, outLLWaferStatus.emptySlot[0], (Hand)robotWafer.currentSlot) });
|
|
|
return;
|
|
|
}
|
|
@@ -3601,8 +3624,8 @@ namespace Venus_RT.Modules
|
|
|
var inWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && wt.currentSlot == inLLWaferStatus.inSlot.First());
|
|
|
if(inWafer != null && !_dictModuleTask[inWafer.destMod].HasWafer && _dictModuleTask[inWafer.destMod].TimeToReady < 20)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inWafer.destMod, $"{inWafer.destMod} will be ready in {_dictModuleTask[inWafer.destMod].TimeToReady} seconds");
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inWafer.destMod, $"{inWafer.destMod} will be ready in {_dictModuleTask[inWafer.destMod].TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, inLL, $"{inLL} will be ready in {inLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, inLLWaferStatus.inSlot.First(), ModuleName.TMRobot, (int)freeHands[0], freeHands[0])});
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)freeHands[0], inWafer.destMod, 0, freeHands[0]) });
|
|
|
return;
|
|
@@ -3616,8 +3639,8 @@ namespace Venus_RT.Modules
|
|
|
var readyReturnPMs = _dictModuleTask.Where(mod => ModuleHelper.IsPm(mod.Key) && mod.Value.HasWafer && mod.Value.TimeToReady < 5).OrderBy(mod => mod.Value.TimeToReady).ToList();
|
|
|
if(readyReturnPMs.Count > 0)
|
|
|
{
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, readyReturnPMs.First().Key, $"{readyReturnPMs.First().Key} will be ready in {readyReturnPMs.First().Value.TimeToReady} seconds");
|
|
|
- LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, readyReturnPMs.First().Key, $"{readyReturnPMs.First().Key} will be ready in {readyReturnPMs.First().Value.TimeToReady} seconds");
|
|
|
+ //LOG.Write(eEvent.INFO_TROUGHPUT_ENHANCE_TRACE, outLL, $"{outLL} will be ready in {outLLModule.TimeToReady} seconds");
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(readyReturnPMs.First().Key, 0, ModuleName.TMRobot, (int)freeHands[0], freeHands[0]) });
|
|
|
_tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)freeHands[0], outLL, outLLWaferStatus.emptySlot.First(), freeHands[0]) });
|
|
|
return;
|
|
@@ -3658,12 +3681,16 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
var pmActions = new List<MoveItem>();
|
|
|
var pmWafer = _lstWaferTasks.Find(wafer => (wafer.movingStatus == RState.End || wafer.movingStatus == RState.Init) && wafer.currentMod == robotWafers[0].destMod && ModuleHelper.IsLoadPort(wafer.destMod));
|
|
|
- if (pmWafer != null && string.IsNullOrWhiteSpace(pmWafer.wtwCleanRecipe))
|
|
|
+ if (pmWafer != null)
|
|
|
{
|
|
|
int pickSlot = 1 - robotWafers[0].currentSlot;
|
|
|
pmWafer.RouteTo(ModuleName.TMRobot, pickSlot);
|
|
|
pmActions.Add(new MoveItem(pmWafer.currentMod, 0, ModuleName.TMRobot, pickSlot, (Hand)pickSlot));
|
|
|
- pmActions.Add(new MoveItem(ModuleName.TMRobot, robotWafers[0].currentSlot, pmWafer.currentMod, 0, (Hand)robotWafers[0].currentSlot));
|
|
|
+
|
|
|
+ if (string.IsNullOrWhiteSpace(pmWafer.wtwCleanRecipe) && !(_dictModuleTask[robotWafers[0].destMod] as PMTask).HasPendingCleanTask)
|
|
|
+ {
|
|
|
+ pmActions.Add(new MoveItem(ModuleName.TMRobot, robotWafers[0].currentSlot, pmWafer.currentMod, 0, (Hand)robotWafers[0].currentSlot));
|
|
|
+ }
|
|
|
_tmSchdActions.Enqueue(pmActions);
|
|
|
return;
|
|
|
}
|
|
@@ -4598,6 +4625,103 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void RunLotCleanTasks()
|
|
|
+ {
|
|
|
+ foreach(var pm in _dictModuleTask)
|
|
|
+ {
|
|
|
+ if (!ModuleHelper.IsPm(pm.Key))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ var pmTask = pm.Value as PMTask;
|
|
|
+ if(pmTask.HasWafer)
|
|
|
+ {
|
|
|
+ var pmWafer = _lstWaferTasks.Find(wt => wt.currentMod == pm.Key);
|
|
|
+ if (pmWafer != null && IsProcessJobEnding(pmWafer.lotId, pm.Key) && !_postLotCleanMarks[pm.Key].Contains(pmWafer.lotId))
|
|
|
+ {
|
|
|
+ var pj = _lstProcessJobs.Find(process => process.InnerId == pmWafer.lotId);
|
|
|
+ if (pj != null)
|
|
|
+ {
|
|
|
+ var postClean = pj.Sequence.GetPostCleanRecipe(pm.Key);
|
|
|
+ if (!string.IsNullOrWhiteSpace(postClean))
|
|
|
+ {
|
|
|
+ pmTask.InvokePostJobClean(postClean);
|
|
|
+ _postLotCleanMarks[pm.Key].Add(pmWafer.lotId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // pre clean
|
|
|
+ var waitInWafer = GetFirstWaitInWafer(pm.Key);
|
|
|
+ if (waitInWafer != null && !_preLotCleanMarks[pm.Key].Contains(waitInWafer.lotId))
|
|
|
+ {
|
|
|
+ var pj = _lstProcessJobs.Find(process => process.InnerId == waitInWafer.lotId);
|
|
|
+ if (pj != null)
|
|
|
+ {
|
|
|
+ var preClean = pj.Sequence.GetPreCleanRecipe(pm.Key);
|
|
|
+ if (!string.IsNullOrWhiteSpace(preClean))
|
|
|
+ {
|
|
|
+ pmTask.InvokePreJobClean(preClean);
|
|
|
+ _preLotCleanMarks[pm.Key].Add(waitInWafer.lotId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool IsProcessJobEnding(Guid pjId, ModuleName pm)
|
|
|
+ {
|
|
|
+ if(!_lstWaferTasks.Exists(wt => wt.lotId == pjId && wt.destMod == pm && !ModuleHelper.IsPm(wt.currentMod)))
|
|
|
+ {
|
|
|
+ var processJob = _lstProcessJobs.Find(pj => pj.InnerId == pjId);
|
|
|
+ if (processJob == null)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ foreach(var slot in processJob.SlotWafers)
|
|
|
+ {
|
|
|
+ if(WaferManager.Instance.CheckHasWafer(slot.Item1, slot.Item2))
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.GetWafer(slot.Item1, slot.Item2).NextSequenceStep == 0)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ WaferTask GetFirstWaitInWafer(ModuleName pm)
|
|
|
+ {
|
|
|
+ int distance(WaferTask wafer)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsTMRobot(wafer.currentMod))
|
|
|
+ return 0;
|
|
|
+ else if (ModuleHelper.IsLoadLock(wafer.currentMod))
|
|
|
+ {
|
|
|
+ return (_dictModuleTask[wafer.currentMod] as LoadlockTask).Distance;
|
|
|
+ }
|
|
|
+ else if(ModuleHelper.IsEFEMRobot(wafer.currentMod))
|
|
|
+ {
|
|
|
+ if (wafer.IsAligned)
|
|
|
+ return 15;
|
|
|
+ else
|
|
|
+ return 19;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 17;
|
|
|
+ }
|
|
|
+
|
|
|
+ var waitInWafers = _lstWaferTasks.Where(wt => (wt.destMod == pm) && !ModuleHelper.IsPm(wt.currentMod) && !ModuleHelper.IsLoadPort(wt.currentMod)).OrderBy(wt => distance(wt));
|
|
|
+
|
|
|
+ if (waitInWafers.Count() > 0)
|
|
|
+ return waitInWafers.First();
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
private void ReturnVacWafers()
|
|
|
{
|
|
|
if (_tmSchdActions.Count > 0 || _curTmAction.Count > 0)
|