WaferTaskManager.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.Util;
  4. using MECF.Framework.Common.Equipment;
  5. using MECF.Framework.Common.Jobs;
  6. using MECF.Framework.Common.RecipeCenter;
  7. using MECF.Framework.Common.SubstrateTrackings;
  8. using PunkHPX8_RT.Modules;
  9. using PunkHPX8_RT.Schedulers;
  10. using System;
  11. using System.Collections.Concurrent;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using System.Windows.Markup;
  17. using Aitex.Core.RT.SCCore;
  18. using MECF.Framework.Common.ToolLayout;
  19. using PunkHPX8_RT.Devices.EFEM;
  20. using Aitex.Core.RT.Device;
  21. using MECF.Framework.RT.Core.Equipments;
  22. namespace PunkHPX8_RT.Dispatch
  23. {
  24. public class WaferTaskManager : Singleton<WaferTaskManager>
  25. {
  26. #region 常量
  27. private const string SIDE_A = "SideA";
  28. private const string SIDE_B = "SideB";
  29. #endregion
  30. #region 内部变量
  31. /// <summary>
  32. /// FA回复
  33. /// </summary>
  34. private SchedulerFACallback _schedulerFACallback = new SchedulerFACallback();
  35. /// <summary>
  36. /// 任务锁
  37. /// </summary>
  38. private object _taskLocker = new object();
  39. /// <summary>
  40. /// 任务集合
  41. /// </summary>
  42. private List<WaferTask> _waferTaskList = new List<WaferTask>();
  43. /// <summary>
  44. /// Wafer task字典
  45. /// </summary>
  46. private ConcurrentDictionary<string, WaferTask> _waferTasksDic = new ConcurrentDictionary<string, WaferTask>();
  47. /// <summary>
  48. /// Wafer配对字典(key-自身WaferId,value-配对WaferId)
  49. /// </summary>
  50. private ConcurrentDictionary<string, string> _waferTaskMatchDic = new ConcurrentDictionary<string, string>();
  51. #endregion
  52. /// <summary>
  53. /// 初始化Task
  54. /// </summary>
  55. /// <param name="task"></param>
  56. public void InitializeTask(WaferTask task)
  57. {
  58. _waferTasksDic[task.WaferId] = task;
  59. lock(_taskLocker)
  60. {
  61. _waferTaskList.Add(task);
  62. }
  63. }
  64. /// <summary>
  65. /// 获取WaferTask
  66. /// </summary>
  67. /// <param name="waferId"></param>
  68. /// <returns></returns>
  69. public WaferTask GetWaferTask(string waferId)
  70. {
  71. return _waferTasksDic.ContainsKey(waferId) ? _waferTasksDic[waferId] : null;
  72. }
  73. /// <summary>
  74. /// 是否包含
  75. /// </summary>
  76. /// <param name="waferId"></param>
  77. /// <returns></returns>
  78. public bool Contains(string waferId)
  79. {
  80. return _waferTasksDic.ContainsKey(waferId);
  81. }
  82. /// <summary>
  83. /// 移除任务
  84. /// </summary>
  85. /// <param name="waferId"></param>
  86. public void RemoveWaferTask(string waferId)
  87. {
  88. if(_waferTasksDic.ContainsKey(waferId))
  89. {
  90. _waferTasksDic.TryRemove(waferId, out var task);
  91. task.Dispose();
  92. task.OnTaskComplete -= WaferTask_OnTaskComplete;
  93. LOG.WriteBackgroundLog(eEvent.EV_SCHEDULER, "Scheduler", $"remove wafer {waferId} task");
  94. }
  95. if(_waferTaskMatchDic.ContainsKey(waferId))
  96. {
  97. _waferTaskMatchDic.TryRemove(waferId,out var taskMath);
  98. }
  99. lock(_taskLocker)
  100. {
  101. int index = _waferTaskList.FindIndex(O => O.WaferId == waferId);
  102. if (index >= 0)
  103. {
  104. _waferTaskList.RemoveAt(index);
  105. }
  106. }
  107. }
  108. /// <summary>
  109. /// 加载Wafer Task集合
  110. /// </summary>
  111. /// <returns></returns>
  112. public List<WaferTask> LoadWaferTaskList()
  113. {
  114. return _waferTaskList.ToList();
  115. }
  116. /// <summary>
  117. /// 检验是否可以创建Wafer Task
  118. /// </summary>
  119. /// <returns></returns>
  120. public bool CheckEnableCreateWaferTask()
  121. {
  122. lock (_taskLocker)
  123. {
  124. if (_waferTaskList.Count == 0)
  125. {
  126. return true;
  127. }
  128. if (WaferManager.Instance.CheckHasWafer(ModuleName.Aligner1, 0))
  129. {
  130. return false;
  131. }
  132. foreach (WaferTask item in _waferTaskList)
  133. {
  134. //Wafer还未离开Aligner
  135. if (item.CurrentSequenceIndex <= 1)
  136. {
  137. return false;
  138. }
  139. }
  140. return true;
  141. }
  142. }
  143. /// <summary>
  144. /// 获取下一个执行的ProcessJob
  145. /// </summary>
  146. /// <param name="jobs"></param>
  147. /// <returns></returns>
  148. private ProcessJobInfo GetNextProcessJob(List<ProcessJobInfo> jobs, List<string> executedPPids)
  149. {
  150. try
  151. {
  152. bool isRunInParallelMode = SC.GetValue<bool>("Scheduler.IsRunInParallelMode");
  153. if (!isRunInParallelMode)
  154. {
  155. return jobs[0];
  156. }
  157. else
  158. {
  159. if (_waferTaskList.Count == 0)
  160. {
  161. return jobs[0];
  162. }
  163. WaferTask lastWaferTask = _waferTaskList[_waferTaskList.Count - 1];
  164. string lastSequence = lastWaferTask.ProcessJobInfo.SequenceRecipe?.Ppid;
  165. List<ProcessJobInfo> lastSamePjs = new List<ProcessJobInfo>();
  166. List<ProcessJobInfo> otherPjs = new List<ProcessJobInfo>();
  167. int lastIndex = jobs.FindIndex(O => O.SequenceRecipe?.Ppid == lastSequence);
  168. int nextIndex = (lastIndex == -1 || lastIndex >= jobs.Count - 1) ? 0 : lastIndex + 1;
  169. for (int i = nextIndex; i < jobs.Count; i++)
  170. {
  171. ProcessJobInfo processJobInfo = jobs[i];
  172. if (processJobInfo.SequenceRecipe?.Ppid == lastSequence)
  173. {
  174. lastSamePjs.Add(processJobInfo);
  175. continue;
  176. }
  177. if (executedPPids.Contains(processJobInfo.SequenceRecipe?.Ppid))
  178. {
  179. continue;
  180. }
  181. return processJobInfo;
  182. }
  183. for (int i = 0; i < lastIndex; i++)
  184. {
  185. ProcessJobInfo processJobInfo = jobs[i];
  186. if (processJobInfo.SequenceRecipe?.Ppid == lastSequence)
  187. {
  188. lastSamePjs.Add(processJobInfo);
  189. continue;
  190. }
  191. if (executedPPids.Contains(processJobInfo.SequenceRecipe?.Ppid))
  192. {
  193. continue;
  194. }
  195. return processJobInfo;
  196. }
  197. if (lastSamePjs.Count != 0)
  198. {
  199. return lastSamePjs[0];
  200. }
  201. return jobs[0];
  202. }
  203. }
  204. catch
  205. {
  206. return jobs[0];
  207. }
  208. }
  209. /// <summary>
  210. /// 创建Wafer任务
  211. /// </summary>
  212. public void CreateWaferTask(List<ProcessJobInfo> processJobInfos)
  213. {
  214. int count = 0;
  215. string mateWaferTask = "";
  216. List<WaferInfo> wafers = new List<WaferInfo>();
  217. if (processJobInfos.Count == 0)
  218. {
  219. return;
  220. }
  221. List<string> excludes = new List<string>();
  222. ProcessJobInfo processJob = GetNextProcessJob(processJobInfos, excludes);
  223. if (processJob == null)
  224. {
  225. return;
  226. }
  227. for(int i=0; i<processJobInfos.Count;i++)
  228. {
  229. ProcessJobInfo processJobInfo = processJobInfos[i];
  230. if (processJobInfo.SequenceRecipe?.Ppid != processJob.SequenceRecipe?.Ppid)
  231. {
  232. continue;
  233. }
  234. for(int j=0;j< processJobInfo.SlotWafers.Count; j++)
  235. {
  236. var item = processJobInfo.SlotWafers[j];
  237. if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2))
  238. {
  239. WaferInfo waferInfo = WaferManager.Instance.GetWafer(item.Item1, item.Item2);
  240. if (waferInfo != null && waferInfo.ProcessState == EnumWaferProcessStatus.Idle)
  241. {
  242. if (!Contains(waferInfo.WaferID))
  243. {
  244. if (count == 0)
  245. {
  246. wafers.Add(waferInfo);
  247. count++;
  248. }
  249. else
  250. {
  251. wafers.Add(waferInfo);
  252. break;
  253. }
  254. }
  255. }
  256. }
  257. }
  258. }
  259. SequenceRecipe sequenceRecipe = processJob.SequenceRecipe;
  260. if (wafers.Count == 1)
  261. {
  262. WaferInfo dummyWaferInfo = GetDummyWafer(sequenceRecipe.SubstrateSize);
  263. if (dummyWaferInfo == null)
  264. {
  265. return;
  266. }
  267. CreateWaferTaskSchedulerSequence(wafers[0], sequenceRecipe, "");
  268. mateWaferTask = wafers[0].WaferID;
  269. CreateDummyWaferTaskSchedulerSequence(sequenceRecipe, dummyWaferInfo, mateWaferTask);
  270. _waferTaskMatchDic[wafers[0].WaferID] = dummyWaferInfo.WaferID;
  271. LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"wafer {wafers[0].WaferID} match {dummyWaferInfo.WaferID}");
  272. _waferTaskMatchDic[dummyWaferInfo.WaferID] = wafers[0].WaferID;
  273. LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"wafer {dummyWaferInfo.WaferID} match {wafers[0].WaferID}");
  274. }
  275. else if (wafers.Count >= 2)
  276. {
  277. CreateWaferTaskSchedulerSequence(wafers[0], sequenceRecipe, "");
  278. mateWaferTask = wafers[0].WaferID;
  279. CreateWaferTaskSchedulerSequence(wafers[1], sequenceRecipe,mateWaferTask);
  280. _waferTaskMatchDic[wafers[0].WaferID] = wafers[1].WaferID;
  281. _waferTaskMatchDic[wafers[1].WaferID] = wafers[0].WaferID;
  282. }
  283. }
  284. /// <summary>
  285. /// 获取Dummy Wafer
  286. /// </summary>
  287. /// <param name="waferSize"></param>
  288. /// <returns></returns>
  289. private WaferInfo GetDummyWafer(int waferSize)
  290. {
  291. List<string> dummmys= DummyCasseteItemManager.Instance.InstalledModules;
  292. foreach(string item in dummmys)
  293. {
  294. if (Enum.TryParse(item, out ModuleName dummyModule))
  295. {
  296. DummyDevice dummyDevice= Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(dummyModule - ModuleName.Dummy1);
  297. if ((int)dummyDevice.WaferSize != waferSize)
  298. {
  299. continue;
  300. }
  301. int maxSlot = dummyDevice.MaxSlotNumber;
  302. for (int i = 0; i < maxSlot; i++)
  303. {
  304. if (WaferManager.Instance.CheckHasWafer(item, i))
  305. {
  306. return WaferManager.Instance.GetWafer(dummyModule, i);
  307. }
  308. }
  309. }
  310. }
  311. return null;
  312. }
  313. /// <summary>
  314. /// 创建WaferTask SchedulerSequence
  315. /// </summary>
  316. /// <param name="waferInfo"></param>
  317. /// <param name="pufModuleName"></param>
  318. /// <param name="waferHolderInfo"></param>
  319. /// <param name="sequenceRecipe"></param>
  320. private void CreateWaferTaskSchedulerSequence(WaferInfo waferInfo, SequenceRecipe sequenceRecipe, string mateWafeTask)
  321. {
  322. List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyWaferAllSchedulerSequence(waferInfo,sequenceRecipe);
  323. WaferTask waferTask = new WaferTask(waferInfo, sequences);
  324. if (!string.IsNullOrEmpty(mateWafeTask))
  325. {
  326. waferTask.MateWaferTask = mateWafeTask;
  327. }
  328. waferTask.OnTaskComplete += WaferTask_OnTaskComplete;
  329. LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create wafer {waferInfo.WaferID} task");
  330. InitializeTask(waferTask);
  331. }
  332. /// <summary>
  333. /// 创建Dummy Wafer Task 调度工序
  334. /// </summary>
  335. /// <param name="waferInfo"></param>
  336. /// <param name="pufModuleName"></param>
  337. /// <param name="mateWaferTask"></param>
  338. private void CreateDummyWaferTaskSchedulerSequence(SequenceRecipe sequenceRecipe,WaferInfo waferInfo,string mateWaferTask)
  339. {
  340. List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyDummyWaferAllSchedulerSequence(sequenceRecipe,waferInfo);
  341. WaferTask waferTask = new WaferTask(waferInfo,sequences);
  342. if (!string.IsNullOrEmpty(mateWaferTask))
  343. {
  344. waferTask.MateWaferTask = mateWaferTask;
  345. }
  346. LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create Dummy wafer {waferInfo.WaferID} task");
  347. waferTask.OnTaskStart += WaferTask_OnTaskStart;
  348. waferTask.OnTaskComplete += WaferTask_OnTaskComplete;
  349. InitializeTask(waferTask);
  350. }
  351. /// <summary>
  352. /// 任务开始
  353. /// </summary>
  354. /// <param name="id"></param>
  355. /// <exception cref="NotImplementedException"></exception>
  356. private void WaferTask_OnTaskStart(string id)
  357. {
  358. WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(id);
  359. if (waferInfo != null && waferInfo.WaferType == WaferType.Production)
  360. {
  361. ModuleName moduleName = (ModuleName)waferInfo.OriginStation;
  362. if (ModuleHelper.IsLoadPort(moduleName))
  363. {
  364. CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString());
  365. }
  366. _schedulerFACallback.JobWaferStart(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob),
  367. waferInfo.SequenceName, waferInfo.OriginSlot);
  368. }
  369. }
  370. /// <summary>
  371. /// Wafer task完成事件
  372. /// </summary>
  373. /// <param name="id"></param>
  374. private void WaferTask_OnTaskComplete(string id)
  375. {
  376. WaferInfo waferInfo=WaferManager.Instance.GetWaferByWaferId(id);
  377. if (waferInfo != null&&waferInfo.WaferType==WaferType.Production)
  378. {
  379. ModuleName moduleName = (ModuleName)waferInfo.OriginStation;
  380. if (ModuleHelper.IsLoadPort(moduleName))
  381. {
  382. CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString());
  383. }
  384. _schedulerFACallback.JobWaferEnd(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob),
  385. waferInfo.SequenceName, waferInfo.OriginSlot);
  386. }
  387. RemoveWaferTask(id);
  388. }
  389. /// <summary>
  390. /// 检验所有task是否完成
  391. /// </summary>
  392. /// <returns></returns>
  393. public bool CheckAllTaskComplete()
  394. {
  395. return _waferTaskList.Count == 0;
  396. }
  397. /// <summary>
  398. /// 暂停
  399. /// </summary>
  400. public void PauseAllTask()
  401. {
  402. List<WaferTask> waferTasks = _waferTaskList.ToList();
  403. foreach(WaferTask item in waferTasks)
  404. {
  405. item.Pause();
  406. }
  407. }
  408. /// <summary>
  409. /// 恢复所有任务
  410. /// </summary>
  411. public void ResumeAllTask()
  412. {
  413. List<WaferTask> waferTasks = _waferTaskList.ToList();
  414. foreach (WaferTask item in waferTasks)
  415. {
  416. item.Resume();
  417. }
  418. }
  419. /// <summary>
  420. /// 恢复所有任务
  421. /// </summary>
  422. public void RemoveAllTask()
  423. {
  424. List<WaferTask> waferTasks = _waferTaskList.ToList();
  425. foreach (WaferTask item in waferTasks)
  426. {
  427. RemoveWaferTask(item.WaferId);
  428. }
  429. }
  430. /// <summary>
  431. /// 根据WaferId获取配对另一个WaferId
  432. /// </summary>
  433. /// <param name="waferId"></param>
  434. /// <returns></returns>
  435. public string GetMatchWaferIdByWaferId(string waferId)
  436. {
  437. return _waferTaskMatchDic.ContainsKey(waferId) ? _waferTaskMatchDic[waferId] : "";
  438. }
  439. /// <summary>
  440. /// 检验Wafer存在匹配的wafer任务(wafer是单片任务还是双片任务)
  441. /// </summary>
  442. /// <param name="waferId"></param>
  443. /// <returns></returns>
  444. public string CheckWaferHasMatch(string waferId)
  445. {
  446. if (_waferTaskMatchDic.ContainsKey(waferId))
  447. {
  448. return _waferTaskMatchDic[waferId];
  449. }
  450. else
  451. {
  452. return "";
  453. }
  454. }
  455. }
  456. }