Browse Source

enhance manual return wafer algorithm.

sangwq 1 year ago
parent
commit
a80b5af3fd

+ 3 - 18
Venus/Framework/Common/Utilities/Singleton.cs

@@ -8,23 +8,8 @@ namespace Aitex.Core.Util
     [Serializable]
     public class Singleton<T> where T : class, new()
     {
-        private static volatile T instance;
-        private static object locker = new Object();
-        public Singleton() { }
-
-        public static T Instance
-        {
-            get
-            {
-                if (instance == null)
-                {
-                    lock (locker)
-                    {
-                        if (instance == null) instance = new T();
-                    }
-                }
-                return instance;
-            }
-        }
+        private static readonly Lazy<T> lazy =
+                                        new Lazy<T>(() => new T(), true);
+        public static T Instance => lazy.Value;
     } 
 }

+ 291 - 17
Venus/Venus_RT/Modules/AutoCycle.cs

@@ -776,9 +776,9 @@ namespace Venus_RT.Modules
             return false;
         }
 
-        List<int> GetModuleValidSlots(ModuleName mod)
+        Queue<int> GetModuleValidSlots(ModuleName mod)
         {
-            var validSlot = new List<int>();
+            var validSlot = new Queue<int>();
             if (ModuleHelper.IsLoadLock(mod))
             {
                 if (!IsLoadLockReservedByEFEM(mod))
@@ -787,23 +787,23 @@ namespace Venus_RT.Modules
                     foreach (var slot in inSlots)
                     {
                         if (WaferManager.Instance.CheckNoWafer(mod, slot) && !_movingItems.Exists(item => item.DestinationModule == mod && item.DestinationSlot == slot))
-                            validSlot.Add(slot);
+                            validSlot.Enqueue(slot);
 
                         if (WaferManager.Instance.CheckHasWafer(mod, slot) && _movingItems.Exists(item => item.SourceModule == mod && item.SourceSlot == slot))
-                            validSlot.Add(slot);
+                            validSlot.Enqueue(slot);
                     }
                 }
             }
             else if (ModuleHelper.IsPm(mod))
             {
                 if (WaferManager.Instance.CheckNoWafer(mod, 0) && !_movingItems.Exists(item => item.DestinationModule == mod))
-                    validSlot.Add(0);
+                    validSlot.Enqueue(0);
 
                 if (WaferManager.Instance.CheckHasWafer(mod, 0) && _movingItems.Exists(item => item.SourceModule == mod))
-                    validSlot.Add(0);
+                    validSlot.Enqueue(0);
             }
 
-            return validSlot.Distinct().ToList();
+            return validSlot;
         }
 
         private int GetModuleSlotCount(ModuleName mod)
@@ -848,10 +848,8 @@ namespace Venus_RT.Modules
                     {
                         if (!inSlots.Exists(item => item.SourceModule == slot.Key.Module && item.SourceSlot == slot.Key.Slot))
                         {
-                            inSlots.Add(new MoveItem(slot.Key.Module, slot.Key.Slot, inModule, validSlots.First(), Hand.None));
+                            inSlots.Add(new MoveItem(slot.Key.Module, slot.Key.Slot, inModule, validSlots.Dequeue(), Hand.None));
                         }
-
-                        validSlots.RemoveAt(0);
                     }
                 }
             }
@@ -1788,7 +1786,7 @@ namespace Venus_RT.Modules
             List<ModuleName> usedPMs = GetPmUsedInRunningPj();
             foreach (var module in _vacModules)
             {
-                if (ModuleHelper.IsPm(module.Key) && _vacSchedulers[module.Key].IsOnline && usedPMs.Contains(module.Key))
+                if (ModuleHelper.IsPm(module.Key) && ((_vacSchedulers[module.Key].IsOnline && usedPMs.Contains(module.Key)) || _cycleState == RState.End ))
                 {
                     if (WaferManager.Instance.CheckHasWafer(module.Key, 0))
                         exist++;
@@ -1873,7 +1871,7 @@ namespace Venus_RT.Modules
 
         private bool IsLoadLockReadyForEFEMManualMove(ModuleName ll)
         {
-            return (_vacSchedulers[ll].IsIdle && !_vacSchedulers[ll].IsOnline) || (_vacSchedulers[ll].IsAvailable && _vacModules[ll].MovingStatus == MovingStatus.Idle && !IsLoadLockReservedByTM(ll));
+            return ((_vacSchedulers[ll].IsIdle && !_vacSchedulers[ll].IsOnline) || _vacSchedulers[ll].IsAvailable) && _vacModules[ll].MovingStatus == MovingStatus.Idle && !IsLoadLockReservedByTM(ll);
         }
 
         private bool IsPMKeepEmpty(ModuleName pm)
@@ -1930,7 +1928,6 @@ namespace Venus_RT.Modules
         {
             int processedCount = 0;
             int unprocessCount = 0;
-            int empty = 0;
             int slotCount = ll == ModuleName.LLA ? _LLASlotNumber : _LLBSlotNumber;
             if (ModuleHelper.IsLoadLock(ll))
             {
@@ -2500,7 +2497,7 @@ namespace Venus_RT.Modules
                 foreach (var tar in tars)
                 {
                     var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
-                    if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
+                    if (wafer.IsEmpty || wafer.InnerId.ToString().Length < 10)
                         continue;
 
                     if (wafer.InnerId == tar.Value && _tmRobot.RobotStatus != RState.Running)
@@ -2550,12 +2547,12 @@ namespace Venus_RT.Modules
             {
                 foreach (var item in _movingItems)
                 {
-                    if (_vacModules[item.DestinationModule].MovingStatus == MovingStatus.Moving)
+                    if (!ModuleHelper.IsTMRobot(item.DestinationModule) && _vacModules[item.DestinationModule].MovingStatus == MovingStatus.Moving)
                     {
                         _vacModules[item.DestinationModule].MovingStatus = MovingStatus.Idle;
                     }
 
-                    if (_vacModules[item.SourceModule].MovingStatus == MovingStatus.Moving)
+                    if (!ModuleHelper.IsTMRobot(item.SourceModule) && _vacModules[item.SourceModule].MovingStatus == MovingStatus.Moving)
                     {
                         _vacModules[item.SourceModule].MovingStatus = MovingStatus.Idle;
                     }
@@ -2572,7 +2569,7 @@ namespace Venus_RT.Modules
                 foreach (var tar in tars)
                 {
                     var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
-                    if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
+                    if (wafer.IsEmpty || wafer.InnerId.ToString().Length < 10)
                         continue;
 
                     if (wafer.InnerId == tar.Value && _efemRobot.RobotStatus != RState.Running)
@@ -3175,5 +3172,282 @@ namespace Venus_RT.Modules
         }
 
         #endregion
+
+        #region Manual Return All Wafer
+        public RState CheckManualReturnWafer()
+        {
+            if(!_tmRobot.IsIdle && (GetPMWaferExistence().exist + GetTMRobotWaferCount() > 0))
+            {
+                LOG.Write(eEvent.ERR_ROUTER, ModuleName.TMRobot, $"The TM Robot is not ready for return wafer.");
+                return RState.Failed;
+            }
+
+            if (!_efemRobot.IsIdle)
+            {
+                LOG.Write(eEvent.ERR_ROUTER, ModuleName.EfemRobot, $"The EFEM Robot is not ready for return wafer.");
+                return RState.Failed;
+            }
+
+            var schedulers = _vacSchedulers.Concat(_atmSchedulers);
+            foreach(var mod in schedulers)
+            {
+                if (ModuleHelper.IsLoadPort(mod.Key))
+                    continue;
+
+                int nSlotNumber = ModuleHelper.IsLoadLock(mod.Key) ? (mod.Key == ModuleName.LLA ? _LLASlotNumber : _LLBSlotNumber) : (ModuleHelper.IsTMRobot(mod.Key) || ModuleHelper.IsEFEMRobot(mod.Key) ? 2 : 1);
+                for(int slot = 0; slot < nSlotNumber; slot++)
+                {
+                    var wafer = WaferManager.Instance.GetWafer(mod.Key, slot);
+                    if (wafer.IsEmpty)
+                        continue;
+
+                    if(!mod.Value.IsIdle)
+                    {
+                        LOG.Write(eEvent.ERR_ROUTER, mod.Key, $"{mod.Key} is not ready for return wafer.");
+                        return RState.Failed;
+                    }
+
+                    var destLP = (ModuleName)wafer.OriginStation;
+                    if(!_atmSchedulers[destLP].IsAvailable)
+                    {
+                        LOG.Write(eEvent.ERR_ROUTER, destLP, $"The destination Loadport {destLP} is not ready for return wafer.");
+                        return RState.Failed;
+                    }
+                }
+            }
+
+            Clear();
+            return RState.Running;
+        }
+
+        public RState ReturnAllWafers()
+        {
+            var llaWaferStatus = GetLLProcessStatusCount(ModuleName.LLA);
+            var llbWaferStatus = GetLLProcessStatusCount(ModuleName.LLB);
+            var pmWaferStatus = GetPMWaferExistence();
+            if (pmWaferStatus.exist + (_LLASlotNumber - llaWaferStatus.empty) + (_LLBSlotNumber - llbWaferStatus.empty) + GetTMRobotWaferCount() + GetAtmInerWaferCount() + GetEfemRoborWaferCount() == 0)
+            {
+                Clear();
+                return RState.End;
+            }
+
+            ReturnAtmWafers();
+            ReturnVacWafers();
+            CheckReturnWafersArrived();
+
+            return RState.Running;
+        }
+
+        private void ReturnVacWafers()
+        {
+            if(_tmRobot.IsAvailable && _tmRobot.RobotStatus != RState.Running && _movingItems.Count == 0)
+            {
+                var tmRobotWaferCount = GetTMRobotWaferCount();
+                if(tmRobotWaferCount > 0 || GetPMWaferExistence().exist > 0)
+                {
+                    var llaWaferStatus = GetLLProcessStatusCount(ModuleName.LLA);
+                    var llbWaferStatus = GetLLProcessStatusCount(ModuleName.LLB);
+
+                    if (IsLoadReadyForTM(ModuleName.LLA) && llaWaferStatus.empty > 0 && (!IsLoadReadyForTM(ModuleName.LLB) || (!_vacSchedulers[ModuleName.LLB].IsVac && llaWaferStatus.empty == llbWaferStatus.empty) || llaWaferStatus.empty > llbWaferStatus.empty))
+                    {
+                        if (tmRobotWaferCount > 0)
+                            ReturnTMRobotWafersToLL(ModuleName.LLA);
+                        else
+                            ReturnPMWafersToLL(ModuleName.LLA);
+                    }
+                    else if (IsLoadReadyForTM(ModuleName.LLB) && llbWaferStatus.empty > 0)
+                    {
+                        if (tmRobotWaferCount > 0)
+                            ReturnTMRobotWafersToLL(ModuleName.LLB);
+                        else
+                            ReturnPMWafersToLL(ModuleName.LLB);
+                    }
+                }
+
+                RuningTMRobotTask();
+            }
+        }
+
+        private void ReturnAtmWafers()
+        {
+            if(_efemRobot.IsAvailable && _efemRobot.RobotStatus != RState.Running && _efemMovingItems.Count == 0)
+            {
+                var aligners = _atmSchedulers.Where(x => ModuleHelper.IsAligner(x.Key) && x.Value.IsAvailable && WaferManager.Instance.CheckHasWafer(x.Key, 0)).ToDictionary(k => k.Key, v => v.Value);
+                var lls = _vacSchedulers.Where(x => ModuleHelper.IsLoadLock(x.Key) && IsLoadLockReadyForEFEMManualMove(x.Key) && GetLLProcessStatusCount(x.Key).processed + GetLLProcessStatusCount(x.Key).unprocessed > 0).ToDictionary(k => k.Key, v => v.Value);
+                if (GetEfemRoborWaferCount() > 0)
+                {
+                    for(int slot = 0; slot < 2; slot++)
+                    {
+                        var wafer = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, slot);
+                        if(!wafer.IsEmpty)
+                        {
+                            _efemMovingItems.Add(new MoveItem(ModuleName.EfemRobot, slot, (ModuleName)wafer.OriginStation, wafer.OriginSlot, (Hand)slot));
+                        }
+                    }
+                }
+                else if(aligners.Count > 0)
+                {
+                    foreach(var align in aligners)
+                    {
+                        var wafer = WaferManager.Instance.GetWafer(align.Key, 0);
+                        var hand = GetEFEMRobotFreeHand();
+                        if (!wafer.IsEmpty && hand != Hand.None)
+                        {
+                            _efemMovingItems.Add(new MoveItem(align.Key, 0, ModuleName.EfemRobot, (int)hand, hand));
+                        }
+                    }
+                }
+                else if(lls.Count > 0)
+                {
+                    ModuleName source = lls.First().Key;
+                    if(lls.Count > 1)
+                    {
+                        if (GetLLProcessStatusCount(ModuleName.LLB).empty < GetLLProcessStatusCount(ModuleName.LLA).empty)
+                            source = ModuleName.LLB;
+                        else
+                            source = ModuleName.LLA;
+                    }
+
+                    int slotNumber = source == ModuleName.LLA ? _LLASlotNumber : _LLBSlotNumber;
+
+                    for(int i = 0; i < slotNumber; i++)
+                    {
+                        var wafer = WaferManager.Instance.GetWafer(source, i);
+                        var hand = GetEFEMRobotFreeHand();
+                        if (!wafer.IsEmpty && hand != Hand.None)
+                        {
+                            _efemMovingItems.Add(new MoveItem(source, i, ModuleName.EfemRobot, (int)hand, hand));
+                        }
+                    }
+                }
+
+                RuningEFEMRobotTask();
+            }
+        }
+
+        private void ReturnPMWafersToLL(ModuleName ll)
+        {
+            var validSlots = GetModuleValidSlots(ll);
+            foreach(var pm in _vacSchedulers)
+            {
+                if (!ModuleHelper.IsPm(pm.Key))
+                    continue;
+
+                if(pm.Value.IsIdle && WaferManager.Instance.CheckHasWafer(pm.Key, 0) && validSlots.Count > 0)
+                {
+                    _movingItems.Add(new MoveItem( pm.Key, 0, ll, validSlots.Dequeue(), Hand.None));
+                    if (_movingItems.Count >= 2)
+                        return;
+                }
+            }
+        }
+
+        private void ReturnTMRobotWafersToLL(ModuleName ll)
+        {
+            var validSlots = GetModuleValidSlots(ll);
+            for(int slot = 0; slot < 2; slot++)
+            {
+                if(WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, slot))
+                {
+                    _movingItems.Add(new MoveItem(ModuleName.TMRobot, slot, ll, validSlots.Dequeue(), (Hand)slot));
+                }
+            }
+        }
+
+        private void CheckReturnWafersArrived()
+        {
+            foreach (var mod in _vacSchedulers.Append(new KeyValuePair<ModuleName, SchedulerModule>(ModuleName.TMRobot, _tmRobot)))
+            {
+                var tars = _vacWaferTargets.Where(item => item.Key.Module == mod.Key).ToArray();
+                foreach (var tar in tars)
+                {
+                    var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
+                    if (wafer.IsEmpty || wafer.InnerId.ToString().Length < 10)
+                        continue;
+
+                    if (wafer.InnerId == tar.Value && _tmRobot.RobotStatus != RState.Running)
+                    {
+                        // wafer arrive
+                        _vacWaferTargets.Remove(tar.Key);
+                    }
+                }
+
+                if (ModuleHelper.IsLoadLock(mod.Key))
+                {
+                    if (!IsLoadLockReservedByTM(mod.Key) && mod.Value.IsAvailable)
+                    {
+                        _vacModules[mod.Key].MovingStatus = MovingStatus.Idle;
+                    }
+                }
+            }
+
+            _vacMoveFinishTrig.CLK = _vacWaferTargets.Count == 0 && _tmRobot.RobotStatus != RState.Running;
+            if (_vacMoveFinishTrig.Q)
+            {
+                foreach (var item in _movingItems)
+                {
+                    if (!ModuleHelper.IsTMRobot(item.DestinationModule) && _vacModules[item.DestinationModule].MovingStatus == MovingStatus.Moving)
+                    {
+                        _vacModules[item.DestinationModule].MovingStatus = MovingStatus.Idle;
+                    }
+
+                    if (!ModuleHelper.IsTMRobot(item.SourceModule) && _vacModules[item.SourceModule].MovingStatus == MovingStatus.Moving)
+                    {
+                        _vacModules[item.SourceModule].MovingStatus = MovingStatus.Idle;
+                    }
+                }
+
+
+                _movingItems.Clear();
+            }
+
+
+            foreach (var mod in _atmSchedulers.Append(new KeyValuePair<ModuleName, SchedulerModule>(ModuleName.EfemRobot, _efemRobot)))
+            {
+                var tars = _atmWaferTargets.Where(item => item.Key.Module == mod.Key).ToArray();
+                foreach (var tar in tars)
+                {
+                    var wafer = WaferManager.Instance.GetWafer(tar.Key.Module, tar.Key.Slot);
+                    if (wafer.IsEmpty || wafer.InnerId.ToString().Length < 10)
+                        continue;
+
+                    if (wafer.InnerId == tar.Value && _efemRobot.RobotStatus != RState.Running)
+                    {
+
+                        if (!ModuleHelper.IsLoadPort(tar.Key.Module) && !ModuleHelper.IsEFEMRobot(tar.Key.Module))
+                            _atmSchedulers[tar.Key.Module].WaferArrived(tar.Key.Slot);
+
+                        _atmWaferTargets.Remove(tar.Key);
+
+                        if (ModuleHelper.IsAligner(tar.Key.Module))
+                        {
+                            _atmModules[tar.Key.Module].MovingStatus = MovingStatus.WaitAlign;
+                        }
+                    }
+                }
+
+                if (ModuleHelper.IsLoadLock(mod.Key))
+                {
+                    if (!IsLoadLockReservedByEFEM(mod.Key) && mod.Value.IsAvailable)
+                    {
+                        _vacModules[mod.Key].MovingStatus = MovingStatus.Idle;
+                    }
+                }
+            }
+
+            if (_atmWaferTargets.Count == 0 && _efemRobot.RobotStatus != RState.Running && _efemMovingItems.Count > 0)
+            {
+                foreach (var item in _efemMovingItems)
+                {
+                    if (ModuleHelper.IsLoadLock(item.Module))
+                    {
+                        _vacModules[item.Module].MovingStatus = MovingStatus.Idle;
+                    }
+                }
+
+                _efemMovingItems.Clear();
+            }
+        }
+        #endregion
     }
 }

+ 4 - 2
Venus/Venus_RT/Modules/RouteManager.cs

@@ -945,12 +945,14 @@ namespace Venus_RT.Modules
 
         private bool FsmStartReturnWafer(object[] objs)
         {
-            return _returnWafer.Start(objs) == RState.Running;
+            //return _returnWafer.Start(objs) == RState.Running;
+            return _AutoCycle.CheckManualReturnWafer() == RState.Running;
         }
 
         private bool FsmMonitorReturnWafer(object[] objs)
         {
-            RState ret = _returnWafer.Monitor();
+            //RState ret = _returnWafer.Monitor();
+            RState ret = _AutoCycle.ReturnAllWafers();
             if (ret == RState.Failed || ret == RState.Timeout)
             {
                 PostMsg(MSG.ERROR);