SchedulerPrewet.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. using Aitex.Common.Util;
  2. using Aitex.Core.RT.ConfigCenter;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.Util;
  5. using MECF.Framework.Common.Equipment;
  6. using MECF.Framework.Common.RecipeCenter;
  7. using CyberX8_Core;
  8. using CyberX8_RT.Modules;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using CyberX8_RT.Modules.Prewet;
  15. using MECF.Framework.Common.CommonData;
  16. using Aitex.Core.RT.Fsm;
  17. using Aitex.Core.RT.SCCore;
  18. using CyberX8_RT.Modules.Rinse;
  19. namespace CyberX8_RT.Schedulers.Prewet
  20. {
  21. public class SchedulerPrewet : SchedulerModule
  22. {
  23. private enum PrewetOperation
  24. {
  25. None,
  26. RunRecipe,
  27. WaitForPick,
  28. Keepwet
  29. }
  30. #region 内部变量
  31. /// <summary>
  32. /// Prewet实体
  33. /// </summary>
  34. private PrewetEntity _prewetEntity;
  35. /// <summary>
  36. /// keep wet次数
  37. /// </summary>
  38. private int _keepwetCount = 0;
  39. /// <summary>
  40. /// keep wet限制次数
  41. /// </summary>
  42. private int _keepwetLimit = 0;
  43. /// <summary>
  44. /// 当前操作
  45. /// </summary>
  46. private PrewetOperation _currentOperation=PrewetOperation.None;
  47. #endregion
  48. #region 属性
  49. /// <summary>
  50. /// 是否空闲
  51. /// </summary>
  52. public override bool IsIdle
  53. {
  54. get { return _state == RState.End; }
  55. }
  56. /// <summary>
  57. /// 是否错误
  58. /// </summary>
  59. public override bool IsError
  60. {
  61. get { return _state == RState.Failed || _state == RState.Timeout; }
  62. }
  63. #endregion
  64. /// <summary>
  65. /// 构造函数
  66. /// </summary>
  67. /// <param name="module"></param>
  68. public SchedulerPrewet(ModuleName moduleName) : base(moduleName.ToString())
  69. {
  70. _prewetEntity = Singleton<RouteManager>.Instance.GetModule<PrewetEntity>(moduleName.ToString());
  71. }
  72. /// <summary>
  73. /// 执行
  74. /// </summary>
  75. /// <param name="parameter"></param>
  76. /// <returns></returns>
  77. public override bool RunProcess(object recipe, object parameter, List<SchedulerSyncModuleMessage> syncModuleMessages)
  78. {
  79. if (!(recipe is PwtRecipe))
  80. {
  81. _state = RState.Failed;
  82. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), "recipe is invalid");
  83. return false;
  84. }
  85. _keepwetCount = 0;
  86. _keepwetLimit = SC.GetValue<int>("Prewet.KeepWetMaxLimit");
  87. PwtRecipe pwtRecipe = (PwtRecipe)recipe;
  88. bool result = _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.RunRecipe, pwtRecipe,1);
  89. if (result)
  90. {
  91. _state = RState.Running;
  92. _currentOperation = PrewetOperation.RunRecipe;
  93. }
  94. return result;
  95. }
  96. /// <summary>
  97. /// 监控执行
  98. /// </summary>
  99. /// <returns></returns>
  100. public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer)
  101. {
  102. bool exsitEnableCell = false;
  103. if (_prewetEntity.IsError)
  104. {
  105. _state=RState.Failed;
  106. return true;
  107. }
  108. if (_prewetEntity.State == (int)PrewetState.WaitForPick || (_prewetEntity.IsIdle && _prewetEntity.WaferHolderInfo == null))
  109. {
  110. _state = RState.End;
  111. _currentOperation = PrewetOperation.None;
  112. return true;
  113. }
  114. if (_prewetEntity.State==(int)PrewetState.RunRecipeComplete&&_currentOperation==PrewetOperation.RunRecipe)
  115. {
  116. CheckNextModuleCondition(schedulerSequence,ref exsitEnableCell);
  117. }
  118. else if((_prewetEntity.State==(int)PrewetState.DelayKeepwetComplete)&&_currentOperation==PrewetOperation.Keepwet)
  119. {
  120. if(_keepwetCount>_keepwetLimit)
  121. {
  122. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"keepwet count {_keepwetCount} over limit {_keepwetLimit}");
  123. _state = RState.Failed;
  124. }
  125. else
  126. {
  127. CheckNextModuleTimeToReady(schedulerSequence,ref exsitEnableCell);
  128. }
  129. }
  130. else if (_prewetEntity.State == (int)PrewetState.DelayKeepweting && _currentOperation == PrewetOperation.Keepwet)
  131. {
  132. CheckNextModuleTimeToReady(schedulerSequence, ref exsitEnableCell);
  133. }
  134. return true;
  135. }
  136. /// <summary>
  137. /// 检验下一个
  138. /// </summary>
  139. /// <param name="sequence"></param>
  140. /// <returns></returns>
  141. private void CheckNextModuleCondition(SchedulerSequence sequence,ref bool existEnableCell)
  142. {
  143. PwtRecipe pwtRecipe = (PwtRecipe)sequence.Recipe;
  144. if(!pwtRecipe.KeepWet)
  145. {
  146. NotifyPrewetReadyForPick("prewet no keepwet");
  147. return;
  148. }
  149. CheckNextModuleTimeToReady(sequence,ref existEnableCell);
  150. }
  151. /// <summary>
  152. /// 检验下一模块剩余时间
  153. /// </summary>
  154. /// <param name="sequence"></param>
  155. private void CheckNextModuleTimeToReady(SchedulerSequence sequence,ref bool existEnableCell)
  156. {
  157. int idleKeepwetPauseBetweenScanSeconds = SC.GetValue<int>("Prewet.IdleKeepwetPauseBetweenScanSeconds");
  158. ModuleType nextModuleType = sequence.NextModuleType;
  159. if (nextModuleType == ModuleType.Metal)
  160. {
  161. if (!(sequence.NextRecipe is DepRecipe))
  162. {
  163. NotifyPrewetReadyForPick("sequence nextRecipe is not deprecipe");
  164. }
  165. else
  166. {
  167. DepRecipe depRecipe = sequence.NextRecipe as DepRecipe;
  168. ModuleName moduleName = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, "",sequence.SequenceType,ref existEnableCell);
  169. if (moduleName != ModuleName.Unknown)
  170. {
  171. IModuleEntity moduleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(moduleName.ToString());
  172. if (SchedulerSequenceManager.Instance.CheckMetalCellRecipeTimeAvaible(moduleEntity, depRecipe))
  173. {
  174. if (moduleEntity.IsIdle)
  175. {
  176. NotifyPrewetReadyForPick($"{moduleEntity.Module} Is idle");
  177. }
  178. else
  179. {
  180. NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}");
  181. }
  182. }
  183. else
  184. {
  185. NotifyPrewetKeepWet();
  186. }
  187. }
  188. else
  189. {
  190. if (existEnableCell)
  191. {
  192. NotifyPrewetKeepWet();
  193. }
  194. else
  195. {
  196. NotifyPrewetReadyForPick($"no enable metal");
  197. }
  198. }
  199. }
  200. }
  201. else
  202. {
  203. ModuleName moduleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextModuleType,sequence.SequenceType);
  204. if (moduleName != ModuleName.Unknown)
  205. {
  206. IModuleEntity moduleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(moduleName.ToString());
  207. if (moduleEntity.IsIdle)
  208. {
  209. NotifyPrewetReadyForPick($"{moduleEntity.Module} is idle");
  210. }
  211. else
  212. {
  213. if (moduleEntity.TimeToReady <= idleKeepwetPauseBetweenScanSeconds)
  214. {
  215. NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}");
  216. }
  217. else
  218. {
  219. NotifyPrewetKeepWet();
  220. }
  221. }
  222. }
  223. else
  224. {
  225. NotifyPrewetKeepWet();
  226. }
  227. }
  228. }
  229. /// <summary>
  230. /// 通知Prewet准备Process for pick
  231. /// </summary>
  232. private void NotifyPrewetReadyForPick(string reason)
  233. {
  234. bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(),
  235. (int)PrewetMsg.PrepareToPick);
  236. if (result)
  237. {
  238. _currentOperation = PrewetOperation.WaitForPick;
  239. LOG.WriteLog(eEvent.INFO_PREWET, Module.ToString(), reason);
  240. }
  241. }
  242. /// <summary>
  243. /// 通知Prewet准备Keep Wet
  244. /// </summary>
  245. private void NotifyPrewetKeepWet()
  246. {
  247. if (_prewetEntity.State == (int)PrewetState.DelayKeepweting)
  248. {
  249. return;
  250. }
  251. bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, ModuleName.Prewet1.ToString(),
  252. (int)PrewetMsg.DelayKeepwet);
  253. if(result)
  254. {
  255. if (_currentOperation != PrewetOperation.Keepwet)
  256. {
  257. _currentOperation = PrewetOperation.Keepwet;
  258. }
  259. _keepwetCount++;
  260. }
  261. }
  262. /// <summary>
  263. /// 检验前置条件
  264. /// </summary>
  265. /// <param name="sequenceIndex"></param>
  266. /// <param name="parameter"></param>
  267. /// <returns></returns>
  268. public override bool CheckPrecondition(List<SchedulerSequence> schedulerSequences, int sequenceIndex, object parameter,string materialId,ref string reason)
  269. {
  270. if (_state == RState.Running)
  271. {
  272. reason = "scheduler module is already running";
  273. return false;
  274. }
  275. if (_prewetEntity.State!=(int)PrewetState.WaitForPlace)
  276. {
  277. reason = "prewet state is not WaitForPlace";
  278. return false;
  279. }
  280. if(_prewetEntity.WaferHolderInfo==null)
  281. {
  282. reason = "prewet has no wafer shuttle";
  283. return false;
  284. }
  285. if (_prewetEntity.WaferHolderInfo.Id != materialId)
  286. {
  287. reason = $"{_prewetEntity.Module} wafer shuttle {_prewetEntity.WaferHolderInfo.Id} is not matched with {materialId}";
  288. return false;
  289. }
  290. _currentOperation = PrewetOperation.None;
  291. return true;
  292. }
  293. }
  294. }