|
@@ -208,8 +208,15 @@ namespace Venus_RT.Modules
|
|
|
Aligning,
|
|
|
|
|
|
// Loadlock Status
|
|
|
- ExchangeWaferWithEFEM,
|
|
|
- ExchangeWaferWithTM,
|
|
|
+ StartPump,
|
|
|
+ Pumping,
|
|
|
+ VacReady,
|
|
|
+ StartVent,
|
|
|
+ Venting,
|
|
|
+ AtmReady,
|
|
|
+
|
|
|
+ // Unknown
|
|
|
+ Unknown,
|
|
|
}
|
|
|
|
|
|
public class ModuleTask
|
|
@@ -220,6 +227,8 @@ namespace Venus_RT.Modules
|
|
|
public virtual int SlotNum { get; protected set; }
|
|
|
public virtual bool IsIdle { get { return Status == ModuleStatus.Idle; } }
|
|
|
|
|
|
+ public virtual bool HasWafer { get { return WaferManager.Instance.CheckHasWafer(Module, 0); } }
|
|
|
+
|
|
|
private int _currentActionTime = 0;
|
|
|
|
|
|
public virtual int IdleTime
|
|
@@ -677,6 +686,17 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public enum LLStatus
|
|
|
+ {
|
|
|
+ StartPump,
|
|
|
+ Pumping,
|
|
|
+ VacReady,
|
|
|
+ StartVent,
|
|
|
+ Venting,
|
|
|
+ AtmReady,
|
|
|
+ Unknow,
|
|
|
+ }
|
|
|
+
|
|
|
public class LoadlockTask : ModuleTask
|
|
|
{
|
|
|
private Dictionary<int, int> _wafersDelayTime = new Dictionary<int, int>();
|
|
@@ -693,17 +713,14 @@ namespace Venus_RT.Modules
|
|
|
get { return Scheduler.IsAvailable ? 0 : (Scheduler.TimeToReady + 500) / 1000; }
|
|
|
}
|
|
|
|
|
|
- public int ReayOutWafersInTime(int seconds)
|
|
|
+ public bool ReayForTMInTime(int seconds)
|
|
|
{
|
|
|
+ return (Status == ModuleStatus.Pumping && TimeToReady < seconds) || Status == ModuleStatus.VacReady;
|
|
|
+ }
|
|
|
|
|
|
- int readyOut = 0;
|
|
|
- foreach(var slot in _wafersDelayTime)
|
|
|
- {
|
|
|
- if (slot.Value >= 0 && Scheduler.WaferArrivedTicks(slot.Key) / 1000 + seconds > slot.Value)
|
|
|
- readyOut++;
|
|
|
- }
|
|
|
-
|
|
|
- return readyOut;
|
|
|
+ public bool ReayForEfemInTime(int seconds)
|
|
|
+ {
|
|
|
+ return (Status == ModuleStatus.Venting && TimeToReady < seconds) || Status == ModuleStatus.AtmReady;
|
|
|
}
|
|
|
|
|
|
public override void WaferArrived(WaferTask wafer, int slot)
|
|
@@ -728,6 +745,7 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (Scheduler.IsAvailable && Scheduler.IsVac)
|
|
|
{
|
|
|
+ Status = ModuleStatus.StartVent;
|
|
|
return (Scheduler as SchedulerLoadLock).PreVent();
|
|
|
}
|
|
|
|
|
@@ -738,11 +756,45 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (Scheduler.IsAvailable && Scheduler.IsAtm)
|
|
|
{
|
|
|
+ Status = ModuleStatus.StartPump;
|
|
|
return (Scheduler as SchedulerLoadLock).PrePump();
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+ public override RState Run()
|
|
|
+ {
|
|
|
+ if (Scheduler.IsIdle)
|
|
|
+ {
|
|
|
+ if (Scheduler.IsAvailable && Scheduler.IsVac)
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.VacReady;
|
|
|
+ }
|
|
|
+ else if (Scheduler.IsAvailable && Scheduler.IsAtm)
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.AtmReady;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.Idle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ switch(Status)
|
|
|
+ {
|
|
|
+ case ModuleStatus.StartPump:
|
|
|
+ Status = ModuleStatus.Pumping;
|
|
|
+ break;
|
|
|
+ case ModuleStatus.StartVent:
|
|
|
+ Status = ModuleStatus.Venting;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return RState.Running;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
enum LLSlotInOutOpt
|
|
@@ -780,10 +832,10 @@ namespace Venus_RT.Modules
|
|
|
private int _efemRobotSingleArmOption = 0;
|
|
|
private int _tmRobotSingleArmOption = 0;
|
|
|
private LLSlotInOutOpt _LLSlotInOutOption = 0;
|
|
|
- private Dictionary<ModuleName, int> _lpCycleWafer = new Dictionary<ModuleName, int> { { ModuleName.LP1, 0}, { ModuleName.LP2, 0 },{ ModuleName.LP3, 0 } };
|
|
|
+ private Dictionary<ModuleName, int> _lpCycleWafer = new Dictionary<ModuleName, int> { {ModuleName.LP1, 0}, { ModuleName.LP2, 0}, { ModuleName.LP3, 0} };
|
|
|
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, 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 Stopwatch _cycleWatch = new Stopwatch();
|
|
|
|
|
|
private SequenceLLInOutPath _LLInOutPath = SequenceLLInOutPath.DInDOut;
|
|
@@ -820,10 +872,10 @@ namespace Venus_RT.Modules
|
|
|
_loadportControlJobDic[lp.ToString()] = null;
|
|
|
DATA.Subscribe($"{lp}.CurrentControlJob", () => _loadportControlJobDic[lp.ToString()], SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
|
|
|
- DATA.Subscribe($"{lp}.CycledCount", () => _lpCycleCount.Keys.Contains(lp) ?_lpCycleCount[lp]:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
- DATA.Subscribe($"{lp}.CycledWafer", () => _lpCycleCount.Keys.Contains(lp) ? _lpCycleWafer[lp]:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
- DATA.Subscribe($"{lp}.CycleSetPoint", () => _lpCycleCount.Keys.Contains(lp) ? _lpCycleSP[lp]:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
- DATA.Subscribe($"{lp}.Throughput", () => _lpCycleCount.Keys.Contains(lp) ? _lpThroughput[lp]:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
+ DATA.Subscribe($"{lp}.CycledCount", () => _lpCycleCount[lp], SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
+ DATA.Subscribe($"{lp}.CycledWafer", () => _lpCycleWafer[lp], SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
+ DATA.Subscribe($"{lp}.CycleSetPoint", () => _lpCycleSP[lp], SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
+ DATA.Subscribe($"{lp}.Throughput", () => _lpThroughput[lp], SubscriptionAttribute.FLAG.IgnoreSaveDB);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -863,8 +915,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
|
|
|
_cycleWatch.Stop();
|
|
|
- _lpCycleWafer.Clear();
|
|
|
- _lpCycleCount.Clear();
|
|
|
+ Clear();
|
|
|
|
|
|
return RState.Running;
|
|
|
}
|
|
@@ -907,7 +958,7 @@ namespace Venus_RT.Modules
|
|
|
string preCleanRecipe = param.ContainsKey("PreCleanRecipeName") ? (string)param["PreCleanRecipeName"] : string.Empty;
|
|
|
string postCleanRecipe = param.ContainsKey("PostCleanRecipeName") ? (string)param["PostCleanRecipeName"] : string.Empty;
|
|
|
|
|
|
- int cycleNumber= param.ContainsKey("CycleNumber") ? (int)param["CycleNumber"] : 1;
|
|
|
+ int cycleNumber = param.ContainsKey("CycleNumber") ? (int)param["CycleNumber"] : 1;
|
|
|
if (slotSequence.Length != SC.GetValue<int>("EFEM.LoadPort.SlotNumber"))
|
|
|
{
|
|
|
reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be {SC.GetValue<int>("EFEM.LoadPort.SlotNumber")}";
|
|
@@ -943,7 +994,7 @@ namespace Venus_RT.Modules
|
|
|
cj.PreJobClean = preCleanRecipe;
|
|
|
cj.PostJobClean = postCleanRecipe;
|
|
|
cj.SequenceNameList = slotSequence;
|
|
|
- cj.CycleNumber = cycleNumber; // only for temperary debug
|
|
|
+ cj.CycleNumber = cycleNumber;
|
|
|
|
|
|
_lpCycleSP[ModuleHelper.Converter(module)] = cj.CycleNumber;
|
|
|
|
|
@@ -1290,6 +1341,11 @@ namespace Venus_RT.Modules
|
|
|
_loadportControlJobDic[key] = null;
|
|
|
}
|
|
|
|
|
|
+ _lpCycleWafer = new Dictionary<ModuleName, int> { { ModuleName.LP1, 0 }, { ModuleName.LP2, 0 }, { ModuleName.LP3, 0 } };
|
|
|
+ _lpCycleCount = new Dictionary<ModuleName, int> { { ModuleName.LP1, 0 }, { ModuleName.LP2, 0 }, { ModuleName.LP3, 0 } };
|
|
|
+ _lpCycleSP = new Dictionary<ModuleName, int> { { ModuleName.LP1, 0 }, { ModuleName.LP2, 0 }, { ModuleName.LP3, 0 } };
|
|
|
+ _lpThroughput = new Dictionary<ModuleName, float> { { ModuleName.LP1, 0 }, { ModuleName.LP2, 0 }, { ModuleName.LP3, 0 } };
|
|
|
+
|
|
|
_lstWaferTasks.Clear();
|
|
|
_tmSchdActions.Clear();
|
|
|
_curTmAction.Clear();
|
|
@@ -2375,7 +2431,6 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private void Routing2SlotATMSystem()
|
|
|
{
|
|
|
-
|
|
|
var atmWaferCount = _lstWaferTasks.Where(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod) || ModuleHelper.IsAligner(wafer.currentMod)).Count();
|
|
|
var efemRobotWafers = _lstWaferTasks.Where(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod)).ToList();
|
|
|
var validHands = (_efemRobotSingleArmOption == 0 ? 2 : 1);
|
|
@@ -2385,40 +2440,42 @@ namespace Venus_RT.Modules
|
|
|
var outLL = LLInOutPath == SequenceLLInOutPath.AInBOut ? ModuleName.LLB : ModuleName.LLA;
|
|
|
var inLLWaferStatus = GetLLReadyInOutSlots(inLL);
|
|
|
var outLLWaferStatus = GetLLReadyInOutSlots(outLL);
|
|
|
+ var inLLModule = _dictModuleTask[inLL] as LoadlockTask;
|
|
|
+ var outLLModule = _dictModuleTask[outLL] as LoadlockTask;
|
|
|
+ var needAlign = _lstProcessJobs.Exists(pj => pj.State == EnumProcessJobState.Processing && IsSequenceNeedAlign(pj.Sequence));
|
|
|
|
|
|
- // whether can do double return in 5 second, single return with single arm option or LL under atm pressure
|
|
|
- if ((outLLWaferStatus.outSlot.Count == 2 && _dictModuleTask[outLL].TimeToReady < 5 && (atmWaferCount < 2 || !_dictModuleTask[outLL].Scheduler.IsAtm)) ||
|
|
|
- (outLLWaferStatus.outSlot.Count == 1 && ((_dictModuleTask[outLL].TimeToReady < 2 && _dictModuleTask[outLL].Scheduler.IsAtm)
|
|
|
- || _efemRobotSingleArmOption != 0
|
|
|
- || _lstWaferTasks.Where(wt => ModuleHelper.IsLoadPort(wt.destMod)).Count() == 1)))
|
|
|
+ // return wafer while out LL ready or cooling state
|
|
|
+ if ((outLLWaferStatus.outSlot.Count > 0) && outLLModule.ReayForEfemInTime(10))
|
|
|
{
|
|
|
if (ExchangeWaferWithLL(outLL))
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // need pass by aligner
|
|
|
- if(_lstProcessJobs.Exists(pj => pj.State == EnumProcessJobState.Processing && IsSequenceNeedAlign(pj.Sequence)))
|
|
|
+ if (needAlign)
|
|
|
{
|
|
|
- if (atmWaferCount == 0 || (atmWaferCount == 1 && inLLWaferStatus.emptySlot.Count == 2 && _efemRobotSingleArmOption == 0 && (outLLWaferStatus.outSlot.Count < 2)))
|
|
|
+ if (atmWaferCount == 0 || (atmWaferCount == 1 && inLLWaferStatus.emptySlot.Count == 2 && _efemRobotSingleArmOption == 0 && (outLLWaferStatus.outSlot.Count < 2 || (outLLModule.TimeToReady - inLLModule.TimeToReady > 10) || !outLLModule.ReayForEfemInTime(30))))
|
|
|
{
|
|
|
if (ForwardATMWafers(inLL))
|
|
|
return;
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
- // don need pass by aligner
|
|
|
else
|
|
|
{
|
|
|
- var outModule = _dictModuleTask[outLL] as LoadlockTask;
|
|
|
- if ((atmWaferCount < validHands - outModule.ReayOutWafersInTime(20) || _dictModuleTask[inLL].TimeToReady < 5) && _lstWaferTasks.Count(wt => wt.currentMod == inLL || wt.currentMod == ModuleName.EfemRobot) < validHands)
|
|
|
+ if (inLLModule.ReayForEfemInTime(20) && inLLWaferStatus.emptySlot.Count > efemRobotWafers.Count && ((outLLModule.TimeToReady - inLLModule.TimeToReady > 10) || !outLLModule.ReayForEfemInTime(30) || outLLWaferStatus.emptySlot.Count < efemRobotWafers.Count))
|
|
|
{
|
|
|
if (ForwardATMWafers(inLL))
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (inLLWaferStatus.emptySlot.Count >= validHands && _dictModuleTask[inLL].TimeToReady < 2)
|
|
|
+ if (inLLModule.ReayForEfemInTime(5) &&
|
|
|
+ inLLWaferStatus.emptySlot.Count > 0 && atmWaferCount > 0 &&
|
|
|
+ (inLLWaferStatus.emptySlot.Count == atmWaferCount ||
|
|
|
+ !_lstWaferTasks.Exists(wt => ModuleHelper.IsLoadPort(wt.currentMod) && ModuleHelper.IsPm(wt.destMod)) ||
|
|
|
+ _efemRobotSingleArmOption != 0))
|
|
|
{
|
|
|
- ExchangeWaferWithLL(inLL);
|
|
|
+ if (ExchangeWaferWithLL(inLL))
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -2687,7 +2744,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
var nextModule = nextActions.First().Module;
|
|
|
|
|
|
- if (ModuleHelper.IsLoadLock(nextModule) && !_dictModuleTask[nextModule].IsIdle)
|
|
|
+ if (ModuleHelper.IsLoadLock(nextModule) && !_dictModuleTask[nextModule].Scheduler.IsAvailable)
|
|
|
return;
|
|
|
|
|
|
_curEfemAction = _efemSchdActions.Dequeue();
|
|
@@ -3056,248 +3113,142 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private void Routing2SlotVacSystem()
|
|
|
{
|
|
|
- var robotWafers = _lstWaferTasks.Where(wafer => (wafer.movingStatus == RState.End || wafer.movingStatus == RState.Init) && ModuleHelper.IsTMRobot(wafer.currentMod)).OrderBy(wafer => TimeForNextModuleReady(wafer)).ToList();
|
|
|
+ var robotWafers = _lstWaferTasks.Where(wafer => ModuleHelper.IsTMRobot(wafer.currentMod)).OrderBy(wafer => TimeForNextModuleReady(wafer)).ToList();
|
|
|
+ var freeHands = GetTMFreeHand();
|
|
|
if (LLInOutPath == SequenceLLInOutPath.AInBOut || LLInOutPath == SequenceLLInOutPath.BInAOut)
|
|
|
{
|
|
|
var inLL = LLInOutPath == SequenceLLInOutPath.AInBOut ? ModuleName.LLA : ModuleName.LLB;
|
|
|
var outLL = LLInOutPath == SequenceLLInOutPath.AInBOut ? ModuleName.LLB : ModuleName.LLA;
|
|
|
var inLLWaferStatus = GetLLReadyInOutSlots(inLL);
|
|
|
var outLLWaferStatus = GetLLReadyInOutSlots(outLL);
|
|
|
-
|
|
|
- if(robotWafers.Count == 2)
|
|
|
- {
|
|
|
- int returnCount = 0;
|
|
|
- foreach (var wafer in robotWafers)
|
|
|
- {
|
|
|
- if (ModuleHelper.IsPm(wafer.destMod))
|
|
|
- {
|
|
|
- if (_dictModuleTask[wafer.destMod].TimeToReady <= 5 &&
|
|
|
- !_lstWaferTasks.Exists(waferT => waferT.currentMod == wafer.destMod) &&
|
|
|
- !_lstWaferTasks.Exists(waferT => waferT.routedMod == wafer.destMod))
|
|
|
- {
|
|
|
- wafer.RouteTo(wafer.destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, wafer.destMod, 0, (Hand)wafer.currentSlot) });
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (_dictModuleTask[outLL].TimeToReady <= 5 && !IsLLReservedByEFEM(outLL) && outLLWaferStatus.emptySlot.Count > returnCount)
|
|
|
- {
|
|
|
- wafer.RouteTo(outLL, outLLWaferStatus.emptySlot[returnCount]);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, outLL, outLLWaferStatus.emptySlot[returnCount], (Hand)wafer.currentSlot) });
|
|
|
- returnCount++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else if(robotWafers.Count == 1)
|
|
|
+ var inLLModule = _dictModuleTask[inLL] as LoadlockTask;
|
|
|
+ var outLLModule = _dictModuleTask[outLL] as LoadlockTask;
|
|
|
+
|
|
|
+ if(robotWafers.Count == 0)
|
|
|
{
|
|
|
- int freeHand = 1 - robotWafers.First().currentSlot;
|
|
|
- if (ModuleHelper.IsPm(robotWafers.First().destMod))
|
|
|
+ // push wafer from LL to PM and avoid blocking two robot arms
|
|
|
+ if (inLLModule.ReayForTMInTime(10) && inLLWaferStatus.inSlot.Count > 0)
|
|
|
{
|
|
|
- if(_dictModuleTask[robotWafers.First().destMod].TimeToReady <= 5)
|
|
|
+ var pickActions = new List<MoveItem>();
|
|
|
+ var inLLWafers = _lstWaferTasks.FindAll(wt => wt.currentMod == inLL).ToList();
|
|
|
+ if (inLLWaferStatus.inSlot.Count < 2 || inLLWafers.Exists(wt => !_dictModuleTask[wt.destMod].HasWafer && _dictModuleTask[wt.destMod].TimeToReady < 20))
|
|
|
{
|
|
|
- if(_lstWaferTasks.Exists(waferT => waferT.currentMod == robotWafers.First().destMod))
|
|
|
- {
|
|
|
- var pmActions = new List<MoveItem>();
|
|
|
- var pmWafer = _lstWaferTasks.Find(wafer => wafer.currentMod == robotWafers.First().destMod);
|
|
|
- pmWafer.RouteTo(ModuleName.TMRobot, freeHand);
|
|
|
- pmActions.Add(new MoveItem(pmWafer.currentMod, 0, ModuleName.TMRobot, freeHand, (Hand)freeHand));
|
|
|
- pmActions.Add(new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, pmWafer.currentMod, 0, (Hand)robotWafers.First().currentSlot));
|
|
|
- _tmSchdActions.Enqueue(pmActions);
|
|
|
- }
|
|
|
- else
|
|
|
+ for (int i = 0; i < Math.Min(inLLWaferStatus.inSlot.Count, freeHands.Count); i++)
|
|
|
{
|
|
|
- robotWafers.First().RouteTo(robotWafers.First().destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, robotWafers.First().destMod, 0, (Hand)robotWafers.First().currentSlot) });
|
|
|
+ pickActions.Add(new MoveItem(inLL, inLLWaferStatus.inSlot[i], ModuleName.TMRobot, (int)freeHands[i], freeHands[i]));
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (_dictModuleTask[outLL].TimeToReady <= 5 && !IsLLReservedByEFEM(outLL) && outLLWaferStatus.emptySlot.Count > 0)
|
|
|
+
|
|
|
+ if(pickActions.Count > 0)
|
|
|
{
|
|
|
- robotWafers.First().RouteTo(outLL, outLLWaferStatus.emptySlot[0]);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, outLL, outLLWaferStatus.emptySlot[0], (Hand)robotWafers.First().currentSlot) });
|
|
|
+ _tmSchdActions.Enqueue(pickActions);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (_tmSchdActions.Count == 0 && _tmRobotSingleArmOption == 0)
|
|
|
+ // keep out loadlock readyForTM State after put one wafer and wait for another out wafer
|
|
|
+ var readyOutPMs = _dictModuleTask.Where(mod => ModuleHelper.IsPm(mod.Key) && mod.Value.HasWafer && mod.Value.TimeToReady < 20).OrderBy(mod => mod.Value.TimeToReady).ToList();
|
|
|
+ if(readyOutPMs.Count > 0 && outLLModule.ReayForTMInTime(30) && outLLWaferStatus.emptySlot.Count > 0)
|
|
|
{
|
|
|
- // try push in one wafer
|
|
|
- if (!IsLLReservedByEFEM(inLL) && _dictModuleTask[inLL].TimeToReady < 5 && inLLWaferStatus.inSlot.Count > 0)
|
|
|
+ var placeActions = new List<MoveItem>();
|
|
|
+ int pickCount = 0;
|
|
|
+ foreach(var pm in readyOutPMs)
|
|
|
{
|
|
|
- foreach (var slot in inLLWaferStatus.inSlot)
|
|
|
+ var pmWafer = _lstWaferTasks.Find(wt => wt.currentMod == pm.Key);
|
|
|
+ if(pmWafer != null && pickCount < freeHands.Count && pickCount < outLLWaferStatus.emptySlot.Count)
|
|
|
{
|
|
|
- var llWafer = _lstWaferTasks.Find(wafer => wafer.currentMod == inLL && wafer.currentSlot == slot);
|
|
|
- if (llWafer != null && !_lstWaferTasks.Exists(wt => wt.currentMod == llWafer.destMod) && _dictModuleTask[llWafer.destMod].TimeToReady < 15)
|
|
|
- {
|
|
|
- llWafer.RouteTo(llWafer.destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, slot, ModuleName.TMRobot, freeHand, (Hand)freeHand) });
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, freeHand, llWafer.destMod, 0, (Hand)freeHand) });
|
|
|
- return;
|
|
|
- }
|
|
|
+ _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++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // try to return one wafer
|
|
|
- if (!IsLLReservedByEFEM(outLL) && outLLWaferStatus.emptySlot.Count > 0)
|
|
|
+ if(pickCount > 0)
|
|
|
{
|
|
|
- var reayReturnWafer = _lstWaferTasks.Find(wt => ModuleHelper.IsPm(wt.currentMod) && ModuleHelper.IsLoadPort(wt.destMod) && _dictModuleTask[wt.currentMod].TimeToReady <= 2);
|
|
|
- if (reayReturnWafer != null)
|
|
|
- {
|
|
|
- reayReturnWafer.RouteTo(outLL, outLLWaferStatus.emptySlot[0]);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(reayReturnWafer.currentMod, 0, ModuleName.TMRobot, freeHand, (Hand)freeHand) });
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, freeHand, outLL, outLLWaferStatus.emptySlot[0], (Hand)freeHand) });
|
|
|
- return;
|
|
|
- }
|
|
|
+ _tmSchdActions.Enqueue(placeActions);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else // no wafer on robot arm
|
|
|
+ else
|
|
|
{
|
|
|
- var readyInPms = _dictModuleTask.Where(mod => ModuleHelper.IsPm(mod.Key) && !_lstWaferTasks.Exists(wt => wt.currentMod == mod.Key) && mod.Value.Scheduler.IsOnline && mod.Value.TimeToReady <= 15);
|
|
|
- var readyOutWafers = _lstWaferTasks.Where(wt => ModuleHelper.IsPm(wt.currentMod) && ModuleHelper.IsLoadPort(wt.destMod) && _dictModuleTask[wt.currentMod].TimeToReady <= 2).ToList() ;
|
|
|
-
|
|
|
- if(_tmRobotSingleArmOption != 0)
|
|
|
- {
|
|
|
- var hands = GetTMValidFreeHands(robotWafers, new List<MoveItem>());
|
|
|
- if (hands.Count == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if(!IsLLReservedByEFEM(inLL) && _dictModuleTask[inLL].TimeToReady <= 5 && inLLWaferStatus.inSlot.Count > 0 && readyInPms.Count() > 0)
|
|
|
- {
|
|
|
- foreach(var pm in readyInPms)
|
|
|
- {
|
|
|
- var llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && inLLWaferStatus.inSlot.Contains(wt.currentSlot) && wt.destMod == pm.Key);
|
|
|
- if(llWafer != null)
|
|
|
- {
|
|
|
- llWafer.RouteTo(llWafer.destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, llWafer.currentSlot, ModuleName.TMRobot, (int)hands.First(), hands.First()) });
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)hands.First(), llWafer.destMod, 0, hands.First()) });
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(readyOutWafers.Count > 0 && !IsLLReservedByEFEM(outLL) && _dictModuleTask[outLL].TimeToReady < 50 && outLLWaferStatus.emptySlot.Count > 0)
|
|
|
- {
|
|
|
- var returnWafer = readyOutWafers.First();
|
|
|
- returnWafer.RouteTo(outLL, outLLWaferStatus.emptySlot.First());
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(returnWafer.currentMod, 0, ModuleName.TMRobot, (int)hands.First(), hands.First()) });
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)hands.First(), outLL, outLLWaferStatus.emptySlot.First(), hands.First()) });
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if(!IsLLReservedByEFEM(inLL) && _dictModuleTask[inLL].TimeToReady <= 5 && inLLWaferStatus.inSlot.Count > 0)
|
|
|
+ foreach(var robotWafer in robotWafers)
|
|
|
{
|
|
|
- if(inLLWaferStatus.inSlot.Count == 2)
|
|
|
+ if(ModuleHelper.IsPm(robotWafer.destMod))
|
|
|
{
|
|
|
- if(readyInPms.Count() > 0) // double move from LL to PM
|
|
|
+ if (_dictModuleTask[robotWafer.destMod].TimeToReady < 5)
|
|
|
{
|
|
|
- int pickCount = 0;
|
|
|
- var swapActions = new List<MoveItem>();
|
|
|
- var singleActions = new List<MoveItem>();
|
|
|
- foreach(var pm in readyInPms)
|
|
|
+ if (_dictModuleTask[robotWafer.destMod].HasWafer)
|
|
|
{
|
|
|
- var llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && inLLWaferStatus.inSlot.Contains(wt.currentSlot) && wt.destMod == pm.Key);
|
|
|
- if(llWafer != null)
|
|
|
+ // PM Swap
|
|
|
+ if(freeHands.Count > 0)
|
|
|
{
|
|
|
- llWafer.RouteTo(pm.Key, 0);
|
|
|
- swapActions.Add(new MoveItem(inLL, llWafer.currentSlot, ModuleName.TMRobot, pickCount, (Hand)pickCount));
|
|
|
- singleActions.Add(new MoveItem(ModuleName.TMRobot, pickCount, pm.Key, 0, (Hand)pickCount));
|
|
|
- pickCount++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(pickCount == 1)
|
|
|
- {
|
|
|
- int remainSlot = swapActions.First().SourceSlot == inLLWaferStatus.inSlot[0] ? inLLWaferStatus.inSlot[1] : inLLWaferStatus.inSlot[0];
|
|
|
- var remainWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && wt.currentSlot == remainSlot);
|
|
|
- if (remainWafer != null)
|
|
|
- {
|
|
|
- remainWafer.RouteTo(ModuleName.TMRobot, 1);
|
|
|
- swapActions.Add(new MoveItem(inLL, remainSlot, ModuleName.TMRobot, 1, Hand.Blade2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(swapActions.Count > 0)
|
|
|
- {
|
|
|
- _tmSchdActions.Enqueue(swapActions);
|
|
|
- foreach(var ac in singleActions)
|
|
|
- {
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { ac });
|
|
|
+ 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);
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- foreach(var slot in inLLWaferStatus.inSlot)
|
|
|
+ else
|
|
|
{
|
|
|
- var llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && wt.currentSlot == slot);
|
|
|
- if (llWafer != null)
|
|
|
- {
|
|
|
- if(!_lstWaferTasks.Exists(wt => wt.currentMod == llWafer.destMod) && _dictModuleTask[llWafer.destMod].Scheduler.IsOnline)
|
|
|
- {
|
|
|
- var swapActions = new List<MoveItem>();
|
|
|
- swapActions.Add(new MoveItem(inLL, slot, ModuleName.TMRobot, 0, Hand.Blade1));
|
|
|
- int remainSlot = slot == inLLWaferStatus.inSlot[0] ? inLLWaferStatus.inSlot[1] : inLLWaferStatus.inSlot[0];
|
|
|
- swapActions.Add(new MoveItem(inLL, remainSlot, ModuleName.TMRobot, 1, Hand.Blade2));
|
|
|
- _tmSchdActions.Enqueue(swapActions);
|
|
|
-
|
|
|
- llWafer.RouteTo(ModuleName.TMRobot, 0);
|
|
|
- if (_dictModuleTask[llWafer.destMod].TimeToReady <= 30)
|
|
|
- {
|
|
|
- llWafer.RouteTo(llWafer.destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, 0, llWafer.destMod, 0, Hand.Blade1) });
|
|
|
- }
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot) });
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var llWafer = _lstWaferTasks.Find(wt => wt.currentMod == inLL && wt.currentSlot == inLLWaferStatus.inSlot.First());
|
|
|
- if (llWafer != null)
|
|
|
+ if (outLLModule.ReayForTMInTime(5))
|
|
|
{
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(inLL, inLLWaferStatus.inSlot.First(), ModuleName.TMRobot, 0, Hand.Blade1) });
|
|
|
- if (!_lstWaferTasks.Exists(wt => wt.currentMod == llWafer.destMod) && _dictModuleTask[llWafer.destMod].TimeToReady < 15)
|
|
|
+ // try match a double place
|
|
|
+ if (robotWafers.Count == 2 && robotWafers.All(wt => ModuleHelper.IsLoadPort(wt.destMod)) && outLLWaferStatus.emptySlot.Count == 2)
|
|
|
+ {
|
|
|
+ var doublePlace = new List<MoveItem>
|
|
|
+ {
|
|
|
+ new MoveItem(ModuleName.TMRobot, 0, outLL, 0, Hand.Blade1),
|
|
|
+ new MoveItem(ModuleName.TMRobot, 1, outLL, 1, Hand.Blade2)
|
|
|
+ };
|
|
|
+ _tmSchdActions.Enqueue(doublePlace);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(outLLWaferStatus.emptySlot.Count > 0)
|
|
|
{
|
|
|
- llWafer.RouteTo(llWafer.destMod, 0);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, 0, llWafer.destMod, 0, Hand.Blade1) });
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, outLL, outLLWaferStatus.emptySlot[0], (Hand)robotWafer.currentSlot) });
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (_tmSchdActions.Count > 0)
|
|
|
+ if (freeHands.Count == 0)
|
|
|
return;
|
|
|
|
|
|
- if(!IsLLReservedByEFEM(outLL) && outLLWaferStatus.emptySlot.Count > 0 && readyOutWafers.Count > 0)
|
|
|
+ // try to push one wafer in pm
|
|
|
+ if(inLLWaferStatus.inSlot.Count == 1 && inLLModule.ReayForTMInTime(5))
|
|
|
{
|
|
|
- if(readyOutWafers.Count >= 2 && outLLWaferStatus.emptySlot.Count == 2)
|
|
|
+ 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)
|
|
|
{
|
|
|
- readyOutWafers[0].RouteTo(outLL, outLLWaferStatus.emptySlot[0]);
|
|
|
- readyOutWafers[1].RouteTo(outLL, outLLWaferStatus.emptySlot[1]);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(readyOutWafers[0].currentMod, readyOutWafers[0].currentSlot, ModuleName.TMRobot, 0, Hand.Blade1) });
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(readyOutWafers[1].currentMod, readyOutWafers[1].currentSlot, ModuleName.TMRobot, 1, Hand.Blade2) });
|
|
|
- var swapActions = new List<MoveItem>();
|
|
|
- swapActions.Add(new MoveItem(ModuleName.TMRobot, 0, outLL, outLLWaferStatus.emptySlot[0], Hand.Blade1));
|
|
|
- swapActions.Add(new MoveItem(ModuleName.TMRobot, 1, outLL, outLLWaferStatus.emptySlot[1], Hand.Blade2));
|
|
|
- _tmSchdActions.Enqueue(swapActions);
|
|
|
+ _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;
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // try to return one wafer
|
|
|
+ if(outLLModule.ReayForTMInTime(15) && outLLWaferStatus.emptySlot.Count > 0)
|
|
|
+ {
|
|
|
+ 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)
|
|
|
{
|
|
|
- var freeHands = GetTMValidFreeHands(robotWafers, new List<MoveItem>());
|
|
|
- readyOutWafers[0].RouteTo(outLL, outLLWaferStatus.emptySlot[0]);
|
|
|
- _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(readyOutWafers[0].currentMod, readyOutWafers[0].currentSlot, 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]) });
|
|
|
+ _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;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -3564,9 +3515,11 @@ namespace Venus_RT.Modules
|
|
|
var pickHand = SelectTMPickArm(destPM);
|
|
|
if(pickHand != Hand.None)
|
|
|
{
|
|
|
- var pmSwap = new List<MoveItem>();
|
|
|
- pmSwap.Add(new MoveItem(destPM, 0, ModuleName.TMRobot, (int)pickHand, pickHand));
|
|
|
- pmSwap.Add(new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, destPM, 0, (Hand)robotWafers.First().currentSlot));
|
|
|
+ var pmSwap = new List<MoveItem>
|
|
|
+ {
|
|
|
+ new MoveItem(destPM, 0, ModuleName.TMRobot, (int)pickHand, pickHand),
|
|
|
+ new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, destPM, 0, (Hand)robotWafers.First().currentSlot)
|
|
|
+ };
|
|
|
_tmSchdActions.Enqueue(pmSwap);
|
|
|
return;
|
|
|
}
|
|
@@ -4147,65 +4100,132 @@ namespace Venus_RT.Modules
|
|
|
if (RouteManager.IsATMMode)
|
|
|
return;
|
|
|
|
|
|
- var preaparedLLs = new List<ModuleName>();
|
|
|
- var lls = _efemSchdActions.Where(acs => ModuleHelper.IsLoadLock(acs.First().Module)).Select(item => item.First().Module).ToList();
|
|
|
- if (_curEfemAction.Count == 0 && _efemSchdActions.Count > 0 && ModuleHelper.IsLoadLock(_efemSchdActions.First().First().Module))
|
|
|
- lls.Remove(_efemSchdActions.First().First().Module);
|
|
|
+ var schdPumpingLLs = new List<ModuleName>();
|
|
|
+ var schdVentingLLs = new List<ModuleName>();
|
|
|
+ var schdCoolingLLs = new List<ModuleName>();
|
|
|
+ var llaWaferStatus = GetLLReadyInOutSlots(ModuleName.LLA);
|
|
|
+ var llbWaferStatus = GetLLReadyInOutSlots(ModuleName.LLB);
|
|
|
|
|
|
- foreach(var ll in lls)
|
|
|
+ // pre pumping/venting for schedule actions
|
|
|
+ if (_efemSchdActions.Count > 0)
|
|
|
{
|
|
|
- if(_dictModuleTask[ll].Scheduler.IsAvailable && _dictModuleTask[ll].Scheduler.IsVac && !preaparedLLs.Contains(ll))
|
|
|
+ var ventLLs = _efemSchdActions.Where(acs => ModuleHelper.IsLoadLock(acs.First().Module)).Select(item => item.First().Module).ToList();
|
|
|
+ foreach(var ll in ventLLs)
|
|
|
{
|
|
|
- (_dictModuleTask[ll].Scheduler as SchedulerLoadLock).PreVent();
|
|
|
- preaparedLLs.Add(ll);
|
|
|
+ if (!schdVentingLLs.Contains(ll))
|
|
|
+ schdVentingLLs.Add(ll);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- lls = _tmSchdActions.Where(acs => ModuleHelper.IsLoadLock(acs.First().Module)).Select(item => item.First().Module).ToList();
|
|
|
- if(_curTmAction.Count == 0 && _tmSchdActions.Count > 0 && ModuleHelper.IsLoadLock(_tmSchdActions.First().First().Module))
|
|
|
- lls.Remove(_tmSchdActions.First().First().Module);
|
|
|
-
|
|
|
- foreach (var ll in lls)
|
|
|
+ if(_tmSchdActions.Count > 0)
|
|
|
{
|
|
|
- if (_dictModuleTask[ll].Scheduler.IsAvailable && _dictModuleTask[ll].Scheduler.IsAtm && !preaparedLLs.Contains(ll))
|
|
|
+ var pumpLLs = _tmSchdActions.Where(acs => ModuleHelper.IsLoadLock(acs.First().Module)).Select(item => item.First().Module).ToList();
|
|
|
+ foreach(var ll in pumpLLs)
|
|
|
{
|
|
|
- (_dictModuleTask[ll].Scheduler as SchedulerLoadLock).PrePump();
|
|
|
- preaparedLLs.Add(ll);
|
|
|
+ if (!schdPumpingLLs.Contains(ll))
|
|
|
+ schdPumpingLLs.Add(ll);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (_efemSchdActions.Count > 0 || _curEfemAction.Count > 0 || _tmSchdActions.Count > 0 || _curTmAction.Count > 0)
|
|
|
- return;
|
|
|
+ // loadlock in out path advance check
|
|
|
+ if (_LLInOutPath == SequenceLLInOutPath.AInBOut)
|
|
|
+ {
|
|
|
+ if(llaWaferStatus.emptySlot.Count == _LLASlotNumber)
|
|
|
+ {
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdVentingLLs.Add(ModuleName.LLA);
|
|
|
+ }
|
|
|
+ else if ((llaWaferStatus.inSlot.Count == _LLASlotNumber) ||
|
|
|
+ (llaWaferStatus.inSlot.Count > 0 && llaWaferStatus.inSlot.Count < _LLASlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsLoadPort(wt.currentMod) && ModuleHelper.IsPm(wt.destMod)) == 0))
|
|
|
+ {
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLA);
|
|
|
+ }
|
|
|
|
|
|
- if (LLInOutPath == SequenceLLInOutPath.AInBOut || LLInOutPath == SequenceLLInOutPath.BInAOut)
|
|
|
+ if(llbWaferStatus.emptySlot.Count == _LLBSlotNumber)
|
|
|
+ {
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLB))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLB);
|
|
|
+ }
|
|
|
+ else if ((llbWaferStatus.outSlot.Count == _LLBSlotNumber) ||
|
|
|
+ (llbWaferStatus.outSlot.Count > 0 && llbWaferStatus.outSlot.Count < _LLBSlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsPm(wt.currentMod)) == 0))
|
|
|
+ {
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLB))
|
|
|
+ schdCoolingLLs.Add(ModuleName.LLB);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(_LLInOutPath == SequenceLLInOutPath.BInAOut)
|
|
|
{
|
|
|
- var inLL = LLInOutPath == SequenceLLInOutPath.AInBOut ? ModuleName.LLA : ModuleName.LLB;
|
|
|
- var outLL = LLInOutPath == SequenceLLInOutPath.AInBOut ? ModuleName.LLB : ModuleName.LLA;
|
|
|
- var inLLWaferCount = _lstWaferTasks.Where(wafer => wafer.currentMod == inLL).Count();
|
|
|
- var outLLWaferCount = _lstWaferTasks.Where(wafer => wafer.currentMod == outLL).Count();
|
|
|
+ if (llbWaferStatus.emptySlot.Count == _LLBSlotNumber)
|
|
|
+ {
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdVentingLLs.Add(ModuleName.LLB);
|
|
|
+ }
|
|
|
+ else if ((llbWaferStatus.inSlot.Count == _LLBSlotNumber) ||
|
|
|
+ (llbWaferStatus.inSlot.Count > 0 && llbWaferStatus.inSlot.Count < _LLBSlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsLoadPort(wt.currentMod) && ModuleHelper.IsPm(wt.destMod)) == 0))
|
|
|
+ {
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLB))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLB);
|
|
|
+ }
|
|
|
|
|
|
- if (inLLWaferCount == 0 && !preaparedLLs.Contains(inLL))
|
|
|
+ if (llaWaferStatus.emptySlot.Count == _LLASlotNumber)
|
|
|
+ {
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLA);
|
|
|
+ }
|
|
|
+ else if ((llaWaferStatus.outSlot.Count == _LLASlotNumber) ||
|
|
|
+ (llaWaferStatus.outSlot.Count > 0 && llaWaferStatus.outSlot.Count < _LLASlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsPm(wt.currentMod)) == 0))
|
|
|
+ {
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdCoolingLLs.Add(ModuleName.LLA);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ((llaWaferStatus.inSlot.Count == _LLASlotNumber) ||
|
|
|
+ (llaWaferStatus.inSlot.Count > 0 && llaWaferStatus.inSlot.Count < _LLASlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsLoadPort(wt.currentMod) && ModuleHelper.IsPm(wt.destMod)) == 0))
|
|
|
{
|
|
|
- (_dictModuleTask[inLL] as LoadlockTask).PreVent();
|
|
|
- preaparedLLs.Add(inLL);
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLA);
|
|
|
}
|
|
|
- else if(inLLWaferCount == (LLInOutPath == SequenceLLInOutPath.AInBOut ? _LLASlotNumber : _LLBSlotNumber) && !preaparedLLs.Contains(inLL))
|
|
|
+ else if ((llaWaferStatus.outSlot.Count == _LLASlotNumber) ||
|
|
|
+ (llaWaferStatus.outSlot.Count > 0 && llaWaferStatus.outSlot.Count < _LLASlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsPm(wt.currentMod)) == 0))
|
|
|
{
|
|
|
- (_dictModuleTask[inLL] as LoadlockTask).PrePump();
|
|
|
- preaparedLLs.Add(inLL);
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLA))
|
|
|
+ schdCoolingLLs.Add(ModuleName.LLA);
|
|
|
}
|
|
|
|
|
|
- if(outLLWaferCount == 0 && !preaparedLLs.Contains(outLL))
|
|
|
+ if ((llbWaferStatus.inSlot.Count == _LLBSlotNumber) ||
|
|
|
+ (llbWaferStatus.inSlot.Count > 0 && llbWaferStatus.inSlot.Count < _LLBSlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsLoadPort(wt.currentMod) && ModuleHelper.IsPm(wt.destMod)) == 0))
|
|
|
{
|
|
|
- (_dictModuleTask[outLL] as LoadlockTask).PrePump();
|
|
|
- preaparedLLs.Add(outLL);
|
|
|
+ if (!schdPumpingLLs.Contains(ModuleName.LLB))
|
|
|
+ schdPumpingLLs.Add(ModuleName.LLB);
|
|
|
}
|
|
|
- else if(outLLWaferCount == (LLInOutPath == SequenceLLInOutPath.BInAOut ? _LLASlotNumber : _LLBSlotNumber) && !preaparedLLs.Contains(outLL))
|
|
|
+ else if ((llbWaferStatus.outSlot.Count == _LLBSlotNumber) ||
|
|
|
+ (llbWaferStatus.outSlot.Count > 0 && llbWaferStatus.outSlot.Count < _LLBSlotNumber && _lstWaferTasks.Count(wt => ModuleHelper.IsPm(wt.currentMod)) == 0))
|
|
|
{
|
|
|
- (_dictModuleTask[outLL] as LoadlockTask).PreVent();
|
|
|
- preaparedLLs.Add(outLL);
|
|
|
+ if (!schdVentingLLs.Contains(ModuleName.LLB))
|
|
|
+ schdCoolingLLs.Add(ModuleName.LLB);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ foreach(var ventLL in schdVentingLLs)
|
|
|
+ {
|
|
|
+ if (_dictModuleTask[ventLL].Scheduler.IsAvailable && !_dictModuleTask[ventLL].Scheduler.IsAtm)
|
|
|
+ (_dictModuleTask[ventLL].Scheduler as SchedulerLoadLock).PreVent();
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach(var pumpLL in schdPumpingLLs)
|
|
|
+ {
|
|
|
+ if (_dictModuleTask[pumpLL].Scheduler.IsAvailable && !_dictModuleTask[pumpLL].Scheduler.IsVac && !schdVentingLLs.Contains(pumpLL))
|
|
|
+ (_dictModuleTask[pumpLL].Scheduler as SchedulerLoadLock).PrePump();
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach(var coolLL in schdCoolingLLs)
|
|
|
+ {
|
|
|
+ if (_dictModuleTask[coolLL].Scheduler.IsOnline && !_dictModuleTask[coolLL].Scheduler.IsAtm)
|
|
|
+ (_dictModuleTask[coolLL].Scheduler as SchedulerLoadLock).SubscribeCoolingTask();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void ReturnVacWafers()
|