|
@@ -17,6 +17,7 @@ using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
+using System.Runtime.Remoting.Contexts;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
using Venus_Core;
|
|
@@ -138,10 +139,10 @@ namespace Venus_RT.Modules
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
|
|
|
- if (cj.State == EnumControlJobState.WaitingForStart)
|
|
|
+ if (cj.State == EnumControlJobState.Queued)
|
|
|
{
|
|
|
|
|
|
- cj.SetState(EnumControlJobState.Executing);
|
|
|
+ cj.SetState(EnumControlJobState.WaitingForStart);
|
|
|
//PreJobClean(cj);
|
|
|
|
|
|
cj.JetState = EnumJetCtrlJobState.Quequed;
|
|
@@ -149,6 +150,11 @@ namespace Venus_RT.Modules
|
|
|
|
|
|
cj.StartTime = DateTime.Now;
|
|
|
|
|
|
+ cj.IsPreJobCleanDone = false;
|
|
|
+ cj.IsPreJobCleanStart = false;
|
|
|
+ cj.IsPostJobCleanDone = false;
|
|
|
+ cj.IsPostJobCleanStart = false;
|
|
|
+
|
|
|
if (_IsFirstLot)
|
|
|
{
|
|
|
_dbCallback.LotCreated(cj);
|
|
@@ -191,6 +197,17 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
_cycleWatch.Restart();
|
|
|
}
|
|
|
+ if (string.IsNullOrEmpty(cj.PreJobClean))
|
|
|
+ {
|
|
|
+ cj.IsPreJobCleanStart = true;
|
|
|
+ cj.IsPreJobCleanDone = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (string.IsNullOrEmpty(cj.PostJobClean))
|
|
|
+ {
|
|
|
+ cj.IsPostJobCleanStart = true;
|
|
|
+ cj.IsPostJobCleanDone = true;
|
|
|
+ }
|
|
|
|
|
|
|
|
|
_starttime = DateTime.Now;
|
|
@@ -246,9 +263,10 @@ namespace Venus_RT.Modules
|
|
|
cj.LotName = lotId;
|
|
|
cj.LotInnerId = Guid.NewGuid();
|
|
|
cj.LotWafers = new List<WaferInfo>();
|
|
|
- cj.SetState(EnumControlJobState.WaitingForStart);
|
|
|
+ cj.SetState(EnumControlJobState.Queued);
|
|
|
cj.JetState = EnumJetCtrlJobState.Created;
|
|
|
-
|
|
|
+ cj.PreJobClean = param.ContainsKey("PreCleanRecipeName") ? (string)param["PreCleanRecipeName"] : string.Empty;
|
|
|
+ cj.PostJobClean = param.ContainsKey("PostCleanRecipeName") ? (string)param["PostCleanRecipeName"] : string.Empty;
|
|
|
Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
|
|
|
Dictionary<string, List<Tuple<ModuleName, int>>> seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
|
|
|
Dictionary<string, string> indexSequence = new Dictionary<string, string>();
|
|
@@ -450,6 +468,7 @@ namespace Venus_RT.Modules
|
|
|
//run sequence
|
|
|
if (IsSequenceCycle)
|
|
|
{
|
|
|
+ CheckCleanJobDone();
|
|
|
CheckCycleDone();
|
|
|
SETMRobotTask();
|
|
|
SERunTMRobotTask();
|
|
@@ -467,7 +486,67 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- #region 推进|检查|计数
|
|
|
+ #region 推进|检查|计数|Clean
|
|
|
+ private void CheckCleanJobDone()
|
|
|
+ {
|
|
|
+ //所有已安装pm都可用
|
|
|
+ if (IsAllNeedPMsAvailabe() && _TMRobot.IsAvailable)
|
|
|
+ {
|
|
|
+ //执行了PreClean 将其置为Executing
|
|
|
+ if (_lstControlJobs.Exists(x => x.IsPreJobCleanStart && !x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(x => x.IsPreJobCleanStart && !x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart);
|
|
|
+ cj.IsPreJobCleanDone = true;
|
|
|
+ cj.SetState(EnumControlJobState.Executing);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //执行了PostClean 将其置为Executing
|
|
|
+ if (_lstControlJobs.Exists(x => x.IsPostJobCleanStart && !x.IsPostJobCleanDone && x.State == EnumControlJobState.Executing))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(x => x.IsPostJobCleanStart && !x.IsPostJobCleanDone && x.State == EnumControlJobState.Executing);
|
|
|
+ cj.IsPostJobCleanDone = true;
|
|
|
+ cj.SetState(EnumControlJobState.Completed);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //no exist excuting cj && exist waiting cj
|
|
|
+ if (!_lstControlJobs.Exists(x => x.State == EnumControlJobState.Executing) &&
|
|
|
+ _lstControlJobs.Exists(x => !x.IsPreJobCleanStart && !x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(x => !x.IsPreJobCleanStart && !x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart);
|
|
|
+ RunPreCleanJob(cj);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_lstControlJobs.Exists(x => x.IsPreJobCleanStart && x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(x => x.IsPreJobCleanStart && x.IsPreJobCleanDone && x.State == EnumControlJobState.WaitingForStart);
|
|
|
+ cj.SetState(EnumControlJobState.Executing);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RunPreCleanJob(ControlJobInfo cj)
|
|
|
+ {
|
|
|
+ foreach (SchedulerPM pm in dictSchedulers.Values)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(pm.Module) && pm.IsAvailable && pm.RunJobCleanTask(cj.PreJobClean))
|
|
|
+ {
|
|
|
+ cj.IsPreJobCleanStart = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (cj.IsPreJobCleanStart == true && IsAllNeedPMsAvailabe())
|
|
|
+ {
|
|
|
+ cj.IsPreJobCleanDone = true;
|
|
|
+ cj.SetState(EnumControlJobState.Executing);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
private void CheckCycleDone()
|
|
|
{
|
|
|
|
|
@@ -492,32 +571,111 @@ namespace Venus_RT.Modules
|
|
|
if (CycleIndex >= CycleNum)
|
|
|
{
|
|
|
_lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing).SetState(EnumControlJobState.Completed);
|
|
|
- _cycleState = RState.End;
|
|
|
+ if (_lstControlJobs.Exists(lcj => lcj.State == EnumControlJobState.Executing))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing);
|
|
|
+ if (!cj.IsPostJobCleanStart)
|
|
|
+ {
|
|
|
+ foreach (SchedulerPM pm in dictSchedulers.Values)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(pm.Module) && pm.IsAvailable)
|
|
|
+ {
|
|
|
+ pm.RunJobCleanTask(cj.PostJobClean);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _pastWafer += _currentWafer;
|
|
|
+ cj.IsPostJobCleanStart = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cj.SetState(EnumControlJobState.Completed);
|
|
|
+ cj.IsPostJobCleanDone = true;
|
|
|
+ _cycleState = RState.End;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _pastWafer += _currentWafer;
|
|
|
- ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing);
|
|
|
- _currentWafer = 0;
|
|
|
-
|
|
|
- int maxslot = 0;
|
|
|
- cj.LotWafers.ForEach(x => maxslot = x.OriginSlot > maxslot ? x.OriginSlot : maxslot);
|
|
|
- //waiting status means no use
|
|
|
- movingStatus = new List<MovingStatus>();
|
|
|
- movingStatus.AddRange(new MovingStatus[maxslot + 1]);
|
|
|
- for (int i = 0; i < movingStatus.Count; i++)
|
|
|
- movingStatus[i] = MovingStatus.Waiting;
|
|
|
- foreach (var wafer in cj.LotWafers)
|
|
|
+ //if the pm is excuting => run postclean
|
|
|
+ if (_lstControlJobs.Exists(lcj => lcj.State == EnumControlJobState.Executing))
|
|
|
+ {
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing);
|
|
|
+ if (!cj.IsPostJobCleanStart)
|
|
|
+ {
|
|
|
+ foreach (SchedulerPM pm in dictSchedulers.Values)
|
|
|
+ {
|
|
|
+ if (ModuleHelper.IsPm(pm.Module) && pm.IsAvailable)
|
|
|
+ {
|
|
|
+ pm.RunJobCleanTask(cj.PostJobClean);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _pastWafer += _currentWafer;
|
|
|
+ cj.IsPostJobCleanStart = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cj.SetState(EnumControlJobState.Completed);
|
|
|
+ cj.IsPostJobCleanDone = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //if is Completed => run preclean
|
|
|
+ if (_lstControlJobs.Exists(lcj => lcj.State == EnumControlJobState.Completed))
|
|
|
{
|
|
|
- WaferInfo currentWafer = WaferManager.Instance.GetWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot);
|
|
|
- WaferManager.Instance.UpdateWaferProcessStatus((ModuleName)wafer.OriginStation, wafer.OriginSlot, EnumWaferProcessStatus.Idle);
|
|
|
- currentWafer.ProcessJob = _lstProcessJobs.Find(x => x.Sequence.Name == wafer.SequenceName);
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Completed);
|
|
|
+ cj.SetState(EnumControlJobState.WaitingForStart);
|
|
|
|
|
|
- if (currentWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("VPA"))
|
|
|
- movingStatus[wafer.OriginSlot] = MovingStatus.WaitAlign;
|
|
|
+ if (string.IsNullOrEmpty(cj.PreJobClean))
|
|
|
+ {
|
|
|
+ cj.IsPreJobCleanStart = true;
|
|
|
+ cj.IsPreJobCleanDone = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cj.IsPreJobCleanStart = false;
|
|
|
+ cj.IsPreJobCleanDone = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (string.IsNullOrEmpty(cj.PostJobClean))
|
|
|
+ {
|
|
|
+ cj.IsPostJobCleanStart = true;
|
|
|
+ cj.IsPostJobCleanDone = true;
|
|
|
+ }
|
|
|
else
|
|
|
- movingStatus[wafer.OriginSlot] = MovingStatus.WaitProcess;
|
|
|
+ {
|
|
|
+ cj.IsPostJobCleanStart = false;
|
|
|
+ cj.IsPostJobCleanDone = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ _currentWafer = 0;
|
|
|
+
|
|
|
+ int maxslot = 0;
|
|
|
+ cj.LotWafers.ForEach(x => maxslot = x.OriginSlot > maxslot ? x.OriginSlot : maxslot);
|
|
|
+ //waiting status means no use
|
|
|
+ movingStatus = new List<MovingStatus>();
|
|
|
+ movingStatus.AddRange(new MovingStatus[maxslot + 1]);
|
|
|
+ for (int i = 0; i < movingStatus.Count; i++)
|
|
|
+ movingStatus[i] = MovingStatus.Waiting;
|
|
|
+
|
|
|
+
|
|
|
+ foreach (var wafer in cj.LotWafers)
|
|
|
+ {
|
|
|
+ WaferInfo currentWafer = WaferManager.Instance.GetWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot);
|
|
|
+ WaferManager.Instance.UpdateWaferProcessStatus((ModuleName)wafer.OriginStation, wafer.OriginSlot, EnumWaferProcessStatus.Idle);
|
|
|
+ currentWafer.ProcessJob = _lstProcessJobs.Find(x => x.Sequence.Name == wafer.SequenceName);
|
|
|
+
|
|
|
+ if (currentWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("VPA"))
|
|
|
+ movingStatus[wafer.OriginSlot] = MovingStatus.WaitAlign;
|
|
|
+ else
|
|
|
+ movingStatus[wafer.OriginSlot] = MovingStatus.WaitProcess;
|
|
|
+ }
|
|
|
+
|
|
|
+ RunPreCleanJob(cj);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -533,9 +691,9 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
|
|
|
private bool WaferAllInVCE()
|
|
|
- {
|
|
|
- ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing);
|
|
|
+ {
|
|
|
bool flag = true;
|
|
|
+ ControlJobInfo cj = _lstControlJobs.Find(lcj => lcj.State == EnumControlJobState.Executing|| lcj.State == EnumControlJobState.Completed);
|
|
|
cj.LotWafers.ForEach(wafer => flag = WaferManager.Instance.CheckHasWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot) && flag);
|
|
|
return flag;
|
|
|
}
|