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.DBCore; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Jobs; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; using System; using System.Collections.Generic; using System.Linq; using System.Xml; using VirgoRT.Modules.Schedulers; using VirgoRT.Scheduler; namespace VirgoRT.Modules { public partial class AutoTransfer : TransferModule { private List _lstControlJobs = new List(); private List _lstProcessJobs = new List(); //private Object _locker = new Object(); private List _lstPms = new List(); private List _lstAligners = new List(); private List _lstCoolings = new List(); private List _lstLps = new List(); private const string LogSource = "Scheduler"; private bool _isCycleMode; private int _lp1cycleSetPoint = 0; private int _lp2cycleSetPoint = 0; //private int _cycledCount = 0; //private int _cycledWafer = 0; private int _lp1cycledWafer = 0; private int _lp2cycledWafer = 0; public int CoolingLimit = 1; private int _lp1cycledCount = 0; private int _lp2cycledCount = 0; private bool _isRunningInParallelMode; private bool _isFixAlignerAndCooling; // 如果不同的尺寸,就固定住4寸和6寸,用不同的aligner,cooling,PM,避免来回 private Dictionary _mapLpPm = new Dictionary(); private Dictionary _mapLpAligner = new Dictionary(); private Dictionary _mapLpCooling = new Dictionary(); private List _mapTarget = new List(); public bool HasJobRunning { get { return _lstControlJobs.Count > 0; } } private SchedulerFACallback _faCallback; private SchedulerDBCallback _dbCallback; public AutoTransfer() { _faCallback = new SchedulerFACallback(); _dbCallback = new SchedulerDBCallback(); if (SC.GetValue("System.PMAIsInstalled")) _lstPms.Add(_pma); //if (SC.GetValue("System.PMBIsInstalled")) // _lstPms.Add(_pmb); CoolingLimit = SC.GetValue("System.CoolingTimeLimit"); //_lstAligners.AddRange(new[] { _aligner1, _aligner2 }); _lstCoolings.AddRange(new[] { _cooling1 }); _lstLps.AddRange(new[] { _lp1 }); //DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount); //DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer); DATA.Subscribe("Scheduler.LP1CycledWafer", () => _lp1cycledWafer); DATA.Subscribe("Scheduler.LP2CycledWafer", () => _lp2cycledWafer); DATA.Subscribe("Scheduler.LP1CycledCount", () => _lp1cycledCount); DATA.Subscribe("Scheduler.LP2CycledCount", () => _lp2cycledCount); DATA.Subscribe("Scheduler.LP1CycleSetPoint", () => _lp1cycleSetPoint); DATA.Subscribe("Scheduler.LP2CycleSetPoint", () => _lp2cycleSetPoint); DATA.Subscribe("Scheduler.PjIdList", () => Array.ConvertAll(_lstProcessJobs.ToArray(), x => x.InnerId.ToString()).ToList()); foreach (var lp in _lstLps) { DATA.Subscribe($"{lp.Module}.LocalJobName", () => { var cj = _lstControlJobs.FirstOrDefault(x => x.Module == lp.Module.ToString()); if (cj != null) return cj.Name; return ""; }); DATA.Subscribe($"{lp.Module}.JobLotName", () => { var cj = _lstControlJobs.FirstOrDefault(x => x.Module == lp.Module.ToString()); if (cj != null) return cj.LotName; return ""; }); DATA.Subscribe($"{lp.Module}.LocalJobStatus", () => { var cj = _lstControlJobs.FirstOrDefault(x => x.Module == lp.Module.ToString()); if (cj != null) return cj.State.ToString(); return ""; }); DATA.Subscribe($"{lp.Module}.CurrentRecipeList", () => { var local = lp; List result = Enumerable.Repeat("", 25).ToList(); for (int i = 0; i < _lstProcessJobs.Count; i++) { foreach (var wafers in _lstProcessJobs[i].SlotWafers) { if (wafers.Item1 == local.Module) { result[wafers.Item2] = _lstProcessJobs[i].Sequence.Name; } } } return result; }); } } public void Clear() { _efemRobot.ResetTask(); foreach (var pm in _lstPms) { pm.ResetTask(); } foreach (var buffer in _lstAligners) { buffer.ResetTask(); } foreach (var buffer in _lstCoolings) { buffer.ResetTask(); } foreach (var lp in _lstLps) { lp.ResetTask(); } _lstControlJobs.Clear(); _lstProcessJobs.Clear(); _mapLpAligner.Clear(); _mapLpCooling.Clear(); _mapLpPm.Clear(); _isFixAlignerAndCooling = false; _isRunningInParallelMode = false; _mapTarget.Clear(); } #region Job Management public void CreateJob(Dictionary param) { _isCycleMode = SC.GetValue("System.IsCycleMode"); string[] slotSequence = (string[])param["SlotSequence"]; string jobId = (string)param["JobId"]; string module = (string)param["Module"]; bool autoStart = (bool)param["AutoStart"]; string lotId = jobId; if (param.ContainsKey("LotId")) lotId = (string)param["LotId"]; if (slotSequence.Length != 25) { EV.PostWarningLog(LogSource, $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 25"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (!ModuleHelper.IsLoadPort(ModuleHelper.Converter(module))) { EV.PostWarningLog(LogSource, $"{module} should be LoadPort"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (string.IsNullOrEmpty(jobId)) { jobId = "CJ_Local_" + module; } if (_lstControlJobs.Exists(x => x.Name == jobId)) { EV.PostWarningLog(LogSource, $"{jobId} already created"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } SchedulerLoadPort lp = GetModule(module) as SchedulerLoadPort; if (!lp.CheckReadyRunJob()) { EV.PostWarningLog(LogSource, $"{module} not ready"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } ControlJobInfo cj = new ControlJobInfo(); cj.Name = jobId; cj.Module = module; cj.LotName = lotId; cj.LotInnerId = Guid.NewGuid(); cj.LotWafers = new List(); cj.SetState(EnumControlJobState.WaitingForStart); Dictionary seqSlot = new Dictionary(); Dictionary>> seqSlotWafers = new Dictionary>>(); Dictionary indexSequence = new Dictionary(); bool enableGroupBySequence = SC.GetValue("Scheduler.GroupWaferBySequence"); for (int i = 0; i < 25; i++) { if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim())) continue; string groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString(); indexSequence[groupName] = slotSequence[i]; if (!seqSlot.ContainsKey(groupName)) { seqSlot[groupName] = new bool[25]; } if (!seqSlotWafers.ContainsKey(groupName)) { seqSlotWafers[groupName] = new List>(); } seqSlot[groupName][i] = true; if (!WaferManager.Instance.CheckHasWafer(module, i)) { EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} not in the carrier"); //return; } if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), i, WaferStatus.Normal)) { EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Status}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).ProcessState != EnumWaferProcessStatus.Idle) { EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} process status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).ProcessState}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } var smallWafer = SC.GetValue($"System.SmallWafer"); var _enableTransferFromWS3Slot1 = SC.GetValue($"System.EnableTransferFromWS3Slot1"); //特殊场景,3寸片第一片不能取放 if (i == 0 && (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Size == WaferSize.WS3) && (int)smallWafer == 3 && !_enableTransferFromWS3Slot1) { EV.PostWarningLog(LogSource, $"job wafer: {module} 3 inch slot {i + 1} is not supported."); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } var _slot1UnSupportWaferSize = SC.GetStringValue($"System.LPSlot1UnSupportedWaferSize"); if(i==0 && !string.IsNullOrWhiteSpace(_slot1UnSupportWaferSize)) { var waferSize = WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i)?.Size.ToString().Trim(); if(waferSize != null && _slot1UnSupportWaferSize.Split(',').Select(p => "WS" + p).Contains(waferSize)) { EV.PostWarningLog(LogSource, $"job wafer: {module} {waferSize} inch slot {i + 1} is not supported."); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } } cj.LotWafers.Add(WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i)); WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).SequenceName = slotSequence[i]; WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).NextSequenceStep = 0; WaferManager.Instance.UpdateWaferLotId(ModuleHelper.Converter(module), i, lotId); seqSlotWafers[groupName].Add(Tuple.Create(ModuleHelper.Converter(module), i)); cj.JobWaferSize = WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Size; } if (seqSlotWafers.Count == 0) { EV.PostWarningLog(LogSource, $"job has not assign wafer"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } List pjs = new List(); string[] seqs = seqSlot.Keys.ToArray(); for (int i = 0; i < seqs.Length; i++) { ProcessJobInfo pj = new ProcessJobInfo(); pj.Name = jobId + "_" + (i + 1); pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]); pj.ControlJobName = cj.Name; pj.LotName = lotId; pj.SlotWafers = seqSlotWafers[seqs[i]]; pj.SetState(EnumProcessJobState.Queued); if (!CheckSequencePmReady(pj.Sequence, null, out _, out string reason)) { EV.PostWarningLog(LogSource, $"no valid chamber for the {reason}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (SC.GetValue("System.WaferThickness.EnableThickness")) { // sequence must have thickness type if (string.IsNullOrEmpty(pj.Sequence.ThicknessType)) { EV.PostWarningLog(LogSource, $"not set valid thickness type in {pj.Sequence.Name}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (!lp.CheckOrSetThickness(pj.Sequence.ThicknessType, out string reason1)) { EV.PostWarningLog(LogSource, $"not set valid thickness type in {pj.Sequence.Name}, {reason1}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } } if (!CheckSequenceOrderOk(pj.Sequence, out reason)) { EV.PostWarningLog(LogSource, $"sequence path not valid, {reason}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (!CheckPMWaferSizeSupported(pj, out reason)) { EV.PostAlarmLog(LogSource, $"detect unsupported wafer size, {reason}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (!SC.GetValue("System.IsATMMode") && !CheckSequenceRecipeFileValid(pj.Sequence, out reason)) { EV.PostWarningLog(LogSource, $"recipe file not valid in the sequence, {reason}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } if (!SetSequenceTemperatureInfo(pj.Sequence, out reason)) { EV.PostWarningLog(LogSource, $"sequence recipe temperature not valid, {reason}"); _faCallback.JobCreateFailed(module, lotId, jobId, ""); return; } pjs.Add(pj); } _dbCallback.LotUpdate(cj); foreach (var pj in pjs) { cj.ProcessJobNameList.Add(pj.Name); _lstProcessJobs.Add(pj); } _lstControlJobs.Add(cj); UpdateParallelMode(); _faCallback.JobCreated(cj, GetFirstProcessJob(cj)); if (cj.Module == ModuleName.LP1.ToString()) { _lp1cycleSetPoint = _isCycleMode ? SC.GetValue("System.CycleCount") : 0; _lp1cycledWafer = 0; _lp1cycledCount = 0; } else if (cj.Module == ModuleName.LP2.ToString()) { _lp2cycleSetPoint = _isCycleMode ? SC.GetValue("System.CycleCount") : 0; _lp2cycledWafer = 0; _lp2cycledCount = 0; } } internal ProcessJobInfo GetFirstProcessJob(ControlJobInfo cj) { foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name) return pj; } return null; } 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); } } _faCallback.JobStopped(cj, GetFirstProcessJob(cj)); _dbCallback.LotFinished(cj); } 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; } 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++; } JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed); } } _faCallback.JobAborted(cj, GetFirstProcessJob(cj)); _dbCallback.LotFinished(cj); foreach (var pj in pjAbortList) { _lstProcessJobs.Remove(pj); } _lstControlJobs.Remove(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); } _faCallback.JobResumed(cj, GetFirstProcessJob(cj)); } internal void StartJob(string jobName) { ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName); 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); //PreJobClean(cj); (GetModule(cj.Module) as SchedulerLoadPort).NoteJobStart(); cj.StartTime = DateTime.Now; _dbCallback.LotCreated(cj); _faCallback.JobStarted(cj, GetFirstProcessJob(cj)); } } 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); } _faCallback.JobPaused(cj, GetFirstProcessJob(cj)); } internal void Map(string moduleName) { ModuleName target = ModuleHelper.Converter(moduleName); if (!ModuleHelper.IsLoadPort(target)) { EV.PostWarningLog(LogSource, $"Invalid map target {target}"); return; } if (!_mapTarget.Contains(target)) { _mapTarget.Add(target); } } #endregion Job Management public Result Start(params object[] objs) { //_isCycleMode = SC.GetValue("System.IsCycleMode"); //_cycleSetPoint = _isCycleMode ? SC.GetValue("System.CycleCount") : 0; //_cycledWafer = 0; //_cycledCount = 0; //_lp1cycledWafer = 0; //_lp2cycledWafer = 0; var waferInfo = ""; bool hasPmOnline = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsAvailable) { schedulerPm.SetPMAuto(); hasPmOnline = true; continue; } } if (WaferManager.Instance.CheckHasWafer(ModuleName.PMA, 0)) waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.PMA}"; if (WaferManager.Instance.CheckHasWafer(ModuleName.Cooling1, 0)) waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.Cooling1}"; if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0)) waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.EfemRobot} primary arm"; if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1)) waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.EfemRobot} secondly arm"; if (waferInfo != "") { EV.PostWarningLog("Scheduler", $"can not change to auto mode, {waferInfo} wafer presence."); return Result.FAIL; } if (!hasPmOnline) { EV.PostWarningLog("Scheduler", "can not change to auto mode, at least one process chamber be online"); return Result.FAIL; } return Result.RUN; } public Result Monitor() { MonitorEfemRobotMapTask(); ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing); if (cjActive != null) { MonitorModuleTasks(); } MonitorJobTasks(); MonitorCleanTasks(); return Result.RUN; } #region Job task public Result MonitorJobTasks() { UpdateParallelMode(); UpdateProcessJobStatus(); UpdateControlJobStatus(); StartNewJob(); return Result.RUN; } private void UpdateParallelMode() { bool enableParallel = SC.GetValue("Scheduler.IsRunInParallelMode"); bool bothLpHasJob = true; _isRunningInParallelMode = enableParallel; Dictionary> lpNeededPmTemperature = new Dictionary>(); foreach (var lp in _lstLps) { var cj = _lstControlJobs.Find(x => x.Module == lp.Module.ToString()); bothLpHasJob = bothLpHasJob && (cj != null); if (cj != null) { lpNeededPmTemperature[lp.Module] = new Dictionary(); var pj = _lstProcessJobs.FirstOrDefault(x => x.ControlJobName == cj.Name); if (pj != null) { var seq = pj.Sequence; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module) && !lpNeededPmTemperature[lp.Module].ContainsKey(module)) { lpNeededPmTemperature[lp.Module][module] = (float)seq.Steps[i] .StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"]; } } } } } } bool needSamePm = false; ModuleName pmSource = ModuleName.System; foreach (var pmNeeded in lpNeededPmTemperature) { if (pmNeeded.Value.Count == 1) { var source = pmNeeded.Value.Keys.First(); if (source != pmSource) { pmSource = source; } else { needSamePm = true; break; } } else if (pmNeeded.Value.Count > 1) { needSamePm = true; } } var needFixPosition = enableParallel && bothLpHasJob && !needSamePm; _isRunningInParallelMode = needFixPosition; if (needFixPosition != _isFixAlignerAndCooling) { _isFixAlignerAndCooling = needFixPosition; if (needFixPosition) { //aligner固定不做逻辑 _mapLpAligner[ModuleName.LP1] = ModuleName.Aligner1; _mapLpAligner[ModuleName.LP2] = ModuleName.Aligner2; _mapLpCooling[ModuleName.LP1] = ModuleName.Cooling1; _mapLpCooling[ModuleName.LP2] = ModuleName.Cooling2; bool assigned = false; foreach (var pmNeeded in lpNeededPmTemperature) { if (pmNeeded.Value.Count == 1) { _mapLpPm[pmNeeded.Key] = pmNeeded.Value.Keys.First(); var anotherLp = pmNeeded.Key == ModuleName.LP1 ? ModuleName.LP2 : ModuleName.LP1; var anotherPm = _mapLpPm[pmNeeded.Key] == ModuleName.PMA ? ModuleName.PMB : ModuleName.PMA; _mapLpPm[anotherLp] = anotherPm; assigned = true; break; } } if (!assigned) { _mapLpPm[ModuleName.LP1] = ModuleName.PMA; _mapLpPm[ModuleName.LP2] = ModuleName.PMB; float pmaTemp = ((SchedulerPM)GetModule(ModuleName.PMA.ToString())).Temperature; float pmbTemp = ((SchedulerPM)GetModule(ModuleName.PMB.ToString())).Temperature; float tempCurrent = Math.Abs(lpNeededPmTemperature[ModuleName.LP1][ModuleName.PMA] - pmaTemp) + Math.Abs(lpNeededPmTemperature[ModuleName.LP2][ModuleName.PMB] - pmbTemp); float tempAnother = Math.Abs(lpNeededPmTemperature[ModuleName.LP1][ModuleName.PMB] - pmbTemp) + Math.Abs(lpNeededPmTemperature[ModuleName.LP2][ModuleName.PMA] - pmaTemp); if (tempAnother < tempCurrent) { _mapLpPm[ModuleName.LP1] = ModuleName.PMB; _mapLpPm[ModuleName.LP2] = ModuleName.PMA; } } } } } private void UpdateProcessJobStatus() { foreach (var pj in _lstProcessJobs) { if (pj.State == EnumProcessJobState.Processing) { if (CheckAllWaferReturned(pj, true)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); } } else if (pj.State == EnumProcessJobState.Stopping) { if (CheckAllWaferReturned(pj, false)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); } } } } private void UpdateControlJobStatus() { if (_lstControlJobs.Count == 0) return; bool lp1ControlJobComplete = true; bool lp2ControlJobComplete = true; List cjRemoveList = new List(); foreach (var cj in _lstControlJobs) { if (!GetModule(cj.Module).IsAvailable) { if (cj.Module == ModuleName.LP1.ToString()) lp1ControlJobComplete = false; else { lp2ControlJobComplete = false; } continue; } 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) { cj.SetState(EnumControlJobState.Completed); cj.EndTime = DateTime.Now; int cycledCount = cj.Module == ModuleName.LP1.ToString() ? _lp1cycledCount : _lp2cycledCount; int cycleSetPoint = cj.Module == ModuleName.LP1.ToString() ? _lp1cycleSetPoint : _lp2cycleSetPoint; if (!(_isCycleMode && cycledCount + 1 < cycleSetPoint)) { CompleteJobClean(cj); } _faCallback.JobFinished(cj, GetFirstProcessJob(cj)); _dbCallback.LotFinished(cj); if (!(_isCycleMode && cycledCount < cycleSetPoint)) (GetModule(cj.Module) as SchedulerLoadPort).NoteJobComplete(); } } LoadportCassetteState state = (LoadportCassetteState)DATA.Poll($"{cj.Module}.CassetteState"); if (cj.State == EnumControlJobState.Completed && state != LoadportCassetteState.Normal) { cjRemoveList.Add(cj); } if (cj.Module == ModuleName.LP1.ToString()) { lp1ControlJobComplete = lp1ControlJobComplete && cj.State == EnumControlJobState.Completed; } else { lp2ControlJobComplete = lp2ControlJobComplete && cj.State == EnumControlJobState.Completed; } } if (_isCycleMode && ((_lp1cycledCount < _lp1cycleSetPoint) || (_lp2cycledCount < _lp2cycleSetPoint))) { //int countPerCycle = 0; int lp1countPerCycle = 0; int lp2countPerCycle = 0; //int countProcessed = 0; int lp1countProcessed = 0; int lp2countProcessed = 0; foreach (var pj in _lstProcessJobs) { var cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName); if (cj.Module == ModuleName.LP1.ToString()) { foreach (var pjSlotWafer in pj.SlotWafers) { lp1countPerCycle++; WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2); if (!wafer.IsEmpty) { if (!(wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)) { if (!CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2)) { lp1countProcessed++; } } } //if (!wafer.IsEmpty && !CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2)) // lp1countProcessed++; } } else if (cj.Module == ModuleName.LP2.ToString()) { foreach (var pjSlotWafer in pj.SlotWafers) { lp2countPerCycle++; WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2); if (!wafer.IsEmpty) { if (!(wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)) { if (!CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2)) { lp2countProcessed++; } } } //if (!wafer.IsEmpty && !CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2)) // lp2countProcessed++; } } //foreach (var pjSlotWafer in pj.SlotWafers) //{ // countPerCycle++; // WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2); // if (!wafer.IsEmpty && !CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2)) // countProcessed++; //} } //_cycledWafer = _cycledCount * countPerCycle + countProcessed; if (_lp1cycledCount < _lp1cycleSetPoint) _lp1cycledWafer = _lp1cycledCount * lp1countPerCycle + lp1countProcessed; if (_lp2cycledCount < _lp2cycleSetPoint) _lp2cycledWafer = _lp2cycledCount * lp2countPerCycle + lp2countProcessed; if (lp1ControlJobComplete && (_lp1cycledCount < _lp1cycleSetPoint)) { _lp1cycledCount++; if (_lp1cycledCount < _lp1cycleSetPoint) { foreach (var cj in _lstControlJobs) { if (cj.Module != ModuleName.LP1.ToString()) continue; cj.SetState(EnumControlJobState.Executing); cj.LotInnerId = Guid.NewGuid(); //PreJobClean(cj); _dbCallback.LotCreated(cj); foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName != 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; } } } } } if (lp2ControlJobComplete && (_lp2cycledCount < _lp2cycleSetPoint)) { _lp2cycledCount++; if (_lp2cycledCount < _lp2cycleSetPoint) { foreach (var cj in _lstControlJobs) { if (cj.Module != ModuleName.LP2.ToString()) continue; cj.SetState(EnumControlJobState.Executing); cj.LotInnerId = Guid.NewGuid(); //PreJobClean(cj); _dbCallback.LotCreated(cj); foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName != 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; } } } } } } foreach (var cj in cjRemoveList) { List pjRemoveList = new List(); foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name) pjRemoveList.Add(pj); } foreach (var pj in pjRemoveList) { _lstProcessJobs.Remove(pj); } _lstControlJobs.Remove(cj); } if (cjRemoveList.Count > 0) { UpdateParallelMode(); } } public bool CheckJobJustDone(out string sJobName) { foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Completed && !cj.BeenPosted) { //LP;WaferSize;Lot;Number;Start;End; sJobName = $"{cj.Module};{cj.JobWaferSize};{cj.LotName};{cj.LotWafers.Count};{cj.StartTime:T};{cj.EndTime:T}"; cj.BeenPosted = true; return true; } } //string strInfo = $"{cj.Module} has finished: \r\n\r\nProcessed wafer number: {cj.LotWafers.Count} \r\nStart time: {cj.BeginTime} \r\nEnd time: {cj.EndTime} \r\nDuration: {(cj.EndTime - cj.BeginTime).TotalSeconds:F0} sec"; sJobName = "NULL"; return false; } public bool CheckAllJobDone() { foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused) return false; } return true; } private void StartNewJob() { ControlJobInfo cjActived = null; List pmOccupied = GetPmUsedInRunningPj(); foreach (var cj in _lstControlJobs) { if (cj.State != EnumControlJobState.Executing) continue; cjActived = cj; foreach (var pjName in cjActived.ProcessJobNameList) { var pj = _lstProcessJobs.Find(x => x.Name == pjName); if (pj == null) { LOG.Error($"Not find pj named {pjName} in {cjActived.Name}"); continue; } if (pj.State == EnumProcessJobState.Queued) { if (CheckSequencePmReady(pj.Sequence, pmOccupied, out var pmUsed, out string reason)) { ActiveProcessJob(pj); foreach (var moduleName in pmUsed) { if (!pmOccupied.Contains(moduleName)) pmOccupied.Add(moduleName); } } break; } } if (!_isRunningInParallelMode) break; } } private bool ActiveProcessJob(ProcessJobInfo pj) { foreach (var pjSlotWafer in pj.SlotWafers) { WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2); wafer.ProcessJob = pj; wafer.NextSequenceStep = 0; WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString()); } ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName); CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module); JobDataRecorder.StartPJ(pj.InnerId.ToString(), carrier.InnerId.ToString(), cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count); pj.SetState(EnumProcessJobState.Processing); PreJobClean(cj); return true; } #endregion Job task #region Module task public Result MonitorModuleTasks() { MonitorPMTask(); MonitorAlignerTask(); MonitorCoolingTask(); MonitorInterlockTask(); MonitorEfemRobotTask(); return Result.RUN; } private void MonitorInterlockTask() { foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused || cj.State == EnumControlJobState.WaitingForStart) { var lp = GetModule(cj.Module); if (!(lp as SchedulerLoadPort).CheckPlaced()) { EV.PostAlarmLog("System", "Cassette removed while job not finished."); Singleton.Instance.PostMsg(RouteManager.MSG.ERROR); } } } } private void MonitorAlignerTask() { if (!_efemRobot.IsAvailable) return; foreach (var buffer in _lstAligners) { if (buffer.IsWaitTransfer(ModuleName.EfemRobot)) { buffer.PostTransfer(ModuleName.EfemRobot); } } foreach (var schedulerBuffer in _lstAligners) { if (!schedulerBuffer.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0) ) continue; if (CheckWaferNextStepIsAlign(schedulerBuffer.Module, 0)) { WaferInfo wafer = WaferManager.Instance.GetWafers(schedulerBuffer.Module)[0]; var job = wafer.ProcessJob; GetWaferSequenceAlignTime(schedulerBuffer.Module, 0, out float time); if (schedulerBuffer.Align(time)) { wafer.NextSequenceStep++; } } } } private void MonitorCoolingTask() { if (!_efemRobot.IsAvailable) return; foreach (var buffer in _lstCoolings) { if (buffer.IsWaitTransfer(ModuleName.EfemRobot)) { buffer.PostTransfer(ModuleName.EfemRobot); } } foreach (var schedulerBuffer in _lstCoolings) { if (!schedulerBuffer.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0) ) continue; if (CheckWaferNextStepIsCooling(schedulerBuffer.Module, 0)) { WaferInfo wafer = WaferManager.Instance.GetWafers(schedulerBuffer.Module)[0]; var job = wafer.ProcessJob; GetWaferSequenceAlignTime(schedulerBuffer.Module, 0, out float time); if (time < CoolingLimit) { time = CoolingLimit; } if (schedulerBuffer.Cooling((int)time)) { wafer.NextSequenceStep++; } } } } private void MonitorEfemRobotTask() { if (!_efemRobot.IsAvailable) return; //efem robot is idle, release all the target foreach (var pm in _lstPms) { if (pm.IsWaitTransfer(ModuleName.EfemRobot)) { pm.PostTransfer(ModuleName.EfemRobot); } } if (_efemRobot.FirstDetectWaferArrive(0) && _efemRobot.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, 0)) GetModule(_efemRobot.Module).GetWaferInfo(0).NextSequenceStep++; if (_efemRobot.FirstDetectWaferArrive(1) && _efemRobot.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, 1)) GetModule(_efemRobot.Module).GetWaferInfo(1).NextSequenceStep++; //efem robot is idle, release all the target foreach (var lp in _lstLps) { if (lp.IsWaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick)) { lp.PostTransfer(ModuleName.EfemRobot); } if (lp.IsWaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place)) { lp.PostTransfer(ModuleName.EfemRobot); ProcessJobInfo pj = WaferManager.Instance.GetWafer(lp.Module, lp.InTransferSlot) .ProcessJob; ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName); _faCallback.JobWaferEnd(cj, pj, lp.Module.ToString(), lp.InTransferSlot); } } MonitorEfemRobotLoadPortTask(); if (!_efemRobot.IsAvailable) return; if (!_efemRobot.IsAvailable) return; MonitorEfemRobotPMTask(); if (!_efemRobot.IsAvailable) return; MonitorEfemRobotCoolingTask(); if (!_efemRobot.IsAvailable) return; MonitorEfemRobotGotoTask(); } private void MonitorEfemRobotMapTask() { if (!_efemRobot.IsAvailable) return; if (_mapTarget.Count > 0) { ModuleName first = _mapTarget[0]; //避免重复map,job信息被清除 foreach (var cj in _lstControlJobs) { if (cj.Module != first.ToString()) continue; if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused) { EV.PostWarningLog("System", $"{first} is running, can not map again"); _mapTarget.Remove(first); return; } } SchedulerLoadPort lp = GetModule(first.ToString()) as SchedulerLoadPort; if (lp != null && lp.IsAvailable) { _efemRobot.Map(first); _mapTarget.Remove(first); } } } private void MonitorEfemRobotPMTask() { if (!_efemRobot.IsAvailable) return; //swap PM if (_efemRobot.Blade1Enable && _efemRobot.Blade2Enable && (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ^ WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1))) { Hand pickBlade = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ? Hand.Blade1 : Hand.Blade2; Hand placeBlade = pickBlade == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1; SchedulerPM swapPm = null; foreach (var pm in _lstPms) { if (!pm.IsAvailable || !WaferManager.Instance.CheckHasWafer(pm.Module, 0) || CheckWaferNeedProcess(pm.Module, 0, pm.Module) || !pm.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade) || !CheckVacuumWaferHasAvailableTarget(pm.Module, 0) || !CheckWaferNextProcessIn(ModuleName.EfemRobot, (int)placeBlade, pm.Module)) continue; if (swapPm == null || (pm.WaferArriveTicks[0] < swapPm.WaferArriveTicks[0])) { swapPm = pm; } } if (swapPm != null && _efemRobot.CheckWaferNextStepIsThisModuleSlotInSwap(swapPm.Module, 0, (int)pickBlade) && CheckWaferCanPick(swapPm.Module, 0, pickBlade)) { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)pickBlade) && _efemRobot.PickAndPlace(swapPm.Module, 0, 0, pickBlade, placeBlade)) { swapPm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } if (!_efemRobot.IsAvailable) return; //place to pm bool blade0HasWaferAndNeedProcess = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedProcess(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedProcess = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedProcess(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedProcess || blade1HasWaferAndNeedProcess) { List orderedBlade = new List(); if (blade0HasWaferAndNeedProcess && blade1HasWaferAndNeedProcess) { int result = CompareWaferPriority(ModuleName.EfemRobot, 0, ModuleName.EfemRobot, 1); if (result < 0 || (result == 0 && _efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0])) { orderedBlade.AddRange(new List() { Hand.Blade2, Hand.Blade1 }); } else { orderedBlade.AddRange(new List() { Hand.Blade1, Hand.Blade2 }); } } else { orderedBlade.Add(blade0HasWaferAndNeedProcess ? Hand.Blade1 : Hand.Blade2); } foreach (Hand placeBlade in orderedBlade) { foreach (var pm in _lstPms) { if (!pm.IsAvailable || !WaferManager.Instance.CheckNoWafer(pm.Module, 0) || !CheckWaferNextProcessIn(ModuleName.EfemRobot, (int)placeBlade, pm.Module)) continue; if (_isFixAlignerAndCooling && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1) { int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).OriginStation; if (origin == (int)ModuleName.LP1 && _mapLpPm[ModuleName.LP1] != pm.Module) continue; if (origin == (int)ModuleName.LP2 && _mapLpPm[ModuleName.LP2] != pm.Module) continue; } if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(pm.Module, 0, placeBlade)) { pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } } } } if (!_efemRobot.IsAvailable) return; if (_cooling1.HasWafer(0) && (!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable)) return; int waferCount = 0; if (_cooling1.HasWafer(0)) waferCount++; //if (_cooling2.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0) && !_efemRobot.CheckWaferNextStepModule(0, _pma.Module)) waferCount++; if (_efemRobot.HasWafer(1) && !_efemRobot.CheckWaferNextStepModule(1, _pma.Module)) waferCount++; if (waferCount >= 2) return; //pick from pm bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickPm = ModuleName.System; int preOriginSlot = int.MaxValue; string pmPj = string.Empty; int preWaferCountInCooling = 0; foreach (var schedulerPm in _lstPms) { if (!schedulerPm.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0) || CheckWaferNeedProcess(schedulerPm.Module, 0, schedulerPm.Module)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerPm.Module, 0); bool pickAllowed = CheckVacuumWaferHasAvailableTarget(schedulerPm.Module, 0); if (!pickAllowed) continue; if ((pickPm == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && pmPj == wafer.ProcessJob.Name) || (GetCoolingWaferCount(wafer.ProcessJob.Name) < preWaferCountInCooling)) { preOriginSlot = wafer.OriginSlot; pickPm = schedulerPm.Module; pmPj = wafer.ProcessJob.Name; preWaferCountInCooling = GetCoolingWaferCount(pmPj); continue; } } if (pickPm != ModuleName.System) { SchedulerModule pm = GetModule(pickPm.ToString()); //if (!pm.CheckWaferNextStepModuleNoWafer(0)) //{ // return; //} Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 0) && CheckWaferCanPick(pickPm, 0, Hand.Blade1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 1) && CheckWaferCanPick(pickPm, 0, Hand.Blade2)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 1) && CheckWaferCanPick(pickPm, 0, Hand.Blade1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 0) && CheckWaferCanPick(pickPm, 0, Hand.Blade2)) { pickBlade = Hand.Blade2; } else { return; } //if (blade1Empty && blade2Empty) //{ // if (_efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0]) // pickBlade = Hand.Blade2; //} if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)pickBlade) && pm.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(pm.Module, 0, pickBlade)) { pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } private void MonitorEfemRobotPMPlaceTask() { //place to pm bool blade0HasWaferAndNeedProcess = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedProcess(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedProcess = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedProcess(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedProcess || blade1HasWaferAndNeedProcess) { List orderedBlade = new List(); if (blade0HasWaferAndNeedProcess && blade1HasWaferAndNeedProcess) { int result = CompareWaferPriority(ModuleName.EfemRobot, 0, ModuleName.EfemRobot, 1); if (result < 0 || (result == 0 && _efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0])) { orderedBlade.AddRange(new List() { Hand.Blade2, Hand.Blade1 }); } else { orderedBlade.AddRange(new List() { Hand.Blade1, Hand.Blade2 }); } } else { orderedBlade.Add(blade0HasWaferAndNeedProcess ? Hand.Blade1 : Hand.Blade2); } foreach (Hand placeBlade in orderedBlade) { foreach (var pm in _lstPms) { if (!pm.IsAvailable || !WaferManager.Instance.CheckNoWafer(pm.Module, 0) || !CheckWaferNextProcessIn(ModuleName.EfemRobot, (int)placeBlade, pm.Module)) continue; if (_isFixAlignerAndCooling && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1) { int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).OriginStation; if (origin == (int)ModuleName.LP1 && _mapLpPm[ModuleName.LP1] != pm.Module) continue; if (origin == (int)ModuleName.LP2 && _mapLpPm[ModuleName.LP2] != pm.Module) continue; } if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(pm.Module, 0, placeBlade)) { pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } } } } } private void MonitorEfemRobotPMPickTask() { if (!_efemRobot.IsAvailable) return; if (_cooling1.HasWafer(0) && (!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable)) return; int waferCount = 0; if (_cooling1.HasWafer(0)) waferCount++; //if (_cooling2.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0) && !_efemRobot.CheckWaferNextStepModule(0, _pma.Module)) waferCount++; if (_efemRobot.HasWafer(1) && !_efemRobot.CheckWaferNextStepModule(1, _pma.Module)) waferCount++; if (waferCount >= 2) return; //pick from pm bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickPm = ModuleName.System; int preOriginSlot = int.MaxValue; string pmPj = string.Empty; int preWaferCountInCooling = 0; foreach (var schedulerPm in _lstPms) { if (!schedulerPm.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0) || CheckWaferNeedProcess(schedulerPm.Module, 0, schedulerPm.Module)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerPm.Module, 0); bool pickAllowed = false; if (!pickAllowed) continue; if ((pickPm == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && pmPj == wafer.ProcessJob.Name) || (GetCoolingWaferCount(wafer.ProcessJob.Name) < preWaferCountInCooling)) { preOriginSlot = wafer.OriginSlot; pickPm = schedulerPm.Module; pmPj = wafer.ProcessJob.Name; preWaferCountInCooling = GetCoolingWaferCount(pmPj); continue; } } if (pickPm != ModuleName.System) { SchedulerModule pm = GetModule(pickPm.ToString()); //if (!pm.CheckWaferNextStepModuleNoWafer(0)) //{ // return; //} Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 0)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 1)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickPm, 0, 0)) { pickBlade = Hand.Blade2; } else { return; } //if (blade1Empty && blade2Empty) //{ // if (_efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0]) // pickBlade = Hand.Blade2; //} if (pm.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(pm.Module, 0, pickBlade)) { pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } private void MonitorEfemRobotLoadPortTask() { if (!_efemRobot.IsAvailable) return; bool blade0HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && !CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && !CheckWaferNeedCooling(ModuleName.EfemRobot, 0); bool blade1HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && !CheckWaferNeedProcess(ModuleName.EfemRobot, 1) && !CheckWaferNeedCooling(ModuleName.EfemRobot, 1); //pick bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if ( GetWaferCountInJobQueue(ModuleName.System) > 0 && (blade1Empty || blade2Empty) && GetNextWaferInJobQueue(ModuleName.System) != null) { SlotItem position = GetNextWaferInJobQueue(ModuleName.System); bool canPick = false; if (position != null && CheckWaferPmTemperatureIsOk(position.Module, position.Slot)) { SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(position.Module.ToString()); if (lp.CheckWaferNextStepModuleNoWafer(position.Slot)) { Hand pickBlade = Hand.Blade1; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0) && CheckWaferCanPick(position.Module, position.Slot, Hand.Blade1)) { pickBlade = Hand.Blade1; canPick = true; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1) && CheckWaferCanPick(position.Module, position.Slot, Hand.Blade2)) { pickBlade = Hand.Blade2; canPick = true; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1) && CheckWaferCanPick(position.Module, position.Slot, Hand.Blade1)) { pickBlade = Hand.Blade1; canPick = true; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0) && CheckWaferCanPick(position.Module, position.Slot, Hand.Blade2)) { pickBlade = Hand.Blade2; canPick = true; } //var nextPosition = GetNextNextWaferInJobQueue(ModuleName.System, position.Slot); int pickSlot = position.Slot; //if (nextPosition != null && blade1Empty && blade2Empty && Math.Abs(nextPosition.Slot - position.Slot) == 1 && position.Module == nextPosition.Module) //{ // var wafer = WaferManager.Instance.GetWafer(position.Module, position.Slot); // var nextWafer = WaferManager.Instance.GetWafer(nextPosition.Module, nextPosition.Slot); // if (wafer != null && // wafer.ProcessJob != null && // wafer.ProcessJob.Sequence != null && // wafer.ProcessJob.Sequence.Steps != null && // wafer.ProcessJob.Sequence.Steps.Count > 0 && // wafer.ProcessJob.Sequence.Steps[0].StepModules != null && // wafer.ProcessJob.Sequence.Steps[0].StepModules.Contains(ModuleName.EfemRobot) && // wafer.ProcessJob.Sequence.Steps[0].StepParameter != null && // (wafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("0,1") || wafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("1,0")) && // nextWafer != null && // nextWafer.ProcessJob != null && // nextWafer.ProcessJob.Sequence != null && // nextWafer.ProcessJob.Sequence.Steps != null && // nextWafer.ProcessJob.Sequence.Steps.Count > 0 && // nextWafer.ProcessJob.Sequence.Steps[0].StepModules != null && // nextWafer.ProcessJob.Sequence.Steps[0].StepModules.Contains(ModuleName.EfemRobot) && // nextWafer.ProcessJob.Sequence.Steps[0].StepParameter != null && // (nextWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("0,1") || nextWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("1,0"))) // { // bool isNextStepEmpty = false; // foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules) // { // if (WaferManager.Instance.CheckNoWafer(stepModule, 0)) // isNextStepEmpty = true; // } // foreach (var stepModule in nextWafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules) // { // if (WaferManager.Instance.CheckNoWafer(stepModule, 0)) // isNextStepEmpty = true; // } // if (isNextStepEmpty) // { // pickSlot = position.Slot < nextPosition.Slot ? position.Slot : nextPosition.Slot; // pickBlade = Hand.Both; // } // } //} if (lp.IsReadyForPick(ModuleName.EfemRobot, pickSlot, pickBlade) && canPick) { if ((blade0HasWaferAndProcessed && pickBlade == Hand.Blade2) || (blade1HasWaferAndProcessed && pickBlade == Hand.Blade1)) { Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2; SlotItem destination = GetWaferReturnLoadPort(_efemRobot.Module, (int)placeBlade); if (destination != null && ModuleHelper.IsLoadPort(destination.Module)) { if (lp.IsReadyForPlace(ModuleName.EfemRobot, destination.Slot, placeBlade)) { if (_efemRobot.PickAndPlace(position.Module, position.Slot, destination.Slot, pickBlade, (Hand)placeBlade)) { lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, destination.Slot); return; } } } } if (_cooling1.HasWafer(0) && (!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable)) canPick = false; int waferCount = 0; if (_cooling1.HasWafer(0)) waferCount++; //if (_aligner2.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(1)) waferCount++; if (waferCount >= 2) canPick = false; if((!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable) && (_cooling1.HasWafer(0) || _pma.HasWafer(0))) { canPick = false; } if (canPick && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)pickBlade) && _efemRobot.Pick(position.Module, position.Slot, pickBlade)) { lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, position.Slot); return; } } } } } if (!_efemRobot.IsAvailable) return; //place if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed) { Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2; if (blade0HasWaferAndProcessed && blade1HasWaferAndProcessed) { if (WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginSlot < WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginSlot) { placeBlade = Hand.Blade2; } } SlotItem destination = GetWaferReturnLoadPort(_efemRobot.Module, (int)placeBlade); if (destination != null && ModuleHelper.IsLoadPort(destination.Module)) { SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(destination.Module.ToString()); if (lp.IsReadyForPlace(ModuleName.EfemRobot, destination.Slot, placeBlade)) { if (_efemRobot.Place(destination.Module, destination.Slot, (Hand)placeBlade)) { lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, destination.Slot); return; } } } } } private void MonitorEfemRobotLoadPortPlaceTask() { if (!_efemRobot.IsAvailable) return; //place bool blade0HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && !CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && !CheckWaferNeedCooling(ModuleName.EfemRobot, 0); bool blade1HasWaferAndProcessed = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && !CheckWaferNeedProcess(ModuleName.EfemRobot, 1) && !CheckWaferNeedCooling(ModuleName.EfemRobot, 1); if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed) { Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2; if (blade0HasWaferAndProcessed && blade1HasWaferAndProcessed) { if (WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginSlot < WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginSlot) { placeBlade = Hand.Blade2; } } SlotItem destination = GetWaferReturnLoadPort(_efemRobot.Module, (int)placeBlade); if (destination != null && ModuleHelper.IsLoadPort(destination.Module)) { SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(destination.Module.ToString()); if (lp.IsReadyForPlace(ModuleName.EfemRobot, destination.Slot, placeBlade)) { if (_efemRobot.Place(destination.Module, destination.Slot, (Hand)placeBlade)) { lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, destination.Slot); //_cycledTotalWafer++; //if (SC.ContainsItem("System.TotalCycledWafer")) // SC.SetItemValue("System.TotalCycledWafer", _cycledTotalWafer); return; } } } } } private void MonitorEfemRobotLoadPortPickTask() { if (!_efemRobot.IsAvailable) return; if (_cooling1.HasWafer(0) && (!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable)) return; int waferCount = 0; if (_cooling1.HasWafer(0)) waferCount++; //if (_aligner2.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(1)) waferCount++; if (waferCount >= 2) return; //pick int maxOutWafer = 6;//cooling*2 + Aligner*2+PM*2 bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); bool bothAlignerEmpty = true; foreach (var schedulerAligner in _lstAligners) { if (WaferManager.Instance.CheckHasWafer(schedulerAligner.Module, 0)) { bothAlignerEmpty = false; break; } } bool bothBladeEmpty = blade1Empty && blade2Empty; if (GetWaferCountOutofLP(ModuleName.System) < maxOutWafer && GetWaferCountInJobQueue(ModuleName.System) > 0 && (bothBladeEmpty || (bothAlignerEmpty && (blade1Empty || blade2Empty)))) { SlotItem position = GetNextWaferInJobQueue(ModuleName.System); if (position != null //&& CheckWaferHasAvailableTarget(position.Module, position.Slot) && CheckWaferPmTemperatureIsOk(position.Module, position.Slot)) { SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(position.Module.ToString()); if (!lp.CheckWaferNextStepModuleNoWafer(position.Slot)) { return; } Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0)) { pickBlade = Hand.Blade2; } else { return; } var nextPosition = GetNextNextWaferInJobQueue(ModuleName.System, position.Slot); int pickSlot = position.Slot; if (nextPosition != null && bothBladeEmpty && Math.Abs(nextPosition.Slot - position.Slot) == 1 && position.Module == nextPosition.Module) { var wafer = WaferManager.Instance.GetWafer(position.Module, position.Slot); var nextWafer = WaferManager.Instance.GetWafer(nextPosition.Module, nextPosition.Slot); if (wafer != null && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.ProcessJob.Sequence.Steps != null && wafer.ProcessJob.Sequence.Steps.Count > 0 && wafer.ProcessJob.Sequence.Steps[0].StepModules != null && wafer.ProcessJob.Sequence.Steps[0].StepModules.Contains(ModuleName.EfemRobot) && wafer.ProcessJob.Sequence.Steps[0].StepParameter != null && (wafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("0,1") || wafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("1,0")) && nextWafer != null && nextWafer.ProcessJob != null && nextWafer.ProcessJob.Sequence != null && nextWafer.ProcessJob.Sequence.Steps != null && nextWafer.ProcessJob.Sequence.Steps.Count > 0 && nextWafer.ProcessJob.Sequence.Steps[0].StepModules != null && nextWafer.ProcessJob.Sequence.Steps[0].StepModules.Contains(ModuleName.EfemRobot) && nextWafer.ProcessJob.Sequence.Steps[0].StepParameter != null && (nextWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("0,1") || nextWafer.ProcessJob.Sequence.Steps[0].StepParameter.ContainsValue("1,0"))) { bool isNextStepEmpty = false; foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules) { if (WaferManager.Instance.CheckNoWafer(stepModule, 0)) isNextStepEmpty = true; } foreach (var stepModule in nextWafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules) { if (WaferManager.Instance.CheckNoWafer(stepModule, 0)) isNextStepEmpty = true; } if (isNextStepEmpty) { pickSlot = position.Slot < nextPosition.Slot ? position.Slot : nextPosition.Slot; pickBlade = Hand.Both; } } } if (lp.IsReadyForPick(ModuleName.EfemRobot, pickSlot, pickBlade)) { if (_efemRobot.Pick(position.Module, position.Slot, pickBlade)) { lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, position.Slot); return; } } } } } private void MonitorEfemRobotAlignerTask() { if (!_efemRobot.IsAvailable) return; ////swap Aligner //if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ^ WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)) //{ // Hand pickBlade = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ? Hand.Blade1 : Hand.Blade2; // Hand placeBlade = pickBlade == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1; // SchedulerAligner swapAligner = null; // foreach (var aligner in _lstAligners) // { // if (!aligner.IsAvailable || !WaferManager.Instance.CheckHasWafer(aligner.Module, 0) // || !aligner.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade) // || CheckWaferNeedAlign(aligner.Module, 0) // || !CheckWaferNeedAlign(ModuleName.EfemRobot, (int)placeBlade)) // continue; // if (swapAligner == null || (aligner.WaferArriveTicks[0] < swapAligner.WaferArriveTicks[0])) // { // swapAligner = aligner; // } // } // if (swapAligner != null) // { // if (_efemRobot.PickAndPlace(swapAligner.Module, 0, 0, pickBlade, placeBlade)) // { // swapAligner.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); // return; // } // } //} //place to aligner bool blade0HasWaferAndNeedAligner = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedAlign(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedAligner = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedAlign(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedAligner || blade1HasWaferAndNeedAligner) { foreach (var buffer in _lstAligners) { if (!buffer.IsAvailable || !WaferManager.Instance.CheckNoWafer(buffer.Module, 0)) continue; List orderedBlade = new List(); if (blade0HasWaferAndNeedAligner && blade1HasWaferAndNeedAligner) { int result = CompareWaferPriority(ModuleName.EfemRobot, 0, ModuleName.EfemRobot, 1); if (result < 0 || (result == 0 && _efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0])) { orderedBlade.AddRange(new List() { Hand.Blade2, Hand.Blade1 }); } else { orderedBlade.AddRange(new List() { Hand.Blade1, Hand.Blade2 }); } } else { orderedBlade.Add(blade0HasWaferAndNeedAligner ? Hand.Blade1 : Hand.Blade2); } foreach (Hand placeBlade in orderedBlade) { if (_isFixAlignerAndCooling && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1) { int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).OriginStation; if (origin == (int)ModuleName.LP1 && _mapLpAligner[ModuleName.LP1] != buffer.Module) continue; if (origin == (int)ModuleName.LP2 && _mapLpAligner[ModuleName.LP2] != buffer.Module) continue; } if (!buffer.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade) || !buffer.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(buffer.Module, 0, placeBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } } } } if (!_efemRobot.IsAvailable) return; //pick from aligner bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickAligner = ModuleName.System; int preOriginSlot = int.MaxValue; string prePj = string.Empty; int preWaferCountInCooling = 0; foreach (var schedulerAligner in _lstAligners) { if (!schedulerAligner.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerAligner.Module, 0) || CheckWaferNeedAlign(schedulerAligner.Module, 0)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerAligner.Module, 0); bool pickAllowed = CheckBufferWaferHasAvailableTarget(schedulerAligner.Module, 0) || (blade1Empty && blade2Empty); if (!pickAllowed) { continue; } if ((pickAligner == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && prePj == wafer.ProcessJob.Name) || (GetCoolingWaferCount(wafer.ProcessJob.Name) < preWaferCountInCooling)) { preOriginSlot = wafer.OriginSlot; pickAligner = schedulerAligner.Module; prePj = wafer.ProcessJob.Name; preWaferCountInCooling = GetCoolingWaferCount(prePj); continue; } } if (pickAligner != ModuleName.System) { SchedulerModule buffer = GetModule(pickAligner.ToString()); if (!buffer.CheckWaferNextStepModuleNoWafer(0)) { return; } Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 0)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 1)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 0)) { pickBlade = Hand.Blade2; } else { return; } //if (!CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && // !CheckWaferNeedProcess(ModuleName.EfemRobot, 1)) if (!CheckWaferNeedProcess(ModuleName.EfemRobot, (int)pickBlade)) { if (buffer.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(buffer.Module, 0, pickBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } } private void MonitorEfemRobotAlignerPlaceTask() { if (!_efemRobot.IsAvailable) return; //place to aligner bool blade0HasWaferAndNeedAligner = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedAlign(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedAligner = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedAlign(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedAligner || blade1HasWaferAndNeedAligner) { foreach (var buffer in _lstAligners) { if (!buffer.IsAvailable || !WaferManager.Instance.CheckNoWafer(buffer.Module, 0)) continue; Hand placeBlade = blade0HasWaferAndNeedAligner ? Hand.Blade1 : Hand.Blade2; //List orderedBlade = new List(); //if (blade0HasWaferAndNeedAligner && blade1HasWaferAndNeedAligner) //{ // int result = CompareWaferPriority(ModuleName.EfemRobot, 0, ModuleName.EfemRobot, 1); // if (result < 0 || (result == 0 && _efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0])) // { // orderedBlade.AddRange(new List() { Hand.Blade2, Hand.Blade1 }); // } // else // { // orderedBlade.AddRange(new List() { Hand.Blade1, Hand.Blade2 }); // } //} //else //{ // orderedBlade.Add(blade0HasWaferAndNeedAligner ? Hand.Blade1 : Hand.Blade2); //} //foreach (Hand placeBlade in orderedBlade) //{ // if (_isFixAlignerAndCooling && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1) // { // int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).OriginStation; // if (origin == (int)ModuleName.LP1 && _mapLpAligner[ModuleName.LP1] != buffer.Module) // continue; // if (origin == (int)ModuleName.LP2 && _mapLpAligner[ModuleName.LP2] != buffer.Module) // continue; // } if (!buffer.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade) || !buffer.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(buffer.Module, 0, placeBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } //} } } } private void MonitorEfemRobotAlignerPickTask() { if (!_efemRobot.IsAvailable) return; //pick from aligner bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickAligner = ModuleName.System; int preOriginSlot = int.MaxValue; string prePj = string.Empty; int preWaferCountInCooling = 0; foreach (var schedulerAligner in _lstAligners) { if (!schedulerAligner.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerAligner.Module, 0) || CheckWaferNeedAlign(schedulerAligner.Module, 0)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerAligner.Module, 0); bool pickAllowed = CheckBufferWaferHasAvailableTarget(schedulerAligner.Module, 0) || (blade1Empty && blade2Empty); if (!pickAllowed) { continue; } if ((pickAligner == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && prePj == wafer.ProcessJob.Name) || (GetCoolingWaferCount(wafer.ProcessJob.Name) < preWaferCountInCooling)) { preOriginSlot = wafer.OriginSlot; pickAligner = schedulerAligner.Module; prePj = wafer.ProcessJob.Name; preWaferCountInCooling = GetCoolingWaferCount(prePj); continue; } } if (pickAligner != ModuleName.System) { SchedulerModule buffer = GetModule(pickAligner.ToString()); if ((_pma.HasWafer(0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(_pma.Module, 0, 0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(buffer.Module, 0, 0)) || (_pma.HasWafer(0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(_pma.Module, 0, 1) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(buffer.Module, 0, 1)) || (_pmb.HasWafer(0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(_pmb.Module, 0, 0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(buffer.Module, 0, 0)) || (_pmb.HasWafer(0) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(_pmb.Module, 0, 1) && _efemRobot.CheckWaferNextStepIsThisModuleSlot(buffer.Module, 0, 1))) { if (!buffer.CheckWaferNextStepModuleNoWafer(0)) { return; } } Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 0)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 1)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickAligner, 0, 0)) { pickBlade = Hand.Blade2; } else { return; } if (!CheckWaferNeedProcess(ModuleName.EfemRobot, (int)pickBlade)) { if (buffer.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(buffer.Module, 0, pickBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } } private void MonitorEfemRobotCoolingTask() { if (!_efemRobot.IsAvailable || !_efemRobot.LiftDone) return; //swap Cooling if (_efemRobot.Blade1Enable && _efemRobot.Blade2Enable && (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ^ WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1))) { Hand pickBlade = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) ? Hand.Blade1 : Hand.Blade2; Hand placeBlade = pickBlade == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1; SchedulerAligner swapCooling = null; foreach (var cooling in _lstCoolings) { if (!cooling.IsAvailable || !WaferManager.Instance.CheckHasWafer(cooling.Module, 0) || !cooling.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade) || !CheckWaferHasAvailableTarget(cooling.Module, 0) || !CheckWaferNeedCooling(ModuleName.EfemRobot, (int)placeBlade)) continue; if (swapCooling == null || (cooling.WaferArriveTicks[0] < swapCooling.WaferArriveTicks[0])) { swapCooling = cooling; } } if (swapCooling != null && _efemRobot.CheckWaferNextStepIsThisModuleSlotInSwap(swapCooling.Module, 0, (int)pickBlade) && CheckWaferCanPick(swapCooling.Module, 0, pickBlade)) { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)pickBlade) && _efemRobot.PickAndPlace(swapCooling.Module, 0, 0, pickBlade, placeBlade)) { swapCooling.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } if (!_efemRobot.IsAvailable) return; //place to cooling bool blade0HasWaferAndNeedCooling = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedCooling(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedCooling = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedCooling(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedCooling || blade1HasWaferAndNeedCooling) { foreach (var buffer in _lstCoolings) { if (!buffer.IsAvailable || !WaferManager.Instance.CheckNoWafer(buffer.Module, 0)) continue; Hand placeBlade = blade0HasWaferAndNeedCooling ? Hand.Blade1 : Hand.Blade2; if (!buffer.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade) || !buffer.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(buffer.Module, 0, placeBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } } } if (!_efemRobot.IsAvailable) return; int waferCount = 0; //if (_cooling1.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0) && !_efemRobot.CheckWaferNextStepModule(0, _cooling1.Module)) waferCount++; if (_efemRobot.HasWafer(1) && !_efemRobot.CheckWaferNextStepModule(1, _cooling1.Module)) waferCount++; if (_pma.HasWafer(0)) { waferCount++; if(!_efemRobot.Blade1Enable || !_efemRobot.Blade2Enable) return; } //pick from cooling bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickBuffer = ModuleName.System; int preOriginSlot = int.MaxValue; string prePj = string.Empty; int preWaferCountInPm = 0; foreach (var schedulerBuffer in _lstCoolings) { if (!schedulerBuffer.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0) || CheckWaferNeedCooling(schedulerBuffer.Module, 0)) continue; if (waferCount >= 2 && !CheckWaferSequenceDone(schedulerBuffer.Module, 0)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerBuffer.Module, 0); bool pickAllowed = CheckWaferHasAvailableTarget(schedulerBuffer.Module, 0); if (!pickAllowed) continue; if ((pickBuffer == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && prePj == wafer.ProcessJob.Name) || (GetProcessingWaferCount(wafer.ProcessJob.Name) < preWaferCountInPm)) { preOriginSlot = wafer.OriginSlot; pickBuffer = schedulerBuffer.Module; prePj = wafer.ProcessJob.Name; preWaferCountInPm = GetProcessingWaferCount(prePj); continue; } } if (pickBuffer != ModuleName.System) { SchedulerModule buffer = GetModule(pickBuffer.ToString()); Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 0) && CheckWaferCanPick(pickBuffer, 0, Hand.Blade1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 1) && CheckWaferCanPick(pickBuffer, 0, Hand.Blade2)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 1) && CheckWaferCanPick(pickBuffer, 0, Hand.Blade1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 0) && CheckWaferCanPick(pickBuffer, 0, Hand.Blade2)) { pickBlade = Hand.Blade2; } else { return; } if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, (int)pickBlade) && buffer.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(buffer.Module, 0, pickBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } private void MonitorEfemRobotCoolingPlaceTask() { if (!_efemRobot.IsAvailable) return; //place to cooling bool blade0HasWaferAndNeedCooling = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedCooling(ModuleName.EfemRobot, 0); bool blade1HasWaferAndNeedCooling = WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedCooling(ModuleName.EfemRobot, 1); if (blade0HasWaferAndNeedCooling || blade1HasWaferAndNeedCooling) { foreach (var buffer in _lstCoolings) { if (!buffer.IsAvailable || !WaferManager.Instance.CheckNoWafer(buffer.Module, 0)) continue; Hand placeBlade = blade0HasWaferAndNeedCooling ? Hand.Blade1 : Hand.Blade2; //List orderedBlade = new List(); //if (blade0HasWaferAndNeedCooling && blade1HasWaferAndNeedCooling) //{ // int result = CompareWaferPriority(ModuleName.EfemRobot, 0, ModuleName.EfemRobot, 1); // if (result < 0 || (result == 0 && _efemRobot.WaferArriveTicks[1] < _efemRobot.WaferArriveTicks[0])) // { // orderedBlade.AddRange(new List() { Hand.Blade2, Hand.Blade1 }); // } // else // { // orderedBlade.AddRange(new List() { Hand.Blade1, Hand.Blade2 }); // } //} //else //{ // orderedBlade.Add(blade0HasWaferAndNeedCooling ? Hand.Blade1 : Hand.Blade2); //} //foreach (Hand placeBlade in orderedBlade) //{ // if (_isFixAlignerAndCooling && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1) // { // int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).OriginStation; // if (origin == (int)ModuleName.LP1 && _mapLpCooling[ModuleName.LP1] != buffer.Module) // continue; // if (origin == (int)ModuleName.LP2 && _mapLpCooling[ModuleName.LP2] != buffer.Module) // continue; // } if (!buffer.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade) || !buffer.IsReadyForPlace(ModuleName.EfemRobot, 0, placeBlade)) continue; if (_efemRobot.Place(buffer.Module, 0, placeBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0); return; } //} } } } private void MonitorEfemRobotCoolingPickTask() { if (!_efemRobot.IsAvailable) return; int waferCount = 0; //if (_cooling1.HasWafer(0)) waferCount++; if (_efemRobot.HasWafer(0) && !_efemRobot.CheckWaferNextStepModule(0, _cooling1.Module)) waferCount++; if (_efemRobot.HasWafer(1) && !_efemRobot.CheckWaferNextStepModule(1, _cooling1.Module)) waferCount++; if (_pma.HasWafer(0)) waferCount++; if (waferCount >= 2) return; //pick from cooling bool blade1Empty = _efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0); bool blade2Empty = _efemRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1); if (blade1Empty || blade2Empty) { ModuleName pickBuffer = ModuleName.System; int preOriginSlot = int.MaxValue; string prePj = string.Empty; int preWaferCountInPm = 0; foreach (var schedulerBuffer in _lstCoolings) { if (!schedulerBuffer.IsAvailable || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0) || CheckWaferNeedCooling(schedulerBuffer.Module, 0)) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerBuffer.Module, 0); bool pickAllowed = false; if (!pickAllowed) continue; if ((pickBuffer == ModuleName.System) || (wafer.OriginSlot < preOriginSlot && prePj == wafer.ProcessJob.Name) || (GetProcessingWaferCount(wafer.ProcessJob.Name) < preWaferCountInPm)) { preOriginSlot = wafer.OriginSlot; pickBuffer = schedulerBuffer.Module; prePj = wafer.ProcessJob.Name; preWaferCountInPm = GetProcessingWaferCount(prePj); continue; } } if (pickBuffer != ModuleName.System) { SchedulerModule buffer = GetModule(pickBuffer.ToString()); Hand pickBlade; if (blade1Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 0)) { pickBlade = Hand.Blade1; } else if (blade2Empty && _efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 1)) { pickBlade = Hand.Blade2; } else if (blade1Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 1)) { pickBlade = Hand.Blade1; } else if (blade2Empty && !_efemRobot.CheckWaferNextStepIsThisModuleSlot(pickBuffer, 0, 0)) { pickBlade = Hand.Blade2; } else { return; } if (buffer.IsReadyForPick(ModuleName.EfemRobot, 0, pickBlade)) { if (_efemRobot.Pick(buffer.Module, 0, pickBlade)) { buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); return; } } } } } private void MonitorEfemRobotGotoTask() { if (!_efemRobot.IsAvailable) return; SchedulerPM gotoPm = null; int gotoSlot = Int32.MaxValue; int gotoModule = -1; foreach (var pm in _lstPms) { WaferInfo wafer = WaferManager.Instance.GetWafer(pm.Module, 0); if (wafer.IsEmpty) continue; if (gotoPm == null) { gotoPm = pm; gotoModule = wafer.OriginStation; gotoSlot = wafer.OriginSlot; continue; } if (wafer.OriginSlot < gotoSlot && gotoModule == wafer.OriginStation) { gotoSlot = wafer.OriginSlot; gotoPm = pm; } } if (gotoPm != null) { if (_efemRobot.PreviousTarget == gotoPm.Module) return; if (_efemRobot.Goto(gotoPm.Module, 0)) { return; } } } private void MonitorPMTask() { bool robotWaferAssigned = false; bool aligner1WaferAssigned = false; bool aligner2WaferAssigned = false; foreach (var pm in _lstPms) { if (!pm.IsAvailable) continue; if (WaferManager.Instance.CheckHasWafer(pm.Module, 0)) { if (CheckWaferNeedProcess(pm.Module, 0, pm.Module)) { WaferInfo wafer = WaferManager.Instance.GetWafer(pm.Module, 0); var recipeName = pm.Module == ModuleName.PMA ? wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PMARecipe"] : wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PMBRecipe"]; if (pm.CheckSlitDoorDown() && pm.Process((string)recipeName, false, true, wafer)) { WaferManager.Instance.GetWafer(pm.Module, 0).NextSequenceStep++; continue; } } else { if (!pm.IsReadyForPick(ModuleName.EfemRobot, 0, Hand.Blade1)) { pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0); } } } else //no wafer { if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1) && WaferManager.Instance.CheckNoWafer(ModuleName.Aligner1, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.Aligner2, 0)) { ModuleName source = ModuleName.System; if (_isFixAlignerAndCooling) { foreach (var moduleName in _mapLpPm) { if (moduleName.Value == pm.Module) source = moduleName.Key; } } SlotItem item = GetNextWaferInJobQueue(source); if (item != null && CheckWaferNeedProcess(item.Module, item.Slot, pm.Module)) { if (GetWaferTemperatureSetInRecipe(item.Module, item.Slot, pm.Module, out float temp) && !pm.IsTemperatureReady(temp) && !SC.GetValue("System.IsATMMode")) { pm.Preheating(temp); continue; } } } if (!pm.IsAvailable) continue; if (!robotWaferAssigned && CheckWaferNeedProcess(ModuleName.EfemRobot, 0, pm.Module) && CheckWaferNextProcessIn(ModuleName.EfemRobot, 0, pm.Module)) { robotWaferAssigned = true; GetWaferTemperatureSetInRecipe(ModuleName.EfemRobot, 0, pm.Module, out float temp); bool alreadyPrepare = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsPrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0) || (!_efemRobot.IsAvailable) || (schedulerPm.IsAvailable && WaferManager.Instance.CheckNoWafer(pm.Module, 0) && pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1))) alreadyPrepare = true; } if (!alreadyPrepare) { if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1) || !pm.IsTemperatureReady(temp)) { pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp, Hand.Blade1, WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).Size); } } } if (!pm.IsAvailable) continue; if (!robotWaferAssigned && CheckWaferNeedProcess(ModuleName.EfemRobot, 1, pm.Module) && CheckWaferNextProcessIn(ModuleName.EfemRobot, 1, pm.Module)) { robotWaferAssigned = true; GetWaferTemperatureSetInRecipe(ModuleName.EfemRobot, 1, pm.Module, out float temp); bool alreadyPrepare = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsPrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0) || (!_efemRobot.IsAvailable) || (schedulerPm.IsAvailable && WaferManager.Instance.CheckNoWafer(pm.Module, 0) && pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade2))) alreadyPrepare = true; } if (!alreadyPrepare) { if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade2) || !pm.IsTemperatureReady(temp)) { pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp, Hand.Blade2, WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).Size); } } } if (!pm.IsAvailable) continue; //并行模式下,避免提前预判aligner的wafer位置 if (_isRunningInParallelMode) continue; if (!aligner1WaferAssigned && CheckWaferNeedProcess(ModuleName.Aligner1, 0, pm.Module)) { aligner1WaferAssigned = true; GetWaferTemperatureSetInRecipe(ModuleName.Aligner1, 0, pm.Module, out float temp); bool alreadyPrepare = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsPrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0) || (!_efemRobot.IsAvailable) || (schedulerPm.IsAvailable && WaferManager.Instance.CheckNoWafer(pm.Module, 0) && pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1))) alreadyPrepare = true; } if (!alreadyPrepare) { if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1) || !pm.IsTemperatureReady(temp)) { pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp, Hand.Blade1, WaferManager.Instance.GetWafer(ModuleName.Aligner1, 0).Size); } } } if (!pm.IsAvailable) continue; if (!aligner2WaferAssigned && CheckWaferNeedProcess(ModuleName.Aligner2, 0, pm.Module)) { aligner2WaferAssigned = true; GetWaferTemperatureSetInRecipe(ModuleName.Aligner2, 0, pm.Module, out float temp); bool alreadyPrepare = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsPrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0) || (!_efemRobot.IsAvailable) || (schedulerPm.IsAvailable && WaferManager.Instance.CheckNoWafer(pm.Module, 0) && pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1))) alreadyPrepare = true; } if (!alreadyPrepare) { if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0, Hand.Blade1) || !pm.IsTemperatureReady(temp)) { pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp, Hand.Blade1, WaferManager.Instance.GetWafer(ModuleName.Aligner2, 0).Size); } } } if (!pm.IsAvailable) continue; } } } #endregion Module task #region Logic Check private bool CheckSequencePmReady(SequenceInfo seq, List pmOccupied, out List pmUsed, out string reason) { pmUsed = new List(); reason = ""; bool pmIsReady = true; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; bool hasPm = false; foreach (var module in stepInfo.StepModules) { if (!ModuleHelper.IsPm(module)) { hasPm = true; break; } PM pm = DEVICE.GetDevice(module.ToString()); if (pm.IsInstalled && (pmOccupied == null || !pmOccupied.Contains(module))) { hasPm = true; } if (!pmUsed.Contains(module)) pmUsed.Add(module); } if (pmIsReady && !hasPm) { reason = $"Step {i + 1} no valid PM, " + string.Join("|", stepInfo.StepModules); pmIsReady = false; } } return pmIsReady; } private bool CheckSequenceOrderOk(SequenceInfo seq, out string reason) { reason = ""; bool foundPm = false; bool isAlignerAfterPm = false; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { foundPm = true; } if (ModuleHelper.IsAligner(module) && foundPm) { isAlignerAfterPm = true; } } } if (!foundPm) { reason = $"not found PM in the sequence file;"; } if (isAlignerAfterPm) { reason += "Aligner after PM not support"; } return true; } public bool CheckPMWaferSizeSupported(ProcessJobInfo pj, out string reason) { reason = ""; foreach (var pos in pj.SlotWafers) { WaferInfo wafer = WaferManager.Instance.GetWafer(pos.Item1, pos.Item2); if (wafer.IsEmpty) return false; for (int i = 0; i < pj.Sequence.Steps.Count; i++) { foreach (var stepModule in pj.Sequence.Steps[i].StepModules) { if (ModuleHelper.IsPm(stepModule)) { string SupportedWaferSize = SC.GetStringValue($"{stepModule}.SupportedWaferSize"); if (!SupportedWaferSize.Split(',').Contains(wafer.Size.ToString().Replace("WS", ""))) { reason = $"sequence step {i + 1} , {stepModule} not support WaferSize : {wafer.Size}"; return false; } } } } } return true; } protected int GetUnprocessedWaferCount() { int count = 0; foreach (ProcessJobInfo pj in _lstProcessJobs) { if (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused) count += GetUnprocessedWaferCount(pj); } return count; } protected int GetUnprocessedWaferCount(ProcessJobInfo pj) { int count = 0; 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) continue; if (CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2)) count++; } return count; } 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; } return true; } private bool CheckWaferNextStepIsAlign(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.Aligner1) || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner2)) return true; return false; } private bool CheckWaferNextStepIsCooling(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.Cooling1) || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling2)) return true; return false; } private bool GetWaferTemperatureSetInRecipe(ModuleName waferModule, int waferSlot, ModuleName pmModule, out float temp) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); var seq = wafer.ProcessJob.Sequence; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (module == pmModule) { temp = (float)seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"]; return true; } } } temp = 0; LOG.Error($"Can not find wafer {waferModule} {waferSlot + 1} temperature set in recipe"); return false; } private bool CheckWaferPmTemperatureIsOk(ModuleName waferModule, int waferSlot) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null) return false; if (SC.GetValue("System.IsATMMode")) { return true; } var seq = wafer.ProcessJob.Sequence; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; bool stepOk = false; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { float tempNeeded = (float)seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"]; if ((GetModule(module.ToString()) as SchedulerPM).IsTemperatureReady(tempNeeded)) { stepOk = true; break; } } else { stepOk = true; } } if (!stepOk) return false; } return true; } private bool CheckWaferNeedAlign(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; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules .Contains(ModuleName.Aligner1) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules .Contains(ModuleName.Aligner2)) return false; return true; } private bool CheckWaferNeedCooling(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; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules .Contains(ModuleName.Cooling1) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules .Contains(ModuleName.Cooling2)) return false; return true; } private bool CheckWaferNextProcessIn(ModuleName waferModule, int waferSlot, ModuleName chamber) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); if (wafer.IsEmpty || 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; } if (_isFixAlignerAndCooling && _mapLpPm[(ModuleName)wafer.OriginStation] != chamber) return false; return wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(chamber); } public bool CheckWaferNeedProcessAndPMAvailable(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System) { 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; for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++) { if (wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(ModuleName.PMA) || wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(ModuleName.PMB)) { var hasPmAvailable = false; foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules) { var pm = GetModule(stepModule.ToString()) as SchedulerPM; if (pm != null) { if (pm.IsAvailable || (pm.IsOnline && pm.Task != SchedulerModule.TaskType.PreJobProcess)) { hasPmAvailable = true; break; } } } if (!hasPmAvailable) return false; if (processIn == ModuleName.System) return true; if (_isFixAlignerAndCooling && _mapLpPm[(ModuleName)wafer.OriginStation] != processIn) return false; if (wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(processIn)) return true; } } return false; } 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.ProcessJob == null || wafer.ProcessJob.Sequence == null) return false; if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return false; for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++) { if (wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(ModuleName.PMA) || wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(ModuleName.PMB)) { if (processIn == ModuleName.System) return true; if (_isFixAlignerAndCooling && _mapLpPm[(ModuleName)wafer.OriginStation] != processIn) return false; if (wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(processIn)) return true; } } return false; } private bool CheckVacuumWaferHasAvailableTarget(ModuleName waferModule, int waferSlot) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); foreach (var buffer in _lstCoolings) { if (!buffer.IsAvailable) continue; if (WaferManager.Instance.CheckNoWafer(buffer.Module, 0)) { return true; } } if (_efemRobot.Blade1Enable && _efemRobot.NoWafer(0)) return true; if (_efemRobot.Blade2Enable && _efemRobot.NoWafer(1)) return true; return false; } private bool CheckWaferHasAvailableTarget(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; //sequence done, return LP if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return true; foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules) { if (WaferManager.Instance.CheckNoWafer(stepModule, 0)) return true; } if ((_efemRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.Robot, 0)) || (_efemRobot.Blade2Enable || WaferManager.Instance.CheckNoWafer(ModuleName.Robot, 1))) return true; return false; } public bool CheckWaferCanPick(ModuleName module, int slot, Hand hand) { bool canPick = true; foreach(var cool in _lstCoolings) { if (!WaferManager.Instance.CheckHasWafer(cool.Module, 0) || cool.Module == module) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(cool.Module, 0); if (!wafer.IsEmpty && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.NextSequenceStep < wafer.ProcessJob.Sequence.Steps.Count) { for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++) { if (!wafer.ProcessJob.Sequence.Steps[i].StepParameter.ContainsKey("SlotSelection")) continue; if (wafer.ProcessJob.Sequence.Steps[i].StepParameter["SlotSelection"].ToString().Contains("0,1")) continue; //if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["SlotSelection"].ToString().Contains(((int)hand).ToString())) canPick = false; } } } foreach (var pm in _lstPms) { if (!WaferManager.Instance.CheckHasWafer(pm.Module, 0) || pm.Module == module) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(pm.Module, 0); if (!wafer.IsEmpty && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.NextSequenceStep < wafer.ProcessJob.Sequence.Steps.Count) { for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++) { if (!wafer.ProcessJob.Sequence.Steps[i].StepParameter.ContainsKey("SlotSelection")) continue; if (wafer.ProcessJob.Sequence.Steps[i].StepParameter["SlotSelection"].ToString().Contains("0,1")) continue; //if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["SlotSelection"].ToString().Contains(((int)hand).ToString())) canPick = false; } } } { var anotherBlade = hand == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1; WaferInfo wafer = WaferManager.Instance.GetWafer(_efemRobot.Module, (int)anotherBlade); if (!wafer.IsEmpty && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.NextSequenceStep < wafer.ProcessJob.Sequence.Steps.Count) { for(int i = wafer.NextSequenceStep; i< wafer.ProcessJob.Sequence.Steps.Count;i++) { if (!wafer.ProcessJob.Sequence.Steps[i].StepParameter.ContainsKey("SlotSelection")) continue; if (wafer.ProcessJob.Sequence.Steps[i].StepParameter["SlotSelection"].ToString().Contains("0,1")) continue; canPick = false; } } } return canPick; } private bool CheckWaferSequenceDone(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; //sequence done, return LP if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count) return true; return false; } private bool CheckBufferWaferHasAvailableTarget(ModuleName waferModule, int waferSlot) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); //System.Diagnostics.Trace.Assert(!wafer.IsEmpty); if (!CheckWaferNeedProcess(waferModule, waferSlot)) return true; // Check for an empty PM foreach (var pm in _lstPms) { if (WaferManager.Instance.CheckNoWafer(pm.Module, 0)) { if (pm.IsAvailable == false) continue; if (!CheckWaferNextProcessIn(waferModule, waferSlot, pm.Module)) continue; return true; } } return false; } private bool SetSequenceTemperatureInfo(SequenceInfo seq, out string reason) { for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { string attr = module == ModuleName.PMA ? "PMARecipe" : "PMBRecipe"; if (stepInfo.StepParameter.ContainsKey(attr) && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr])) { var recipeName = (string)stepInfo.StepParameter[attr]; if (!string.IsNullOrEmpty(recipeName)) { var recipeContent = RecipeFileManager.Instance.LoadRecipe($"", recipeName, false); if (string.IsNullOrEmpty(recipeContent)) { reason = $"Can not find recipe file{recipeName}"; return false; } try { XmlDocument xml = new XmlDocument(); xml.LoadXml(recipeContent); var substrateTemp = xml.DocumentElement.HasAttribute("SubstrateTemp") ? xml.DocumentElement.Attributes["SubstrateTemp"].Value : ""; if (!float.TryParse(substrateTemp, out float temp)) { reason = $"Invalid substrate temperature in recipe head {recipeName}"; return false; } seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"] = temp; } catch (Exception ex) { LOG.Write(ex); reason = $"recipe not valid, {recipeName}"; return false; } } } } } } reason = ""; return true; } private bool CheckSequenceRecipeFileValid(SequenceInfo seq, out string reason) { for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { string attr = module == ModuleName.PMA ? "PMARecipe" : "PMBRecipe"; if (stepInfo.StepParameter.ContainsKey(attr) && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr])) { var recipeName = (string)stepInfo.StepParameter[attr]; if (!string.IsNullOrEmpty(recipeName)) { var recipeContent = RecipeFileManager.Instance.LoadRecipe($"", recipeName, false); if (string.IsNullOrEmpty(recipeContent)) { reason = $"Can not find recipe file{recipeName}"; return false; } } } } } } reason = ""; return true; } private bool GetWaferSequenceAlignTime(ModuleName module, int slot, out float time) { time = 0; 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.Aligner1) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner2) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling1) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling2)) return false; if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("CoolingTime")) return false; if (!float.TryParse((string)wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"], out time)) return false; return true; } private int GetWaferCountOutofLP(ModuleName lp) { int count = 0; var lstPosition = new List() { ModuleName.EfemRobot, ModuleName.Aligner1, ModuleName.Aligner2, ModuleName.Cooling1, ModuleName.Cooling2, ModuleName.PMA, ModuleName.PMB, }; foreach (var moduleName in lstPosition) { if (ModuleHelper.IsPm(moduleName) && !GetModule(moduleName.ToString()).IsOnline) continue; if (WaferManager.Instance.CheckHasWafer(moduleName, 0)) { if (lp == ModuleName.System || WaferManager.Instance.GetWafer(moduleName, 0).OriginStation == (int)lp) count++; } } if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1)) { if (lp == ModuleName.System || WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginStation == (int)lp) count++; } return count; } private SlotItem GetWaferReturnLoadPort(ModuleName module, int slot) { WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot); if (!wafer.IsEmpty) { return new SlotItem((ModuleName)wafer.OriginStation, wafer.OriginSlot); } return null; } private int GetWaferCountInJobQueue(ModuleName sourceLp) { int count = 0; foreach (var lp in _lstLps) { for (int i = 0; i < 25; i++) { if (CheckWaferNeedProcess(lp.Module, i) && (sourceLp == ModuleName.System || sourceLp == lp.Module)) count++; } } return count; } /// /// 获取下一个Wafer。根据某个LP,或者任意LP /// /// 如果是System,表示查询的时候根据任意LoadPort /// private SlotItem GetNextWaferInJobQueue(ModuleName lpModule) { if (!_isRunningInParallelMode) { foreach (var cj in _lstControlJobs) { if (lpModule != ModuleName.System && (cj.Module != lpModule.ToString())) continue; if (cj.State == EnumControlJobState.Executing) { foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing) { foreach (var pjSlotWafer in pj.SlotWafers) { if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2)) return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2); } } } } } return null; } //parallel mode Dictionary pjWafer = new Dictionary(); Dictionary> pmUsed = new Dictionary>(); foreach (var cj in _lstControlJobs) { if (cj.State != EnumControlJobState.Executing) continue; foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing) { foreach (var pjSlotWafer in pj.SlotWafers) { if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2)) { pjWafer[pj.Name] = new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2); break; } } } } } if (pjWafer.Count == 0) return null; if (pjWafer.Count == 1) return pjWafer.Values.First(); string preferPj = pjWafer.Keys.First(); int runningWaferCount = GetWaitingProcessWaferCount(preferPj); foreach (var slotItem in pjWafer) { if (slotItem.Key == preferPj) continue; int count = GetWaitingProcessWaferCount(slotItem.Key); if (count < runningWaferCount) { preferPj = slotItem.Key; runningWaferCount = count; } } return pjWafer[preferPj]; } private SlotItem GetNextNextWaferInJobQueue(ModuleName lpModule, int nextSlot) { foreach (var cj in _lstControlJobs) { if (lpModule != ModuleName.System && (cj.Module != lpModule.ToString())) continue; if (cj.State == EnumControlJobState.Executing) { foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing) { foreach (var pjSlotWafer in pj.SlotWafers) { if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2) && pjSlotWafer.Item2 != nextSlot) return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2); } } } } } return null; } private int GetWaitingProcessWaferCount(string pjName) { List> location = new List>() { Tuple.Create(ModuleName.EfemRobot, 0), Tuple.Create(ModuleName.EfemRobot, 1), Tuple.Create(ModuleName.Aligner1, 0), Tuple.Create(ModuleName.Aligner2, 0), Tuple.Create(ModuleName.PMA, 0), Tuple.Create(ModuleName.PMB, 0), }; int count = 0; foreach (var tuple in location) { if (ModuleHelper.IsPm(tuple.Item1) && !GetModule(tuple.Item1.ToString()).IsOnline) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(tuple.Item1, tuple.Item2); if (wafer.IsEmpty) continue; if (wafer.ProcessJob != null && wafer.ProcessJob.Name == pjName) count++; } return count; } private int GetCoolingWaferCount(string pjName) { List> location = new List>() { Tuple.Create(ModuleName.Cooling1, 0), Tuple.Create(ModuleName.Cooling2, 0), }; int count = 0; foreach (var tuple in location) { WaferInfo wafer = WaferManager.Instance.GetWafer(tuple.Item1, tuple.Item2); if (wafer.IsEmpty) continue; if (wafer.ProcessJob != null && wafer.ProcessJob.Name == pjName) count++; } return count; } private int GetProcessingWaferCount(string pjName) { List> location = new List>() { Tuple.Create(ModuleName.PMA, 0), Tuple.Create(ModuleName.PMB, 0), }; int count = 0; foreach (var tuple in location) { if (ModuleHelper.IsPm(tuple.Item1) && !GetModule(tuple.Item1.ToString()).IsOnline) continue; WaferInfo wafer = WaferManager.Instance.GetWafer(tuple.Item1, tuple.Item2); if (wafer.IsEmpty) continue; if (wafer.ProcessJob != null && wafer.ProcessJob.Name == pjName) count++; } return count; } private List GetPmUsedInRunningPj() { var pmUsed = new List(); foreach (var cj in _lstControlJobs) { if (cj.State != EnumControlJobState.Executing && cj.State != EnumControlJobState.Paused) continue; foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name && (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused)) { for (int i = 0; i < pj.Sequence.Steps.Count; i++) { SequenceStepInfo stepInfo = pj.Sequence.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module) && !pmUsed.Contains(module)) pmUsed.Add(module); } } } } } return pmUsed; } private int CompareWaferPriority(ModuleName module1, int slot1, ModuleName module2, int slot2) { if (module1 == ModuleName.System || module2 == ModuleName.System) return 0; WaferInfo wafer1 = WaferManager.Instance.GetWafer(module1, slot1); WaferInfo wafer2 = WaferManager.Instance.GetWafer(module2, slot2); if (wafer1.IsEmpty || wafer2.IsEmpty) return 0; if (wafer1.Size != wafer2.Size) return 0; //same process job && same load port if (_lstProcessJobs.Exists(x => x.SlotWafers.Exists(y => y.Item1 == (ModuleName)wafer1.OriginStation && y.Item2 == wafer1.OriginSlot) && x.SlotWafers.Exists((y => y.Item1 == (ModuleName)wafer2.OriginStation && y.Item2 == wafer2.OriginSlot))) && (wafer1.OriginStation == wafer2.OriginStation)) { //lower number slot has high priority return wafer2.OriginSlot - wafer1.OriginSlot; } return 0; } private List GetPmNeeded(ControlJobInfo cj) { List result = new List(); foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName != cj.Name) continue; var seq = pj.Sequence; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { var pm = _lstPms.Find(x => x.Module == module); if (pm != null && !result.Contains(pm)) { result.Add(pm); } } } } } return result; } public bool CheckRecipeUsedInJob(string pathName) { foreach (var pj in _lstProcessJobs) { var seq = pj.Sequence; for (int i = 0; i < seq.Steps.Count; i++) { SequenceStepInfo stepInfo = seq.Steps[i]; foreach (var module in stepInfo.StepModules) { if (ModuleHelper.IsPm(module)) { string attr = module == ModuleName.PMA ? "PMARecipe" : "PMBRecipe"; if (stepInfo.StepParameter.ContainsKey(attr) && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr])) { var recipeName = (string)stepInfo.StepParameter[attr]; if (!string.IsNullOrEmpty(recipeName)) { if (pathName.EndsWith("\\" + recipeName + ".rcp")) return true; } } } } } } return false; } public bool CheckSequenceUsedInJob(string pathName) { foreach (var pj in _lstProcessJobs) { if (pathName.EndsWith("\\" + pj.Sequence.Name + ".seq")) return true; } return false; } #endregion Logic Check } }