|
@@ -699,6 +699,13 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ enum LLSlotInOutOpt
|
|
|
+ {
|
|
|
+ AllInAllOut,
|
|
|
+ UpperInLowerOut,
|
|
|
+ LowerInUpperOut,
|
|
|
+ }
|
|
|
+
|
|
|
class SystemDispatcher : ICycle
|
|
|
{
|
|
|
private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
|
|
@@ -732,6 +739,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private int _efemRobotSingleArmOption = 0;
|
|
|
private int _tmRobotSingleArmOption = 0;
|
|
|
+ private LLSlotInOutOpt _LLSlotInOutOption = 0;
|
|
|
private Dictionary<ModuleName, int> _lpCycleWafer = new Dictionary<ModuleName, int>();
|
|
|
private Dictionary<ModuleName, int> _lpCycleCount = new Dictionary<ModuleName, int>();
|
|
|
private Stopwatch _cycleWatch = new Stopwatch();
|
|
@@ -804,6 +812,12 @@ namespace Venus_RT.Modules
|
|
|
_cycledCount = 0;
|
|
|
_throughput = 0;
|
|
|
|
|
|
+ // rounding TM robot single arm option
|
|
|
+ if(_tmRobotSingleArmOption > 2 && _LLSlotInOutOption == LLSlotInOutOpt.AllInAllOut)
|
|
|
+ {
|
|
|
+ _tmRobotSingleArmOption = 0;
|
|
|
+ }
|
|
|
+
|
|
|
_cycleWatch.Stop();
|
|
|
_lpCycleWafer.Clear();
|
|
|
_lpCycleCount.Clear();
|
|
@@ -830,8 +844,6 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
public bool CreateJob(Dictionary<string, object> param, out string reason)
|
|
|
{
|
|
|
reason = "";
|
|
@@ -1176,10 +1188,6 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
if (RtInstance.ConfigType == ConfigType.Kepler2200)
|
|
|
{
|
|
|
- //if (!CheckSequenceKepler2200TemperatureReady(GetFirstProcessJob(cj).Sequence))
|
|
|
- //{
|
|
|
- // return false;
|
|
|
- //}
|
|
|
foreach (var item in _lstProcessJobs)
|
|
|
{
|
|
|
if (item.ControlJobName == cj.Name && !CheckSequenceKepler2200TemperatureReady(item.Sequence))
|
|
@@ -1397,7 +1405,11 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private void prelude()
|
|
|
{
|
|
|
-
|
|
|
+ bool available = true;
|
|
|
+ foreach(var mod in _dictModuleTask)
|
|
|
+ {
|
|
|
+ available = mod.Value.Scheduler.IsAvailable; // force scheduler update
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void epilogue()
|
|
@@ -1940,7 +1952,7 @@ namespace Venus_RT.Modules
|
|
|
var waferStaus = GetLLReadyInOutSlots(ll);
|
|
|
var atmWafers = _lstWaferTasks.Where(wafer => (wafer.movingStatus == RState.End ||wafer.movingStatus == RState.Init) && (ModuleHelper.IsEFEMRobot(wafer.currentMod) || ModuleHelper.IsAligner(wafer.currentMod))).ToList();
|
|
|
var notAlignedWafer = atmWafers.Where(wafer => !wafer.IsAligned).ToList();
|
|
|
- var readyInWafers = _lstWaferTasks.Where(wafer => ModuleHelper.IsLoadPort(wafer.currentMod) && wafer.movingStatus == RState.Init && wafer.pressureStatus == RState.Init).OrderBy(wafer => wafer.currentSlot).ToArray();
|
|
|
+ var readyInWafers = _lstWaferTasks.Where(wafer => ModuleHelper.IsLoadPort(wafer.currentMod) && wafer.movingStatus == RState.Init && wafer.pressureStatus == RState.Init && CanWaferGotoLL(wafer, ll)).OrderBy(wafer => wafer.currentSlot).ToArray();
|
|
|
var freeHands = GetEFEMFreeHand();
|
|
|
|
|
|
if ((atmWafers.Count >= 2 && atmWafers.Count(wafer => !wafer.IsAligned) == 0) || freeHands.Count == 0 || readyInWafers.Length == 0)
|
|
@@ -1992,7 +2004,7 @@ namespace Venus_RT.Modules
|
|
|
(atmWafers.Count(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod)) == 0 || waferStaus.emptySlot.Count >= 2))
|
|
|
{
|
|
|
var alignerWafer = atmWafers.Where(wafer => ModuleHelper.IsAligner(wafer.currentMod)).First();
|
|
|
- if(CanWaferGotoLL(alignerWafer, ll))
|
|
|
+ if (CanWaferGotoLL(alignerWafer, ll))
|
|
|
{
|
|
|
alignerWafer.RouteTo(ll, waferStaus.emptySlot[placeCount]);
|
|
|
|
|
@@ -2006,7 +2018,7 @@ namespace Venus_RT.Modules
|
|
|
var armWafers = atmWafers.Where(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod)).ToArray();
|
|
|
foreach(var wafer in armWafers)
|
|
|
{
|
|
|
- if(CanWaferGotoLL(wafer, ll) && placeCount < waferStaus.emptySlot.Count)
|
|
|
+ if (CanWaferGotoLL(wafer, ll) && placeCount < waferStaus.emptySlot.Count)
|
|
|
{
|
|
|
wafer.RouteTo(ll, waferStaus.emptySlot[placeCount]);
|
|
|
|
|
@@ -2066,13 +2078,20 @@ namespace Venus_RT.Modules
|
|
|
if (_efemRobotStatus != RState.End)
|
|
|
return;
|
|
|
|
|
|
- if(_LLASlotNumber == 2)
|
|
|
+ if(_LLSlotInOutOption == LLSlotInOutOpt.AllInAllOut)
|
|
|
{
|
|
|
- Routing2SlotATMSystem();
|
|
|
+ if (_LLASlotNumber == 2)
|
|
|
+ {
|
|
|
+ Routing2SlotATMSystem();
|
|
|
+ }
|
|
|
+ else if (_LLASlotNumber == 4)
|
|
|
+ {
|
|
|
+ Routing4SlotATMSystem();
|
|
|
+ }
|
|
|
}
|
|
|
- else if(_LLASlotNumber == 4)
|
|
|
+ else
|
|
|
{
|
|
|
- Routing4SlotATMSystem();
|
|
|
+ RoutingFixedSlotATMSystem();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2167,6 +2186,41 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void RoutingFixedSlotATMSystem()
|
|
|
+ {
|
|
|
+ var atmWaferCount = _lstWaferTasks.Where(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod) || ModuleHelper.IsAligner(wafer.currentMod)).Count();
|
|
|
+ var lls = _dictModuleTask.Where(mod => ModuleHelper.IsLoadLock(mod.Key) && mod.Value.Scheduler.IsOnline);
|
|
|
+
|
|
|
+ if ( atmWaferCount == 0 || (_efemRobotSingleArmOption == 0 && atmWaferCount == 1 ))
|
|
|
+ {
|
|
|
+ foreach(var ll in lls)
|
|
|
+ {
|
|
|
+ if (ForwardATMWafers(ll.Key))
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // try to match a ll swap action
|
|
|
+ if(_LLASlotNumber == 2)
|
|
|
+ {
|
|
|
+ var readyReturnLL = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).eOutSlot.Count > 0).OrderBy(ll => ll.Value.TimeToReady);
|
|
|
+ foreach(var ll in readyReturnLL)
|
|
|
+ {
|
|
|
+ if (ExchangeWaferWithLL(ll.Key))
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var readyReturnLL = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).eOutSlot.Count > 0).OrderByDescending(ll => GetLLFixedReadyInOutSlots(ll.Key).eOutSlot.Count);
|
|
|
+ foreach (var ll in readyReturnLL)
|
|
|
+ {
|
|
|
+ if (ExchangeWaferWithLL(ll.Key))
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void RoutingSameLLInOutATMSystem()
|
|
|
{
|
|
|
var atmWaferCount = _lstWaferTasks.Where(wafer => ModuleHelper.IsEFEMRobot(wafer.currentMod) || ModuleHelper.IsAligner(wafer.currentMod)).Count();
|
|
@@ -2621,6 +2675,19 @@ namespace Venus_RT.Modules
|
|
|
return (returnWafers[preferLL], preferLL, llSwapActions[preferLL]);
|
|
|
}
|
|
|
|
|
|
+ ModuleName FindTheBestMovePathWithFixSlot(IEnumerable<KeyValuePair<ModuleName, ModuleTask>> lls, List<WaferTask> pmWafers)
|
|
|
+ {
|
|
|
+ Dictionary<ModuleName, int> moveValues = new Dictionary<ModuleName, int>();
|
|
|
+ foreach(var ll in lls)
|
|
|
+ {
|
|
|
+ var llWaferStatus = GetLLFixedReadyInOutSlots(ll.Key);
|
|
|
+ moveValues[ll.Key] = Math.Min(pmWafers.Where(wt => CanWaferGotoLL(wt, ll.Key)).Count(), GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count) + llWaferStatus.tOutSlot.Count;
|
|
|
+ }
|
|
|
+
|
|
|
+ var preferLL = moveValues.OrderByDescending(v => v.Value).First().Key;
|
|
|
+ return moveValues[preferLL] > 0 ? preferLL : ModuleName.System;
|
|
|
+ }
|
|
|
+
|
|
|
void RoutingTMSwapActions(List<MoveItem> actions)
|
|
|
{
|
|
|
foreach (var action in actions)
|
|
@@ -2681,13 +2748,20 @@ namespace Venus_RT.Modules
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if(_LLASlotNumber == 2)
|
|
|
+ if(_LLSlotInOutOption == LLSlotInOutOpt.AllInAllOut)
|
|
|
{
|
|
|
- Routing2SlotVacSystem();
|
|
|
+ if (_LLASlotNumber == 2)
|
|
|
+ {
|
|
|
+ Routing2SlotVacSystem();
|
|
|
+ }
|
|
|
+ else if (_LLASlotNumber == 4)
|
|
|
+ {
|
|
|
+ Routing4SlotVacSystem();
|
|
|
+ }
|
|
|
}
|
|
|
- else if(_LLASlotNumber == 4)
|
|
|
+ else
|
|
|
{
|
|
|
- Routing4SlotVacSystem();
|
|
|
+ RoutingFixedSlotVacSystem();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -3060,7 +3134,6 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
private void Routing4SlotVacSystem()
|
|
@@ -3185,6 +3258,375 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void RoutingFixedSlotVacSystem()
|
|
|
+ {
|
|
|
+ var robotWafers = _lstWaferTasks.Where(wt => ModuleHelper.IsTMRobot(wt.currentMod));
|
|
|
+ var lls = _dictModuleTask.Where(mod => ModuleHelper.IsLoadLock(mod.Key) && mod.Value.Scheduler.IsOnline);
|
|
|
+ if (_LLASlotNumber == 2)
|
|
|
+ {
|
|
|
+ if (robotWafers.Count() == 1)
|
|
|
+ {
|
|
|
+ if(ModuleHelper.IsPm(robotWafers.First().destMod))
|
|
|
+ {
|
|
|
+ var destPM = robotWafers.First().destMod;
|
|
|
+ if(_dictModuleTask[destPM].TimeToReady <= 5)
|
|
|
+ {
|
|
|
+ if(_lstWaferTasks.Exists(wt => wt.currentMod == destPM))
|
|
|
+ {
|
|
|
+ var pickHand = SelectTMPickArm(destPM);
|
|
|
+ if(pickHand != Hand.None)
|
|
|
+ {
|
|
|
+ var pmSwap = new List<MoveItem>();
|
|
|
+ pmSwap.Add(new MoveItem(destPM, 0, ModuleName.TMRobot, (int)pickHand, pickHand));
|
|
|
+ pmSwap.Add(new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, destPM, 0, (Hand)robotWafers.First().currentSlot));
|
|
|
+ _tmSchdActions.Enqueue(pmSwap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, destPM, 0, (Hand)robotWafers.First().currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var readySwapLL = lls.Where(ll => CanWaferGotoLL(robotWafers.First(), ll.Key) &&
|
|
|
+ GetLLFixedReadyInOutSlots(ll.Key).tOutSlot.Count == 1 &&
|
|
|
+ GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 1 &&
|
|
|
+ ll.Value.TimeToReady <= 10);
|
|
|
+ if (readySwapLL.Count() > 0)
|
|
|
+ {
|
|
|
+ var destLL = readySwapLL.First().Key;
|
|
|
+ Hand pickHand = SelectTMPickArm(destLL);
|
|
|
+ if (pickHand != Hand.None)
|
|
|
+ {
|
|
|
+ Hand placeHand = (Hand)robotWafers.First().currentSlot;
|
|
|
+ var llSwap = new List<MoveItem>();
|
|
|
+ var llSlots = GetLLFixedReadyInOutSlots(destLL);
|
|
|
+ llSwap.Add(new MoveItem(destLL, llSlots.tOutSlot.First(), ModuleName.TMRobot, (int)pickHand, pickHand));
|
|
|
+ llSwap.Add(new MoveItem(ModuleName.TMRobot, (int)placeHand, destLL, llSlots.tInSlot.First(), placeHand));
|
|
|
+ _tmSchdActions.Enqueue(llSwap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var emptyLL = lls.Where(ll => CanWaferGotoLL(robotWafers.First(), ll.Key) &&
|
|
|
+ GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 1 &&
|
|
|
+ ll.Value.TimeToReady <= 2);
|
|
|
+ if (emptyLL.Count() > 0)
|
|
|
+ {
|
|
|
+ var destLL = emptyLL.First().Key;
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem( ModuleName.TMRobot,
|
|
|
+ robotWafers.First().currentSlot,
|
|
|
+ destLL,
|
|
|
+ GetLLFixedReadyInOutSlots(destLL).tInSlot.First(),
|
|
|
+ (Hand)robotWafers.First().currentSlot) });
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (robotWafers.Count() == 0)
|
|
|
+ {
|
|
|
+ var readyReturnWafers = _lstWaferTasks.Where(wt => ModuleHelper.IsPm(wt.currentMod) && ModuleHelper.IsLoadPort(wt.destMod)).ToList();
|
|
|
+ if(readyReturnWafers.Count > 0)
|
|
|
+ {
|
|
|
+ // try to do a LL swap action
|
|
|
+ var readySwapLL = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).tOutSlot.Count == 1 && GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 1 && ll.Value.TimeToReady <= 10);
|
|
|
+ foreach (var pmWafer in readyReturnWafers)
|
|
|
+ {
|
|
|
+ foreach (var ll in readySwapLL)
|
|
|
+ {
|
|
|
+ if (CanWaferGotoLL(pmWafer, ll.Key))
|
|
|
+ {
|
|
|
+ var returnHand = SelectTMPickArm(pmWafer.currentMod);
|
|
|
+ var pickHand = SelectTMPickArm(ll.Key);
|
|
|
+ var llWaferStatus = GetLLFixedReadyInOutSlots(ll.Key);
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(pmWafer.currentMod, pmWafer.currentSlot, ModuleName.TMRobot, (int)returnHand, returnHand) });
|
|
|
+
|
|
|
+ var llSwapActions = new List<MoveItem>();
|
|
|
+ llSwapActions.Add(new MoveItem(ModuleName.TMRobot, (int)returnHand, ll.Key, llWaferStatus.tInSlot.First(), returnHand));
|
|
|
+ llSwapActions.Add(new MoveItem(ll.Key, llWaferStatus.tOutSlot.First(), ModuleName.TMRobot, (int)pickHand, pickHand));
|
|
|
+ _tmSchdActions.Enqueue(llSwapActions);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // just return to LL
|
|
|
+ var readyInLL = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 1 && ll.Value.TimeToReady <= 5);
|
|
|
+ foreach(var pmWafer in readyReturnWafers)
|
|
|
+ {
|
|
|
+ foreach(var ll in readyInLL)
|
|
|
+ {
|
|
|
+ if(CanWaferGotoLL(pmWafer, ll.Key))
|
|
|
+ {
|
|
|
+ var returnHand = SelectTMPickArm(pmWafer.currentMod);
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(pmWafer.currentMod, pmWafer.currentSlot, ModuleName.TMRobot, (int)returnHand, returnHand) });
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, (int)returnHand, ll.Key, GetLLFixedReadyInOutSlots(ll.Key).tInSlot.First(), returnHand) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var readyPushInLLs = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).tOutSlot.Count == 1 && ll.Value.TimeToReady <= 2);
|
|
|
+ if(readyPushInLLs.Count() > 0)
|
|
|
+ {
|
|
|
+ var destLL = readyPushInLLs.First().Key;
|
|
|
+ if(readyPushInLLs.Count() == 2 && readyPushInLLs.First().Value.Scheduler.IsAtm && readyPushInLLs.Last().Value.Scheduler.IsVac)
|
|
|
+ {
|
|
|
+ destLL = readyPushInLLs.Last().Key;
|
|
|
+ }
|
|
|
+
|
|
|
+ var pickHand = SelectTMPickArm(destLL);
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(destLL, GetLLFixedReadyInOutSlots(destLL).tOutSlot.First(), ModuleName.TMRobot, (int)pickHand, pickHand) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // should not go here
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, "Had better avoid picking two wafers on TM robot arms under Loadlock fixed slot pattern");
|
|
|
+ foreach(var wafer in robotWafers)
|
|
|
+ {
|
|
|
+ if(ModuleHelper.IsPm(wafer.destMod))
|
|
|
+ {
|
|
|
+ if(!_lstWaferTasks.Exists(wt => wt.currentMod == wafer.destMod) && _dictModuleTask[wafer.destMod].TimeToReady <= 2)
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, wafer.destMod, 0, (Hand)wafer.currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var readyInLL = lls.Where(ll => GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 1 && CanWaferGotoLL(wafer, ll.Key) && ll.Value.TimeToReady <= 2);
|
|
|
+ if(readyInLL.Count() > 0)
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, readyInLL.First().Key, GetLLFixedReadyInOutSlots(readyInLL.First().Key).tInSlot.First(), (Hand)wafer.currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else // 4 slot Loadlock
|
|
|
+ {
|
|
|
+ if(robotWafers.Count() > 0)
|
|
|
+ {
|
|
|
+ if (robotWafers.Count() == 2)
|
|
|
+ {
|
|
|
+ if (robotWafers.All(wt => ModuleHelper.IsLoadPort(wt.destMod)))
|
|
|
+ {
|
|
|
+ var destLL = lls.Where(ll => robotWafers.All(wt => CanWaferGotoLL(wt, ll.Key)) &&
|
|
|
+ ll.Value.TimeToReady <= 10 &&
|
|
|
+ GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count == 2).
|
|
|
+ OrderByDescending(ll => GetLLFixedReadyInOutSlots(ll.Key).tOutSlot.Count).
|
|
|
+ OrderBy(ll => ll.Value.TimeToReady);
|
|
|
+
|
|
|
+ if (destLL.Count() > 0)
|
|
|
+ {
|
|
|
+ var swapLL = destLL.First().Key;
|
|
|
+ var llWaferStatus = GetLLFixedReadyInOutSlots(swapLL);
|
|
|
+
|
|
|
+ var swapActions = new List<MoveItem>();
|
|
|
+ swapActions.Add(new MoveItem(ModuleName.TMRobot, robotWafers.First().currentSlot, swapLL, llWaferStatus.tInSlot.First(), (Hand)robotWafers.First().currentSlot));
|
|
|
+ swapActions.Add(new MoveItem(ModuleName.TMRobot, robotWafers.Last().currentSlot, swapLL, llWaferStatus.tInSlot.Last(), (Hand)robotWafers.Last().currentSlot));
|
|
|
+
|
|
|
+ int pickCount = 0;
|
|
|
+ foreach (var slot in llWaferStatus.eOutSlot)
|
|
|
+ {
|
|
|
+ swapActions.Add(new MoveItem(swapLL, slot, ModuleName.TMRobot, pickCount, (Hand)pickCount));
|
|
|
+ }
|
|
|
+ _tmSchdActions.Enqueue(swapActions);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var wafer in robotWafers)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(wafer.destMod))
|
|
|
+ {
|
|
|
+ if (!_lstWaferTasks.Exists(wt => wt.currentMod == wafer.destMod) && _dictModuleTask[wafer.destMod].TimeToReady <= 5)
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, wafer.destMod, 0, (Hand)wafer.currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var placeLL = lls.Where(ll => CanWaferGotoLL(wafer, ll.Key) && ll.Value.TimeToReady <= 5 && GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count > 0).OrderBy(ll => ll.Value.TimeToReady);
|
|
|
+ if (placeLL.Count() > 0)
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, wafer.currentSlot, placeLL.First().Key, GetLLFixedReadyInOutSlots(placeLL.First().Key).tInSlot.First(), (Hand)wafer.currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (robotWafers.Count() == 1)
|
|
|
+ {
|
|
|
+ var robotWafer = robotWafers.First();
|
|
|
+ if (ModuleHelper.IsPm(robotWafer.destMod))
|
|
|
+ {
|
|
|
+ if (_dictModuleTask[robotWafer.destMod].TimeToReady <= 5)
|
|
|
+ {
|
|
|
+ if (_lstWaferTasks.Exists(wt => wt.currentMod == robotWafer.destMod))
|
|
|
+ {
|
|
|
+ var pmSwap = new List<MoveItem>();
|
|
|
+ pmSwap.Add(new MoveItem(robotWafer.destMod, 0, ModuleName.TMRobot, 1 - robotWafer.currentSlot, (Hand)(1 - robotWafer.currentSlot)));
|
|
|
+ pmSwap.Add(new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot));
|
|
|
+ _tmSchdActions.Enqueue(pmSwap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, robotWafer.destMod, 0, (Hand)robotWafer.currentSlot) });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var destLL = lls.Where(ll => CanWaferGotoLL(robotWafer, ll.Key) &&
|
|
|
+ ll.Value.TimeToReady <= 10 &&
|
|
|
+ GetLLFixedReadyInOutSlots(ll.Key).tInSlot.Count > 0).
|
|
|
+ OrderByDescending(ll => GetLLFixedReadyInOutSlots(ll.Key).tOutSlot.Count).
|
|
|
+ OrderBy(ll => ll.Value.TimeToReady);
|
|
|
+
|
|
|
+ if (destLL.Count() > 0)
|
|
|
+ {
|
|
|
+ var swapLL = destLL.First().Key;
|
|
|
+ var llWaferStatus = GetLLFixedReadyInOutSlots(swapLL);
|
|
|
+ var llSwap = new List<MoveItem>();
|
|
|
+ llSwap.Add(new MoveItem(ModuleName.TMRobot, robotWafer.currentSlot, swapLL, llWaferStatus.tInSlot.First(), (Hand)robotWafer.currentSlot));
|
|
|
+ int pickCount = 0;
|
|
|
+ foreach (var slot in llWaferStatus.tOutSlot)
|
|
|
+ {
|
|
|
+ llSwap.Add(new MoveItem(swapLL, slot, ModuleName.TMRobot, pickCount, (Hand)pickCount));
|
|
|
+ pickCount++;
|
|
|
+ }
|
|
|
+
|
|
|
+ _tmSchdActions.Enqueue(llSwap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else // robot empty
|
|
|
+ {
|
|
|
+ var nearlyReadyReturnWafers = _lstWaferTasks.Where(wt => ModuleHelper.IsPm(wt.currentMod) && (ModuleHelper.IsLoadPort(wt.destMod) || _dictModuleTask[wt.currentMod].TimeToReady <= 10)).OrderBy(wt => _dictModuleTask[wt.currentMod].TimeToReady).ToList();
|
|
|
+ var readyLL = lls.Where(ll => ll.Value.TimeToReady <= 10);
|
|
|
+ if(readyLL.Count() > 0)
|
|
|
+ {
|
|
|
+ var llPath = FindTheBestMovePathWithFixSlot(readyLL, nearlyReadyReturnWafers);
|
|
|
+ if(ModuleHelper.IsLoadLock(llPath))
|
|
|
+ {
|
|
|
+ int returnCount = 0;
|
|
|
+ var llWaferStatus = GetLLFixedReadyInOutSlots(llPath);
|
|
|
+ var llSwapActions = new List<MoveItem>();
|
|
|
+ foreach(var wafer in nearlyReadyReturnWafers)
|
|
|
+ {
|
|
|
+ if(CanWaferGotoLL(wafer, llPath) && returnCount < Math.Min(llWaferStatus.tInSlot.Count, 2))
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(new List<MoveItem> { new MoveItem(wafer.currentMod, 0, ModuleName.TMRobot, returnCount, (Hand)returnCount) });
|
|
|
+ llSwapActions.Add(new MoveItem(ModuleName.TMRobot, returnCount, llPath, llWaferStatus.tInSlot[returnCount], (Hand)returnCount));
|
|
|
+ returnCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int pickCount = 0;
|
|
|
+ foreach(var slot in llWaferStatus.tOutSlot)
|
|
|
+ {
|
|
|
+ if (pickCount < 2)
|
|
|
+ {
|
|
|
+ llSwapActions.Add(new MoveItem(llPath, slot, ModuleName.TMRobot, pickCount, (Hand)pickCount));
|
|
|
+ pickCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(llSwapActions.Count > 0)
|
|
|
+ {
|
|
|
+ _tmSchdActions.Enqueue(llSwapActions);
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsTMRobotArmNotReserved(Hand hand)
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, (int)hand) || _lstWaferTasks.Exists(wt => wt.currentMod == ModuleName.TMRobot && wt.currentSlot == (int)hand))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ foreach(var acs in _tmSchdActions)
|
|
|
+ {
|
|
|
+ foreach(var ac in acs)
|
|
|
+ {
|
|
|
+ if ((ac.DestinationModule == ModuleName.TMRobot || ac.SourceModule == ModuleName.TMRobot) && ac.DestinationSlot == (int)hand)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Hand SelectTMPickArm(ModuleName mod)
|
|
|
+ {
|
|
|
+ switch (_tmRobotSingleArmOption)
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ {
|
|
|
+ if (IsTMRobotArmNotReserved(Hand.Blade1))
|
|
|
+ return Hand.Blade1;
|
|
|
+
|
|
|
+ if (IsTMRobotArmNotReserved(Hand.Blade2))
|
|
|
+ return Hand.Blade2;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ {
|
|
|
+ if (IsTMRobotArmNotReserved(Hand.Blade1))
|
|
|
+ return Hand.Blade1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ {
|
|
|
+ if (IsTMRobotArmNotReserved(Hand.Blade2))
|
|
|
+ return Hand.Blade2;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ // Blade1 In Blade2 Out
|
|
|
+ case 3:
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsLoadLock(mod) && IsTMRobotArmNotReserved(Hand.Blade1))
|
|
|
+ return Hand.Blade1;
|
|
|
+
|
|
|
+ if (ModuleHelper.IsPm(mod) && IsTMRobotArmNotReserved(Hand.Blade2))
|
|
|
+ return Hand.Blade2;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ // Blade2 In Blade1 Out
|
|
|
+ case 4:
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsLoadLock(mod) && IsTMRobotArmNotReserved(Hand.Blade2))
|
|
|
+ return Hand.Blade2;
|
|
|
+
|
|
|
+ if (ModuleHelper.IsPm(mod) && IsTMRobotArmNotReserved(Hand.Blade1))
|
|
|
+ return Hand.Blade1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Hand.None;
|
|
|
+ }
|
|
|
+
|
|
|
private List<Hand> GetTMFreeHand()
|
|
|
{
|
|
|
var lstHands = new List<Hand>();
|
|
@@ -3279,6 +3721,50 @@ namespace Venus_RT.Modules
|
|
|
return (readInSlots, readyOutSlots, emptySlots);
|
|
|
}
|
|
|
|
|
|
+ private (List<int> eInSlot, List<int> eOutSlot, List<int> tInSlot, List<int> tOutSlot) GetLLFixedReadyInOutSlots(ModuleName ll)
|
|
|
+ {
|
|
|
+ var eInSlot = new List<int>();
|
|
|
+ var eOutSlot = new List<int>();
|
|
|
+ var tInSlot = new List<int>();
|
|
|
+ var tOutSlot = new List<int>();
|
|
|
+
|
|
|
+ int SlotNumber = ll == ModuleName.LLA ? _LLASlotNumber : _LLBSlotNumber;
|
|
|
+ for (int slot = 0; slot < SlotNumber; slot++)
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckNoWafer(ll, slot) && !_lstWaferTasks.Exists(wafer => (wafer.routedMod == ll && wafer.routedSlot == slot) || (wafer.currentMod == ll && wafer.currentSlot == slot) || (wafer.nextMod == ll && wafer.nextSlot == slot)))
|
|
|
+ {
|
|
|
+ if ((slot >= SlotNumber / 2 && _LLSlotInOutOption == LLSlotInOutOpt.UpperInLowerOut) ||
|
|
|
+ (slot < SlotNumber / 2 && _LLSlotInOutOption == LLSlotInOutOpt.LowerInUpperOut))
|
|
|
+ {
|
|
|
+ eInSlot.Add(slot);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ tInSlot.Add(slot);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WaferManager.Instance.CheckHasWafer(ll, slot))
|
|
|
+ {
|
|
|
+ var wafer = WaferManager.Instance.GetWafer(ll, slot);
|
|
|
+ var waferTask = _lstWaferTasks.Find(wt => wt.waferId == wafer.InnerId && wt.currentMod == ll && wt.currentSlot == slot);
|
|
|
+ if(waferTask == null)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.ERR_ROUTER, ll, $"Routing failed, cannot find inner task associated with {wafer.WaferOrigin}");
|
|
|
+ }
|
|
|
+ else if (waferTask.movingStatus == RState.End)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(waferTask.destMod))
|
|
|
+ tOutSlot.Add(slot);
|
|
|
+ else if (_dictModuleTask[ll].Scheduler.WaferArrivedTicks(slot) > waferTask.llDelayTime * 1000)
|
|
|
+ eOutSlot.Add(slot);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (eInSlot, eOutSlot, tInSlot, tOutSlot);
|
|
|
+ }
|
|
|
+
|
|
|
private (List<WaferInfo> wafers, List<int> emptySlots) GetLLWaferExistance(ModuleName ll)
|
|
|
{
|
|
|
var lstWafers = new List<WaferInfo>();
|
|
@@ -3598,7 +4084,7 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
if (recipe.Header.Temperature != null && recipe.Header.Temperature != "" && (currentChamberTemperature > Convert.ToSingle(recipe.Header.Temperature) + 10 || currentChamberTemperature < Convert.ToSingle(recipe.Header.Temperature) - 10))
|
|
|
{
|
|
|
- LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Start job失败,由于{seq.Name}里{module}腔体温度{currentChamberTemperature}与{recipeName} Recipe温度{recipe.Header.Temperature}不匹配");
|
|
|
+ LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Start job失败,由于{module}腔体温度{currentChamberTemperature}与{recipeName} Recipe温度{recipe.Header.Temperature}不匹配");
|
|
|
return false;
|
|
|
}
|
|
|
}
|