|
@@ -27,6 +27,7 @@ using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
|
|
|
using Venus_RT.Modules.TM.VenusEntity;
|
|
|
using System.Threading.Tasks;
|
|
|
using Venus_RT.Modules.VCE;
|
|
|
+using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
|
|
|
|
|
|
namespace Venus_RT.Modules
|
|
|
{
|
|
@@ -42,10 +43,12 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
enum CleanType
|
|
|
{
|
|
|
+ LongIdleClean,
|
|
|
IdleClean,
|
|
|
PreJobClean,
|
|
|
PostJobClean,
|
|
|
WTWClean,
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public override int TimeToReady
|
|
@@ -84,9 +87,11 @@ namespace Venus_RT.Modules
|
|
|
private WaferTask _wafer;
|
|
|
private SchedulerPM _pmScheduler => Scheduler as SchedulerPM;
|
|
|
|
|
|
+ private string _longIdleCleanRecipe;
|
|
|
private string _preJobCleanRecipe;
|
|
|
private string _postJobCleanRecipe;
|
|
|
private string _wtwCleanRecipe;
|
|
|
+ private DateTime _lstProcessTime;
|
|
|
private Queue<CleanType> _pendingCleanTask = new Queue<CleanType>();
|
|
|
|
|
|
public VenusPMTask(ModuleName pm) : base(pm)
|
|
@@ -114,6 +119,10 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
Status = ModuleStatus.WaitPreJobClean;
|
|
|
}
|
|
|
+ else if (cleanTask == CleanType.LongIdleClean && !string.IsNullOrWhiteSpace(_longIdleCleanRecipe))
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.WaitLongIdleClean;
|
|
|
+ }
|
|
|
}
|
|
|
else if (_pmScheduler.RunIdleCleanTask()) // Check Idle Clean
|
|
|
{
|
|
@@ -180,6 +189,23 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
+ case ModuleStatus.WaitLongIdleClean:
|
|
|
+ {
|
|
|
+ if (WaferManager.Instance.CheckNoWafer(Module, 0))
|
|
|
+ {
|
|
|
+ if (_pmScheduler.RunJobCleanTask(_longIdleCleanRecipe))
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.StartLongIdleClean;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LOG.Write(eEvent.WARN_ROUTER, Module, $"Run LongTime clean recipe{_longIdleCleanRecipe} failed");
|
|
|
+ Status = ModuleStatus.Idle;
|
|
|
+ _longIdleCleanRecipe = string.Empty;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
case ModuleStatus.Processing:
|
|
|
{
|
|
|
var wafer = WaferManager.Instance.GetWafer(Module, 0);
|
|
@@ -197,6 +223,12 @@ namespace Venus_RT.Modules
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
+ case ModuleStatus.LongIdleClean:
|
|
|
+ {
|
|
|
+ _longIdleCleanRecipe = string.Empty;
|
|
|
+ Status = ModuleStatus.Idle;
|
|
|
+ }
|
|
|
+ break;
|
|
|
case ModuleStatus.PreJobClean:
|
|
|
{
|
|
|
_preJobCleanRecipe = string.Empty;
|
|
@@ -266,6 +298,9 @@ namespace Venus_RT.Modules
|
|
|
case ModuleStatus.StartIdleClean:
|
|
|
Status = ModuleStatus.IdleClean;
|
|
|
break;
|
|
|
+ case ModuleStatus.StartLongIdleClean:
|
|
|
+ Status = ModuleStatus.LongIdleClean;
|
|
|
+ break;
|
|
|
case ModuleStatus.StartPreJobClean:
|
|
|
Status = ModuleStatus.PreJobClean;
|
|
|
break;
|
|
@@ -305,6 +340,10 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
Status = ModuleStatus.WaitPreJobClean;
|
|
|
}
|
|
|
+ else if (cleanTask == CleanType.LongIdleClean && !string.IsNullOrWhiteSpace(_longIdleCleanRecipe))
|
|
|
+ {
|
|
|
+ Status = ModuleStatus.WaitLongIdleClean;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
_wafer = null;
|
|
@@ -333,6 +372,12 @@ namespace Venus_RT.Modules
|
|
|
{
|
|
|
return !_pendingCleanTask.Contains(CleanType.PostJobClean) && string.IsNullOrWhiteSpace(_postJobCleanRecipe);
|
|
|
}
|
|
|
+
|
|
|
+ public void InvokeLongIdleClean(string longIdleJobClean)
|
|
|
+ {
|
|
|
+ _longIdleCleanRecipe = longIdleJobClean;
|
|
|
+ _pendingCleanTask.Enqueue(CleanType.LongIdleClean);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//class VenusPMTask : ModuleTask
|
|
@@ -777,6 +822,9 @@ namespace Venus_RT.Modules
|
|
|
private Dictionary<ModuleName, List<Guid>> _preLotCleanMarks = new Dictionary<ModuleName, List<Guid>>();
|
|
|
private Dictionary<ModuleName, List<Guid>> _postLotCleanMarks = new Dictionary<ModuleName, List<Guid>>();
|
|
|
|
|
|
+ // process => int => pm 0.PMA 1.PMB 2.PMC 3.PMD
|
|
|
+ private Dictionary<string, Dictionary<ModuleName, int>> _Sequence2PMWaferCount = new Dictionary<string, Dictionary<ModuleName, int>>();
|
|
|
+
|
|
|
private bool _isCycleMode;
|
|
|
private int _cycleSetPoint = 0;
|
|
|
private int _cycledCount = 0;
|
|
@@ -1013,6 +1061,14 @@ namespace Venus_RT.Modules
|
|
|
pj.LotName = lotId;
|
|
|
pj.SlotWafers = seqSlotWafers[seqs[i]];
|
|
|
pj.SetState(EnumProcessJobState.Queued);
|
|
|
+ if (!_Sequence2PMWaferCount.ContainsKey(pj.Sequence.Name))
|
|
|
+ _Sequence2PMWaferCount.Add(pj.Sequence.Name,new Dictionary<ModuleName, int>()
|
|
|
+ {
|
|
|
+ {ModuleName.PMA , 0},
|
|
|
+ {ModuleName.PMB , 0},
|
|
|
+ {ModuleName.PMC , 0},
|
|
|
+ {ModuleName.PMD , 0},
|
|
|
+ });
|
|
|
|
|
|
if (!CheckSequencePmReady(pj.Sequence, out reason))
|
|
|
{
|
|
@@ -1303,6 +1359,7 @@ namespace Venus_RT.Modules
|
|
|
_curTmAction.Clear();
|
|
|
_lstControlJobs.Clear();
|
|
|
_lstProcessJobs.Clear();
|
|
|
+ _Sequence2PMWaferCount.Clear();
|
|
|
InUseRecipes.Clear();
|
|
|
|
|
|
_lpCycleWafer[ModuleName.LP1] = 0;
|
|
@@ -2097,7 +2154,6 @@ namespace Venus_RT.Modules
|
|
|
if (pj != null)
|
|
|
{
|
|
|
//2024-10-31 15:36:19 修改postjob来源
|
|
|
- //var postClean = pj.Sequence.GetPostCleanRecipe(pm.Key);
|
|
|
var postClean = pj.Sequence.GetPostCleanRecipe(pm.Key);
|
|
|
if (!string.IsNullOrWhiteSpace(postClean))
|
|
|
{
|
|
@@ -2116,8 +2172,13 @@ namespace Venus_RT.Modules
|
|
|
var pj = _lstProcessJobs.Find(process => process.InnerId == waitInWafer.lotId);
|
|
|
if (pj != null)
|
|
|
{
|
|
|
+ var longIdleClean = pj.Sequence.GetLongIdleCleanRecipe(pm.Key, out int idletime);
|
|
|
+ if (!string.IsNullOrWhiteSpace(longIdleClean) && idletime >= 0 && Singleton<RouteManager>.Instance.GetPM(pm.Key).LastProcessDone != null && (DateTime.Now - Singleton<RouteManager>.Instance.GetPM(pm.Key).LastProcessDone).TotalSeconds > idletime)
|
|
|
+ {
|
|
|
+ pmTask.InvokeLongIdleClean(longIdleClean);
|
|
|
+ }
|
|
|
+
|
|
|
//2024-10-31 15:36:37 修改prejob来源
|
|
|
- //var preClean = pj.Sequence.GetPreCleanRecipe(pm.Key);
|
|
|
var preClean = pj.Sequence.GetPreCleanRecipe(pm.Key);
|
|
|
if (!string.IsNullOrWhiteSpace(preClean))
|
|
|
{
|
|
@@ -2610,18 +2671,44 @@ namespace Venus_RT.Modules
|
|
|
temperature = temp;
|
|
|
}
|
|
|
|
|
|
- var waferTask = new WaferTask((ModuleName)wafer.OriginStation,
|
|
|
- wafer.OriginSlot,
|
|
|
- pm,
|
|
|
- 0,
|
|
|
- temperature,
|
|
|
- wafer.InnerId,
|
|
|
- wafer.ProcessJob.InnerId,
|
|
|
- recipeName,
|
|
|
- wafer.ProcessJob.Sequence.GetWTWCleanRecipe(pm),
|
|
|
- wafer.ProcessJob.Sequence.LLInOutPath,
|
|
|
- wafer.ProcessJob.Sequence.LLDelayTime,
|
|
|
- IsSequenceNeedAlign(wafer.ProcessJob.Sequence)); // post clean
|
|
|
+
|
|
|
+ int interval = wafer.ProcessJob.Sequence.GetWTWCleanInterval(pm);
|
|
|
+
|
|
|
+ WaferTask waferTask;
|
|
|
+
|
|
|
+ ++_Sequence2PMWaferCount[wafer.ProcessJob.Sequence.Name][pm];
|
|
|
+
|
|
|
+ if (interval == 1 || _Sequence2PMWaferCount[wafer.ProcessJob.Sequence.Name][pm] % interval == 0)
|
|
|
+ {
|
|
|
+ waferTask = new WaferTask((ModuleName)wafer.OriginStation,
|
|
|
+ wafer.OriginSlot,
|
|
|
+ pm,
|
|
|
+ 0,
|
|
|
+ temperature,
|
|
|
+ wafer.InnerId,
|
|
|
+ wafer.ProcessJob.InnerId,
|
|
|
+ recipeName,
|
|
|
+ wafer.ProcessJob.Sequence.GetWTWCleanRecipe(pm),
|
|
|
+ wafer.ProcessJob.Sequence.LLInOutPath,
|
|
|
+ wafer.ProcessJob.Sequence.LLDelayTime,
|
|
|
+ IsSequenceNeedAlign(wafer.ProcessJob.Sequence)); // post clean
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ waferTask = new WaferTask((ModuleName)wafer.OriginStation,
|
|
|
+ wafer.OriginSlot,
|
|
|
+ pm,
|
|
|
+ 0,
|
|
|
+ temperature,
|
|
|
+ wafer.InnerId,
|
|
|
+ wafer.ProcessJob.InnerId,
|
|
|
+ recipeName,
|
|
|
+ "",
|
|
|
+ wafer.ProcessJob.Sequence.LLInOutPath,
|
|
|
+ wafer.ProcessJob.Sequence.LLDelayTime,
|
|
|
+ IsSequenceNeedAlign(wafer.ProcessJob.Sequence)); // post clean
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
waferTask.OnWaferArrived += WaferArrived;
|
|
|
waferTask.OnWaferLeaved += WaferLeaved;
|