using System; using System.Collections.Generic; using System.Linq; using Aitex.Core.Common; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.ModuleLibrary.SystemModules; using EfemDualSchedulerLib.Schedulers; using Aitex.Core.Util; namespace EfemDualSchedulerLib { public class ReturnAllWafer : SchedulerModuleFactory, IRoutine { private bool _needCooling; private int _coolingTime; Dictionary _checkPosition = new Dictionary() { {ModuleName.EfemRobot, 2}, {ModuleName.Aligner1, 1}, {ModuleName.Aligner2, 1}, {ModuleName.Cooling1, 1}, {ModuleName.Cooling2, 1}, {ModuleName.LLA, 8}, {ModuleName.LLB, 8}, {ModuleName.TMRobot, 2}, {ModuleName.PMA, 2}, {ModuleName.PMB, 2}, }; private List _lstPms = new List(); private List _lstLps = new List(); private List _lstLls = new List(); private List _lstAligners = new List(); private List _lstCoolings = new List(); private R_TRIG _trigLLReturnWafer = new R_TRIG(); private R_TRIG _trigLLNoInstall = new R_TRIG(); Queue tmRobotActions = new Queue() { }; public ReturnAllWafer(EquipmentManager equipment) : base() { _checkPosition.Where(p => p.Key != ModuleName.EfemRobot && p.Key != ModuleName.TMRobot && !SC.GetValueOrDefault($"System.SetUp.{p.Key.ToString()}.IsInstalled")) .ToList().ForEach(p => _checkPosition.Remove(p.Key)); if (_checkPosition.ContainsKey(ModuleName.TMRobot) && SC.IsDoubleFork) _checkPosition[ModuleName.TMRobot] = 4; if (SC.GetValueOrDefault("System.SetUp.PMA.IsInstalled")) _lstPms.Add(_pm1); if (SC.GetValueOrDefault("System.SetUp.PMB.IsInstalled")) _lstPms.Add(_pm2); //if (SC.GetValueOrDefault("System.SetUp.PMC.IsInstalled")) // _lstPms.Add(_pm3); if (SC.GetValueOrDefault("System.SetUp.LLA.IsInstalled")) _lstLls.Add(_loadlockA); if (SC.GetValueOrDefault("System.SetUp.LLB.IsInstalled")) _lstLls.Add(_loadlockB); if (SC.GetValueOrDefault("System.SetUp.Aligner1.IsInstalled")) _lstAligners.Add(_aligner1); if (SC.GetValueOrDefault("System.SetUp.Aligner2.IsInstalled")) _lstAligners.Add(_aligner2); if (SC.GetValueOrDefault("System.SetUp.Cooling1.IsInstalled")) _lstCoolings.Add(_cooling1); if (SC.GetValueOrDefault("System.SetUp.Cooling2.IsInstalled")) _lstCoolings.Add(_cooling2); if (SC.GetValueOrDefault("System.SetUp.LP1.IsInstalled")) _lstLps.Add(_lp1); if (SC.GetValueOrDefault("System.SetUp.LP2.IsInstalled")) _lstLps.Add(_lp2); if (SC.GetValueOrDefault("System.SetUp.LP3.IsInstalled")) _lstLps.Add(_lp3); tmRobotActions.Enqueue(MonitorTMRobotPMATask); tmRobotActions.Enqueue(MonitorTMRobotPMBTask); tmRobotActions.Enqueue(MonitorTMRobotLoadLockTask); } public Result Start(params object[] objs) { if (objs.Length > 1) { _needCooling = (bool)objs[0]; _coolingTime = (int)objs[1] > 1 ? (int)objs[1] : 1; } foreach (var positions in _checkPosition) { for (int i = 0; i < positions.Value; i++) { WaferInfo wafer = WaferManager.Instance.GetWafer(positions.Key, i); if (!wafer.IsEmpty) { ModuleName originLoadPort = (ModuleName)wafer.OriginStation; if (!ModuleHelper.IsLoadPort(originLoadPort)) { EV.PostWarningLog("System", $"Wafer {positions.Key}.{i + 1} can not return, origin is not LP"); return Result.FAIL; } if (wafer.Status == WaferStatus.Dummy) { EV.PostWarningLog("System", $"Wafer {positions.Key}.{i + 1} can not return, wafer is dummy"); return Result.FAIL; } if (WaferManager.Instance.CheckHasWafer(originLoadPort, wafer.OriginSlot)) { EV.PostWarningLog("System", $"Wafer {positions.Key}.{i + 1} can not return, origin has wafer"); return Result.FAIL; } if (!(GetModule(originLoadPort.ToString()) as SchedulerLoadPort).IsReadyForPlace(ModuleName.EfemRobot, Hand.Blade1, wafer.OriginSlot)) { EV.PostWarningLog("System", $"{originLoadPort} not ready to place Wafer"); return Result.FAIL; } EV.PostInfoLog("System", $"Wafer return, {positions.Key}.{i + 1}=>{(ModuleName)wafer.OriginStation}.{wafer.OriginSlot + 1}"); } } } _trigLLReturnWafer.RST = true; _trigLLNoInstall.RST = true; return Result.RUN; } public Result Monitor() { MonitorModuleTasks(); if (MonitorTaskDone()) { return Result.DONE; } return Result.RUN; } public void Clear() { } public void Abort() { _tmRobot?.ResetTask(); _efem?.ResetTask(); foreach (var pm in _lstPms) { pm.ResetTask(); } foreach (var lp in _lstLps) { lp.ResetTask(); } } public Result MonitorModuleTasks() { MonitorPMTask(); MonitorLoadLockTask(); MonitorCoolingTask(); MonitorTMRobotTask(); MonitorEfemRobotTask(); return Result.RUN; } private void MonitorTMRobotTask() { if (!_tmRobot.IsAvailable) return; //_tmRobot is idle, release all the target foreach (var ll in _lstLls) { if (ll.IsWaitTransfer(ModuleName.TMRobot)) ll.StopWaitTransfer(ModuleName.TMRobot); } foreach (var pm in _lstPms) { if (pm.IsWaitTransfer(ModuleName.TMRobot)) pm.StopWaitTransfer(ModuleName.TMRobot); } if (!_tmRobot.IsAvailable) return; var act = tmRobotActions.Peek(); act.Invoke(); if (!_tmRobot.IsAvailable) return; if (act == MonitorTMRobotLoadLockTask && _lstLls.Any(x => !x.IsAvailable)) return; tmRobotActions.Enqueue(tmRobotActions.Dequeue()); //MonitorTMRobotPMATask(); //if (!_tmRobot.IsAvailable) // return; //MonitorTMRobotPMBTask(); //if (!_tmRobot.IsAvailable) // return; //MonitorTMRobotLoadLockTask(); } private bool CheckReturnWaferByModule(ModuleName currentName) { var bufferIndex = SC.GetValueOrDefault("System.Scheduler.ReturnWaferPath"); const int enumOffset = 29; if (bufferIndex > 0) { ModuleName targetModule = (ModuleName)Enum.Parse(typeof(ModuleName), (bufferIndex + enumOffset).ToString()); _trigLLNoInstall.CLK = !SC.GetValueOrDefault($"System.SetUp.{targetModule}.IsInstalled"); if (_trigLLNoInstall.Q) { EV.PostWarningLog("System", $"Wafer can not return by {targetModule}, because of the {targetModule} is not installed"); } if (_trigLLNoInstall.CLK) { return false; } _trigLLReturnWafer.CLK = targetModule != currentName; if(_trigLLReturnWafer.Q && !_lstLls.Any(p => p.Module == targetModule)) { EV.PostWarningLog("System", $"Wafer can not return by {currentName}, because of the {currentName} is not set up "); } if(_trigLLReturnWafer.CLK) { return false; } } return true; } private void MonitorTMRobotLoadLockTask() { if (!_tmRobot.IsAvailable) return; if (SC.IsDoubleFork && _lstLls.Any(x => !x.IsAvailable)) return; //place to loadlock { bool blade1HasWafer = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)); bool blade2HasWafer = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)); if (blade1HasWafer || blade2HasWafer) { Hand placeBlade = blade1HasWafer ? Hand.Blade1 : Hand.Blade2; foreach (var ll in _lstLls) { if (!ll.IsAvailable) continue; if (!CheckReturnWaferByModule(ll.Module)) continue; var slots = GetSlotCouldBePlace(ll, placeBlade); if (slots != null && slots.Length > 0 ) { if (_tmRobot.Place(ll.Module, Converter.MapPanToLLSlot(Converter.GetPanAndSlotFromPlace(placeBlade).Item1, slots), placeBlade, Converter.GetPanAndSlotFromPlace(placeBlade).Item1, 0, 0, false)) { if (SC.IsDoubleFork) _lstLls.All(p => p.WaitTransfer(ModuleName.TMRobot)); else ll.WaitTransfer(ModuleName.TMRobot); return; } } } } } } private void MonitorTMRobotPMATask() { if (!_tmRobot.IsAvailable) return; //pick from pm { bool blade1Empty = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p=> WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)); bool blade2Empty = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p=> WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)); if (blade1Empty || blade2Empty) { Hand pickBlade = blade1Empty ? Hand.Blade1 : Hand.Blade2; //foreach (var pm in _lstPms) { var pm = _pm1; if (!pm.IsAvailable) return; var slot = GetWaferCouldBeReturn(pm.Module); if (slot != null && slot.Length>0 /*&& pm.IsReadyForPick(ModuleName.TMRobot, pickBlade, (int)slot)*/) { if (_tmRobot.Pick(pm.Module, slot, pickBlade, Converter.GetPanAndSlotFromPick(pickBlade,slot).Item1, 0, 0, false)) { pm.WaitTransfer(ModuleName.TMRobot); return; } } } } } } private void MonitorTMRobotPMBTask() { if (!_tmRobot.IsAvailable) return; //pick from pm { bool blade1Empty = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p=> WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)); bool blade2Empty = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)); if (blade1Empty || blade2Empty) { Hand pickBlade = blade1Empty ? Hand.Blade1 : Hand.Blade2; //foreach (var pm in _lstPms) { var pm = _pm2; if (!pm.IsAvailable) return; var slot = GetWaferCouldBeReturn(pm.Module); if (slot != null && slot.Length > 0 /*&& pm.IsReadyForPick(ModuleName.TMRobot, pickBlade, (int)slot)*/) { if (_tmRobot.Pick(pm.Module, slot, pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, slot).Item1, 0, 0, false)) { pm.WaitTransfer(ModuleName.TMRobot); return; } } } } } } private bool MonitorTaskDone() { foreach (var positions in _checkPosition) { for (int i = 0; i < positions.Value; i++) { if (CheckWaferCouldBeReturn(positions.Key, i)) { return false; } } } foreach (var lp in _lstLps) { if (!lp.IsAvailable) return false; } if (!_tmRobot.IsAvailable) return false; if (!_efem.IsAvailable) return false; return true; } private void MonitorPMTask() { // foreach (var pm in _lstPms) // { // if (!pm.IsAvailable) // continue; // var wafers = WaferManager.Instance.GetWafers(pm.Module); // for (int i = 0; i < wafers.Length; i++) // { // if (!pm.IsAvailable) // break; // if (CheckWaferCouldBeReturn(pm.Module, i)) // { // if (!pm.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)) // { // pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, i); // } // } // } // } } private void MonitorLoadLockTask() { foreach (var ll in _lstLls) { if (!ll.IsAvailable) continue; var wafers = WaferManager.Instance.GetWafers(ll.Module); for (int i = 0; i < wafers.Length; i++) { var wafer = wafers[i]; if (!wafer.IsEmpty && wafer.NextStation != (int)ModuleName.LoadLock && ll.PostTransfer(ll.Module,EnumTransferType.Place,i)) { wafer.NextStation = (int)ModuleName.LoadLock; } } } } private void MonitorCoolingTask() { foreach (var cooling in _lstCoolings) { if (!cooling.IsAvailable) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(cooling.Module, 0); if (wafer.NextStation != (int)ModuleName.Cooling) { //int coolingTime = SC.GetValueOrDefault("System.DefaultCoolingTime"); if (cooling.Cooling(_coolingTime)) { wafer.NextStation = (int)ModuleName.Cooling; } } } } private void MonitorEfemRobotTask() { if (!_efem.IsAvailable) return; //efem robot is idle, release all the target foreach (var ll in _lstLls) { if (ll.IsWaitTransfer(ModuleName.EfemRobot)) ll.StopWaitTransfer(ModuleName.EfemRobot); } foreach (var al in _lstAligners) { if (al.IsWaitTransfer(ModuleName.EfemRobot)) al.StopWaitTransfer(ModuleName.EfemRobot); } foreach (var bf in _lstCoolings) { if (bf.IsWaitTransfer(ModuleName.EfemRobot)) bf.StopWaitTransfer(ModuleName.EfemRobot); } foreach (var lp in _lstLps) { if (lp.IsWaitTransfer(ModuleName.EfemRobot)) lp.StopWaitTransfer(ModuleName.EfemRobot); } MonitorEfemRobotAlignerTask(); if (!_efem.IsAvailable) return; MonitorEfemRobotLoadLockTask(); MonitorEfemRobotCoolingTask(); MonitorEfemRobotLoadPortTask(); } private void MonitorEfemRobotLoadPortTask() { if (!_efem.IsAvailable) return; //place bool blade0HasWaferAndProcessed = _efem.Blade1Enable && CheckWaferCouldBeReturn(ModuleName.EfemRobot, 0); bool blade1HasWaferAndProcessed = _efem.Blade2Enable && CheckWaferCouldBeReturn(ModuleName.EfemRobot, 1); if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed) { Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2; if (blade0HasWaferAndProcessed && blade1HasWaferAndProcessed) { if (WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginSlot < WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginSlot) { placeBlade = Hand.Blade2; } } if (_needCooling && WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).NextStation != (int)ModuleName.Cooling) return; SlotItem destination = GetWaferReturnLoadPort(ModuleName.EfemRobot, (int)placeBlade); if (destination != null) { SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(destination.Module.ToString()); if (lp.IsReadyForPlace(ModuleName.EfemRobot, Hand.Blade1, destination.Slot)) { if (_efem.Place(destination.Module, destination.Slot, placeBlade)) { WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).NextStation = (int)ModuleName.System; lp.WaitTransfer(ModuleName.EfemRobot); return; } } } } } private void MonitorEfemRobotLoadLockTask() { if (!_efem.IsAvailable) return; if ((_cooling1.HasWafer(0) || _cooling2.HasWafer(0)) && (!_efem.Blade1Enable || !_efem.Blade2Enable)) return; int waferCount = 0; if (_cooling1.HasWafer(0)) waferCount++; if (_cooling2.HasWafer(0)) waferCount++; if (_efem.HasWafer(0)) waferCount++; if (_efem.HasWafer(1)) waferCount++; if (waferCount >= 2) return; foreach (var ll in _lstLls) { if (!ll.IsAvailable) continue; { bool blade1Empty = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { Hand pickBlade = blade1Empty ? Hand.Blade1 : Hand.Blade2; var wafers = WaferManager.Instance.GetWafers(ll.Module); for (int i = 0; i < wafers.Length; i++) { if (CheckWaferCouldBeReturn(wafers[i]) && wafers[i].NextStation == (int)ModuleName.LoadLock) { if (ll.IsReadyForPick(ModuleName.EfemRobot, pickBlade, i)) { if (_efem.Pick(ll.Module, i, pickBlade)) { ll.WaitTransfer(ModuleName.EfemRobot); return; } } } } } } } } private void MonitorEfemRobotCoolingTask() { if (!_efem.IsAvailable) return; //pick from Cooling bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1EmptyAndEnable || blade2EmptyAndEnable) { Hand pickBlade = blade1EmptyAndEnable ? Hand.Blade1 : Hand.Blade2; foreach (var cooling in _lstCoolings) { if (!_efem.IsAvailable) return; if (!cooling.IsAvailable) continue; if (cooling.HasWafer(0) && cooling.GetWaferInfo(0).NextStation == (int)ModuleName.Cooling) { if (cooling.IsReadyForPick(ModuleName.EfemRobot, pickBlade, 0)) { if (_efem.Pick(cooling.Module, 0, pickBlade)) { cooling.WaitTransfer(ModuleName.EfemRobot); return; } } } } } //不需要cooling,返回 if (!_needCooling) return; //place to Cooling bool blade1NeedCooling = _efem.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).NextStation != (int)ModuleName.Cooling; bool blade2NeedCooling = _efem.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).NextStation != (int)ModuleName.Cooling; if (blade1NeedCooling || blade2NeedCooling) { Hand placeBlade = blade1NeedCooling ? Hand.Blade1 : Hand.Blade2; foreach (var cooling in _lstCoolings) { if (!_efem.IsAvailable) return; if (!cooling.IsAvailable) continue; if (cooling.IsReadyForPlace(ModuleName.EfemRobot, placeBlade, 0)) { if (_efem.Place(cooling.Module, 0, placeBlade)) { cooling.WaitTransfer(ModuleName.EfemRobot); return; } } } } } private void MonitorEfemRobotAlignerTask() { if (!_efem.IsAvailable) return; //pick from aligner bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1EmptyAndEnable || blade2EmptyAndEnable) { Hand pickBlade = blade1EmptyAndEnable ? Hand.Blade1 : Hand.Blade2; foreach (var aligner in _lstAligners) { if (!_efem.IsAvailable) return; if (!aligner.IsAvailable) continue; if (aligner.HasWafer(0)) { if (aligner.IsReadyForPick(ModuleName.EfemRobot, pickBlade, 0)) { if (_efem.Pick(aligner.Module, 0, pickBlade)) { aligner.WaitTransfer(ModuleName.EfemRobot); return; } } } } } } private int[] GetWaferCouldBeReturn(ModuleName module) { var wafers = WaferManager.Instance.GetWafers(module); List slots = new List(); for (int i = 0; i < wafers.Length; i++) { if (CheckWaferCouldBeReturn(wafers[i])) { slots.Add(i); if(SC.IsDoubleFork) { var leftOrRightSlot = (i % 2 > 0) ? i - 1 : i + 1; var wafer = WaferManager.Instance.GetWafer(module, leftOrRightSlot); if(wafer != null && !wafer.IsEmpty && CheckWaferCouldBeReturn(wafer)) { slots.Add(leftOrRightSlot); } } return slots.ToArray(); } } return null; } private bool TryGetNextCanBeRetrunWafer(ModuleName module, int selectedSlot, out int nextSlot) { nextSlot = 0; if (!SC.IsDoubleFork) return false; nextSlot = (selectedSlot % 2 > 0) ? selectedSlot - 1 : selectedSlot + 1; var wafer = WaferManager.Instance.GetWafer(module, nextSlot); return !wafer.IsEmpty && CheckWaferCouldBeReturn(wafer); } private int[] GetSlotCouldBePlace(SchedulerLoadLock ll, Hand placeBlade) { var wafers = WaferManager.Instance.GetWafers(ll.Module); var isDoubleFork = SC.IsDoubleFork; for (int i = 0; i < wafers.Length; ) { if(isDoubleFork) { if (wafers[i].IsEmpty && ll.IsReadyForPlace(ModuleName.TMRobot, placeBlade, i) && wafers[i + 1].IsEmpty && ll.IsReadyForPlace(ModuleName.TMRobot, placeBlade, i + 1)) { if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, ((int)placeBlade) + 2)) return new int[] { i, i + 1 }; else return new int[] { i}; } i += 2; } else { if (wafers[i].IsEmpty && ll.IsReadyForPlace(ModuleName.TMRobot, placeBlade, i)) return new int[] {i}; i += 1; } } return null; } private bool CheckWaferCouldBeReturn(WaferInfo wafer) { if (!wafer.IsEmpty) { return ModuleHelper.IsLoadPort((ModuleName)wafer.OriginStation) && wafer.Status != WaferStatus.Dummy && WaferManager.Instance.CheckNoWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot); } return false; } private bool CheckWaferCouldBeReturn(ModuleName module, int slot) { WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot); if (!wafer.IsEmpty) { return ModuleHelper.IsLoadPort((ModuleName)wafer.OriginStation) && wafer.Status != WaferStatus.Dummy && WaferManager.Instance.CheckNoWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot); } return false; } private SlotItem GetWaferReturnLoadPort(ModuleName module, int slot) { WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot); if (!wafer.IsEmpty) { return new SlotItem((ModuleName)wafer.OriginStation, wafer.OriginSlot); } return null; } } }