using Aitex.Core.Common; using Aitex.Core.RT.Log; using Aitex.Core.Util; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Jobs; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.Common.WaferHolder; using CyberX8_RT.Modules.PUF; using CyberX8_RT.Modules; using CyberX8_RT.Schedulers; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Markup; using Aitex.Core.RT.SCCore; namespace CyberX8_RT.Dispatch { public class WaferTaskManager : Singleton<WaferTaskManager> { #region 常量 private const string SIDE_A = "SideA"; private const string SIDE_B = "SideB"; #endregion #region 内部变量 /// <summary> /// FA回复 /// </summary> private SchedulerFACallback _schedulerFACallback = new SchedulerFACallback(); /// <summary> /// 任务锁 /// </summary> private object _taskLocker = new object(); /// <summary> /// 任务集合 /// </summary> private List<WaferTask> _waferTaskList = new List<WaferTask>(); /// <summary> /// Wafer task字典 /// </summary> private ConcurrentDictionary<string, WaferTask> _waferTasksDic = new ConcurrentDictionary<string, WaferTask>(); /// <summary> /// Wafer配对字典(key-自身WaferId,value-配对WaferId) /// </summary> private ConcurrentDictionary<string, string> _waferTaskMatchDic = new ConcurrentDictionary<string, string>(); /// <summary> /// Wafer--WaferHolder任务字典(key-自身WaferId,value-WaferHolder任务) /// </summary> private ConcurrentDictionary<string, WaferHolderTask> _waferWaferHolderTaskDic = new ConcurrentDictionary<string, WaferHolderTask>(); #endregion /// <summary> /// 初始化Task /// </summary> /// <param name="task"></param> public void InitializeTask(WaferTask task) { _waferTasksDic[task.WaferId] = task; lock(_taskLocker) { _waferTaskList.Add(task); } } /// <summary> /// 获取WaferTask /// </summary> /// <param name="waferId"></param> /// <returns></returns> public WaferTask GetWaferTask(string waferId) { return _waferTasksDic.ContainsKey(waferId) ? _waferTasksDic[waferId] : null; } /// <summary> /// 是否包含 /// </summary> /// <param name="waferId"></param> /// <returns></returns> public bool Contains(string waferId) { return _waferTasksDic.ContainsKey(waferId); } /// <summary> /// 移除任务 /// </summary> /// <param name="waferId"></param> public void RemoveWaferTask(string waferId) { if(_waferTasksDic.ContainsKey(waferId)) { _waferTasksDic.TryRemove(waferId, out var task); task.Dispose(); task.OnTaskComplete -= WaferTask_OnTaskComplete; LOG.WriteBackgroundLog(eEvent.EV_SCHEDULER, "Scheduler", $"remove wafer {waferId} task"); } if(_waferTaskMatchDic.ContainsKey(waferId)) { _waferTaskMatchDic.TryRemove(waferId,out var taskMath); } lock(_taskLocker) { int index = _waferTaskList.FindIndex(O => O.WaferId == waferId); if (index >= 0) { _waferTaskList.RemoveAt(index); } } } /// <summary> /// 加载Wafer Task集合 /// </summary> /// <returns></returns> public List<WaferTask> LoadWaferTaskList() { return _waferTaskList.ToList(); } /// <summary> /// 创建Wafer任务 /// </summary> public int CreateWaferTask(List<ProcessJobInfo> processJobInfos, WaferHolderInfo waferHolderInfo,WaferHolderTask waferHolderTask) { int count = 0; string mateWaferTask = ""; List<WaferInfo> wafers = new List<WaferInfo>(); if (processJobInfos.Count == 0) { return 0; } for(int i=0; i<processJobInfos.Count;i++) { ProcessJobInfo processJobInfo = processJobInfos[i]; for(int j=0;j< processJobInfo.SlotWafers.Count; j++) { var item = processJobInfo.SlotWafers[j]; if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2)) { WaferInfo waferInfo = WaferManager.Instance.GetWafer(item.Item1, item.Item2); if (waferInfo != null && waferInfo.ProcessState == EnumWaferProcessStatus.Idle) { if (!Contains(waferInfo.WaferID)) { if (count == 0) { wafers.Add(waferInfo); count++; } else { wafers.Add(waferInfo); break; } } } } } } SequenceRecipe sequenceRecipe = processJobInfos[0].SequenceRecipe; if (wafers.Count == 1) { WaferInfo waferInfo = wafers[0]; ModuleName pufModuleName = ModuleName.PUF1; string waferSide = ""; string dummySide = ""; bool lastSingleWaferToSideB = sequenceRecipe.LastSingleWaferToSideB; if (lastSingleWaferToSideB) { if (CheckLoaderHasSameWaferSize()) { waferSide = SIDE_B; dummySide = SIDE_A; } else { string side = AnalyseLoadSide(sequenceRecipe); waferSide = side; dummySide = side; } } else { if (CheckLoaderHasSameWaferSize()) { waferSide = SIDE_A; dummySide = SIDE_B; } else { string side = AnalyseLoadSide(sequenceRecipe); waferSide = side; dummySide = side; } } if (CheckWaferHolderHasSameTypeWafers(waferHolderInfo)) { List<WaferInfo> dummyWafers = DummyWaferManager.Instance.LoadDummyWafersByWaferHolder(waferHolderInfo); if (dummyWafers.Count != 0) { CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide); WaferInfo dummyInfo = null; if (dummyWafers.Count > 1) { foreach (WaferInfo info in dummyWafers) { //最后一片Wafer使用B面,那么dummy片使用0 slot if (lastSingleWaferToSideB && info.OriginSlot == 0) { dummyInfo = info; break; } //最后一片Wafer使用A面,那么dummy片使用1 slot if (!lastSingleWaferToSideB && info.OriginSlot == 1) { dummyInfo = info; break; } } if (dummyInfo == null) { dummyInfo = dummyWafers[0]; } } else { dummyInfo = dummyWafers[0]; } CreateDummyWaferTaskSchedulerSequence(waferHolderInfo.SequenceRecipe, dummyInfo, pufModuleName, waferInfo.WaferID,dummySide); _waferTaskMatchDic[waferInfo.WaferID] = dummyWafers[0].WaferID; _waferTaskMatchDic[dummyWafers[0].WaferID] = waferInfo.WaferID; _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask; _waferWaferHolderTaskDic[dummyWafers[0].WaferID] = waferHolderTask; return 2; } else { CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide); _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask; return 1; } } else { CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide); _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask; return 1; } } else if (wafers.Count >= 2) { for (int i = 0; i < 2; i++) { WaferInfo waferInfo = wafers[i]; ModuleName pufModuleName = ModuleName.PUF1; if (i == 0) { mateWaferTask = wafers[0].WaferID; if (CheckLoaderHasSameWaferSize()) { CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "", SIDE_A); } else { string side = AnalyseLoadSide(sequenceRecipe); CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "", side); } } else { if (CheckLoaderHasSameWaferSize()) { CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, mateWaferTask, SIDE_B); } else { string side = AnalyseLoadSide(sequenceRecipe); CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, mateWaferTask, side); } } } _waferTaskMatchDic[wafers[0].WaferID] = wafers[1].WaferID; _waferTaskMatchDic[wafers[1].WaferID] = wafers[0].WaferID; _waferWaferHolderTaskDic[wafers[0].WaferID] = waferHolderTask; _waferWaferHolderTaskDic[wafers[1].WaferID] = waferHolderTask; return 2; } return 0; } /// <summary> /// 检验Loader两边是不是尺寸一致 /// </summary> /// <returns></returns> private bool CheckLoaderHasSameWaferSize() { int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize"); int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize"); return sideAWaferSize == sideBWaferSize; } /// <summary> /// Loader两边尺寸不一致,解析Loader使用side /// </summary> /// <param name="recipe"></param> /// <returns></returns> private string AnalyseLoadSide(SequenceRecipe recipe) { int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize"); int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize"); if (sideAWaferSize != sideBWaferSize) { if(recipe.SubstrateSize==sideAWaferSize) { return SIDE_A; } else { return SIDE_B; } } return ""; } /// <summary> /// 检验WaferHolder是否存在两片生产片 /// </summary> /// <param name="waferHolderInfo"></param> /// <returns></returns> private bool CheckWaferHolderHasSameTypeWafers(WaferHolderInfo waferHolderInfo) { int count = 0; WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferAId); WaferType waferType = WaferType.Production; if (waferAInfo != null) { waferType = waferAInfo.WaferType; count++; } WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferBId); if (waferBInfo != null) { if (waferBInfo.WaferType == waferType) { count++; } } return count >= 2; } /// <summary> /// 检验WaferHolder是否存在两片生产片 /// </summary> /// <param name="waferHolderInfo"></param> /// <returns></returns> private bool CheckWaferHolderHasTwoProductionWafers(WaferHolderInfo waferHolderInfo) { int count = 0; WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferAId); if (waferAInfo != null && waferAInfo.WaferType==WaferType.Production) { count++; } WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferBId); if (waferBInfo != null && waferBInfo.WaferType == WaferType.Production) { count++; } return count >= 2; } /// <summary> /// 创建WaferTask SchedulerSequence /// </summary> /// <param name="waferInfo"></param> /// <param name="pufModuleName"></param> /// <param name="waferHolderInfo"></param> /// <param name="sequenceRecipe"></param> private void CreateWaferTaskSchedulerSequence(WaferInfo waferInfo, ModuleName pufModuleName, WaferHolderInfo waferHolderInfo, SequenceRecipe sequenceRecipe, string mateWafeTask,string side) { List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyWaferAllSchedulerSequence(waferInfo, pufModuleName,side, waferHolderInfo, sequenceRecipe); PUFEntity pufEntity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(pufModuleName.ToString()); WaferTask waferTask = new WaferTask(waferInfo, pufEntity, sequences); if (!string.IsNullOrEmpty(mateWafeTask)) { waferTask.MateWaferTask = mateWafeTask; } waferTask.OnTaskComplete += WaferTask_OnTaskComplete; LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create wafer {waferInfo.WaferID} task"); InitializeTask(waferTask); } /// <summary> /// 创建DummyWaferTask /// </summary> /// <param name="waferInfos"></param> public int CreateDummyWaferTask(List<WaferInfo> waferInfos,SequenceRecipe sequenceRecipe,WaferHolderTask waferHolderTask) { string mateWaferTask = ""; int waferCount = 0; for (int i = 0; i < waferInfos.Count; i++) { WaferInfo waferInfo = waferInfos[i]; int orginalSlot = waferInfo.OriginSlot; ModuleName pufModuleName = ModuleName.PUF1; string side = orginalSlot == 0 ? SIDE_A : SIDE_B; if(!CheckLoaderHasSameWaferSize()) { side = AnalyseLoadSide(sequenceRecipe); } waferCount = i; if (!Contains(waferInfo.WaferID)) { if (i == 0) { mateWaferTask = waferInfo.WaferID; CreateDummyWaferTaskSchedulerSequence(sequenceRecipe,waferInfo, pufModuleName,"", side); _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask; } else { CreateDummyWaferTaskSchedulerSequence(sequenceRecipe,waferInfo, pufModuleName, mateWaferTask,side); _waferTaskMatchDic[mateWaferTask] = waferInfo.WaferID; _waferTaskMatchDic[waferInfo.WaferID] = mateWaferTask; _waferWaferHolderTaskDic[waferInfo.WaferID]= waferHolderTask; break; } } } return waferCount + 1; } /// <summary> /// 创建Dummy Wafer Task 调度工序 /// </summary> /// <param name="waferInfo"></param> /// <param name="pufModuleName"></param> /// <param name="mateWaferTask"></param> private void CreateDummyWaferTaskSchedulerSequence(SequenceRecipe sequenceRecipe,WaferInfo waferInfo,ModuleName pufModuleName,string mateWaferTask,string side) { List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyDummyWaferAllSchedulerSequence(sequenceRecipe,waferInfo,pufModuleName, side); PUFEntity pufEntity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(pufModuleName.ToString()); WaferTask waferTask = new WaferTask(waferInfo, pufEntity,sequences); if (!string.IsNullOrEmpty(mateWaferTask)) { waferTask.MateWaferTask = mateWaferTask; } LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create Dummy wafer {waferInfo.WaferID} task"); waferTask.OnTaskStart += WaferTask_OnTaskStart; waferTask.OnTaskComplete += WaferTask_OnTaskComplete; InitializeTask(waferTask); } /// <summary> /// 任务开始 /// </summary> /// <param name="id"></param> /// <exception cref="NotImplementedException"></exception> private void WaferTask_OnTaskStart(string id) { WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(id); if (waferInfo != null && waferInfo.WaferType == WaferType.Production) { ModuleName moduleName = (ModuleName)waferInfo.OriginStation; if (ModuleHelper.IsLoadPort(moduleName)) { CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString()); } _schedulerFACallback.JobWaferStart(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob), waferInfo.SequenceName, waferInfo.OriginSlot); } } /// <summary> /// Wafer task完成事件 /// </summary> /// <param name="id"></param> private void WaferTask_OnTaskComplete(string id) { WaferInfo waferInfo=WaferManager.Instance.GetWaferByWaferId(id); if (waferInfo != null&&waferInfo.WaferType==WaferType.Production) { ModuleName moduleName = (ModuleName)waferInfo.OriginStation; if (ModuleHelper.IsLoadPort(moduleName)) { CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString()); } _schedulerFACallback.JobWaferEnd(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob), waferInfo.SequenceName, waferInfo.OriginSlot); } RemoveWaferTask(id); } /// <summary> /// 检验所有task是否完成 /// </summary> /// <returns></returns> public bool CheckAllTaskComplete() { return _waferTaskList.Count == 0; } /// <summary> /// 暂停 /// </summary> public void PauseAllTask() { List<WaferTask> waferTasks = _waferTaskList.ToList(); foreach(WaferTask item in waferTasks) { item.Pause(); } } /// <summary> /// 恢复所有任务 /// </summary> public void ResumeAllTask() { List<WaferTask> waferTasks = _waferTaskList.ToList(); foreach (WaferTask item in waferTasks) { item.Resume(); } } /// <summary> /// 恢复所有任务 /// </summary> public void RemoveAllTask() { List<WaferTask> waferTasks = _waferTaskList.ToList(); foreach (WaferTask item in waferTasks) { RemoveWaferTask(item.WaferId); } } /// <summary> /// 根据WaferId获取配对另一个WaferId /// </summary> /// <param name="waferId"></param> /// <returns></returns> public string GetMatchWaferIdByWaferId(string waferId) { return _waferTaskMatchDic.ContainsKey(waferId) ? _waferTaskMatchDic[waferId] : ""; } /// <summary> /// 移除WaferId匹配WaferHolderTask字典 /// </summary> /// <param name="waferId"></param> public void RemoveWaferIdMatchWaferHolderTaskDic(string waferId) { if(_waferWaferHolderTaskDic.ContainsKey(waferId)) { _waferWaferHolderTaskDic.TryRemove(waferId, out var waferHolderTask); } } /// <summary> /// 获取WaferId匹配WaferHolderTask字典 /// </summary> /// <param name="waferId"></param> /// <returns></returns> public WaferHolderTask GetWaferHolderTaskByWaferId(string waferId) { return _waferWaferHolderTaskDic.ContainsKey(waferId) ? _waferWaferHolderTaskDic[waferId] : null; } /// <summary> /// 获取WaferHolder Task对应的Wafer Task WaferId集合 /// </summary> /// <param name="waferHolderId"></param> /// <returns></returns> public List<string> GetWaferHolderMathWaferId(string waferHolderId) { List<string> keys = _waferWaferHolderTaskDic.Keys.ToList(); List<string> result = new List<string>(); foreach(string item in keys) { if(_waferWaferHolderTaskDic[item].WaferHolderInfo.Id==waferHolderId) { result.Add(item); } } return result; } /// <summary> /// 检验Wafer存在匹配的wafer任务(wafer是单片任务还是双片任务) /// </summary> /// <param name="waferId"></param> /// <returns></returns> public string CheckWaferHasMatch(string waferId) { if (_waferTaskMatchDic.ContainsKey(waferId)) { return _waferTaskMatchDic[waferId]; } else { return ""; } } } }