using System.Diagnostics; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.Util; 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 Venus_RT.Scheduler; using Venus_Core; namespace Venus_RT.Modules.Schedulers { class SchedulerItem { public TMEntity.MSG MoveType { get; set; } public ModuleName target { get; set; } public Queue moveList { get; set; } } public class SchedulerTMRobot : SchedulerModule { public override bool IsAvailable { get { return _entity.IsIdle && (_entity.IsOnline || !Singleton.Instance.IsAutoMode) && RunSchedulers(); } } public override bool IsOnline { get { return _entity.IsOnline; } } public override bool IsIdle { get { return _entity.IsIdle; } } public override bool IsError { get { return _entity.IsError; } } public RState RobotStatus { get { return _entity.RobotStatus;} } public override bool IsVac { get { return _entity.IsTMVac; } } public override bool IsAtm { get { return _entity.IsTMVac; } } private TMEntity _entity = null; public int _entityTaskToken = (int)FSM_MSG.NONE; private Queue _schedulerList = new Queue(); private SchedulerItem _currentScheduler = null; private int _singleArmOption = 0; public SchedulerTMRobot() : base(ModuleName.TM.ToString()) { _entity = Singleton.Instance.TM; _singleArmOption = SC.GetValue("TM.SingleArmOption"); } private bool CheckTaskDone() { bool ret = false; switch (_entityTaskToken) { case (int)TMEntity.MSG.Pick: case (int)TMEntity.MSG.PMPick: ret = WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Peek().DestinationModule, _currentScheduler.moveList.Peek().DestinationSlot) && WaferManager.Instance.CheckNoWafer(_currentScheduler.moveList.Peek().SourceModule, _currentScheduler.moveList.Peek().SourceSlot); break; case (int)TMEntity.MSG.Place: case (int)TMEntity.MSG.PMPlace: ret = WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Peek().DestinationModule, _currentScheduler.moveList.Peek().DestinationSlot) && WaferManager.Instance.CheckNoWafer(_currentScheduler.moveList.Peek().SourceModule, _currentScheduler.moveList.Peek().SourceSlot); break; case (int)TMEntity.MSG.Swap: ret = WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Peek().DestinationModule, _currentScheduler.moveList.Peek().DestinationSlot) && WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Last().DestinationModule, _currentScheduler.moveList.Last().DestinationSlot); break; case (int)TMEntity.MSG.PMSwap: ret = WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Peek().DestinationModule, _currentScheduler.moveList.Peek().DestinationSlot) && WaferManager.Instance.CheckHasWafer(_currentScheduler.moveList.Peek().SourceModule, _currentScheduler.moveList.Peek().SourceSlot); break; case (int)FSM_MSG.NONE: ret = true; break; } if(ret && _entityTaskToken != (int)FSM_MSG.NONE) { _entityTaskToken = (int)FSM_MSG.NONE; LOG.Write(eEvent.EV_ROUTER, ModuleName.TM, $"Scheduler, { _currentScheduler.target} Task done: { _currentScheduler.MoveType}"); } return ret; } public bool PostMoveItems(MoveItem[] items) { foreach(var item in items) { LOG.Write(eEvent.EV_ROUTER, ModuleName.TMRobot, $"Post Moving Item: {item.SourceModule} Slot {item.SourceSlot + 1} => {item.DestinationModule} Slot {item.DestinationSlot + 1}"); } void PackPMSwapCmds(MoveItem[] swapItems) { // must swap the item order for PM swap if (!ModuleHelper.IsTMRobot(swapItems[1].SourceModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = TMEntity.MSG.Pick; item.target = swapItems[1].SourceModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(swapItems[1].SourceModule, swapItems[1].SourceSlot, ModuleName.TMRobot, 0, (Hand)0)); _schedulerList.Enqueue(item); } SchedulerItem swap = new SchedulerItem(); swap.MoveType = TMEntity.MSG.PMSwap; swap.target = swapItems[0].SourceModule; swap.moveList = new Queue(); swap.moveList.Enqueue(new MoveItem(swapItems[0].SourceModule, swapItems[0].SourceSlot, ModuleName.TMRobot, 1, (Hand)1)); swap.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, 0, swapItems[1].DestinationModule, swapItems[1].DestinationSlot, (Hand)0)); _schedulerList.Enqueue(swap); if (!ModuleHelper.IsTMRobot(swapItems[0].DestinationModule)) { SchedulerItem last = new SchedulerItem(); last.MoveType = TMEntity.MSG.Place; last.target = swapItems[0].DestinationModule; last.moveList = new Queue(); last.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, 1, swapItems[0].DestinationModule, swapItems[0].DestinationSlot, (Hand)1)); _schedulerList.Enqueue(last); } } void PackSwapCmds(MoveItem[] swapItems, TMEntity.MSG swapType, int swapIndex) { SchedulerItem swap = new SchedulerItem(); swap.MoveType = swapType; swap.target = swapItems[0].DestinationModule; swap.moveList = new Queue(); for (int i = 0; i < swapIndex; i++) { if(!ModuleHelper.IsTMRobot(swapItems[i].SourceModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(swapItems[i].SourceModule) ? TMEntity.MSG.Pick : TMEntity.MSG.PMPick; item.target = swapItems[i].SourceModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(swapItems[i].SourceModule, swapItems[i].SourceSlot, ModuleName.TMRobot, i, (Hand)i)); _schedulerList.Enqueue(item); swap.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, i, swapItems[i].DestinationModule, swapItems[i].DestinationSlot, (Hand)i)); } } for (int j = swapIndex; j < swapItems.Length; j++) { swap.moveList.Enqueue(new MoveItem(swapItems[j].SourceModule, swapItems[j].SourceSlot, ModuleName.TMRobot, j - swapIndex, (Hand)(j - swapIndex))); } _schedulerList.Enqueue(swap); for (int j = swapIndex; j < swapItems.Length; j++) { if (!ModuleHelper.IsTMRobot(swapItems[j].DestinationModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(swapItems[j].DestinationModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace; item.target = swapItems[j].DestinationModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, j - swapIndex, swapItems[j].DestinationModule, swapItems[j].DestinationSlot, (Hand)(j - swapIndex))); _schedulerList.Enqueue(item); } } } if(WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) && _singleArmOption == 0) { if (items.Length == 4) { if (ModuleHelper.IsLoadLock(items[0].DestinationModule) && items[0].DestinationModule == items[1].DestinationModule && items[0].DestinationModule == items[2].SourceModule && items[0].DestinationModule == items[3].SourceModule) { PackSwapCmds(items, TMEntity.MSG.Swap, 2); } } else if (items.Length == 3) { if (ModuleHelper.IsLoadLock(items[0].DestinationModule) && items[0].DestinationModule == items[1].DestinationModule && items[0].DestinationModule == items[2].SourceModule) { PackSwapCmds(items, TMEntity.MSG.Swap, 2); } else if (ModuleHelper.IsLoadLock(items[0].DestinationModule) && items[0].DestinationModule == items[1].SourceModule && items[0].DestinationModule == items[2].SourceModule) { PackSwapCmds(items, TMEntity.MSG.Swap, 1); } else if(ModuleHelper.IsLoadLock(items[0].SourceModule) && items[0].SourceModule == items[1].SourceModule && ModuleHelper.IsPm(items[1].DestinationModule) && items[1].DestinationModule == items[2].SourceModule) { SchedulerItem llDoublePick = new SchedulerItem(); llDoublePick.MoveType = TMEntity.MSG.Swap; llDoublePick.target = items[0].SourceModule; llDoublePick.moveList = new Queue(); llDoublePick.moveList.Enqueue(new MoveItem(items[0].SourceModule, items[0].SourceSlot, ModuleName.TMRobot, 0, 0)); llDoublePick.moveList.Enqueue(new MoveItem(items[1].SourceModule, items[1].SourceSlot, ModuleName.TMRobot, 1, (Hand)1)); _schedulerList.Enqueue(llDoublePick); SchedulerItem pm1_place = new SchedulerItem(); pm1_place.MoveType = TMEntity.MSG.PMPlace; pm1_place.target = items[0].DestinationModule; pm1_place.moveList = new Queue(); pm1_place.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, 0, items[0].DestinationModule, items[0].DestinationSlot, 0)); _schedulerList.Enqueue(pm1_place); SchedulerItem pm2_swap = new SchedulerItem(); pm2_swap.MoveType = TMEntity.MSG.PMSwap; pm2_swap.target = items[2].SourceModule; pm2_swap.moveList = new Queue(); pm2_swap.moveList.Enqueue(new MoveItem(items[2].SourceModule, items[2].SourceSlot, ModuleName.TMRobot, 0, 0)); pm2_swap.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, 1, items[1].DestinationModule, items[1].DestinationSlot, (Hand)1)); _schedulerList.Enqueue(pm2_swap); if(ModuleHelper.IsLoadLock(items[2].DestinationModule)) { SchedulerItem llPlace = new SchedulerItem(); llPlace.MoveType = TMEntity.MSG.Place; llPlace.target = items[2].DestinationModule; llPlace.moveList = new Queue(); llPlace.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, 0, items[2].DestinationModule, items[2].DestinationSlot, 0)); _schedulerList.Enqueue(llPlace); } } } else if (items.Length == 2) { if (ModuleHelper.IsLoadLock(items[0].DestinationModule) && items[0].DestinationModule == items[1].DestinationModule) { PackSwapCmds(items, TMEntity.MSG.Swap, 2); } else if (ModuleHelper.IsLoadLock(items[0].SourceModule) && items[0].SourceModule == items[1].SourceModule) { PackSwapCmds(items, TMEntity.MSG.Swap, 0); } else if (ModuleHelper.IsPm(items[0].SourceModule) && items[0].SourceModule == items[1].DestinationModule) { PackPMSwapCmds(items); } } } Hand freeHand = SelectFreeHand(); if(freeHand == Hand.None && !ModuleHelper.IsTMRobot(items[0].SourceModule)) { LOG.Write(eEvent.WARN_ROUTER, ModuleName.TMRobot, "No Free Arm to transfer wafer"); return false; } if(_schedulerList.Count == 0) { foreach(var moveItem in items) { if(!ModuleHelper.IsTMRobot(moveItem.SourceModule) && !ModuleHelper.IsTMRobot(moveItem.DestinationModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(moveItem.SourceModule) ? TMEntity.MSG.Pick : TMEntity.MSG.PMPick; item.target = moveItem.SourceModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(moveItem.SourceModule, moveItem.SourceSlot, ModuleName.TMRobot, (int)freeHand, freeHand)); _schedulerList.Enqueue(item); item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(moveItem.DestinationModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace; item.target = moveItem.DestinationModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, (int)freeHand, moveItem.DestinationModule, moveItem.DestinationSlot, freeHand)); _schedulerList.Enqueue(item); } else if(ModuleHelper.IsTMRobot(moveItem.SourceModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(moveItem.DestinationModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace; item.target = moveItem.DestinationModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, moveItem.SourceSlot, moveItem.DestinationModule, moveItem.DestinationSlot, (Hand)moveItem.SourceSlot)); _schedulerList.Enqueue(item); } else if(ModuleHelper.IsTMRobot(moveItem.DestinationModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(moveItem.SourceModule) ? TMEntity.MSG.Pick : TMEntity.MSG.PMPick; item.target = moveItem.SourceModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(moveItem.SourceModule, moveItem.SourceSlot, ModuleName.TMRobot, moveItem.DestinationSlot, (Hand)moveItem.DestinationSlot)); _schedulerList.Enqueue(item); } } } PrepareLLPressure(items); RunSchedulers(); return true; } public bool SendMoveItems(MoveItem[] items) { for(int i = 1; i < items.Length; i++) { if(items[i - 1].Module != items[i].Module) { LOG.Write(eEvent.ERR_ROUTER, ModuleName.TMRobot, $"the actions for {items[i - 1].Module} and for {items[i].Module} should not put together"); return false; } } void PackMoveItems(TMEntity.MSG cmdType, MoveItem[] actions) { SchedulerItem schItem = new SchedulerItem(); schItem.MoveType = cmdType; schItem.target = actions[0].DestinationModule; schItem.moveList = new Queue(); foreach(var ac in actions) { schItem.moveList.Enqueue(ac); } _schedulerList.Enqueue(schItem); } if (ModuleHelper.IsTMRobot(items[0].DestinationModule)) // pick { if(ModuleHelper.IsLoadLock(items[0].Module)) { PackMoveItems(items.Length > 1 ? TMEntity.MSG.Swap : TMEntity.MSG.Pick, items); } else { PackMoveItems(items.Length > 1 ? TMEntity.MSG.PMSwap : TMEntity.MSG.PMPick, items); } } else if (ModuleHelper.IsTMRobot(items[0].SourceModule)) // place { if (ModuleHelper.IsLoadLock(items[0].Module)) { PackMoveItems(items.Length > 1 ? TMEntity.MSG.Swap : TMEntity.MSG.Place, items); } else { if(items.Length == 1) { PackMoveItems(TMEntity.MSG.PMPlace, items); } else { LOG.Write(eEvent.ERR_ROUTER, ModuleName.TMRobot, $"multi actons for PM place command"); return false; } } } else return false; foreach (var item in items) { LOG.Write(eEvent.EV_ROUTER, ModuleName.TMRobot, $"Post Moving Item: {item.SourceModule} Slot {item.SourceSlot + 1} => {item.DestinationModule} Slot {item.DestinationSlot + 1}"); } return true; } Hand SelectFreeHand() { if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && _singleArmOption != 2) return Hand.Blade1; if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) && _singleArmOption != 1) return Hand.Blade2; return Hand.None; } bool RunSchedulers() { if(_entity.IsIdle && CheckTaskDone()) { if (_schedulerList.Count == 0) return true; _currentScheduler = _schedulerList.Dequeue(); Queue moveItems = new Queue(); foreach(var item in _currentScheduler.moveList) { moveItems.Enqueue(item); LOG.Write(eEvent.INFO_TM, ModuleName.TMRobot, $"TM Moving Items: {item.SourceModule} Slot {item.SourceSlot + 1} => {item.DestinationModule} Slot {item.DestinationSlot + 1}"); } if(_entity.CheckToPostMessage((int)_currentScheduler.MoveType, moveItems)) { _entityTaskToken = (int)_currentScheduler.MoveType; } else _entityTaskToken = (int)FSM_MSG.NONE; } return false; } public override void ResetTask() { base.ResetTask(); _entityTaskToken = (int)FSM_MSG.NONE; _schedulerList.Clear(); } private void PrepareLLPressure(MoveItem[] items) { if (items.Length == 0 || RouteManager.IsATMMode) return; ModuleName firstModule = items[0].SourceModule; List lls = new List(); for (int i = 0; i < items.Length; i++) { if(ModuleHelper.IsLoadLock(items[i].SourceModule) && Singleton.Instance.GetLL(items[i].SourceModule).IsATM) { if (!lls.Contains(items[i].SourceModule) && items[i].SourceModule != firstModule) lls.Add(items[i].SourceModule); } if (ModuleHelper.IsLoadLock(items[i].DestinationModule) && Singleton.Instance.GetLL(items[i].DestinationModule).IsATM) { if (!lls.Contains(items[i].DestinationModule) && items[i].DestinationModule != firstModule) lls.Add(items[i].DestinationModule); } } foreach( var ll in lls) { Singleton.Instance.GetLL(ll).CheckToPostMessage((int)LLEntity.MSG.Pump); } } } }