|
@@ -78,6 +78,8 @@ namespace Venus_RT.Modules
|
|
|
List<int> _LLAOutSlot = new List<int> { 0, 1, 2, 3 };
|
|
|
List<int> _LLBInSlot = new List<int> { 0, 1, 2, 3 };
|
|
|
List<int> _LLBOutSlot = new List<int> { 0, 1, 2, 3 };
|
|
|
+ int _LLASlotNumber = 4;
|
|
|
+ int _LLBSlotNumber = 4;
|
|
|
|
|
|
List<MoveItem> _movingItems = new List<MoveItem>();
|
|
|
List<MoveItem> _efemMovingItems = new List<MoveItem>();
|
|
@@ -102,6 +104,9 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
InitModules();
|
|
|
|
|
|
+ _LLASlotNumber = SC.GetValue<int>("LLA.SlotNumber");
|
|
|
+ _LLBSlotNumber = SC.GetValue<int>("LLB.SlotNumber");
|
|
|
+
|
|
|
DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
|
|
|
DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer);
|
|
|
DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
|
|
@@ -568,6 +573,8 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ StartNewJob();
|
|
|
}
|
|
|
|
|
|
private void driveVacSystem()
|
|
@@ -584,7 +591,6 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
if (mod.Value.IsAvailable && _vacModules[mod.Key].MovingStatus == MovingStatus.Staying)
|
|
|
{
|
|
|
-
|
|
|
if(ModuleHelper.IsLoadLock(mod.Key))
|
|
|
{
|
|
|
var inSlots = mod.Key == ModuleName.LLA ? _LLAInSlot : _LLBInSlot;
|
|
@@ -859,11 +865,6 @@ namespace Venus_RT.Modules
|
|
|
if (ProcessLLEFEMRobotTask(scheduler.Key))
|
|
|
return;
|
|
|
}
|
|
|
- else if(ModuleHelper.IsLoadPort(scheduler.Key))
|
|
|
- {
|
|
|
- if (ProcessLPEFEMRobotTask(scheduler.Key))
|
|
|
- return;
|
|
|
- }
|
|
|
else if(ModuleHelper.IsAligner(scheduler.Key))
|
|
|
{
|
|
|
if (ProcessAlignerEFEMRobotTask(scheduler.Key))
|
|
@@ -874,6 +875,11 @@ namespace Venus_RT.Modules
|
|
|
if (ProcessCoolingEFEMRobotTask(scheduler.Key))
|
|
|
return;
|
|
|
}
|
|
|
+ else if (ModuleHelper.IsLoadPort(scheduler.Key))
|
|
|
+ {
|
|
|
+ if (ProcessLPEFEMRobotTask(scheduler.Key))
|
|
|
+ return;
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
// should not go here
|
|
@@ -974,6 +980,83 @@ namespace Venus_RT.Modules
|
|
|
return _efemMovingItems.Count > 0;
|
|
|
}
|
|
|
|
|
|
+ private Tuple<int, int> GetPMWaferExistence()
|
|
|
+ {
|
|
|
+ int exist = 0;
|
|
|
+ int empty = 0;
|
|
|
+ foreach (var atmModule in _atmModules)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(atmModule.Key))
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckHasWafer(atmModule.Key, 0))
|
|
|
+ exist++;
|
|
|
+ else
|
|
|
+ empty++;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Tuple<int, int>(exist, empty);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int GetTMRobotWaferCount()
|
|
|
+ {
|
|
|
+ return (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) ? 1 : 0) + (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) ? 1 : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int GetEfemRoborWaferCount()
|
|
|
+ {
|
|
|
+ return (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) ? 1 : 0) + (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) ? 1 : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Tuple<int, int> GetLLProcessStatusCount(ModuleName ll)
|
|
|
+ {
|
|
|
+ int processedCount = 0;
|
|
|
+ int unprocessCount = 0;
|
|
|
+ int slotCount = ll == ModuleName.LLA ? _LLASlotNumber : _LLBSlotNumber;
|
|
|
+ if(ModuleHelper.IsLoadLock(ll))
|
|
|
+ {
|
|
|
+ for(int i = 0; i < slotCount;i++)
|
|
|
+ {
|
|
|
+ if(WaferManager.Instance.CheckHasWafer(ll, i))
|
|
|
+ {
|
|
|
+ if(CheckWaferNeedProcessAndPMAvailable(ll, i))
|
|
|
+ unprocessCount++;
|
|
|
+ else
|
|
|
+ processedCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Tuple<int, int>(processedCount, unprocessCount);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private int GetAtmInerWaferCount()
|
|
|
+ {
|
|
|
+ int nCount = 0;
|
|
|
+ foreach(var atmModule in _atmModules)
|
|
|
+ {
|
|
|
+ if (!ModuleHelper.IsEFEMRobot(atmModule.Key) && WaferManager.Instance.CheckHasWafer(atmModule.Key, 0))
|
|
|
+ nCount++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return nCount;
|
|
|
+ }
|
|
|
+ private bool IsReadyPushWaferIn()
|
|
|
+ {
|
|
|
+ var llaWaferStatus = GetLLProcessStatusCount(ModuleName.LLA);
|
|
|
+ var llbWaferStatus = GetLLProcessStatusCount(ModuleName.LLB);
|
|
|
+ var pmWaferStatus = GetPMWaferExistence();
|
|
|
+ if (pmWaferStatus.Item2 <= (llaWaferStatus.Item2 + llbWaferStatus.Item2))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (GetEfemRoborWaferCount() >= 1 && GetAtmInerWaferCount() > 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
private bool ProcessLPEFEMRobotTask(ModuleName lp)
|
|
|
{
|
|
|
// check return
|
|
@@ -995,16 +1078,16 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (_efemMovingItems.Count > 0)
|
|
|
- return true;
|
|
|
-
|
|
|
- var outSlots = GetNextWaferInJobQueue(lp);
|
|
|
- foreach(var slot in outSlots)
|
|
|
+ if(_efemMovingItems.Count == 0 && IsReadyPushWaferIn())
|
|
|
{
|
|
|
- var hand = GetEFEMRobotFreeHand();
|
|
|
- if(hand != Hand.None)
|
|
|
+ var outSlots = GetNextWaferInJobQueue(lp);
|
|
|
+ foreach (var slot in outSlots)
|
|
|
{
|
|
|
- _efemMovingItems.Add(new MoveItem(lp, slot, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
+ var hand = GetEFEMRobotFreeHand();
|
|
|
+ if (hand != Hand.None)
|
|
|
+ {
|
|
|
+ _efemMovingItems.Add(new MoveItem(lp, slot, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1015,10 +1098,6 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
var inSlots = new List<int>();
|
|
|
|
|
|
-
|
|
|
- //if (GetSystemInnerWaferCount() >= SystemInternalWaferCount || GetBufferWaferCount() > _maxBufferWaferCount)
|
|
|
- //return new SlotItem(ModuleName.System, -1);
|
|
|
-
|
|
|
foreach (var cj in _lstControlJobs)
|
|
|
{
|
|
|
if (lp != ModuleName.System && (cj.Module != lp.ToString()))
|
|
@@ -1056,13 +1135,20 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
_efemMovingItems.Add(new MoveItem(aligner, 0, ModuleName.EfemRobot, (int)hand, hand));
|
|
|
}
|
|
|
+
|
|
|
+ //// check with whether another robot arm wafer wait go to aligner
|
|
|
+ //var robotSlots = GetEfemRobotWaferReadyInHands(aligner);
|
|
|
+ //if (robotSlots.Count > 0)
|
|
|
+ //{
|
|
|
+ // _efemMovingItems.Add(new MoveItem(ModuleName.EfemRobot, robotSlots.First(), aligner, 0, (Hand)robotSlots.First()));
|
|
|
+ //}
|
|
|
}
|
|
|
- else
|
|
|
+ else if(WaferManager.Instance.CheckNoWafer(aligner, 0))
|
|
|
{
|
|
|
var robotSlots = GetEfemRobotWaferReadyInHands(aligner);
|
|
|
if(robotSlots.Count > 0)
|
|
|
{
|
|
|
- _efemMovingItems.Add(new MoveItem(aligner, 0, ModuleName.EfemRobot, robotSlots.First(), (Hand)robotSlots.First()));
|
|
|
+ _efemMovingItems.Add(new MoveItem(ModuleName.EfemRobot, robotSlots.First(), aligner, 0, (Hand)robotSlots.First()));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1093,7 +1179,7 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
private void RuningEFEMRobotTask()
|
|
|
{
|
|
|
- if (_efemRobot.IsAvailable)
|
|
|
+ if (_efemRobot.IsAvailable && _efemMovingItems.Count > 0)
|
|
|
{
|
|
|
if (_efemRobot.PostMoveItems(_efemMovingItems.ToArray()))
|
|
|
{
|
|
@@ -1247,6 +1333,140 @@ namespace Venus_RT.Modules
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ private List<ModuleName> GetPmUsedInRunningPj()
|
|
|
+ {
|
|
|
+ var pmUsed = new List<ModuleName>();
|
|
|
+ foreach (var cj in _lstControlJobs)
|
|
|
+ {
|
|
|
+ if (cj.State != EnumControlJobState.Executing && cj.State != EnumControlJobState.Paused)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ if (pj.ControlJobName == cj.Name && (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused))
|
|
|
+ {
|
|
|
+ for (int i = 0; i < pj.Sequence.Steps.Count; i++)
|
|
|
+ {
|
|
|
+ SequenceStepInfo stepInfo = pj.Sequence.Steps[i];
|
|
|
+ foreach (var module in stepInfo.StepModules)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(module) && !pmUsed.Contains(module))
|
|
|
+ pmUsed.Add(module);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return pmUsed;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<SchedulerPM> GetPmNeeded(ControlJobInfo cj)
|
|
|
+ {
|
|
|
+ List<SchedulerPM> result = new List<SchedulerPM>();
|
|
|
+
|
|
|
+ foreach (var pj in _lstProcessJobs)
|
|
|
+ {
|
|
|
+ if (pj.ControlJobName != cj.Name)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ var seq = pj.Sequence;
|
|
|
+ for (int i = 0; i < seq.Steps.Count; i++)
|
|
|
+ {
|
|
|
+ SequenceStepInfo stepInfo = seq.Steps[i];
|
|
|
+ foreach (var module in stepInfo.StepModules)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(module))
|
|
|
+ {
|
|
|
+ var pm = _vacSchedulers[module] as SchedulerPM;
|
|
|
+
|
|
|
+ if (pm != null && !result.Contains(pm))
|
|
|
+ {
|
|
|
+ result.Add(pm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ private void PreJobClean(ControlJobInfo cj)
|
|
|
+ {
|
|
|
+ if (cj.IsPreJobCleanDone)
|
|
|
+ return;
|
|
|
+
|
|
|
+ cj.IsPreJobCleanDone = true;
|
|
|
+
|
|
|
+ List<SchedulerPM> pms = GetPmNeeded(cj);
|
|
|
+ foreach (var pm in pms)
|
|
|
+ {
|
|
|
+ pm.PreJobClean();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private bool ActiveProcessJob(ProcessJobInfo pj)
|
|
|
+ {
|
|
|
+ foreach (var pjSlotWafer in pj.SlotWafers)
|
|
|
+ {
|
|
|
+ WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
|
|
+
|
|
|
+ wafer.ProcessJob = pj;
|
|
|
+ wafer.NextSequenceStep = 0;
|
|
|
+
|
|
|
+ WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString());
|
|
|
+ }
|
|
|
+
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName);
|
|
|
+
|
|
|
+ CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
|
|
|
+ JobDataRecorder.StartPJ(pj.InnerId.ToString(), carrier.InnerId.ToString(), cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
|
|
|
+
|
|
|
+ pj.SetState(EnumProcessJobState.Processing);
|
|
|
+
|
|
|
+ PreJobClean(cj);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ private void StartNewJob()
|
|
|
+ {
|
|
|
+ ControlJobInfo cjActived = null;
|
|
|
+
|
|
|
+ List<ModuleName> pmOccupied = GetPmUsedInRunningPj();
|
|
|
+ foreach (var cj in _lstControlJobs)
|
|
|
+ {
|
|
|
+ if (cj.State != EnumControlJobState.Executing)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ cjActived = cj;
|
|
|
+
|
|
|
+ foreach (var pjName in cjActived.ProcessJobNameList)
|
|
|
+ {
|
|
|
+ var pj = _lstProcessJobs.Find(x => x.Name == pjName);
|
|
|
+ if (pj == null)
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"Not find pj named {pjName} in {cjActived.Name}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pj.State == EnumProcessJobState.Queued)
|
|
|
+ {
|
|
|
+ if (CheckSequencePmReady(pj.Sequence, pmOccupied, out var pmUsed, out string reason))
|
|
|
+ {
|
|
|
+ ActiveProcessJob(pj);
|
|
|
+
|
|
|
+ foreach (var moduleName in pmUsed)
|
|
|
+ {
|
|
|
+ if (!pmOccupied.Contains(moduleName))
|
|
|
+ pmOccupied.Add(moduleName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
}
|
|
|
}
|