using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.Common; using Aitex.Core.RT.Device; using Aitex.Core.RT.SCCore; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; namespace Aitex.Sorter.RT.Module.Recipe { public class RecipeParserByPort1ToN { public List Parse(SorterRecipeXml xmlRecipe, out string reason) { List result = new List(); reason = string.Empty; List wafersInSourceList = new List(); List wafersInDestinationList = new List(); List destinationModules = new List(); bool isLoad = false; for (int i = 0; i < xmlRecipe.Source.Count; i++) { LoadPort lp = DEVICE.GetDevice(xmlRecipe.Source[i].ToString()); if (lp.IsEnableTransferWafer(out reason)) { isLoad = true; WaferInfo[] wafersInSource = WaferManager.Instance.GetWafers(xmlRecipe.Source[i]); wafersInSourceList.Add(wafersInSource); } } if (!isLoad) { if (string.IsNullOrEmpty(reason)) reason = "Source is not valid for transfer."; return result; } reason = string.Empty; isLoad = false; for (int i = 0; i < xmlRecipe.Destination.Count; i++) { LoadPort lp = DEVICE.GetDevice(xmlRecipe.Destination[i].ToString()); if (lp.IsEnableTransferWafer(out reason)) { isLoad = true; if (!lp.IsEnableTransferWafer()) continue; destinationModules.Add(xmlRecipe.Destination[i]); WaferInfo[] wafersInDestination = WaferManager.Instance.GetWafers(xmlRecipe.Destination[i]); wafersInDestinationList.Add(wafersInDestination); } } if (!isLoad) { if (string.IsNullOrEmpty(reason)) reason = "Destination is not valid for transfer.."; return result; } if (wafersInSourceList.Count == 0 || wafersInDestinationList.Count == 0) { reason = "Recipe has no vaild transfer task."; return result; } switch (xmlRecipe.PlaceModeTransfer1To1) { case SorterRecipePlaceModeTransfer1To1.FromBottom: FromBottom(xmlRecipe, wafersInSourceList, wafersInDestinationList, destinationModules, ref result, out reason); break; case SorterRecipePlaceModeTransfer1To1.FromTop: FromTop(xmlRecipe, wafersInSourceList, wafersInDestinationList, destinationModules, ref result, out reason); break; case SorterRecipePlaceModeTransfer1To1.SameSlot: SameSlot(xmlRecipe, wafersInSourceList, wafersInDestinationList, destinationModules, ref result, out reason); break; default: reason = string.Format("recipe PlaceModeTransfer1To1 {0} not valid", xmlRecipe.PlaceModeTransfer1To1); return result; } //if (result.Count == 0) // reason = "Recipe has no vaild transfer task."; return result; } /// /// 从source最下面开始取wafer,顺序放在destination的最下面 /// /// /// /// bool FromBottom(SorterRecipeXml xmlRecipe, List sourceList, List destinationList, List destinationModules, ref List lst, out string reason) { reason = string.Empty; SCConfigItem _scLP2Pitch = SC.GetConfigItem("LoadPort.LoadPort2Pitch"); if (_scLP2Pitch == null || _scLP2Pitch.IntValue == 10) { int destinationIndex = -1; for (int i = 0; i < sourceList.Count * sourceList[0].Length; i++) { WaferInfo[] source = sourceList[i / sourceList[0].Length]; if (source[i % sourceList[0].Length].IsEmpty) continue; int to = destinationIndex; for (int j = destinationIndex + 1; j < destinationList.Count * destinationList[0].Length; j++) { WaferInfo[] destination = destinationList[j / destinationList[0].Length]; if (destination[j % destinationList[0].Length].IsEmpty) { to = j; break; } } if (to == destinationIndex) break; destinationIndex = to; lst.Add(new TransferInfo() { Source = (ModuleName)source[i % sourceList[0].Length].Station, SourceSlot = source[i % sourceList[0].Length].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = to % destinationList[0].Length, Station = destinationModules[to / destinationList[0].Length], WaferID = source[i % sourceList[0].Length].WaferID, }); ; } } else { if (sourceList.Count > 1 || destinationList.Count > 1) { reason = "Multiple Sources and Destinations are not supported in SameSlot mode"; return false; } int destinationIndex = -1; SCConfigItem _scEnable = SC.GetConfigItem("LoadPort.EnableSlot1OnLP2"); bool isContinue = false; for (int i = 0; i < sourceList[0].Length; i++) { WaferInfo[] source = sourceList[0]; if (isContinue && source[i].IsEmpty) isContinue = false; if (source[i].IsEmpty) { continue; } if (!_scEnable.BoolValue && i == 0) { isContinue = true; continue; } if (isContinue) continue; int to = destinationIndex; for (int j = destinationIndex + 1; j < destinationList.Count * destinationList[0].Length; j++) { WaferInfo[] destination = destinationList[j / destinationList[0].Length]; if (destination[j % destinationList[0].Length].IsEmpty) { to = j; break; } } if (to == destinationIndex) break; destinationIndex = to; lst.Add(new TransferInfo() { Source = (ModuleName)source[i % sourceList[0].Length].Station, SourceSlot = source[i % sourceList[0].Length].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = to % destinationList[0].Length, Station = destinationModules[to / destinationList[0].Length], WaferID = source[i % sourceList[0].Length].WaferID, }); } } return true; } /// /// 放在同一位置,如果有冲突,直接忽略 /// /// /// /// bool SameSlot(SorterRecipeXml xmlRecipe, List sourceList, List destinationList, List destinationModules, ref List lst, out string reason) { reason = string.Empty; if (sourceList.Count > 1 || destinationList.Count > 1) { reason = "Multiple Sources and Destinations are not supported in SameSlot mode"; return false; } WaferInfo[] source = sourceList[0]; WaferInfo[] destination = destinationList[0]; //int destinationIndex = -1; SCConfigItem _scLP2Pitch = SC.GetConfigItem("LoadPort.LoadPort2Pitch"); if (_scLP2Pitch == null || _scLP2Pitch.IntValue == 10) { for (int i = 0; i < source.Length && i < destination.Length; i++) { if (source[i].IsEmpty || (!destination[i].IsEmpty && !(source[i].Station == destination[i].Station && source[i].Slot == destination[i].Slot))) continue; lst.Add(new TransferInfo() { Source = (ModuleName)source[i].Station, SourceSlot = source[i].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = i, Station = destinationModules[0], WaferID = source[i].WaferID, }); } } else if (_scLP2Pitch.IntValue == 7 && xmlRecipe.Destination[0] == ModuleName.LP2) { SCConfigItem _scEnable = SC.GetConfigItem("LoadPort.EnableSlot1OnLP2"); for (int i = source.Length - 1; i >= 0; i--) { if (source[i].IsEmpty || !destination[i].IsEmpty || (!_scEnable.BoolValue && i == 0) || (i > 0 && !destination[i - 1].IsEmpty)) continue; lst.Add(new TransferInfo() { Source = (ModuleName)source[i].Station, SourceSlot = source[i].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = i, Station = destinationModules[0], WaferID = source[i].WaferID, }); } } else if ((_scLP2Pitch.IntValue == 7 && xmlRecipe.Source[0] == ModuleName.LP2)) { SCConfigItem _scEnable = SC.GetConfigItem("LoadPort.EnableSlot1OnLP2"); bool isContinue = false; for (int i = 0; i < source.Length && i < destination.Length; i++) { if (isContinue && source[i].IsEmpty) isContinue = false; if (source[i].IsEmpty || !destination[i].IsEmpty) continue; if (!_scEnable.BoolValue && i == 0 || (i > 0 && !destination[i - 1].IsEmpty)) { isContinue = true; continue; } if (isContinue) continue; lst.Add(new TransferInfo() { Source = (ModuleName)source[i].Station, SourceSlot = source[i].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = i, Station = destinationModules[0], WaferID = source[i].WaferID, }); } } return true; } /// /// 从source最上面开始取wafer,顺序放在destination的最上面 /// /// /// /// bool FromTop(SorterRecipeXml xmlRecipe, List sourceList, List destinationList, List destinationModules, ref List lst, out string reason) { reason = string.Empty; SCConfigItem _scLP2Pitch = SC.GetConfigItem("LoadPort.LoadPort2Pitch"); if (_scLP2Pitch == null || _scLP2Pitch.IntValue == 10) { int destinationIndex = destinationList.Count * destinationList[0].Length; for (int i = 0; i < sourceList.Count * sourceList[0].Length; i++) { WaferInfo[] source = sourceList[sourceList.Count - i / sourceList[0].Length - 1]; if (source[i % sourceList[0].Length].IsEmpty) continue; if (SC.ContainsItem("Process.EnableSlot25OnLP2") && (!SC.GetValue("Process.EnableSlot25OnLP2")) && destinationModules[0] == ModuleName.LP2 && destinationIndex == 25) destinationIndex = 24; int to = destinationIndex; for (int j = destinationIndex - 1; j >= 0; j--) { WaferInfo[] destination = destinationList[destinationList.Count - j / destinationList[0].Length - 1]; if (destination[j % destinationList[0].Length].IsEmpty) { to = j; break; } } if (to == destinationIndex) break; destinationIndex = to; lst.Add(new TransferInfo() { Source = (ModuleName)source[i % sourceList[0].Length].Station, SourceSlot = source[i % sourceList[0].Length].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = to % destinationList[0].Length, Station = destinationModules[destinationList.Count - to / destinationList[0].Length - 1], WaferID = source[i % sourceList[0].Length].WaferID, }); } } else { if (sourceList.Count > 1 || destinationList.Count > 1) { reason = "Multiple Sources and Destinations are not supported in SameSlot mode"; return false; } SCConfigItem _scEnable = SC.GetConfigItem("LoadPort.EnableSlot1OnLP2"); if (xmlRecipe.Source[0] == ModuleName.LP2) //Source为LP2 { bool isContinue = false; int destinationIndex = destinationList[0].Length; for (int i = 0; i < sourceList[0].Length; i++) { WaferInfo[] source = sourceList[0]; if (isContinue && source[i].IsEmpty) isContinue = false; if (source[i].IsEmpty) continue; if (!_scEnable.BoolValue && i == 0) { isContinue = true; continue; } if (isContinue) continue; int to = destinationIndex; for (int j = destinationIndex - 1; j >= 0; j--) { WaferInfo[] destination = destinationList[0]; if (destination[j].IsEmpty) { to = j; break; } } if (to == destinationIndex) break; destinationIndex = to; lst.Add(new TransferInfo() { Source = (ModuleName)source[i].Station, SourceSlot = source[i].Slot, Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = to, Station = destinationModules[0], WaferID = source[i].WaferID, }); } } else //Station为LP2 { int destinationIndex = destinationList[0].Length; if (SC.ContainsItem("Process.EnableSlot25OnLP2") && (!SC.GetValue("Process.EnableSlot25OnLP2"))&& destinationIndex == 25) destinationIndex = 24; for (int i = sourceList[0].Length - 1; i >= 0; i--) { WaferInfo[] source = sourceList[0]; if (source[i].IsEmpty) continue; int to = destinationIndex; for (int j = destinationIndex - 1; j >= 0; j--) { WaferInfo[] destination = destinationList[0]; if (j == 0) { if (_scEnable.BoolValue) { if (destination[j].IsEmpty) { to = j; break; } } } else { if (destination[j - 1].IsEmpty && destination[j].IsEmpty) { to = j; break; } } } if (to == destinationIndex) break; destinationIndex = to; lst.Add(new TransferInfo() { Angle = xmlRecipe.AlignAngle, Option = (xmlRecipe.IsAlign ? MoveOption.Align : MoveOption.None) | (xmlRecipe.IsReadLaserMarker ? MoveOption.ReadID : MoveOption.None) | (xmlRecipe.IsReadT7Code ? MoveOption.ReadID2 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 1 ? MoveOption.Reader1 : MoveOption.None) | (xmlRecipe.WaferReaderIndex == 2 ? MoveOption.Reader2 : MoveOption.None) | (xmlRecipe.IsTurnOver ? MoveOption.Turnover : MoveOption.None), Slot = to, Station = destinationModules[0], WaferID = source[i].WaferID, }); } } } return true; } } }