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; 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 && */RunSchedulers(); } } public override bool IsOnline { get { return _entity.IsOnline; } } public override bool IsError { get { return _entity.IsError; } } private TMEntity _entity = null; public int _entityTaskToken = (int)FSM_MSG.NONE; private Queue _schedulerList = new Queue(); private SchedulerItem _currentScheduler = null; public SchedulerTMRobot() : base(ModuleName.TM.ToString()) { _entity = Singleton.Instance.TM; } 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)) { 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 (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) { 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); } } } RunSchedulers(); return true; } Hand SelectFreeHand() { if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0)) return Hand.Blade1; if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 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; } } }