SchedulerPM.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. using System.Diagnostics;
  2. using Aitex.Core.Common;
  3. using Aitex.Core.RT.DataCenter;
  4. using Aitex.Core.RT.Event;
  5. using Aitex.Core.RT.Fsm;
  6. using Aitex.Core.RT.Log;
  7. using Aitex.Core.RT.OperationCenter;
  8. using Aitex.Core.RT.SCCore;
  9. using Aitex.Core.Util;
  10. using Aitex.Sorter.Common;
  11. using MECF.Framework.Common.DataCenter;
  12. using MECF.Framework.Common.Equipment;
  13. using MECF.Framework.Common.Schedulers;
  14. using MECF.Framework.Common.SubstrateTrackings;
  15. using MECF.Framework.RT.ModuleLibrary.PMModules;
  16. using MECF.Framework.RT.ModuleLibrary.SystemModules;
  17. namespace EfemDualSchedulerLib.Schedulers
  18. {
  19. public class SchedulerPM : SchedulerModule
  20. {
  21. public override bool IsAvailable
  22. {
  23. get { return _pm.IsReady && _pm.IsOnline && CheckTaskDone() && !_waitCompletejobClean; }
  24. }
  25. public override bool IsOnline
  26. {
  27. get { return _pm.IsOnline; }
  28. }
  29. public override bool IsError
  30. {
  31. get { return _pm.IsError; }
  32. }
  33. public bool IsIdle
  34. {
  35. get { return _pm.IsReady && _pm.IsOnline && CheckTaskDone(); }
  36. }
  37. private PMModuleBase _pm = null;
  38. private ModuleName _taskRobot;
  39. private EnumTransferType _taskTransferType;
  40. private int _taskSlot;
  41. private DeviceTimer _timer = new DeviceTimer();
  42. protected readonly string _statNameProcessedWaferCount;//zyx add 2021.8.6
  43. protected readonly string _statNameProcessTime;
  44. public RD_TRIG IdlePurgeTrig { get; set; } = new RD_TRIG();
  45. public Stopwatch IdlePurgeTimer { get; set; } = new Stopwatch();
  46. public int IdlePurgeTime { get; set; }
  47. public int IdlePurgeNextRunTime { get; set; }
  48. public RD_TRIG IdleCleanTrig { get; set; } = new RD_TRIG();
  49. public Stopwatch IdleCleanTimer { get; set; } = new Stopwatch();
  50. public int IdleCleanTime { get; set; }
  51. public int IdleCleanNextRunTime { get; set; }
  52. private bool _waitPreJobClean;
  53. private bool _waitCompletejobClean;
  54. private R_TRIG _trigIdleCleanFailed = new R_TRIG();
  55. private R_TRIG _trigIdlePurgeFailed = new R_TRIG();
  56. public RD_TRIG PreJobCleanTrig { get; set; } = new RD_TRIG();
  57. public Stopwatch PreJobCleanTimer { get; set; } = new Stopwatch();
  58. public int PreJobCleanTime { get; set; }
  59. //protected readonly string _statNameRFTime;
  60. //protected readonly string _statNameMWTime;
  61. public SchedulerPM(ModuleName chamber) : base(chamber.ToString())
  62. {
  63. _pm = EquipmentManager.Modules[chamber] as PMModuleBase;
  64. _pm.IsOnline = true;
  65. _statNameProcessedWaferCount = $"{chamber}.ProcessedWaferCount";
  66. _statNameProcessTime = $"{chamber}.ProcessTime";
  67. //_statNameRFTime = $"{chamber}.RFTime";
  68. //_statNameMWTime = $"{chamber}.MWTime";
  69. System.Diagnostics.Trace.Assert(_pm != null);
  70. }
  71. public bool CheckTempReady(double temp1, double temp2)
  72. {
  73. return _pm.CheckTempReady(temp1, temp2);
  74. }
  75. public override bool IsReadyForPick(ModuleName robot, Hand blade, int slot)
  76. {
  77. return _pm.CheckReadyForTransfer(robot, blade, slot, EnumTransferType.Pick, out _)
  78. && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(_module), slot);
  79. }
  80. public override bool IsReadyForPlace(ModuleName robot, Hand blade, int slot)
  81. {
  82. return _pm.CheckReadyForTransfer(robot, blade, slot, EnumTransferType.Place, out _)
  83. && WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(_module), slot);
  84. }
  85. public override bool PrepareTransfer(ModuleName robot, EnumTransferType type, int slot)
  86. {
  87. _task = TaskType.PrepareTransfer;
  88. _taskRobot = robot;
  89. _taskSlot = slot;
  90. _taskTransferType = type;
  91. if (!_pm.PrepareTransfer(robot, Hand.Blade1, slot, type, 0, 0, false, out string reason))
  92. {
  93. LOG.Write(reason);
  94. return false;
  95. }
  96. LogTaskStart(_task, $"{robot} {type} slot {slot + 1}");
  97. return true;
  98. }
  99. public bool Preheating(double temperature1, double temperature2)
  100. {
  101. _task = TaskType.Heating;
  102. if (_pm.InvokePreHeat(temperature1, temperature2))
  103. {
  104. LOG.Write("Can not PreHeat");
  105. return false;
  106. }
  107. LogTaskStart(_task, $"preheat to {temperature1},{temperature2}");
  108. return true;
  109. }
  110. public bool IsPrepareTransfer(ModuleName robot, EnumTransferType type, int slot)
  111. {
  112. return _task == TaskType.PrepareTransfer && _taskRobot == robot && _taskSlot == slot &&
  113. _taskTransferType == type;
  114. }
  115. public override bool Process(string recipeName, bool isCleanRecipe, bool withWafer)
  116. {
  117. _task = TaskType.Process;
  118. //if (SC.GetValue<bool>("System.IsATMMode"))
  119. //{
  120. // _timer.Start(SC.GetValue<int>("System.ATMProcessDelayTime") * 1000);
  121. // //_entityTaskToken = (int)FSM_MSG.TIMER;
  122. // WaferManager.Instance.GetWafer(Module, 0).ProcessState = EnumWaferProcessStatus.InProcess;
  123. // WaferManager.Instance.GetWafer(Module, 1).ProcessState = EnumWaferProcessStatus.InProcess;
  124. //}
  125. //else
  126. {
  127. if (!_pm.Process(recipeName, isCleanRecipe, withWafer, out string reason))
  128. {
  129. LOG.Write(reason);
  130. return false;
  131. }
  132. }
  133. UpdateStats_data(recipeName, isCleanRecipe);
  134. LogTaskStart(_task, $"recipe: {recipeName}, clean: {isCleanRecipe}, with wafer: {withWafer}");
  135. return true;
  136. }
  137. public virtual void UpdateStats_data(string recipeName, bool isClean)
  138. {
  139. if (!isClean)
  140. {
  141. int value1 = StatsDataManager.Instance.Increase(_statNameProcessedWaferCount);
  142. int value2 = StatsDataManager.Instance.Increase(_statNameProcessTime);
  143. LOG.Write($"{_statNameProcessedWaferCount} counter increase 1 to {value1}");
  144. LOG.Write($"{_statNameProcessTime} counter increase 1 to {value2}");
  145. }
  146. }
  147. public bool CheckTaskDone()
  148. {
  149. bool ret = false;
  150. switch (_task)
  151. {
  152. case TaskType.None:
  153. ret = true;
  154. break;
  155. case TaskType.PrepareTransfer:
  156. ret = _pm.CheckReadyForTransfer(_taskRobot, Hand.Blade1, _taskSlot, _taskTransferType, out _);
  157. break;
  158. case TaskType.Heating:
  159. ret = true;
  160. break;
  161. case TaskType.Process:
  162. case TaskType.IdlePurgeProcess:
  163. case TaskType.IdleCleanProcess:
  164. case TaskType.PreJobProcess:
  165. case TaskType.CompleteJobProcess:
  166. //if (SC.GetValue<bool>("System.IsATMMode"))
  167. //{
  168. // ret = _timer.IsTimeout();
  169. // if (ret)
  170. // {
  171. // WaferManager.Instance.GetWafer(Module, 0).ProcessState = EnumWaferProcessStatus.Completed;
  172. // WaferManager.Instance.GetWafer(Module, 1).ProcessState = EnumWaferProcessStatus.Completed;
  173. // }
  174. //}
  175. //else
  176. {
  177. ret = _pm.IsReady;
  178. }
  179. break;
  180. }
  181. if (ret && _task != TaskType.None)
  182. {
  183. LogTaskDone(_task, "");
  184. _task = TaskType.None;
  185. }
  186. return ret;
  187. }
  188. public bool CheckInProcess()
  189. {
  190. return _task == TaskType.Process;
  191. }
  192. public bool CloseSlitValve()
  193. {
  194. return _pm.CloseSlitValve(out _);
  195. }
  196. public bool CheckSlitValveClose()
  197. {
  198. return _pm.CheckSlitValveClose();
  199. }
  200. public bool Monitor()
  201. {
  202. return true;
  203. }
  204. #region clean task
  205. public void InitClean()
  206. {
  207. DATA.Subscribe($"{Module}.IdlePurgeNextRunTime", () => IdlePurgeNextRunTime);
  208. DATA.Subscribe($"{Module}.IdleCleanNextRunTime", () => IdleCleanNextRunTime);
  209. OP.Subscribe($"{Module}.ResetIdlePurgeTime", (string cmd, object[] args) =>
  210. {
  211. ResetIdlePurgeTime();
  212. return true;
  213. });
  214. OP.Subscribe($"{Module}.ResetIdleCleanTime", (string cmd, object[] args) =>
  215. {
  216. ResetIdleCleanTime();
  217. return true;
  218. });
  219. }
  220. internal void ResetIdlePurgeTime()
  221. {
  222. IdlePurgeTimer.Restart();
  223. }
  224. internal void ResetIdleCleanTime()
  225. {
  226. IdleCleanTimer.Restart();
  227. }
  228. public bool ResetClean(bool resetPurge, bool resetClean, bool jobClean)
  229. {
  230. if (resetPurge)
  231. {
  232. IdlePurgeTrig.RST = true;
  233. IdlePurgeTimer.Stop();
  234. IdlePurgeTime = 0;
  235. }
  236. if (resetClean)
  237. {
  238. IdleCleanTrig.RST = true;
  239. IdleCleanTimer.Stop();
  240. IdleCleanTime = 0;
  241. }
  242. if (jobClean)
  243. {
  244. _waitPreJobClean = false;
  245. _waitCompletejobClean = false;
  246. PreJobCleanTrig.RST = true;
  247. PreJobCleanTimer.Stop();
  248. }
  249. return true;
  250. }
  251. public void MonitorCleanTasks()
  252. {
  253. var hasWafer = WaferManager.Instance.CheckHasWafer(Module, 0) && WaferManager.Instance.CheckHasWafer(Module, 1);
  254. var enablePurge = false;//SC.GetValue<bool>($"{Module}.IdlePurge.IsEnabled");
  255. var enableClean = SC.GetValue<bool>($"{Module}.IdleClean.IsEnabled");
  256. #region Idle Purge
  257. IdlePurgeTrig.CLK = (IsIdle || _task != TaskType.IdlePurgeProcess) && enablePurge && !hasWafer;
  258. if (IdlePurgeTrig.R)
  259. {
  260. LOG.Write($"{Module} idle purge start calc elapse time");
  261. IdlePurgeTimer.Restart();
  262. }
  263. if (IdlePurgeTrig.T)
  264. {
  265. LOG.Write($"{Module} idle purge stopped calc elapse time");
  266. ResetClean(true, false, false);
  267. }
  268. if (IdlePurgeTimer.IsRunning)
  269. {
  270. IdlePurgeTime = (int)IdlePurgeTimer.ElapsedMilliseconds / 1000;
  271. int idlePurgeTimeSetPoint = SC.GetValue<int>($"{Module}.IdlePurge.IdlePurgeTime");
  272. var nextRunTime = idlePurgeTimeSetPoint - IdlePurgeTime;
  273. if (nextRunTime < 0)
  274. nextRunTime = 0;
  275. if (enablePurge)
  276. {
  277. if (nextRunTime <= 0 && IsAvailable)
  278. {
  279. var recipe = SC.GetStringValue($"{Module}.IdlePurge.IdlePurgeRecipe");
  280. if (string.IsNullOrEmpty(recipe))
  281. {
  282. _trigIdlePurgeFailed.CLK = true;
  283. LOG.Write($"{Module} Idle purge can not run, recipe is empty");
  284. ResetClean(true, false, false);
  285. }
  286. else if (hasWafer)
  287. {
  288. _trigIdlePurgeFailed.CLK = true;
  289. LOG.Write($"{Module} Idle purge can not run, has wafer");
  290. ResetClean(true, false, false);
  291. }
  292. else
  293. {
  294. _trigIdlePurgeFailed.CLK = false;
  295. LOG.Write($"{Module} Start run idle purge recipe {recipe}");
  296. IdlePurgeProcess("ALD\\Process\\" + recipe);
  297. }
  298. if (_trigIdlePurgeFailed.Q)
  299. {
  300. EV.PostWarningLog(Module.ToString(), "Can not run idle purge recipe");
  301. }
  302. }
  303. }
  304. else
  305. {
  306. nextRunTime = 0;
  307. }
  308. IdlePurgeNextRunTime = nextRunTime;
  309. }
  310. else
  311. {
  312. IdlePurgeNextRunTime = 0;
  313. }
  314. #endregion
  315. #region Idle Clean
  316. IdleCleanTrig.CLK = (IsIdle || _task != TaskType.IdleCleanProcess) && enableClean && !hasWafer;
  317. if (IdleCleanTrig.R)
  318. {
  319. LOG.Write($"{Module} idle clean start calc elapse time");
  320. IdleCleanTimer.Restart();
  321. }
  322. if (IdleCleanTrig.T)
  323. {
  324. LOG.Write($"{Module} idle clean stopped calc elapse time");
  325. ResetClean(false, true, false);
  326. }
  327. if (IdleCleanTimer.IsRunning)
  328. {
  329. IdleCleanTime = (int)IdleCleanTimer.ElapsedMilliseconds / 1000;
  330. int idleCleanTimeSetPoint = SC.GetValue<int>($"{Module}.IdleClean.IdleCleanTime");
  331. var nextRunTime = idleCleanTimeSetPoint - IdleCleanTime;
  332. if (nextRunTime < 0)
  333. nextRunTime = 0;
  334. if (enableClean)
  335. {
  336. if (nextRunTime <= 0 && IsAvailable)
  337. {
  338. var recipe = SC.GetStringValue($"{Module}.IdleClean.IdleCleanRecipe");
  339. if (string.IsNullOrEmpty(recipe))
  340. {
  341. _trigIdleCleanFailed.CLK = true;
  342. LOG.Write($"{Module} Idle clean can not run, recipe is empty");
  343. ResetClean(false, true, false);
  344. }
  345. else if (hasWafer)
  346. {
  347. _trigIdleCleanFailed.CLK = true;
  348. LOG.Write($"{Module} Idle clean can not run, has wafer");
  349. ResetClean(false, true, false);
  350. }
  351. else
  352. {
  353. _trigIdleCleanFailed.CLK = false;
  354. LOG.Write($"{Module} Start run idle Clean recipe {recipe}");
  355. IdleCleanProcess($"{Module}\\" + recipe);
  356. }
  357. if (_trigIdleCleanFailed.Q)
  358. {
  359. EV.PostWarningLog(Module.ToString(), "Can not run idle clean recipe");
  360. }
  361. }
  362. }
  363. else
  364. {
  365. nextRunTime = 0;
  366. }
  367. IdleCleanNextRunTime = nextRunTime;
  368. }
  369. else
  370. {
  371. IdleCleanNextRunTime = 0;
  372. }
  373. #endregion
  374. #region PreJob Clean
  375. var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
  376. var enablePreJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnablePreJobClean");
  377. var enableCompleteJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnableCompleteJobClean");
  378. if (enableJobClean && enableCompleteJobClean && _waitCompletejobClean && IsIdle)
  379. {
  380. var recipe = SC.GetStringValue($"{Module}.JobClean.CompleteJobCleanRecipe");
  381. if (string.IsNullOrEmpty(recipe))
  382. {
  383. EV.PostWarningLog(Module.ToString(), "complete job clean can not run, recipe is empty");
  384. }
  385. else if (hasWafer)
  386. {
  387. EV.PostWarningLog(Module.ToString(), "complete job clean can not run, has wafer");
  388. }
  389. else
  390. {
  391. EV.PostInfoLog(Module.ToString(), $"Start run complete job clean recipe {recipe}");
  392. CompleteJobProcess($"{Module}\\" + recipe);
  393. }
  394. _waitCompletejobClean = false;
  395. }
  396. PreJobCleanTrig.CLK = enableJobClean && enablePreJobClean && IsIdle;
  397. if (PreJobCleanTrig.R)
  398. {
  399. PreJobCleanTimer.Restart();
  400. }
  401. if (PreJobCleanTrig.T)
  402. {
  403. ResetClean(false, false, true);
  404. }
  405. if (enableJobClean && enablePreJobClean && _waitPreJobClean && PreJobCleanTimer.IsRunning && IsIdle)
  406. {
  407. PreJobCleanTime = (int)PreJobCleanTimer.ElapsedMilliseconds / 1000;
  408. int PreJobCleanIdleTimeSP = SC.GetValue<int>($"{Module}.JobClean.IdleCleanTime");
  409. if (PreJobCleanTime >= PreJobCleanIdleTimeSP)
  410. {
  411. var recipe = SC.GetStringValue($"{Module}.JobClean.PreJobCleanRecipe");
  412. if (string.IsNullOrEmpty(recipe))
  413. {
  414. EV.PostWarningLog(Module.ToString(), "pre job clean can not run, recipe is empty");
  415. }
  416. else if (hasWafer)
  417. {
  418. EV.PostWarningLog(Module.ToString(), "pre job clean can not run, has wafer");
  419. }
  420. else
  421. {
  422. EV.PostInfoLog(Module.ToString(), $"Start run pre job clean recipe {recipe}");
  423. PreJobProcess($"{Module}\\" + recipe);
  424. }
  425. }
  426. }
  427. #endregion
  428. }
  429. public bool IdlePurgeProcess(string recipeName)
  430. {
  431. _task = TaskType.IdlePurgeProcess;
  432. if (!_pm.Process(recipeName, true, false, out string reason))
  433. {
  434. LOG.Write(reason);
  435. return false;
  436. }
  437. LogTaskStart(_task, $"recipe: {recipeName}, clean: {true}, with wafer: {false}");
  438. return true;
  439. }
  440. public bool IdleCleanProcess(string recipeName)
  441. {
  442. _task = TaskType.IdleCleanProcess;
  443. if (!_pm.Process(recipeName, true, false, out string reason))
  444. {
  445. LOG.Write(reason);
  446. return false;
  447. }
  448. LogTaskStart(_task, $"recipe: {recipeName}, clean: {true}, with wafer: {false}");
  449. return true;
  450. }
  451. public void PreJobClean()
  452. {
  453. var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
  454. var enablePreJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnablePreJobClean");
  455. var enableCompleteJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnableCompleteJobClean");
  456. _waitPreJobClean = enableJobClean && enablePreJobClean;
  457. }
  458. public bool PreJobProcess(string recipeName)
  459. {
  460. _task = TaskType.PreJobProcess;
  461. if (!_pm.Process(recipeName, true, false, out string reason))
  462. {
  463. LOG.Write(reason);
  464. return false;
  465. }
  466. LogTaskStart(_task, $"recipe: {recipeName}, clean: {true}, with wafer: {false}");
  467. return true;
  468. }
  469. public void CompleteJobClean()
  470. {
  471. var enableJobClean = SC.GetValue<bool>($"{Module}.JobClean.IsEnabled");
  472. var enablePreJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnablePreJobClean");
  473. var enableCompleteJobClean = SC.GetValue<bool>($"{Module}.JobClean.EnableCompleteJobClean");
  474. _waitCompletejobClean = enableJobClean && enableCompleteJobClean;
  475. }
  476. public bool CompleteJobProcess(string recipeName)
  477. {
  478. _task = TaskType.CompleteJobProcess;
  479. if (!_pm.Process(recipeName, true, false, out string reason))
  480. {
  481. LOG.Write(reason);
  482. return false;
  483. }
  484. LogTaskStart(_task, $"recipe: {recipeName}, clean: {true}, with wafer: {false}");
  485. return true;
  486. }
  487. #endregion
  488. }
  489. }