2126 lines
76 KiB
C#
2126 lines
76 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Windows.Media.Imaging;
|
||
using Aitex.Core.Common;
|
||
using Aitex.Core.RT.DataCenter;
|
||
using Aitex.Core.RT.Device;
|
||
using Aitex.Core.RT.Event;
|
||
using Aitex.Core.RT.Log;
|
||
using Aitex.Core.RT.RecipeCenter;
|
||
using Aitex.Core.RT.Routine;
|
||
using Aitex.Core.RT.SCCore;
|
||
using Aitex.Core.Util;
|
||
using Aitex.Sorter.Common;
|
||
using MECF.Framework.Common.DataCenter;
|
||
using MECF.Framework.Common.DBCore;
|
||
using MECF.Framework.Common.Equipment;
|
||
using MECF.Framework.Common.Jobs;
|
||
using MECF.Framework.Common.Schedulers;
|
||
using MECF.Framework.Common.SubstrateTrackings;
|
||
using MECF.Framework.FA.Core.FAControl;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
|
||
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.TMs;
|
||
using SicRT.Modules.Schedulers;
|
||
using SicRT.Scheduler;
|
||
|
||
namespace SicRT.Modules
|
||
{
|
||
public partial class AutoTransfer : SchedulerModuleFactory
|
||
{
|
||
/* 几个问题待解决
|
||
* 1.参数
|
||
* 2.Routine判断是否执行完了
|
||
*
|
||
*/
|
||
private bool _isPmAInstal = true;
|
||
private bool _isPmBInstal = false;
|
||
private bool _cotrolJobComplete = false;
|
||
|
||
private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
|
||
private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
|
||
|
||
//private Object _locker = new Object();
|
||
private List<SchedulerPM> _lstPmsCurrentSequence = new List<SchedulerPM>();
|
||
|
||
private const string LogSource = "Scheduler";
|
||
private const string StatsNameTotalRunningWafer = "TotalRunningWafer";
|
||
private const string StatsNameTotalWaferProcessedPM1 = "PM1.WaferProcessed";
|
||
private const string StatsNameTotalWaferProcessedPM2 = "PM2.WaferProcessed";
|
||
|
||
private bool _isInited;
|
||
|
||
private bool _isCycleMode;
|
||
private int _cycleSetPoint = 0;
|
||
private int _cycledCount = 0;
|
||
private int _cycledWafer = 0;
|
||
private int _totalWaferWhenStart = 0;
|
||
private bool _AllModuleFinised = false; //所有模块工作都已经完成
|
||
private string _curRecipeName = "";
|
||
private string _curSequenceName = "";
|
||
private bool _canSetHeat = false; //需不需要PM开始停止加热(TMRobot从LoadLock开始取盘)
|
||
|
||
private bool _isModuleErrorPrevious;
|
||
private bool[] _isPMErrorPrevious = new bool[4];
|
||
|
||
private ushort _debugger2 = 0;
|
||
private ushort _debugger3 = 0;
|
||
private ushort _debugger4 = 0;
|
||
private ushort _debugger5 = 0;
|
||
private ushort _debugger6 = 0;
|
||
private ushort _debugger7 = 0;
|
||
private ushort _debugger8 = 0;
|
||
|
||
private R_TRIG _trigJobComplete = new R_TRIG();
|
||
private R_TRIG _loadLockFinishedTrig = new R_TRIG(); //LoadLock完成后充气需要发出蜂鸣
|
||
private R_TRIG _loadLockStartTrig = new R_TRIG(); //LoadLock放入Wafer后需要Purge
|
||
private R_TRIG _updateAutoJobLocation = new R_TRIG(); //需要向数据库更新Wafer位置
|
||
private string _pm1WaferStaus = "";
|
||
|
||
private string strCurrentRecipeName, strCurrentJobID;
|
||
|
||
public AutoTransfer()
|
||
{
|
||
|
||
DATA.Subscribe("Scheduler.IsCycleMode", () => _isCycleMode);
|
||
DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
|
||
DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
|
||
DATA.Subscribe("Scheduler.RecipeName", () => _curRecipeName);
|
||
DATA.Subscribe("Scheduler.SequenceName", () => _curSequenceName);
|
||
|
||
DATA.Subscribe("LoadLock.LocalJobName", () =>
|
||
{
|
||
var jb = _lstControlJobs.Find(x => x.Module == "LoadLock");
|
||
if (jb != null)
|
||
return jb.Name;
|
||
return "";
|
||
});
|
||
DATA.Subscribe("LoadLock.LocalJobStatus", () =>
|
||
{
|
||
var jb = _lstControlJobs.Find(x => x.Module == "LoadLock");
|
||
if (jb != null)
|
||
return jb.State.ToString();
|
||
return "";
|
||
});
|
||
}
|
||
|
||
public bool HasJobRunning
|
||
{
|
||
get { return _lstControlJobs.Count > 0; }
|
||
}
|
||
|
||
|
||
public void Clear()
|
||
{
|
||
_tmRobot.ResetTask();
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
pm.ResetTask();
|
||
}
|
||
foreach (var ll in _lstLls)
|
||
{
|
||
ll.ResetTask();
|
||
}
|
||
_buffer.ResetTask();
|
||
_preHeat.ResetTask();
|
||
|
||
_lstControlJobs.Clear();
|
||
_lstProcessJobs.Clear();
|
||
}
|
||
|
||
public void GetConfig()
|
||
{
|
||
_cycledCount = 0;
|
||
_isPmAInstal = SC.GetValue<bool>("System.SetUp.IsPM1Installed");
|
||
_isPmBInstal = SC.GetValue<bool>("System.SetUp.IsPM2Installed");
|
||
|
||
_isCycleMode = SC.GetValue<bool>("System.IsCycleMode");
|
||
_cycleSetPoint = _isCycleMode ? SC.GetValue<int>("System.CycleCount") : 0;
|
||
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
pm.GetConfigInfo();
|
||
}
|
||
}
|
||
|
||
#region Job Management
|
||
|
||
public void CreateJob(Dictionary<string, object> param)
|
||
{
|
||
string[] slotSequence = (string[])param["SlotSequence"];
|
||
string jobId = (string)param["JobId"] + DateTime.Now.ToString("HHmmss");
|
||
string module = (string)param["Module"];
|
||
bool autoStart = (bool)param["AutoStart"];
|
||
|
||
|
||
if (string.IsNullOrEmpty(jobId))
|
||
{
|
||
jobId = "CJ_Local_" + module;
|
||
}
|
||
|
||
Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
|
||
Dictionary<string, List<int>> seqSlotWafers = new Dictionary<string, List<int>>();
|
||
Dictionary<string, string> indexSequence = new Dictionary<string, string>();
|
||
|
||
bool enableGroupBySequence = SC.GetValue<bool>("System.Scheduler.GroupWaferBySequence");
|
||
|
||
for (int i = 0; i < 1; i++)
|
||
{
|
||
if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
|
||
continue;
|
||
|
||
string groupName = i.ToString();
|
||
indexSequence[groupName] = slotSequence[i];
|
||
|
||
if (!seqSlot.ContainsKey(groupName))
|
||
{
|
||
seqSlot[groupName] = new bool[1];
|
||
}
|
||
|
||
if (!seqSlotWafers.ContainsKey(groupName))
|
||
{
|
||
seqSlotWafers[groupName] = new List<int>();
|
||
}
|
||
|
||
seqSlot[groupName][i] = true;
|
||
seqSlotWafers[groupName].Add(i);
|
||
}
|
||
|
||
if (seqSlotWafers.Count == 0)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"Can not create job, no wafer assigned");
|
||
return;
|
||
}
|
||
|
||
List<ProcessJobInfo> pjs = new List<ProcessJobInfo>();
|
||
string[] seqs = seqSlot.Keys.ToArray();
|
||
|
||
List<string> pjIDs = new List<string>();
|
||
for (int i = 0; i < seqs.Length; i++)
|
||
{
|
||
var name = jobId + "_" + (i + 1);
|
||
|
||
if (!CreateProcessJob(name, indexSequence[seqs[i]], seqSlotWafers[seqs[i]], autoStart)) //ProcessJob创建失败直接返回,不再创建ControlJob
|
||
return;
|
||
|
||
pjIDs.Add(name);
|
||
}
|
||
|
||
if (!CreateControlJob(jobId, module, pjIDs, autoStart))
|
||
{
|
||
foreach (var pjName in pjIDs)
|
||
{
|
||
var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
|
||
if (pj != null)
|
||
_lstProcessJobs.Remove(pj);
|
||
}
|
||
}
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
|
||
if (wafer != null)
|
||
{
|
||
if (wafer.ProcessState == EnumWaferProcessStatus.Idle)
|
||
{
|
||
WaferManager.Instance.GetWafer(_loadlock.Module, 0).NextSequenceStep = 0;
|
||
}
|
||
|
||
wafer.LotId = (string)param["JobId"];
|
||
string recipeName = _curRecipeName;
|
||
if (recipeName.IndexOf(@"\") > 0)
|
||
{
|
||
recipeName = recipeName.Substring(recipeName.LastIndexOf(@"\") + 1);
|
||
}
|
||
|
||
strCurrentRecipeName = recipeName;
|
||
strCurrentJobID = (string)param["JobId"];
|
||
AutoJobRecorder.Add(wafer.InnerId.ToString(), recipeName, (string)param["JobId"], ModuleName.LoadLock.ToString(),GetWaferStatue(wafer));
|
||
}
|
||
}
|
||
|
||
public bool CreateControlJob(string jobId, string module, List<string> pjIDs, bool isAutoStart)
|
||
{
|
||
if (_lstControlJobs.Exists(x => x.Name == jobId))
|
||
{
|
||
EV.PostWarningLog(LogSource, $"{jobId} is already created");
|
||
return false;
|
||
}
|
||
|
||
if (_lstProcessJobs.Count <= 0) //判断上一步ProcessJob是否创建成功
|
||
{
|
||
EV.PostWarningLog(LogSource, $"process job is not exist");
|
||
return false;
|
||
}
|
||
|
||
ControlJobInfo cj = new ControlJobInfo();
|
||
cj.Name = jobId;
|
||
cj.Module = module;
|
||
cj.SetState(EnumControlJobState.WaitingForStart);
|
||
|
||
|
||
int totalWafer = 0;
|
||
foreach (var pjName in pjIDs)
|
||
{
|
||
var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
|
||
if (pj == null)
|
||
{
|
||
LOG.Info($"not find {pjName} while create control job");
|
||
continue;
|
||
}
|
||
|
||
var slotWafers = new List<Tuple<ModuleName, int>>();
|
||
foreach (var slotWafer in pj.SlotWafers)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slotWafer.Item2))
|
||
{
|
||
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} not in the carrier");
|
||
return false;
|
||
}
|
||
if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), slotWafer.Item2, WaferStatus.Normal))
|
||
{
|
||
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).Status}");
|
||
return false;
|
||
}
|
||
if (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).ProcessState != EnumWaferProcessStatus.Idle)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} process status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).ProcessState}");
|
||
return false;
|
||
}
|
||
|
||
slotWafers.Add(Tuple.Create(ModuleHelper.Converter(module), slotWafer.Item2));
|
||
|
||
totalWafer++;
|
||
}
|
||
|
||
pj.ControlJobName = jobId;
|
||
|
||
cj.ProcessJobNameList.Add(pj.Name);
|
||
pj.SlotWafers = slotWafers;
|
||
foreach (var pjSlotWafer in pj.SlotWafers)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
||
|
||
WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
|
||
WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
|
||
WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), jobId);
|
||
}
|
||
}
|
||
|
||
_lstControlJobs.Add(cj);
|
||
|
||
CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
|
||
JobDataRecorder.StartCJ(cj.InnerId.ToString(), null, cj.Name, cj.Module, cj.Module, totalWafer);
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool CreateProcessJob(string jobId, string sequenceName, List<int> slotNumbers/*0 based*/, bool isAutoStart)
|
||
{
|
||
var sequenceInfo = SequenceInfoHelper.GetInfo(sequenceName);
|
||
|
||
#region 模块和顺序检查
|
||
if (!CheckSequenceReady(sequenceInfo, out string reason))
|
||
{
|
||
EV.PostWarningLog(LogSource, reason);
|
||
return false;
|
||
}
|
||
#endregion
|
||
|
||
var slotWafers = new List<Tuple<ModuleName, int>>();
|
||
foreach (var slot in slotNumbers)
|
||
{
|
||
slotWafers.Add(Tuple.Create(ModuleName.System, slot));
|
||
}
|
||
|
||
ProcessJobInfo pj = new ProcessJobInfo();
|
||
pj.Name = jobId;
|
||
pj.Sequence = sequenceInfo;
|
||
pj.SlotWafers = slotWafers;
|
||
pj.SetState(EnumProcessJobState.Queued);
|
||
|
||
_lstProcessJobs.Add(pj);
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
internal void StopJob(string jobName)
|
||
{
|
||
ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
|
||
if (cj == null)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"stop job rejected, not found job with id {jobName}");
|
||
return;
|
||
}
|
||
|
||
foreach (var pj in _lstProcessJobs)
|
||
{
|
||
if (pj.ControlJobName == cj.Name)
|
||
{
|
||
pj.SetState(EnumProcessJobState.Stopping);
|
||
}
|
||
}
|
||
|
||
if (_cycleSetPoint > 0)
|
||
{
|
||
_cycleSetPoint = _cycledCount;
|
||
}
|
||
}
|
||
|
||
public void Abort()
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, 0);
|
||
if (wafer != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer.InnerId.ToString(), ModuleName.PM1.ToString(), "Abort");
|
||
}
|
||
|
||
WaferInfo wafer1 = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
|
||
if (wafer1 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer1.InnerId.ToString(), ModuleName.TM.ToString(), "Abort");
|
||
}
|
||
|
||
WaferInfo wafer2 = WaferManager.Instance.GetWafer(ModuleName.Buffer, 0);
|
||
if (wafer2 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer2.InnerId.ToString(), ModuleName.Buffer.ToString(), "Abort");
|
||
}
|
||
|
||
WaferInfo wafer3 = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
|
||
if (wafer3 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer3.InnerId.ToString(), ModuleName.LoadLock.ToString(), "Abort");
|
||
}
|
||
}
|
||
|
||
internal void AbortJob(string jobName)
|
||
{
|
||
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
|
||
//if (cj == null)
|
||
//{
|
||
// EV.PostWarningLog(LogSource, $"abort job rejected, not found job with id {jobName}");
|
||
// return;
|
||
//}
|
||
if (_lstControlJobs.Count == 0)
|
||
{
|
||
return;
|
||
}
|
||
ControlJobInfo cj = _lstControlJobs[_lstControlJobs.Count - 1];
|
||
int unprocessed_cj = 0;
|
||
int aborted_cj = 0;
|
||
|
||
List<ProcessJobInfo> pjAbortList = new List<ProcessJobInfo>();
|
||
foreach (var pj in _lstProcessJobs)
|
||
{
|
||
if (pj.ControlJobName == cj.Name)
|
||
{
|
||
pj.SetState(EnumProcessJobState.Aborting);
|
||
pjAbortList.Add(pj);
|
||
|
||
int unprocessed = 0;
|
||
int aborted = 0;
|
||
WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
|
||
foreach (var waferInfo in wafers)
|
||
{
|
||
waferInfo.ProcessJob = null;
|
||
waferInfo.NextSequenceStep = 0;
|
||
if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
|
||
{
|
||
unprocessed++;
|
||
unprocessed_cj++;
|
||
}
|
||
}
|
||
JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
|
||
}
|
||
}
|
||
|
||
foreach (var pj in pjAbortList)
|
||
{
|
||
_lstProcessJobs.Remove(pj);
|
||
}
|
||
|
||
_lstControlJobs.Remove(cj);
|
||
|
||
JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
|
||
}
|
||
|
||
public void ResumeJob(string jobName)
|
||
{
|
||
ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
|
||
if (cj == null)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"resume job rejected, not found job with id {jobName}");
|
||
return;
|
||
}
|
||
|
||
if (cj.State == EnumControlJobState.Paused)
|
||
{
|
||
cj.SetState(EnumControlJobState.Executing);
|
||
}
|
||
}
|
||
|
||
internal void PauseJob(string jobName)
|
||
{
|
||
ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
|
||
if (cj == null)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"pause job rejected, not found job with id {jobName}");
|
||
return;
|
||
}
|
||
|
||
if (cj.State == EnumControlJobState.Executing)
|
||
{
|
||
cj.SetState(EnumControlJobState.Paused);
|
||
}
|
||
}
|
||
|
||
internal void StartJob(string jobName)
|
||
{
|
||
GetConfig();
|
||
|
||
if (_lstControlJobs.Count < 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
foreach (ControlJobInfo cj in _lstControlJobs)
|
||
{
|
||
if (cj == null)
|
||
{
|
||
EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}");
|
||
return;
|
||
}
|
||
if (cj.State == EnumControlJobState.WaitingForStart)
|
||
{
|
||
cj.SetState(EnumControlJobState.Executing);
|
||
}
|
||
_loadLockStartTrig.RST = true;
|
||
_loadLockFinishedTrig.RST = true;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// Start Auto Transfer
|
||
/// </summary>
|
||
/// <param name="objs"></param>
|
||
/// <returns></returns>
|
||
public Result Start(params object[] objs)
|
||
{
|
||
GetConfig();
|
||
|
||
_cycledWafer = 0;
|
||
_cycledCount = 0;
|
||
_totalWaferWhenStart = StatsDataManager.Instance.GetValue(StatsNameTotalRunningWafer);
|
||
|
||
bool hasPmOnline = false;
|
||
foreach (var schedulerPm in _lstPms)
|
||
{
|
||
if (schedulerPm.IsOnline && !schedulerPm.IsError)
|
||
{
|
||
hasPmOnline = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!hasPmOnline)
|
||
{
|
||
EV.PostWarningLog("System", "can not change to auto mode, at least one process chamber be online and no error");
|
||
return Result.FAIL;
|
||
}
|
||
|
||
if (!_tmRobot.IsOnline || _tmRobot.IsError)
|
||
{
|
||
EV.PostWarningLog("System", "can not change to auto mode, TM robot should be online and no error");
|
||
return Result.FAIL;
|
||
}
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
public Result Monitor()
|
||
{
|
||
ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
|
||
if (cjActive != null)
|
||
{
|
||
MonitorModuleTasks();
|
||
|
||
MonitorAutoJobStatus();
|
||
|
||
MonitorPmPreTasks();
|
||
}
|
||
|
||
MonitorJobTasks();
|
||
|
||
MonitorCleanTasks();
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
#region Job task
|
||
public Result MonitorJobTasks()
|
||
{
|
||
UpdateProcessJobStatus();
|
||
|
||
UpdateControlJobStatus();
|
||
|
||
StartNewJob();
|
||
|
||
//_trigJobComplete.CLK = CheckJobComplete();
|
||
//if (_trigJobComplete.Q)
|
||
//{
|
||
// _loadlock.SetJobStatue();
|
||
// return Result.DONE;
|
||
//}
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
public Result MonitorCleanTasks()
|
||
{
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
pm.MonitorCleanTasks();
|
||
}
|
||
return Result.RUN;
|
||
}
|
||
|
||
public Result MonitorPmPreTasks()
|
||
{
|
||
//检查
|
||
if (CheckWaferNeedProcess(_loadlock.Module, 0))
|
||
{
|
||
string pmModule = GetProcessModule(_loadlock.Module, 0);
|
||
if (pmModule != "" && WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(pmModule), 0))
|
||
{
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
if (pm.Module.ToString() == pmModule && pm.CurrentWaferID == "")
|
||
{
|
||
//设置需要运行Pre和Complete Recipe的内容及相关的ProcessID
|
||
string waferID = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).WaferID;
|
||
|
||
bool enbalePre = false;
|
||
bool enbaleComplete = false;
|
||
string preRecipe = "";
|
||
string completeRecipe = "";
|
||
|
||
if (GetPreCompleteRecipeInfo(_loadlock.Module, 0, out enbalePre, out enbaleComplete, out preRecipe, out completeRecipe))
|
||
{
|
||
pm.SetCleanInfo(waferID, enbalePre, enbaleComplete, preRecipe, completeRecipe);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
pm.MonitorClean();
|
||
}
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
|
||
{
|
||
for (int i = 0; i < pj.SlotWafers.Count; ++i)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
|
||
if (wafer.IsEmpty)
|
||
return false;
|
||
if (checkAllProcessed && CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
|
||
return false;
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.InnerId != pj.InnerId)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
protected bool CheckAllDummyWaferReturned()
|
||
{
|
||
foreach (var schedulerPm in _lstPms)
|
||
{
|
||
if (WaferManager.Instance.CheckWaferIsDummy(schedulerPm.Module, 0))
|
||
return false;
|
||
}
|
||
|
||
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 0))
|
||
return false;
|
||
|
||
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 1))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
protected bool CheckAllPmCleaned(ProcessJobInfo pj)
|
||
{
|
||
foreach (var schedulerPm in _lstPms)
|
||
{
|
||
if (CheckNeedRunClean(schedulerPm.Module, out _, out _))
|
||
{
|
||
foreach (var sequenceStepInfo in pj.Sequence.Steps)
|
||
{
|
||
if (sequenceStepInfo.StepModules.Contains(schedulerPm.Module))
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
private void UpdateProcessJobStatus()
|
||
{
|
||
foreach (var pj in _lstProcessJobs)
|
||
{
|
||
if (pj.State == EnumProcessJobState.Processing)
|
||
{
|
||
if (CheckAllWaferReturned(pj, true) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned() && _loadlock.IsAvailable && _tmRobot.IsAvailable)
|
||
{
|
||
if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
|
||
{
|
||
_loadlock.SetJobStatue();
|
||
pj.SetState(EnumProcessJobState.ProcessingComplete);
|
||
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
|
||
AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).InnerId.ToString());
|
||
}
|
||
}
|
||
}
|
||
else if (pj.State == EnumProcessJobState.Stopping)
|
||
{
|
||
if (CheckAllWaferReturned(pj, false) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned() && _loadlock.IsAvailable && _tmRobot.IsAvailable)
|
||
{
|
||
if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
|
||
{
|
||
_loadlock.SetJobStatue();
|
||
pj.SetState(EnumProcessJobState.ProcessingComplete);
|
||
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
|
||
AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).InnerId.ToString());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void UpdateControlJobStatus()
|
||
{
|
||
if (_lstControlJobs.Count == 0)
|
||
return;
|
||
|
||
List<ControlJobInfo> cjRemoveList = new List<ControlJobInfo>();
|
||
foreach (var cj in _lstControlJobs)
|
||
{
|
||
if (cj.State == EnumControlJobState.Completed)
|
||
{
|
||
_lstControlJobs.Remove(cj);
|
||
break;
|
||
}
|
||
else if (cj.State == EnumControlJobState.Executing)
|
||
{
|
||
bool allPjCompleted = true;
|
||
foreach (var pjName in cj.ProcessJobNameList)
|
||
{
|
||
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
|
||
if (pj == null)
|
||
{
|
||
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
|
||
continue;
|
||
}
|
||
if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
|
||
{
|
||
allPjCompleted = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (allPjCompleted)
|
||
{
|
||
//Cycle模式下执行+1操作
|
||
if (_isCycleMode && _cycledCount < _cycleSetPoint)
|
||
{
|
||
_cycledCount++;
|
||
|
||
if (_cycledCount < _cycleSetPoint)
|
||
{
|
||
foreach (var pjName in cj.ProcessJobNameList)
|
||
{
|
||
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
|
||
if (pj == null)
|
||
{
|
||
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
|
||
continue;
|
||
}
|
||
pj.SetState(EnumProcessJobState.Queued);
|
||
pj.InnerId = Guid.NewGuid();
|
||
foreach (var pjSlotWafer in pj.SlotWafers)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
|
||
|
||
AutoJobRecorder.Add(wafer.InnerId.ToString(), strCurrentRecipeName, strCurrentJobID, ModuleName.LoadLock.ToString(), GetWaferStatue(wafer));
|
||
|
||
wafer.ProcessJob = null;
|
||
wafer.NextSequenceStep = 0;
|
||
wafer.ProcessState = EnumWaferProcessStatus.Idle;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cj.SetState(EnumControlJobState.Completed);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void StartNewJob()
|
||
{
|
||
foreach (var cj in _lstControlJobs)
|
||
{
|
||
if (cj.State == EnumControlJobState.Executing)
|
||
{
|
||
foreach (var pjName in cj.ProcessJobNameList)
|
||
{
|
||
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
|
||
if (pj == null)
|
||
{
|
||
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
|
||
continue;
|
||
}
|
||
|
||
if (pj.State == EnumProcessJobState.Queued)
|
||
{
|
||
ActiveProcessJob(pj);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public bool CheckAllJobDone()
|
||
{
|
||
foreach (var cj in _lstControlJobs)
|
||
{
|
||
if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
|
||
return false;
|
||
}
|
||
|
||
if (_lstControlJobs.Count == 0)
|
||
{
|
||
EV.PostWarningLog("System", "ControlJob Finished!");
|
||
return true;
|
||
}
|
||
return false;
|
||
|
||
//if (WaferManager.Instance.CheckHasWafer(ModuleName.LoadLock, 0) && _lstControlJobs.Count==0 )
|
||
//{
|
||
// if (WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).ProcessState == EnumWaferProcessStatus.Completed)
|
||
// {
|
||
// AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).InnerId.ToString());
|
||
// _loadlock.SetJobStatue();
|
||
//
|
||
// return true;
|
||
// }
|
||
//}
|
||
return false;
|
||
}
|
||
|
||
public void MonitorAutoJobStatus()
|
||
{
|
||
_updateAutoJobLocation.CLK = _tmRobot.IsAvailable;
|
||
if (_updateAutoJobLocation.Q)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, 0);
|
||
if(wafer != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer.InnerId.ToString(), ModuleName.PM1.ToString(), GetWaferStatue(wafer));
|
||
}
|
||
|
||
WaferInfo wafer1 = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
|
||
if (wafer1 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer1.InnerId.ToString(), ModuleName.TM.ToString(), GetWaferStatue(wafer1));
|
||
}
|
||
|
||
WaferInfo wafer2 = WaferManager.Instance.GetWafer(ModuleName.Buffer, 0);
|
||
if (wafer2 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer2.InnerId.ToString(), ModuleName.Buffer.ToString(), GetWaferStatue(wafer2));
|
||
}
|
||
|
||
WaferInfo wafer3 = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
|
||
if (wafer3 != null)
|
||
{
|
||
AutoJobRecorder.UpdatePosition(wafer3.InnerId.ToString(), ModuleName.LoadLock.ToString(), GetWaferStatue(wafer3));
|
||
}
|
||
}
|
||
}
|
||
|
||
#region 组件检查
|
||
|
||
private bool CheckSequenceReady(SequenceInfo seq, out string reason)
|
||
{
|
||
reason = "";
|
||
bool pmIsReady = false;
|
||
bool bufferIsReady = false;
|
||
for (int i = 0; i < seq.Steps.Count; i++)
|
||
{
|
||
SequenceStepInfo stepInfo = seq.Steps[i];
|
||
foreach (var module in stepInfo.StepModules)
|
||
{
|
||
if ((module == ModuleName.PM1 || module == ModuleName.PMA))
|
||
{
|
||
if (!_isPmAInstal)
|
||
{
|
||
reason = "Sequence stepinfo contains a no installed PM";
|
||
return false;
|
||
}
|
||
_curSequenceName = seq.Name;
|
||
_curRecipeName = seq.Steps[i].RecipeName; //顺便获取最新的Recipe名字
|
||
pmIsReady = true;
|
||
|
||
if (!SicPM.RecipeExecutions.RecipeParser.CheckDataAvalible(_curRecipeName, module.ToString(), out string reason1))
|
||
{
|
||
reason = "Recipe data is error!";
|
||
return false;
|
||
}
|
||
}
|
||
else if ((module == ModuleName.PM2 || module == ModuleName.PMB))
|
||
{
|
||
if (!_isPmBInstal)
|
||
{
|
||
reason = "Sequence stepinfo contains a no installed PM";
|
||
return false;
|
||
}
|
||
_curSequenceName = seq.Name;
|
||
_curRecipeName = seq.Steps[i].RecipeName; //顺便获取最新的Recipe名字
|
||
pmIsReady = true;
|
||
|
||
if (!SicPM.RecipeExecutions.RecipeParser.CheckDataAvalible(_curRecipeName, module.ToString(), out string reason1))
|
||
{
|
||
reason = "Recipe data is error!";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (module == ModuleName.Buffer)
|
||
{
|
||
if (!pmIsReady)
|
||
{
|
||
reason = "Sequence stepinfo error,The buffer step must after the PM step";
|
||
return false;
|
||
}
|
||
bufferIsReady = true;
|
||
}
|
||
}
|
||
}
|
||
if (!pmIsReady)
|
||
{
|
||
reason = "Sequence stepinfo must contain a PM step";
|
||
return false;
|
||
}
|
||
if (!bufferIsReady)
|
||
{
|
||
reason = "Sequence stepinfo must contain a Buffer step";
|
||
return false;
|
||
}
|
||
return true;
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
private bool ActiveProcessJob(ProcessJobInfo pj)
|
||
{
|
||
_lstPmsCurrentSequence.Clear();
|
||
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) && _lstPms.Exists(x => x.Module == module))
|
||
{
|
||
_lstPmsCurrentSequence.Add(_lstPms.Find(x => x.Module == module));
|
||
}
|
||
}
|
||
}
|
||
|
||
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(), null, cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
|
||
pj.SetState(EnumProcessJobState.Processing);
|
||
|
||
return true;
|
||
}
|
||
|
||
private bool CheckJobComplete(string lp = null)
|
||
{
|
||
if (_lstProcessJobs.Count == 0)
|
||
return false;
|
||
|
||
if (_lstControlJobs.Count == 0)
|
||
return false;
|
||
|
||
if (_isCycleMode && _cycledCount < _cycleSetPoint)
|
||
return false;
|
||
|
||
if (lp != null)
|
||
{
|
||
var cj = _lstControlJobs.Find(x => x.Module == lp);
|
||
if (cj == null)
|
||
return false;
|
||
}
|
||
|
||
foreach (var pj in _lstProcessJobs)
|
||
{
|
||
if (lp == null)
|
||
{
|
||
if (pj.State != EnumProcessJobState.ProcessingComplete)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (var cj in _lstControlJobs)
|
||
{
|
||
if (lp == null)
|
||
{
|
||
if (cj.State != EnumControlJobState.Completed)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (cj.Module == lp && cj.State != EnumControlJobState.Completed)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
#endregion
|
||
|
||
#region Module task
|
||
|
||
public Result MonitorModuleTasks()
|
||
{
|
||
MonitorPMTask();
|
||
|
||
MonitorTmRobotTask();
|
||
|
||
MonitorLoadLockTask();
|
||
|
||
MonitorBufferTask();
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
private void MonitorBufferTask()
|
||
{
|
||
if (WaferManager.Instance.CheckHasWafer(_buffer.Module, 0) && CheckWaferNextStepIsBuffer(_buffer.Module, 0) && _tmRobot.IsAvailable && _buffer.IsAvailable)
|
||
{
|
||
//判断冷却方式是温度还是时间
|
||
bool coolingTypeIsTime = CheckCoolingTypeIsTime(_buffer.Module, 0);
|
||
int coolingValue = GetWaferSequenceBufferCoolingValue(_buffer.Module, 0);
|
||
|
||
_buffer.Cooling(coolingTypeIsTime, coolingValue);
|
||
WaferManager.Instance.GetWafer(_buffer.Module, 0).NextSequenceStep++;
|
||
}
|
||
}
|
||
|
||
|
||
private void MonitorLoadLockTask()
|
||
{
|
||
if (!_loadlock.CheckLidClose())
|
||
{
|
||
_loadlock.SetOffline();
|
||
return;
|
||
}
|
||
|
||
if (!_tmRobot.IsAvailable || !_loadlock.IsAvailable)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (WaferManager.Instance.CheckHasWafer(_loadlock.Module, 0))
|
||
{
|
||
if (!CheckWaferSequenceStepDone(_loadlock.Module, 0))
|
||
{
|
||
if (CheckWaferNextStepIsLoadLock(_loadlock.Module, 0, "Routine", out string strNextRoutine))
|
||
{
|
||
if (strNextRoutine.ToLower() == "vent")
|
||
{
|
||
if (_loadlock.Vent())
|
||
{
|
||
WaferManager.Instance.GetWafer(_loadlock.Module, 0).NextSequenceStep++;
|
||
}
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if (_loadlock.Purge())
|
||
{
|
||
WaferManager.Instance.GetWafer(_loadlock.Module, 0).NextSequenceStep++;
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!_loadlock.IsReadyForPick(ModuleName.TMRobot, 0))
|
||
{
|
||
_loadlock.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!_loadlock.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
{
|
||
_loadlock.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0) && WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).ProcessState == EnumWaferProcessStatus.Completed)
|
||
//{
|
||
// if (!_loadlock.CheckAtAtm())
|
||
// {
|
||
// if (_isCycleMode && _cycledCount < _cycleSetPoint)
|
||
// {
|
||
// return;
|
||
// }
|
||
// else
|
||
// {
|
||
// if (!_loadLockFinishedPurgeOver)
|
||
// {
|
||
// _loadlock.Purge();
|
||
// _loadLockFinishedPurgeOver =true;
|
||
// return;
|
||
// }
|
||
// }
|
||
// }
|
||
|
||
// if (_loadLockFinishedPurgeOver)
|
||
// {
|
||
// if (!_loadLockFinishedVent)
|
||
// {
|
||
// _loadlock.Vent();
|
||
// _loadLockFinishedVent =true;
|
||
// return;
|
||
// }
|
||
|
||
// _trigJobComplete.CLK = _loadLockFinishedVent;
|
||
// if (_trigJobComplete.Q)
|
||
// {
|
||
// AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).InnerId.ToString());
|
||
// _loadlock.SetJobStatue();
|
||
// }
|
||
// }
|
||
//}
|
||
//else
|
||
//{
|
||
// if (WaferManager.Instance.CheckHasWafer(_loadlock.Module, 0))
|
||
// {
|
||
// //第一次Start,LoadLock需要执行Purge
|
||
// _loadLockStartTrig.CLK = true;
|
||
// if (_loadLockStartTrig.Q)
|
||
// {
|
||
// //_loadLockFinishedPurgeOver = false;
|
||
// _loadlock.Purge();
|
||
// return;
|
||
// }
|
||
|
||
// if (!_loadlock.IsReadyForPick(ModuleName.TMRobot, 0))
|
||
// {
|
||
// _loadlock.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// if (!_loadlock.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
// {
|
||
// _loadlock.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
|
||
}
|
||
|
||
private void MonitorPMTask()
|
||
{
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
WaferInfo wafer1 = WaferManager.Instance.GetWafer(pm.Module, 0);
|
||
if (wafer1 == null)
|
||
{
|
||
_pm1WaferStaus = "";
|
||
}
|
||
else if (wafer1.ProcessState.ToString() != _pm1WaferStaus)
|
||
{
|
||
_pm1WaferStaus = wafer1.ProcessState.ToString();
|
||
AutoJobRecorder.UpdatePosition(wafer1.InnerId.ToString(), ModuleName.PM1.ToString(), GetWaferStatue(wafer1));
|
||
}
|
||
|
||
|
||
if (!pm.IsAvailable)
|
||
continue;
|
||
|
||
if (WaferManager.Instance.CheckHasWafer(pm.Module, 0))
|
||
{
|
||
if (CheckNeedRunClean(pm.Module, out bool withWafer, out string recipe) && withWafer
|
||
&& WaferManager.Instance.GetWafer(pm.Module, 0).Status == WaferStatus.Dummy
|
||
&& WaferManager.Instance.GetWafer(pm.Module, 0).ProcessState == EnumWaferProcessStatus.Wait)
|
||
{
|
||
pm.Process(recipe, true, withWafer);
|
||
continue;
|
||
}
|
||
|
||
if (CheckWaferNeedProcess(pm.Module, 0, pm.Module))
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(pm.Module, 0);
|
||
if (pm.Process(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].RecipeName, false, true))
|
||
{
|
||
pm.SetCurrentRunCount();
|
||
WaferManager.Instance.GetWafer(pm.Module, 0).NextSequenceStep++;
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!pm.IsReadyForPick(ModuleName.TMRobot, 0))
|
||
{
|
||
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (CheckNeedRunClean(pm.Module, out bool withWafer, out string recipe) && !withWafer)
|
||
{
|
||
pm.Process(recipe, true, withWafer);
|
||
continue;
|
||
}
|
||
|
||
if (!pm.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
{
|
||
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
|
||
return;
|
||
}
|
||
|
||
//if (!pm.CheckHeatIsDisbale() && _canSetHeat)
|
||
//{
|
||
// pm.SetHeatDisable();
|
||
// _canSetHeat = false;
|
||
//}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void MonitorTmRobotTask()
|
||
{
|
||
if (!_tmRobot.IsAvailable)
|
||
return;
|
||
|
||
//TM robot is idle, release all the target
|
||
foreach (var ll in _lstLls)
|
||
{
|
||
if (ll.IsWaitTransfer(ModuleName.TMRobot))
|
||
ll.StopWaitTransfer(ModuleName.TMRobot);
|
||
}
|
||
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
if (pm.IsWaitTransfer(ModuleName.TMRobot))
|
||
pm.StopWaitTransfer(ModuleName.TMRobot);
|
||
}
|
||
|
||
if (_buffer.IsWaitTransfer(ModuleName.TMRobot))
|
||
_buffer.StopWaitTransfer(ModuleName.TMRobot);
|
||
|
||
|
||
MonitorTmRobotLoadLockTask();
|
||
|
||
MonitorTmRobotBufferTask();
|
||
|
||
MonitorTmRobotPMTask();
|
||
|
||
|
||
}
|
||
|
||
private void MonitorTmRobotLoadLockTask()
|
||
{
|
||
if (!_tmRobot.IsAvailable)
|
||
return;
|
||
|
||
//place to ll
|
||
bool blade0HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) &&
|
||
!CheckWaferNeedProcess(ModuleName.TMRobot, 0) &&
|
||
!(WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0).Status == WaferStatus.Dummy)
|
||
&& (CheckWaferNoSequence(ModuleName.TMRobot, 0) || CheckWaferSequenceStepDone(ModuleName.TMRobot, 0) || CheckWaferNextStepIsLoadLock(ModuleName.TMRobot, 0));
|
||
|
||
if (blade0HasWaferAndProcessed && WaferManager.Instance.CheckNoWafer(_loadlock.Module, 0))
|
||
{
|
||
Hand placeBlade = Hand.Blade1;
|
||
|
||
SchedulerLoadLock placeLL = null;
|
||
int placeSlot = Int32.MinValue;
|
||
|
||
if (_loadlock.IsAvailable && _loadlock.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
{
|
||
int slot = WaferManager.Instance.GetWafer(_loadlock.Module, 0).OriginSlot;
|
||
if (slot > placeSlot)
|
||
{
|
||
placeLL = _loadlock;
|
||
placeSlot = slot;
|
||
}
|
||
}
|
||
|
||
if (placeLL != null)
|
||
{
|
||
if (placeLL.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
{
|
||
if (_tmRobot.Place(placeLL.Module, 0, placeBlade))
|
||
{
|
||
placeLL.WaitTransfer(ModuleName.TMRobot);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!_tmRobot.IsAvailable)
|
||
return;
|
||
|
||
//pick from ll
|
||
if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && !CheckWaferNextStepIsLoadLock(ModuleName.LoadLock, 0))
|
||
{
|
||
Hand pickBlade = Hand.Blade1;
|
||
|
||
SchedulerLoadLock pickLL = null;
|
||
int pickSlot = Int32.MaxValue;
|
||
|
||
if (!_loadlock.IsAvailable
|
||
|| !_loadlock.IsReadyForPick(ModuleName.TM, 0)
|
||
|| !WaferManager.Instance.CheckHasWafer(_loadlock.Module, 0)
|
||
|| !CheckWaferNeedProcess(_loadlock.Module, 0)
|
||
|| !CheckWaferProcessModuleIsAvailable(_loadlock.Module, 0))
|
||
return;
|
||
|
||
|
||
bool findChamberToProcess = false;
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
if (!pm.IsAvailable || WaferManager.Instance.CheckHasWafer(pm.Module, 0) || CheckNeedRunClean(pm.Module, out _, out _))
|
||
continue;
|
||
|
||
bool llWaferProcessIn = CheckWaferNextProcessIn(_loadlock.Module, 0, pm.Module);
|
||
bool robotWaferProcessIn = CheckWaferNextProcessIn(ModuleName.TMRobot, (int)pickBlade, pm.Module);
|
||
|
||
if (!llWaferProcessIn)
|
||
continue;
|
||
if (robotWaferProcessIn)
|
||
continue;
|
||
|
||
findChamberToProcess = true;
|
||
}
|
||
|
||
|
||
//string chamberToProcess = GetProcessModule(_loadlock.Module, 0);
|
||
//foreach (var pm in _lstPms)
|
||
//{
|
||
// if (pm.Module.ToString() == chamberToProcess)
|
||
// {
|
||
// if (pm.CurrentWaferID != "" && pm.CurrentWaferID != WaferManager.Instance.GetWafer(_loadlock.Module, 0).WaferID)
|
||
// {
|
||
// return;
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
if (!findChamberToProcess)
|
||
return;
|
||
|
||
|
||
int slot = WaferManager.Instance.GetWafer(_loadlock.Module, 0).OriginSlot;
|
||
if (slot < pickSlot)
|
||
{
|
||
pickLL = _loadlock;
|
||
pickSlot = slot;
|
||
}
|
||
|
||
if (pickLL != null)
|
||
{
|
||
if (pickLL.IsReadyForPick(ModuleName.TMRobot, 0))
|
||
{
|
||
if (_tmRobot.Pick(pickLL.Module, 0, pickBlade))
|
||
{
|
||
pickLL.WaitTransfer(ModuleName.TMRobot);
|
||
_canSetHeat =true;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void MonitorTmRobotBufferTask()
|
||
{
|
||
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
|
||
return;
|
||
|
||
//place to Buffer (工艺做完,Sequence下一步是Buffer)
|
||
bool blade0HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) &&
|
||
!CheckWaferNeedProcess(ModuleName.TMRobot, 0, _pm1.Module) &&
|
||
CheckWaferNextStepIsBuffer(ModuleName.TMRobot, 0);
|
||
//(CheckWaferNextStepIsBuffer(ModuleName.TMRobot, 0) || (!CheckWaferNextStepIsBuffer(ModuleName.Buffer, 0) && !CheckWaferNextStepIsBuffer(ModuleName.LoadLock, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.LoadLock,0)));
|
||
//place to buffer
|
||
if (blade0HasWaferAndProcessed && WaferManager.Instance.CheckNoWafer(ModuleName.Buffer, 0))
|
||
{
|
||
Hand placeBlade = Hand.Blade1;
|
||
|
||
if (_buffer.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
{
|
||
if (_tmRobot.Place(_buffer.Module, 0, placeBlade))
|
||
{
|
||
_buffer.WaitTransfer(ModuleName.TMRobot);
|
||
return;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//pick from buffer
|
||
if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.LoadLock, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.Buffer, 0) && !CheckWaferNextStepIsBuffer(ModuleName.Buffer, 0))
|
||
{
|
||
Hand pickBlade = Hand.Blade1;
|
||
|
||
if (_tmRobot.Pick(_buffer.Module, 0, pickBlade))
|
||
{
|
||
_buffer.WaitTransfer(ModuleName.TMRobot);
|
||
return;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
private void MonitorTmRobotPMTask()
|
||
{
|
||
if (!_tmRobot.IsAvailable)
|
||
return;
|
||
|
||
//place to pm
|
||
bool blade0HasWaferAndNeedProcess = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) &&
|
||
CheckWaferNeedProcess(ModuleName.TMRobot, 0);
|
||
|
||
if (blade0HasWaferAndNeedProcess)
|
||
{
|
||
_debugger2++;
|
||
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
if (!pm.IsAvailable
|
||
|| !WaferManager.Instance.CheckNoWafer(pm.Module, 0)
|
||
|| !pm.IsReadyForPlace(ModuleName.TMRobot, 0))
|
||
//|| !pm.CheckTempBelow900())
|
||
continue;
|
||
|
||
bool cleanRequired = CheckNeedRunClean(pm.Module, out bool withWafer, out _);
|
||
|
||
if (cleanRequired)
|
||
{
|
||
if (!withWafer)
|
||
continue;
|
||
|
||
bool blade0DummyPlace = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) &&
|
||
CheckWaferNeedProcess(ModuleName.TMRobot, 0, pm.Module) && WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 0);
|
||
bool blade1DummyPlace = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) &&
|
||
CheckWaferNeedProcess(ModuleName.TMRobot, 1, pm.Module) && WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 1);
|
||
if (blade0DummyPlace || blade1DummyPlace)
|
||
{
|
||
Hand placeBlade = blade0DummyPlace ? Hand.Blade1 : Hand.Blade2;
|
||
if (blade0DummyPlace && blade1DummyPlace)
|
||
{
|
||
if (WaferManager.Instance.GetWafer(ModuleName.TMRobot, 1).OriginSlot <
|
||
WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0).OriginSlot)
|
||
{
|
||
placeBlade = Hand.Blade2;
|
||
}
|
||
}
|
||
|
||
if (_tmRobot.Place(pm.Module, 0, placeBlade))
|
||
{
|
||
pm.WaitTransfer(ModuleName.TMRobot);
|
||
return;
|
||
}
|
||
}
|
||
|
||
continue;
|
||
}
|
||
|
||
bool blade0Place = WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) &&
|
||
CheckWaferNeedProcess(ModuleName.TMRobot, 0, pm.Module);
|
||
if (blade0Place)
|
||
{
|
||
Hand placeBlade = Hand.Blade1;
|
||
|
||
if (_tmRobot.Place(pm.Module, 0, placeBlade))
|
||
{
|
||
pm.WaitTransfer(ModuleName.TMRobot);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!_tmRobot.IsAvailable)
|
||
return;
|
||
|
||
//pick from pm
|
||
if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0))
|
||
{
|
||
_debugger3++;
|
||
|
||
Hand pickBlade = Hand.Blade1;
|
||
|
||
ModuleName pickPm = ModuleName.System;
|
||
int waferOriginSlot = int.MaxValue;
|
||
foreach (var schedulerPm in _lstPms)
|
||
{
|
||
//增加温度低于900才能Pick的限制
|
||
if (!schedulerPm.IsAvailable
|
||
|| WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0)
|
||
|| CheckWaferNeedProcess(schedulerPm.Module, 0, schedulerPm.Module)
|
||
|| WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, (int)pickBlade))
|
||
//|| !schedulerPm.CheckTempBelow900())
|
||
continue;
|
||
|
||
_debugger4++;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
|
||
|
||
bool pickAllowed = CheckVacuumWaferHasAvailableTarget(schedulerPm.Module, 0, schedulerPm.Module);
|
||
|
||
if (pickAllowed)
|
||
{
|
||
_debugger5++;
|
||
|
||
int slot = wafer.OriginSlot;
|
||
if (slot < waferOriginSlot)
|
||
{
|
||
waferOriginSlot = slot;
|
||
pickPm = schedulerPm.Module;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pickPm != ModuleName.System)
|
||
{
|
||
_debugger6++;
|
||
|
||
SchedulerModule pm = GetModule(pickPm.ToString());
|
||
if (pm.IsReadyForPick(ModuleName.TMRobot, 0))
|
||
{
|
||
_debugger7++;
|
||
bool hasWaferNeedRun = CheckWaferNeedProcess(ModuleName.LoadLock, 0) || CheckWaferNeedProcess(ModuleName.TMRobot, 0) || CheckWaferNeedProcess(ModuleName.Buffer, 0);
|
||
|
||
if (_tmRobot.Pick(pm.Module, 0, pickBlade))
|
||
{
|
||
_debugger8++;
|
||
pm.WaitTransfer(ModuleName.TMRobot);
|
||
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Logic Check
|
||
|
||
private bool CheckNeedRunClean(ModuleName module, out bool withWafer, out string recipeName)
|
||
{
|
||
recipeName = string.Empty;
|
||
withWafer = false;
|
||
|
||
|
||
return false;
|
||
}
|
||
|
||
private bool CheckVacuumWaferHasAvailableTarget(ModuleName waferModule, int waferSlot, ModuleName chamberSwappable)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (CheckWaferNeedProcess(waferModule, waferSlot))
|
||
{
|
||
// Check for an empty PM
|
||
foreach (var pm in _lstPms)
|
||
{
|
||
if (WaferManager.Instance.CheckNoWafer(pm.Module, 0) || pm.Module == chamberSwappable)
|
||
{
|
||
if (pm.IsAvailable == false)
|
||
continue;
|
||
|
||
if (!CheckWaferNextProcessIn(waferModule, waferSlot, pm.Module))
|
||
continue;
|
||
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (WaferManager.Instance.CheckNoWafer(_buffer.Module, 0) && _buffer.IsAvailable)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private bool CheckWaferNextProcessIn(ModuleName waferModule, int waferSlot, ModuleName chamber)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.ProcessJob == null ||
|
||
wafer.ProcessJob.Sequence == null ||
|
||
wafer.ProcessJob.Sequence.Steps == null ||
|
||
wafer.ProcessJob.Sequence.Steps.Count <= wafer.NextSequenceStep ||
|
||
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep] == null ||
|
||
wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
//return wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(chamber);
|
||
|
||
for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
|
||
{
|
||
if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(chamber))
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private SequenceInfo GetCurrentSequenceInfo()
|
||
{
|
||
foreach (var pj in _lstProcessJobs)
|
||
{
|
||
if (pj.State == EnumProcessJobState.Processing)
|
||
{
|
||
return pj.Sequence;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断Buffer的冷却方式是时间还是温度
|
||
/// </summary>
|
||
/// <param name="module"></param>
|
||
/// <param name="slot"></param>
|
||
/// <returns></returns>
|
||
private bool CheckCoolingTypeIsTime(ModuleName module, int slot)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
|
||
return false;
|
||
|
||
if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingType"].ToString().ToLower() == "time")
|
||
{
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private int GetWaferSequenceBufferCoolingValue(ModuleName module, int slot)
|
||
{
|
||
int coolingValue = 0;
|
||
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return coolingValue;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return coolingValue;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return coolingValue;
|
||
|
||
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
|
||
return coolingValue;
|
||
|
||
int.TryParse(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingValue"].ToString(),
|
||
out coolingValue);
|
||
return coolingValue;
|
||
}
|
||
|
||
private bool CheckWaferNextStepIsBuffer(ModuleName module, int slot)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Buffer))
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
private bool CheckWaferNextStepIsLoadLock(ModuleName module, int slot)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.LoadLock))
|
||
return true;
|
||
|
||
|
||
return false;
|
||
}
|
||
|
||
private bool CheckWaferNextStepIsLoadLock(ModuleName module, int slot, string nodeName, out string nodeValue)
|
||
{
|
||
nodeValue = "";
|
||
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.LoadLock))
|
||
{
|
||
nodeValue = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[nodeName].ToString();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
private bool CheckWaferNextStepIsTMRobot(ModuleName module, int slot)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.TMRobot))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
private bool CheckWaferNextStepIsPM(ModuleName module, int slot)
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Any(m => ModuleHelper.IsPm(m)))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取前处理和后处理的Recipe信息
|
||
/// </summary>
|
||
/// <param name="module"></param>
|
||
/// <param name="slot"></param>
|
||
/// <returns></returns>
|
||
private bool GetPreCompleteRecipeInfo(ModuleName module, int slot,out bool enablePre,out bool enableComplete,out string preRecipe,out string completeRecipe)
|
||
{
|
||
enablePre = false;
|
||
enableComplete = false;
|
||
preRecipe = "";
|
||
completeRecipe = "";
|
||
|
||
try
|
||
{
|
||
if (!WaferManager.Instance.CheckHasWafer(module, slot))
|
||
return false;
|
||
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
|
||
for (int i = 0; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
|
||
{
|
||
if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Any(m => ModuleHelper.IsPm(m)))
|
||
{
|
||
if (wafer.ProcessJob.Sequence.Steps[i].StepParameter["EnablePre"].ToString().Trim() != "")
|
||
{
|
||
enablePre = true;
|
||
}
|
||
if (wafer.ProcessJob.Sequence.Steps[i].StepParameter["EnableComplete"].ToString().Trim() != "")
|
||
{
|
||
enableComplete = true;
|
||
}
|
||
preRecipe = wafer.ProcessJob.Sequence.Steps[i].StepParameter["PretreatmentRecipe"].ToString();
|
||
completeRecipe = wafer.ProcessJob.Sequence.Steps[i].StepParameter["CompleteRecipe"].ToString();
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
enablePre = false;
|
||
enableComplete = false;
|
||
preRecipe = "";
|
||
completeRecipe = "";
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public bool CheckWaferNeedProcess(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.IsEmpty)
|
||
return false;
|
||
|
||
if (wafer.Status == WaferStatus.Dummy && wafer.ProcessState == EnumWaferProcessStatus.Wait)
|
||
{
|
||
if (ModuleHelper.IsPm(processIn))
|
||
{
|
||
return (CheckNeedRunClean(processIn, out bool withWafer, out _) && withWafer);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
if (processIn != ModuleName.System && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules
|
||
.Contains(processIn))
|
||
return false;
|
||
|
||
bool hasPm = false;
|
||
for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
|
||
{
|
||
foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
|
||
{
|
||
if (ModuleHelper.IsPm(stepModule))
|
||
{
|
||
hasPm = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (hasPm)
|
||
break;
|
||
}
|
||
|
||
if (processIn == ModuleName.System && !hasPm)
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool CheckWaferSequenceStepDone(ModuleName waferModule, int waferSlot)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.IsEmpty)
|
||
{
|
||
return false;
|
||
}
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count && wafer.ProcessJob.Sequence.Steps.Count>0)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public bool CheckWaferNoSequence(ModuleName waferModule, int waferSlot)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.IsEmpty)
|
||
{
|
||
return false;
|
||
}
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
{
|
||
return true;
|
||
}
|
||
if (wafer.ProcessJob != null && _lstProcessJobs != null)
|
||
{
|
||
if (_lstProcessJobs.Find(a => a.InnerId == wafer.ProcessJob.InnerId) == null)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public bool CheckBufferWaferHasJob()
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.Buffer, 0);
|
||
|
||
if (wafer.IsEmpty)
|
||
{
|
||
return false;
|
||
}
|
||
if (wafer.ProcessJob == null )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
ProcessJobInfo pj = _lstProcessJobs.Find(x => x.InnerId == wafer.ProcessJob.InnerId);
|
||
if (pj == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
|
||
}
|
||
|
||
public bool CheckWaferProcessModuleIsAvailable(ModuleName waferModule, int waferSlot)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.IsEmpty)
|
||
return false;
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return false;
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return false;
|
||
|
||
//foreach (var module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
|
||
//{
|
||
// if (WaferManager.Instance.CheckNoWafer(module, 0)
|
||
// && _lstPms.Find(x => x.Module == module).IsAvailable
|
||
// && !CheckNeedRunClean(module, out bool _, out string _))
|
||
// return true;
|
||
//}
|
||
|
||
foreach (var step in wafer.ProcessJob.Sequence.Steps)
|
||
{
|
||
foreach (var module in step.StepModules)
|
||
{
|
||
if (module.ToString().StartsWith("PM")
|
||
&& WaferManager.Instance.CheckNoWafer(module, 0)
|
||
&& _lstPms.Find(x => x.Module == module).IsAvailable
|
||
&& !CheckNeedRunClean(module, out bool _, out string _))
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//获取
|
||
public string GetProcessModule(ModuleName waferModule, int waferSlot)
|
||
{
|
||
WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
|
||
|
||
if (wafer.IsEmpty)
|
||
return "";
|
||
|
||
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
|
||
return "";
|
||
|
||
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
|
||
return "";
|
||
|
||
foreach (var step in wafer.ProcessJob.Sequence.Steps)
|
||
{
|
||
foreach (var module in step.StepModules)
|
||
{
|
||
if (module.ToString().StartsWith("PM")
|
||
&& WaferManager.Instance.CheckNoWafer(module, 0)
|
||
&& _lstPms.Find(x => x.Module == module).IsAvailable
|
||
&& !CheckNeedRunClean(module, out bool _, out string _))
|
||
return module.ToString();
|
||
}
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
#region Module error
|
||
|
||
public Result MonitorModuleError()
|
||
{
|
||
bool isModuleError = false;
|
||
bool[] isPMError = new bool[4];
|
||
|
||
for (int i = 0; i < isPMError.Length; i++)
|
||
{
|
||
isPMError[i] = false;
|
||
}
|
||
|
||
if (_tmRobot.IsError)
|
||
isModuleError = true;
|
||
|
||
for (int i = 0; i < _lstPms.Count; i++) // PM出错,不影响其他腔体的传片
|
||
{
|
||
if (_lstPms[i].IsError)
|
||
isPMError[i] = true;
|
||
}
|
||
|
||
foreach (var ll in _lstLls)
|
||
{
|
||
if (ll.IsError)
|
||
isModuleError = true;
|
||
}
|
||
|
||
if (isModuleError && !_isModuleErrorPrevious)
|
||
{
|
||
//var jb1 = _lstControlJobs.Find(x => x.Module == "LP1");
|
||
//if (jb1 != null)
|
||
// PauseJob(jb1.Name);
|
||
|
||
//var jb2 = _lstControlJobs.Find(x => x.Module == "LP2");
|
||
//if (jb2 != null)
|
||
// PauseJob(jb2.Name);
|
||
}
|
||
else if (!isModuleError && _isModuleErrorPrevious)
|
||
{
|
||
Reset();
|
||
//CloseDoor();
|
||
}
|
||
|
||
for (int i = 0; i < _lstPms.Count; i++)
|
||
{
|
||
if (!isPMError[i] && _isPMErrorPrevious[i])
|
||
{
|
||
_lstPms[i].ResetTask();
|
||
}
|
||
|
||
_isPMErrorPrevious[i] = isPMError[i];
|
||
}
|
||
|
||
_isModuleErrorPrevious = isModuleError;
|
||
|
||
return Result.RUN;
|
||
}
|
||
|
||
|
||
private string GetWaferStatue(WaferInfo wafer)
|
||
{
|
||
if (wafer.ProcessState == EnumWaferProcessStatus.InProcess)
|
||
{
|
||
return "InProcess";
|
||
}
|
||
else if (wafer.ProcessState == EnumWaferProcessStatus.Completed)
|
||
{
|
||
return "Completed";
|
||
}
|
||
else
|
||
{
|
||
return "Idle";
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
} |