瀏覽代碼

New routing algorithm for cooling function.

sangwq 9 月之前
父節點
當前提交
0c9d2dbd96
共有 2 個文件被更改,包括 346 次插入267 次删除
  1. 61 2
      Venus/Venus_RT/Modules/Schedulers/SchedulerLoadLock.cs
  2. 285 265
      Venus/Venus_RT/Modules/SystemDispatcher.cs

+ 61 - 2
Venus/Venus_RT/Modules/Schedulers/SchedulerLoadLock.cs

@@ -11,6 +11,7 @@ using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.Schedulers;
 using MECF.Framework.Common.SubstrateTrackings;
 using Venus_RT.Scheduler;
+using Venus_Core;
 
 namespace Venus_RT.Modules.Schedulers
 {
@@ -23,12 +24,10 @@ namespace Venus_RT.Modules.Schedulers
         public override bool IsOnline
         {
             get { return _entity.IsOnline; }
-
         }
         public override bool IsError
         {
             get { return _entity.IsError; }
-
         }
 
         public override bool IsIdle
@@ -53,6 +52,15 @@ namespace Venus_RT.Modules.Schedulers
         }
 
         private LLEntity _entity = null;
+
+        enum CoolingState
+        {
+            Init,
+            Start,
+            Cooling,
+            End,
+        }
+        private CoolingState _coolingState =  CoolingState.End;
         public SchedulerLoadLock(ModuleName module) : base(module.ToString())
         {
             _entity = Singleton<RouteManager>.Instance.GetLL(module);
@@ -60,9 +68,48 @@ namespace Venus_RT.Modules.Schedulers
 
         private bool CheckTaskDone()
         {
+            if (Singleton<RouteManager>.Instance.IsAutoMode)
+            {
+                if(IsOnline && IsInclude)
+                {
+                    if (IsIdle)
+                    {
+                        switch(_coolingState)
+                        {
+                            case CoolingState.Init:
+                                {
+                                    if(_entity.Invoke(LLEntity.MSG.AutoCooling.ToString()) == (int)LLEntity.MSG.AutoCooling)
+                                    {
+                                        _coolingState =  CoolingState.Start;
+                                    }
+                                }
+                                break;
+                            case CoolingState.Cooling:
+                                _coolingState = CoolingState.End;
+                                break;
+                        }
+                    }
+                    else
+                    {
+                        switch(_coolingState)
+                        {
+                            case CoolingState.Start:
+                                _coolingState = CoolingState.Cooling;
+                                break; ;
+                        }
+                    }
+                }
+            }
+
             return true;
         }
 
+        public override void ResetTask()
+        {
+            _coolingState = CoolingState.End;
+            base.ResetTask();
+        }
+
         public List<int> GetOrderedOutSlot()
         {
             return  WaferArriveTicks.OrderBy(item => item.Value).ToDictionary(k => k.Key, v => v.Value).Keys.ToList();
@@ -75,7 +122,19 @@ namespace Venus_RT.Modules.Schedulers
 
         public bool PrePump()
         {
+            _coolingState = CoolingState.End;
             return _entity.Invoke(LLEntity.MSG.Pump.ToString()) == (int)LLEntity.MSG.Pump;
         }
+
+        public bool SubscribeCoolingTask()
+        {
+            if (!IsAtm)
+            {
+                if (_coolingState == CoolingState.End)
+                    _coolingState = CoolingState.Init;
+            }
+
+            return true;
+        }
     }
 }

+ 285 - 265
Venus/Venus_RT/Modules/SystemDispatcher.cs

@@ -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()