|
@@ -20,10 +20,13 @@ namespace Venus_RT.Modules.PMs
|
|
|
{
|
|
|
private enum ProcessStep
|
|
|
{
|
|
|
- kPreparePressure,
|
|
|
- kPrepareTemperature,
|
|
|
- kRunRecipes,
|
|
|
- kEnd,
|
|
|
+ PreparePressure,
|
|
|
+ PrepareTemperature,
|
|
|
+ RunProcessRecipes,
|
|
|
+ End,
|
|
|
+ RunCleanRecipes,
|
|
|
+ RunChuckRecipes,
|
|
|
+ RunDechuckRecipes,
|
|
|
}
|
|
|
public string CurrentRunningRecipe { get; set; }
|
|
|
public string ProcessRecipeName { get; set; }
|
|
@@ -47,7 +50,7 @@ namespace Venus_RT.Modules.PMs
|
|
|
//private bool _needPumpDown = false;
|
|
|
public Recipe _currentRecipe = null;
|
|
|
private int _currentStep = 0;
|
|
|
- private Queue<Recipe> _qeRecipes = new Queue<Recipe>();
|
|
|
+ private List<Recipe> Recipelist = new List<Recipe>();
|
|
|
|
|
|
private double _tolerance;
|
|
|
private double _OffsetTemp = 0.0f;
|
|
@@ -62,7 +65,14 @@ namespace Venus_RT.Modules.PMs
|
|
|
private RecipeFACallback _faCallback;
|
|
|
private JetChamber _jetChamber;
|
|
|
private RecipeType _recipeType;
|
|
|
- private Recipe processRecipe;
|
|
|
+ private Recipe ProcessRecipe;
|
|
|
+ private Recipe ChuckRecipe;
|
|
|
+ private Recipe DechuckRecipe;
|
|
|
+ private Recipe CleanRecipe;
|
|
|
+ private bool isprocess;
|
|
|
+ private bool isdechuck;
|
|
|
+ private bool ischuck;
|
|
|
+ private bool isclean;
|
|
|
private double ChillerTemp
|
|
|
{
|
|
|
get
|
|
@@ -130,10 +140,13 @@ namespace Venus_RT.Modules.PMs
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
public RState Start(params object[] objs)
|
|
|
{
|
|
|
+ isprocess = false;
|
|
|
+ ischuck = false;
|
|
|
+ isclean = false;
|
|
|
+ isdechuck = false;
|
|
|
+ Recipelist.Clear();
|
|
|
string recipeName = (string)objs[0];
|
|
|
if (objs.Length >= 2)
|
|
|
{
|
|
@@ -148,10 +161,6 @@ namespace Venus_RT.Modules.PMs
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //if (objs.Length >= 2)
|
|
|
- //{
|
|
|
- // _withWafer = (bool)objs[2];
|
|
|
- //}
|
|
|
if (_withWafer && WaferManager.Instance.CheckNoWafer(Module, 0))
|
|
|
{
|
|
|
Stop($"can not run process, no wafer at {Module}");
|
|
@@ -176,13 +185,8 @@ namespace Venus_RT.Modules.PMs
|
|
|
{
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- // Load/Validate Recipe
|
|
|
- _qeRecipes.Clear();
|
|
|
currentRecipeResult = new RecipeResult();
|
|
|
currentRecipeResult.RecipeName = recipeName;
|
|
|
-
|
|
|
string recipeContent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipeName, false, objs[2].ToString());
|
|
|
Recipe recipe = Recipe.Load(recipeContent);
|
|
|
currentRecipeResult.RecipeStepCount = recipe.Steps.Count;
|
|
@@ -192,56 +196,64 @@ namespace Venus_RT.Modules.PMs
|
|
|
EV.PostAlarmLog(Module.ToString(), $"Load Recipe:{recipeName} failed");
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
-
|
|
|
_recipeRunningMode = SC.GetValue<int>($"{Module}.RecipeRunningMode");
|
|
|
_processHelper.m_RecipeHead = recipe.Header;
|
|
|
switch (recipe.Header.Type)
|
|
|
{
|
|
|
case RecipeType.Process:
|
|
|
+
|
|
|
if (_recipeRunningMode == 1 && recipe.Header.ChuckRecipe != null && !string.IsNullOrEmpty(recipe.Header.ChuckRecipe))
|
|
|
{
|
|
|
string chuckcontent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipe.Header.ChuckRecipe, false, RecipeType.Chuck.ToString());
|
|
|
- var chuckRecipe = Recipe.Load(chuckcontent);
|
|
|
- if (chuckRecipe != null)
|
|
|
+ ChuckRecipe = Recipe.Load(chuckcontent);
|
|
|
+ if (ChuckRecipe != null)
|
|
|
{
|
|
|
ChuckRecipeName = recipe.Header.ChuckRecipe;
|
|
|
- _qeRecipes.Enqueue(chuckRecipe);
|
|
|
+ ischuck = true;
|
|
|
+ Recipelist.Add(ChuckRecipe);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ isprocess = true;
|
|
|
ProcessRecipeHead = recipe.Header;
|
|
|
-
|
|
|
+ ProcessRecipe = recipe;
|
|
|
ProcessRecipeName = recipeName;
|
|
|
- _qeRecipes.Enqueue(recipe);
|
|
|
+ Recipelist.Add(recipe);
|
|
|
+
|
|
|
+
|
|
|
|
|
|
if (_recipeRunningMode == 1 && recipe.Header.DechuckRecipe != null && !string.IsNullOrEmpty(recipe.Header.DechuckRecipe))
|
|
|
{
|
|
|
|
|
|
string dechuckcontent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipe.Header.DechuckRecipe, false, RecipeType.DeChuck.ToString());
|
|
|
- var dechuckRecipe = Recipe.Load(dechuckcontent);
|
|
|
- if (dechuckRecipe != null)
|
|
|
+ DechuckRecipe = Recipe.Load(dechuckcontent);
|
|
|
+ if (DechuckRecipe != null)
|
|
|
{
|
|
|
DechuckRecipeName = recipe.Header.DechuckRecipe;
|
|
|
- _qeRecipes.Enqueue(dechuckRecipe);
|
|
|
+ isdechuck = true;
|
|
|
+ Recipelist.Add(DechuckRecipe);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
break;
|
|
|
case RecipeType.Chuck:
|
|
|
ChuckRecipeName = recipeName;
|
|
|
- _qeRecipes.Enqueue(recipe);
|
|
|
+ ChuckRecipe = recipe;
|
|
|
+ Recipelist.Add(ChuckRecipe);
|
|
|
+ ischuck = true;
|
|
|
break;
|
|
|
case RecipeType.DeChuck:
|
|
|
DechuckRecipeName = recipeName;
|
|
|
- _qeRecipes.Enqueue(recipe);
|
|
|
+ Recipelist.Add(DechuckRecipe);
|
|
|
+ DechuckRecipe = recipe;
|
|
|
+ isdechuck = true;
|
|
|
break;
|
|
|
case RecipeType.Clean:
|
|
|
+ CleanRecipe = recipe;
|
|
|
CleanRecipeName = recipeName;
|
|
|
- _qeRecipes.Enqueue(recipe);
|
|
|
+ Recipelist.Add(CleanRecipe);
|
|
|
+ isclean = true;
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
- foreach (Recipe rcp in _qeRecipes)
|
|
|
+ foreach (Recipe rcp in Recipelist)
|
|
|
{
|
|
|
if (AssignFuns(rcp) == false)
|
|
|
{
|
|
@@ -250,7 +262,6 @@ namespace Venus_RT.Modules.PMs
|
|
|
return RState.Failed;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
_bLoopMode = false;
|
|
|
_loopStartStep = 0;
|
|
|
_loopCounter = 0;
|
|
@@ -267,11 +278,14 @@ namespace Venus_RT.Modules.PMs
|
|
|
}
|
|
|
public RState Monitor()
|
|
|
{
|
|
|
- Runner
|
|
|
- .Run(ProcessStep.kPreparePressure, PreparePressure, IsPressureReady)
|
|
|
- .Run(ProcessStep.kPrepareTemperature, PrepareTemp, IsTempReady)
|
|
|
- .Run(ProcessStep.kRunRecipes, StartNewRecipe, RunRecipes, 5 * 60 * 60 * 1000)
|
|
|
- .End(ProcessStep.kEnd, ProcessDone, _delay_1s);
|
|
|
+ Runner
|
|
|
+ .Run(ProcessStep.PreparePressure, PreparePressure, IsPressureReady)
|
|
|
+ .Run(ProcessStep.PrepareTemperature, PrepareTemp, IsTempReady)
|
|
|
+ .RunIf(ProcessStep.RunCleanRecipes, isclean, StartNewCleanRecipe, RunRecipes, 5 * 60 * 60 * 1000)
|
|
|
+ .RunIf(ProcessStep.RunChuckRecipes, ischuck, StartNewChuckRecipe, RunRecipes, 5 * 60 * 60 * 1000)
|
|
|
+ .RunIf(ProcessStep.RunProcessRecipes, isprocess, StartNewProcessRecipe, RunRecipes, 5 * 60 * 60 * 1000)
|
|
|
+ .RunIf(ProcessStep.RunDechuckRecipes, isdechuck, StartNewDechuckRecipe, RunRecipes, 5 * 60 * 60 * 1000)
|
|
|
+ .End(ProcessStep.End, ProcessDone, _delay_1s);
|
|
|
|
|
|
return Runner.Status;
|
|
|
}
|
|
@@ -336,7 +350,7 @@ namespace Venus_RT.Modules.PMs
|
|
|
}
|
|
|
|
|
|
public RState StartNewStep()
|
|
|
- {
|
|
|
+ {
|
|
|
ProcessDataRecorder.StepStart(GuidAllStep, _currentRecipe.Steps[_currentStep].StepNo, $"{Module}:{_currentRecipe.Header.Name}:{_currentRecipe.Steps[_currentStep].Description}", _currentRecipe.Steps[_currentStep].Time);
|
|
|
_stepTime.Restart();
|
|
|
var state = _currentRecipe.Steps[_currentStep].Start();
|
|
@@ -370,28 +384,72 @@ namespace Venus_RT.Modules.PMs
|
|
|
|
|
|
return RState.Running;
|
|
|
}
|
|
|
-
|
|
|
- private bool StartNewRecipe()
|
|
|
+ private bool StartNewProcessRecipe()
|
|
|
{
|
|
|
- if (_qeRecipes.Count > 0)
|
|
|
+ if (ProcessRecipe != null)
|
|
|
{
|
|
|
+ _currentRecipe = ProcessRecipe;
|
|
|
_currentStep = 0;
|
|
|
- _currentRecipe = _qeRecipes.Dequeue();
|
|
|
CurrentRunningRecipe = _currentRecipe.Header.Name;
|
|
|
- if (GuidAllStep == null)
|
|
|
- {
|
|
|
- GuidAllStep = Guid.NewGuid().ToString();
|
|
|
- RecipeStartTime = DateTime.Now;
|
|
|
- Recipetime.Restart();
|
|
|
- }
|
|
|
+ GuidAllStep = Guid.NewGuid().ToString();
|
|
|
+ RecipeStartTime = DateTime.Now;
|
|
|
+ Recipetime.Restart();
|
|
|
+ Notify($"Recipe:{CurrentRunningRecipe} start");
|
|
|
+ _chamber.EPDRecipeStart(CurrentRunningRecipe);
|
|
|
+ return StartNewStep() == RState.Running;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ private bool StartNewChuckRecipe()
|
|
|
+ {
|
|
|
+ if (ChuckRecipe != null)
|
|
|
+ {
|
|
|
+ _currentRecipe = ChuckRecipe;
|
|
|
+ _currentStep = 0;
|
|
|
+ CurrentRunningRecipe = _currentRecipe.Header.Name;
|
|
|
+ GuidAllStep = Guid.NewGuid().ToString();
|
|
|
+ RecipeStartTime = DateTime.Now;
|
|
|
+ Recipetime.Restart();
|
|
|
Notify($"Recipe:{CurrentRunningRecipe} start");
|
|
|
_chamber.EPDRecipeStart(CurrentRunningRecipe);
|
|
|
return StartNewStep() == RState.Running;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
- private bool RunRecipes()
|
|
|
- {
|
|
|
+ private bool StartNewDechuckRecipe()
|
|
|
+ {
|
|
|
+ if (DechuckRecipe != null)
|
|
|
+ {
|
|
|
+ _currentRecipe = DechuckRecipe;
|
|
|
+ _currentStep = 0;
|
|
|
+ CurrentRunningRecipe = _currentRecipe.Header.Name;
|
|
|
+ GuidAllStep = Guid.NewGuid().ToString();
|
|
|
+ RecipeStartTime = DateTime.Now;
|
|
|
+ Recipetime.Restart();
|
|
|
+ Notify($"Recipe:{CurrentRunningRecipe} start");
|
|
|
+ _chamber.EPDRecipeStart(CurrentRunningRecipe);
|
|
|
+ return StartNewStep() == RState.Running;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ private bool StartNewCleanRecipe()
|
|
|
+ {
|
|
|
+ if (CleanRecipe != null)
|
|
|
+ {
|
|
|
+ _currentRecipe = CleanRecipe;
|
|
|
+ _currentStep = 0;
|
|
|
+ CurrentRunningRecipe = _currentRecipe.Header.Name;
|
|
|
+ GuidAllStep = Guid.NewGuid().ToString();
|
|
|
+ RecipeStartTime = DateTime.Now;
|
|
|
+ Recipetime.Restart();
|
|
|
+ Notify($"Recipe:{CurrentRunningRecipe} start");
|
|
|
+ _chamber.EPDRecipeStart(CurrentRunningRecipe);
|
|
|
+ return StartNewStep() == RState.Running;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ private bool RunRecipes()
|
|
|
+ {
|
|
|
var step = _currentRecipe.Steps[_currentStep];
|
|
|
currentRecipeResult.RecipeStepCount = _currentRecipe.Steps.Count;
|
|
|
currentRecipeResult.RecipeName = _currentRecipe.Header.Name;
|
|
@@ -400,15 +458,12 @@ namespace Venus_RT.Modules.PMs
|
|
|
currentRecipeResult.RecipeStepType = step.Type.ToString();
|
|
|
currentRecipeResult.RecipeStepDescription = string.IsNullOrEmpty(step.Description) ? "" : step.Description;
|
|
|
currentRecipeResult.RecipeStepSetTime = step.Time;
|
|
|
- currentRecipeResult.RecipeType = _currentRecipe.Header.Type.ToString();
|
|
|
+ currentRecipeResult.RecipeType = _currentRecipe.Header.Type.ToString();
|
|
|
currentRecipeResult.RecipeStepDuringTime = new System.TimeSpan(0, 0, System.Convert.ToInt32(_stepTime.ElapsedMilliseconds / 1000));
|
|
|
-
|
|
|
-
|
|
|
var result = step.Run();
|
|
|
if (result == RState.Failed)
|
|
|
{
|
|
|
- WaferManager.Instance.UpdateWaferProcessStatus(Module, 0, EnumWaferProcessStatus.Completed);
|
|
|
- RecipeDown("Fail");
|
|
|
+ RecipeDone("Fail");
|
|
|
UpdateWaferStatus(false);
|
|
|
Runner.Stop($"Recipe:{CurrentRunningRecipe}, Step:{_currentStep + 1} Failed");
|
|
|
EV.PostAlarmLog(Module.ToString(), $"Recipe:{CurrentRunningRecipe}, Step:{_currentStep + 1} Failed");
|
|
@@ -454,21 +509,21 @@ namespace Venus_RT.Modules.PMs
|
|
|
Notify($"Recipe:{CurrentRunningRecipe} finished");
|
|
|
//FaEvent.FaPostInfo(Module.ToString(), $"Recipe:{CurrentRunningRecipe} finished");
|
|
|
UpdateWaferStatus();
|
|
|
- if (_currentRecipe.Header.Type == RecipeType.Process)
|
|
|
- {
|
|
|
+ //if (_currentRecipe.Header.Type == RecipeType.Process)
|
|
|
+ //{
|
|
|
|
|
|
- processRecipe = (Recipe)SerializeHelper.Instance.Clone(_currentRecipe);
|
|
|
- }
|
|
|
+ // processRecipe = (Recipe)SerializeHelper.Instance.Clone(_currentRecipe);
|
|
|
+ //}
|
|
|
_chamber.EPDRecipeStop();
|
|
|
- RecipeDown("Success");
|
|
|
- return !StartNewRecipe();
|
|
|
+ RecipeDone("Success");
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- public void RecipeDown(string result)
|
|
|
+
|
|
|
+ public void RecipeDone(string result)
|
|
|
{
|
|
|
Recipetime.Stop();
|
|
|
WaferInfo waferInfo = WaferManager.Instance.GetWafer(ModuleHelper.Converter(Module.ToString()), 0);
|
|
@@ -477,20 +532,19 @@ namespace Venus_RT.Modules.PMs
|
|
|
WaferId = waferInfo.InnerId.ToString();
|
|
|
SlotID = waferInfo.OriginSlot.ToString();
|
|
|
LotID = waferInfo.ProcessJob == null || string.IsNullOrEmpty(waferInfo.ProcessJob.ControlJobName) ? "" : waferInfo.ProcessJob.ControlJobName;
|
|
|
- }
|
|
|
+ }
|
|
|
RecipeEndTime = RecipeStartTime + Recipetime.Elapsed;
|
|
|
switch (_currentRecipe.Header.Type)
|
|
|
{
|
|
|
case RecipeType.Clean:
|
|
|
- ProcessDataRecorder.RecordPrecess(GuidAllStep, RecipeStartTime, DateTime.Now, _currentRecipe.Header.Name, result, "", _chamber.Name, "", "", _currentRecipe.Header.Type.ToString());
|
|
|
+ ProcessDataRecorder.RecordPrecess(GuidAllStep, RecipeStartTime, RecipeEndTime, _currentRecipe.Header.Name, result, "", _chamber.Name, "", "", _currentRecipe.Header.Type.ToString());
|
|
|
break;
|
|
|
case RecipeType.Chuck:
|
|
|
case RecipeType.DeChuck:
|
|
|
case RecipeType.Process:
|
|
|
ProcessDataRecorder.RecordPrecess(GuidAllStep, RecipeStartTime, RecipeEndTime, _currentRecipe.Header.Name, result, WaferId, _chamber.Name, LotID, SlotID, _currentRecipe.Header.Type.ToString());
|
|
|
break;
|
|
|
- }
|
|
|
- GuidAllStep = null;
|
|
|
+ }
|
|
|
}
|
|
|
private bool ProcessDone()
|
|
|
{
|
|
@@ -543,7 +597,7 @@ namespace Venus_RT.Modules.PMs
|
|
|
|
|
|
public async void Abort()
|
|
|
{
|
|
|
- RecipeDown("Abort");
|
|
|
+ RecipeDone("Abort");
|
|
|
_chamber.GeneratorBiasPowerOn(false);
|
|
|
_chamber.GeneratorPowerOn(false);
|
|
|
_chamber.TurnPendulumValve(false);
|