|
@@ -0,0 +1,365 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+
|
|
|
+using Aitex.Core.Common;
|
|
|
+using Aitex.Core.RT.Routine;
|
|
|
+using Aitex.Core.RT.SCCore;
|
|
|
+using Aitex.Sorter.Common;
|
|
|
+using Aitex.Core.RT.Log;
|
|
|
+using Aitex.Core.Util;
|
|
|
+using Aitex.Core.RT.DataCenter;
|
|
|
+using Aitex.Core.RT.RecipeCenter;
|
|
|
+using Aitex.Core.RT.Fsm;
|
|
|
+
|
|
|
+using MECF.Framework.Common.Jobs;
|
|
|
+using MECF.Framework.Common.Routine;
|
|
|
+using MECF.Framework.Common.Equipment;
|
|
|
+using MECF.Framework.Common.SubstrateTrackings;
|
|
|
+using MECF.Framework.Common.Schedulers;
|
|
|
+using MECF.Framework.Common.DBCore;
|
|
|
+
|
|
|
+using Venus_Core;
|
|
|
+
|
|
|
+using Venus_RT.Modules.Schedulers;
|
|
|
+using Venus_RT.Scheduler;
|
|
|
+
|
|
|
+namespace Venus_RT.Modules
|
|
|
+{
|
|
|
+ public class ManualTransfer : IRoutine
|
|
|
+ {
|
|
|
+ SchedulerTMRobot _tmRobot = new SchedulerTMRobot();
|
|
|
+ SchedulerEfemRobot _efemRobot = new SchedulerEfemRobot();
|
|
|
+
|
|
|
+ private Queue<MoveItem> _moveTaskQueue = new Queue<MoveItem>();
|
|
|
+ private MoveItem _move_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None);
|
|
|
+ private MoveItem _current_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None);
|
|
|
+
|
|
|
+ private Guid _wafer_id;
|
|
|
+ private R_TRIG _wafer_arrive_trig = new R_TRIG();
|
|
|
+ private MovingStatus _moving_status = MovingStatus.Staying;
|
|
|
+
|
|
|
+ public RState Start(params object[] objs)
|
|
|
+ {
|
|
|
+
|
|
|
+ _moveTaskQueue.Clear();
|
|
|
+ _moving_status = MovingStatus.Staying;
|
|
|
+ _wafer_arrive_trig.RST = true ;
|
|
|
+
|
|
|
+ _move_item.SourceModule = (ModuleName)objs[0];
|
|
|
+ _move_item.SourceSlot = (int)objs[1];
|
|
|
+ _move_item.DestinationModule = (ModuleName)objs[2];
|
|
|
+ _move_item.DestinationSlot = (int)objs[3];
|
|
|
+
|
|
|
+ _wafer_id = WaferManager.Instance.GetWafer(_move_item.SourceModule, _move_item.SourceSlot).InnerId;
|
|
|
+
|
|
|
+ if(IsCrossTransfer(_move_item))
|
|
|
+ {
|
|
|
+ var slot = SelectLLFreeSlot();
|
|
|
+ if (slot.Module == ModuleName.System)
|
|
|
+ return RState.Failed;
|
|
|
+
|
|
|
+
|
|
|
+ if (ModuleHelper.IsPm(_move_item.SourceModule) || ModuleHelper.IsTMRobot(_move_item.SourceModule))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, slot.Module, slot.Slot, Hand.Blade1));
|
|
|
+ if(ModuleHelper.IsEFEMRobot(_move_item.DestinationModule))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.DestinationSlot));
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Hand hand = SelectEfemRobotFreeHand();
|
|
|
+ if(hand == Hand.None)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, _move_item.DestinationModule, _move_item.DestinationSlot, hand));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsEFEMRobot(_move_item.SourceModule))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, slot.Module, slot.Slot, (Hand)_move_item.SourceSlot));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Hand hand = SelectEfemRobotFreeHand();
|
|
|
+ if (hand == Hand.None)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, slot.Module, slot.Slot, hand));
|
|
|
+ }
|
|
|
+
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, _move_item.DestinationModule, _move_item.DestinationSlot, Hand.Blade1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(IsVacTransfer(_move_item))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(_move_item);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(ModuleHelper.IsEFEMRobot(_move_item.SourceModule))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.SourceSlot));
|
|
|
+ }
|
|
|
+ else if (ModuleHelper.IsEFEMRobot(_move_item.DestinationModule))
|
|
|
+ {
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.DestinationSlot));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Hand hand = SelectEfemRobotFreeHand();
|
|
|
+ if (hand == Hand.None)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
+ _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, _move_item.DestinationModule, _move_item.DestinationSlot, hand));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _current_item = _moveTaskQueue.Dequeue();
|
|
|
+ _moving_status = MovingStatus.Waiting;
|
|
|
+ return RState.Running;
|
|
|
+ }
|
|
|
+
|
|
|
+ public RState Monitor()
|
|
|
+ {
|
|
|
+ return MoveWaferForward();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Abort()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private RState MoveWaferForward()
|
|
|
+ {
|
|
|
+ switch(_moving_status)
|
|
|
+ {
|
|
|
+ case MovingStatus.Waiting:
|
|
|
+ {
|
|
|
+ if(IsCurrentModuleReady())
|
|
|
+ {
|
|
|
+
|
|
|
+ if(IsVacTransfer(_current_item))
|
|
|
+ {
|
|
|
+ _tmRobot.PostMoveItems(new MoveItem[1] { _current_item });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _efemRobot.PostMoveItems(new MoveItem[1] { _current_item });
|
|
|
+ }
|
|
|
+
|
|
|
+ _moving_status = MovingStatus.Moving;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MovingStatus.Moving:
|
|
|
+ {
|
|
|
+ _wafer_arrive_trig.CLK = IsArriveCurrentTarget();
|
|
|
+ if (_wafer_arrive_trig.Q)
|
|
|
+ {
|
|
|
+ _moving_status = MovingStatus.Staying;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MovingStatus.Staying:
|
|
|
+ {
|
|
|
+ if(IsCurrentModuleReady())
|
|
|
+ {
|
|
|
+ if(_moveTaskQueue.Count > 0)
|
|
|
+ {
|
|
|
+ _current_item = _moveTaskQueue.Dequeue();
|
|
|
+ _moving_status = MovingStatus.Waiting;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return TransferStatus();
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsVacTransfer(MoveItem item)
|
|
|
+ {
|
|
|
+ return ModuleHelper.IsPm(item.SourceModule) ||
|
|
|
+ ModuleHelper.IsTMRobot(item.SourceModule) ||
|
|
|
+ ModuleHelper.IsPm(item.DestinationModule) ||
|
|
|
+ ModuleHelper.IsTMRobot(item.DestinationModule);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsCrossTransfer(MoveItem item)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsLoadLock(item.DestinationModule) || ModuleHelper.IsLoadLock(item.SourceModule))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (((ModuleHelper.IsPm(item.SourceModule) || ModuleHelper.IsTMRobot(item.SourceModule)) &&
|
|
|
+ !ModuleHelper.IsPm(item.DestinationModule) && !ModuleHelper.IsTMRobot(item.DestinationModule)) ||
|
|
|
+ ((ModuleHelper.IsPm(item.DestinationModule) || ModuleHelper.IsTMRobot(item.DestinationModule)) &&
|
|
|
+ !ModuleHelper.IsPm(item.SourceModule) && !ModuleHelper.IsTMRobot(item.SourceModule)))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsArriveCurrentTarget()
|
|
|
+ {
|
|
|
+ var wafer = WaferManager.Instance.GetWafer(_current_item.DestinationModule, _current_item.DestinationSlot);
|
|
|
+ return !wafer.IsEmpty && wafer.InnerId == _wafer_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsCurrentModuleReady()
|
|
|
+ {
|
|
|
+ return (IsVacTransfer(_current_item) ? _tmRobot.IsAvailable : _efemRobot.IsAvailable) &&
|
|
|
+ _isModuleReady(_current_item.SourceModule) &&
|
|
|
+ _isModuleReady(_current_item.DestinationModule);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsTransferError()
|
|
|
+ {
|
|
|
+ return (IsVacTransfer(_current_item) ? _tmRobot.IsError : _efemRobot.IsError) ||
|
|
|
+ _isModuleError(_current_item.SourceModule) ||
|
|
|
+ _isModuleError(_current_item.DestinationModule);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _isModuleReady(ModuleName module)
|
|
|
+ {
|
|
|
+ return Singleton<TransferModule>.Instance.GetScheduler(module).IsAvailable;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _isModuleError(ModuleName module)
|
|
|
+ {
|
|
|
+ return Singleton<TransferModule>.Instance.GetScheduler(module).IsError;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Hand SelectEfemRobotFreeHand()
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
|
|
|
+ return Hand.Blade1;
|
|
|
+ else if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1))
|
|
|
+ return Hand.Blade2;
|
|
|
+ else
|
|
|
+ return Hand.None;
|
|
|
+ }
|
|
|
+
|
|
|
+ private SlotItem SelectLLFreeSlot()
|
|
|
+ {
|
|
|
+ foreach(var ll in new ModuleName[2] { ModuleName.LLA, ModuleName.LLB})
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsInstalled(ll) && _isModuleReady(ll))
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckNoWafer(ll, i))
|
|
|
+ return new SlotItem(ll, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, "Cannot move wafer as no valid Loadlock slot");
|
|
|
+ return new SlotItem(ModuleName.System, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private RState TransferStatus()
|
|
|
+ {
|
|
|
+ if (IsTransferError())
|
|
|
+ return RState.Failed;
|
|
|
+
|
|
|
+ if (IsCurrentModuleReady() && _moveTaskQueue.Count == 0 && _moving_status == MovingStatus.Staying)
|
|
|
+ return RState.End;
|
|
|
+
|
|
|
+ return RState.Running;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ReturnAllWafer : IRoutine
|
|
|
+ {
|
|
|
+ private List<ModuleName> _moduleList = new List<ModuleName> { ModuleName.EfemRobot, ModuleName.Aligner1, ModuleName.Aligner, ModuleName.LLA, ModuleName.LLB, ModuleName.TMRobot, ModuleName.PMA, ModuleName.PMB, ModuleName.PMC, ModuleName.PMD };
|
|
|
+ private ManualTransfer _manualTransfer;
|
|
|
+ private Queue<MoveItem> _returnTaskQueue = new Queue<MoveItem>();
|
|
|
+ private MoveItem _current_item;
|
|
|
+ public ReturnAllWafer(ManualTransfer manualTransfer)
|
|
|
+ {
|
|
|
+ _manualTransfer = manualTransfer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public RState Start(params object[] objs)
|
|
|
+ {
|
|
|
+ foreach(var mod in _moduleList)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsInstalled(mod) && Singleton<TransferModule>.Instance.GetScheduler(mod).IsAvailable)
|
|
|
+ {
|
|
|
+ PushWaferToReturnQueqe(mod, 0);
|
|
|
+ if (ModuleHelper.IsEFEMRobot(mod) || ModuleHelper.IsTMRobot(mod))
|
|
|
+ {
|
|
|
+ PushWaferToReturnQueqe(mod, 1);
|
|
|
+ }
|
|
|
+ else if (ModuleHelper.IsLoadLock(mod))
|
|
|
+ {
|
|
|
+ int nSlotNumber = SC.GetValue<int>($"{mod}.SlotNumber");
|
|
|
+ for (int i = 1; i < nSlotNumber; i++)
|
|
|
+ {
|
|
|
+ PushWaferToReturnQueqe(mod, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_returnTaskQueue.Count == 0)
|
|
|
+ return RState.Failed;
|
|
|
+
|
|
|
+ _current_item = _returnTaskQueue.Dequeue();
|
|
|
+ _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot);
|
|
|
+ return RState.Running;
|
|
|
+ }
|
|
|
+
|
|
|
+ public RState Monitor()
|
|
|
+ {
|
|
|
+ var ret = _manualTransfer.Monitor();
|
|
|
+ if (ret == RState.End)
|
|
|
+ {
|
|
|
+ if (_returnTaskQueue.Count > 0)
|
|
|
+ {
|
|
|
+ _current_item = _returnTaskQueue.Dequeue();
|
|
|
+ _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return RState.End;
|
|
|
+ }
|
|
|
+ else if (ret == RState.Failed || ret == RState.Timeout)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.ERR_ROUTINE_FAILED, ModuleName.System, $"Return Wafer {_current_item.SourceModule}{_current_item.SourceSlot} failed");
|
|
|
+ return RState.Failed;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return RState.Running;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Abort()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void PushWaferToReturnQueqe(ModuleName mod, int nSlot)
|
|
|
+ {
|
|
|
+ var wafer = WaferManager.Instance.GetWafer(mod, nSlot);
|
|
|
+ if (!wafer.IsEmpty)
|
|
|
+ {
|
|
|
+ _returnTaskQueue.Enqueue(new MoveItem(mod, nSlot, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|