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; } } 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; private 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) { 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.IsTM(swapItems[i].SourceModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(swapItems[i].SourceModule) ? TMEntity.MSG.Pick : TMEntity.MSG.PMPick; item.target = swapItems[0].SourceModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(swapItems[0].SourceModule, swapItems[0].SourceSlot, ModuleName.TM, i, (Hand)i)); _schedulerList.Enqueue(item); swap.moveList.Enqueue(new MoveItem(ModuleName.TM, 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.TM, j - swapIndex, (Hand)(j - swapIndex))); } _schedulerList.Enqueue(swap); for (int j = swapIndex; j < swapItems.Length; j++) { if (!ModuleHelper.IsTM(swapItems[j].DestinationModule)) { SchedulerItem item = new SchedulerItem(); item.MoveType = ModuleHelper.IsLoadLock(swapItems[j].SourceModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace; item.target = swapItems[j].DestinationModule; item.moveList = new Queue(); item.moveList.Enqueue(new MoveItem(ModuleName.TM, j - swapIndex, swapItems[j].DestinationModule, swapItems[j].DestinationSlot, (Hand)(j - swapIndex))); _schedulerList.Enqueue(item); } } } if(WaferManager.Instance.CheckNoWafer(ModuleName.TM, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TM, 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) { PackSwapCmds(items, TMEntity.MSG.PMSwap, 1); } } } Hand freeHand = SelectFreeHand(); if(freeHand == Hand.None) { LOG.Write(eEvent.WARN_ROUTER, ModuleName.TM, "No Free Arm to transfer wafer"); return false; } if(_schedulerList.Count == 0) { foreach(var moveItem in items) { if(!ModuleHelper.IsTM(moveItem.SourceModule)) { 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.TM, (int)freeHand, freeHand)); _schedulerList.Enqueue(item); } if (!ModuleHelper.IsTM(moveItem.DestinationModule)) { 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.TM, (int)freeHand, moveItem.DestinationModule, moveItem.DestinationSlot, freeHand)); _schedulerList.Enqueue(item); } } } return true; } Hand SelectFreeHand() { if (WaferManager.Instance.CheckNoWafer(ModuleName.TM, 0)) return Hand.Blade1; if (WaferManager.Instance.CheckNoWafer(ModuleName.TM, 1)) return Hand.Blade2; return Hand.None; } bool RunSchedulers() { if(_entity.IsIdle && CheckTaskDone()) { if (_schedulerList.Count == 0) return true; _currentScheduler = _schedulerList.Dequeue(); if(_entity.CheckToPostMessage((int)_currentScheduler.MoveType, _currentScheduler.moveList.ToArray())) { _entityTaskToken = (int)_currentScheduler.MoveType; } else _entityTaskToken = (int)FSM_MSG.NONE; } return false; } } }