using Aitex.Core.RT.Fsm; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using CyberX8_RT.Modules; using CyberX8_RT.Schedulers.Transporter; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.RecipeCenter; using SecsGem.Core.ItemModel; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace CyberX8_RT.Schedulers { public class SchedulerModuleTimeManager : Singleton { /// /// 确定后面所有Metal、Qdr和Dryer资源 /// /// /// /// /// /// /// public bool ConfirmAllMetalQdrAndDryer(List schedulerSequences, string waferHolderId, int sequenceIndex,bool checkConflict,DateTime startTime) { int transporterTransferSeconds = SC.GetValue("Transporter.TransporterTransferSeconds"); var avaibleResults = AnalyseAfterAvaibleCell(schedulerSequences, startTime, waferHolderId, sequenceIndex,checkConflict); if (!avaibleResults.success) { return false; } if (avaibleResults.results.Count == 0 && avaibleResults.rinseResults.Item2 == ModuleName.Unknown && avaibleResults.dryerResults.Item2 == ModuleName.Unknown) { return false; } SchedulerModulePartTime metalPartTime = new SchedulerModulePartTime(); SchedulerModulePartTime qdrPartTime = new SchedulerModulePartTime(); SchedulerModulePartTime dryerPartTime = new SchedulerModulePartTime(); //处理metal和Rinse for (int i = 0; i < avaibleResults.results.Count; i++) { var item = avaibleResults.results[i]; int index = item.Item1; SchedulerSequence sequence = schedulerSequences[index]; if (sequence.State == CyberX8_Core.RState.End) { continue; } if (sequence.ModuleName != ModuleName.Transporter1) { continue; } SchedulerSequence metalSequence = schedulerSequences[index + 1]; if (metalSequence.ModuleType != ModuleType.Metal) { continue; } DepRecipe depRecipe = (DepRecipe)metalSequence.Recipe; QdrRecipe qdrRecipe = (QdrRecipe)metalSequence.NextRecipe; int depRecipeTimeLength = depRecipe.CalculateRecipeTotalTime(); int qdrRecipeTimeLength = qdrRecipe.CalculateRunRecipeTime(); if(!(sequence.Parameters is TransporterAction)) { continue; } TransporterAction transporterAction = (TransporterAction)sequence.Parameters; if(!(transporterAction.Parameter is WaferHolderMoveItem)) { continue; } WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)transporterAction.Parameter; waferHolderMoveItem.DestModule = item.Item2; DateTime metalStartTime = item.Item4.AddSeconds(transporterTransferSeconds); if (metalSequence.SchedulerModule == null) { metalSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(item.Item2); metalSequence.ModuleName = item.Item2; } if (!checkConflict) { SchedulerTime lastSchedulerTime = SchedulerMetalTimeManager.Instance.GetLastSchedulerTime(item.Item2.ToString()); DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, metalPartTime, item.Item2.ToString(), depRecipeTimeLength, transporterTransferSeconds); if (lastSchedulerEndTime > metalStartTime) { metalStartTime = lastSchedulerEndTime; } } SchedulerMetalTimeManager.Instance.AddMetalScheduler(item.Item2.ToString(), waferHolderId, index + 1, metalStartTime, depRecipeTimeLength, false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, item.Item2.ToString(), ModuleType.Metal, index + 1, metalStartTime, depRecipeTimeLength); metalPartTime.AddScheduler(item.Item2.ToString(), waferHolderId, index + 1, metalStartTime, depRecipeTimeLength); if (index + 3 >= schedulerSequences.Count) { continue; } SchedulerSequence transporterSequence = schedulerSequences[index + 2]; if(!(transporterSequence.Parameters is TransporterAction)) { continue; } TransporterAction action = transporterSequence.Parameters as TransporterAction; if(!(action.Parameter is WaferHolderMoveItem)) { continue; } WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)action.Parameter; tranporterMoveItem.DestModule = item.Item3; //增加了transporter时间轴 SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, index + 2, metalStartTime.AddSeconds(depRecipeTimeLength), false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, index + 2, metalStartTime.AddSeconds(depRecipeTimeLength), transporterTransferSeconds); SchedulerSequence qdrSequence = schedulerSequences[index + 3]; if (qdrSequence.ModuleType != ModuleType.Rinse) { continue; } if (qdrSequence.SchedulerModule == null) { qdrSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(item.Item3); qdrSequence.ModuleName = item.Item3; } DateTime schedulerQdrStartTime = SchedulerQdrTimeManager.Instance.CalculateQdrSchedulerStartTime(metalStartTime, depRecipeTimeLength); if (!checkConflict) { SchedulerTime lastSchedulerTime = SchedulerQdrTimeManager.Instance.GetLastSchedulerTime(item.Item3.ToString()); DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, item.Item3.ToString(), qdrRecipeTimeLength, transporterTransferSeconds); if (lastSchedulerEndTime > schedulerQdrStartTime) { schedulerQdrStartTime = lastSchedulerEndTime; } } SchedulerQdrTimeManager.Instance.AddQdrScheduler(item.Item3.ToString(), waferHolderId, index + 3, schedulerQdrStartTime, qdrRecipeTimeLength, false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, item.Item3.ToString(),ModuleType.Rinse, index + 3, schedulerQdrStartTime, qdrRecipeTimeLength); qdrPartTime.AddScheduler(item.Item3.ToString(), waferHolderId, index + 3, schedulerQdrStartTime, qdrRecipeTimeLength); //增加了transporter时间轴 SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, index + 4, schedulerQdrStartTime.AddSeconds(qdrRecipeTimeLength), false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, index + 4, schedulerQdrStartTime.AddSeconds(qdrRecipeTimeLength), transporterTransferSeconds); } //处理单独Rinse if (avaibleResults.rinseResults.Item2 != ModuleName.Unknown) { int transporterIndex = avaibleResults.rinseResults.Item1; SchedulerSequence transporterSequence = schedulerSequences[transporterIndex]; if (transporterSequence.State != CyberX8_Core.RState.End) { //增加了transporter时间轴 SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex, avaibleResults.rinseResults.Item3, false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex, avaibleResults.rinseResults.Item3, transporterTransferSeconds); } if(transporterSequence.Parameters is TransporterAction) { TransporterAction transporterAction=transporterSequence.Parameters as TransporterAction; WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)transporterAction.Parameter; tranporterMoveItem.DestModule = avaibleResults.rinseResults.Item2; SchedulerSequence rinseSequence = schedulerSequences[transporterIndex + 1]; QdrRecipe qdrRecipe = rinseSequence.Recipe as QdrRecipe; if (rinseSequence.SchedulerModule == null) { rinseSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(avaibleResults.rinseResults.Item2); rinseSequence.ModuleName = avaibleResults.rinseResults.Item2; } DateTime schedulerRinseStartTime = avaibleResults.rinseResults.Item3.AddSeconds(transporterTransferSeconds); if (!checkConflict) { SchedulerTime lastSchedulerTime = SchedulerQdrTimeManager.Instance.GetLastSchedulerTime(avaibleResults.rinseResults.Item2.ToString()); DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, avaibleResults.rinseResults.Item2.ToString(), qdrRecipe.CalculateRunRecipeTime(), transporterTransferSeconds); if (lastSchedulerEndTime > schedulerRinseStartTime) { schedulerRinseStartTime = lastSchedulerEndTime; } } SchedulerQdrTimeManager.Instance.AddQdrScheduler(avaibleResults.rinseResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime(), false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, avaibleResults.rinseResults.Item2.ToString(), ModuleType.Rinse, transporterIndex + 1, schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime()); qdrPartTime.AddScheduler(avaibleResults.rinseResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerRinseStartTime, qdrRecipe.CalculateRunRecipeTime()); SchedulerSequence nextTransporterSequence = schedulerSequences[transporterIndex + 2]; if (nextTransporterSequence != null && nextTransporterSequence.State != CyberX8_Core.RState.End) { //增加了transporter时间轴 SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex + 2, schedulerRinseStartTime.AddSeconds(qdrRecipe.CalculateRunRecipeTime()), false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex + 2, schedulerRinseStartTime.AddSeconds(qdrRecipe.CalculateRunRecipeTime()), transporterTransferSeconds); } } } //处理Dryer if (avaibleResults.dryerResults.Item2 != ModuleName.Unknown) { int transporterIndex = avaibleResults.dryerResults.Item1; SchedulerSequence transporterSequence = schedulerSequences[transporterIndex]; if (transporterSequence.Parameters is TransporterAction) { TransporterAction action=transporterSequence.Parameters as TransporterAction; WaferHolderMoveItem tranporterMoveItem = (WaferHolderMoveItem)action.Parameter; tranporterMoveItem.DestModule = avaibleResults.dryerResults.Item2; SchedulerSequence dryerSequence = schedulerSequences[transporterIndex + 1]; HvdRecipe hvdRecipe = dryerSequence.Recipe as HvdRecipe; if (dryerSequence.SchedulerModule == null) { dryerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(avaibleResults.dryerResults.Item2); dryerSequence.ModuleName = avaibleResults.dryerResults.Item2; } DateTime schedulerDryerStartTime = SchedulerDryerTimeManager.Instance.CalculateDryerSchedulerStartTime(avaibleResults.dryerResults.Item3); if (!checkConflict) { SchedulerTime lastSchedulerTime = SchedulerDryerTimeManager.Instance.GetLastSchedulerTime(avaibleResults.dryerResults.Item2.ToString()); DateTime lastSchedulerEndTime = GetModuleLastSchedulerEndTime(lastSchedulerTime, qdrPartTime, avaibleResults.dryerResults.Item2.ToString(), hvdRecipe.DryTime, transporterTransferSeconds); if (lastSchedulerEndTime > schedulerDryerStartTime) { schedulerDryerStartTime = lastSchedulerEndTime; } } if (!SchedulerTransporterTimeManager.Instance.Contained(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex)) { if (transporterSequence.State != CyberX8_Core.RState.End) { //增加了transporter时间轴 SchedulerTransporterTimeManager.Instance.AddTransporterScheduler(ModuleName.Transporter1.ToString(), waferHolderId, transporterIndex, schedulerDryerStartTime.AddSeconds(-transporterTransferSeconds), false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, ModuleName.Transporter1.ToString(), ModuleType.Transporter, transporterIndex, schedulerDryerStartTime.AddSeconds(-transporterTransferSeconds), transporterTransferSeconds); } } SchedulerDryerTimeManager.Instance.AddDryerScheduler(avaibleResults.dryerResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerDryerStartTime, hvdRecipe.DryTime, false); SchedulerWaferHolderTimeManager.Instance.AddWaferHolderTime(waferHolderId, avaibleResults.dryerResults.Item2.ToString(), ModuleType.Dryer, transporterIndex + 1, schedulerDryerStartTime, hvdRecipe.DryTime); dryerPartTime.AddScheduler(avaibleResults.dryerResults.Item2.ToString(), waferHolderId, transporterIndex + 1, schedulerDryerStartTime, hvdRecipe.DryTime); } } SchedulerMetalTimeManager.Instance.WriteMetalSchedulerTimeLog(); SchedulerQdrTimeManager.Instance.WriteQdrSchedulerTimeLog(); SchedulerDryerTimeManager.Instance.WriteDryerSchedulerTimeLog(); SchedulerTransporterTimeManager.Instance.WriteTransporterSchedulerTimeLog(); SchedulerWaferHolderTimeManager.Instance.WriteSchedulerTimeLog(waferHolderId); qdrPartTime.Dispose(); metalPartTime.Dispose(); dryerPartTime.Dispose(); return true; } /// /// 获取最新调度时间 /// /// /// /// /// /// /// private DateTime GetModuleLastSchedulerEndTime(SchedulerTime schedulerTime,SchedulerModulePartTime partTime,string module,int recipeLength,int transporterTransferSeconds) { DateTime lastSchedulerEndTime = DateTime.MinValue; if (schedulerTime != null) { lastSchedulerEndTime = schedulerTime.ScheduleStartTime.AddSeconds(recipeLength).AddSeconds(transporterTransferSeconds); } DateTime lastPartTime = partTime.GetLastSchedulerTime(module); if (lastPartTime.AddSeconds(transporterTransferSeconds) > lastSchedulerEndTime) { lastSchedulerEndTime = lastPartTime.AddSeconds(transporterTransferSeconds); } return lastSchedulerEndTime; } /// /// 分析后面所有Cell可用资源 /// sequenceIndex为transporter对应的索引 /// /// /// /// /// public (bool success,List<(int, ModuleName, ModuleName, DateTime)> results, (int, ModuleName, DateTime) rinseResults,(int, ModuleName, DateTime) dryerResults) AnalyseAfterAvaibleCell(List schedulerSequences, DateTime startTime, string waferHolderId, int sequenceIndex,bool checkConflict) { int transporterTransferSeconds = SC.GetValue("Transporter.TransporterTransferSeconds"); List<(int, ModuleName, ModuleName, DateTime)> results = new List<(int, ModuleName, ModuleName, DateTime)>(); var dryerResults = new ValueTuple(); dryerResults.Item2 = ModuleName.Unknown; var rinseResults = new ValueTuple(); rinseResults.Item2 = ModuleName.Unknown; SchedulerModulePartTime metalPartTime = new SchedulerModulePartTime(); SchedulerModulePartTime qdrPartTime = new SchedulerModulePartTime(); for (int i = sequenceIndex; i < schedulerSequences.Count; i++) { SchedulerSequence sequence = schedulerSequences[i]; if (sequence.State == CyberX8_Core.RState.End) { continue; } if (sequence.ModuleName != ModuleName.Transporter1) { continue; } if(!(sequence.Parameters is TransporterAction)) { continue; } TransporterAction transporterAction = (TransporterAction)sequence.Parameters; if(!(transporterAction.Parameter is WaferHolderMoveItem)) { continue; } WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)transporterAction.Parameter; //确定Dryer资源 if (waferHolderMoveItem.DestModuleType == ModuleType.Dryer) { SchedulerSequence nextSequence = schedulerSequences[i + 1]; HvdRecipe hvdRecipe = (HvdRecipe)nextSequence.Recipe; ModuleName dryerModule = SchedulerSequenceManager.Instance.GetAvaibleDryerCell(waferHolderId, startTime, hvdRecipe.DryTime,checkConflict); if (dryerModule == ModuleName.Unknown) { metalPartTime.Dispose(); qdrPartTime.Dispose(); return (false,results,rinseResults,dryerResults); } dryerResults.Item1 = i; dryerResults.Item2 = dryerModule; dryerResults.Item3 = startTime; continue; } if (waferHolderMoveItem.DestModuleType == ModuleType.Rinse&&!checkConflict) { SchedulerSequence preSequence= schedulerSequences[i -1]; if (preSequence.ModuleName == ModuleName.Unknown) { continue; } SchedulerSequence nextSequence = schedulerSequences[i + 1]; QdrRecipe nextQdrRecipe = (QdrRecipe)nextSequence.Recipe; ModuleName qdrModule = SchedulerSequenceManager.Instance.GetAvaibleQdrCell(waferHolderId, preSequence.ModuleName.ToString()); if (qdrModule == ModuleName.Unknown) { metalPartTime.Dispose(); qdrPartTime.Dispose(); return (false, results,rinseResults, dryerResults); } rinseResults.Item1 = i; rinseResults.Item2 = qdrModule; rinseResults.Item3 = startTime; startTime = startTime.AddSeconds(transporterTransferSeconds).AddSeconds(nextQdrRecipe.CalculateRunRecipeTime()); continue; } if (waferHolderMoveItem.DestModuleType != ModuleType.Metal) { continue; } SchedulerSequence metalSequence = schedulerSequences[i + 1]; if (metalSequence.Recipe == null || !(metalSequence.Recipe is DepRecipe)) { continue; } DepRecipe depRecipe = (DepRecipe)metalSequence.Recipe; QdrRecipe qdrRecipe = (QdrRecipe)metalSequence.NextRecipe; int depRecipeTimeLength = depRecipe.CalculateRecipeTotalTime(); int qdrRecipeTimeLength = qdrRecipe.CalculateRunRecipeTime(); bool existEnableCell = false; var result = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, waferHolderMoveItem.SourceModule.ToString(), metalSequence.SequenceType, waferHolderId, metalSequence.WaferSize,startTime.AddSeconds(transporterTransferSeconds), depRecipeTimeLength, qdrRecipeTimeLength, checkConflict,metalPartTime,qdrPartTime, ref existEnableCell); if (result.metalModule == ModuleName.Unknown || result.rinseModule == ModuleName.Unknown) { metalPartTime.Dispose(); qdrPartTime.Dispose(); return (false,results,rinseResults,dryerResults); } results.Add((i, result.metalModule, result.rinseModule, startTime)); startTime = startTime.AddSeconds(transporterTransferSeconds).AddSeconds(depRecipeTimeLength) .AddSeconds(transporterTransferSeconds).AddSeconds(qdrRecipeTimeLength); metalPartTime.AddScheduler(result.metalModule.ToString(), waferHolderId, i + 1, startTime, depRecipeTimeLength); qdrPartTime.AddScheduler(result.rinseModule.ToString(), waferHolderId, i + 3, startTime.AddSeconds(depRecipeTimeLength).AddSeconds(transporterTransferSeconds), qdrRecipeTimeLength); i += 3; } metalPartTime.Dispose(); qdrPartTime.Dispose(); return (true, results,rinseResults, dryerResults); } } }