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 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 _lstControlJobs = new List(); private List _lstProcessJobs = new List(); //private Object _locker = new Object(); private List _lstPmsCurrentSequence = new List(); 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 = ""; 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("System.SetUp.IsPM1Installed"); _isPmBInstal = SC.GetValue("System.SetUp.IsPM2Installed"); _isCycleMode = SC.GetValue("System.IsCycleMode"); _cycleSetPoint = _isCycleMode ? SC.GetValue("System.CycleCount") : 0; foreach (var pm in _lstPms) { pm.GetConfigInfo(); } } #region Job Management public void CreateJob(Dictionary param) { //_lstControlJobs = new List(); //_lstProcessJobs = new List(); string[] slotSequence = (string[])param["SlotSequence"]; string jobId = (string)param["JobId"] + DateTime.Now.ToString("yyyyMMddHHmmss"); string module = (string)param["Module"]; bool autoStart = (bool)param["AutoStart"]; if (string.IsNullOrEmpty(jobId)) { jobId = "CJ_Local_" + module; } Dictionary seqSlot = new Dictionary(); Dictionary> seqSlotWafers = new Dictionary>(); Dictionary indexSequence = new Dictionary(); bool enableGroupBySequence = SC.GetValue("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(); } seqSlot[groupName][i] = true; seqSlotWafers[groupName].Add(i); } if (seqSlotWafers.Count == 0) { EV.PostWarningLog(LogSource, $"Can not create job, no wafer assigned"); return; } List pjs = new List(); string[] seqs = seqSlot.Keys.ToArray(); List pjIDs = new List(); 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) { string recipeName = _curRecipeName; if (recipeName.IndexOf(@"\") > 0) { recipeName = recipeName.Substring(recipeName.LastIndexOf(@"\") + 1); } AutoJobRecorder.Add(wafer.InnerId.ToString(), recipeName, (string)param["JobId"], ModuleName.LoadLock.ToString(), GetWaferStatue(wafer)); } } public bool CreateControlJob(string jobId, string module, List 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>(); 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 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>(); 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; } } 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 pjAbortList = new List(); 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 /// /// Start Auto Transfer /// /// /// 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("Scheduler", "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("Scheduler", "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() && _tmRobot.IsAvailable && _loadlock.IsAvailable) { if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); } } } else if (pj.State == EnumProcessJobState.Stopping) { if (CheckAllWaferReturned(pj, false) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned() && _tmRobot.IsAvailable && _loadlock.IsAvailable) { if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); } } } } } private void UpdateControlJobStatus() { if (_lstControlJobs.Count == 0) return; List cjRemoveList = new List(); 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); 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() { //_trigLp1JobComplete.CLK = _isUnloadFoup && CheckJobComplete(ModuleName.LP1.ToString()) && !IsRemoteConnected; //if (_trigLp1JobComplete.Q) //{ // CheckLp1AutoGaslinePurge(); //qiming 20210429 //} //_trigLp2JobComplete.CLK = _isUnloadFoup && CheckJobComplete(ModuleName.LP2.ToString()) && !IsRemoteConnected; //if (_trigLp2JobComplete.Q) //{ // CheckLp2AutoGaslinePurge(); //qiming 20210429 //} foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused) 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(); EV.PostWarningLog("Scheduler", "ControlJob Finished!"); 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)) { EV.PostWarningLog(LogSource, reason1); //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 bool _loadLockFinishedPurgeOver = false; private bool _loadLockFinishedVent = false; private void MonitorLoadLockTask() { if (!_tmRobot.IsAvailable || !_loadlock.IsAvailable) { return; } 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(); //MonitorTmRobotPreHeatTask(); } 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) && CheckWaferSequenceStepDone(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)) { _loadLockFinishedPurgeOver = false; _loadLockFinishedVent = false; placeLL.WaitTransfer(ModuleName.TMRobot); return; } } } } if (!_tmRobot.IsAvailable) return; //pick from ll if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 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.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)) { if (_loadlock.HasWafer(0)) { return; } Hand pickBlade = Hand.Blade1; if (!_buffer.CheckTaskDone() || !CheckWaferSequenceStepDone(_buffer.Module, 0)) { return; } bool waferHasJob = CheckBufferWaferHasJob(); if (!waferHasJob && !_buffer.IsReadyForPick(ModuleName.TMRobot, 0)) { return; } else { 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; } /// /// 判断Buffer的冷却方式是时间还是温度 /// /// /// /// 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 false; return true; } 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.Any(m => ModuleHelper.IsLoadLock(m))) return false; return true; } 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; } /// /// 获取前处理和后处理的Recipe信息 /// /// /// /// 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 true; } if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count && wafer.ProcessJob.Sequence.Steps.Count > 0) { 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 } }