TMCycle.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Aitex.Core.Common;
  5. using Aitex.Core.RT.DataCenter;
  6. using Aitex.Core.RT.Event;
  7. using Aitex.Core.RT.Routine;
  8. using Aitex.Core.RT.SCCore;
  9. using Aitex.Sorter.Common;
  10. using MECF.Framework.Common.Equipment;
  11. using MECF.Framework.Common.Schedulers;
  12. using MECF.Framework.Common.SubstrateTrackings;
  13. using MECF.Framework.RT.ModuleLibrary.SystemModules;
  14. using EfemDualSchedulerLib.Schedulers;
  15. namespace EfemDualSchedulerLib
  16. {
  17. public class TMCycle : SchedulerModuleFactory, IRoutine
  18. {
  19. Dictionary<ModuleName, int> _checkPosition = new Dictionary<ModuleName, int>()
  20. {
  21. {ModuleName.TMRobot, 2},
  22. {ModuleName.PMA, 2},
  23. {ModuleName.PMB, 2},
  24. };
  25. Queue<Action> tmRobotActions = new Queue<Action>() { };
  26. private List<SchedulerPM> _lstPms = new List<SchedulerPM>();
  27. private List<SchedulerLoadLock> _lstLls = new List<SchedulerLoadLock>();
  28. public bool PMAIsInstalled
  29. {
  30. get
  31. {
  32. return SC.GetValueOrDefault<bool>("System.SetUp.PMA.IsInstalled");
  33. }
  34. }
  35. public bool PMBIsInstalled
  36. {
  37. get
  38. {
  39. return SC.GetValueOrDefault<bool>("System.SetUp.PMB.IsInstalled");
  40. }
  41. }
  42. public TMCycle(EquipmentManager equipment) : base()
  43. {
  44. DATA.Subscribe("TMCylce.RemainedCycleCount", () =>
  45. {
  46. return cycleCount - 1;
  47. });
  48. //有优先级,先处理pmb后pma
  49. if (PMBIsInstalled)
  50. _lstPms.Add(_pm2);
  51. if (PMAIsInstalled)
  52. _lstPms.Add(_pm1);
  53. _lstLls.Add(_loadlockA);
  54. _lstLls.Add(_loadlockB);
  55. tmRobotActions.Enqueue(MonitorTmRobotLoadLockPickTask);
  56. tmRobotActions.Enqueue(MonitorTMRobotPMPlaceTask);
  57. tmRobotActions.Enqueue(MonitorTMRobotPMPickTask);
  58. tmRobotActions.Enqueue(MonitorTmRobotLoadLockPlaceTask);
  59. }
  60. List<string> tmCycleRoutine = new List<string>() { "LLA", "PMA", "PMB", "LLB" };
  61. int cycleCount = 1;
  62. public Result Start(params object[] objs)
  63. {
  64. if (objs.Length == 2)
  65. {
  66. tmCycleRoutine = ((string[])objs[0]).ToList();
  67. cycleCount = (int)objs[1];
  68. }
  69. //if (!PMAIsInstalled && !PMBIsInstalled)
  70. //{
  71. // EV.PostWarningLog("System", $"TM Cycle, PMA & PMB Both UnInstalled.");
  72. // return Result.FAIL;
  73. //}
  74. if (!PMAIsInstalled && tmCycleRoutine.Contains("PMA"))
  75. {
  76. EV.PostWarningLog("System", $"TM Cycle, PMA is UnInstalled.");
  77. return Result.FAIL;
  78. }
  79. if (!PMBIsInstalled && tmCycleRoutine.Contains("PMB"))
  80. {
  81. EV.PostWarningLog("System", $"TM Cycle, PMB is UnInstalled.");
  82. return Result.FAIL;
  83. }
  84. foreach (var positions in _checkPosition)
  85. {
  86. for (int i = 0; i < positions.Value; i++)
  87. {
  88. WaferInfo wafer = WaferManager.Instance.GetWafer(positions.Key, i);
  89. if (!wafer.IsEmpty)
  90. {
  91. EV.PostWarningLog("System", $"TM Cycle, {positions.Key}.{i + 1} can not has wafer.");
  92. return Result.FAIL;
  93. }
  94. }
  95. }
  96. WaferInfo[] OriginWafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(tmCycleRoutine.First()));
  97. WaferInfo[] DestinationWafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(tmCycleRoutine.Last()));
  98. for (int i = 0; i < OriginWafers.Length; i++)
  99. {
  100. if (!OriginWafers[i].IsEmpty)
  101. {
  102. OriginWafers[i].OriginStation = (int)ModuleHelper.Converter(tmCycleRoutine.First());
  103. OriginWafers[i].OriginSlot = i;
  104. OriginWafers[i].ProcessState = EnumWaferProcessStatus.InProcess;
  105. OriginWafers[i].NextSequenceStep = 0;
  106. if (tmCycleRoutine.First() != tmCycleRoutine.Last() && !DestinationWafers[i].IsEmpty)
  107. {
  108. EV.PostWarningLog("System", $"TM Cycle, {tmCycleRoutine.Last()}.{i + 1} already has wafer.");
  109. return Result.FAIL;
  110. }
  111. }
  112. }
  113. if (tmCycleRoutine.First() != tmCycleRoutine.Last())
  114. {
  115. tmCycleRoutine.Add(tmCycleRoutine.First());
  116. }
  117. return Result.RUN;
  118. }
  119. public Result Monitor()
  120. {
  121. MonitorModuleTasks();
  122. if (MonitorTaskDone())
  123. {
  124. return Result.DONE;
  125. }
  126. return Result.RUN;
  127. }
  128. public void Clear()
  129. {
  130. }
  131. public void Abort()
  132. {
  133. }
  134. public Result MonitorModuleTasks()
  135. {
  136. MonitorPMTask();
  137. MonitorTMRobotTask();
  138. return Result.RUN;
  139. }
  140. private void MonitorTMRobotTask()
  141. {
  142. if (!_tmRobot.IsAvailable)
  143. return;
  144. //_tmRobot is idle, release all the target
  145. foreach (var ll in _lstLls)
  146. {
  147. if (ll.IsWaitTransfer(ModuleName.TMRobot))
  148. ll.StopWaitTransfer(ModuleName.TMRobot);
  149. }
  150. foreach (var pm in _lstPms)
  151. {
  152. if (pm.IsWaitTransfer(ModuleName.TMRobot))
  153. pm.StopWaitTransfer(ModuleName.TMRobot);
  154. }
  155. if (!_tmRobot.IsAvailable)
  156. return;
  157. var act = tmRobotActions.Peek();
  158. act.Invoke();
  159. if (!_tmRobot.IsAvailable)
  160. return;
  161. tmRobotActions.Enqueue(tmRobotActions.Dequeue());
  162. //MonitorTMRobotPMTask();
  163. //if (!_tmRobot.IsAvailable)
  164. // return;
  165. //MonitorTMRobotLoadLockTask();
  166. }
  167. private void MonitorTmRobotLoadLockPlaceTask()
  168. {
  169. if (!_tmRobot.IsAvailable)
  170. return;
  171. //place to ll
  172. bool blade0HasWaferAndProcessed = _tmRobot.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0);
  173. bool blade1HasWaferAndProcessed = _tmRobot.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1);
  174. if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed)
  175. {
  176. Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2;
  177. foreach (var ll in _lstLls)
  178. {
  179. if (!ll.IsAvailable)
  180. continue;
  181. if (!CheckWaferNextStep(ModuleName.TMRobot, (int)placeBlade, ll.Module))
  182. continue;
  183. var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
  184. var slot = wafer.OriginSlot;
  185. if (ll.IsReadyForPlace(ModuleName.TMRobot, placeBlade, (int)slot))
  186. {
  187. if (_tmRobot.Place(ll.Module, (int)slot, placeBlade, 0, 0, false))
  188. {
  189. if (wafer.NextSequenceStep >= tmCycleRoutine.Count-1)
  190. wafer.ProcessState = EnumWaferProcessStatus.Completed;
  191. ll.WaitTransfer(ModuleName.TMRobot);
  192. return;
  193. }
  194. }
  195. }
  196. }
  197. }
  198. private void MonitorTmRobotLoadLockPickTask()
  199. {
  200. if (!_tmRobot.IsAvailable)
  201. return;
  202. //pick from ll
  203. if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
  204. {
  205. Hand pickBlade;
  206. if (_tmRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0))
  207. {
  208. pickBlade = Hand.Blade1;
  209. }
  210. else if (_tmRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
  211. {
  212. pickBlade = Hand.Blade2;
  213. }
  214. else
  215. {
  216. return;
  217. }
  218. foreach (var ll in _lstLls)
  219. {
  220. if (!ll.IsAvailable)
  221. continue;
  222. var wafers = WaferManager.Instance.GetWafers(ll.Module);
  223. for (int pickSlot = 0; pickSlot < wafers.Length; pickSlot++)
  224. {
  225. if (wafers[pickSlot].NextSequenceStep == 0)
  226. {
  227. ModuleName nextModule = ModuleHelper.Converter(tmCycleRoutine[1]);
  228. if (WaferManager.Instance.GetWafers(nextModule).All(x => !x.IsEmpty))
  229. return;
  230. }
  231. if (wafers[pickSlot].ProcessState != EnumWaferProcessStatus.InProcess)
  232. continue;
  233. if (ll.IsReadyForPick(ModuleName.TMRobot, pickBlade, pickSlot))
  234. {
  235. if (_tmRobot.Pick(ll.Module, pickSlot, pickBlade, 0, 0, false))
  236. {
  237. wafers[pickSlot].NextSequenceStep++;
  238. ll.WaitTransfer(ModuleName.TMRobot);
  239. return;
  240. }
  241. }
  242. }
  243. }
  244. }
  245. }
  246. private void MonitorTMRobotLoadLockTask()
  247. {
  248. if (!_tmRobot.IsAvailable)
  249. return;
  250. //place to llb
  251. {
  252. bool blade1HasWafer = _tmRobot.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0).NextStation == (int)ModuleName.LLB;
  253. bool blade2HasWafer = _tmRobot.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) && WaferManager.Instance.GetWafer(ModuleName.TMRobot, 1).NextStation == (int)ModuleName.LLB;
  254. if (blade1HasWafer || blade2HasWafer)
  255. {
  256. Hand placeBlade = blade1HasWafer ? Hand.Blade1 : Hand.Blade2;
  257. var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
  258. {
  259. if (!_loadlockB.IsAvailable)
  260. return;
  261. var slot = wafer.OriginSlot;
  262. if (_loadlockB.IsReadyForPlace(ModuleName.TMRobot, placeBlade, (int)slot))
  263. {
  264. if (_tmRobot.Place(_loadlockB.Module, (int)slot, placeBlade, 0, 0, false))
  265. {
  266. _loadlockB.WaitTransfer(ModuleName.TMRobot);
  267. return;
  268. }
  269. }
  270. }
  271. }
  272. }
  273. if (!_tmRobot.IsAvailable)
  274. return;
  275. //pick from lla
  276. if (PMAIsInstalled && PMBIsInstalled && WaferManager.Instance.CheckHasWafer(ModuleName.PMA, 0) && WaferManager.Instance.CheckHasWafer(ModuleName.PMA, 1))
  277. return;
  278. if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
  279. {
  280. Hand pickBlade;
  281. if (_tmRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
  282. {
  283. pickBlade = Hand.Blade2;
  284. }
  285. else if (_tmRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
  286. {
  287. pickBlade = Hand.Blade1;
  288. }
  289. else
  290. {
  291. return;
  292. }
  293. {
  294. if (!_loadlockA.IsAvailable)
  295. return;
  296. var wafers = WaferManager.Instance.GetWafers(_loadlockA.Module);
  297. for (int pickSlot = 0; pickSlot < wafers.Length; pickSlot++)
  298. {
  299. if (_loadlockA.IsReadyForPick(ModuleName.TMRobot, pickBlade, pickSlot))
  300. {
  301. if (_tmRobot.Pick(_loadlockA.Module, pickSlot, pickBlade, 0, 0, false))
  302. {
  303. _loadlockA.WaitTransfer(ModuleName.TMRobot);
  304. return;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. private void MonitorTMRobotPMPlaceTask()
  312. {
  313. if (!_tmRobot.IsAvailable)
  314. return;
  315. //place to pm
  316. bool blade0HasWafer = _tmRobot.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0);
  317. bool blade1HasWafer = _tmRobot.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1);
  318. if (blade0HasWafer || blade1HasWafer)
  319. {
  320. Hand placeBlade = blade0HasWafer ? Hand.Blade1 : Hand.Blade2;
  321. var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
  322. foreach (var schedulerPm in _lstPms)
  323. {
  324. if (!schedulerPm.IsAvailable)
  325. continue;
  326. if (!CheckWaferNextStep(ModuleName.TMRobot, (int)placeBlade, schedulerPm.Module))
  327. continue;
  328. var pmWafer0 = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
  329. var pmWafer1 = WaferManager.Instance.GetWafer(schedulerPm.Module, 1);
  330. //如果腔体中两片都满了,则不允许放入
  331. if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
  332. continue;
  333. if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0))
  334. {
  335. if (_tmRobot.Place(schedulerPm.Module, 0, placeBlade, 0, 0, false))
  336. {
  337. schedulerPm.WaitTransfer(ModuleName.TMRobot);
  338. return;
  339. }
  340. }
  341. if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 1))
  342. {
  343. if (_tmRobot.Place(schedulerPm.Module, 1, placeBlade, 0, 0, false))
  344. {
  345. schedulerPm.WaitTransfer(ModuleName.TMRobot);
  346. return;
  347. }
  348. }
  349. }
  350. }
  351. }
  352. private void MonitorTMRobotPMPickTask()
  353. {
  354. //pick from pm
  355. {
  356. bool blade1Empty = _tmRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0);
  357. bool blade2Empty = _tmRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1);
  358. if (blade1Empty || blade2Empty)
  359. {
  360. Hand pickBlade = blade1Empty ? Hand.Blade1 : Hand.Blade2;
  361. foreach (var pm in _lstPms)
  362. {
  363. if (!pm.IsAvailable)
  364. continue;
  365. var wafers = WaferManager.Instance.GetWafers(pm.Module);
  366. for (int slot = 0; slot < wafers.Length; slot++)
  367. {
  368. if (pm.IsReadyForPick(ModuleName.TMRobot, pickBlade, slot))
  369. {
  370. if (_tmRobot.Pick(pm.Module, slot, pickBlade, 0, 0, false))
  371. {
  372. wafers[slot].NextSequenceStep++;
  373. pm.WaitTransfer(ModuleName.TMRobot);
  374. return;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. }
  381. }
  382. private void MonitorTMRobotPMTask()
  383. {
  384. if (!_tmRobot.IsAvailable)
  385. return;
  386. //place to pm
  387. bool blade0HasWafer = _tmRobot.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0);
  388. bool blade1HasWafer = _tmRobot.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1);
  389. if (blade0HasWafer || blade1HasWafer)
  390. {
  391. Hand placeBlade = blade0HasWafer ? Hand.Blade1 : Hand.Blade2;
  392. var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
  393. foreach (var schedulerPm in _lstPms)
  394. {
  395. if (!schedulerPm.IsAvailable)
  396. continue;
  397. if (wafer.NextStation != (int)schedulerPm.Module)
  398. continue;
  399. var pmWafer0 = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
  400. var pmWafer1 = WaferManager.Instance.GetWafer(schedulerPm.Module, 1);
  401. //如果腔体中两片都满了,则不允许放入
  402. if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
  403. continue;
  404. if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0))
  405. {
  406. if (_tmRobot.Place(schedulerPm.Module, 0, placeBlade, 0, 0, false))
  407. {
  408. schedulerPm.WaitTransfer(ModuleName.TMRobot);
  409. return;
  410. }
  411. }
  412. if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 1))
  413. {
  414. if (_tmRobot.Place(schedulerPm.Module, 1, placeBlade, 0, 0, false))
  415. {
  416. schedulerPm.WaitTransfer(ModuleName.TMRobot);
  417. return;
  418. }
  419. }
  420. }
  421. }
  422. if (!_tmRobot.IsAvailable)
  423. return;
  424. //pick from pm
  425. {
  426. bool blade1Empty = _tmRobot.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0);
  427. bool blade2Empty = _tmRobot.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1);
  428. if (blade1Empty || blade2Empty)
  429. {
  430. Hand pickBlade = blade1Empty ? Hand.Blade1 : Hand.Blade2;
  431. foreach (var pm in _lstPms)
  432. {
  433. if (!pm.IsAvailable)
  434. continue;
  435. var wafers = WaferManager.Instance.GetWafers(pm.Module);
  436. for (int slot = 0; slot < wafers.Length; slot++)
  437. {
  438. if (pm.IsReadyForPick(ModuleName.TMRobot, pickBlade, slot))
  439. {
  440. if (_tmRobot.Pick(pm.Module, slot, pickBlade, 0, 0, false))
  441. {
  442. wafers[slot].NextSequenceStep++;
  443. pm.WaitTransfer(ModuleName.TMRobot);
  444. return;
  445. }
  446. }
  447. }
  448. }
  449. }
  450. }
  451. }
  452. private bool MonitorTaskDone()
  453. {
  454. foreach (var positions in _checkPosition)
  455. {
  456. for (int i = 0; i < positions.Value; i++)
  457. {
  458. WaferInfo wafer = WaferManager.Instance.GetWafer(positions.Key, i);
  459. if (!wafer.IsEmpty)
  460. {
  461. return false;
  462. }
  463. }
  464. }
  465. foreach (var ll in _lstLls)
  466. {
  467. var llWafers = WaferManager.Instance.GetWafers(ll.Module);
  468. for (int i = 0; i < llWafers.Length; i++)
  469. {
  470. if (!llWafers[i].IsEmpty && llWafers[i].ProcessState != EnumWaferProcessStatus.Completed)
  471. return false;
  472. }
  473. }
  474. if (!_tmRobot.IsAvailable)
  475. return false;
  476. WaferInfo[] originWafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(tmCycleRoutine.First()));
  477. if (cycleCount > 1 && originWafers.All(x => x.IsEmpty || x.ProcessState == EnumWaferProcessStatus.Completed))
  478. {
  479. cycleCount--;
  480. foreach (WaferInfo wafer in originWafers)
  481. {
  482. wafer.NextSequenceStep = 0;
  483. wafer.ProcessState = EnumWaferProcessStatus.InProcess;
  484. }
  485. return false;
  486. }
  487. return true;
  488. }
  489. private void MonitorPMTask()
  490. {
  491. foreach (var pm in _lstPms)
  492. {
  493. if (!pm.IsAvailable)
  494. continue;
  495. if (pm.Module == ModuleName.PMA && !PMAIsInstalled)
  496. continue;
  497. if (pm.Module == ModuleName.PMB && !PMBIsInstalled)
  498. continue;
  499. var wafers = WaferManager.Instance.GetWafers(pm.Module);
  500. for (int i = 0; i < wafers.Length; i++)
  501. {
  502. if (!pm.IsAvailable)
  503. break;
  504. if (!wafers[i].IsEmpty && !pm.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i))
  505. {
  506. pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, i);
  507. return;
  508. }
  509. if (wafers[i].IsEmpty && !pm.IsReadyForPlace(ModuleName.TMRobot, Hand.Blade1, i))
  510. {
  511. pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, i);
  512. return;
  513. }
  514. }
  515. }
  516. }
  517. private bool CheckWaferNextStep(ModuleName module, int slot, ModuleName nextModule)
  518. {
  519. if (!WaferManager.Instance.CheckHasWafer(module, slot))
  520. return false;
  521. WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
  522. if (wafer.NextSequenceStep >= tmCycleRoutine.Count)
  523. return false;
  524. if (tmCycleRoutine[wafer.NextSequenceStep] != nextModule.ToString())
  525. return false;
  526. return true;
  527. }
  528. }
  529. }