using Aitex.Common.Util; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using FurnaceRT.Equipments.CarrierRobots; using FurnaceRT.Equipments.PMs.RecipeExecutions; using FurnaceRT.Equipments.Schedulers; using FurnaceRT.Equipments.Systems; using FurnaceRT.Equipments.WaferRobots; using MECF.Framework.Common.Jobs; using Aitex.Core.RT.Log; using MECF.Framework.Common.DBCore; using Aitex.Core.RT.DataCenter; using System.Diagnostics; using FurnaceRT.Equipments.PMs; using MECF.Framework.Common.Schedulers; using System.Windows.Input; using System.Net.Sockets; using FurnaceRT.Equipments.FIMSs; using FurnaceRT.Devices; using System.Text.RegularExpressions; using MECF.Framework.Common.CommonData; using FurnaceRT.Equipments.Boats; using MECF.Framework.FA.Core.FAControl; using MECF.Framework.UI.Client.CenterViews.Operations.FA; using FurnaceRT.Equipments.LPs; using MECF.Framework.Common.CommonData.EnumData; using MECF.Framework.Common.DataCenter; using DocumentFormat.OpenXml.Drawing.Charts; using MECF.Framework.Common.Utilities; using System.Threading; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs; namespace FurnaceRT.Equipments.Jobs { public class AutoTransfer : SchedulerModuleFactory { private List _lstControlJobs = new List(); private List _lstProcessJobs = new List(); public List LstProcessJobs => _lstProcessJobs; //private Object _locker = new Object(); private const string LogSource = "Scheduler"; System.Timers.Timer timer = null; private bool _isCycleMode; private int _cycleSetPoint = 0; private int _cycledCount = 0; private int _cycledWafer = 0; private int _cycledTotalWafer = 0; private int _cycleTime; private int _cycleTimeSecond = 0; private Stopwatch _coolTimer = new Stopwatch(); private SchedulerFACallback _faCallback; private SchedulerDBCallback _dbCallback; private ProcessJobInfo _secondPj; private Dictionary _sideDummyWafers = new Dictionary(); private Dictionary _extraDummyWafers = new Dictionary(); private List _sideDummySlots = new List(); private List _extraDummySlots = new List(); private List _productSlots = new List(); private List _monitor1Slots = new List(); private List _monitor2Slots = new List(); private List _tSlots = new List();//expert mode private List _xdSlots = new List();//expert mode private List _lstCurrentPjStocker = new List(); private Dictionary _chargeRuleAlarmTrigDic = new Dictionary(); private Dictionary _waferStatusAlarmTrigDic = new Dictionary(); private Dictionary _dummyWaferCheckTrigDic = new Dictionary(); private Dictionary _logTrigDic = new Dictionary(); private bool _isCoolingSkip = false; public bool HasJobRunning { get { return _lstControlJobs.Count > 0; } } public AutoTransfer() { _faCallback = new SchedulerFACallback(); _dbCallback = new SchedulerDBCallback(); InitModule(); _cycledTotalWafer = SC.ContainsItem("System.TotalCycledWafer") ? SC.GetValue("System.TotalCycledWafer") : 0; DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount); DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer); DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint); DATA.Subscribe("Scheduler.CycledTotalWafer", () => _cycledTotalWafer); DATA.Subscribe("Scheduler.SecondPj", () => new List() { _secondPj }); DATA.Subscribe("Scheduler.PjIdList", () => Array.ConvertAll(_lstProcessJobs.ToArray(), x => x.InnerId.ToString()).ToList()); DATA.Subscribe($"LP1.LocalJobName", () => { var cj = _lstControlJobs.FirstOrDefault(x => x.Module == "LP1"); if (cj != null) return cj.Name; return ""; }); DATA.Subscribe($"LP2.LocalJobStatus", () => { var cj = _lstControlJobs.FirstOrDefault(x => x.Module == "LP2"); if (cj != null) return cj.State.ToString(); return ""; }); DATA.Subscribe($"Scheduler.CurrentControlJob", () => { var cj = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing); return cj; }); DATA.Subscribe($"Scheduler.CurrentProcessJob", () => { var pj = _lstProcessJobs.Find(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused); return pj; }); DATA.Subscribe($"Scheduler.ControlJobList", () => { return _lstControlJobs; }); DATA.Subscribe($"Scheduler.ProcessJobList", () => { return _lstProcessJobs; }); DATA.Subscribe($"Scheduler.CoolingTime", () => { var pj = _lstProcessJobs.Find(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused); return pj != null ? pj.CoolTimeSec : 0; }); DATA.Subscribe($"Scheduler.CoolingRemainTime", () => { var pj = _lstProcessJobs.Find(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused); var coolTime = pj != null ? pj.CoolTimeSec : 0; if (_coolTimer.IsRunning) return (coolTime - _coolTimer.ElapsedMilliseconds / 1000) > 0 ? coolTime - _coolTimer.ElapsedMilliseconds / 1000 : 0; return coolTime; }); DATA.Subscribe($"Scheduler.StockerUseSlots", () => { Dictionary stockerUseSlots = new Dictionary(); if (!_lstProcessJobs.Any()) return stockerUseSlots; foreach (var pj in _lstProcessJobs) { if (pj.Stockers != null) { foreach (var stocker in pj.Stockers) { if (!stockerUseSlots.ContainsKey(stocker.Item1)) stockerUseSlots.Add(stocker.Item1, string.Join(",", stocker.Item3)); else { var value = stockerUseSlots[stocker.Item1]; stockerUseSlots[stocker.Item1] = $"{value},{string.Join(",", stocker.Item3)}"; } } } } return stockerUseSlots; }); } public void Clear() { _carrierRobot.ResetTask(); _waferRobot.ResetTask(); foreach (var pm in _lstPms) { pm.ResetTask(); } foreach (var lp in _lstLPs) { lp.ResetTask(); } foreach (var fims in _lstFIMSs) { fims.ResetTask(); } _lstControlJobs.Clear(); _lstProcessJobs.Clear(); _isCoolingSkip = false; } public void ResetTask(ModuleName module) { if (module == _carrierRobot.Module) _carrierRobot.ResetTask(); if (module == _waferRobot.Module) _waferRobot.ResetTask(); foreach (var lp in _lstLPs) { if (module == _carrierRobot.Module) lp.ResetTask(); } foreach (var fims in _lstFIMSs) { if (module == _carrierRobot.Module) fims.ResetTask(); } } #region Job Management public Result CreateJob(params object[] objs) { _isCycleMode = SC.GetValue("System.IsCycleMode"); _cycleSetPoint = _isCycleMode ? SC.GetValue("System.CycleCount") : 0; if (_isCycleMode) { _cycledWafer = 0; _cycledCount = 0; } if (objs == null || objs.Length == 0) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set("Parameter not valid"); return Result.FAIL; } var param = (Dictionary)objs[0]; if (param == null) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set("Parameter not valid"); return Result.FAIL; } var content = ""; foreach (var key in param.Keys) { content += $"{key}-{param[key]}#"; } LOG.Write($"Control Job: {content}"); if (!Singleton.Instance.GetJobRecipeInfor((string)param["JobRecipe"], out string processRecipe, out string layoutRecipe, out int coolTime, out string reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); return Result.FAIL; } if (string.IsNullOrEmpty(layoutRecipe)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set("Parameter not valid, Layout Recipe is null"); return Result.FAIL; } var path = $"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Layout\\{layoutRecipe}.rcp"; if (!File.Exists(path)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Layout \"{layoutRecipe}\" not exist."); return Result.FAIL; } path = $"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Process\\{processRecipe}.rcp"; if (!File.Exists(path)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Process recipe \"{processRecipe}\" not exist."); return Result.FAIL; } if (!RecipeParser.Parse(processRecipe, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out reason, "Process")) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Load process recipe {processRecipe} failed, {reason}"); return Result.FAIL; } List>> useStockers = new List>>(); if (RecipeParser.LayoutRecipeParse(layoutRecipe, ModuleName.PM1.ToString(), out RecipeLayoutEntityNormal layoutRecipeDataNormal, out RecipeLayoutEntityExpert layoutRecipeDataExpert, out reason)) { if (param.ContainsKey("CarrierPara")) { //Stocker1,P_00000036,25,Exist,1111111111111111111111111,LP1;Stocker2,P_00000037,25,Exist,1111111111111111111111111,LP2 var paras = param["CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { foreach (var item in paras) { //Stocker13,,21/22/23/24/25" var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var pStocker = GetModule(arry[0]) as SchedulerStocker; if (pStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("P") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return Result.FAIL; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } if (param.ContainsKey("mCarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["mCarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M")) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return Result.FAIL; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } if (param.ContainsKey("m1CarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["m1CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M1") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return Result.FAIL; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } if (param.ContainsKey("m2CarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["m2CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M2") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return Result.FAIL; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } useStockers.Sort(compare); foreach (var s in _lstSideDummyStocker) { if (CarrierManager.Instance.CheckHasCarrier(s.Module, 0) && CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierType == CarrierType.SD) useStockers.Add(Tuple.Create(s.Module.ToString(), CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierId, new List())); else { bool onRobot = false; if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier.CarrierType == CarrierType.SD && carrier.InternalModuleName == s.Module) { useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); onRobot = true; } } if (!onRobot) { bool inFIMS = false; foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (!carrier.IsEmpty && carrier.CarrierType == CarrierType.SD && carrier.InternalModuleName == s.Module) { inFIMS = true; useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); } } if (!inFIMS && CarrierManager.Instance.GetLocationByInternalCarrierModuleName(s.Module, CarrierType.SD) != null) useStockers.Add(Tuple.Create(s.Module.ToString(), "", new List())); } } } foreach (var s in _lstExtraDummyStocker) { if (CarrierManager.Instance.CheckHasCarrier(s.Module, 0) && CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierType == CarrierType.ED) useStockers.Add(Tuple.Create(s.Module.ToString(), CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierId, new List())); else { bool onRobot = false; if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier.CarrierType == CarrierType.ED && carrier.InternalModuleName == s.Module) { useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); onRobot = true; } } if (!onRobot) { bool inFIMS = false; foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (!carrier.IsEmpty && carrier.CarrierType == CarrierType.ED && carrier.InternalModuleName == s.Module) { inFIMS = true; useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); } } if (!inFIMS && CarrierManager.Instance.GetLocationByInternalCarrierModuleName(s.Module, CarrierType.SD) != null) useStockers.Add(Tuple.Create(s.Module.ToString(), "", new List())); } } } var wafers = WaferManager.Instance.GetWafers(_pm1.Module); if (wafers.Any(x => !x.IsEmpty) && !_lstProcessJobs.Any(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused) && SC.GetValue("System.IsEnableDummyWaferDischarge")) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have wafer in boat"); return Result.FAIL; } if (wafers.Any(x => !x.IsEmpty && x.WaferType == WaferType.None)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have unknown wafer in boat"); return Result.FAIL; } var robotWafers = WaferManager.Instance.GetWafers(ModuleName.WaferRobot); if (robotWafers.Any(x => !x.IsEmpty) && !_lstProcessJobs.Any(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have wafer in wafer robot"); return Result.FAIL; } if (robotWafers.Any(x => !x.IsEmpty && x.WaferType == WaferType.None)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have unknown wafer in wafer robot"); return Result.FAIL; } if (!CheckWaferStatus(useStockers, true, true, out reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); return Result.FAIL; } } var pjJobId = param["PJID"].ToString(); var cjJobId = param["CJID"].ToString(); ControlJobInfo cj = null; if (_lstControlJobs.Exists(x => x.Name == cjJobId)) { for (int i = 1; i < 1000; i++) { if (!_lstControlJobs.Exists(x => x.Name == $"{cjJobId}_{i}")) { cjJobId = $"{cjJobId}_{i}"; break; } } } cj = new ControlJobInfo(); cj.Name = cjJobId; //cj.Module = module; cj.LotName = cjJobId; cj.LotInnerId = Guid.NewGuid(); cj.LotWafers = new List(); cj.CreateTime = DateTime.Now; cj.SetState(EnumControlJobState.WaitingForStart); ProcessJobInfo pj = new ProcessJobInfo(); pj.Name = pjJobId; pj.JobRecipe = param["JobRecipe"].ToString(); pj.ProcessRecipe = processRecipe; pj.LayoutRecipe = layoutRecipe; pj.ControlJobName = cj.Name; pj.SetState(EnumProcessJobState.Queued); pj.CreateTime = DateTime.Now; pj.Stockers = useStockers; pj.SlotWafers = new List>(); pj.ProcessingState = EnumProcessingState.WaitingMaterial; pj.CoolTimeSec = coolTime; pj.IsEmptyLayout = !layoutRecipeDataExpert.Items.Any(x => x != "----"); pj.IsN2PurgeMode = recipeHead.IsN2PurgeMode; pj.N2PurgeModeStr = recipeHead.N2PurgeModeStr; if (useStockers.Any() && !CheckChargeRule(pj, out bool waferShort, false, true, out reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {layoutRecipe} check charge rule failed, {reason}"); return Result.FAIL; } foreach (var stocker in useStockers) { if (CarrierManager.Instance.CheckHasCarrier($"{stocker.Item1}", 0) && CarrierManager.Instance.GetCarrier($"{stocker.Item1}", 0).InternalModuleName.ToString() != stocker.Item1) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Carrier of {stocker.Item1} is not match stocker module name {CarrierManager.Instance.GetCarrier($"{stocker.Item1}", 0).InternalModuleName}"); return Result.FAIL; } } _lstProcessJobs.Add(pj); cj.ProcessJobNameList.Add(pj.Name); if (!_lstControlJobs.Contains(cj)) _lstControlJobs.Add(cj); _faCallback.JobCreated(cj, pj); _secondPj = null; if ((Singleton.Instance.Modules[ModuleName.PM1] as PMModule).IsExcuteIdleRecipe) (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).EndIdleRecipe(); return Result.RUN; } static int compare(Tuple t1, Tuple t2) { int.TryParse(t1.Item1.Replace("Stocker", ""), out int s1); int.TryParse(t2.Item1.Replace("Stocker", ""), out int s2); if (s1 > s2) { return 1; } else { return -1; } } static int compare(Tuple> t1, Tuple> t2) { int.TryParse(t1.Item1.Replace("Stocker", ""), out int s1); int.TryParse(t2.Item1.Replace("Stocker", ""), out int s2); if (s1 > s2) { return 1; } else { return -1; } } internal ProcessJobInfo GetFirstProcessJob(ControlJobInfo cj, ProcessJobInfo checkPj = null) { DateTime dtMin = DateTime.MaxValue; ProcessJobInfo currentPj = null; foreach (var pj in _lstProcessJobs) { if (checkPj != null && checkPj == pj) continue; if (pj.ControlJobName == cj.Name) { if (pj.CreateTime.CompareTo(dtMin) < 0) { dtMin = pj.CreateTime; currentPj = pj; } } } return currentPj; } 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) { if (pj.State == EnumProcessJobState.Processing) _faCallback.JobStopped(cj, pj); pj.SetState(EnumProcessJobState.Stopping); pj.ProcessingState = EnumProcessingState.WaitingWithdrawal; } } if (_isCycleMode) { if (_cycleSetPoint > _cycledCount) { _cycleSetPoint = _cycledCount; EV.PostWarningLog("System", $"system in cycle mode, cycle count reset to {_cycledCount}"); } } _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) { if (pj.State == EnumProcessJobState.Processing) _faCallback.JobAborted(cj, pj); pj.SetState(EnumProcessJobState.Aborting); if (pj.ProcessingState == EnumProcessingState.Charging || pj.ProcessingState == EnumProcessingState.Discharging) { var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; pmModule?.SetN2PurgeLAO2CheckFirstEnable(false); pmModule?.SetN2PurgeProcess(false); } pj.ProcessingState = EnumProcessingState.WaitingWithdrawal; 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); } } Singleton.Instance.FAProcessJobs[jobName].RequestAbort(); foreach (var pj in pjAbortList) { _lstProcessJobs.Remove(pj); } _lstControlJobs.Remove(cj); _dbCallback.LotFinished(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); } foreach (var pj in _lstProcessJobs) { if (pj.ControlJobName == cj.Name) { if (pj.State == EnumProcessJobState.Processing) _faCallback.JobResumed(cj, pj); } } } internal bool StartJob(string jobName) { if (!CheckPMStatus()) { EV.PostWarningLog("Scheduler", "can not change to auto mode, at least one process chamber be online"); return false; } ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName); if (cj == null) { EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}"); return false; } if (_isCycleMode) { if (CheckAllJobDone()) { _cycledWafer = 0; _cycledCount = 0; } } if (cj.State == EnumControlJobState.WaitingForStart) { cj.SetState(EnumControlJobState.Executing); //(GetModule(cj.Module) as SchedulerLoadPort).NoteJobStart(); cj.LotInnerId = Guid.NewGuid(); cj.BeginTime = DateTime.Now; _dbCallback.LotCreated(cj); _faCallback.JobStarted(cj, GetFirstProcessJob(cj)); } return true; } internal void PauseJob(string jobName) { foreach (var cj in _lstControlJobs) { if (cj.Name != jobName && !string.IsNullOrEmpty(jobName)) continue; if (cj.State == EnumControlJobState.Executing) { cj.SetState(EnumControlJobState.Paused); _faCallback.JobPaused(cj, GetFirstProcessJob(cj)); } } } #endregion Job Management private bool CheckPMStatus() { bool hasPmOnline = false; foreach (var schedulerPm in _lstPms) { if (schedulerPm.IsAvailable) { hasPmOnline = true; continue; } } return hasPmOnline; } public Result Start(params object[] objs) { Clear(); _cycledWafer = 0; _cycledCount = 0; timer.Start(); if (!CheckPMStatus()) { 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() { ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing); if (cjActive != null) { MonitorModuleTasks(); } MonitorJobTasks(); return Result.RUN; } #region Job task public Result MonitorJobTasks() { UpdateProcessJobStatus(); UpdateControlJobStatus(); StartNewJob(); return Result.RUN; } private void UpdateProcessJobStatus() { foreach (var pj in _lstProcessJobs) { if (pj.ProcessingState == EnumProcessingState.Discharging && pj.IsEmptyLayout) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; pmModule?.SetN2PurgeLAO2CheckFirstEnable(false); pmModule?.SetN2PurgeProcess(false); } else { if (pj.State == EnumProcessJobState.Processing) { if (CheckAllWaferReturned(pj, true)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; pmModule?.SetN2PurgeLAO2CheckFirstEnable(false); pmModule?.SetN2PurgeProcess(false); } } else if (pj.State == EnumProcessJobState.Stopping) { if (CheckAllWaferReturned(pj, false)) { pj.SetState(EnumProcessJobState.ProcessingComplete); JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0); var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; pmModule?.SetN2PurgeLAO2CheckFirstEnable(false); pmModule?.SetN2PurgeProcess(false); } } } } } private void UpdateControlJobStatus() { if (_lstControlJobs.Count == 0) return; bool allControlJobComplete = true; List cjRemoveList = new List(); foreach (var cj in _lstControlJobs) { 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; string strInfo = $"{cj.Module} has finished: \r\n\r\nProcessed wafer number: {cj.LotWafers.Count} \r\nBegin time: {cj.BeginTime} \r\nEnd time: {cj.EndTime} \r\nDuration: {(cj.EndTime - cj.BeginTime).TotalSeconds:F0} sec"; EV.PostInfoLog("Scheduler", strInfo); if (SC.GetValue("System.Job.EnablePopDialogWhenJobDone")) { EV.PostPopDialogMessage(EventLevel.Information, "System Information", strInfo); } _faCallback.JobFinished(cj, GetFirstProcessJob(cj)); _dbCallback.LotFinished(cj); //if (!(_isCycleMode && _cycledCount < _cycleSetPoint)) // (GetModule(cj.Module) as SchedulerLoadPort).NoteJobComplete(); } } if (cj.State == EnumControlJobState.Completed && (!SC.GetValue("System.IsCycleMode") || (SC.GetValue("System.IsCycleMode") && _cycledCount >= _cycleSetPoint))) { cjRemoveList.Add(cj); } allControlJobComplete = allControlJobComplete && cj.State == EnumControlJobState.Completed; } if (_isCycleMode && _cycledCount < _cycleSetPoint) { int countPerCycle = 0; int countProcessed = 0; foreach (var pj in _lstProcessJobs) { if (pj.State == EnumProcessJobState.Queued || pj.SlotWafers == null) continue; 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 (allControlJobComplete) { _cycledCount++; if (_cycledCount < _cycleSetPoint) { foreach (var cj in _lstControlJobs) { cj.SetState(EnumControlJobState.Executing); cj.LotInnerId = Guid.NewGuid(); //_dbCallback.LotCreated(cj); } foreach (var pj in _lstProcessJobs) { pj.SetState(EnumProcessJobState.Queued); pj.ProcessingState = EnumProcessingState.WaitingMaterial; pj.InnerId = Guid.NewGuid(); if (pj.SlotWafers == null) continue; 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; } pj.SlotWafers.Clear(); } } else { foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Completed) { cjRemoveList.Add(cj); } } } } } if (_waferRobot.IsAvailable && cjRemoveList.Any()) { (Singleton.Instance.Modules[ModuleName.WaferRobot] as WaferRobotModule).Home(out _); } 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); } } public bool CheckAllJobDone() { foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused || cj.State == EnumControlJobState.Queued || cj.State == EnumControlJobState.WaitingForStart) return false; } if (_lstControlJobs.Count > 0 || _lstProcessJobs.Count > 0) { return false; } return true; } public List>> GetProcessingStockers() { if (!_lstControlJobs.Any() || !_lstProcessJobs.Any()) return null; foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Completed) continue; var pj = GetFirstProcessJob(cj); if (pj != null) { if (pj.ProcessingState != EnumProcessingState.Discharging) return pj.Stockers; else { List>> temp = new List>>(); foreach (var item in pj.Stockers) { if (CarrierManager.Instance.CheckHasCarrier(item.Item1, 0)) { var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1).ToList(); if (wafers != null && !wafers.Any(x => !x.IsEmpty && x.OriginStation == (int)ModuleHelper.Converter(item.Item1))) continue; } temp.Add(Tuple.Create(item.Item1, item.Item2, item.Item3)); } return temp; } } } return null; } public List>> GetSecondlyProcessingStockers() { var pj = GetSecondlyProcessJob(); return pj != null ? pj.Stockers : null; } private ProcessJobInfo GetSecondlyProcessJob() { if (!_lstControlJobs.Any() || !_lstProcessJobs.Any()) return null; if (_lstControlJobs.Count > 1) { var cj = _lstControlJobs[1]; if (cj.State == EnumControlJobState.Completed) return null; var pj = GetFirstProcessJob(cj); return pj; } return null; } private ProcessJobInfo GetSecondlyProcessJobV2() { if (!_lstControlJobs.Any() || !_lstProcessJobs.Any()) return null; if (_lstControlJobs.Count > 1 && _secondPj == null) { var cj = _lstControlJobs[1]; if (cj.State == EnumControlJobState.Completed) return null; var pj = GetFirstProcessJob(cj); return pj; } return _secondPj; } public List>> GetAllPJStockers() { List>> temp = new List>>(); if (!_lstControlJobs.Any() || !_lstProcessJobs.Any()) return temp; foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Completed) continue; foreach (var pj in _lstProcessJobs) { if (pj != null && pj.ControlJobName == cj.Name) { temp.AddRange(pj.Stockers); } } } return temp; } private void StartNewJob() { if (!_lstControlJobs.Any() || !_lstProcessJobs.Any()) return; _secondPj = GetSecondlyProcessJobV2(); ControlJobInfo cjActived = null; DateTime dtMin = DateTime.MaxValue; foreach (var cj in _lstControlJobs) { if (cj.State == EnumControlJobState.Completed) continue; if (cj.CreateTime.CompareTo(dtMin) < 0) { dtMin = cj.CreateTime; cjActived = cj; } } if (cjActived == null) return; if (cjActived.State != EnumControlJobState.Executing && cjActived.State != EnumControlJobState.Paused) { cjActived.BeginTime = DateTime.Now; cjActived.SetState(EnumControlJobState.Executing); } ProcessJobInfo pj = null; foreach (var cj in _lstControlJobs) { if (cj.State != EnumControlJobState.Executing) continue; cjActived = cj; pj = GetFirstProcessJob(cjActived); if (pj != null && pj.State == EnumProcessJobState.Queued) { if (!pj.IsEmptyLayout) { if (CheckProcessJobReady(pj)) { //先不管charge rule if (!CheckChargeRule(pj, out bool waferShort, true, true, out string reason)) { if (!_chargeRuleAlarmTrigDic.ContainsKey(pj.InnerId.ToString())) _chargeRuleAlarmTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _chargeRuleAlarmTrigDic[pj.InnerId.ToString()].CLK = true; if (_chargeRuleAlarmTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {pj.LayoutRecipe} check charge rule failed, {reason}"); return; } if (!CheckWaferStatus(pj.Stockers, false, false, out reason)) { if (!_waferStatusAlarmTrigDic.ContainsKey(pj.InnerId.ToString())) _waferStatusAlarmTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _waferStatusAlarmTrigDic[pj.InnerId.ToString()].CLK = true; if (_waferStatusAlarmTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); return; } if (!CheckDummyWaferUse(pj, cj)) return; if (!SC.GetValue("System.IsEnableDummyWaferDischarge")) { var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1).ToList(); if (wafers != null && wafers.Any(x => !x.IsEmpty && (x.WaferType == WaferType.SD || x.WaferType == WaferType.ED))) { for (int i = 0; i < wafers.Count; i++) { var wafer = wafers[i]; if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType != WaferType.SD && wafer.WaferType != WaferType.ED) { if (!_dummyWaferCheckTrigDic.ContainsKey(pj.InnerId.ToString())) _dummyWaferCheckTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _dummyWaferCheckTrigDic[pj.InnerId.ToString()].CLK = true; if (_dummyWaferCheckTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {pj.LayoutRecipe} check charge rule failed, invalid wafer in boat"); return; } if (!pj.SideDummySlots.Any(x => x == i) && !pj.ExtraDummySlots.Any(x => x == i)) { if (!_dummyWaferCheckTrigDic.ContainsKey(pj.InnerId.ToString())) _dummyWaferCheckTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _dummyWaferCheckTrigDic[pj.InnerId.ToString()].CLK = true; if (_dummyWaferCheckTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {pj.LayoutRecipe} check charge rule failed, invalid dummy wafer in boat, dummy wafer layout mismatch"); return; } } var existSDSlots = new List(); foreach (var slot in pj.SideDummySlots) { var wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, slot); if (!wafer.IsEmpty) { if (wafer.WaferType != WaferType.SD) { if (!_dummyWaferCheckTrigDic.ContainsKey(pj.InnerId.ToString())) _dummyWaferCheckTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _dummyWaferCheckTrigDic[pj.InnerId.ToString()].CLK = true; if (_dummyWaferCheckTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {pj.LayoutRecipe} check charge rule failed, invalid dummy wafer in boat, SD wafer layout mismatch"); return; } else { existSDSlots.Add(slot); } } } var existEDSlots = new List(); foreach (var slot in pj.ExtraDummySlots) { var wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, slot); if (!wafer.IsEmpty) { if (wafer.WaferType != WaferType.ED) { if (!_dummyWaferCheckTrigDic.ContainsKey(pj.InnerId.ToString())) _dummyWaferCheckTrigDic.Add(pj.InnerId.ToString(), new R_TRIG()); _dummyWaferCheckTrigDic[pj.InnerId.ToString()].CLK = true; if (_dummyWaferCheckTrigDic[pj.InnerId.ToString()].Q) Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {pj.LayoutRecipe} check charge rule failed, invalid dummy wafer in boat, ED wafer layout mismatch"); return; } else { existEDSlots.Add(slot); } } } for (int i = 0; i < wafers.Count; i++) { var wafer = wafers[i]; if (wafer == null || wafer.IsEmpty) continue; wafer.ProcessState = EnumWaferProcessStatus.Idle; } pj.IsNeedChargeDummyWafer = pj.ExtraDummySlots.Count != existEDSlots.Count || pj.SideDummySlots.Count != existSDSlots.Count; } else { pj.IsNeedChargeDummyWafer = true; } } else { pj.IsNeedChargeDummyWafer = true; } ActiveProcessJob(cjActived, pj); _sideDummyWafers = GetDummyWafers(_lstSideDummyStocker, pj.SideDummySlots.Count(), WaferType.SD); _extraDummyWafers = GetDummyWafers(_lstExtraDummyStocker, pj.ExtraDummySlots.Count(), WaferType.ED); _sideDummySlots = pj.SideDummySlots; _extraDummySlots = pj.ExtraDummySlots; _productSlots = pj.ProductSlots; _monitor1Slots = pj.Monitor1Slots; _monitor2Slots = pj.Monitor2Slots; _lstCurrentPjStocker.Clear(); foreach (var s in pj.Stockers) { var module = GetModule(s.Item1) as SchedulerStocker; if (module != null) _lstCurrentPjStocker.Add(module); } } } else { if (!SC.GetValue("System.IsEnableDummyWaferDischarge")) { var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1).ToList(); for (int i = 0; i < wafers.Count; i++) { var wafer = wafers[i]; if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType != WaferType.ED && wafer.WaferType != WaferType.SD) continue; wafer.ProcessState = EnumWaferProcessStatus.Idle; } } ActiveProcessJob(cjActived, pj); } break; } } if (_lstControlJobs.Count > 1 && pj != null) { var second = GetSecondlyProcessJob(); if (second != null && second.IsEmptyLayout && !second.IsStandbyStarted && (pj.ProcessingState == EnumProcessingState.Cooling || pj.ProcessingState == EnumProcessingState.Discharging)) { foreach (var pm in _lstPms) { if (pm.IsAvailable) { _dbCallback.PjCreated(second); _dbCallback.PjStart(); pm.Standby(second.ProcessRecipe); second.IsStandbyStarted = true; } } } } } private bool ActiveProcessJob(ControlJobInfo cj, ProcessJobInfo pj) { //_dbCallback.JobCreated(cj, pj); pj.SetState(EnumProcessJobState.Processing); pj.ProcessingState = EnumProcessingState.Charging; pj.BeginTime = DateTime.Now; if (pj.IsN2PurgeMode) { var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; //pmModule?.SetN2PurgeProcess(true); //if (SC.ContainsItem("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable") && SC.GetValue("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable")) // pmModule?.SetN2PurgeLAO2CheckFirstEnable(true); if (SC.ContainsItem("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable") && SC.GetValue("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable")) { pmModule?.SetN2PurgeProcess(true); pmModule?.SetN2PurgeLAO2CheckFirstEnable(true); } if (SC.ContainsItem("PM1.RecipeRelevancyN2Purge") && SC.GetValue("PM1.RecipeRelevancyN2Purge") && SC.ContainsItem("PM1.SelectN2PurgeMode")) { var setValue = pmModule.GetN2PurgeModeEnumByStr(pj.N2PurgeModeStr); SC.SetItemValueFromString("PM1.SelectN2PurgeMode", setValue); pmModule.RestAllN2PrugeRD(); } } foreach (var pm in _lstPms) { if (pm.IsAvailable) { _dbCallback.PjCreated(pj); _dbCallback.PjStart(); pm.Standby(pj.ProcessRecipe); pj.IsStandbyStarted = true; } } return true; } #endregion Job task #region Module task public Result MonitorModuleTasks() { MonitorFIMSTask(); MonitorWaferRobotTask(); MonitorCarrierRobotTask(); MonitorPMTask(); return Result.RUN; } private void MonitorWaferRobotTask() { if (!_waferRobot.IsAvailable) return; foreach (var fims in _lstFIMSs) { if (fims.IsWaitTransfer(ModuleName.WaferRobot)) { fims.StopWaitTransfer(ModuleName.WaferRobot); } } foreach (var pm in _lstPms) { if (pm.IsWaitTransfer(ModuleName.WaferRobot)) { pm.StopWaitTransfer(ModuleName.WaferRobot); } } MonitorWaferRobotFIMSTask(); if (!_waferRobot.IsAvailable) return; MonitorWaferRobotPMTask(); } private void MonitorCarrierRobotTask() { if (!_carrierRobot.IsAvailable) return; //efem robot is idle, release all the target foreach (var fims in _lstFIMSs) { if (fims.IsWaitTransfer(ModuleName.CarrierRobot)) { fims.StopWaitTransfer(ModuleName.CarrierRobot); } } foreach (var stock in _lstTotlaStockers) { if (stock.IsWaitTransfer(ModuleName.CarrierRobot)) { stock.StopWaitTransfer(ModuleName.CarrierRobot); } } var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return; if (pj.ProcessingState == EnumProcessingState.Discharging) { //discharge DischargingOrderBySort(SC.GetStringValue("System.ChargingOrderBySort")); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstSideDummyStocker, WaferType.SD, _sideDummySlots); if (!_carrierRobot.IsAvailable) return; MonitorCarrierRobotPickFIMSTask(); if (!_carrierRobot.IsAvailable) return; MonitorCarrierRobotPlaceFIMSTaskInDischarge(); } else if (pj.ProcessingState == EnumProcessingState.Charging) { //charge if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstSideDummyStocker, WaferType.SD); if (!_carrierRobot.IsAvailable) return; ChargingOrderBySort(pj, SC.GetStringValue("System.ChargingOrderBySort")); if (!_carrierRobot.IsAvailable) return; MonitorCarrierRobotPickFIMSTask(); if (!_carrierRobot.IsAvailable) return; MonitorCarrierRobotPlaceFIMSTaskInCharge(); } else if (pj.ProcessingState == EnumProcessingState.Processing) { MonitorCarrierRobotPickFIMSTask(); MonitorCassetteRobotPlaceStockerTask(); } } private void MonitorFIMSTask() { if (!_lstProcessJobs.Any()) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return; //load if (pj.ProcessingState == EnumProcessingState.Charging) { foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!CheckCarrierCanPickFromFIMS(st.Module) && !fimsDevice.IsLoadCompleted && st.Load(pj.IsN2PurgeMode, "Charging")) { return; } } } else if (pj.ProcessingState == EnumProcessingState.Discharging) { //先判断空片的情况,空片的先load foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); var wafers = WaferManager.Instance.GetWafers(st.Module); if (wafers != null) { if (CheckCarrierNoHasEmptySlot(st.Module) && !fimsDevice.IsLoadCompleted && st.Load(pj.IsN2PurgeMode, "Discharging")) { return; } } } foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null) { if (!CheckCarrierCanPickFromFIMSInDischarge(carrier.InternalModuleName) && !fimsDevice.IsLoadCompleted && st.Load(pj.IsN2PurgeMode, "Discharging")) { return; } } } } //unload if (pj.ProcessingState == EnumProcessingState.Charging) { foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (CheckCarrierCanPickFromFIMS(st.Module) && !fimsDevice.IsUnloadCompleted && st.Unload(pj.IsN2PurgeMode, "Charging")) { return; } } if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable || CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (fimsDevice.IsUnloadCompleted) continue; var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); var transfer = Singleton.Instance.GetTransferJobStockers(); if (transfer != null && transfer.Any(x => x.Stocker == carrier.InternalModuleName)) continue; GetWaferSlotsAndWaferType(carrier, out List slots, out WaferType waferType); if (slots != null && GetWaferCountRelatedToWaferRobot(waferType, false) <= slots.Count && CheckCarrierCanPickFromStocker(ModuleName.CarrierRobot) && fims.Unload(pj.IsN2PurgeMode, "Charging")) { return; } } } } else if (pj.ProcessingState == EnumProcessingState.Discharging) { //先判断满片的情况,满片的先unload foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null) { if (!CheckCarrierHasEmptySlot(st.Module) && _waferRobot.IsAvailable && !fimsDevice.IsUnloadCompleted && st.Unload(pj.IsN2PurgeMode, "Discharging")) { return; } } } foreach (var st in _lstFIMSs) { if (!st.IsAvailable || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null) { if (CheckCarrierCanPickFromFIMSInDischarge(carrier.InternalModuleName) && _waferRobot.IsAvailable && !fimsDevice.IsUnloadCompleted && st.Unload(pj.IsN2PurgeMode, "Discharging")) { return; } } } } } private void MonitorWaferRobotPMTask() { if (!_waferRobot.IsAvailable) return; var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; if (pmModule == null) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return; //place var wafer = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2); List slots = GetWaferSlots(wafer.WaferType); if (!_logTrigDic.ContainsKey("GetWaferSlots(wafer.WaferType)")) _logTrigDic.Add("GetWaferSlots(wafer.WaferType)", new R_TRIG()); _logTrigDic["GetWaferSlots(wafer.WaferType)"].CLK = slots == null; if (_logTrigDic["GetWaferSlots(wafer.WaferType)"].Q) LOG.Write($"GetWaferSlots(wafer.WaferType) is null"); if (pj.ProcessingState == EnumProcessingState.Charging && wafer != null && !wafer.IsEmpty && wafer.ProcessState == EnumWaferProcessStatus.Idle && slots != null) { Hand placeBlade = Hand.Blade1; int placeSlot = -1; for (int i = 0; i < slots.Count; i++) { if (!WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i])) continue; placeSlot = slots[i]; placeBlade = Hand.Blade1; break; } if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 1) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 3) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 4)) { //check PM for (int i = 0; i < slots.Count; i++) { if (!WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i])) continue; placeSlot = slots[i]; if (i + 4 < slots.Count && Math.Abs(slots[i] - slots[i + 4]) == 4) { if (WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 1]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 2]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 3]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 4])) { placeBlade = Hand.Both; if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") placeSlot = slots[i + 4]; } } break; } } if (pmModule.CheckReadyForTransfer(_waferRobot.Module, placeBlade, placeSlot, EnumTransferType.Place, out string reason) && placeSlot != -1 && _waferRobot.Place(_pm1.Module, placeSlot, placeBlade)) { _pm1.WaitTransfer(ModuleName.WaferRobot); return; } } if (!_waferRobot.IsAvailable) return; //pick List targetWaferSlots = GetWaferSlots(); if (!_logTrigDic.ContainsKey("GetWaferSlots()")) _logTrigDic.Add("GetWaferSlots()", new R_TRIG()); _logTrigDic["GetWaferSlots()"].CLK = targetWaferSlots == null; if (_logTrigDic["GetWaferSlots()"].Q) LOG.Write($"GetWaferSlots() is null"); if (pj.ProcessingState == EnumProcessingState.Discharging && wafer != null && wafer.IsEmpty && targetWaferSlots != null) { Hand pickBlade = Hand.Blade1; int pickSlot = -1; var isEnableDummyWaferDischarge = SC.GetValue("System.IsEnableDummyWaferDischarge"); //check PM for (int i = 0; i < targetWaferSlots.Count; i++) { var targetWafer = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i]); if (targetWafer == null || targetWafer.IsEmpty || (targetWafer.ProcessState != EnumWaferProcessStatus.Completed && targetWafer.ProcessState != EnumWaferProcessStatus.Abort && targetWafer.ProcessState != EnumWaferProcessStatus.Failed)) continue; if (!isEnableDummyWaferDischarge && (targetWafer.WaferType == WaferType.SD || targetWafer.WaferType == WaferType.ED)) continue; pickSlot = targetWaferSlots[i]; if (i + 4 < targetWaferSlots.Count && Math.Abs(targetWaferSlots[i] - targetWaferSlots[i + 4]) == 4) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, targetWaferSlots[i + 1]) && WaferManager.Instance.CheckHasWafer(_pm1.Module, targetWaferSlots[i + 2]) && WaferManager.Instance.CheckHasWafer(_pm1.Module, targetWaferSlots[i + 3]) && WaferManager.Instance.CheckHasWafer(_pm1.Module, targetWaferSlots[i + 4]) && SC.GetValue($"{_waferRobot.Module}.IsSupport5Wafer")) { bool isFromTopToBottom = SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom"; var wafer0 = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i + (isFromTopToBottom ? 4 : 0)]); var wafer1 = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i + (isFromTopToBottom ? 3 : 1)]); var wafer2 = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i + 2]); var wafer3 = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i + (isFromTopToBottom ? 1 : 3)]); var wafer4 = WaferManager.Instance.GetWafer(_pm1.Module, targetWaferSlots[i + (isFromTopToBottom ? 0 : 4)]); if (WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 1) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 3) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 4) && wafer0.OriginStation == wafer1.OriginStation && wafer0.OriginStation == wafer2.OriginStation && wafer0.OriginStation == wafer3.OriginStation && wafer0.OriginStation == wafer4.OriginStation && Math.Abs(wafer1.OriginSlot - wafer2.OriginSlot) == 1 && Math.Abs(wafer2.OriginSlot - wafer3.OriginSlot) == 1 && Math.Abs(wafer0.OriginSlot - wafer4.OriginSlot) == 4 && Math.Abs(wafer0.OriginSlot - wafer3.OriginSlot) == 3 && Math.Abs(wafer0.OriginSlot - wafer2.OriginSlot) == 2 && Math.Abs(wafer0.OriginSlot - wafer1.OriginSlot) == 1) { pickBlade = Hand.Both; pickSlot = wafer4.Slot; } } } break; } if (pmModule.CheckReadyForTransfer(_waferRobot.Module, pickBlade, pickSlot, EnumTransferType.Pick, out string reason) && pickSlot != -1 && _waferRobot.Pick(_pm1.Module, pickSlot, pickBlade)) { _pm1.WaitTransfer(ModuleName.WaferRobot); } } } private void MonitorWaferRobotFIMSTask() { if (!_waferRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return; //pick if (pj.ProcessingState == EnumProcessingState.Charging && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 2)) { SchedulerFIMS fims = null; List slots = null; WaferType waferType = WaferType.None; ModuleName currentFims = GetCurrentTransferFims(); foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; if (!CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!fimsDevice.IsLoadCompleted) continue; var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null && !carrier.IsEmpty) { var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); bool hasWafer = false; var wafers = WaferManager.Instance.GetWafers(st.Module); if (wafers != null && stockerInfo != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (!wafer.IsEmpty && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) { hasWafer = true; break; } } } if (!hasWafer) continue; if (currentFims != ModuleName.System && currentFims != st.Module) continue; GetWaferSlotsAndWaferType(carrier, out slots, out waferType); if (slots != null && GetWaferCountRelatedToWaferRobot(waferType, false) < slots.Count) { fims = st; break; } } } if (fims != null && slots != null) { Hand pickBlade = Hand.Blade1; int pickSlot = -1; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); if (WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 1) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 3) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 4)) { //check PM for (int i = 0; i < slots.Count; i++) { if (!WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i])) continue; if (i + 4 < slots.Count && Math.Abs(slots[i] - slots[i + 4]) == 4) { if (WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 1]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 2]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 3]) && WaferManager.Instance.CheckNoWafer(_pm1.Module, slots[i + 4]) && SC.GetValue($"{_waferRobot.Module}.IsSupport5Wafer")) { pickBlade = Hand.Both; break; } } break; } //check cassette Dictionary dummyWafers = new Dictionary(); if (waferType == WaferType.SD) dummyWafers = _sideDummyWafers; else if (waferType == WaferType.ED) dummyWafers = _extraDummyWafers; var wafers = WaferManager.Instance.GetWafers(fims.Module).ToList(); if (SC.GetStringValue("System.ChargingOrderFromCassette") == "FromTopToBottom") wafers.Reverse(); if (wafers != null) { for (int i = 0; i < wafers.Count; i++) { if (wafers[i] == null || wafers[i].IsEmpty || wafers[i].ProcessState != EnumWaferProcessStatus.Idle) continue; if ((wafers[i].WaferType == WaferType.SD || wafers[i].WaferType == WaferType.ED) && !dummyWafers.ContainsKey(wafers[i].InnerId.ToString())) continue; if (stockerInfo.Item3.Any() && !stockerInfo.Item3.Any(x => x == i)) continue; pickSlot = wafers[i].OriginSlot; if (pickBlade == Hand.Both) { if (i < SC.GetValue("System.CassetteSlotCount") - 4) { if (waferType == WaferType.SD || waferType == WaferType.ED) { if (!wafers[i + 1].IsEmpty && !wafers[i + 2].IsEmpty && !wafers[i + 3].IsEmpty && !wafers[i + 4].IsEmpty && wafers[i + 1].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 2].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 3].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 4].ProcessState == EnumWaferProcessStatus.Idle && (!stockerInfo.Item3.Any() || (stockerInfo.Item3.Any(x => x == i + 1) && stockerInfo.Item3.Any(x => x == i + 2) && stockerInfo.Item3.Any(x => x == i + 3) && stockerInfo.Item3.Any(x => x == i + 4))) && dummyWafers.ContainsKey(wafers[i + 1].InnerId.ToString()) && dummyWafers.ContainsKey(wafers[i + 2].InnerId.ToString()) && dummyWafers.ContainsKey(wafers[i + 3].InnerId.ToString()) && dummyWafers.ContainsKey(wafers[i + 4].InnerId.ToString())) { if (SC.GetStringValue("System.ChargingOrderFromCassette") == "FromTopToBottom") pickSlot = wafers[i + 4].OriginSlot; break; } else { pickBlade = Hand.Blade1; break; } } else { if (!wafers[i + 1].IsEmpty && !wafers[i + 2].IsEmpty && !wafers[i + 3].IsEmpty && !wafers[i + 4].IsEmpty && wafers[i + 1].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 2].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 3].ProcessState == EnumWaferProcessStatus.Idle && wafers[i + 4].ProcessState == EnumWaferProcessStatus.Idle && (!stockerInfo.Item3.Any() || (stockerInfo.Item3.Any(x => x == i + 1) && stockerInfo.Item3.Any(x => x == i + 2) && stockerInfo.Item3.Any(x => x == i + 3) && stockerInfo.Item3.Any(x => x == i + 4)))) { if (SC.GetStringValue("System.ChargingOrderFromCassette") == "FromTopToBottom") pickSlot = wafers[i + 4].OriginSlot; break; } else { pickBlade = Hand.Blade1; break; } } } else { pickBlade = Hand.Blade1; break; } } else { pickBlade = Hand.Blade1; break; } } } } if (SC.GetValue($"System.IsEnableFIMSChargeMapping")) { if (carrier != null && !carrier.IsEmpty && carrier.IsMapped && carrier.IsMapOK && pickSlot != -1 && _pm1.IsAvailable && _waferRobot.Pick(fims.Module, pickSlot, pickBlade)) { fims.WaitTransfer(ModuleName.WaferRobot); return; } } else { if (pickSlot != -1 && _waferRobot.Pick(fims.Module, pickSlot, pickBlade)) { fims.WaitTransfer(ModuleName.WaferRobot); } } } } if (!_waferRobot.IsAvailable) return; // mapping if (pj.ProcessingState == EnumProcessingState.Charging && SC.GetValue($"System.IsEnableFIMSChargeMapping") && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 2) && WaferManager.Instance.CheckNoWafer(ModuleName.WaferRobot, 1)) { foreach (var fims in _lstFIMSs) { if (!fims.IsAvailable) continue; if (!CarrierManager.Instance.CheckHasCarrier(fims.Module.ToString(), 0)) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{fims.Module}"); if (!fimsDevice.IsLoadCompleted) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module); if (carrier == null || carrier.IsEmpty || carrier.IsMapped) continue; var mappingSlot = GetMappingSlot(fims.Module); if (_waferRobot.Map(fims.Module, mappingSlot.Length == 0 ? 0 : Regex.Matches(mappingSlot, "1").Count, mappingSlot, true, false, Hand.Blade1)) { fims.WaitTransfer(ModuleName.WaferRobot); return; } } } if (!_waferRobot.IsAvailable) return; //place var robotWafer = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2); if (pj.ProcessingState == EnumProcessingState.Discharging && robotWafer != null && !robotWafer.IsEmpty && (robotWafer.ProcessState == EnumWaferProcessStatus.Completed || robotWafer.ProcessState == EnumWaferProcessStatus.Abort || robotWafer.ProcessState == EnumWaferProcessStatus.Failed)) { SchedulerFIMS fims = null; var waferInRobot = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2); foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; if (!CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!fimsDevice.IsLoadCompleted) continue; var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier == null || carrier.IsEmpty) continue; if ((ModuleName)waferInRobot.OriginStation != carrier.InternalModuleName) continue; bool hasEmptySlot = false; var wafers = WaferManager.Instance.GetWafers(st.Module); if (wafers != null) { foreach (var wafer in wafers) { if (wafer == null) continue; if (wafer.IsEmpty) { hasEmptySlot = true; break; } } } if (hasEmptySlot) { fims = st; break; } } if (fims != null) { Hand placeBlade = Hand.Blade1; int placeSlot = waferInRobot.OriginSlot; if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 1) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 3) && WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 4) && WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 0).OriginStation == WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 1).OriginStation && WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 1).OriginStation == WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2).OriginStation && WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2).OriginStation == WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 3).OriginStation && WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 3).OriginStation == WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 4).OriginStation) { var tempPlaceSlot = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 0).OriginSlot; if (tempPlaceSlot + 4 < SC.GetValue("System.CassetteSlotCount")) { if (WaferManager.Instance.CheckNoWafer(fims.Module, tempPlaceSlot + 1) && WaferManager.Instance.CheckNoWafer(fims.Module, tempPlaceSlot + 2) && WaferManager.Instance.CheckNoWafer(fims.Module, tempPlaceSlot + 3) && WaferManager.Instance.CheckNoWafer(fims.Module, tempPlaceSlot + 4)) { placeBlade = Hand.Both; placeSlot = tempPlaceSlot; } } } if (placeSlot != -1 && _waferRobot.Place(fims.Module, placeSlot, placeBlade)) { fims.WaitTransfer(ModuleName.WaferRobot); } } } } private bool CheckWaferSlotsHasWafer(List slots) { foreach (var slot in slots) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, slot)) { return true; } } return false; } private List GetWaferSlots() { List slots = null; switch (SC.GetStringValue("System.ChargingOrderBySort")) { case "ED,P,M": if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; break; case "ED,M,P": if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; break; case "P,ED,M": if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; break; case "P,M,ED": if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; break; case "M,P,ED": if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; break; case "M,ED,P": if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; break; default: if (CheckWaferSlotsHasWafer(_monitor1Slots)) return _monitor1Slots; if (CheckWaferSlotsHasWafer(_monitor2Slots)) return _monitor2Slots; if (CheckWaferSlotsHasWafer(_productSlots)) return _productSlots; if (CheckWaferSlotsHasWafer(_extraDummySlots)) return _extraDummySlots; break; } foreach (var slot in _sideDummySlots) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, slot)) { return _sideDummySlots; } } return slots; } private bool CheckCarrierHasWaferInPM(ModuleName module) { bool isHaveWafer = false; for (int i = 0; i < WaferManager.Instance.GetWafers(_pm1.Module).Length; i++) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (wafer.OriginStation == (int)module) { isHaveWafer = true; break; } } return isHaveWafer; } private void DischargingOrderBySort(string order) { switch (order) { case "ED,P,M": MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); break; case "ED,M,P": MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); break; case "P,ED,M": MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); break; case "P,M,ED": if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); break; case "M,P,ED": if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; break; case "M,ED,P": MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; break; default: MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M1, _monitor1Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.M2, _monitor2Slots); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.P, _productSlots); if (!_carrierRobot.IsAvailable) return; if (SC.GetValue("System.IsEnableDummyWaferDischarge")) MonitorCassetteRobotStockerTaskInDischarge(_lstTotlaStockers, WaferType.ED, _extraDummySlots); break; } } private void ChargingOrderBySort(ProcessJobInfo pj, string order) { List pjStocker = new List(); foreach (var s in pj.Stockers) { var module = GetModule(s.Item1) as SchedulerStocker; if (module != null) pjStocker.Add(module); } switch (order) { case "ED,P,M": if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); break; case "ED,M,P": if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); break; case "P,ED,M": MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); if (!_carrierRobot.IsAvailable) return; if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); break; case "P,M,ED": MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); if (!_carrierRobot.IsAvailable) return; if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); break; case "M,P,ED": MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); if (!_carrierRobot.IsAvailable) return; if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); break; case "M,ED,P": MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); if (!_carrierRobot.IsAvailable) return; if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); break; default: if (pj.IsNeedChargeDummyWafer) MonitorCassetteRobotStockerTask(_lstExtraDummyStocker, WaferType.ED); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.P); if (!_carrierRobot.IsAvailable) return; MonitorCassetteRobotStockerTask(pjStocker, WaferType.M1); MonitorCassetteRobotStockerTask(pjStocker, WaferType.M2); break; } } private void MonitorCassetteRobotStockerTaskInDischarge(List targetStockers, WaferType targetWaferType, List waferSlots) { if (!_carrierRobot.IsAvailable) return; var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); //pick if (CarrierManager.Instance.CheckNoCarrier(ModuleName.CarrierRobot, 0) && waferSlots.Count > 0) { bool needPickSdCassette = false; int sdWaferCount = GetWaferCountRelatedToWaferRobot(targetWaferType, true); needPickSdCassette = sdWaferCount > 0; var sdStockerModule = GetModuleNameForNextWafer(targetWaferType); if (needPickSdCassette && sdStockerModule != ModuleName.System) { SchedulerStocker sdStocker = null; foreach (var sd in targetStockers) { if (!CarrierManager.Instance.CheckHasCarrier(sd.Module, 0) || CarrierManager.Instance.GetCarrier(sd.Module, 0).CarrierType != targetCarrierType) continue; if (sd.Module == sdStockerModule && CheckCarrierHasEmptySlot(sd.Module)) { sdStocker = sd; break; } } SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; if (CarrierManager.Instance.CheckNoCarrier(st.Module, 0)) { fims = st; break; } } if (sdStocker != null && fims != null) { if (_carrierRobot.Pick(sdStocker.Module, 0, Hand.Blade1)) { sdStocker.WaitTransfer(ModuleName.CarrierRobot); return; } } } } if (!_carrierRobot.IsAvailable) return; //place var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier != null && !carrier.IsEmpty && carrier.CarrierType == targetCarrierType) { if (!CheckModuleHasWaferInWaferRobotAndPM(carrier.InternalModuleName) || !CheckCarrierHasEmptySlot(ModuleName.CarrierRobot)) { SchedulerStocker sdStocker = null; foreach (var sd in targetStockers) { if (CarrierManager.Instance.CheckNoCarrier(sd.Module, 0) && sd.Module == carrier.InternalModuleName) { sdStocker = sd; break; } } if (sdStocker != null) { var canPlace = true; var transfer = Singleton.Instance.GetTransferJobStockers(); if (transfer != null && transfer.Any(x => x.Stocker == carrier.InternalModuleName)) canPlace = false; if (canPlace && _carrierRobot.Place(sdStocker.Module, 0, Hand.Blade1)) { sdStocker.WaitTransfer(ModuleName.CarrierRobot); return; } } } } } private bool CheckCarrierCanPickFromFIMSInDischarge(ModuleName fimsCarrierModule) { List robotModules = new List(); for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.WaferRobot).Length; i++) { var wafer = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, i); if (wafer == null || wafer.IsEmpty) continue; if (!robotModules.Contains((ModuleName)wafer.OriginStation)) robotModules.Add((ModuleName)wafer.OriginStation); } if (robotModules.Contains(fimsCarrierModule)) return false; List pmModules = new List(); for (int i = 0; i < WaferManager.Instance.GetWafers(_pm1.Module).Length; i++) { var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (!pmModules.Contains((ModuleName)wafer.OriginStation)) pmModules.Add((ModuleName)wafer.OriginStation); } if (pmModules.Contains(fimsCarrierModule)) return false; return true; } private ModuleName GetNextStockerRelatedToWaferRobot() { List fimsModules = new List(); foreach (var fims in _lstFIMSs) { if (CarrierManager.Instance.CheckNoCarrier(fims.Module, 0)) continue; fimsModules.Add(CarrierManager.Instance.GetCarrier(fims.Module, 0).InternalModuleName); } List robotModules = new List(); for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.WaferRobot).Length; i++) { var wafer = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, i); if (wafer == null || wafer.IsEmpty) continue; if (!robotModules.Contains((ModuleName)wafer.OriginStation)) robotModules.Add((ModuleName)wafer.OriginStation); } if (robotModules.Count > 0) { foreach (var module in robotModules) { if (!fimsModules.Any(x => x == module)) return module; } } List pmModules = new List(); for (int i = 0; i < WaferManager.Instance.GetWafers(_pm1.Module).Length; i++) { var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (!pmModules.Contains((ModuleName)wafer.OriginStation)) pmModules.Add((ModuleName)wafer.OriginStation); if (pmModules.Count == _lstFIMSs.Count) break; } if (pmModules.Count > 0) { foreach (var module in pmModules) { if (!fimsModules.Any(x => x == module)) return module; } } return ModuleName.System; } private void MonitorCassetteRobotPlaceStockerTask() { if (!_carrierRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return; //place var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier != null && !carrier.IsEmpty && pj.Stockers.Any(x => x.Item1 == carrier.InternalModuleName.ToString())) { var target = pj.Stockers.Find(x => x.Item1 == carrier.InternalModuleName.ToString()); if (target != null && CarrierManager.Instance.CheckNoCarrier(target.Item1, 0)) { if (_carrierRobot.Place(ModuleHelper.Converter(target.Item1), 0, Hand.Blade1)) { GetModule(target.Item1).WaitTransfer(ModuleName.CarrierRobot); return; } } } } private void MonitorCassetteRobotStockerTask(List targetStockers, WaferType targetWaferType) { if (!_carrierRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return; var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); var targetSlots = GetWaferSlots(targetWaferType); var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); if (targetSlots == null) return; //pick if (CarrierManager.Instance.CheckNoCarrier(ModuleName.CarrierRobot, 0) && targetSlots.Count > 0) { bool needPickTargetCassette = false; int targetWaferCount = GetWaferCountRelatedToWaferRobot(targetWaferType); if (targetWaferCount < targetSlots.Count) needPickTargetCassette = true; if (needPickTargetCassette) { SchedulerStocker targetStocker = null; foreach (var target in targetStockers) { if (CarrierManager.Instance.CheckHasCarrier(target.Module, 0) && !CheckCarrierHasNoWafer(target.Module, targetWaferType) && CarrierManager.Instance.GetCarrier(target.Module).CarrierType == targetCarrierType) { if (pj.ProcessingState == EnumProcessingState.Charging) { carrier = CarrierManager.Instance.GetCarrier(target.Module); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); var wafers = WaferManager.Instance.GetWafers(target.Module); if (wafers != null && stockerInfo != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (!wafer.IsEmpty && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) { targetStocker = target; break; } } if (targetStocker != null) break; } } else { targetStocker = target; break; } } } SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; if (CarrierManager.Instance.CheckNoCarrier(st.Module, 0)) { fims = st; break; } } if (targetStocker != null && fims != null) { switch (targetCarrierType.ToString()) { case "SD": _lstPlaceSideDummyStocker.Add(targetStocker); break; case "ED": _lstPlaceExtraDummyStockers.Add(targetStocker); break; case "P": _lstPlaceCurrentBatchStocker.Add(targetStocker); break; case "M1": _lstPlaceMonitor1Stocker.Add(targetStocker); break; case "M2": _lstPlaceMonitor2Stocker.Add(targetStocker); break; } if (_carrierRobot.Pick(targetStocker.Module, 0, Hand.Blade1)) { targetStocker.WaitTransfer(ModuleName.CarrierRobot); return; } } } } if (!_carrierRobot.IsAvailable) return; //place carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier != null && !carrier.IsEmpty && carrier.CarrierType == targetCarrierType) { var needPlace = false; if (pj.ProcessingState == EnumProcessingState.Charging) { var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); if (wafers != null && stockerInfo != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (stockerInfo.Item3.Any() && !stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) { needPlace = true; break; } } } } if (GetWaferCountRelatedToWaferRobot(targetWaferType) >= targetSlots.Count || CheckCarrierHasNoWafer(ModuleName.CarrierRobot, targetWaferType) || needPlace) { switch (targetCarrierType.ToString()) { case "SD": targetStockers = _lstPlaceSideDummyStocker; break; case "ED": targetStockers = _lstPlaceExtraDummyStockers; break; case "P": targetStockers = _lstPlaceCurrentBatchStocker; break; case "M1": targetStockers = _lstPlaceMonitor1Stocker; break; case "M2": targetStockers = _lstPlaceMonitor2Stocker; break; } SchedulerStocker targetStocker = null; foreach (var target in targetStockers) { if (CarrierManager.Instance.CheckNoCarrier(target.Module, 0) && carrier.InternalModuleName == target.Module) { if (pj.ProcessingState == EnumProcessingState.Charging) { var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); if (wafers != null && stockerInfo != null) { var hasWafer = false; foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (stockerInfo.Item3.Any() && stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) { hasWafer = true; break; } } if (!hasWafer) { targetStocker = target; break; } } } else { targetStocker = target; break; } } } if (targetStocker != null) { if (_carrierRobot.Place(targetStocker.Module, 0, Hand.Blade1)) { targetStocker.WaitTransfer(ModuleName.CarrierRobot); return; } } } } } private bool CheckCarrierCanPickFromStocker(ModuleName currentModule) { var currentWafers = WaferManager.Instance.GetWafers(currentModule); if (currentWafers != null && !currentWafers.Any(x => !x.IsEmpty)) { //空盒子 return false; } var carrierType = CarrierManager.Instance.GetCarrier(currentModule, 0).CarrierType; var ret = CheckHasPWafer(); var waferTypeSlots = GetWaferTypeSlots(); if (waferTypeSlots != null && waferTypeSlots.Count > 0) { Dictionary nextWaferTypeDic = new Dictionary(); int startIndex = -1; for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, waferTypeSlots[i].Item2)) { startIndex = i; continue; } //P wafer不够的情况 if (waferTypeSlots[i].Item1 == WaferType.P) { if (!ret.Item1) continue; else { if (i - startIndex > ret.Item2) continue; } } if (!nextWaferTypeDic.ContainsKey(waferTypeSlots[i].Item1)) nextWaferTypeDic.Add(waferTypeSlots[i].Item1, 0); nextWaferTypeDic[waferTypeSlots[i].Item1] += 1; if (nextWaferTypeDic.Count == _lstFIMSs.Count) break; if (i - startIndex >= _lstFIMSs.Count * 25) break; } Dictionary fimsWaferTypeDic = new Dictionary(); foreach (var fims in _lstFIMSs) { if (CarrierManager.Instance.CheckHasCarrier(fims.Module, 0)) { for (int i = 0; i < WaferManager.Instance.GetWafers(fims.Module).Length; i++) { var wafer = WaferManager.Instance.GetWafer(fims.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (!fimsWaferTypeDic.ContainsKey(wafer.WaferType)) fimsWaferTypeDic.Add(wafer.WaferType, 0); fimsWaferTypeDic[wafer.WaferType] += 1; } } } foreach (var type in nextWaferTypeDic.Keys) { if (carrierType.ToString() == type.ToString()) { if (type == WaferType.P || type == WaferType.M1 || type == WaferType.M2) { if (!fimsWaferTypeDic.ContainsKey(type) || nextWaferTypeDic[type] > fimsWaferTypeDic[type]) return true; } else if (type == WaferType.SD) { foreach (var wafer in currentWafers) { if (wafer.IsEmpty) continue; if (_sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) return true; } } else if (type == WaferType.ED) { foreach (var wafer in currentWafers) { if (wafer.IsEmpty) continue; if (_extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) return true; } } } } } return false; } private bool CheckCarrierCanPickFromFIMS(ModuleName currentModule) { var fimsWafers = WaferManager.Instance.GetWafers(currentModule); if (fimsWafers != null && !fimsWafers.Any(x => !x.IsEmpty)) { //空盒子 return true; } var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return true; var carrier = CarrierManager.Instance.GetCarrier(currentModule, 0); var carrierType = carrier.CarrierType; if (!pj.Stockers.Any(x => x.Item1 == carrier.InternalModuleName.ToString())) return true; var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); GetWaferSlotsAndWaferType(carrier, out var slots, out var waferType); Dictionary dummyWafers = new Dictionary(); if (waferType == WaferType.SD) dummyWafers = _sideDummyWafers; else if (waferType == WaferType.ED) dummyWafers = _extraDummyWafers; if (stockerInfo != null) { var hasWafer = false; foreach (var wafer in fimsWafers) { if (wafer == null || wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (stockerInfo.Item3.Any() && stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) { hasWafer = true; break; } if (!stockerInfo.Item3.Any()) { if (slots != null && slots.Count > 0) { for (int i = 0; i < slots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, slots[i])) { continue; } if ((wafer.WaferType == WaferType.SD || wafer.WaferType == WaferType.ED) && !dummyWafers.ContainsKey(wafer.InnerId.ToString())) continue; return false; } } } } if (hasWafer) return false; } return true; var ret = CheckHasPWafer(); var waferTypeSlots = GetWaferTypeSlots(); if (waferTypeSlots != null && waferTypeSlots.Count > 0) { List nextWaferTypeLst = new List(); int startIndex = -1; for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, waferTypeSlots[i].Item2)) { startIndex = i; continue; } //P wafer不够的情况 if (waferTypeSlots[i].Item1 == WaferType.P) { if (!ret.Item1) continue; else { if (i - startIndex > ret.Item2) continue; } } if (!nextWaferTypeLst.Contains(waferTypeSlots[i].Item1)) nextWaferTypeLst.Add(waferTypeSlots[i].Item1); if (nextWaferTypeLst.Count == _lstFIMSs.Count) break; if (i - startIndex >= _lstFIMSs.Count * 25) break; } foreach (var type in nextWaferTypeLst) { if (carrierType.ToString() == type.ToString()) { if (type == WaferType.P || type == WaferType.M1 || type == WaferType.M2) return false; else if (type == WaferType.SD) { foreach (var wafer in fimsWafers) { if (wafer.IsEmpty) continue; if (_sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) return false; } } else if (type == WaferType.ED) { foreach (var wafer in fimsWafers) { if (wafer.IsEmpty) continue; if (_extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) return false; } } } } } return true; } private bool CheckCarrierCanPlaceToStocker(ModuleName currentModule) { var fimsWafers = WaferManager.Instance.GetWafers(currentModule); if (fimsWafers != null && !fimsWafers.Any(x => !x.IsEmpty)) { //空盒子 return true; } var carrierType = CarrierManager.Instance.GetCarrier(currentModule, 0).CarrierType; var ret = CheckHasPWafer(); var waferTypeSlots = GetWaferTypeSlots(); if (waferTypeSlots != null && waferTypeSlots.Count > 0) { List nextWaferTypeLst = new List(); int startIndex = -1; for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(_pm1.Module, waferTypeSlots[i].Item2)) { startIndex = i; continue; } //P wafer不够的情况 if (waferTypeSlots[i].Item1 == WaferType.P) { if (!ret.Item1) continue; else { if (i - startIndex > ret.Item2) continue; } } if (!nextWaferTypeLst.Contains(waferTypeSlots[i].Item1)) nextWaferTypeLst.Add(waferTypeSlots[i].Item1); if (nextWaferTypeLst.Count == _lstFIMSs.Count) break; if (i - startIndex >= _lstFIMSs.Count * 25) break; } foreach (var type in nextWaferTypeLst) { if (carrierType.ToString() == type.ToString()) { if (type == WaferType.P || type == WaferType.M1 || type == WaferType.M2) return false; else if (type == WaferType.SD) { foreach (var wafer in fimsWafers) { if (wafer.IsEmpty) continue; if (_sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) return false; } } else if (type == WaferType.ED) { foreach (var wafer in fimsWafers) { if (wafer.IsEmpty) continue; if (_extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) return false; } } } } } return true; } private void MonitorCarrierRobotPickFIMSTask() { if (!_carrierRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return; //pick var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier != null && carrier.IsEmpty) { SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!fimsDevice.IsUnloadCompleted) continue; if (CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) { carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null) { if (pj.ProcessingState == EnumProcessingState.Discharging) { //discharge if (!CheckCarrierHasEmptySlot(st.Module)) { fims = st; break; } if (!CheckModuleHasWaferInWaferRobotAndPM(carrier.InternalModuleName)) { fims = st; break; } } else if (pj.ProcessingState == EnumProcessingState.Charging) { //charge GetWaferSlotsAndWaferType(carrier, out List slots, out WaferType waferType); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); var wafers = WaferManager.Instance.GetWafers(st.Module); if (wafers != null && stockerInfo != null) { bool isEmpty = true; foreach (var wafer in wafers) { if (!wafer.IsEmpty) { if (stockerInfo.Item3.Any()) { if (stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) { isEmpty = false; break; } } else { if (waferType == WaferType.P || waferType == WaferType.M1 || waferType == WaferType.M2) { isEmpty = false; break; } else if (waferType == WaferType.SD && _sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) { isEmpty = false; break; } else if (waferType == WaferType.ED && _extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) { isEmpty = false; break; } } } } if (isEmpty) { fims = st; break; } } if (slots != null && GetWaferCountRelatedToWaferRobot(waferType, false) >= slots.Count) { fims = st; break; } } else if (pj.ProcessingState == EnumProcessingState.Processing) { foreach (var bf in pj.Stockers) { if (CarrierManager.Instance.CheckHasCarrier(bf.Item1, 0)) continue; if (bf.Item1 == carrier.InternalModuleName.ToString()) { fims = st; break; } } } } } } if (fims != null) { if (_carrierRobot.Pick(fims.Module, 0, Hand.Blade1)) { fims.WaitTransfer(ModuleName.CarrierRobot); return; } } } if (!_carrierRobot.IsAvailable) return; } private void MonitorCarrierRobotPlaceFIMSTaskInCharge() { if (!_carrierRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return; var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); //place carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); if (carrier != null && !carrier.IsEmpty && stockerInfo != null) { SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!fimsDevice.IsUnloadCompleted) continue; if (CarrierManager.Instance.CheckNoCarrier(st.Module, 0)) { GetWaferSlotsAndWaferType(carrier, out List slots, out WaferType waferType); if (slots != null && GetWaferCountRelatedToWaferRobot(waferType, false) <= slots.Count) { var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == waferType) { if (pj.ProcessingState == EnumProcessingState.Charging && stockerInfo.Item3.Any() && !stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) continue; fims = st; break; } } } if (fims != null) break; } } if (fims != null) { if (_carrierRobot.Place(fims.Module, 0, Hand.Blade1)) { fims.WaitTransfer(ModuleName.CarrierRobot); return; } } } } private void MonitorCarrierRobotPlaceFIMSTaskInDischarge() { if (!_carrierRobot.IsAvailable) return; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return; var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); //place carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier != null && !carrier.IsEmpty && CheckCarrierHasEmptySlot(ModuleName.CarrierRobot) && CheckModuleHasWaferInWaferRobotAndPM(carrier.InternalModuleName)) { SchedulerFIMS fims = null; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; // check FIMS var fimsDevice = DEVICE.GetDevice($"PM1.{st.Module}"); if (!fimsDevice.IsUnloadCompleted) continue; if (CarrierManager.Instance.CheckNoCarrier(st.Module, 0)) { fims = st; break; } } if (fims != null) { if (_carrierRobot.Place(fims.Module, 0, Hand.Blade1)) { fims.WaitTransfer(ModuleName.CarrierRobot); return; } } } } private bool CheckCarrierHasNoWafer(ModuleName module, WaferType waferType) { bool isEmpty = true; var wafers = WaferManager.Instance.GetWafers(module); if (wafers != null) { foreach (var wafer in wafers) { if (!wafer.IsEmpty) { if (waferType == WaferType.P || waferType == WaferType.M1 || waferType == WaferType.M2) { isEmpty = false; break; } else if (waferType == WaferType.SD && _sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) { isEmpty = false; break; } else if (waferType == WaferType.ED && _extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) { isEmpty = false; break; } } } } return isEmpty; } private Dictionary GetDummyWafers(List targetStockers, int needWaferCount, WaferType waferType) { Dictionary dummyWafers = new Dictionary(); float useCountMin = GetWaferUseCountMin(targetStockers, waferType); float useCountMax = GetWaferUseCountMax(targetStockers, waferType); int range = (int)(useCountMax - useCountMin); var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), waferType.ToString())); for (int i = 0; i <= range; i++) { foreach (var target in targetStockers) { var carrier = CarrierManager.Instance.GetCarrier(target.Module); if (carrier == null || carrier.IsEmpty || carrier.CarrierType != targetCarrierType) continue; var wafers = WaferManager.Instance.GetWafers(target.Module); if (wafers != null) { foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; if (wafer.UseCount <= useCountMin && dummyWafers.Count() < needWaferCount) { if (!dummyWafers.ContainsKey(wafer.InnerId.ToString())) dummyWafers.Add(wafer.InnerId.ToString(), wafer.OriginStation); } } } } if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier.CarrierType == targetCarrierType) { var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); if (wafers != null) { foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; if (wafer.UseCount <= useCountMin && dummyWafers.Count() < needWaferCount) { if (!dummyWafers.ContainsKey(wafer.InnerId.ToString())) dummyWafers.Add(wafer.InnerId.ToString(), wafer.OriginStation); } } } } } foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (!carrier.IsEmpty && carrier.CarrierType == targetCarrierType) { var wafers = WaferManager.Instance.GetWafers(fims.Module); if (wafers != null) { foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; if (wafer.UseCount <= useCountMin && dummyWafers.Count() < needWaferCount) { if (!dummyWafers.ContainsKey(wafer.InnerId.ToString())) dummyWafers.Add(wafer.InnerId.ToString(), wafer.OriginStation); } } } } } if (dummyWafers.Count() < needWaferCount) useCountMin++; else break; } return dummyWafers; } private float GetWaferUseCountMin(List targetStockers, WaferType waferType) { float iUseCountMin = 10000; foreach (var target in targetStockers) { var wafers = WaferManager.Instance.GetWafers(target.Module); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount < iUseCountMin) iUseCountMin = wafer.UseCount; } } if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount < iUseCountMin) iUseCountMin = wafer.UseCount; } } foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var wafers = WaferManager.Instance.GetWafers(fims.Module); foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount < iUseCountMin) iUseCountMin = wafer.UseCount; } } return iUseCountMin; } private float GetWaferUseCountMax(List targetStockers, WaferType waferType) { float iUseCountMax = 0; foreach (var target in targetStockers) { var wafers = WaferManager.Instance.GetWafers(target.Module); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount >= iUseCountMax) iUseCountMax = wafer.UseCount; } } if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var wafers = WaferManager.Instance.GetWafers(ModuleName.CarrierRobot); foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount >= iUseCountMax) iUseCountMax = wafer.UseCount; } } foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var wafers = WaferManager.Instance.GetWafers(fims.Module); foreach (var wafer in wafers) { if (wafer.IsEmpty || wafer.WaferType != waferType) continue; if (wafer.UseCount >= iUseCountMax) iUseCountMax = wafer.UseCount; } } return iUseCountMax; } private ModuleName GetModuleNameForNextWafer(WaferType waferType) { ModuleName module = ModuleName.System; bool hasEmptyFims = false; foreach (var fims in _lstFIMSs) { if (CarrierManager.Instance.CheckNoCarrier(fims.Module, 0)) { hasEmptyFims = true; break; } } if (!hasEmptyFims) return module; if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 0)) { module = (ModuleName)WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 0).OriginStation; } else if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 1)) { module = (ModuleName)WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 1).OriginStation; } else if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 2)) { module = (ModuleName)WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 2).OriginStation; } else if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 3)) { module = (ModuleName)WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 3).OriginStation; } else if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 4)) { module = (ModuleName)WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 4).OriginStation; } else { if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { for (int i = 0; i < SC.GetValue($"Boat.SlotCount"); i++) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType == waferType) { module = (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation; break; } } } else { for (int i = SC.GetValue($"Boat.SlotCount") - 1; i >= 0; i--) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType == waferType) { module = (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation; break; } } } } //下一片要放回的cassette已经在fims上 bool isCarrierAlreadyPicked = false; foreach (var fims in _lstFIMSs) { if (!CarrierManager.Instance.CheckHasCarrier(fims.Module, 0)) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module); if (carrier != null && carrier.InternalModuleName == module) { isCarrierAlreadyPicked = true; } } if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot); if (carrier != null && carrier.InternalModuleName == module) { isCarrierAlreadyPicked = true; } } if (isCarrierAlreadyPicked) { if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { for (int i = 0; i < SC.GetValue($"Boat.SlotCount"); i++) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType == waferType && (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation != module) { module = (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation; break; } } } else { for (int i = SC.GetValue($"Boat.SlotCount") - 1; i >= 0; i--) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; if (wafer.WaferType == waferType && (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation != module) { module = (ModuleName)WaferManager.Instance.GetWafer(_pm1.Module, i).OriginStation; break; } } } } return module; } private int GetWaferCountRelatedToWaferRobot(WaferType waferType, bool includeFims = true) { int count = 0; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.IsEmptyLayout) return count; if (includeFims) { foreach (var fims in _lstFIMSs) { if (CarrierManager.Instance.CheckNoCarrier(fims.Module, 0)) continue; var wafers = WaferManager.Instance.GetWafers(fims.Module); var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == waferType) { if (pj.ProcessingState == EnumProcessingState.Charging && stockerInfo != null && stockerInfo.Item3.Any() && !stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) continue; if (waferType == WaferType.P || waferType == WaferType.M1 || waferType == WaferType.M2) count++; else if (waferType == WaferType.SD && _sideDummyWafers.ContainsKey(wafer.InnerId.ToString())) count++; else if (waferType == WaferType.ED && _extraDummyWafers.ContainsKey(wafer.InnerId.ToString())) count++; } } } } for (int i = 0; i < WaferManager.Instance.GetWafers(ModuleName.WaferRobot).Length; i++) { var wafer = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, i); if (!wafer.IsEmpty && wafer.WaferType == waferType) { var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == ((ModuleName)wafer.OriginStation).ToString()); if (pj.ProcessingState == EnumProcessingState.Charging && stockerInfo != null && stockerInfo.Item3.Any() && !stockerInfo.Item3.Any(x => x == wafer.OriginSlot)) continue; count++; } } for (int i = 0; i < WaferManager.Instance.GetWafers(_pm1.Module).Length; i++) { var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (!wafer.IsEmpty && wafer.WaferType == waferType) count++; } return count; } private void GetWaferSlotsAndWaferType(CarrierInfo carrier, out List slots, out WaferType waferType) { slots = null; waferType = WaferType.None; if (carrier != null && !carrier.IsEmpty) { switch (carrier.CarrierType) { case CarrierType.SD: slots = _sideDummySlots; waferType = WaferType.SD; break; case CarrierType.ED: slots = _extraDummySlots; waferType = WaferType.ED; break; case CarrierType.M1: slots = _monitor1Slots; waferType = WaferType.M1; break; case CarrierType.M2: slots = _monitor2Slots; waferType = WaferType.M2; break; case CarrierType.P: slots = _productSlots; waferType = WaferType.P; break; } } } private bool CheckCarrierHasEmptySlot(ModuleName module) { bool hasEmpty = false; var wafers = WaferManager.Instance.GetWafers(module); if (wafers != null) { foreach (var wafer in wafers) { if (wafer.IsEmpty) { hasEmpty = true; break; } } } return hasEmpty; } private bool CheckCarrierNoHasEmptySlot(ModuleName module) { bool noHasEmpty = true; var wafers = WaferManager.Instance.GetWafers(module); if (wafers != null) { foreach (var wafer in wafers) { if (!wafer.IsEmpty) { noHasEmpty = false; break; } } } return noHasEmpty; } private bool CheckModuleHasWaferInWaferRobotAndPM(ModuleName module) { bool isHaveWafer = false; var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1).ToList(); if (wafers != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) continue; if (wafer.OriginStation == (int)module) { isHaveWafer = true; break; } } } wafers = WaferManager.Instance.GetWafers(ModuleName.WaferRobot).ToList(); if (wafers != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) continue; if (wafer.OriginStation == (int)module) { isHaveWafer = true; break; } } } return isHaveWafer; } private bool CheckWaferStatus(List>> useStockers, bool isNeedCheckMonitor, bool isNeedCheckP, out string reason) { reason = string.Empty; if (SC.GetValue("System.IsCycleMode")) { foreach (var module in Singleton.Instance.Modules.Keys) { if (!ModuleHelper.IsStocker(module) || !useStockers.Any(x => x.Item1 == module.ToString())) continue; var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; wafer.ProcessState = EnumWaferProcessStatus.Idle; } } } else { foreach (var module in Singleton.Instance.Modules.Keys) { if (!ModuleHelper.IsStocker(module) || !useStockers.Any(x => x.Item1 == module.ToString())) continue; var stockerInfo = useStockers.FirstOrDefault(x => x.Item1 == module.ToString()); var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null || stockerInfo == null) continue; if (SC.GetValue("System.EnableWarningFailedWafer")) { if (wafers.ToList().Any(x => x.ProcessState == EnumWaferProcessStatus.Failed)) { reason = $"{module} has failed wafers."; return false; } } foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; if (wafer.ProcessState != EnumWaferProcessStatus.Idle && SC.GetValue("System.EnableWarningWaferProcessState") && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) { if (wafer.WaferType == WaferType.P && isNeedCheckP) { reason = $"{(ModuleName)wafer.OriginStation} {wafer.WaferType} wafer already completed process."; return false; } if (isNeedCheckMonitor) { if (wafer.WaferType == WaferType.M2 || wafer.WaferType == WaferType.M || wafer.WaferType == WaferType.M1) { reason = $"{(ModuleName)wafer.OriginStation} {wafer.WaferType} wafer already completed process."; return false; } } } if (wafer.WaferType == WaferType.ED || wafer.WaferType == WaferType.SD) wafer.ProcessState = EnumWaferProcessStatus.Idle; } } } return true; } private Tuple CheckHasPWafer() { var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null || pj.Stockers == null) return Tuple.Create(false, 0); int countP = 0; foreach (var stocker in pj.Stockers) { var wafers = WaferManager.Instance.GetWafersByOriginalPosition(ModuleHelper.Converter(stocker.Item1)); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == WaferType.P && wafer.Station != (int)ModuleName.PM1) { countP++; } } } return Tuple.Create(countP > 0, countP); } //返回下一片要放的wafer的slot和type private int GetNextWaferSlot(out WaferType waferType) { var waferTypeSlots = GetWaferTypeSlots(); waferType = WaferType.None; var ret = CheckHasPWafer(); int slot = -1; if (waferTypeSlots != null) { for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(ModuleName.PM1, waferTypeSlots[i].Item2)) { continue; } //针对P wafer不够的情况 if (!ret.Item1 && waferTypeSlots[i].Item1 == WaferType.P) continue; slot = waferTypeSlots[i].Item2; waferType = waferTypeSlots[i].Item1; break; } } return slot; } //返回下一片要放的wafer的type,需要除去当前在机械手上的wafer private WaferType GetNextWaferType() { var ret = CheckHasPWafer(); var waferTypeSlots = GetWaferTypeSlots(); WaferType waferType = WaferType.None; if (waferTypeSlots != null) { for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(ModuleName.PM1, waferTypeSlots[i].Item2)) { continue; } var wafer0 = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 0); var wafer1 = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 1); if (i < waferTypeSlots.Count && wafer0 != null && !wafer0.IsEmpty && wafer0.WaferType == waferTypeSlots[i].Item1) i++; if (i < waferTypeSlots.Count && wafer1 != null && !wafer1.IsEmpty && wafer1.WaferType == waferTypeSlots[i].Item1) i++; //机械手wafer放过去就放满了 if (i >= waferTypeSlots.Count) { break; } //针对P wafer不够的情况 if (!ret.Item1 && waferTypeSlots[i].Item1 == WaferType.P) continue; waferType = waferTypeSlots[i].Item1; break; } } return waferType; } private ModuleName GetCurrentTransferFims() { ModuleName currentFims = ModuleName.System; foreach (var st in _lstFIMSs) { if (!st.IsAvailable) continue; if (!CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var carrier = CarrierManager.Instance.GetCarrier(st.Module, 0); if (carrier != null && !carrier.IsEmpty) { bool hasWafer = false; var wafers = WaferManager.Instance.GetWafers(st.Module); if (wafers != null) { foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) continue; if (!wafer.IsEmpty) { hasWafer = true; break; } } } if (hasWafer && CheckCarrierHasWaferInPM(carrier.InternalModuleName)) { currentFims = st.Module; break; }; } } return currentFims; } private List GetWaferSlots(out WaferType waferType) { var waferTypeSlots = GetWaferTypeSlots(); waferType = WaferType.None; var slots = new List(); if (waferTypeSlots != null) { List> fimsWaferInforLst = new List>(); foreach (var st in _lstFIMSs) { if (!CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; var fimsWafers = WaferManager.Instance.GetWafers(st.Module); int waferCountFIMS = 0; WaferType waferTypeFIMS = WaferType.None; if (fimsWafers != null) { foreach (var fimsWafer in fimsWafers) { if (!fimsWafer.IsEmpty) { waferTypeFIMS = fimsWafer.WaferType; if (fimsWafer.WaferType == WaferType.P || fimsWafer.WaferType == WaferType.M1 || fimsWafer.WaferType == WaferType.M2) { waferCountFIMS++; } else if (fimsWafer.WaferType == WaferType.SD && _sideDummyWafers.ContainsKey(fimsWafer.InnerId.ToString())) { waferCountFIMS++; } else if (fimsWafer.WaferType == WaferType.ED && _extraDummyWafers.ContainsKey(fimsWafer.InnerId.ToString())) { waferCountFIMS++; } } } } if (waferCountFIMS > 0) fimsWaferInforLst.Add(Tuple.Create(st.Module, waferTypeFIMS, waferCountFIMS)); } //两个FIMS都有Carrier,直接返回 if (_lstFIMSs.Count == fimsWaferInforLst.Count) return slots; //FIMS有空的,才继续 int startIndex = 0; for (int i = 0; i < waferTypeSlots.Count; i++) { if (WaferManager.Instance.CheckHasWafer(ModuleName.PM1, waferTypeSlots[i].Item2)) { continue; } var wafer0 = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 0); var wafer1 = WaferManager.Instance.GetWafer(ModuleName.WaferRobot, 1); if (i < waferTypeSlots.Count && wafer0 != null && !wafer0.IsEmpty && wafer0.WaferType == waferTypeSlots[i].Item1) i++; if (i >= waferTypeSlots.Count) break; if (i < waferTypeSlots.Count && wafer1 != null && !wafer1.IsEmpty && wafer1.WaferType == waferTypeSlots[i].Item1) i++; if (i >= waferTypeSlots.Count) break; if (fimsWaferInforLst.Count > 0) { var fimsWaferInfor = fimsWaferInforLst.FirstOrDefault(x => x.Item2 == waferTypeSlots[i].Item1); if (fimsWaferInfor != null) { for (; i < waferTypeSlots.Count;) { if (i >= waferTypeSlots.Count) break; if (waferTypeSlots[i].Item1 == fimsWaferInfor.Item2) i++; else break; } } } if (i >= waferTypeSlots.Count) { i = waferTypeSlots.Count - 1; } startIndex = i; waferType = waferTypeSlots[i].Item1; break; } for (int i = startIndex; i < waferTypeSlots.Count; i++) { if (waferTypeSlots[i].Item1 != waferType) { break; } slots.Add(waferTypeSlots[i].Item2); } } return slots; } private List GetWaferSlots(WaferType waferType) { var slots = new List(); var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return null; if (!RecipeParser.LayoutRecipeParse(pj.LayoutRecipe, ModuleName.PM1.ToString(), out RecipeLayoutEntityNormal layoutRecipeDataNormal, out RecipeLayoutEntityExpert layoutRecipeDataExpert, out string reason)) { //Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Load layout recipe {pj.LayoutRecipe} failed, {reason}"); return null; } switch (waferType) { case WaferType.SD: return pj.SideDummySlots; case WaferType.ED: return pj.ExtraDummySlots; case WaferType.M1: return pj.Monitor1Slots; case WaferType.M2: return pj.Monitor2Slots; case WaferType.P: return pj.ProductSlots; } return null; } private List GetWaferSlots(RecipeLayoutEntityExpert layoutRecipeDataExpert, WaferType waferType) { var slots = new List(); if (layoutRecipeDataExpert == null) return null; var type = ""; switch (waferType) { case WaferType.SD: type = "sd"; break; case WaferType.ED: type = "fd"; break; case WaferType.M1: type = "m1"; break; case WaferType.M2: type = "m2"; break; case WaferType.P: type = "pd"; break; } if (layoutRecipeDataExpert != null) { for (int i = 0; i < layoutRecipeDataExpert.Items.Count; i++) { if (layoutRecipeDataExpert.Items[i].ToLower() == type) { slots.Add(i); } } if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { slots.Sort((x, y) => -x.CompareTo(y));//降序 } else { slots.Sort((x, y) => x.CompareTo(y));//升序 } } return slots; } #region charge rule private bool CheckChargeRule(ProcessJobInfo pj, out bool waferShort, bool needCheckPWafer, bool needCheckMWafer, out string reason) { waferShort = false; //needCheckPWafer = false; reason = string.Empty; if (!RecipeParser.LayoutRecipeParse(pj.LayoutRecipe, ModuleName.PM1.ToString(), out RecipeLayoutEntityNormal layoutRecipeDataNormal, out RecipeLayoutEntityExpert layoutRecipeDataExpert, out reason)) { //Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Load layout recipe {pj.LayoutRecipe} failed, {reason}"); return false; } if (!CheckLayoutParameter(layoutRecipeDataNormal, out reason)) { return false; } int iCassetteSlotCount = SC.GetValue("System.CassetteSlotCount"); if (iCassetteSlotCount == 0) { reason = "System.CassetteSlotCount not valid"; return false; } int iSlotCount = SC.GetValue($"Boat.SlotCount"); var productSlots = GetWaferSlots(layoutRecipeDataExpert, WaferType.P); var monitor1Slots = GetWaferSlots(layoutRecipeDataExpert, WaferType.M1); var monitor2Slots = GetWaferSlots(layoutRecipeDataExpert, WaferType.M2); var sideDummySlots = GetWaferSlots(layoutRecipeDataExpert, WaferType.SD); var extraDummySlots = GetWaferSlots(layoutRecipeDataExpert, WaferType.ED); int iNeedCassetteNum; var temp = (float)productSlots.Count / iCassetteSlotCount; iNeedCassetteNum = (int)Math.Ceiling(temp); int iCurrentCassetteNum = GetCurrentCassetteNum(pj, WaferType.P); int iDummyUpper = int.Parse(layoutRecipeDataNormal.DummyUpperSlot); int iDummyLower = int.Parse(layoutRecipeDataNormal.DummyLowerSlot); int iNeedPWaferNum = productSlots.Count; int iNeedM1WaferNum = monitor1Slots.Count; int iNeedM2WaferNum = monitor2Slots.Count; int iNeedSDWaferNum = sideDummySlots.Count; int iNeedEDWaferNum = extraDummySlots.Count; int iCurrentPWaferNum = GetCurrentWaferNum(pj, WaferType.P, out bool pSlotSelect); int iCurrentSDWaferNum = GetCurrentDummyWaferNum(WaferType.SD); int iCurrentM1WaferNum = GetCurrentWaferNum(pj, WaferType.M1, out bool m1SlotSelect); int iCurrentM2WaferNum = GetCurrentWaferNum(pj, WaferType.M2, out bool m2SlotSelect); int iCurrentEDWaferNum = GetCurrentDummyWaferNum(WaferType.ED); //if (iNeedMWaferNum > iCurrentMWaferNum) //{ // reason = "monitor wafer are short."; // return false; //} //if (iNeedSDWaferNum > iCurrentSDWaferNum) //{ // reason = "dummy wafer are short."; // return false; //} //if (iNeedEDWaferNum > iCurrentEDWaferNum) //{ // reason = "extra dummy wafer are short."; // return false; //} if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { sideDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 extraDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 monitor1Slots.Sort((x, y) => -x.CompareTo(y));//降序 monitor2Slots.Sort((x, y) => -x.CompareTo(y));//降序 productSlots.Sort((x, y) => -x.CompareTo(y));//降序 } else { sideDummySlots.Sort((x, y) => x.CompareTo(y));//升序 extraDummySlots.Sort((x, y) => x.CompareTo(y));//升序 monitor1Slots.Sort((x, y) => x.CompareTo(y));//升序 monitor2Slots.Sort((x, y) => x.CompareTo(y));//升序 productSlots.Sort((x, y) => x.CompareTo(y));//升序 } pj.SideDummySlots = sideDummySlots; pj.ExtraDummySlots = extraDummySlots; pj.Monitor1Slots = monitor1Slots; pj.Monitor2Slots = monitor2Slots; pj.ProductSlots = productSlots; bool bM1Short = false; bool bM2Short = false; if (needCheckMWafer) { bM1Short = GetRemainWaferNum(pj, WaferType.M1) < 0 && monitor1Slots.Count > 0; bM2Short = GetRemainWaferNum(pj, WaferType.M2) < 0 && monitor2Slots.Count > 0; if (monitor1Slots.Count > 0 && m1SlotSelect && iCurrentM1WaferNum != monitor1Slots.Count) { reason = $"layout recipe M1 wafer number={iCurrentM1WaferNum}, current M1 wafer number={monitor1Slots.Count}, not match"; return false; } if (monitor2Slots.Count > 0 && m2SlotSelect && iCurrentM2WaferNum != monitor2Slots.Count) { reason = $"layout recipe M2 wafer number={iCurrentM2WaferNum}, current M2 wafer number={monitor2Slots.Count}, not match"; return false; } if (bM1Short) { reason = "M1 wafer are short"; return false; } if (bM2Short) { reason = "M2 wafer are short"; return false; } } if (!needCheckPWafer) return true; if (iNeedPWaferNum > iCurrentPWaferNum) { reason = "layout recipe production wafer number greater than current production wafer number"; return false; } if (pSlotSelect && iNeedPWaferNum != iCurrentPWaferNum) { reason = $"layout recipe production wafer number={iNeedPWaferNum}, current production wafer number={iCurrentPWaferNum}, not match"; return false; } //下面charge rule暂时不判断 return true; //if (layoutRecipeDataNormal.ProductPosition.ToLower() == "slot") //{ // if (iNeedPWaferNum <= iCurrentPWaferNum) // { // return true; // } // else // { // reason = "production wafer insufficiency productPos set to slot"; // return false; // } //} string strWhenCassetteAreShort = layoutRecipeDataNormal.WhenCassetteInBatchAreShort; string strWhenPWaferShort = layoutRecipeDataNormal.WhenPWaferShort; string strWhenWaferInCassetteAreShort = layoutRecipeDataNormal.WhenWaferInCassetteAreShort; string strWhenEDAreShort = layoutRecipeDataNormal.WhenEDAreShort; bool bSDMove = layoutRecipeDataNormal.SDRule == "Move"; bool bBoatSupplyED = layoutRecipeDataNormal.RuleOfSpaceInBoat == "SupplyED" && !bSDMove; bool bEDShort = false; List adjustedSlot = new List(); for (int i = 0; i < layoutRecipeDataExpert.Items.Count; i++) { adjustedSlot.Add(layoutRecipeDataExpert.Items[i]); } bool bCassetteSuppleED; bool bWaferSuppleED; if (iNeedPWaferNum > iCurrentPWaferNum) { // 先判断cassette是否充足,然后再判断P wafers是否充足 if (iNeedCassetteNum > iCurrentCassetteNum) { if (strWhenCassetteAreShort != "LeaveAs" && strWhenCassetteAreShort != "SupplyED") { reason = "cassette in batch are short"; return true; } else { bCassetteSuppleED = strWhenCassetteAreShort == "SupplyED"; // 重新计算需要的P wafers iNeedPWaferNum = iNeedPWaferNum - (iNeedCassetteNum - iCurrentCassetteNum) * iCassetteSlotCount; // 判断P wafers是否充足 if (iNeedPWaferNum > iCurrentPWaferNum) { // 只有在when P wafer short == leave as 的时候 when wafer in cassette are short 才执行判断 if (strWhenPWaferShort == "LeaveAs") { if (strWhenWaferInCassetteAreShort != "LeaveAs" && strWhenWaferInCassetteAreShort != "SupplyED") { reason = "wafer in cassette are short"; return true; } else { bWaferSuppleED = strWhenWaferInCassetteAreShort == "SupplyED"; bEDShort = CassetteShortWaferInCassetteShort(pj, ref adjustedSlot, ref iCurrentEDWaferNum, layoutRecipeDataNormal, layoutRecipeDataExpert, bCassetteSuppleED, bWaferSuppleED); } } else { bEDShort = CassetteShortPWaferShort(pj, ref adjustedSlot, ref iCurrentEDWaferNum, layoutRecipeDataNormal, layoutRecipeDataExpert, iCurrentPWaferNum, bCassetteSuppleED); } } else { bWaferSuppleED = false; bEDShort = CassetteShortWaferInCassetteShort(pj, ref adjustedSlot, ref iCurrentEDWaferNum, layoutRecipeDataNormal, layoutRecipeDataExpert, bCassetteSuppleED, bWaferSuppleED); } } } else { // 只有在when P wafer short == leave as 的时候 when wafer in cassette are short 才执行判断 if (strWhenPWaferShort == "LeaveAs") { if (strWhenWaferInCassetteAreShort == "LeaveAs") { } else if (strWhenWaferInCassetteAreShort == "SupplyED") { bCassetteSuppleED = false; bWaferSuppleED = true; bEDShort = CassetteShortWaferInCassetteShort(pj, ref adjustedSlot, ref iCurrentEDWaferNum, layoutRecipeDataNormal, layoutRecipeDataExpert, bCassetteSuppleED, bWaferSuppleED); } else { reason = "wafer in cassette are short"; return true; } } else { bWaferSuppleED = false; bEDShort = CassetteShortPWaferShort(pj, ref adjustedSlot, ref iCurrentEDWaferNum, layoutRecipeDataNormal, layoutRecipeDataExpert, iCurrentPWaferNum, bWaferSuppleED); } } } if (bSDMove) { for (int i = iDummyUpper; i < iSlotCount - iDummyLower; i++) { if (adjustedSlot[i] != "") { for (int j = 0; j < iDummyUpper; j++) { adjustedSlot[i - j - 1] = "dummy"; } break; } } for (int i = iSlotCount - iDummyLower - 1; i > iDummyUpper; i--) { if (adjustedSlot[i] != "") { for (int j = 0; j < iDummyLower; j++) { adjustedSlot[i + j + 1] = "dummy"; } break; } } } else { if (bBoatSupplyED) { for (int i = iDummyUpper; i < iSlotCount - iDummyLower; i++) { if (iCurrentEDWaferNum > 0) { if (adjustedSlot[i] == "") { adjustedSlot[i] = "extradummy"; iCurrentEDWaferNum--; } } else { bEDShort = true; break; } } } for (int i = 0; i < iDummyUpper; i++) { adjustedSlot[i] = "dummy"; } for (int i = iSlotCount - iDummyLower; i < iSlotCount; i++) { adjustedSlot[i] = "dummy"; } } if (bEDShort) { switch (strWhenEDAreShort) { case "WarningAndContinue": case "AbortWhenError": reason = "extradummy wafer are short"; break; case "LeaveAs": bEDShort = false; break; } } sideDummySlots.Clear(); extraDummySlots.Clear(); monitor1Slots.Clear(); monitor2Slots.Clear(); productSlots.Clear(); for (int i = 0; i < adjustedSlot.Count; i++) { if (adjustedSlot[i].ToLower() == "dummy" && iCurrentSDWaferNum > 0) { sideDummySlots.Add(i); iCurrentSDWaferNum--; } if (adjustedSlot[i].ToLower() == "extradummy") { extraDummySlots.Add(i); } if (adjustedSlot[i].ToLower() == "monitor1" && iCurrentM1WaferNum > 0) { monitor1Slots.Add(i); iCurrentM1WaferNum--; } if (adjustedSlot[i].ToLower() == "monitor2" && iCurrentM2WaferNum > 0) { monitor2Slots.Add(i); iCurrentM2WaferNum--; } if (adjustedSlot[i].ToLower() == "pd") { productSlots.Add(i); } } bM1Short = (GetCurrentWaferNum(pj, WaferType.M1, out m1SlotSelect) < monitor1Slots.Count) || monitor1Slots.Count == 0; bM2Short = (GetCurrentWaferNum(pj, WaferType.M2, out m2SlotSelect) < monitor2Slots.Count) || monitor2Slots.Count == 0; bool bSDShort = (GetCurrentWaferNum(pj, WaferType.SD, out bool sdSlotSelect) < sideDummySlots.Count) || sideDummySlots.Count == 0; if (SC.GetValue("System.IsLeaveAsAllWaferWhenWaferShort")) bEDShort = bM1Short = bM2Short = bSDShort = false; waferShort = bEDShort || bM1Short || bM2Short || bSDShort; if (bM1Short || bM2Short) { if (reason == string.Empty) { if (bSDShort) { reason = "dummy wafer and monitor wafer are short"; } else { reason = "monitor wafer are short"; } } else { if (bSDShort) { reason = "extradummy wafer,monitor wafer and dummy wafer are short"; } else { reason = "extradummy wafer and dummy wafer are short"; } } } else { if (reason == string.Empty) { if (bSDShort) { reason = "dummy wafer are short"; } } else { if (bSDShort) { reason = "extradummy wafer and dummy wafer are short"; } } } if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { sideDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 extraDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 monitor1Slots.Sort((x, y) => -x.CompareTo(y));//降序 monitor2Slots.Sort((x, y) => -x.CompareTo(y));//降序 productSlots.Sort((x, y) => -x.CompareTo(y));//降序 } else { sideDummySlots.Sort((x, y) => x.CompareTo(y));//升序 extraDummySlots.Sort((x, y) => x.CompareTo(y));//升序 monitor1Slots.Sort((x, y) => x.CompareTo(y));//升序 monitor2Slots.Sort((x, y) => x.CompareTo(y));//升序 productSlots.Sort((x, y) => x.CompareTo(y));//升序 } pj.SideDummySlots = sideDummySlots; pj.ExtraDummySlots = extraDummySlots; pj.Monitor1Slots = monitor1Slots; pj.Monitor2Slots = monitor2Slots; pj.ProductSlots = productSlots; return true; } private bool CheckLayoutParameter(RecipeLayoutEntityNormal layoutRecipeDataNormal, out string reason) { reason = string.Empty; if (string.IsNullOrEmpty(layoutRecipeDataNormal.DummyUpperSlot)) { reason = "DummyUpper is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.DummyLowerSlot)) { reason = "DummyLower is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.CenteringSlotPosition)) { reason = "CenteringSlotPosition is null"; return false; } //if (string.IsNullOrEmpty(layoutRecipeDataNormal.Pitch)) //{ // reason = "Pitch is null"; // return false; //} if (string.IsNullOrEmpty(layoutRecipeDataNormal.ProductPosition)) { reason = "ProductPosition is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.MonitorPosition)) { reason = "MonitorPosition is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.WhenCassetteInBatchAreShort)) { reason = "WhenCassetteInBatchAreShort is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.WhenPWaferShort)) { reason = "WhenPWaferShort is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.WhenWaferInCassetteAreShort)) { reason = "WhenWaferInCassetteAreShort is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.WhenEDAreShort)) { reason = "WhenEDAreShort is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.SDRule)) { reason = "SDRule is null"; return false; } if (string.IsNullOrEmpty(layoutRecipeDataNormal.RuleOfSpaceInBoat)) { reason = "RuleOfSpaceInBoat is null"; return false; } return true; } private int GetCurrentCassetteNum(ProcessJobInfo pj, WaferType targetWaferType) { int iCassetteNum = 0; var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); foreach (var target in _lstTotlaStockers) { if (pj == null || !pj.Stockers.Any(x => x.Item1 == target.Module.ToString())) continue; var carrier = CarrierManager.Instance.GetCarrier(target.Module); if (!carrier.IsEmpty && carrier.CarrierType == targetCarrierType) iCassetteNum++; } return iCassetteNum; } private int GetRemainWaferNum(ProcessJobInfo pj, WaferType targetWaferType) { int iWaferNum = 0; var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); foreach (var target in _lstTotlaStockers) { var carrier = CarrierManager.Instance.GetCarrier(target.Module); if (carrier == null || carrier.IsEmpty || carrier.CarrierType != targetCarrierType) continue; var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); if (pj == null || !pj.Stockers.Any(x => x.Item1 == target.Module.ToString()) || stockerInfo == null) continue; var wafers = WaferManager.Instance.GetWafers(target.Module); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == targetWaferType && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) iWaferNum++; } } if (CarrierManager.Instance.CheckHasCarrier(_carrierRobot.Module, 0)) { var carrier = CarrierManager.Instance.GetCarrier(_carrierRobot.Module); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); if (carrier.CarrierType == targetCarrierType && pj != null && pj.Stockers.Any(x => x.Item1 == carrier.InternalModuleName.ToString()) && stockerInfo != null) { var wafers = WaferManager.Instance.GetWafers(_carrierRobot.Module); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == targetWaferType && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) iWaferNum++; } } } foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module); var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == carrier.InternalModuleName.ToString()); if (carrier.CarrierType == targetCarrierType && pj != null && pj.Stockers.Any(x => x.Item1 == carrier.InternalModuleName.ToString()) && stockerInfo != null) { var wafers = WaferManager.Instance.GetWafers(fims.Module); foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == targetWaferType && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) iWaferNum++; } } } { var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1); foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty || wafer.WaferType != targetWaferType) continue; var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == ((ModuleName)wafer.OriginStation).ToString()); if (stockerInfo != null && pj != null && pj.Stockers.Any(x => x.Item1 == ((ModuleName)wafer.OriginStation).ToString()) && (!stockerInfo.Item3.Any() || stockerInfo.Item3.Any(x => x == wafer.OriginSlot))) iWaferNum++; } } var useCount = 0; if (targetWaferType == WaferType.M1) useCount = pj.Monitor1Slots.Count; if (targetWaferType == WaferType.M2) useCount = pj.Monitor2Slots.Count; return iWaferNum - useCount; } private int GetCurrentWaferNum(ProcessJobInfo pj, WaferType targetWaferType, out bool isSlotSelect) { int iWaferNum = 0; isSlotSelect = false; var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); foreach (var target in _lstTotlaStockers) { var carrier = CarrierManager.Instance.GetCarrier(target.Module); if (carrier == null || carrier.IsEmpty || carrier.CarrierType != targetCarrierType) continue; if (pj == null || !pj.Stockers.Any(x => x.Item1 == target.Module.ToString())) continue; var stockerInfo = pj.Stockers.FirstOrDefault(x => x.Item1 == target.Module.ToString()); var wafers = WaferManager.Instance.GetWafers(target.Module); foreach (var wafer in wafers) { if (!stockerInfo.Item3.Any() && !wafer.IsEmpty && wafer.WaferType == targetWaferType) iWaferNum++; if (stockerInfo.Item3.Any(x => x == wafer.OriginSlot) && !wafer.IsEmpty && wafer.WaferType == targetWaferType) { iWaferNum++; isSlotSelect = true; } } } return iWaferNum; } private int GetCurrentDummyWaferNum(WaferType targetWaferType) { int iWaferNum = 0; var targetCarrierType = (CarrierType)(Enum.Parse(typeof(CarrierType), targetWaferType.ToString())); foreach (var module in Singleton.Instance.Modules.Keys) { if (module == ModuleName.SMIFA || module == ModuleName.SMIFB || module == ModuleName.Boat) continue; if (ModuleHelper.IsStocker(module)) { var carrier = CarrierManager.Instance.GetCarrier(module); if (carrier == null || carrier.IsEmpty || carrier.CarrierType != targetCarrierType) continue; } var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null) continue; foreach (var wafer in wafers) { if (!wafer.IsEmpty && wafer.WaferType == targetWaferType) iWaferNum++; } } return iWaferNum; } private bool CassetteShortWaferInCassetteShort(ProcessJobInfo pj, ref List adjustslot, ref int currentEDNum, RecipeLayoutEntityNormal layoutRecipeDataNormal, RecipeLayoutEntityExpert layoutRecipeDataExpert, bool cassetteSupplyED, bool waferSupplyED) { bool bEDShort = false; bool monitorSlot = layoutRecipeDataNormal.MonitorPosition.ToLower() == "slot"; int slotCount = SC.GetValue($"Boat.SlotCount"); int cassetteSlotCount = SC.GetValue("System.CassetteSlotCount"); adjustslot = new List(); for (int i = 0; i < slotCount; i++) { adjustslot.Add(""); } if (monitorSlot) { for (int i = 0; i < slotCount; i++) { if (layoutRecipeDataExpert.Items[i].ToLower() == "monitor") adjustslot[i] = "monitor"; } } List tempStockers = new List(); foreach (var p in pj.Stockers) { var module = GetModule(p.Item1) as SchedulerStocker; var carrier = CarrierManager.Instance.GetCarrier(module.Module); if (!carrier.IsEmpty && carrier.CarrierType.ToString() == "P") tempStockers.Add(module); } if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") tempStockers.Reverse(); int.TryParse(layoutRecipeDataNormal.DummyUpperSlot, out int dummyUpper); int.TryParse(layoutRecipeDataNormal.DummyLowerSlot, out int dummyLower); int.TryParse(layoutRecipeDataNormal.CenteringSlotPosition, out int centeringSlotPos); int centeringSlotPosLower; int centeringSlotPosUpper; if (tempStockers.Count % 2 == 0) { centeringSlotPosLower = centeringSlotPos + (cassetteSlotCount + 1) * (tempStockers.Count / 2); centeringSlotPosUpper = centeringSlotPos - (cassetteSlotCount + 1) * (tempStockers.Count / 2); } else { centeringSlotPosLower = centeringSlotPos + (cassetteSlotCount / 2) + 1 + (cassetteSlotCount + 1) * (tempStockers.Count / 2); centeringSlotPosUpper = centeringSlotPos - (cassetteSlotCount / 2) - 1 - (cassetteSlotCount + 1) * (tempStockers.Count / 2); } if (centeringSlotPosLower >= slotCount - dummyLower) { int iIndex = slotCount - dummyLower - 1; if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex--; } foreach (var stocker in tempStockers) { var wafers = WaferManager.Instance.GetWafers(stocker.Module); if (wafers == null) continue; foreach (var wafer in wafers) { if (!wafer.IsEmpty) { for (int i = iIndex; i >= dummyUpper; i--) { if (adjustslot[i] == "") { adjustslot[i] = "production"; iIndex = i - 1; break; } } } else { if (waferSupplyED) { if (currentEDNum > 0) { for (int i = iIndex; i >= dummyUpper; i--) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; iIndex = i - 1; break; } } } else { bEDShort = true; } } } } if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex--; } } if (cassetteSupplyED && currentEDNum > 0) { for (int i = iIndex; i >= dummyUpper; i--) { if (currentEDNum > 0) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; } } else { bEDShort = true; break; } } } } else if (centeringSlotPosUpper <= dummyUpper + 1) { int iIndex = dummyUpper; if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex++; } foreach (var stocker in tempStockers) { var wafers = WaferManager.Instance.GetWafers(stocker.Module); if (wafers == null) continue; foreach (var wafer in wafers) { if (!wafer.IsEmpty) { for (int i = iIndex; i < slotCount - dummyLower; i++) { if (adjustslot[i] == "") { adjustslot[i] = "production"; iIndex = i + 1; break; } } } else { if (waferSupplyED) { if (currentEDNum > 0) { for (int i = iIndex; i < slotCount - dummyLower; i++) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; iIndex = i + 1; break; } } } else { bEDShort = true; } } } } if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex++; } } if (cassetteSupplyED && currentEDNum > 0) { for (int i = iIndex; i < slotCount - dummyLower; i++) { if (currentEDNum > 0) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; } } else { bEDShort = true; break; } } } } else { int iCount = 0; int iUpperIndex = centeringSlotPos - 1; int iLowerIndex = centeringSlotPos - 1; int iUpperCount = 0; int iLowerCount = 0; bool bCassetteEvenNumber = tempStockers.Count % 2 == 0; if (bCassetteEvenNumber && !monitorSlot) { adjustslot[centeringSlotPos - 1] = "monitor"; iUpperIndex--; iLowerIndex++; iCount++; } foreach (var stocker in tempStockers) { var wafers = WaferManager.Instance.GetWafers(stocker.Module); if (wafers == null) continue; foreach (var wafer in wafers) { if (bCassetteEvenNumber) { if (!monitorSlot && iUpperCount >= cassetteSlotCount && iUpperIndex >= dummyUpper) { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iUpperCount = 0; } if (!monitorSlot && iLowerCount >= cassetteSlotCount && iLowerIndex < slotCount - dummyLower) { adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iLowerCount = 0; } } else { if (!monitorSlot && iUpperCount + iLowerCount >= cassetteSlotCount && iUpperIndex >= dummyUpper && iLowerIndex < slotCount - dummyLower) { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iUpperCount = 0; adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iLowerCount = 0; bCassetteEvenNumber = true; } } if (iCount % 2 == 0) { if (!wafer.IsEmpty) { for (int i = iUpperIndex; i >= dummyUpper; i--) { if (adjustslot[i] == "") { adjustslot[i] = "production"; iUpperIndex = i - 1; iUpperCount++; iCount++; break; } } } else { if (waferSupplyED) { if (currentEDNum > 0) { for (int i = iUpperIndex; i >= dummyUpper; i--) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; iUpperIndex = i - 1; iUpperCount++; iCount++; break; } } } else { bEDShort = true; } } } } else { if (!wafer.IsEmpty) { for (int i = iLowerIndex; i < slotCount - dummyLower; i++) { if (adjustslot[i] == "") { adjustslot[i] = "production"; iLowerIndex = i + 1; iLowerCount++; iCount++; break; } } } else { if (waferSupplyED) { if (currentEDNum > 0) { for (int i = iLowerIndex; i < slotCount - dummyLower; i++) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; iLowerIndex = i + 1; iLowerCount++; iCount++; break; } } } else { bEDShort = true; } } } } } if (!monitorSlot) { if (adjustslot[iUpperIndex + 1] != "M") { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iCount++; } if (adjustslot[iLowerIndex - 1] != "monitor") { adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iCount++; } } } if (cassetteSupplyED && currentEDNum > 0) { for (int i = 0; i < slotCount - iCount - dummyUpper - dummyLower; i++) { if (currentEDNum <= 0) { bEDShort = true; break; } for (int j = iUpperIndex; j >= dummyUpper; j--) { if (adjustslot[j] == "") { adjustslot[j] = "extradummy"; iUpperIndex = j - 1; currentEDNum--; break; } } if (currentEDNum <= 0) { bEDShort = true; break; } for (int j = iLowerIndex; j < slotCount - dummyLower; j++) { if (adjustslot[j] == "") { adjustslot[j] = "extradummy"; iLowerIndex = j + 1; currentEDNum--; break; } } } } } return bEDShort; } private bool CassetteShortPWaferShort(ProcessJobInfo pj, ref List adjustslot, ref int currentEDNum, RecipeLayoutEntityNormal layoutRecipeDataNormal, RecipeLayoutEntityExpert layoutRecipeDataExpert, int currentPWaferNum, bool cassetteSupplyED) { bool bEDShort = false; bool monitorSlot = layoutRecipeDataNormal.MonitorPosition.ToLower() == "slot"; int slotCount = SC.GetValue($"Boat.SlotCount"); int cassetteSlotCount = SC.GetValue("System.CassetteSlotCount"); adjustslot = new List(); for (int i = 0; i < slotCount; i++) { adjustslot.Add(""); } if (monitorSlot) { for (int i = 0; i < slotCount; i++) { if (layoutRecipeDataExpert.Items[i].ToLower() == "monitor") adjustslot[i] = "monitor"; } } int.TryParse(layoutRecipeDataNormal.DummyUpperSlot, out int dummyUpper); int.TryParse(layoutRecipeDataNormal.DummyLowerSlot, out int dummyLower); int.TryParse(layoutRecipeDataNormal.CenteringSlotPosition, out int centeringSlotPos); List tempStockers = new List(); foreach (var p in pj.Stockers) { var module = GetModule(p.Item1) as SchedulerStocker; var carrier = CarrierManager.Instance.GetCarrier(module.Module); if (!carrier.IsEmpty && carrier.CarrierType.ToString() == "P") tempStockers.Add(module); } if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") tempStockers.Reverse(); int centeringSlotPosLower; int centeringSlotPosUpper; if ((currentPWaferNum / 2) % cassetteSlotCount == 0) { var temp = (int)Math.Ceiling((float)((currentPWaferNum / 2) / cassetteSlotCount)); centeringSlotPosLower = centeringSlotPos + (cassetteSlotCount + 1) * temp; centeringSlotPosUpper = centeringSlotPos - (cassetteSlotCount + 1) * temp; } else { var temp = (int)Math.Ceiling((float)((currentPWaferNum / 2) / cassetteSlotCount)); centeringSlotPosLower = centeringSlotPos + (currentPWaferNum / 2) + 1 + temp; centeringSlotPosUpper = centeringSlotPos - (currentPWaferNum / 2) - 1 - temp; } if (centeringSlotPosLower >= slotCount - dummyLower) { int iIndex = slotCount - dummyLower - 1; if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex--; } for (int i = 0; i < tempStockers.Count; i++) { if (currentPWaferNum == 0) break; for (int j = 0; j < cassetteSlotCount; j++) { if (currentPWaferNum == 0) break; for (int k = iIndex; k >= dummyUpper; k--) { if (adjustslot[k] == "") { adjustslot[k] = "production"; currentPWaferNum--; iIndex = k - 1; break; } } } if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex--; } } if (cassetteSupplyED) { for (int i = iIndex; i >= dummyUpper; i--) { if (currentEDNum > 0) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; } } else { bEDShort = true; break; } } } } else if (centeringSlotPosUpper <= dummyUpper + 1) { int iIndex = dummyUpper; if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex++; } for (int i = 0; i < tempStockers.Count; i++) { if (currentPWaferNum == 0) break; for (int j = 0; j < cassetteSlotCount; j++) { if (currentPWaferNum == 0) break; for (int k = iIndex; k < slotCount - dummyLower; k++) { if (adjustslot[k] == "") { adjustslot[k] = "production"; currentPWaferNum--; iIndex = k + 1; break; } } } if (!monitorSlot) { adjustslot[iIndex] = "monitor"; iIndex++; } } if (cassetteSupplyED) { for (int i = iIndex; i < slotCount - dummyLower; i++) { if (currentEDNum > 0) { if (adjustslot[i] == "") { adjustslot[i] = "extradummy"; currentEDNum--; } } else { bEDShort = true; break; } } } } else { int iCount = 0; int iUpperIndex = centeringSlotPos - 1; int iLowerIndex = centeringSlotPos - 1; int iUpperCount = 0; int iLowerCount = 0; bool bCassetteEvenNumber = (currentPWaferNum / 2) % cassetteSlotCount == 0; if (bCassetteEvenNumber && !monitorSlot) { adjustslot[centeringSlotPos - 1] = "monitor"; iUpperIndex--; iLowerIndex++; iCount++; } for (int i = 0; i < tempStockers.Count; i++) { if (currentPWaferNum == 0) break; for (int j = 0; j < cassetteSlotCount; j++) { if (currentPWaferNum == 0) break; if (bCassetteEvenNumber) { if (!monitorSlot && iUpperCount >= cassetteSlotCount && iUpperIndex >= dummyUpper) { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iUpperCount = 0; } if (!monitorSlot && iLowerCount >= cassetteSlotCount && iLowerIndex < slotCount - dummyLower) { adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iLowerCount = 0; } } else { if (!monitorSlot && iUpperCount + iLowerCount >= cassetteSlotCount && iUpperIndex >= dummyUpper && iLowerIndex < slotCount - dummyLower) { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iUpperCount = 0; adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iLowerCount = 0; bCassetteEvenNumber = true; } } if (iCount % 2 == 0) { for (int k = iUpperIndex; k >= dummyUpper; k--) { if (adjustslot[k] == "") { adjustslot[k] = "production"; currentPWaferNum--; iUpperIndex = k - 1; iUpperCount++; iCount++; break; } } } else { for (int k = iLowerIndex; k < slotCount - dummyLower; k++) { if (adjustslot[k] == "") { adjustslot[k] = "production"; currentPWaferNum--; iLowerIndex = k + 1; iLowerCount++; iCount++; break; } } } } } if (!monitorSlot) { if (adjustslot[iUpperIndex + 1] != "monitor") { adjustslot[iUpperIndex] = "monitor"; iUpperIndex--; iCount++; } if (adjustslot[iLowerIndex - 1] != "monitor") { adjustslot[iLowerIndex] = "monitor"; iLowerIndex++; iCount++; } } if (cassetteSupplyED) { for (int i = 0; i < slotCount - iCount - dummyUpper - dummyLower; i++) { if (currentEDNum <= 0) { bEDShort = true; break; } for (int j = iUpperIndex; j >= dummyUpper; j--) { if (adjustslot[j] == "") { adjustslot[j] = "extradummy"; currentEDNum--; iUpperIndex = j - 1; break; } } if (currentEDNum <= 0) { bEDShort = true; break; } for (int j = iLowerIndex; j < slotCount - dummyLower; j++) { if (adjustslot[j] == "") { adjustslot[j] = "extradummy"; currentEDNum--; iLowerIndex = j + 1; break; } } } } } return bEDShort; } #endregion #region dummy use private bool CheckDummyWaferUse(ProcessJobInfo pj, ControlJobInfo cj) { foreach (var module in Singleton.Instance.Modules.Keys) { if (!ModuleHelper.IsStocker(module) || !pj.Stockers.Any(x => x.Item1 == module.ToString())) continue; var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; #region New var isScheduleMaintenance = SC.ContainsItem("System.IsScheduleMaintenance") && SC.GetValue("System.IsScheduleMaintenance"); if (isScheduleMaintenance) { #region SD Dummy 时间/次数/膜厚限制 var maintenanceItemSDCarrierUseFreq = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.SDCarrierUseFreq.ToString()); var maintenanceItemSDWaferThickness = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.SDWaferThickness.ToString()); var maintenanceItemSDWaferUserTime = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.SDWaferUserTime.ToString()); int SDCountWarning = (int)maintenanceItemSDCarrierUseFreq.StartValue; int SDCountAlarm = (int)maintenanceItemSDCarrierUseFreq.LimitValue; bool IsEnableSDWaferUseCountWarning = SDCountWarning > 0; int SDThicknessWarning = (int)maintenanceItemSDWaferThickness.StartValue; int SDThicknessAlarm = (int)maintenanceItemSDWaferThickness.LimitValue; bool IsEnableSDWaferThicknessWarning = SDThicknessWarning > 0; int SDTimeWarning = DateTimeUtil.GetSecond(maintenanceItemSDWaferUserTime.StartValue); int SDTimeAlarm = DateTimeUtil.GetSecond(maintenanceItemSDWaferUserTime.LimitValue); bool IsEnableSDWaferUseTimeWarning = SDTimeWarning > 0; if (wafer.WaferType == WaferType.SD && IsEnableSDWaferUseCountWarning && wafer.UseCount > SDCountWarning && wafer.UseCount < SDCountAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDCarrierUseFreq.MaintenanceProcessing, Singleton.Instance.SDWaferTypeUseCountWarning.Set, $"more than {SDCountWarning} 次"); } if (wafer.WaferType == WaferType.SD && IsEnableSDWaferUseTimeWarning && wafer.UseTime > SDTimeWarning && wafer.UseTime < SDTimeAlarm) { DateTimeUtil.ConvertSecondsToHoursAndMinutes(SDTimeWarning, out var hours, out var minutes); (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDWaferUserTime.MaintenanceProcessing, Singleton.Instance.SDWaferTypeUseTimeWarning.Set, $"more than {hours} hour {minutes} min"); } if (wafer.WaferType == WaferType.SD && IsEnableSDWaferThicknessWarning && wafer.UseThick > SDThicknessWarning && wafer.UseThick < SDThicknessAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDWaferThickness.MaintenanceProcessing, Singleton.Instance.SDWaferTypeThicknessWarning.Set, $"more than {SDThicknessWarning} nm"); } if (wafer.WaferType == WaferType.SD && IsEnableSDWaferUseCountWarning && wafer.UseCount >= SDCountAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDCarrierUseFreq.MaintenanceProcessing, Singleton.Instance.SDWaferTypeUseCountAlarm.Set, $"more than {SDCountAlarm} 次"); return false; } if (wafer.WaferType == WaferType.SD && IsEnableSDWaferUseTimeWarning && wafer.UseTime >= SDTimeAlarm) { DateTimeUtil.ConvertSecondsToHoursAndMinutes(SDTimeAlarm, out var hours, out var minutes); (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDWaferUserTime.MaintenanceProcessing, Singleton.Instance.SDWaferTypeUseTimeAlarm.Set, $"more than {hours} hour {minutes}"); return false; } if (wafer.WaferType == WaferType.SD && IsEnableSDWaferThicknessWarning && wafer.UseThick >= SDThicknessAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemSDWaferThickness.MaintenanceProcessing, Singleton.Instance.SDWaferTypeThicknessAlarm.Set, $"more than {SDThicknessAlarm} nm"); return false; } #endregion #region ED var maintenanceItemEDCarrierUseFreq = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.FDCarrierUseFreq.ToString()); var maintenanceItemEDWaferThickness = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.FDWaferThickness.ToString()); var maintenanceItemEDWaferUserTime = ScheduleMaintenanceDataManager.Instance.GetItem(MaintenanceItemEnum.FDWaferUserTime.ToString()); int EDCountWarning = (int)maintenanceItemEDCarrierUseFreq.StartValue; int EDCountAlarm = (int)maintenanceItemEDCarrierUseFreq.LimitValue; bool IsEnableEDWaferUseCountWarning = EDCountWarning > 0; int EDThicknessWarning = (int)maintenanceItemEDWaferThickness.StartValue; int EDThicknessAlarm = (int)maintenanceItemEDWaferThickness.LimitValue; bool IsEnableEDWaferThicknessWarning = EDThicknessWarning > 0; int EDTimeWarning = DateTimeUtil.GetSecond(maintenanceItemEDWaferUserTime.StartValue); int EDTimeAlarm = DateTimeUtil.GetSecond(maintenanceItemEDWaferUserTime.LimitValue); bool IsEnableEDWaferUseTimeWarning = EDTimeWarning > 0; if (wafer.WaferType == WaferType.ED && IsEnableEDWaferUseCountWarning && maintenanceItemEDCarrierUseFreq.CurrentValue > EDCountWarning && wafer.UseCount < EDCountAlarm) { //Singleton.Instance.MaintenanceProcessingCommandExec(maintenanceItemEDCarrierUseFreq.MaintenanceProcessing, Singleton.Instance.EDWaferTypeUseCountWarning.Set, $"more than {EDCountWarning} 次"); //return false; if (Enum.TryParse(maintenanceItemEDCarrierUseFreq.MaintenanceProcessing, out var command)) { switch (command) { case MaintenanceProcessingCommandEnum.None: break; case MaintenanceProcessingCommandEnum.AlarmReport: Singleton.Instance.EDWaferTypeUseCountWarning.Set($"more than {EDCountWarning} 次"); break; case MaintenanceProcessingCommandEnum.JobProhibition: break; case MaintenanceProcessingCommandEnum.JobManualStart: break; case MaintenanceProcessingCommandEnum.JobAutoStart: Singleton.Instance.EDWaferTypeUseCountWarning.Set($"more than {EDCountWarning} 次"); Singleton.Instance.CheckToPostMessage((int)EquipmentManager.MSG.JobAutoStart, cj.Name); var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; if (pmModule != null) pmModule.Process(maintenanceItemEDCarrierUseFreq.AssociationProcessRecipeName, false, true, out string reson); return false; } } } if (wafer.WaferType == WaferType.ED && IsEnableEDWaferUseTimeWarning && wafer.UseTime > EDTimeWarning && wafer.UseTime < EDTimeAlarm) { DateTimeUtil.ConvertSecondsToHoursAndMinutes(EDTimeWarning, out var hours, out var minutes); (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemEDWaferUserTime.MaintenanceProcessing, Singleton.Instance.EDWaferTypeUseTimeWarning.Set, $"more than {hours} hour {minutes} min"); } if (wafer.WaferType == WaferType.ED && IsEnableEDWaferThicknessWarning && wafer.UseThick > EDThicknessWarning && wafer.UseThick < EDThicknessAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemEDWaferThickness.MaintenanceProcessing, Singleton.Instance.EDWaferTypeThicknessWarning.Set, $"more than {EDThicknessWarning} nm"); } if (wafer.WaferType == WaferType.ED && IsEnableEDWaferUseCountWarning && wafer.UseCount >= EDCountAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemEDCarrierUseFreq.MaintenanceProcessing, Singleton.Instance.EDWaferTypeUseCountAlarm.Set, $"more than {EDCountAlarm} 次"); return false; } if (wafer.WaferType == WaferType.ED && IsEnableEDWaferUseTimeWarning && wafer.UseTime >= EDTimeAlarm) { DateTimeUtil.ConvertSecondsToHoursAndMinutes(EDTimeAlarm, out var hours, out var minutes); (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemEDWaferUserTime.MaintenanceProcessing, Singleton.Instance.EDWaferTypeUseTimeAlarm.Set, $"more than {hours} hour {minutes}"); return false; } if (wafer.WaferType == WaferType.ED && IsEnableEDWaferThicknessWarning && wafer.UseThick >= EDThicknessAlarm) { (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).MaintenanceProcessingCommandExec(maintenanceItemEDWaferThickness.MaintenanceProcessing, Singleton.Instance.EDWaferTypeThicknessAlarm.Set, $"more than {EDThicknessAlarm} nm"); return false; } #endregion } else { // SD Dummy if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferUseCountWarning") && wafer.UseCount > SC.GetValue($"PM1.WaferCycleTime.SDCountWarning") && wafer.UseCount < SC.GetValue($"PM1.WaferCycleTime.SDCountAlarm")) { Singleton.Instance.SDWaferTypeUseCountWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDCountWarning")} 次"); } if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferUseTimeWarning") && wafer.UseTime / 3600 > SC.GetValue($"PM1.WaferCycleTime.SDTimeWarning") && wafer.UseTime / 3600 < SC.GetValue($"PM1.WaferCycleTime.SDTimeAlarm")) { Singleton.Instance.SDWaferTypeUseTimeWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDTimeWarning")} hour"); } if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferThicknessWarning") && wafer.UseThick > SC.GetValue($"PM1.WaferCycleTime.SDThicknessWarning") && wafer.UseThick < SC.GetValue($"PM1.WaferCycleTime.SDThicknessAlarm")) { Singleton.Instance.SDWaferTypeThicknessWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDThicknessWarning")} nm"); } if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferUseCountWarning") && wafer.UseCount >= SC.GetValue($"PM1.WaferCycleTime.SDCountAlarm")) { Singleton.Instance.SDWaferTypeUseCountAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDCountAlarm")} 次"); return false; } if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferUseTimeWarning") && wafer.UseTime / 3600 >= SC.GetValue($"PM1.WaferCycleTime.SDTimeAlarm")) { Singleton.Instance.SDWaferTypeUseTimeAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDTimeAlarm")} hour"); return false; } if (wafer.WaferType == WaferType.SD && SC.GetValue($"PM1.WaferCycleTime.IsEnableSDWaferThicknessWarning") && wafer.UseThick >= SC.GetValue($"PM1.WaferCycleTime.SDThicknessAlarm")) { Singleton.Instance.SDWaferTypeThicknessAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.SDThicknessAlarm")} nm"); return false; } // Extra Dummy if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferUseCountWarning") && wafer.UseCount > SC.GetValue($"PM1.WaferCycleTime.EDCountWarning") && wafer.UseCount < SC.GetValue($"PM1.WaferCycleTime.EDCountAlarm")) { Singleton.Instance.EDWaferTypeUseCountWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDCountWarning")} 次"); } if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferUseTimeWarning") && wafer.UseTime / 3600 > SC.GetValue($"PM1.WaferCycleTime.EDTimeWarning") && wafer.UseTime / 3600 < SC.GetValue($"PM1.WaferCycleTime.EDTimeAlarm")) { Singleton.Instance.EDWaferTypeUseTimeWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDTimeWarning")} hour"); } if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferThicknessWarning") && wafer.UseThick > SC.GetValue($"PM1.WaferCycleTime.EDThicknessWarning") && wafer.UseThick < SC.GetValue($"PM1.WaferCycleTime.EDThicknessAlarm")) { Singleton.Instance.EDWaferTypeThicknessWarning.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDThicknessWarning")} nm"); } if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferUseCountWarning") && wafer.UseCount >= SC.GetValue($"PM1.WaferCycleTime.EDCountAlarm")) { Singleton.Instance.EDWaferTypeUseCountAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDCountAlarm")} 次"); return false; } if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferUseTimeWarning") && wafer.UseTime / 3600 >= SC.GetValue($"PM1.WaferCycleTime.EDTimeAlarm")) { Singleton.Instance.EDWaferTypeUseTimeAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDTimeAlarm")} hour"); return false; } if (wafer.WaferType == WaferType.ED && SC.GetValue($"PM1.WaferCycleTime.IsEnableEDWaferThicknessWarning") && wafer.UseThick >= SC.GetValue($"PM1.WaferCycleTime.EDThicknessAlarm")) { Singleton.Instance.EDWaferTypeThicknessAlarm.Set($"more than {SC.GetValue($"PM1.WaferCycleTime.EDThicknessAlarm")} nm"); return false; } } #endregion } } return true; } #endregion private void MonitorPMTask() { if (!_carrierRobot.IsAvailable || !_waferRobot.IsAvailable) return; foreach (var pm in _lstPms) { var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; if (pmModule == null) return; if (!pm.IsAvailable && !pmModule.IsMainRecipeComplete) continue; var wafers = WaferManager.Instance.GetWafers(pm.Module); if (wafers == null) continue; var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return; bool isNeedProcess = false; bool isProcessed = false; foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) continue; if (!pj.SlotWafers.Any(x => x.Item1 == (ModuleName)wafer.OriginStation && x.Item2 == wafer.OriginSlot)) pj.SlotWafers.Add(Tuple.Create((ModuleName)wafer.OriginStation, wafer.OriginSlot)); if (wafer.ProcessJob == null) { wafer.ProcessJob = pj; WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString()); } if (wafer.ProcessState == EnumWaferProcessStatus.Idle) { isNeedProcess = true; isProcessed = false; } if (wafer.ProcessState == EnumWaferProcessStatus.Completed) { isNeedProcess = false; isProcessed = true; } } if (pj.IsEmptyLayout) { if (pj.ProcessingState == EnumProcessingState.Charging) { isNeedProcess = true; isProcessed = false; } else { isNeedProcess = false; if (DateTime.Now - pm.RecipeStartTime > TimeSpan.FromSeconds(5)) isProcessed = true; } } if (isNeedProcess && CheckChargeFinished(pj, pm.Module) && pj.ProcessingState != EnumProcessingState.Processing && pmModule.CheckStandbyCondition() && pm.IsAvailable) { if (SC.GetValue("System.IsEnableBoatChargeMapping") && !pj.IsMapAfterCharge) { var mappingSlot = GetMappingSlot(ModuleName.PM1); if (_waferRobot.Map(ModuleName.PM1, mappingSlot.Length == 0 ? 0 : Regex.Matches(mappingSlot, "1").Count, mappingSlot, true, false, Hand.Blade1)) { pj.IsMapAfterCharge = true; return; } } if (!pj.RobotHomed) { (Singleton.Instance.Modules[ModuleName.WaferRobot] as WaferRobotModule).Home(out _); pj.RobotHomed = true; } pj.ProcessingState = EnumProcessingState.Processing; pmModule?.SetN2PurgeLAO2CheckFirstEnable(false); if (pm.Process((string)pj.ProcessRecipe, false, true)) return; } //工艺结束 if (isProcessed) { if (pj.ProcessingState == EnumProcessingState.Processing) { Singleton.Instance.EndPj(); if (pj.CoolTimeSec > 0) { _coolTimer.Restart(); pj.ProcessingState = EnumProcessingState.CoolingBeforeDischarge; } else { _coolTimer.Restart(); pj.ProcessingState = EnumProcessingState.CoolingBeforeDischarge; } LOG.Write($"Cooling start {pj.CoolTimeSec}"); } if (pj.ProcessingState == EnumProcessingState.CoolingBeforeDischarge && (_coolTimer.ElapsedMilliseconds > pj.CoolTimeSec * 1000 || _isCoolingSkip)) { _isCoolingSkip = false; var boatModule = Singleton.Instance.Modules[ModuleName.Boat] as BoatModule; if (boatModule != null && !boatModule.IsBoatElevatorAtHomePosition && boatModule.ZAxisDevice.IsReady) { boatModule.ZAxisDevice.SetServoMoveTo("HomePosition", out _); } if (boatModule != null && !boatModule.IsBoatRotationAtHomePosition && boatModule.RAxisDevice.IsReady) { boatModule.RAxisDevice.ServoStop(); boatModule.RAxisDevice.SetServoHome(); } if (boatModule != null && boatModule.IsBoatElevatorAtHomePosition && boatModule.IsBoatRotationAtHomePosition) { if (SC.GetValue("System.IsEnableBoatDischargeMapping") && !pj.IsMapBeforeDischarge) { var mappingSlot = GetMappingSlot(ModuleName.PM1); if (_waferRobot.Map(ModuleName.PM1, mappingSlot.Length == 0 ? 0 : Regex.Matches(mappingSlot, "1").Count, mappingSlot, true, false, Hand.Blade1)) { pj.IsMapBeforeDischarge = true; return; } } _coolTimer.Stop(); AdjustDischargeSlots(); pj.ProcessingState = EnumProcessingState.Discharging; LOG.Write($"Cooling completed {pj.CoolTimeSec}"); if (pj.IsN2PurgeMode) { //pmModule?.SetN2PurgeProcess(true); //if (SC.ContainsItem("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable") && SC.GetValue("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable")) // pmModule?.SetN2PurgeLAO2CheckFirstEnable(true); if (SC.ContainsItem("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable") && SC.GetValue("PM1.N2Purge.WaferCharge.TransferRoomN2PurgeEnable")) { pmModule?.SetN2PurgeProcess(true); pmModule?.SetN2PurgeLAO2CheckFirstEnable(true); } if (SC.ContainsItem("PM1.RecipeRelevancyN2Purge") && SC.GetValue("PM1.RecipeRelevancyN2Purge") && SC.ContainsItem("PM1.SelectN2PurgeMode")) { var setValue = pmModule.GetN2PurgeModeEnumByStr(pj.N2PurgeModeStr); SC.SetItemValueFromString("PM1.SelectN2PurgeMode", setValue); pmModule.RestAllN2PrugeRD(); } } } } } } } #endregion Module task #region Logic Check private bool CheckChargeFinished(ProcessJobInfo pj, ModuleName module, bool isOnlyCharge = false) { var wafers = WaferManager.Instance.GetWafers(module); if (pj == null || wafers == null) return false; if (WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 1) || WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 2) || WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 3) || WaferManager.Instance.CheckHasWafer(ModuleName.WaferRobot, 4)) return false; int edCount = 0; int sdCount = 0; int m1Count = 0; int m2Count = 0; int pCount = 0; int expertCount = 0; foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) continue; switch (wafer.WaferType) { case WaferType.M1: m1Count++; break; case WaferType.M2: m2Count++; break; case WaferType.ED: edCount++; break; case WaferType.SD: sdCount++; break; case WaferType.P: pCount++; break; case WaferType.XD: case WaferType.T: expertCount++; break; } } if (expertCount > 0) { if (pj.XdSlots == null || pj.TSlots == null) return false; return expertCount == pj.XdSlots.Count + pj.TSlots.Count; } if (pj.ExtraDummySlots != null && pj.ExtraDummySlots.Count != edCount && pj.ExtraDummySlots.Count > 0) return false; if (pj.SideDummySlots != null && pj.SideDummySlots.Count != sdCount && pj.SideDummySlots.Count > 0) return false; if (pj.Monitor1Slots != null && pj.Monitor1Slots.Count != m1Count) return false; if (pj.Monitor2Slots != null && pj.Monitor2Slots.Count != m2Count) return false; foreach (var s in pj.Stockers) { var carrier = CarrierManager.Instance.GetCarrier(s.Item1, 0); if (carrier == null || carrier.CarrierType != CarrierType.P || carrier.IsEmpty) continue; var carrierWafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(s.Item1)).ToList(); if (carrierWafers == null || (carrierWafers.Any(x => !x.IsEmpty) && pj.ProductSlots.Count > pCount)) return false; } var carrierRobot = CarrierManager.Instance.GetCarrier(_carrierRobot.Module, 0); if (carrierRobot != null && !carrierRobot.IsEmpty && isOnlyCharge) return false; if (carrierRobot != null && !carrierRobot.IsEmpty && carrierRobot.CarrierType == CarrierType.P && pj.Stockers.Any(x => ModuleHelper.Converter(x.Item1) == carrierRobot.InternalModuleName)) { var carrierWafers = WaferManager.Instance.GetWafers(_carrierRobot.Module).ToList(); if (carrierWafers == null || carrierWafers.Any(x => !x.IsEmpty)) return false; } foreach (var fims in _lstFIMSs) { var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (carrier != null && !carrier.IsEmpty && isOnlyCharge) return false; if (carrier != null && !carrier.IsEmpty && carrier.CarrierType == CarrierType.P && pj.Stockers.Any(x => ModuleHelper.Converter(x.Item1) == carrier.InternalModuleName)) { var carrierWafers = WaferManager.Instance.GetWafers(fims.Module).ToList(); if (carrierWafers == null || carrierWafers.Any(x => !x.IsEmpty)) return false; } } return true; } private bool CheckProcessJobReady(ProcessJobInfo pj) { bool isReady = true; if (pj == null) return false; //Boat Ready检查 var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; if (pmModule == null || !pmModule.CheckReadyForTransfer(_waferRobot.Module, Hand.Blade1, 0, EnumTransferType.Place, out string reason)) return false; int pCount = 0; int m1Count = 0; int m2Count = 0; foreach (var s in pj.Stockers) { var type = SC.GetStringValue($"System.Stocker.{s.Item1}WaferType"); if (!string.IsNullOrEmpty(type) && (type.Contains("P") || type.Contains("M") || type.Contains("None"))) { ModuleName module = ModuleHelper.Converter(s.Item1); if (!CarrierManager.Instance.CheckHasCarrier(module, 0)) continue; var wafers = WaferManager.Instance.GetWafers(module).ToList(); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer == null || wafer.ProcessState != EnumWaferProcessStatus.Idle) continue; if (wafer.WaferType == WaferType.M1) m1Count++; if (wafer.WaferType == WaferType.M2) m2Count++; if (wafer.WaferType == WaferType.P) pCount++; } } } if (m1Count < pj.Monitor1Slots.Count || m2Count < pj.Monitor2Slots.Count || pCount < pj.ProductSlots.Count) return false; return isReady; } protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed) { if (pj.SlotWafers == null || pj.SlotWafers.Count == 0 || pj.SlotWafers.Count != (pj.SideDummySlots != null ? pj.SideDummySlots.Count : 0) + (pj.ExtraDummySlots != null ? pj.ExtraDummySlots.Count : 0) + (pj.ProductSlots != null ? pj.ProductSlots.Count : 0) + (pj.Monitor1Slots != null ? pj.Monitor1Slots.Count : 0) + (pj.Monitor2Slots != null ? pj.Monitor2Slots.Count : 0)) return false; var boatWafers = WaferManager.Instance.GetWafers(ModuleName.PM1).ToList(); for (int i = 0; i < pj.SlotWafers.Count; ++i) { if (!CarrierManager.Instance.CheckHasCarrier(pj.SlotWafers[i].Item1, 0)) { var isFOUPUnloaded = true; if (CarrierManager.Instance.CheckHasCarrier(_carrierRobot.Module, 0) && CarrierManager.Instance.GetCarrier(_carrierRobot.Module, 0).InternalModuleName == pj.SlotWafers[i].Item1) { isFOUPUnloaded = false; } foreach (var st in _lstFIMSs) { if (!st.IsOnline || !CarrierManager.Instance.CheckHasCarrier(st.Module, 0)) continue; if (CarrierManager.Instance.GetCarrier(st.Module, 0).InternalModuleName == pj.SlotWafers[i].Item1) { isFOUPUnloaded = false; break; } } if (isFOUPUnloaded) continue;//已经unload } WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2); if (wafer.IsEmpty) { if (SC.GetValue("System.IsEnableDummyWaferDischarge")) return false; else { if (boatWafers.Any(x => x.OriginStation == (int)pj.SlotWafers[i].Item1 && x.OriginSlot == pj.SlotWafers[i].Item2 && !x.IsEmpty && (x.WaferType == WaferType.SD || x.WaferType == WaferType.ED))) continue; else return false; } } if (checkAllProcessed && CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2)) return false; } if (checkAllProcessed) { if (boatWafers != null) { for (int i = 0; i < boatWafers.Count; i++) { var wafer = boatWafers[i]; if (wafer.IsEmpty) continue; if (wafer.ProcessState != EnumWaferProcessStatus.Completed && wafer.ProcessState != EnumWaferProcessStatus.Failed) { return false; } } } } return true; } public bool CheckWaferNeedProcess(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System) { WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot); if (wafer.IsEmpty) return false; if (wafer.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.PM1) || wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(ModuleName.PM2)) { if (processIn == ModuleName.System) return true; //if (_mapLpPm[(ModuleName)wafer.OriginStation] != processIn) // return false; if (wafer.ProcessJob.Sequence.Steps[i].StepModules .Contains(processIn)) return true; } } return false; } private List> GetWaferTypeSlots() { List> slots = new List>(); var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing); if (pj == null) return slots; if (pj.SideDummySlots != null && pj.SideDummySlots.Count > 0) { pj.SideDummySlots.ForEach(x => slots.Add(Tuple.Create(WaferType.SD, x))); } if (pj.ExtraDummySlots != null && pj.ExtraDummySlots.Count > 0) { pj.ExtraDummySlots.ForEach(x => slots.Add(Tuple.Create(WaferType.ED, x))); } if (pj.ProductSlots != null && pj.ProductSlots.Count > 0) { pj.ProductSlots.ForEach(x => slots.Add(Tuple.Create(WaferType.P, x))); } if (pj.Monitor1Slots != null && pj.Monitor1Slots.Count > 0) { pj.Monitor1Slots.ForEach(x => slots.Add(Tuple.Create(WaferType.M1, x))); } if (pj.Monitor2Slots != null && pj.Monitor2Slots.Count > 0) { pj.Monitor2Slots.ForEach(x => slots.Add(Tuple.Create(WaferType.M2, x))); } return slots.OrderByDescending(x => x.Item2).ToList(); } private string GetMappingSlot(ModuleName module) { string mappingSlot = string.Empty; var wafers = WaferManager.Instance.GetWafers(module); if (wafers != null) { for (int i = 0; i < wafers.Length; i++) { if (!wafers[i].IsEmpty) mappingSlot += "1"; else mappingSlot += "0"; } } return mappingSlot; } private void AdjustDischargeSlots() { _sideDummySlots.Clear(); _extraDummySlots.Clear(); _productSlots.Clear(); _monitor1Slots.Clear(); _monitor2Slots.Clear(); for (int i = 0; i < SC.GetValue($"Boat.SlotCount"); i++) { if (!WaferManager.Instance.CheckHasWafer(_pm1.Module, i)) continue; var wafer = WaferManager.Instance.GetWafer(_pm1.Module, i); if (wafer == null || wafer.IsEmpty) continue; switch (wafer.WaferType) { case WaferType.SD: _sideDummySlots.Add(i); break; case WaferType.ED: _extraDummySlots.Add(i); break; case WaferType.P: _productSlots.Add(i); break; case WaferType.M1: _monitor1Slots.Add(i); break; case WaferType.M2: _monitor2Slots.Add(i); break; } } if (SC.GetStringValue("System.ChargingOrderToBoat") == "FromTopToBottom") { _productSlots.Sort((x, y) => x.CompareTo(y));//升序 _monitor1Slots.Sort((x, y) => x.CompareTo(y));//升序 _monitor2Slots.Sort((x, y) => x.CompareTo(y));//升序 _extraDummySlots.Sort((x, y) => x.CompareTo(y));//升序 _sideDummySlots.Sort((x, y) => x.CompareTo(y));//升序 } else { _productSlots.Sort((x, y) => -x.CompareTo(y));//降序 _monitor1Slots.Sort((x, y) => -x.CompareTo(y));//降序 _monitor2Slots.Sort((x, y) => -x.CompareTo(y));//降序 _extraDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 _sideDummySlots.Sort((x, y) => -x.CompareTo(y));//降序 } } public void CreatePj(string processName) { _dbCallback.PjCreated(processName); } public void StartPj() { _dbCallback.PjStart(); } public void EndPj(string endStatus) { _dbCallback.PjUpdated(); _dbCallback.PjFinished(endStatus); } public void PjUpdated() { _dbCallback.PjUpdated(); } public void PjFinished(string endStatus) { _dbCallback.PjFinished(endStatus); } #endregion Logic Check public void CoolingSkip() { _isCoolingSkip = true; } public string GetFirstPJId() { return _dbCallback.GetFirstPJId(); } public string GetFirstPJStatus() { if (_lstProcessJobs == null || _lstProcessJobs.Count == 0) { return ""; } return _lstProcessJobs[0].ProcessingState.ToString(); } #region FA public bool IsCJExisted(string cjid) { return _lstControlJobs.Exists(x => x.Name == cjid); } public bool IsCJExcuting(string cjid) { return _lstControlJobs.Exists(x => x.Name == cjid && x.State == EnumControlJobState.Executing); } public bool CreateControlJob(string jobId, List pjIDs, out ControlJobInfo cj) { cj = null; if (_lstControlJobs.Exists(x => x.Name == jobId)) { //EV.PostWarningLog(LogSource, $"{jobId} is already created"); return false; } cj = new ControlJobInfo(); cj.Name = jobId; //cj.Module = module; cj.LotName = jobId; cj.LotInnerId = Guid.NewGuid(); cj.LotWafers = new List(); cj.CreateTime = DateTime.Now; cj.SetState(EnumControlJobState.Queued); foreach (var pjName in pjIDs) { var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName); if (pj == null) { LOG.Info($"not find {pjName} while create control job"); continue; } pj.ControlJobName = jobId; cj.ProcessJobNameList.Add(pj.Name); } if (!_lstControlJobs.Contains(cj)) _lstControlJobs.Add(cj); _faCallback.JobCreated(cj); //if ((Singleton.Instance.Modules[ModuleName.PM1] as PMModule).IsExcuteIdleRecipe) // (Singleton.Instance.Modules[ModuleName.PM1] as PMModule).EndIdleRecipe(); return true; } private bool CheckWaferStatus(List> useStockers, bool isNeedCheckMonitor, bool isNeedCheckP, out string reason) { reason = string.Empty; if (SC.GetValue("System.IsCycleMode")) { foreach (var module in Singleton.Instance.Modules.Keys) { if (!ModuleHelper.IsStocker(module) || !useStockers.Any(x => x.Item1 == module.ToString())) continue; var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null) continue; foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; wafer.ProcessState = EnumWaferProcessStatus.Idle; } } } else { foreach (var module in Singleton.Instance.Modules.Keys) { if (!ModuleHelper.IsStocker(module) || !useStockers.Any(x => x.Item1 == module.ToString())) continue; var wafers = WaferManager.Instance.GetWafers(module); if (wafers == null) continue; if (SC.GetValue("System.EnableWarningFailedWafer")) { if (wafers.ToList().Any(x => x.ProcessState == EnumWaferProcessStatus.Failed)) { reason = $"{module} has failed wafers."; return false; } } foreach (var wafer in wafers) { if (wafer.IsEmpty) continue; if (wafer.ProcessState != EnumWaferProcessStatus.Idle) { if (SC.GetValue("System.EnableWarningWaferProcessState")) { if (wafer.WaferType == WaferType.P && isNeedCheckP) { reason = $"{(ModuleName)wafer.OriginStation} {wafer.WaferType} wafer already completed process."; return false; } if (isNeedCheckMonitor) { if (wafer.WaferType == WaferType.M) { reason = $"{(ModuleName)wafer.OriginStation} {wafer.WaferType} wafer already completed process."; return false; } } } else { wafer.ProcessState = EnumWaferProcessStatus.Idle; } } if (wafer.WaferType == WaferType.ED || wafer.WaferType == WaferType.SD) wafer.ProcessState = EnumWaferProcessStatus.Idle; } } } return true; } public bool CreateProcessJob(out ProcessJobInfo pj, params object[] objs) { var param = (Dictionary)objs[0]; pj = null; foreach (var module in Singleton.Instance.Modules.Keys) { var lpModule = Singleton.Instance.Modules[module] as LoadPortModule; if (lpModule != null) { if (lpModule.FsmState == (int)LoadPortModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (lpModule.FsmState == (int)LoadPortModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } var fimsModule = Singleton.Instance.Modules[module] as FIMSModule; if (fimsModule != null) { if (fimsModule.FsmState == (int)FIMSModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (fimsModule.FsmState == (int)FIMSModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } var boatModule = Singleton.Instance.Modules[module] as BoatModule; if (boatModule != null) { if (boatModule.FsmState == (int)BoatModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (boatModule.FsmState == (int)BoatModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } var carrierRobotModule = Singleton.Instance.Modules[module] as CarrierRobotModule; if (carrierRobotModule != null) { if (carrierRobotModule.FsmState == (int)CarrierRobotModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (carrierRobotModule.FsmState == (int)CarrierRobotModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } var waferRobotModule = Singleton.Instance.Modules[module] as WaferRobotModule; if (waferRobotModule != null) { if (waferRobotModule.FsmState == (int)WaferRobotModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (waferRobotModule.FsmState == (int)WaferRobotModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } var pmModule = Singleton.Instance.Modules[module] as PMModule; if (pmModule != null) { if (pmModule.FsmState == (int)PMModule.STATE.Init) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is init state"); return false; } if (pmModule.FsmState == (int)PMModule.STATE.Error) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"{module} is error state"); return false; } } } if (!Singleton.Instance.GetJobRecipeInfor((string)param["JobRecipe"], out string processRecipe, out string layoutRecipe, out int coolTime, out string reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); return false; } if (string.IsNullOrEmpty(layoutRecipe)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set("Parameter not valid, Layout Recipe is null"); return false; } var path = $"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Layout\\{layoutRecipe}.rcp"; if (!File.Exists(path)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Layout \"{layoutRecipe}\" not exist."); return false; } path = $"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Process\\{processRecipe}.rcp"; if (!File.Exists(path)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Process recipe \"{processRecipe}\" not exist."); return false; } if (!RecipeParser.Parse(processRecipe, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out reason, "Process")) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Load process recipe {processRecipe} failed, {reason}"); return false; } List>> useStockers = new List>>(); if (RecipeParser.LayoutRecipeParse(layoutRecipe, ModuleName.PM1.ToString(), out RecipeLayoutEntityNormal layoutRecipeDataNormal, out RecipeLayoutEntityExpert layoutRecipeDataExpert, out reason)) { if (param.ContainsKey("CarrierPara")) { //Stocker1,P_00000036,25,Exist,1111111111111111111111111,LP1;Stocker2,P_00000037,25,Exist,1111111111111111111111111,LP2 var paras = param["CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { foreach (var item in paras) { //Stocker13,,21/22/23/24/25" var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var pStocker = GetModule(arry[0]) as SchedulerStocker; if (pStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("P") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return false; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } if (param.ContainsKey("mCarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["mCarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M")) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return false; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } if (param.ContainsKey("m1CarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["m1CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M1") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return false; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } if (param.ContainsKey("m2CarrierPara")) { //Stocker14,P_00000014;Stocker15,P_00000015 var paras = param["m2CarrierPara"].ToString().Split(';'); if (paras != null && paras.Length > 0) { if (!string.IsNullOrEmpty(paras[0])) { foreach (var item in paras) { var arry = item.Split(','); if (arry != null && arry.Length >= 2) { var mStocker = GetModule(arry[0]) as SchedulerStocker; if (mStocker != null && (SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("M2") || SC.GetStringValue($"System.Stocker.{arry[0]}WaferType").Contains("None"))) { var slots = new List(); if (arry.Length >= 3) { var slotParas = arry[2].Split('/').ToList(); if (slotParas != null && slotParas.Count > 0) { foreach (var slotPara in slotParas) { var ret = int.TryParse(slotPara, out int slot); if (ret && slot - 1 >= 0 && !slots.Any(x => x == slot - 1)) { if (_lstProcessJobs.Any()) { foreach (var job in _lstProcessJobs) { if (job.Stockers.Any(x => x.Item1 == arry[0] && x.Item3.Contains(slot - 1))) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Create job failed, already contains {arry[0]}.{slot} in previous process job"); return false; } } } slots.Add(slot - 1); } } } } useStockers.Add(Tuple.Create(arry[0], arry[1], slots)); } } } } } } } if (Singleton.Instance.FaControlState != FAControlState.OnlineRemote.ToString()) useStockers.Sort(compare); foreach (var s in _lstSideDummyStocker) { if (CarrierManager.Instance.CheckHasCarrier(s.Module, 0) && CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierType == CarrierType.SD) useStockers.Add(Tuple.Create(s.Module.ToString(), CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierId, new List())); else { bool onRobot = false; if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier.CarrierType == CarrierType.SD && carrier.InternalModuleName == s.Module) { useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); onRobot = true; } } if (!onRobot) { bool inFIMS = false; foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (!carrier.IsEmpty && carrier.CarrierType == CarrierType.SD && carrier.InternalModuleName == s.Module) { inFIMS = true; useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); } } if (!inFIMS && CarrierManager.Instance.GetLocationByInternalCarrierModuleName(s.Module, CarrierType.SD) != null) useStockers.Add(Tuple.Create(s.Module.ToString(), "", new List())); } } } foreach (var s in _lstExtraDummyStocker) { if (CarrierManager.Instance.CheckHasCarrier(s.Module, 0) && CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierType == CarrierType.ED) useStockers.Add(Tuple.Create(s.Module.ToString(), CarrierManager.Instance.GetCarrier(s.Module, 0).CarrierId, new List())); else { bool onRobot = false; if (CarrierManager.Instance.CheckHasCarrier(ModuleName.CarrierRobot, 0)) { var carrier = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot, 0); if (carrier.CarrierType == CarrierType.ED && carrier.InternalModuleName == s.Module) { useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); onRobot = true; } } if (!onRobot) { bool inFIMS = false; foreach (var fims in _lstFIMSs) { if (!fims.IsOnline) continue; var carrier = CarrierManager.Instance.GetCarrier(fims.Module, 0); if (!carrier.IsEmpty && carrier.CarrierType == CarrierType.ED && carrier.InternalModuleName == s.Module) { inFIMS = true; useStockers.Add(Tuple.Create(s.Module.ToString(), carrier.CarrierId, new List())); } } if (!inFIMS && CarrierManager.Instance.GetLocationByInternalCarrierModuleName(s.Module, CarrierType.SD) != null) useStockers.Add(Tuple.Create(s.Module.ToString(), "", new List())); } } } var wafers = WaferManager.Instance.GetWafers(_pm1.Module); if (wafers.Any(x => !x.IsEmpty) && !_lstProcessJobs.Any(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused) && SC.GetValue("System.IsEnableDummyWaferDischarge")) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have wafer in boat"); return false; } if (wafers.Any(x => !x.IsEmpty && x.WaferType == WaferType.None)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have unknown wafer in boat"); return false; } var robotWafers = WaferManager.Instance.GetWafers(ModuleName.WaferRobot); if (robotWafers.Any(x => !x.IsEmpty) && !_lstProcessJobs.Any(x => x.State == EnumProcessJobState.Processing || x.State == EnumProcessJobState.Paused)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have wafer in wafer robot"); return false; } if (robotWafers.Any(x => !x.IsEmpty && x.WaferType == WaferType.None)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have unknown wafer in wafer robot"); return false; } if (!CheckWaferStatus(useStockers, true, true, out reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); return false; } //if (!CheckWaferStatus(useStockers, out reason)) //{ // Singleton.Instance.ChargeWaferJobStartFailedWarning.Set(reason); // return false; //} foreach (var stocker in useStockers) { if (CarrierManager.Instance.CheckHasCarrier($"{stocker.Item1}", 0) && CarrierManager.Instance.GetCarrier($"{stocker.Item1}", 0).InternalModuleName.ToString() != stocker.Item1) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Carrier of {stocker.Item1} is not match stocker module name {CarrierManager.Instance.GetCarrier($"{stocker.Item1}", 0).InternalModuleName}"); return false; } } bool isOnlyCharge = false; if (param.ContainsKey("Charge")) { bool.TryParse(param["Charge"].ToString(), out isOnlyCharge); } var pjJobId = param["PJID"].ToString(); if (_lstProcessJobs.Exists(x => x.Name == pjJobId)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"Already have the same pj id={pjJobId}"); return false; } pj = new ProcessJobInfo(); pj.Name = pjJobId; pj.JobRecipe = param.ContainsKey("JobRecipe") ? param["JobRecipe"].ToString() : ""; pj.ProcessRecipe = processRecipe; pj.LayoutRecipe = layoutRecipe; pj.ControlJobName = ""; pj.SetState(EnumProcessJobState.Queued); pj.CreateTime = DateTime.Now; pj.Stockers = useStockers; pj.SlotWafers = new List>(); pj.ProcessingState = EnumProcessingState.WaitingMaterial; pj.CoolTimeSec = coolTime; //pj.IsEmptyLayout = !layoutRecipeDataExpert.Items.Any(x => x != "----"); //pj.IsOnlyCharge = isOnlyCharge; if (!CheckChargeRule(pj, out bool waferShort, false, true, out reason)) { Singleton.Instance.ChargeWaferJobStartFailedWarning.Set($"layout recipe {layoutRecipe} check charge rule failed, {reason}"); return false; } _lstProcessJobs.Add(pj); //_faCallback.JobCreated(pj); return true; } #endregion private bool InvokeCoolingAbort(string arg1, object[] args) { var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing && x.ProcessingState == EnumProcessingState.Cooling); if (pj != null) { pj.CoolTimeSec = 0; } return true; } private bool InvokeCoolingModify(string arg1, object[] args) { var pj = _lstProcessJobs.FirstOrDefault(x => x.State == EnumProcessJobState.Processing && x.ProcessingState == EnumProcessingState.Cooling); if (pj != null && args != null && args.Length > 0) { float.TryParse(args[0].ToString(), out float addCoolTime); pj.CoolTimeSec = (int)addCoolTime; } return true; } private List GetBoatSlotMap() { var wafers = WaferManager.Instance.GetWafers(ModuleName.PM1); if (wafers != null) { List slotMap = new List(); foreach (var wafer in wafers) { if (wafer == null || wafer.IsEmpty) { slotMap.Add(""); continue; } if (wafer.WaferType == WaferType.ED || wafer.WaferType == WaferType.SD) slotMap.Add("filler"); else slotMap.Add(wafer.WaferID); } return slotMap; } return null; } } }