SicMultiplate/SicRT/Equipments/ManualAutoTransfer.cs

2858 lines
104 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using Aitex.Core.Common;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.DBCore;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.Schedulers;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UnLoad;
using SicRT.Equipments.Schedulers;
using SicRT.Modules.Schedulers;
namespace SicRT.Modules
{
public partial class ManualAutoTransfer : SchedulerModuleFactory
{
public class TrayInfo
{
public int TrayModule { get; set; }
public int TraySlot { get; set; }
public int TrayProcessCount { get; set; }
}
private List<ControlJobInfo> _lstNeedMapJob = new();
private List<ControlJobInfo> _lstControlJobs = new();
private List<ProcessJobInfo> _lstProcessJobs = new();
private List<TrayInfo> _lstProcessedTrayInfo = new(); //保存石墨盘的进入腔体的信息(最多4次工艺需要换盘)
private int _maxTrayCount = 4; //可以同时运行的石墨盘总数
private bool _cassProcessOnebyOne = false; //Cassette是左右交互取片还是一个Cassette取完再取另一个
private R_TRIG NotifyTrayExhausted = new();
private const string LogSource = "Scheduler";
private SchedulerDBCallback _dbCallback;
//private const string StatsNameTotalRunningWafer = "TotalRunningWafer";
public bool CassetteFromAToB => SC.GetValue<bool>("System.Scheduler.CassetteFromAToB");
private bool _isCycleMode;
private int _cycleSetPoint = 0;
private int _cycledCount = 0;
private int _cycledWafer = 0;
private string _curRecipeName = "";
private string _curSequenceName = "";
private bool _isModuleErrorPrevious;
private bool[] _isPMErrorPrevious = new bool[2];
private double _timeBuffer1 { get; set; }
private double _timeBuffer2 { get; set; }
private double _timeBuffer3 { get; set; }
private double _timeLoad { get; set; }
private const int _bufferFloors = 1;
private Dictionary<string, DateTime> _loadWaferInfo = new();
private Dictionary<string, DateTime> _bufferWaferInfo = new();
private Queue<Action> waferRobotActions = new() { };
private Queue<Action> trayRobotActions = new() { };
private Queue<Action> tmRobotActions = new() { };
private R_TRIG _updateAutoJobLocation = new(); //需要向数据库更新Wafer位置
public ManualAutoTransfer()
{
_dbCallback = new SchedulerDBCallback();
DATA.Subscribe("Scheduler.IsCycleMode", () => _isCycleMode);
DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
DATA.Subscribe("Scheduler.RecipeName", () => _curRecipeName);
DATA.Subscribe("Scheduler.SequenceName", () => _curSequenceName);
DATA.Subscribe("Scheduler.TimeBuffer1", () => _timeBuffer1);
DATA.Subscribe("Scheduler.TimeBuffer2", () => _timeBuffer2);
DATA.Subscribe("Scheduler.TimeBuffer3", () => _timeBuffer3);
DATA.Subscribe("Scheduler.TimeLoad", () => _timeLoad);
DATA.Subscribe("LoadLock.LocalJobName", () =>
{
var jb = _lstControlJobs.Find(x => x.Module == "LoadLock");
if (jb != null)
return jb.Name;
return "";
});
DATA.Subscribe("LoadLock.LocalJobStatus", () =>
{
var jb = _lstControlJobs.Find(x => x.Module == "LoadLock");
if (jb != null)
return jb.State.ToString();
return "";
});
OP.Subscribe($"{ModuleName.TM}.ResetTask", (string cmd, object[] args) =>
{
_tmRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.EFEM}.ResetTask", (string cmd, object[] args) =>
{
_waferRobot.ResetTask();
_trayRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.WaferRobot}.ResetTask", (string cmd, object[] args) =>
{
_waferRobot.ResetTask();
return true;
});
OP.Subscribe($"{ModuleName.TrayRobot}.ResetTask", (string cmd, object[] args) =>
{
_trayRobot.ResetTask();
return true;
});
tmRobotActions.Enqueue(MonitorTmRobotLoadPlaceTask);
tmRobotActions.Enqueue(MonitorTmRobotLoadPickTask);
tmRobotActions.Enqueue(MonitorTmRobotPMPlaceTask);
tmRobotActions.Enqueue(MonitorTmRobotPMPickTask);
tmRobotActions.Enqueue(MonitorTmRobotBufferPlaceTask);
tmRobotActions.Enqueue(MonitorTmRobotBufferPickTask);
}
public bool HasJobRunning
{
get { return _lstControlJobs.Count > 0; }
}
public void Clear()
{
_tmRobot.ResetTask();
foreach (var pm in _lstPms)
{
pm.ResetTask();
}
_load.ResetTask();
_buffer.ResetTask();
_lstControlJobs.Clear();
_lstProcessJobs.Clear();
_loadWaferInfo.Clear();
}
public void ResetTask()
{
if (!_load.IsOnline)
{
_load.ResetTask();
}
if (!_buffer.IsOnline)
{
_buffer.ResetTask();
}
foreach (var pm in _lstPms)
{
if (!pm.IsOnline)
{
pm.ResetTask();
}
}
}
public void GetConfig()
{
_cycledCount = 0;
_isCycleMode = SC.GetValue<bool>("System.IsCycleMode");
_cycleSetPoint = _isCycleMode ? SC.GetValue<int>("System.CycleCount") : 0;
_maxTrayCount = _lstPms.Count * 2;
}
#region Job Management
public bool CreateJob(Dictionary<string, object> param)
{
var reason = "";
var slotSequence = (string[])param["SlotSequence"];
var jobId = (string)param["JobId"];
var module = (string)param["Module"];
var lotId = (string)param["LotId"];
var autoStart = (bool)param["AutoStart"];
////检查Load腔Lock是否锁定
//if(!_load.CheckLocked())
//{
// EV.PostWarningLog(LogSource, $"The Load is Unlocked,do not start");
// return false;
//}
//检查所有Module里Tray的数量
if (GetCurrentTrayCount() >= _maxTrayCount)
{
EV.PostWarningLog(LogSource, $"The machine has more than {_maxTrayCount} Tray");
return false;
}
//拿到Recipe和ModuleName
var recipeName = "";
var moduleName = ModuleName.System;
var seq = SequenceInfoHelper.GetInfo(slotSequence[0]);
for (var i = 0; i < seq.Steps.Count; i++)
{
var stepInfo = seq.Steps[i];
foreach (var m in stepInfo.StepModules)
{
if (ModuleHelper.IsPm(m))
{
recipeName = seq.Steps[i].RecipeName;
moduleName = m;
}
}
}
//每个PM腔不能超过2个对应Wafer
if (moduleName != ModuleName.System)
{
if (GetRunWaferCount(moduleName) >= _maxTrayCount / 2)
{
EV.PostWarningLog(LogSource, $"Creating the job failed . There are already {_maxTrayCount / 2} job of the same pm in the system.");
return false;
}
}
if (CheckModuleHaveWaferWithNoJob(out reason))
{
EV.PostWarningLog(LogSource, $"{reason}");
return false;
}
if (!ValidateSequence(slotSequence, out reason))
{
EV.PostWarningLog(LogSource, $"{reason}");
return false;
}
if (slotSequence.Length != 1)
{
reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 1";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (string.IsNullOrEmpty(jobId))
{
jobId = "CJ_Local_Load" + DateTime.Now;
}
if (_lstControlJobs.Exists(x => x.Name == jobId))
{
reason = $"JobID : {jobId} already created";
EV.PostWarningLog(LogSource, reason);
return false;
}
//检查Sequence对应的PM腔状态
if (!CheckPMState(slotSequence[0]))
{
return false;
}
var cj = new ControlJobInfo();
cj.Name = jobId;
cj.Module = module;
cj.LotName = lotId;
cj.LotInnerId = Guid.NewGuid();
cj.LotWafers = new List<WaferInfoRt>();
cj.SetState(EnumControlJobState.WaitingForStart);
var seqSlot = new Dictionary<string, bool[]>();
var seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
var indexSequence = new Dictionary<string, string>();
var enableGroupBySequence = SC.GetValue<bool>("System.Scheduler.GroupWaferBySequence");
var WaferAssociationInfo = $"WaferAssociationInfo({module}):";
for (var i = 0; i < 1; i++)
{
WaferAssociationInfo = WaferAssociationInfo + string.Format(" slot{0} -- {1};", i + 1, slotSequence[i]);
if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
continue;
var groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString();
indexSequence[groupName] = slotSequence[i];
if (!seqSlot.ContainsKey(groupName))
{
seqSlot[groupName] = new bool[25];
}
if (!seqSlotWafers.ContainsKey(groupName))
{
seqSlotWafers[groupName] = new List<Tuple<ModuleName, int>>();
}
seqSlot[groupName][i] = true;
if (!WaferManager.Instance.CheckHasWafer(module, i))
{
reason = $"job wafer: {module} slot {i + 1} not in the carrier";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), i, WaferStatus.Normal))
{
reason = $"job wafer: {module} slot {i + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).WaferStatus}";
EV.PostWarningLog(LogSource, reason);
return false;
}
var wafer = WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i);
if (wafer == null || wafer.IsWaferEmpty)
{
reason = $"specifies wafer: {module} slot {i + 1} not in the carrier";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.ProcessState != WaferProcessStatus.Idle)
{
reason = $"specifies wafer: {module} slot {i + 1} process state is not idle";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.ProcessJob != null)
{
reason = $"specifies wafer: {module} slot {i + 1} ProcessJob is not null";
EV.PostWarningLog(LogSource, reason);
return false;
}
if (wafer.SubstE90Status != EnumE90Status.NeedProcessing)
{
reason = $"specifies wafer: {module} slot {i + 1} SubstE90Status is not NeedProcessing";
EV.PostWarningLog(LogSource, reason);
return false;
}
seqSlotWafers[groupName].Add(Tuple.Create(ModuleHelper.Converter(module), i));
cj.LotWafers.Add(WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i));
WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).PPID = slotSequence[i];
}
//currentSlotSequenceList[module] = slotSequence.Reverse().ToList();
EV.PostInfoLog(LogSource, WaferAssociationInfo);
if (seqSlotWafers.Count == 0)
{
reason = $"Can not create job, no wafer assigned";
EV.PostWarningLog(LogSource, reason);
return false;
}
var pjs = new List<ProcessJobInfo>();
var seqs = seqSlot.Keys.ToArray();
for (var i = 0; i < seqs.Length; i++)
{
var pj = new ProcessJobInfo();
pj.Name = jobId + "_" + (i + 1);
pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]);
pj.ControlJobName = cj.Name;
//pj.LotName = lotId;
pj.SlotWafers = seqSlotWafers[seqs[i]];
pj.SetState(EnumProcessJobState.Queued);
pjs.Add(pj);
}
foreach (var pj in pjs)
{
cj.ProcessJobNameList.Add(pj.Name);
_lstProcessJobs.Add(pj);
}
_lstControlJobs.Add(cj);
var totalWafer = 0;
foreach (var pj in pjs)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
var wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
wafer.ProcessJob = pj;
wafer.NextSequenceStep = 0;
wafer.WaferOrigin = lotId;
wafer.LotId = lotId;
WaferDataRecorder.SetCjInfo(wafer.WaferInnerID.ToString(), cj.InnerId.ToString());
WaferDataRecorder.SetWaferSequence(wafer.WaferInnerID.ToString(), pj.Sequence.Name);
WaferDataRecorder.SetWaferLotId(wafer.WaferInnerID.ToString(), lotId);
WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, lotId);
totalWafer++;
}
}
//CarrierManager.Instance.DeleteCarrier(cj.Module);
//CarrierManager.Instance.CreateCarrier(cj.Module);
//CarrierManager.Instance.UpdateCarrierId(cj.Module, $"{cj.Module} {DateTime.Now}");
//CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
//JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
JobDataRecorder.StartCJ(cj.InnerId.ToString(), null, cj.Name, cj.Module, cj.Module, totalWafer);
//保存信息
var waferInfo = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
if (waferInfo != null)
{
if (waferInfo.ProcessState == WaferProcessStatus.Idle)
{
WaferManager.Instance.GetWafer(_load.Module, 0).NextSequenceStep = 0;
}
waferInfo.LotId = cj.LotName;
if (recipeName.IndexOf(@"\") > 0)
{
recipeName = recipeName.Substring(recipeName.LastIndexOf(@"\") + 1);
}
AutoJobRecorder.Add(waferInfo.WaferID.ToString(), recipeName, cj.LotName, ModuleName.LoadLock.ToString(), GetWaferStatue(waferInfo));
}
return true;
}
private string GetWaferStatue(WaferInfoRt wafer)
{
if (wafer.ProcessState == WaferProcessStatus.InProcess)
{
return "InProcess";
}
else if (wafer.ProcessState == WaferProcessStatus.Completed)
{
return "Completed";
}
else
{
return "Idle";
}
}
private bool ValidateSequence(string[] seqs, out string reason)
{
reason = string.Empty;
//bool isAllSequenceNull = true;
//for (int i = 0; i < seqs.Length; i++)
//{
// if (string.IsNullOrEmpty(seqs[i]))
// continue;
// var sequence = SequenceInfoHelper.GetInfo(seqs[i]);
// if ((sequence == null || sequence.Steps == null || sequence.Steps.Count == 0) && !string.IsNullOrEmpty(sequence.Name))
// {
// reason = $"Invalid sequence {seqs[i]}";
// return false;
// }
// isAllSequenceNull = false;
// if (sequence.Steps != null)
// {
// int currentIndex = 0;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Aligner)
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Aligner";
// return false;
// }
// else
// {
// if (sequence.Steps[currentIndex].AlignAngle < 0 || sequence.Steps[currentIndex].AlignAngle > 360)
// {
// reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Aligner angle parameter is not valid";
// return false;
// }
// }
// currentIndex++;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Load)
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Load";
// return false;
// }
// currentIndex++;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Buffer)
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Buffer";
// return false;
// }
// else
// {
// //if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("SlotSelection")
// // || string.IsNullOrEmpty(sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString())
// // || sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString().Contains("3"))
// //{
// // reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer SlotSelection parameter is not valid";
// // return false;
// //}
// if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("BufferType") || !sequence.Steps[currentIndex].StepParameter["BufferType"].ToString().Contains("Heat"))
// {
// reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer BufferType parameter is not valid";
// return false;
// }
// }
// currentIndex++;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules.Any(pm => !ModuleHelper.IsPm(pm)))
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be PM";
// return false;
// }
// //if (sequence.Steps.Count == 7)
// //{
// // currentIndex++;
// // if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Buffer)
// // {
// // reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Buffer";
// // return false;
// // }
// // else
// // {
// // if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("SlotSelection")
// // || sequence.Steps[currentIndex].StepParameter["SlotSelection"].ToString() != "3")
// // {
// // reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer SlotSelection parameter is not valid";
// // return false;
// // }
// // if (!sequence.Steps[currentIndex].StepParameter.ContainsKey("BufferType") || !sequence.Steps[currentIndex].StepParameter["BufferType"].ToString().Contains("Cooling"))
// // {
// // reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer BufferType parameter is not valid";
// // return false;
// // }
// // }
// //}
// currentIndex++;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.UnLoad)
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Unload";
// return false;
// }
// currentIndex++;
// if (sequence.Steps[currentIndex] == null || sequence.Steps[currentIndex].StepModules.Count <= 0 || sequence.Steps[currentIndex].StepModules[0] != ModuleName.Aligner)
// {
// reason = $"Invalid sequence {seqs[i]}, {currentIndex + 1}st step should be Aligner";
// return false;
// }
// else
// {
// if (sequence.Steps[0].AlignAngle < 0 || sequence.Steps[0].AlignAngle > 360)
// {
// reason = $"Invalid sequence {seqs[i]}, Aligner angle parameter is not valid";
// return false;
// }
// }
// }
//}
//if (isAllSequenceNull)
//{
// reason = $"Invalid sequence, sequence are all null ";
// return false;
//}
return true;
}
public bool CreateControlJob(string jobId, string module, List<string> pjIDs, bool isAutoStart)
{
if (_lstControlJobs.Exists(x => x.Name == jobId))
{
EV.PostWarningLog(LogSource, $"{jobId} is already created");
return false;
}
if (!ModuleHelper.IsCassette(ModuleHelper.Converter(module)))
{
EV.PostWarningLog(LogSource, $"{module} should be Cassete");
return false;
}
if (_lstProcessJobs.Count <= 0) //判断上一步ProcessJob是否创建成功
{
EV.PostWarningLog(LogSource, $"process job is not exist");
return false;
}
var cj = new ControlJobInfo();
cj.Name = jobId;
cj.Module = module;
cj.LotName = jobId;
cj.LotInnerId = Guid.NewGuid();
cj.LotWafers = new List<WaferInfoRt>();
cj.SetState(EnumControlJobState.WaitingForStart);
var totalWafer = 0;
foreach (var pjName in pjIDs)
{
var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
if (pj == null)
{
LOG.Info($"not find {pjName} while create control job");
continue;
}
var slotWafers = new List<Tuple<ModuleName, int>>();
foreach (var slotWafer in pj.SlotWafers)
{
var _module = GetModule(module);
if (!_module.HasWafer(slotWafer.Item2))
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} not in the carrier");
return false;
}
if (!_module.CheckWaferStatus(slotWafer.Item2, WaferStatus.Normal))
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} status is {_module.GetWaferInfo(slotWafer.Item2).WaferStatus}");
return false;
}
if (_module.GetWaferInfo(slotWafer.Item2).ProcessState != WaferProcessStatus.Idle)
{
EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} process status is {_module.GetWaferInfo(slotWafer.Item2).ProcessState}");
return false;
}
slotWafers.Add(Tuple.Create(ModuleHelper.Converter(module), slotWafer.Item2));
totalWafer++;
}
pj.ControlJobName = cj.Name;
cj.ProcessJobNameList.Add(pj.Name);
pj.SlotWafers = slotWafers;
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfoRt wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
cj.LotWafers.Add(wafer);
wafer.ProcessJob = pj;
wafer.ProcessJobID = pj.Sequence.Name;
WaferDataRecorder.SetCjInfo(wafer.WaferInnerID.ToString(), cj.InnerId.ToString());
WaferDataRecorder.SetWaferSequence(wafer.WaferInnerID.ToString(), pj.Sequence.Name);
WaferDataRecorder.SetWaferLotId(wafer.WaferInnerID.ToString(), jobId);
WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, jobId);
}
}
_lstControlJobs.Add(cj);
CarrierManager.Instance.DeleteCarrier(cj.Module);
CarrierManager.Instance.CreateCarrier(cj.Module);
CarrierManager.Instance.UpdateCarrierId(cj.Module, $"{cj.Module} {DateTime.Now}");
var carrier = CarrierManager.Instance.GetCarrier(cj.Module);
JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
return true;
}
public bool CreateProcessJob(string jobId, string sequenceName, List<int> slotNumbers/*0 based*/, bool isAutoStart)
{
var sequenceInfo = SequenceInfoHelper.GetInfo(sequenceName);
//模块顺序检查
var lstLoad = new List<int>();
var lstBuffer = new List<int>();
var lstUnLoad = new List<int>();
var lstPM = new List<int>();
for (var i = 0; i < sequenceInfo.Steps.Count; i++)
{
if (sequenceInfo.Steps[i].StepModules.Count == 0)
{
return false;
}
if (sequenceInfo.Steps[i].StepModules.Any(pm => ModuleHelper.IsPm(pm)))
{
lstPM.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(load => load == ModuleName.Load || load == ModuleName.LoadLock))
{
lstLoad.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(unload => unload == ModuleName.UnLoad))
{
lstUnLoad.Add(i);
}
if (sequenceInfo.Steps[i].StepModules.Any(buff => buff == ModuleName.Buffer))
{
lstBuffer.Add(i);
}
}
if (lstPM.Count <= 0)
{
EV.PostWarningLog(LogSource, $"Sequence must have pm step info!");
return false;
}
if (lstLoad.Count > 1)
{
EV.PostWarningLog(LogSource, $"Sequence can not contain {lstLoad.Count} Load Step!");
return false;
}
if (lstUnLoad.Count > 1)
{
EV.PostWarningLog(LogSource, $"Sequence can not contain {lstUnLoad.Count} UnLoad Step!");
return false;
}
if (lstBuffer.Count > 0)
{
foreach (var bufferId in lstBuffer)
{
if (lstLoad.Count == 1)
{
if (bufferId < lstLoad[0])
{
EV.PostWarningLog(LogSource, $"Sequence Load Step Must Before Buffer Step!");
return false;
}
}
if (lstUnLoad.Count == 1)
{
if (bufferId > lstUnLoad[0])
{
EV.PostWarningLog(LogSource, $"Sequence Buffer Step Must Before UnLoad Step!");
return false;
}
}
}
}
var slotWafers = new List<Tuple<ModuleName, int>>();
foreach (var slot in slotNumbers)
{
slotWafers.Add(Tuple.Create(ModuleName.System, slot));
}
var pj = new ProcessJobInfo();
pj.Name = jobId;
pj.Sequence = sequenceInfo;
pj.SlotWafers = slotWafers;
pj.SetState(EnumProcessJobState.Queued);
_lstProcessJobs.Add(pj);
return true;
}
internal void StopJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"stop job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
pj.SetState(EnumProcessJobState.Stopping);
}
}
if (_cycleSetPoint > 0)
{
_cycleSetPoint = _cycledCount;
}
}
}
public void Abort()
{
var wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, 0);
if (wafer?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer.WaferID.ToString(), ModuleName.PM1.ToString(), "Abort");
}
var wafer1 = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
if (wafer1?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer1.WaferID.ToString(), ModuleName.TM.ToString(), "Abort");
}
var wafer2 = WaferManager.Instance.GetWafer(ModuleName.Buffer, 0);
if (wafer2?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer2.WaferID.ToString(), ModuleName.Buffer.ToString(), "Abort");
}
var wafer3 = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
if (wafer3?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer3.WaferID.ToString(), ModuleName.LoadLock.ToString(), "Abort");
}
}
internal void AbortJob(string jobName)
{
var cj = _lstControlJobs.Find(x => x.Name == jobName);
if (cj == null)
{
EV.PostWarningLog(LogSource, $"abort job rejected, not found job with id {jobName}");
return;
}
var unprocessed_cj = 0;
var aborted_cj = 0;
var pjAbortList = new List<ProcessJobInfo>();
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
pj.SetState(EnumProcessJobState.Aborting);
pjAbortList.Add(pj);
var unprocessed = 0;
var aborted = 0;
var wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
foreach (var waferInfo in wafers)
{
waferInfo.ProcessJob = null;
waferInfo.NextSequenceStep = 0;
if (waferInfo.ProcessState != WaferProcessStatus.Completed)
{
unprocessed++;
unprocessed_cj++;
}
}
JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
}
}
foreach (var pj in pjAbortList)
{
_lstProcessJobs.Remove(pj);
}
_lstControlJobs.Remove(cj);
_dbCallback.LotFinished(cj);
JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
}
public void ResumeJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"resume job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Paused)
{
cj.SetState(EnumControlJobState.Executing);
}
}
}
internal void PauseJob(string jobName)
{
//ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
//if (cj == null)
//{
// EV.PostWarningLog(LogSource, $"pause job rejected, not found job with id {jobName}");
// return;
//}
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
cj.SetState(EnumControlJobState.Paused);
}
}
}
internal bool CheckPMState(string sequence)
{
var seqInfo = SequenceInfoHelper.GetInfo(sequence);
if (seqInfo.Name != "")
{
foreach (var step in seqInfo.Steps)
{
foreach (var moduleName in step.StepModules)
{
if (ModuleHelper.IsPm(moduleName))
{
var module = _lstPms.Find(x => x.Module == moduleName);
if (module != null)
{
if (module.IsError)
{
EV.PostWarningLog("Scheduler", $"{moduleName} is not be error");
return false;
}
if (!module.IsOnline)
{
EV.PostWarningLog("Scheduler", $"{moduleName} is not be Online");
return false;
}
if (!module.IsLineHeaterEnable)
{
EV.PostWarningLog("Scheduler", $"{moduleName} LineHeater is not be Open");
return false;
}
//if (module.IsService)
//{
// EV.PostWarningLog("Scheduler", $"can not start job, {moduleName} is Service Mode");
// return false;
//}
}
else
{
EV.PostWarningLog("Scheduler", "Sequence PM can not be null!");
return false;
}
}
}
}
}
else
{
EV.PostWarningLog("Scheduler", "Sequence can not be null!");
return false;
}
return true;
}
internal void StartJob(string jobName)
{
GetConfig();
var cj = _lstControlJobs.Find(x => x.Name == jobName);
if (cj == null)
{
EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}");
return;
}
//foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.WaitingForStart)
{
cj.BeginTime = DateTime.Now;
cj.LotInnerId = Guid.NewGuid();
//_dbCallback.LotCreated(cj);
cj.SetState(EnumControlJobState.Executing);
}
}
}
#endregion Job Management
/// <summary>
/// Start Auto Transfer
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public Result Start(params object[] objs)
{
GetConfig();
_cycledWafer = 0;
_cycledCount = 0;
//_totalWaferWhenStart = StatsDataManager.Instance.GetValue(StatsNameTotalRunningWafer);
if (!_tmRobot.IsOnline || _tmRobot.IsError)
{
EV.PostWarningLog("Scheduler", "can not change to auto mode, TM robot should be online and no error");
return Result.FAIL;
}
return Result.RUN;
}
public Result Monitor()
{
var cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
if (cjActive != null)
{
MonitorModuleTasks();
MonitorAutoJobStatus();
}
MonitorModuleError();
MonitorModuleState();
MonitorJobTasks();
MonitorCleanTasks();
return Result.RUN;
}
#region Job task
public Result MonitorJobTasks()
{
UpdateProcessJobStatus();
UpdateControlJobStatus();
StartNewJob();
return Result.RUN;
}
/// <summary>
/// 检查PJ中的Wafer信息是否被清空。
/// <para>如果被清空则说明中间过程中Wafer被人工删除此时返回true通知相关Monitor可以改PJ。</para>
/// </summary>
/// <param name="pj"></param>
/// <returns></returns>
protected bool CheckAllWaferDeleted(ProcessJobInfo pj)
{
var wi = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
return wi == null || wi.Length <= 0;
}
protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
{
for (var i = 0; i < pj.SlotWafers.Count; ++i)
{
WaferInfoRt wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
if (wafer.IsWaferEmpty)
return false;
if (checkAllProcessed && CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
return false;
if (wafer.ProcessJob == null || wafer.ProcessJob.InnerId != pj.InnerId)
{
return false;
}
}
return true;
}
private ModuleName GetWaferReturnedCassette(ModuleName moduleFrom)
{
if (CassetteFromAToB)
{
if (moduleFrom == ModuleName.CassAL)
{
return ModuleName.CassAR;
}
else if (moduleFrom == ModuleName.CassAR)
{
return ModuleName.CassAL;
}
}
return moduleFrom;
}
protected bool CheckAllDummyWaferReturned()
{
foreach (var schedulerPm in _lstPms)
{
if (WaferManager.Instance.CheckWaferIsDummy(schedulerPm.Module, 0))
return false;
}
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 0))
return false;
if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 1))
return false;
return true;
}
protected bool CheckAllPmCleaned(ProcessJobInfo pj)
{
foreach (var schedulerPm in _lstPms)
{
if (GetModule(schedulerPm.Module).CheckNeedRunClean(out _, out _))
{
foreach (var sequenceStepInfo in pj.Sequence.Steps)
{
if (sequenceStepInfo.StepModules.Contains(schedulerPm.Module))
return false;
}
}
}
return true;
}
private void UpdateProcessJobStatus()
{
foreach (var pj in _lstProcessJobs)
{
if (pj.State == EnumProcessJobState.Processing)
{
if ((CheckAllWaferDeleted(pj) || CheckAllWaferReturned(pj, true)) // 当前PJ的Wafer信息均被删除或者Wafer全部返回Cass
&& CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned()
&& _load.IsAvailable && _tmRobot.IsAvailable && _buffer.IsAvailable && _tmRobot.NoTray(0))
{
//if (_unload.IsAvailable && _buffer.IsAvailable && _tmRobot.IsAvailable && _load.IsAvailable
// && _waferRobot.IsAvailable && _unload.NoTray(0)
// && _waferRobot.IsAvailable && _tmRobot.NoTray(0)
// && _waferRobot.IsAvailable && _load.NoTray(0))
if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
{
_load.SetJobStatue();
pj.SetState(EnumProcessJobState.ProcessingComplete);
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).WaferID.ToString());
}
}
}
else if (pj.State == EnumProcessJobState.Stopping)
{
if (CheckAllWaferReturned(pj, false) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned()
&& _load.IsAvailable && _tmRobot.IsAvailable && _buffer.IsAvailable && _tmRobot.NoTray(0))
{
//if (_unload.IsAvailable && _buffer.IsAvailable && _tmRobot.IsAvailable && _load.IsAvailable
// && _waferRobot.IsAvailable && _unload.NoTray(0)
// && _waferRobot.IsAvailable && _tmRobot.NoTray(0)
// && _waferRobot.IsAvailable && _load.NoTray(0))
if (CheckWaferSequenceStepDone(ModuleName.LoadLock, 0))
{
_load.SetJobStatue();
pj.SetState(EnumProcessJobState.ProcessingComplete);
JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
AutoJobRecorder.EndJob(WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0).WaferID.ToString());
}
}
}
}
}
private void UpdateControlJobStatus()
{
if (_lstControlJobs.Count == 0)
return;
var allControlJobComplete = true;
var cjRemoveList = new List<ControlJobInfo>();
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
var allPjCompleted = true;
foreach (var pjName in cj.ProcessJobNameList)
{
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
if (pj == null)
{
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
continue;
}
if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
{
allPjCompleted = false;
break;
}
}
if (allPjCompleted)
{
cj.SetState(EnumControlJobState.Completed);
var unprocessed_cj = 0;
var aborted_cj = 0;
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
{
var unprocessed = 0;
var aborted = 0;
var wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
foreach (var waferInfo in wafers)
{
waferInfo.ProcessJob = null;
waferInfo.NextSequenceStep = 0;
if (waferInfo.ProcessState != WaferProcessStatus.Completed)
{
unprocessed++;
unprocessed_cj++;
}
}
JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
}
}
JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
_dbCallback.LotFinished(cj);
}
}
if (cj.State == EnumControlJobState.Completed)
{
cjRemoveList.Add(cj);
}
allControlJobComplete = allControlJobComplete && cj.State == EnumControlJobState.Completed;
}
if (_isCycleMode && _cycledCount < _cycleSetPoint)
{
var countPerCycle = 0;
var countProcessed = 0;
foreach (var pj in _lstProcessJobs)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
countPerCycle++;
WaferInfoRt wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
if (!wafer.IsWaferEmpty && !GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2))
countProcessed++;
}
}
_cycledWafer = _cycledCount * countPerCycle + countProcessed;
//StatsDataManager.Instance.SetValue(StatsNameTotalRunningWafer, _totalWaferWhenStart + _cycledWafer);
if (allControlJobComplete)
{
_cycledCount++;
if (_cycledCount < _cycleSetPoint)
{
foreach (var cj in _lstControlJobs)
{
cj.SetState(EnumControlJobState.Executing);
}
foreach (var pj in _lstProcessJobs)
{
pj.SetState(EnumProcessJobState.Queued);
pj.InnerId = Guid.NewGuid();
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfoRt wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
wafer.ProcessJob = null;
wafer.NextSequenceStep = 0;
wafer.ProcessState = WaferProcessStatus.Idle;
}
}
}
}
}
foreach (var cj in cjRemoveList)
{
var pjRemoveList = new List<ProcessJobInfo>();
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name)
pjRemoveList.Add(pj);
}
foreach (var pj in pjRemoveList)
{
_lstProcessJobs.Remove(pj);
}
_lstControlJobs.Remove(cj);
}
ControlJobInfo cjActived = null;
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
cjActived = cj;
break;
}
}
}
private void StartNewJob()
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pjName in cj.ProcessJobNameList)
{
var pj = _lstProcessJobs.Find(x => x.Name == pjName);
if (pj == null)
{
LOG.Error($"Not find pj named {pjName} in {cj.Name}");
continue;
}
if (pj.State == EnumProcessJobState.Queued)
{
ActiveProcessJob(pj);
}
}
}
}
}
public void MonitorAutoJobStatus()
{
_updateAutoJobLocation.CLK = _tmRobot.IsAvailable;
if (_updateAutoJobLocation.Q)
{
WaferInfoRt wafer = WaferManager.Instance.GetWafer(ModuleName.PM1, 0);
if (wafer?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer.WaferID.ToString(), ModuleName.PM1.ToString(), GetWaferStatue(wafer));
}
WaferInfoRt wafer1 = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
if (wafer1?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer1.WaferID.ToString(), ModuleName.TM.ToString(), GetWaferStatue(wafer1));
}
WaferInfoRt wafer2 = WaferManager.Instance.GetWafer(ModuleName.Buffer, 0);
if (wafer2?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer2.WaferID.ToString(), ModuleName.Buffer.ToString(), GetWaferStatue(wafer2));
}
WaferInfoRt wafer3 = WaferManager.Instance.GetWafer(ModuleName.LoadLock, 0);
if (wafer3?.WaferID != null)
{
AutoJobRecorder.UpdatePosition(wafer3.WaferID.ToString(), ModuleName.LoadLock.ToString(), GetWaferStatue(wafer3));
}
}
}
public bool CheckAllJobDone()
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
return false;
}
if (_lstControlJobs.Count == 0)
{
//EV.PostWarningLog("Scheduler", "ControlJob Finished!");
return true;
}
return false;
}
private bool ActiveProcessJob(ProcessJobInfo pj)
{
//_lstPms.Clear();
//for (int i = 0; i < pj.Sequence.Steps.Count; i++)
//{
// SequenceStepInfo stepInfo = pj.Sequence.Steps[i];
// foreach (var module in stepInfo.StepModules)
// {
// if (ModuleHelper.IsPm(module) && _lstPms.Exists(x => x.Module == module))
// {
// _lstPms.Add(_lstPms.Find(x => x.Module == module));
// }
// }
//}
foreach (var pjSlotWafer in pj.SlotWafers)
{
WaferInfoRt wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
wafer.ProcessJob = pj;
//wafer.NextSequenceStep = 0;
WaferDataRecorder.SetPjInfo(wafer.WaferInnerID.ToString(), pj.InnerId.ToString());
}
var cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName);
var carrier = CarrierManager.Instance.GetCarrier(cj.Module);
JobDataRecorder.StartPJ(pj.InnerId.ToString(), null, cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
pj.SetState(EnumProcessJobState.Processing);
return true;
}
#endregion Job task
#region Module task
public Result MonitorModuleTasks()
{
//Load和UnLoad不能同时抽气
//System.Diagnostics.Debug.Assert(!((_tmRobot.IsInPumping && _load.IsInPumping) || (_tmRobot.IsInPumping && _unload.IsInPumping) || (_unload.IsInPumping && _load.IsInPumping)),$"检测到 _load.IsInPumping :{_load.IsInPumping}, _unload.IsInPumping :{_unload.IsInPumping}, _tmRobot.IsInPumping :{_tmRobot.IsInPumping}");
//if ((_tmRobot.IsInPumping && _load.IsInPumping)
// || (_tmRobot.IsInPumping && _unload.IsInPumping)
// || (_unload.IsInPumping && _load.IsInPumping))
// EV.PostAlarmLog("Schedule", $"检测到 _load.IsInPumping :{_load.IsInPumping}, _unload.IsInPumping :{_unload.IsInPumping}, _tmRobot.IsInPumping :{_tmRobot.IsInPumping}");
MonitorPMTask();
MonitorBufferTask();
MonitorTmRobotTask();
MonitorLoadTask();
return Result.RUN;
}
#region SIC多片机报错
private void MonitorBufferTask()
{
if (!_buffer.IsAvailable)
{
return;
}
for (var i = 0; i < _bufferFloors; i++)
{
var canExcute = _buffer.HasWafer(i) && _buffer.CheckWaferNextStepIsThis(_buffer.Module, i);
if (canExcute)
{
WaferInfoRt bufferWafer = _buffer.GetWaferInfo(i);
if (i == 2 || i == 1)
{
bufferWafer.NextSequenceStep++;
return;
}
var bufferSetValue = 0;
if (!GetWaferSequenceNextValue(ModuleName.Buffer, i, "SetValue", out var strBufferSetValue))
{
continue;
}
if (!Int32.TryParse(strBufferSetValue, out bufferSetValue))
{
continue;
}
if (_bufferWaferInfo.ContainsKey(bufferWafer.WaferInnerID.ToString()))
{
var dtStartTime = _bufferWaferInfo[bufferWafer.WaferInnerID.ToString()];
var pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
if (i == 0)
{
_timeBuffer1 = pastTime > bufferSetValue ? 0 : (bufferSetValue - pastTime);
}
else if (i == 1)
{
_timeBuffer2 = pastTime > bufferSetValue ? 0 : (bufferSetValue - pastTime);
}
else if (i == 2)
{
_timeBuffer3 = pastTime > bufferSetValue ? 0 : (bufferSetValue - pastTime);
}
if (pastTime > bufferSetValue)
{
bufferWafer.NextSequenceStep++;
_bufferWaferInfo.Remove(bufferWafer.WaferInnerID.ToString());
}
}
else
{
_bufferWaferInfo.Add(bufferWafer.WaferInnerID.ToString(), DateTime.Now);
}
return;
}
}
//Place和Pick条件都一样
if (!_buffer.IsReadyForPlace(ModuleName.TMRobot, 0))
{
_buffer.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
}
}
#endregion SIC多片机报错
/// <summary>
/// 检测到LL中的Wafer已完成Job。
/// </summary>
//private readonly R_TRIG _trigLLPjDone = new();
private void MonitorLoadTask()
{
if (!_load.IsAvailable)
{
return;
}
if (_load.FirstDetectWaferArrive(0) || _load.FirstDetectWaferLeave(0))
{
_load.ResetPurged();
//_trigLLPjDone.RST = true;
}
var canExcute = _load.HasWafer(0);
if (canExcute)
{
if (_load.GetWaferInfo(0).ProcessJob != null)
{
if (_load.GetWaferInfo(0).ProcessJob.State != EnumProcessJobState.Processing)
{
return;
}
}
else
{
return;
}
if (!_load.CheckWaferSequenceStepDone(0))
{
if (_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0))
{
if (_load.CheckWaferNeedProcess(0))
{
//添加夹爪动作和边缘对位
_load.TrayHome();
_load.Purge(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
_load.GetWaferInfo(0).NextSequenceStep++;
return;
}
else
{
if (!GetWaferSequenceNextValue(ModuleName.Load, 0, "SetValue", out var strSetValue))
{
return;
}
if (!Int32.TryParse(strSetValue, out var setValue))
{
return;
}
if (_loadWaferInfo.ContainsKey(_load.GetWaferInfo(0).WaferInnerID.ToString()))
{
var dtStartTime = _loadWaferInfo[_load.GetWaferInfo(0).WaferInnerID.ToString()];
var pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
_timeLoad = pastTime > setValue ? 0 : (setValue - pastTime);
if (pastTime > setValue)
{
if (!_load.CheckPurged())
{
_load.Purge(_load.GetWaferPurgeCount(0), _load.GetWaferPumpDelayTime(0));
return;
}
_load.ResetPurged();
_load.Vent();
_load.GetWaferInfo(0).NextSequenceStep++;
_loadWaferInfo.Remove(_load.GetWaferInfo(0).WaferInnerID.ToString());
return;
}
}
else
{
_loadWaferInfo.Add(_load.GetWaferInfo(0).WaferInnerID.ToString(), DateTime.Now);
return;
}
}
}
else if (!_load.IsReadyForPick(ModuleName.TMRobot, 0) && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
return;
}
}
/*else
{
// Job Done, 响蜂鸣器
_trigLLPjDone.CLK = true;
if (_trigLLPjDone.Q)
{
OP.DoOperation("System.AlertJobDone", ModuleName.LoadLock.ToString(), 0);
}
}*/
}
else
{
if (_load.NoTray(0))
{
if (!_load.IsReadyForPlace(ModuleName.TMRobot, 0) && !_tmRobot.IsInPumping)
{
_load.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
return;
}
}
}
}
private void MonitorPMTask()
{
//if (_pm1.FirstDetectTrayArrive(0))
//{
// _pm1.GetWaferInfo(0).TrayUsedForWhichPM = (int)_pm1.Module;
//}
//if (_pm2.FirstDetectTrayArrive(1))
//{
// _pm2.GetWaferInfo(0).TrayUsedForWhichPM = (int)_pm2.Module;
//}
foreach (var pm in _lstPms)
{
if (!pm.IsAvailable)
continue;
if (pm.HasWafer(0))
{
if (pm.CheckNeedRunClean(out var withWafer, out var recipe) && withWafer
&& GetModule(pm.Module).GetWaferInfo(0).WaferStatus == WaferStatus.Dummy
&& GetModule(pm.Module).GetWaferInfo(0).ProcessState == WaferProcessStatus.Wait)
{
pm.Process(recipe, true, withWafer);
continue;
}
if (GetModule(pm.Module).CheckWaferNeedProcess(0, pm.Module))
{
WaferInfoRt wafer = GetModule(pm.Module).GetWaferInfo(0);
if (pm.Process(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].RecipeName, false, true))
{
GetModule(pm.Module).GetWaferInfo(0).NextSequenceStep++;
continue;
}
}
else
{
if (!pm.IsReadyForPick(ModuleName.TMRobot, 0))
{
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
}
}
}
else
{
if (GetModule(pm.Module).CheckNeedRunClean(out var withWafer, out var recipe) && !withWafer)
{
pm.Process(recipe, true, withWafer);
continue;
}
if (!pm.IsReadyForPlace(ModuleName.TMRobot, 0))
{
pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, 0);
}
}
}
}
#region TmRobotTask
private void MonitorTmRobotLoadPlaceTask()
{
if (!_load.IsAvailable || !_tmRobot.IsAvailable)
{
return;
}
//place Robot有Tray有Wafer,Load无Tray,无Wafer
var canPlace = _tmRobot.HasTray(0) && _load.NoTray(0) && _load.NoWafer(0)
&& !_load.CheckTrayPlaced();
if (canPlace)
{
if (!_tmRobot.CheckWaferNeedProcess(0) || _tmRobot.CheckWaferSequenceStepDone(0) || _load.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0))
{
if (_load.IsReadyForPlace(ModuleName.TMRobot, 0))
{
if (_tmRobot.Place(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TMRobot, false, 0);
return;
}
}
}
}
}
private void MonitorTmRobotLoadPickTask()
{
if (!_load.IsAvailable || !_tmRobot.IsAvailable)
{
return;
}
//pick TM无Tray,需要Process
var canPick = _tmRobot.NoTray(0) && _tmRobot.NoWafer(0)
&& _load.HasTray(0) && _load.HasWafer(0)
&& _load.CheckWaferNeedProcess(0)
&& !_load.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0)
&& _load.CheckWaferNextStepModuleNoTray(0);
if (canPick)
{
//下一步如果去PM1判断PM1是否准备好
if (_pm1.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0))
{
if (!_pm1.IsAvailable || _pm1.HasTray(0) || _pm1.HasWafer(0) || !_pm1.IsReadyForPlace(ModuleName.TMRobot, 0))
{
return;
}
if (!_pm1.CheckBufferToPMTemp())
{
return;
}
}
//下一步如果去PM2判断PM2是否准备好
if (_pm2.CheckWaferNextStepIsThis(ModuleName.LoadLock, 0))
{
if (!_pm2.IsAvailable || _pm2.HasTray(0) || _pm2.HasWafer(0) || !_pm2.IsReadyForPlace(ModuleName.TMRobot, 0))
{
return;
}
if (!_pm2.CheckBufferToPMTemp())
{
return;
}
}
if (_load.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(_load.Module, 0, Hand.Blade1))
{
_load.WaitTransfer(ModuleName.TMRobot, true, 0);
return;
}
}
}
}
private void MonitorTmRobotBufferPlaceTask()
{
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
{
return;
}
//place Buffer位置没有Tray,Robot有Wafer,下一步骤是Buffer
var canPalce = _tmRobot.HasTray(0);
if (canPalce)
{
SlotItem bufferEmptySlot = null;
if (_tmRobot.CheckWaferNeedProcess(0)
&& _buffer.NoTray(0)
&& _buffer.NoWafer(0)
&& _buffer.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0))
{
bufferEmptySlot = new SlotItem(ModuleName.Buffer, 0);
}
//TMRobot的下一步是Buffer3
else if (!_tmRobot.CheckWaferNeedProcess(0)
&& _buffer.NoTray(0)
&& _buffer.NoWafer(0)
&& _buffer.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0))
{
bufferEmptySlot = new SlotItem(ModuleName.Buffer, 0);
}
//Load里有Tray
else if (!_tmRobot.CheckWaferNeedProcess(0)
&& _buffer.NoTray(0)
&& _buffer.NoWafer(0)
&& _load.HasTray(0))
{
bufferEmptySlot = new SlotItem(ModuleName.Buffer, 0);
}
if (bufferEmptySlot == null)
{
return;
}
if (_buffer.IsReadyForPlace(ModuleName.TMRobot, bufferEmptySlot.Slot))
{
if (_tmRobot.Place(_buffer.Module, bufferEmptySlot.Slot, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
return;
}
}
private void MonitorTmRobotTask()
{
// TMRobot Idle或者Error时清除被传盘对象的等待状态
if (_tmRobot.CheckTaskDone())
{
foreach (var pm in _lstPms.Where(
pm => pm.IsWaitTransfer(ModuleName.TMRobot) && _tmRobot.CheckTaskDone()))
{
pm.StopWaitTransfer(ModuleName.TMRobot);
}
if (_buffer.IsWaitTransfer(ModuleName.TMRobot) && _tmRobot.CheckTaskDone())
_buffer.StopWaitTransfer(ModuleName.TMRobot);
if (_load.IsWaitTransfer(ModuleName.TMRobot) && _tmRobot.CheckTaskDone())
_load.StopWaitTransfer(ModuleName.TMRobot);
//if (_unload.IsWaitTransfer(ModuleName.TMRobot))
// _unload.StopWaitTransfer(ModuleName.TMRobot);
}
if (!_tmRobot.IsAvailable)
{
return;
}
if (!_tmRobot.IsAvailable)
return;
var act = tmRobotActions.Peek();
act.Invoke();
tmRobotActions.Enqueue(tmRobotActions.Dequeue());
}
private void MonitorTmRobotBufferPickTask()
{
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
{
return;
}
//pick,Buffer有Tray,机械手没有Tray
MonitorTmRobotBuffer1PickTask();
MonitorTmRobotBuffer2PickTask();
MonitorTmRobotBuffer3PickTask();
}
private void MonitorTmRobotBuffer3PickTask()
{
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
{
return;
}
//pick,Buffer有Tray,机械手没有Tray
var canPick = _tmRobot.NoTray(0);
if (canPick)
{
if (_buffer.HasTray(0) && _buffer.HasWafer(0))
{
if (_buffer.CheckWaferNextStepIsThis(ModuleName.Buffer, 0))
{
return;
}
//下一步如果去PM1判断PM1是否准备好
if (_pm1.CheckWaferNextStepIsThis(ModuleName.Buffer, 0))
{
if (!_pm1.IsAvailable || _pm1.HasTray(0) || _pm1.HasWafer(0) || !_pm1.IsReadyForPlace(ModuleName.TMRobot, 0))
{
return;
}
if (!_pm1.CheckBufferToPMTemp())
{
return;
}
}
if (_buffer.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(_buffer.Module, 0, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
private void MonitorTmRobotBuffer2PickTask()
{
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
{
return;
}
//pick,Buffer有Tray,机械手没有Tray
var canPick = _tmRobot.NoTray(0);
if (canPick)
{
if (_buffer.HasTray(0) && _buffer.HasWafer(0))
{
if (_buffer.CheckWaferNextStepIsThis(ModuleName.Buffer, 0))
{
return;
}
//下一步如果去PM2判断PM2是否准备好
if (_pm2.CheckWaferNextStepIsThis(ModuleName.Buffer, 0))
{
if (!_pm2.IsAvailable || _pm2.HasTray(0) || _pm2.HasWafer(0) || !_pm2.IsReadyForPlace(ModuleName.TMRobot, 0))
{
return;
}
if (!_pm2.CheckBufferToPMTemp())
{
return;
}
}
if (_buffer.CheckWaferNextStepModuleNoTray(0))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(_buffer.Module, 0, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
}
private void MonitorTmRobotBuffer1PickTask()
{
if (!_tmRobot.IsAvailable || !_buffer.IsAvailable)
{
return;
}
var canPick = _tmRobot.NoTray(0) && _tmRobot.NoWafer(0);
if (canPick)
{
if (_buffer.HasTray(0)
&& _load.NoTray(0) && _load.NoWafer(0)
&& !_buffer.CheckWaferNextStepIsThis(ModuleName.Buffer, 0)
&& _load.IsReadyForPlace(ModuleName.TMRobot, 0)
&& _load.IsAvailable
&& _load.IsOnline)
{
if (!_buffer.CheckWaferNeedProcess(0))
{
if (_buffer.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(_buffer.Module, 0, Hand.Blade1))
{
_buffer.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
}
private void MonitorTmRobotPMPlaceTask()
{
if (!_tmRobot.IsAvailable)
return;
//place to pm
var blade0HasWaferAndNeedProcess = _tmRobot.HasWafer(0) && _tmRobot.HasTray(0) && _tmRobot.CheckWaferNeedProcess(0);
if (blade0HasWaferAndNeedProcess)
{
foreach (var pm in _lstPms)
{
if (!pm.IsAvailable
|| !GetModule(pm.Module).NoWafer(0)
|| !GetModule(pm.Module).NoTray(0)
|| !pm.IsReadyForPlace(ModuleName.TMRobot, 0))
continue;
var blade0Place = _tmRobot.HasWafer(0) && _tmRobot.CheckWaferNeedProcess(0, pm.Module) &&
pm.CheckWaferNextStepIsThis(ModuleName.TMRobot, 0);
if (blade0Place)
{
if (!pm.CheckBufferToPMTemp())
{
continue;
}
if (_tmRobot.Place(pm.Module, 0, Hand.Blade1))
{
pm.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
private void MonitorTmRobotPMPickTask()
{
if (!_tmRobot.IsAvailable)
return;
//TMRobot从PM取Wafer,Buffer1中不能有Tray,否则先去Buffer1中的Tray
if (_tmRobot.NoWafer(0) && _tmRobot.NoTray(0))
{
var pickBlade = Hand.Blade1;
var pickPm = ModuleName.System;
foreach (var schedulerPm in _lstPms)
{
//增加温度低于900才能Pick的限制
if (!schedulerPm.IsAvailable
|| GetModule(schedulerPm.Module).NoTray(0)
|| GetModule(schedulerPm.Module).CheckWaferNeedProcess(0, schedulerPm.Module)
|| _tmRobot.HasWafer((int)pickBlade)
|| _tmRobot.HasTray((int)pickBlade))
continue;
if (!schedulerPm.CheckPMToTMRobotTemp())
{
continue;
}
//如果下一步是Buffer,只能取出放Buffer1
if (_buffer.CheckWaferNextStepIsThis(schedulerPm.Module, 0))
{
if (_buffer.NoTray(0) && _buffer.NoWafer(0))
{
pickPm = schedulerPm.Module;
break;
}
}
else if ((_buffer.NoTray(0) && _buffer.NoWafer(0))
|| (_load.NoTray(0) && _load.NoWafer(0)))
{
pickPm = schedulerPm.Module;
break;
}
}
if (pickPm != ModuleName.System)
{
var pm = GetModule(pickPm.ToString());
if (pm.IsReadyForPick(ModuleName.TMRobot, 0))
{
if (_tmRobot.Pick(pm.Module, 0, pickBlade))
{
pm.WaitTransfer(ModuleName.TMRobot);
return;
}
}
}
}
}
#endregion TmRobotTask
#endregion Module task
#region Logic Check
/// <summary>
/// 获得Buffer的方式和数值
/// </summary>
/// <param name="module"></param>
/// <param name="slot"></param>
/// <param name="coolingType"></param>
/// <param name="setValue"></param>
/// <returns></returns>
private bool GetWaferSequenceNextValue(ModuleName module, int slot, string nodeName, out string nodeValue)
{
nodeValue = "";
if (!GetModule(module).HasWafer(slot))
return false;
WaferInfoRt wafer = GetModule(module).GetWaferInfo(slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
return false;
nodeValue = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[nodeName].ToString();
if (String.IsNullOrEmpty(nodeValue))
{
return false;
}
return true;
}
private bool GetWaferSequenceCurrentValue(ModuleName module, int slot, string nodeName, out string nodeValue)
{
nodeValue = "";
if (!GetModule(module).HasWafer(slot))
return false;
WaferInfoRt wafer = GetModule(module).GetWaferInfo(slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepModules.Contains(module))
return false;
nodeValue = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep - 1].StepParameter[nodeName].ToString();
if (String.IsNullOrEmpty(nodeValue))
{
return false;
}
return true;
}
private bool GetWaferSequenceCoolingTime(ModuleName module, int slot, out int coolingTime)
{
coolingTime = 0;
if (!WaferManager.Instance.CheckHasWafer(module, slot))
return false;
WaferInfoRt wafer = WaferManager.Instance.GetWafer(module, slot);
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
return false;
if (!int.TryParse(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"].ToString(),
out coolingTime))
{
coolingTime = 0;
//coolingTime = SC.GetValue<int>("Unload.DefaultCoolingTime");
//EV.PostWarningLog("Scheduler", $"Sequence step Unload cooling time is not valid, instead with the SC default value {coolingTime} seconds");
return false;
}
return true;
}
private bool CheckHasTrayAndNoWafer(List<Tuple<ModuleName, int>> needCheckPositions)
{
foreach (var positionTuple in needCheckPositions)
{
var module = GetModule(positionTuple.Item1);
if (module.HasTray(positionTuple.Item2) && module.NoWafer(positionTuple.Item2))
{
return true;
}
}
return false;
}
private bool CheckTrayExhausted()
{
return !(_buffer.HasTrayAndNotExceedProcessCount(0)
| _buffer.HasTrayAndNotExceedProcessCount(1)
| _buffer.HasTrayAndNotExceedProcessCount(2)
| _cassetteBL.HasTrayAndNotExceedProcessCount(0)
| _cassetteBL.HasTrayAndNotExceedProcessCount(1)
| _cassetteBL.HasTrayAndNotExceedProcessCount(2)
| _cassetteBL.HasTrayAndNotExceedProcessCount(3)
| _cassetteBL.HasTrayAndNotExceedProcessCount(4)
| _cassetteBL.HasTrayAndNotExceedProcessCount(5)
| _cassetteBL.HasTrayAndNotExceedProcessCount(6)
| _cassetteBL.HasTrayAndNotExceedProcessCount(7)
| _load.HasTrayAndNotExceedProcessCount(0)
| _unload.HasTrayAndNotExceedProcessCount(0)
| _tmRobot.HasTrayAndNotExceedProcessCount(0)
| _trayRobot.HasTrayAndNotExceedProcessCount(0)
| _pm1.HasTrayAndNotExceedProcessCount(0)
| _pm2.HasTrayAndNotExceedProcessCount(0));
}
public bool CheckBufferWaferHasJob()
{
WaferInfoRt wafer = _buffer.GetWaferInfo(0);
if (wafer.IsWaferEmpty)
{
return false;
}
if (wafer.ProcessJob == null)
{
return false;
}
var pj = _lstProcessJobs.Find(x => x.InnerId == wafer.ProcessJob.InnerId);
if (pj == null)
{
return false;
}
return true;
}
public bool CheckWaferProcessModuleIsAvailable(ModuleName waferModule, int waferSlot)
{
var wafer = GetModule(waferModule).GetWaferInfo(waferSlot);
if (wafer.IsWaferEmpty)
return false;
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
return false;
//foreach (var module in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
//{
//if (GetModule(module).NoWafer(0)
// && _lstPms.Find(x => x.Module == module).IsAvailable
// && !CheckNeedRunClean(module, out bool _, out string _))
// return true;
//}
foreach (var step in wafer.ProcessJob.Sequence.Steps)
{
foreach (var module in step.StepModules)
{
if (module.ToString().StartsWith("PM")
&& GetModule(module).NoWafer(0)
&& _lstPms.Find(x => x.Module == module).IsAvailable
&& !GetModule(module).CheckNeedRunClean(out var _, out var _))
return true;
}
}
return false;
}
public bool CheckWaferSequenceStepDone(ModuleName waferModule, int waferSlot)
{
var wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
if (wafer.IsWaferEmpty)
{
return false;
}
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
{
return false;
}
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count && wafer.ProcessJob.Sequence.Steps.Count > 0)
{
return true;
}
return false;
}
private SlotItem GetWaferInJobQueue()
{
var processingWafers = new List<Tuple<ModuleName, int>>();
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
{
foreach (var pjSlotWafer in pj.SlotWafers)
{
if (pjSlotWafer.Item1 == ModuleName.CassAL || pjSlotWafer.Item1 == ModuleName.CassAR)
{
processingWafers.Add(pjSlotWafer);
}
}
}
}
}
}
if (processingWafers.Count > 0)
{
processingWafers = processingWafers.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList();
if (SC.GetValue<bool>("System.Scheduler.IsRunInParallelMode"))
{
return SortByParallelMode(processingWafers);
}
else
{
return SortBySerialMode(processingWafers);
}
}
return null;
}
private SlotItem SortBySerialMode(List<Tuple<ModuleName, int>> processingWafers)
{
foreach (var pjSlotWafer in processingWafers)
{
if (pjSlotWafer.Item1 == ModuleName.CassAL || pjSlotWafer.Item1 == ModuleName.CassAR)
{
if (GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2, _pm1.Module))
{
if (GetRunWaferCount(_pm1.Module) < 2)
{
return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
}
else
{
return null;
}
}
else if (GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2, _pm2.Module))
{
if (GetRunWaferCount(_pm2.Module) < 2)
{
return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
}
else
{
return null;
}
}
}
}
return null;
}
private SlotItem SortByParallelMode(List<Tuple<ModuleName, int>> processingWafers)
{
foreach (var pjSlotWafer in processingWafers)
{
if (pjSlotWafer.Item1 == ModuleName.CassAL || pjSlotWafer.Item1 == ModuleName.CassAR)
{
if (GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2, _pm1.Module))
{
if (GetRunWaferCount(_pm1.Module) < 2 && GetRunWaferCount(_pm1.Module) <= GetRunWaferCount(_pm2.Module))
{
return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
}
}
else if (GetModule(pjSlotWafer.Item1).CheckWaferNeedProcess(pjSlotWafer.Item2, _pm2.Module))
{
if (GetRunWaferCount(_pm2.Module) < 2 && GetRunWaferCount(_pm2.Module) <= GetRunWaferCount(_pm1.Module))
{
return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
}
}
}
}
return SortBySerialMode(processingWafers);
}
private SlotItem GetTraySlot(int slotCount, int usedForWhichPM)
{
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
for (var i = 0; i < slotCount; i++)
{
if (_cassetteBL.HasTrayAndNotExceedProcessCount(i) && _cassetteBL.GetWaferInfo(i).TrayUsedForWhichPM == usedForWhichPM)
{
return new SlotItem(ModuleName.CassBL, i);
}
}
}
}
return null;
}
private SlotItem GetTrayOrignSlot(ModuleName module, int slot)
{
WaferInfoRt wafer = GetModule(module).GetWaferInfo(slot);
if (wafer != null && GetModule(module).HasTray(slot) && _cassetteBL.NoTray(wafer.TrayOriginSlot))
{
return new SlotItem(ModuleName.CassBL, wafer.TrayOriginSlot);
}
return null;
}
//private SlotItem GetEmptyTraySlot(int slotCount)
//{
// foreach (var cj in _lstControlJobs)
// {
// if (cj.State == EnumControlJobState.Executing)
// {
// for (int i = 0; i < slotCount; i++)
// {
//if (_cassetteBL.NoTray(i))
// {
// return new SlotItem(ModuleName.CassBL, i);
// }
// }
// }
// }
// return null;
//}
///// <summary>
///// 获取空位置
///// </summary>
///// <param name="isHeat"></param>
///// <returns></returns>
//private SlotItem GetEmptyBufferSlot(WaferInfoRt wafer)
//{
// foreach (var cj in _lstControlJobs)
// {
// if (cj.State == EnumControlJobState.Executing)
// {
// string strSots = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["SlotSelection"].ToString();
// if (strSots == null)
// {
// return null;
// }
// string[] slots = strSots.Split(',');
// for (int i = 0; i < slots.Length; i++)
// {
// int slot = 0;
// if (Int32.TryParse(slots[i], out slot))
// {
// if (_buffer.NoTray(slot - 1))
// {
// return new SlotItem(ModuleName.Buffer, slot - 1);
// }
// }
// }
// }
// }
// return null;
//}
/// <summary>
/// 获取各个模块的Wafer总数量
/// </summary>
/// <returns></returns>
private int GetRunWaferCount()
{
var waferCount = 0;
if (_load.HasWafer(0))
{
waferCount++;
}
if (_unload.HasWafer(0))
{
waferCount++;
}
if (_tmRobot.HasWafer(0))
{
waferCount++;
}
foreach (var pm in _lstPms)
{
if (GetModule(pm.Module).HasWafer(0))
{
waferCount++;
}
}
for (var i = 0; i < _bufferFloors; i++)
{
if (_buffer.HasWafer(i))
{
waferCount++;
}
}
return waferCount;
}
private int GetRunWaferCount(ModuleName processIn)
{
var waferCount = 0;
if (_tmRobot.HasWafer(0) && (_tmRobot.CheckWaferNeedProcess(0, processIn) || _tmRobot.GetWaferInfo(0).SubstHists.Select(x => x.locationID).Contains(processIn.ToString())))
{
waferCount++;
}
if (GetModule(processIn).HasWafer(0) && (GetModule(processIn).CheckWaferNeedProcess(0, processIn) || GetModule(processIn).GetWaferInfo(0).SubstHists.Select(x => x.locationID).Contains(processIn.ToString())))
{
waferCount++;
}
for (var i = 0; i < _bufferFloors; i++)
{
if (_buffer.HasWafer(i) && (_buffer.CheckWaferNeedProcess(i, processIn) || _buffer.GetWaferInfo(i).SubstHists.Select(x => x.locationID).Contains(processIn.ToString())))
{
waferCount++;
}
}
return waferCount;
}
/// <summary>
/// 获取各个模块的石墨盘总数量
/// </summary>
/// <returns></returns>
private int GetCurrentTrayCount()
{
var trayCount = 0;
if (_tmRobot.HasTray(0))
{
trayCount++;
}
foreach (var pm in _lstPms)
{
if (GetModule(pm.Module).HasTray(0))
{
trayCount++;
}
}
for (var i = 0; i < _bufferFloors; i++)
{
if (_buffer.HasTray(i))
{
trayCount++;
}
}
return trayCount;
}
/// <summary>
/// 获取ProcessJob可以同时运行工艺的Wafer总数
/// </summary>
/// <returns></returns>
private int GetCurrentWaferCount()
{
var waferCountDiv = 0;
var cassWaferCount = 0;
foreach (var cj in _lstControlJobs)
{
if (cj.State == EnumControlJobState.Executing)
{
foreach (var pj in _lstProcessJobs)
{
if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
{
cassWaferCount += pj.SlotWafers.Count;
foreach (var pjSlotWafer in pj.SlotWafers)
{
var module = GetModule(pjSlotWafer.Item1);
if (module.HasWafer(pjSlotWafer.Item2) && !module.CheckWaferNeedProcess(pjSlotWafer.Item2))
{
waferCountDiv++;
}
}
}
}
}
}
return cassWaferCount - waferCountDiv;
//int waferCount = 0;
//if (_load.HasWafer(0))
//{
// waferCount++;
//}
//for (int i = 0; i < 3; i++)
//{
//if (_buffer.HasWafer(i))
// {
// waferCount++;
// }
//}
//if (_waferRobot.CheckWaferNeedProcess(0) )
//{
// waferCount++;
//}
//if (_aligner.CheckWaferNeedProcess(0) )
//{
// waferCount++;
//}
//for (int i=0;i<25;i++)
//{
// if (CheckWaferNeedProcess(ModuleName.CassAL, i))
// {
// waferCount++;
// }
// if (CheckWaferNeedProcess(ModuleName.CassAR, i))
// {
// waferCount++;
// }
//}
//return waferCount;
}
#endregion Logic Check
#region Module error
public Result MonitorModuleError()
{
var isModuleError = false;
var isPMError = new bool[2];
for (var i = 0; i < isPMError.Length; i++)
{
isPMError[i] = false;
}
if (_tmRobot.IsError)
isModuleError = true;
for (var i = 0; i < _lstPms.Count; i++) // PM出错不影响其他腔体的传片
{
if (_lstPms[i].IsError)
isPMError[i] = true;
}
if (isModuleError && !_isModuleErrorPrevious)
{
}
else if (!isModuleError && _isModuleErrorPrevious)
{
Reset();
}
for (var i = 0; i < _lstPms.Count; i++)
{
if (!isPMError[i] && _isPMErrorPrevious[i])
{
_lstPms[i].ResetTask();
}
_isPMErrorPrevious[i] = isPMError[i];
}
_isModuleErrorPrevious = isModuleError;
return Result.RUN;
}
public Result MonitorModuleState()
{
var controlJobExecuting = false;
var isModuleBusy = false;
foreach (var controlJob in _lstControlJobs)
{
if (controlJob.State == EnumControlJobState.Executing)
controlJobExecuting = true;
}
//if (!controlJobExecuting)
// return Result.RUN;
//if (_tmRobot.IsOnline && _tmRobot.Entity.IsBusy)
// isModuleBusy = true;
//if (_efemRobot.IsOnline && _efemRobot.Entity.IsBusy)
// isModuleBusy = true;
//foreach (var pm in _lstPms) // PM出错不影响其他腔体的传片
//{
// if (pm.IsOnline && pm.Entity.IsBusy)
// isModuleBusy = true;
//}
//foreach (var ll in _lstLls)
//{
// if (ll.IsOnline && ll.Entity.IsBusy)
// isModuleBusy = true;
//}
//foreach (var lp in _lstLps)
//{
// if (lp.IsOnline && lp.Entity.IsBusy)
// isModuleBusy = true;
//}
//if (_aligner.IsOnline && _aligner.Entity.IsBusy)
// isModuleBusy = true;
//if (isModuleBusy)
//{
// _timer.Stop();
// _started = false;
//}
//else
//{
// if (!_started)
// {
// _timer.Start(_deadLockTimeout * 1000);
// _started = true;
// }
//}
//_trigDeadLock.CLK = _timer.IsTimeout();
//if (_trigDeadLock.Q)
//{
// EV.PostWarningLog("System", "A deadlock has occurred");
//}
return Result.RUN;
}
public Result MonitorCleanTasks()
{
//if (!_isInited)
//{
// _isInited = true;
// InitClean();
//}
//foreach (var pm in _lstPms)
//{
// pm.MonitorCleanTasks();
//}
return Result.RUN;
}
private bool CheckModuleHaveWaferWithNoJob(out string reason)
{
reason = "";
if (_lstControlJobs.Count > 0)
{
reason = "lstControlJobs.Count > 0";
return false;
}
else
{
//if (_buffer.HasWafer(0) || _buffer.HasWafer(1) || _buffer.HasWafer(2))
if (_buffer.HasWafer(0))
{
reason = $"Buffer have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (_tmRobot.HasWafer(0))
{
reason = $"TmRobot have wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (!_load.HasWafer(0))
{
reason = $"Load have no wafer!";
EV.PostWarningLog(LogSource, reason);
return true;
}
if (!_load.HasTray(0))
{
reason = $"Load have no Tray!";
EV.PostWarningLog(LogSource, reason);
return true;
}
return false;
}
}
private bool CheckWaferNeedProcess(ModuleName module, int waferSlot, ModuleName processIn = ModuleName.System)
{
WaferInfoRt wafer = WaferManager.Instance.GetWafer(module, waferSlot);
if (wafer.IsWaferEmpty)
return false;
if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null)
return false;
if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
return false;
//if (processIn != ModuleName.System && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(processIn))
// return false;
var hasPm = false;
for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
{
foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
{
if (ModuleHelper.IsPm(stepModule))
{
hasPm = true;
break;
}
}
if (hasPm)
break;
}
if (processIn == ModuleName.System && !hasPm)
return false;
return true;
}
#endregion Module error
}
}