using Aitex.Common.Util; using Aitex.Core.RT.ConfigCenter; using Aitex.Core.RT.Log; using Aitex.Core.Util; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.RecipeCenter; using CyberX8_Core; using CyberX8_RT.Modules; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CyberX8_RT.Modules.Prewet; using MECF.Framework.Common.CommonData; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.SCCore; using CyberX8_RT.Modules.Rinse; namespace CyberX8_RT.Schedulers.Prewet { public class SchedulerPrewet : SchedulerModule { private enum PrewetOperation { None, RunRecipe, WaitForPick, Keepwet } #region 内部变量 /// /// Prewet实体 /// private PrewetEntity _prewetEntity; /// /// keep wet次数 /// private int _keepwetCount = 0; /// /// keep wet限制次数 /// private int _keepwetLimit = 0; /// /// 当前操作 /// private PrewetOperation _currentOperation=PrewetOperation.None; #endregion #region 属性 /// /// 是否空闲 /// public override bool IsIdle { get { return _state == RState.End; } } /// /// 是否错误 /// public override bool IsError { get { return _state == RState.Failed || _state == RState.Timeout; } } #endregion /// /// 构造函数 /// /// public SchedulerPrewet(ModuleName moduleName) : base(moduleName.ToString()) { _prewetEntity = Singleton.Instance.GetModule(moduleName.ToString()); } /// /// 执行 /// /// /// public override bool RunProcess(object recipe, object parameter, List syncModuleMessages) { if (!(recipe is PwtRecipe)) { _state = RState.Failed; LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), "recipe is invalid"); return false; } _keepwetCount = 0; _keepwetLimit = SC.GetValue("Prewet.KeepWetMaxLimit"); PwtRecipe pwtRecipe = (PwtRecipe)recipe; bool result = _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.RunRecipe, pwtRecipe,1); if (result) { _state = RState.Running; _currentOperation = PrewetOperation.RunRecipe; } return result; } /// /// 监控执行 /// /// public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer) { bool exsitEnableCell = false; if (_prewetEntity.IsError) { _state=RState.Failed; return true; } if (_prewetEntity.State == (int)PrewetState.WaitForPick || (_prewetEntity.IsIdle && _prewetEntity.WaferHolderInfo == null)) { _state = RState.End; _currentOperation = PrewetOperation.None; return true; } if (_prewetEntity.State==(int)PrewetState.RunRecipeComplete&&_currentOperation==PrewetOperation.RunRecipe) { CheckNextModuleCondition(schedulerSequence,ref exsitEnableCell); } else if((_prewetEntity.State==(int)PrewetState.DelayKeepwetComplete)&&_currentOperation==PrewetOperation.Keepwet) { if(_keepwetCount>_keepwetLimit) { LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"keepwet count {_keepwetCount} over limit {_keepwetLimit}"); _state = RState.Failed; } else { CheckNextModuleTimeToReady(schedulerSequence,ref exsitEnableCell); } } else if (_prewetEntity.State == (int)PrewetState.DelayKeepweting && _currentOperation == PrewetOperation.Keepwet) { CheckNextModuleTimeToReady(schedulerSequence, ref exsitEnableCell); } return true; } /// /// 检验下一个 /// /// /// private void CheckNextModuleCondition(SchedulerSequence sequence,ref bool existEnableCell) { PwtRecipe pwtRecipe = (PwtRecipe)sequence.Recipe; if(!pwtRecipe.KeepWet) { NotifyPrewetReadyForPick("prewet no keepwet"); return; } CheckNextModuleTimeToReady(sequence,ref existEnableCell); } /// /// 检验下一模块剩余时间 /// /// private void CheckNextModuleTimeToReady(SchedulerSequence sequence,ref bool existEnableCell) { int idleKeepwetPauseBetweenScanSeconds = SC.GetValue("Prewet.IdleKeepwetPauseBetweenScanSeconds"); ModuleType nextModuleType = sequence.NextModuleType; if (nextModuleType == ModuleType.Metal) { if (!(sequence.NextRecipe is DepRecipe)) { NotifyPrewetReadyForPick("sequence nextRecipe is not deprecipe"); } else { DepRecipe depRecipe = sequence.NextRecipe as DepRecipe; ModuleName moduleName = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, "",sequence.SequenceType,ref existEnableCell); if (moduleName != ModuleName.Unknown) { IModuleEntity moduleEntity = Singleton.Instance.GetModule(moduleName.ToString()); if (SchedulerSequenceManager.Instance.CheckMetalCellRecipeTimeAvaible(moduleEntity, depRecipe)) { if (moduleEntity.IsIdle) { NotifyPrewetReadyForPick($"{moduleEntity.Module} Is idle"); } else { NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}"); } } else { NotifyPrewetKeepWet(); } } else { if (existEnableCell) { NotifyPrewetKeepWet(); } else { NotifyPrewetReadyForPick($"no enable metal"); } } } } else { ModuleName moduleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextModuleType,sequence.SequenceType); if (moduleName != ModuleName.Unknown) { IModuleEntity moduleEntity = Singleton.Instance.GetModule(moduleName.ToString()); if (moduleEntity.IsIdle) { NotifyPrewetReadyForPick($"{moduleEntity.Module} is idle"); } else { if (moduleEntity.TimeToReady <= idleKeepwetPauseBetweenScanSeconds) { NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}"); } else { NotifyPrewetKeepWet(); } } } else { NotifyPrewetKeepWet(); } } } /// /// 通知Prewet准备Process for pick /// private void NotifyPrewetReadyForPick(string reason) { bool result= _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.PrepareToPick); if (result) { _currentOperation = PrewetOperation.WaitForPick; LOG.WriteLog(eEvent.INFO_PREWET, Module.ToString(), reason); } } /// /// 通知Prewet准备Keep Wet /// private void NotifyPrewetKeepWet() { if (_prewetEntity.State == (int)PrewetState.DelayKeepweting) { return; } bool result= _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, ModuleName.Prewet1.ToString(), (int)PrewetMsg.DelayKeepwet); if(result) { if (_currentOperation != PrewetOperation.Keepwet) { _currentOperation = PrewetOperation.Keepwet; } _keepwetCount++; } } /// /// 检验前置条件 /// /// /// /// public override bool CheckPrecondition(List schedulerSequences, int sequenceIndex, object parameter,string materialId,ref string reason) { if (_state == RState.Running) { reason = "scheduler module is already running"; return false; } if (_prewetEntity.State!=(int)PrewetState.WaitForPlace) { reason = "prewet state is not WaitForPlace"; return false; } if(_prewetEntity.WaferHolderInfo==null) { reason = "prewet has no wafer shuttle"; return false; } if (_prewetEntity.WaferHolderInfo.Id != materialId) { reason = $"{_prewetEntity.Module} wafer shuttle {_prewetEntity.WaferHolderInfo.Id} is not matched with {materialId}"; return false; } _currentOperation = PrewetOperation.None; return true; } } }