2023-03-03 15:42:13 +08:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Windows.Media.Imaging ;
using Aitex.Core.Common ;
using Aitex.Core.RT.DataCenter ;
using Aitex.Core.RT.Device ;
using Aitex.Core.RT.Event ;
using Aitex.Core.RT.Log ;
using Aitex.Core.RT.OperationCenter ;
using Aitex.Core.RT.RecipeCenter ;
using Aitex.Core.RT.Routine ;
using Aitex.Core.RT.SCCore ;
using Aitex.Core.Util ;
using Aitex.Sorter.Common ;
using MECF.Framework.Common.DataCenter ;
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 SicRT.Equipments.Schedulers ;
using SicRT.Modules.Schedulers ;
using SicRT.Scheduler ;
namespace SicRT.Modules
{
public partial class AutoTransfer : SchedulerModuleFactory
{
public class TrayInfo
{
public int TrayModule { get ; set ; }
public int TraySlot { get ; set ; }
public int TrayProcessCount { get ; set ; }
}
private List < ControlJobInfo > _lstNeedMapJob = new List < ControlJobInfo > ( ) ;
private List < ControlJobInfo > _lstControlJobs = new List < ControlJobInfo > ( ) ;
private List < ProcessJobInfo > _lstProcessJobs = new List < ProcessJobInfo > ( ) ;
private List < TrayInfo > _lstProcessedTrayInfo = new List < TrayInfo > ( ) ; //保存石墨盘的进入腔体的信息(最多4次工艺需要换盘)
private int _maxTrayCount = 4 ; //可以同时运行的石墨盘总数
private bool _cassProcessOnebyOne = false ; //Cassette是左右交互取片还是一个Cassette取完再取另一个
private R_TRIG NotifyTrayExhausted = new R_TRIG ( ) ;
private R_TRIG _trigIsPumping = new R_TRIG ( ) ;
private const string LogSource = "Scheduler" ;
private SchedulerDBCallback _dbCallback ;
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 string _timeBuffer1 { get ; set ; }
private string _timeBuffer2 { get ; set ; }
private string _timeBuffer3 { get ; set ; }
private Dictionary < string , DateTime > _bufferWaferInfo = new Dictionary < string , DateTime > ( ) ;
Queue < Action > waferRobotActions = new Queue < Action > ( ) { } ;
Queue < Action > trayRobotActions = new Queue < Action > ( ) { } ;
Queue < Action > tmRobotActions = new Queue < Action > ( ) { } ;
public AutoTransfer ( )
{
_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 ( "CassAL.LocalJobName" , ( ) = >
{
var jb = _lstControlJobs . FirstOrDefault ( x = > x . Module = = "CassAL" ) ;
if ( jb ! = null )
return jb . Name ;
return "" ;
} ) ;
DATA . Subscribe ( "CassAL.LocalJobStatus" , ( ) = >
{
var jb = _lstControlJobs . FirstOrDefault ( x = > x . Module = = "CassAL" ) ;
if ( jb ! = null )
return jb . State . ToString ( ) ;
return "" ;
} ) ;
DATA . Subscribe ( "CassAR.LocalJobName" , ( ) = >
{
var jb = _lstControlJobs . FirstOrDefault ( x = > x . Module = = "CassAR" ) ;
if ( jb ! = null )
return jb . Name ;
return "" ;
} ) ;
DATA . Subscribe ( "CassAR.LocalJobStatus" , ( ) = >
{
var jb = _lstControlJobs . FirstOrDefault ( x = > x . Module = = "CassAR" ) ;
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 ;
} ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotCassettePlaceTask ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotCassettePickTask ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotUnLoadPickTask ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotAlignerPlaceTask ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotAlignerPickTask ) ;
waferRobotActions . Enqueue ( MonitorWaferRobotLoadPlaceTask ) ;
trayRobotActions . Enqueue ( MonitorTrayRobotLoadPlaceTask ) ;
trayRobotActions . Enqueue ( MonitorTrayRobotLoadPickTask ) ;
trayRobotActions . Enqueue ( MonitorTrayRobotCassettePlaceTask ) ;
trayRobotActions . Enqueue ( MonitorTrayRobotCassettePickTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotPMPlaceTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotPMPickTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotBufferPlaceTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotBufferPickTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotLoadPlaceTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotLoadPickTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotUnLoadPlaceTask ) ;
tmRobotActions . Enqueue ( MonitorTmRobotUnLoadPickTask ) ;
}
public bool HasJobRunning
{
get { return _lstControlJobs . Count > 0 ; }
}
public void Clear ( )
{
_tmRobot . ResetTask ( ) ;
_waferRobot . ResetTask ( ) ;
_trayRobot . ResetTask ( ) ;
foreach ( var pm in _lstPms )
{
pm . ResetTask ( ) ;
}
foreach ( var cass in _lstWaferCassettes )
{
cass . ResetTask ( ) ;
}
_cassetteBL . ResetTask ( ) ;
_load . ResetTask ( ) ;
_unload . ResetTask ( ) ;
_buffer . ResetTask ( ) ;
_lstControlJobs . Clear ( ) ;
_lstProcessJobs . Clear ( ) ;
_bufferWaferInfo . Clear ( ) ;
}
public void ResetTask ( )
{
if ( ! _tmRobot . IsOnline )
{
_tmRobot . ResetTask ( ) ;
}
if ( ! _waferRobot . IsOnline )
{
_waferRobot . ResetTask ( ) ;
}
if ( ! _trayRobot . IsOnline )
{
_trayRobot . ResetTask ( ) ;
}
if ( ! _load . IsOnline )
{
_load . ResetTask ( ) ;
}
if ( ! _unload . IsOnline )
{
_unload . ResetTask ( ) ;
}
if ( ! _buffer . IsOnline )
{
_buffer . ResetTask ( ) ;
}
foreach ( var pm in _lstPms )
{
if ( ! pm . IsOnline )
{
pm . ResetTask ( ) ;
}
}
foreach ( var cass in _lstWaferCassettes )
{
if ( ! cass . IsOnline )
{
cass . ResetTask ( ) ;
}
}
if ( ! _cassetteBL . IsOnline )
{
_cassetteBL . ResetTask ( ) ;
}
}
public void GetConfig ( )
{
_cycledCount = 0 ;
_isCycleMode = SC . GetValue < bool > ( "System.IsCycleMode" ) ;
_cycleSetPoint = _isCycleMode ? SC . GetValue < int > ( "System.CycleCount" ) : 0 ;
_maxTrayCount = _lstPms . Count * 2 ;
}
public bool CreateJob ( Dictionary < string , object > param )
{
string reason = "" ;
string [ ] slotSequence = ( string [ ] ) param [ "SlotSequence" ] ;
string jobId = ( string ) param [ "JobId" ] ;
string module = ( string ) param [ "Module" ] ;
bool autoStart = ( bool ) param [ "AutoStart" ] ;
string lotId = jobId ;
if ( param . ContainsKey ( "LotId" ) )
lotId = ( string ) param [ "LotId" ] ;
//if (CheckModuleHaveWaferWithNoJob(out reason))
//{
// EV.PostWarningLog(LogSource, $"{reason}");
// return false;
//}
if ( ! ValidateSequence ( slotSequence , out reason ) )
{
EV . PostWarningLog ( LogSource , $"{reason}" ) ;
return false ;
}
if ( slotSequence . Length ! = 25 )
{
reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 25" ;
EV . PostWarningLog ( LogSource , reason ) ;
return false ;
}
if ( string . IsNullOrEmpty ( jobId ) )
{
jobId = "CJ_Local_" + module + DateTime . Now ;
}
if ( _lstControlJobs . Exists ( x = > x . Name = = jobId ) )
{
reason = $"LotID : {jobId} already created" ;
EV . PostWarningLog ( LogSource , reason ) ;
return false ;
}
ControlJobInfo cj = new ControlJobInfo ( ) ;
cj . Name = jobId ;
cj . Module = module ;
cj . LotName = jobId ;
cj . LotInnerId = Guid . NewGuid ( ) ;
2023-03-13 17:37:55 +08:00
cj . LotWafers = new List < WaferInfoRt > ( ) ;
2023-03-03 15:42:13 +08:00
cj . SetState ( EnumControlJobState . WaitingForStart ) ;
Dictionary < string , bool [ ] > seqSlot = new Dictionary < string , bool [ ] > ( ) ;
Dictionary < string , List < Tuple < ModuleName , int > > > seqSlotWafers = new Dictionary < string , List < Tuple < ModuleName , int > > > ( ) ;
Dictionary < string , string > indexSequence = new Dictionary < string , string > ( ) ;
bool enableGroupBySequence = SC . GetValue < bool > ( "System.Scheduler.GroupWaferBySequence" ) ;
string WaferAssociationInfo = $"WaferAssociationInfo({module}):" ;
for ( int i = 0 ; i < 25 ; i + + )
{
WaferAssociationInfo = WaferAssociationInfo + string . Format ( " slot{0} -- {1};" , i + 1 , slotSequence [ i ] ) ;
if ( string . IsNullOrEmpty ( slotSequence [ i ] ) | | string . IsNullOrEmpty ( slotSequence [ i ] . Trim ( ) ) )
continue ;
string 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).Status}" ;
EV . PostWarningLog ( LogSource , reason ) ;
return false ;
}
var wafer = WaferManager . Instance . GetWafer ( ModuleHelper . Converter ( module ) , i ) ;
if ( wafer = = null | | wafer . IsEmpty )
{
reason = $"specifies wafer: {module} slot {i + 1} not in the carrier" ;
EV . PostWarningLog ( LogSource , reason ) ;
return false ;
}
if ( wafer . ProcessState ! = EnumWaferProcessStatus . 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 ;
}
List < ProcessJobInfo > pjs = new List < ProcessJobInfo > ( ) ;
string [ ] seqs = seqSlot . Keys . ToArray ( ) ;
for ( int i = 0 ; i < seqs . Length ; i + + )
{
ProcessJobInfo 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 ) ;
//检查PM的状态
if ( ! CheckSequencePmReady ( pj . Sequence ) )
{
return false ;
}
//if (!CheckSequenceRecipeFileValid(pj.Sequence, out reason))
//{
// reason = $"recipe file not valid in the sequence, {reason}";
// EV.PostWarningLog(LogSource, reason);
// return false;
//}
//if (!CheckSequenceOrderOk(pj.Sequence, out reason))
//{
// reason = $"sequence path not valid, {reason}";
// EV.PostWarningLog(LogSource, reason);
// return false;
//}
pjs . Add ( pj ) ;
}
foreach ( var pj in pjs )
{
cj . ProcessJobNameList . Add ( pj . Name ) ;
_lstProcessJobs . Add ( pj ) ;
}
_lstControlJobs . Add ( cj ) ;
int totalWafer = 0 ;
foreach ( var pj in pjs )
{
foreach ( var pjSlotWafer in pj . SlotWafers )
{
2023-03-13 17:37:55 +08:00
var wafer = WaferManager . Instance . GetWafer ( pjSlotWafer . Item1 , pjSlotWafer . Item2 ) ;
2023-03-03 15:42:13 +08:00
wafer . ProcessJob = pj ;
WaferDataRecorder . SetCjInfo ( wafer . InnerId . ToString ( ) , cj . InnerId . ToString ( ) ) ;
WaferDataRecorder . SetWaferSequence ( wafer . InnerId . ToString ( ) , pj . Sequence . Name ) ;
WaferDataRecorder . SetWaferLotId ( wafer . InnerId . ToString ( ) , jobId ) ;
WaferManager . Instance . UpdateWaferLotId ( pjSlotWafer . Item1 , pjSlotWafer . Item2 , jobId ) ;
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 ) ;
return true ;
}
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 ( "PurgeCount" ) | | ! sequence . Steps [ currentIndex ] . StepParameter . ContainsKey ( "PumpDelayTime" ) )
{
reason = $"Invalid sequence {seqs[i]},{currentIndex + 1}st step Buffer PurgeCount or PumpDelayTime 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 ;
}
ControlJobInfo cj = new ControlJobInfo ( ) ;
cj . Name = jobId ;
cj . Module = module ;
cj . LotName = jobId ;
cj . LotInnerId = Guid . NewGuid ( ) ;
2023-03-13 17:37:55 +08:00
cj . LotWafers = new List < WaferInfoRt > ( ) ;
2023-03-03 15:42:13 +08:00
cj . SetState ( EnumControlJobState . WaitingForStart ) ;
int 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).Status}" ) ;
return false ;
}
if ( _module . GetWaferInfo ( slotWafer . Item2 ) . ProcessState ! = EnumWaferProcessStatus . 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 )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( pjSlotWafer . Item1 ) . GetWaferInfo ( pjSlotWafer . Item2 ) ;
2023-03-03 15:42:13 +08:00
cj . LotWafers . Add ( wafer ) ;
wafer . ProcessJob = pj ;
wafer . ProcessJobID = pj . Sequence . Name ;
WaferDataRecorder . SetCjInfo ( wafer . InnerId . ToString ( ) , cj . InnerId . ToString ( ) ) ;
WaferDataRecorder . SetWaferSequence ( wafer . InnerId . ToString ( ) , pj . Sequence . Name ) ;
WaferDataRecorder . SetWaferLotId ( wafer . InnerId . 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}" ) ;
CarrierInfo 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 ) ;
//模块顺序检查
List < int > lstLoad = new List < int > ( ) ;
List < int > lstBuffer = new List < int > ( ) ;
List < int > lstUnLoad = new List < int > ( ) ;
List < int > lstPM = new List < int > ( ) ;
for ( int 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 ( int 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 ) ) ;
}
ProcessJobInfo 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 ;
}
}
}
internal void AbortJob ( string jobName )
{
ControlJobInfo cj = _lstControlJobs . Find ( x = > x . Name = = jobName ) ;
if ( cj = = null )
{
EV . PostWarningLog ( LogSource , $"abort job rejected, not found job with id {jobName}" ) ;
return ;
}
int unprocessed_cj = 0 ;
int aborted_cj = 0 ;
List < ProcessJobInfo > pjAbortList = new List < ProcessJobInfo > ( ) ;
foreach ( var pj in _lstProcessJobs )
{
if ( pj . ControlJobName = = cj . Name )
{
pj . SetState ( EnumProcessJobState . Aborting ) ;
pjAbortList . Add ( pj ) ;
int unprocessed = 0 ;
int aborted = 0 ;
2023-03-13 17:37:55 +08:00
var wafers = WaferManager . Instance . GetWaferByProcessJob ( pj . Name ) ;
2023-03-03 15:42:13 +08:00
foreach ( var waferInfo in wafers )
{
waferInfo . ProcessJob = null ;
waferInfo . NextSequenceStep = 0 ;
if ( waferInfo . ProcessState ! = EnumWaferProcessStatus . 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 CheckSequencePmReady ( SequenceInfo seqInfo )
{
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" , $"can not start job, {moduleName} is not be error" ) ;
return false ;
}
if ( ! module . IsOnline )
{
EV . PostWarningLog ( "Scheduler" , $"can not start job, {moduleName} is not be online" ) ;
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 ( ) ;
ControlJobInfo 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 needProcessWafer in cj . LotWafers )
{
if ( CheckWaferNeedProcess ( ( ModuleName ) needProcessWafer . OriginStation , needProcessWafer . OriginSlot , ModuleName . PM1 ) )
{
if ( _pm1 . IsError )
{
EV . PostWarningLog ( "Scheduler" , "can not start job, pm1 is in error" ) ;
return ;
}
if ( _pm1 . IsService )
{
EV . PostWarningLog ( "Scheduler" , "can no tstart job, PM1 is Service Mode" ) ;
return ;
}
}
else if ( CheckWaferNeedProcess ( ( ModuleName ) needProcessWafer . OriginStation , needProcessWafer . OriginSlot , ModuleName . PM2 ) )
{
if ( _pm2 . IsError )
{
EV . PostWarningLog ( "Scheduler" , "can not start job, pm2 is in error" ) ;
return ;
}
if ( _pm2 . IsService )
{
EV . PostWarningLog ( "Scheduler" , "can no tstart job, PM2 is Service Mode" ) ;
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 ) ;
}
}
}
/// <summary>
/// Start Auto Transfer
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public Result Start ( params object [ ] objs )
{
GetConfig ( ) ;
_cycledWafer = 0 ;
_cycledCount = 0 ;
bool hasPmOnline = false ;
foreach ( var schedulerPm in _lstPms )
{
if ( schedulerPm . IsOnline & & ! schedulerPm . IsError )
{
hasPmOnline = true ;
break ;
}
}
if ( ! hasPmOnline )
{
EV . PostWarningLog ( "Scheduler" , "can not change to auto mode, at least one process chamber be online and no error" ) ;
return Result . FAIL ;
}
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 ;
}
//Exhaust 耗尽
public Result Monitor ( )
{
NotifyTrayExhausted . CLK = CheckTrayExhausted ( ) ;
if ( NotifyTrayExhausted . Q )
{
EV . PostAlarmLog ( "System" , "Tray ProcessCount Exhausted , No Tray for next Process !" ) ;
}
ControlJobInfo cjActive = _lstControlJobs . Find ( x = > x . State = = EnumControlJobState . Executing ) ;
if ( cjActive ! = null )
{
MonitorModuleTasks ( ) ;
}
MonitorModuleError ( ) ;
MonitorJobTasks ( ) ;
return Result . RUN ;
}
public Result MonitorJobTasks ( )
{
UpdateProcessJobStatus ( ) ;
UpdateControlJobStatus ( ) ;
StartNewJob ( ) ;
return Result . RUN ;
}
protected bool CheckAllWaferReturned ( ProcessJobInfo pj , bool checkAllProcessed )
{
for ( int i = 0 ; i < pj . SlotWafers . Count ; + + i )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( GetWaferReturnedCassette ( pj . SlotWafers [ i ] . Item1 ) ) . GetWaferInfo ( pj . SlotWafers [ i ] . Item2 ) ;
2023-03-03 15:42:13 +08:00
if ( wafer . IsEmpty )
return false ;
if ( checkAllProcessed & & GetModule ( GetWaferReturnedCassette ( pj . SlotWafers [ i ] . Item1 ) ) . CheckWaferNeedProcess ( 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 ( CheckAllWaferReturned ( pj , true ) & & CheckAllPmCleaned ( pj ) & & CheckAllDummyWaferReturned ( ) )
{
if ( _unload . IsAvailable & & _buffer . IsAvailable & & _tmRobot . IsAvailable & & _load . IsAvailable
& & _waferRobot . IsAvailable & & _unload . NoTray ( 0 )
& & _trayRobot . IsAvailable & & _tmRobot . NoTray ( 0 )
& & _load . NoTray ( 0 ) & & _waferRobot . NoWafer ( 0 ) & & _trayRobot . NoTray ( 0 ) )
{
pj . SetState ( EnumProcessJobState . ProcessingComplete ) ;
JobDataRecorder . EndPJ ( pj . InnerId . ToString ( ) , 0 , 0 ) ;
}
}
}
else if ( pj . State = = EnumProcessJobState . Stopping )
{
if ( CheckAllWaferReturned ( pj , false ) & & CheckAllPmCleaned ( pj ) & & CheckAllDummyWaferReturned ( ) )
{
if ( _unload . IsAvailable & & _buffer . IsAvailable & & _tmRobot . IsAvailable & & _load . IsAvailable
& & _waferRobot . IsAvailable & & _unload . NoTray ( 0 )
& & _trayRobot . IsAvailable & & _tmRobot . NoTray ( 0 )
& & _load . NoTray ( 0 ) & & _waferRobot . NoWafer ( 0 ) & & _trayRobot . NoTray ( 0 ) )
{
pj . SetState ( EnumProcessJobState . ProcessingComplete ) ;
JobDataRecorder . EndPJ ( pj . InnerId . ToString ( ) , 0 , 0 ) ;
}
}
}
}
}
private void UpdateControlJobStatus ( )
{
if ( _lstControlJobs . Count = = 0 )
return ;
bool allControlJobComplete = true ;
List < ControlJobInfo > cjRemoveList = new List < ControlJobInfo > ( ) ;
foreach ( var cj in _lstControlJobs )
{
if ( cj . State = = EnumControlJobState . Executing )
{
bool 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 ) ;
int unprocessed_cj = 0 ;
int aborted_cj = 0 ;
foreach ( var pj in _lstProcessJobs )
{
if ( pj . ControlJobName = = cj . Name )
{
int unprocessed = 0 ;
int aborted = 0 ;
2023-03-13 17:37:55 +08:00
var wafers = WaferManager . Instance . GetWaferByProcessJob ( pj . Name ) ;
2023-03-03 15:42:13 +08:00
foreach ( var waferInfo in wafers )
{
waferInfo . ProcessJob = null ;
waferInfo . NextSequenceStep = 0 ;
if ( waferInfo . ProcessState ! = EnumWaferProcessStatus . 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)
//{
// int countPerCycle = 0;
// int countProcessed = 0;
// foreach (var pj in _lstProcessJobs)
// {
// foreach (var pjSlotWafer in pj.SlotWafers)
// {
// countPerCycle++;
// WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
// if (!wafer.IsEmpty && !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)
// {
// WaferInfo wafer = GetModule(pjSlotWafer.Item1).GetWaferInfo(pjSlotWafer.Item2);
// wafer.ProcessJob = null;
// wafer.NextSequenceStep = 0;
// wafer.ProcessState = EnumWaferProcessStatus.Idle;
// }
// }
// }
// }
//}
foreach ( var cj in cjRemoveList )
{
List < ProcessJobInfo > 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 bool CheckAllJobDone ( )
{
foreach ( var cj in _lstControlJobs )
{
if ( cj . State = = EnumControlJobState . Executing | | cj . State = = EnumControlJobState . Paused )
return false ;
}
if ( _lstControlJobs . Count = = 0 )
{
return true ;
}
return false ;
}
private bool ActiveProcessJob ( ProcessJobInfo pj )
{
foreach ( var pjSlotWafer in pj . SlotWafers )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( pjSlotWafer . Item1 ) . GetWaferInfo ( pjSlotWafer . Item2 ) ;
2023-03-03 15:42:13 +08:00
wafer . ProcessJob = pj ;
wafer . NextSequenceStep = 0 ;
WaferDataRecorder . SetPjInfo ( wafer . InnerId . ToString ( ) , pj . InnerId . ToString ( ) ) ;
}
ControlJobInfo cj = _lstControlJobs . Find ( x = > x . Name = = pj . ControlJobName ) ;
CarrierInfo 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 ;
}
public Result MonitorModuleTasks ( )
{
//TMRobot和UnLoad不能同时抽气
_trigIsPumping . CLK = _unload . IsInPumping & & _tmRobot . IsInPumping ;
if ( _trigIsPumping . Q )
{
EV . PostAlarmLog ( "System" , $"检测到 TM.IsInPumping,current Task is {_tmRobot.GetTask()}, _unload.IsInPumping,current Task is {_unload.GetTask()}" ) ;
}
MonitorPMTask ( ) ;
MonitorBufferTask ( ) ;
MonitorAlignerTask ( ) ;
MonitorTmRobotTask ( ) ;
MonitorWaferRobotTask ( ) ;
MonitorTrayRobotTask ( ) ;
MonitorLoadTask ( ) ;
MonitorUnLoadTask ( ) ;
return Result . RUN ;
}
private void MonitorBufferTask ( )
{
if ( ! _buffer . IsAvailable )
{
return ;
}
if ( _buffer . FirstDetectTrayArrive ( 0 )
| | _buffer . FirstDetectTrayArrive ( 1 )
| | _buffer . FirstDetectTrayArrive ( 2 ) )
{
_buffer . ResetPurgeStatus ( ) ;
}
for ( int i = 0 ; i < 3 ; i + + )
{
bool canExcute = _buffer . HasWafer ( i ) & & _buffer . CheckWaferNextStepIsThis ( _buffer . Module , i ) ;
if ( canExcute )
{
2023-03-13 17:37:55 +08:00
var bufferWafer = _buffer . GetWaferInfo ( i ) ;
2023-03-03 15:42:13 +08:00
// int bufferSetValue = 0;
//if (!GetWaferSequenceNextValue(ModuleName.Buffer, i, "BufferType", out string strBufferType))
//{
// continue;
//}
//if (!GetWaferSequenceNextValue(ModuleName.Buffer, i, "SetValue", out string strBufferSetValue))
//{
// continue;
//}
if ( ! GetWaferSequenceNextValue ( ModuleName . Buffer , i , "PurgeCount" , out var strPurgeLoopCount ) )
{
continue ;
}
if ( ! GetWaferSequenceNextValue ( ModuleName . Buffer , i , "PumpDelayTime" , out var strPurgePumpDelay ) )
{
continue ;
}
//if (!Int32.TryParse(strBufferSetValue, out bufferSetValue)
// || !int.TryParse(strPurgeLoopCount, out var purgeLoopCount)
// || !int.TryParse(strPurgePumpDelay, out var purgePumpDelay))
//{
// continue;
//}
if ( ! int . TryParse ( strPurgeLoopCount , out var purgeLoopCount )
| | ! int . TryParse ( strPurgePumpDelay , out var purgePumpDelay ) )
{
continue ;
}
2023-03-13 17:37:55 +08:00
var wafer = _buffer . GetWaferInfo ( i ) ;
2023-03-03 15:42:13 +08:00
//分别判断冷却和加热方式温度是否达到
//if (strBufferType == "HeatByTemp")
//{
// if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
// {
// DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
// double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
// //选择By温度1秒后再判断温度
// if (pastTime > 1)
// {
// if (_buffer.GetTemperature() >= bufferSetValue)
// wafer.NextSequenceStep++;
// _bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
// }
// }
// else
// {
// _bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
// }
//}
//else if (strBufferType == "HeatByTime")
//{
// if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
// {
// DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
// double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
// if (i == 0)
// {
// _timeBuffer1 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// else if (i == 1)
// {
// _timeBuffer2 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// if (i == 2)
// {
// _timeBuffer3 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// if (pastTime > bufferSetValue)
// {
// wafer.NextSequenceStep++;
// _bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
// }
// }
// else
// {
// _bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
// }
//}
//else if (strBufferType == "CoolingByTime")
//{
// if (_bufferWaferInfo.ContainsKey(bufferWafer.InnerId.ToString()))
// {
// DateTime dtStartTime = _bufferWaferInfo[bufferWafer.InnerId.ToString()];
// double pastTime = (DateTime.Now - dtStartTime).TotalSeconds;
// if (i == 0)
// {
// _timeBuffer1 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// else if (i == 1)
// {
// _timeBuffer2 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// if (i == 2)
// {
// _timeBuffer3 = pastTime > bufferSetValue ? "0" : (bufferSetValue - pastTime).ToString();
// }
// if (pastTime > bufferSetValue)
// {
// wafer.NextSequenceStep++;
// _bufferWaferInfo.Remove(bufferWafer.InnerId.ToString());
// }
// }
// else
// {
// _bufferWaferInfo.Add(bufferWafer.InnerId.ToString(), DateTime.Now);
// }
//}
// 如果TMRobot空闲, 并且Buffer收到新盘, 则根据Sequence配置进行Purge。
if ( _tmRobot . IsAvailable & & ! _buffer . HasPurged )
{
_tmRobot . Purge ( purgeLoopCount , purgePumpDelay ) ;
_buffer . HasPurged = true ;
wafer . NextSequenceStep + + ;
}
return ;
}
}
}
private void MonitorLoadTask ( )
{
if ( ! _load . IsAvailable )
{
return ;
}
//第一种情况 : 有Wafer有Tray且Load Sequence还未执行
if ( _load . HasWafer ( 0 ) & & _load . HasTrayAndNotExceedProcessCount ( 0 ) & & _load . CheckWaferNextStepIsThis ( ModuleName . LoadLock , 0 ) )
{
if ( ! _load . CheckWaferTrayGrouped ( ) )
{
_load . GroupWaferTray ( ) ;
return ;
}
_load . Purge ( _load . GetWaferPurgeCount ( 0 ) , _load . GetWaferPumpDelayTime ( 0 ) ) ;
_load . GetWaferInfo ( 0 ) . NextSequenceStep + + ;
return ;
}
//第二种情况: 有Wafer有Tray且Load Sequence已执行
else if ( _load . HasWafer ( 0 ) & & _load . HasTrayAndNotExceedProcessCount ( 0 ) & & ! _load . CheckWaferNextStepIsThis ( ModuleName . LoadLock , 0 ) )
{
if ( ! _load . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Pick , 0 ) ;
return ;
}
}
//第三种情况 : Load腔没盘,TMRobot/Buffer1/2/3中有次数用完的盘
else if ( _load . NoTray ( 0 )
& & ( ( _tmRobot . NoWafer ( 0 ) & & _tmRobot . HasTrayAndExceedProcessCount ( 0 ) )
| | ( _buffer . NoWafer ( 0 ) & & _buffer . HasTrayAndExceedProcessCount ( 0 ) )
| | ( _buffer . NoWafer ( 1 ) & & _buffer . HasTrayAndExceedProcessCount ( 1 ) )
| | ( _buffer . NoWafer ( 2 ) & & _buffer . HasTrayAndExceedProcessCount ( 2 ) ) ) )
{
if ( ! _load . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Place , 0 ) ;
return ;
}
}
//第四种情况 : Load腔没有Wafer且没有Tray
else if ( _load . NoWafer ( 0 ) & & _load . NoTray ( 0 ) )
{
if ( ! _load . IsReadyForPlace ( ModuleName . WaferRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . WaferRobot , EnumTransferType . Place , 0 ) ;
return ;
}
}
//第五种情况 : Load腔有次数用完的盘
else if ( _load . HasTrayAndExceedProcessCount ( 0 ) )
{
if ( ! _load . IsReadyForPick ( ModuleName . TrayRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . TrayRobot , EnumTransferType . Pick , 0 ) ;
return ;
}
}
else
{
bool IsTrayRobotPlace = false ;
foreach ( var pm in _lstPms )
{
if ( _load . HasWafer ( 0 ) & & _load . CheckWaferNeedProcess ( 0 , pm . Module ) & & _load . NoTray ( 0 ) )
{
if ( CheckLoadWaferNeedCassetteTray ( pm . Module ) )
{
IsTrayRobotPlace = true ;
break ;
}
}
}
if ( IsTrayRobotPlace )
{
//第六种情况 : 还没做工艺等TrayRobot来放
if ( ! _load . IsReadyForPlace ( ModuleName . TrayRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . TrayRobot , EnumTransferType . Place , 0 ) ;
return ;
}
}
else
{
//第七种情况 : 准备TMRobot来放Tray
if ( ! _load . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
_load . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Place , 0 ) ;
return ;
}
}
}
}
private void MonitorUnLoadTask ( )
{
if ( ! _unload . IsAvailable )
{
return ;
}
2023-03-11 09:15:28 +08:00
if ( ! _waferRobot . IsAvailable & & _waferRobot . Target = = ModuleName . UnLoad ) // 如果WaferRobot正在操作UnLoad
return ;
if ( ! _tmRobot . IsAvailable & & _tmRobot . Target = = ModuleName . UnLoad ) // 如果TMRobot正在操作UnLoad
return ;
2023-03-03 15:42:13 +08:00
// 重置UnLoad Purge和分离状态
if ( _unload . FirstDetectWaferArrive ( 0 ) | | _unload . FirstDetectWaferLeave ( 0 ) )
{
_unload . ResetPurgedAndSeparatedStatus ( ) ;
}
// TM把Wafer和Tray放如UnLoad后, 先冷却, 再分离, 然后取Tray前Purge
if ( _unload . HasWafer ( 0 ) & & _unload . HasTray ( 0 ) )
{
// 取Tray前Purge
if ( ! _unload . CheckPurgedBeforeTrayPicking ( ) )
{
if ( _tmRobot . IsInPumping )
return ;
_unload . PurgeBeforeTrayPicking (
_unload . GetWaferPurgeCount ( 0 ) ,
_unload . GetWaferPumpDelayTime ( 0 ) ) ;
return ;
}
// Cooling
if ( ! _unload . CheckCoolingCompleted ( ) )
{
GetWaferSequenceCoolingTime ( _unload . Module , 0 , out var coolingTime ) ;
_unload . Cooling ( true , coolingTime ) ;
return ;
}
// 如果没分离,先分离
if ( ! _unload . CheckWaferTraySeparated ( ) )
{
_unload . SeparateWaferTray ( ) ;
return ;
}
}
if ( _unload . HasTray ( 0 ) ) // UnLoad有Tray, 先让TMRobot取Tray
{
if ( _unload . CheckWaferTraySeparated ( ) )
{
// 如果Sequence下一步是UnLoad,并且W&T已冷却和分离
if ( ! _unload . CheckPurgedBeforeTrayPicking ( ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
_unload . PurgeBeforeTrayPicking (
_unload . GetWaferPurgeCount ( 0 ) ,
_unload . GetWaferPumpDelayTime ( 0 ) ) ;
return ;
}
// 如果Tray拿走以前还没Purge, 先Purge, 在让TMRobot取Tray
if ( ! _unload . CheckPurgedBeforeTrayPicking ( ) )
return ;
if ( ! _unload . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
// UnLoad中有Tray, 则准备好让TMRobot来取
_unload . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Pick , 0 ) ;
return ;
}
}
}
else if ( _unload . HasWafer ( 0 ) ) // 如果没Tray, 下一步让WaferRobot取Wafer
{
if ( _unload . CheckWaferTraySeparated ( ) )
{
// 如果取Wafer前还未Purge, 先Purge
if ( ! _unload . CheckPurgedBeforeWaferPicking ( ) & &
_unload . CheckWaferNextStepIsThis ( ModuleName . UnLoad , 0 ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
var cycle = _unload . GetWaferPurgeCount ( 0 , "PurgeCountBeforeWaferPicking" ) ;
var pumpDelay = _unload . GetWaferPumpDelayTime ( 0 , "PumpDelayTimeBeforeWaferPicking" ) ;
_unload . PurgeBeforeWaferPicking ( cycle , pumpDelay ) ;
_unload . GetWaferInfo ( 0 ) . NextSequenceStep + + ;
return ;
}
if ( _unload . CheckPurgedBeforeWaferPicking ( )
& & ! _unload . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
// 准备好让WaferRobot来取
_unload . PrepareTransfer ( ModuleName . WaferRobot , EnumTransferType . Pick , 0 ) ;
}
}
return ;
}
else // 如果UnLoad里啥也没有, 则准备好下次TMRobot喂 W&T
{
// 如果Wafer取完后还没有Purge, 先Purge
if ( ! _unload . CheckPurgedAfterWaferPicked ( ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
var cycle = _unload . GetWaferPurgeCount ( 0 , "PurgeCountAfterWaferPicking" ) ;
var pumpDelay = _unload . GetWaferPumpDelayTime ( 0 , "PumpDelayTimeAfterWaferPicking" ) ;
_unload . PurgeAfterWaferPicked ( cycle , pumpDelay ) ;
}
// 如果Wafer取完后还没有Purge, 则终止后去操作。
if ( ! _unload . CheckPurgedAfterWaferPicked ( ) )
return ;
if ( ! _unload . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . IsInPumping )
{
return ;
}
_unload . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Place , 0 ) ;
return ;
}
}
}
private void MonitorAlignerTask ( )
{
if ( ! _aligner . IsAvailable )
{
return ;
}
if ( _aligner . HasWafer ( 0 ) & & _aligner . CheckWaferNextStepIsThis ( ModuleName . Aligner , 0 ) )
{
_aligner . Aligning ( ) ;
_aligner . GetWaferInfo ( 0 ) . NextSequenceStep + + ;
}
}
private void MonitorPMTask ( )
{
foreach ( var pm in _lstPms )
{
if ( ! pm . IsAvailable )
{
continue ;
}
if ( pm . HasWafer ( 0 ) )
{
//if (pm.CheckNeedRunClean(out bool withWafer, out string recipe) && withWafer
// && GetModule(pm.Module).GetWaferInfo(0).Status == WaferStatus.Dummy
// && GetModule(pm.Module).GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Wait)
//{
// pm.Process(recipe, true, withWafer);
// continue;
//}
if ( GetModule ( pm . Module ) . CheckWaferNeedProcess ( 0 , pm . Module ) )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( pm . Module ) . GetWaferInfo ( 0 ) ;
2023-03-03 15:42:13 +08:00
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 bool withWafer, out string recipe) && !withWafer)
//{
// pm.Process(recipe, true, withWafer);
// continue;
//}
if ( ! pm . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
pm . PrepareTransfer ( ModuleName . TMRobot , EnumTransferType . Place , 0 ) ;
}
}
}
}
private void MonitorTmRobotTask ( )
{
if ( ! _tmRobot . IsAvailable )
return ;
foreach ( var pm in _lstPms )
{
if ( pm . IsWaitTransfer ( ModuleName . TMRobot ) )
pm . StopWaitTransfer ( ModuleName . TMRobot ) ;
}
if ( _buffer . IsWaitTransfer ( ModuleName . TMRobot ) )
_buffer . StopWaitTransfer ( ModuleName . TMRobot ) ;
if ( _load . IsWaitTransfer ( ModuleName . TMRobot ) )
_load . StopWaitTransfer ( ModuleName . TMRobot ) ;
if ( _unload . IsWaitTransfer ( ModuleName . TMRobot ) )
_unload . StopWaitTransfer ( ModuleName . TMRobot ) ;
if ( ! _tmRobot . IsAvailable )
return ;
var act = tmRobotActions . Peek ( ) ;
act . Invoke ( ) ;
tmRobotActions . Enqueue ( tmRobotActions . Dequeue ( ) ) ;
}
private void MonitorWaferRobotTask ( )
{
foreach ( var cass in _lstWaferCassettes )
{
if ( cass . IsWaitTransfer ( ModuleName . WaferRobot ) )
cass . StopWaitTransfer ( ModuleName . WaferRobot ) ;
}
if ( _aligner . IsWaitTransfer ( ModuleName . WaferRobot ) )
_aligner . StopWaitTransfer ( ModuleName . WaferRobot ) ;
if ( _load . IsWaitTransfer ( ModuleName . WaferRobot ) )
_load . StopWaitTransfer ( ModuleName . WaferRobot ) ;
if ( _unload . IsWaitTransfer ( ModuleName . WaferRobot ) )
_unload . StopWaitTransfer ( ModuleName . WaferRobot ) ;
if ( ! _waferRobot . IsAvailable )
return ;
var act = waferRobotActions . Peek ( ) ;
act . Invoke ( ) ;
waferRobotActions . Enqueue ( waferRobotActions . Dequeue ( ) ) ;
}
private void MonitorTrayRobotTask ( )
{
if ( _cassetteBL . IsWaitTransfer ( ModuleName . TrayRobot ) )
_cassetteBL . StopWaitTransfer ( ModuleName . TrayRobot ) ;
if ( _load . IsWaitTransfer ( ModuleName . TrayRobot ) )
_load . StopWaitTransfer ( ModuleName . TrayRobot ) ;
if ( ! _trayRobot . IsAvailable )
{
return ;
}
var act = trayRobotActions . Peek ( ) ;
act . Invoke ( ) ;
trayRobotActions . Enqueue ( trayRobotActions . Dequeue ( ) ) ;
}
private void MonitorTmRobotLoadPlaceTask ( )
{
if ( ! _load . IsAvailable | | ! _tmRobot . IsAvailable )
{
return ;
}
//第二种情况 : Load腔无Tray,TMRobot上有使用次数用完的Tray
bool canPlace = _tmRobot . HasTrayAndExceedProcessCount ( 0 ) & & _tmRobot . NoWafer ( 0 ) & & _load . NoTray ( 0 ) ;
if ( canPlace )
{
if ( _load . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
if ( _unload . IsInPumping )
{
return ;
}
if ( _tmRobot . Place ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
if ( ! _load . IsAvailable | | ! _tmRobot . IsAvailable )
{
return ;
}
//第一种情况 : Load腔有Wafer需要Process,TMRobot上有使用次数未超的Tray
canPlace = _tmRobot . HasTrayAndNotExceedProcessCount ( 0 ) & & _tmRobot . NoWafer ( 0 ) & & _load . NoTray ( 0 ) & & _load . HasWafer ( 0 )
& & _load . CheckWaferNeedProcess ( 0 ) ;
if ( canPlace )
{
if ( _load . CheckWaferNeedProcess ( 0 , _pm1 . Module ) & & _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 1 )
{
return ;
}
if ( _load . CheckWaferNeedProcess ( 0 , _pm2 . Module ) & & _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 0 )
{
return ;
}
if ( _load . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
if ( _unload . IsInPumping )
{
return ;
}
if ( _tmRobot . Place ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
private void MonitorTmRobotLoadPickTask ( )
{
if ( ! _load . IsAvailable | | ! _tmRobot . IsAvailable )
{
return ;
}
//pick TM无Tray,需要Process,下一个位置没有Tray
bool canPick = _tmRobot . NoTray ( 0 ) & & _load . CheckWaferNeedProcess ( 0 ) & & ! _load . CheckWaferNextStepIsThis ( ModuleName . LoadLock , 0 )
& & _load . CheckWaferNextStepModuleNoTray ( 0 ) ;
if ( canPick )
{
//需要完成组合和Purge
if ( ! _load . CheckWaferTrayGrouped ( ) )
{
return ;
}
if ( _load . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _unload . IsInPumping )
{
return ;
}
if ( _tmRobot . Pick ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
private void MonitorTmRobotUnLoadPlaceTask ( )
{
if ( ! _unload . IsAvailable | | ! _tmRobot . IsAvailable )
{
return ;
}
//place Robot有Wafer,UnLoad无Tray无Wafer
bool canPlaceUnLoad = _tmRobot . HasWafer ( 0 )
& & _tmRobot . HasTray ( 0 )
& & _unload . NoTray ( 0 )
& & _unload . NoWafer ( 0 )
& & ( _aligner . CheckWaferNextStepIsThis ( ModuleName . TMRobot , 0 ) | | _unload . CheckWaferNextStepIsThis ( ModuleName . TMRobot , 0 )
| | _tmRobot . CheckWaferSequenceStepDone ( 0 ) ) ;
//&& _tmRobot.GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Completed;
if ( canPlaceUnLoad )
{
if ( _unload . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Place ( _unload . Module , 0 , Hand . Blade1 ) )
{
_unload . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
private void MonitorTmRobotUnLoadPickTask ( )
{
if ( ! _unload . IsAvailable | | ! _tmRobot . IsAvailable )
{
return ;
}
//pick UnLoad有Tray,TM无Tray,LoadLock没有Tray,UnLoad分离完成
bool canPickUnLoad = _tmRobot . NoTray ( 0 )
& & _tmRobot . NoWafer ( 0 )
& & _unload . HasTray ( 0 )
& & _load . NoTray ( 0 ) ;
//&& _unload.GetWaferInfo(0).ProcessState == EnumWaferProcessStatus.Completed;
if ( canPickUnLoad )
{
//需要UnLoad把石墨盘和Wafer分离完成
if ( ! _unload . CheckWaferTraySeparated ( ) )
{
return ;
}
if ( _unload . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _unload . Module , 0 , Hand . Blade1 ) )
{
_unload . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
private void MonitorTmRobotBufferPlaceTask ( )
{
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//place Buffer位置没有Tray,Robot有Wafer,下一步骤是Buffer
bool canPalce = _tmRobot . HasWafer ( 0 ) & & _tmRobot . HasTray ( 0 ) & & _buffer . CheckWaferNextStepIsThis ( ModuleName . TMRobot , 0 ) ;
if ( canPalce )
{
SlotItem bufferEmptySlot = null ;
if ( ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 0 )
& & _tmRobot . CheckWaferNeedProcess ( 0 , _pm1 . Module )
& & _buffer . NoTray ( 0 )
& & _buffer . NoWafer ( 0 ) )
{
bufferEmptySlot = new SlotItem ( ModuleName . Buffer , 0 ) ;
}
else if ( ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 1 )
& & _tmRobot . CheckWaferNeedProcess ( 0 , _pm2 . Module )
& & _buffer . NoTray ( 1 )
& & _buffer . NoWafer ( 1 ) )
{
bufferEmptySlot = new SlotItem ( ModuleName . Buffer , 1 ) ;
}
if ( bufferEmptySlot ! = null )
{
if ( _buffer . IsReadyForPlace ( ModuleName . TMRobot , bufferEmptySlot . Slot ) )
{
if ( _tmRobot . Place ( _buffer . Module , bufferEmptySlot . Slot , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//place 完成工艺后的Tray放入Buffer中
canPalce = _tmRobot . HasTray ( 0 ) & & _tmRobot . NoWafer ( 0 ) ;
if ( canPalce )
{
if ( _tmRobot . HasTrayAndExceedProcessCount ( 0 ) & & _load . NoTray ( 0 ) )
return ;
SlotItem bufferEmptySlot = null ;
if ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 0 & & _buffer . NoTray ( 0 ) & & _buffer . NoWafer ( 0 )
& & ! _load . CheckWaferNeedProcess ( 0 , _pm1 . Module )
& & ! _waferRobot . CheckWaferNeedProcess ( 0 , _pm1 . Module )
& & ! _aligner . CheckWaferNeedProcess ( 0 , _pm1 . Module ) )
{
bufferEmptySlot = new SlotItem ( ModuleName . Buffer , 0 ) ;
}
else if ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 1 & & _buffer . NoTray ( 1 ) & & _buffer . NoWafer ( 1 )
& & ! _load . CheckWaferNeedProcess ( 0 , _pm2 . Module )
& & ! _waferRobot . CheckWaferNeedProcess ( 0 , _pm2 . Module )
& & ! _aligner . CheckWaferNeedProcess ( 0 , _pm2 . Module ) )
{
bufferEmptySlot = new SlotItem ( ModuleName . Buffer , 1 ) ;
}
if ( bufferEmptySlot ! = null )
{
if ( _buffer . IsReadyForPlace ( ModuleName . TMRobot , bufferEmptySlot . Slot ) )
{
if ( _tmRobot . Place ( _buffer . Module , bufferEmptySlot . Slot , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//place load有wafer有tray要process,需放到buffer3进行躲避
canPalce = _tmRobot . HasTray ( 0 ) & & _tmRobot . NoWafer ( 0 ) & & _buffer . NoTray ( 2 ) & & _buffer . NoWafer ( 2 ) ;
if ( canPalce )
{
if ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 0
& & ( ( _load . HasTray ( 0 ) & & _load . HasWafer ( 0 ) & & _load . CheckWaferNeedProcess ( 0 , _pm1 . Module ) )
| | ( _buffer . HasTray ( 0 ) & & _buffer . HasWafer ( 0 ) )
) )
{
if ( _buffer . IsReadyForPlace ( ModuleName . TMRobot , 2 ) )
{
if ( _tmRobot . Place ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
else if ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 1
& & ( ( _load . HasTray ( 0 ) & & _load . HasWafer ( 0 ) & & _load . CheckWaferNeedProcess ( 0 , _pm2 . Module ) )
| | ( _buffer . HasTray ( 1 ) & & _buffer . HasWafer ( 1 ) )
) )
{
if ( _buffer . IsReadyForPlace ( ModuleName . TMRobot , 2 ) )
{
if ( _tmRobot . Place ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
}
private void MonitorTmRobotBufferPickTask ( )
{
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
MonitorTmRobotBuffer1PickTask ( ) ;
MonitorTmRobotBuffer2PickTask ( ) ;
MonitorTmRobotBuffer3PickTask ( ) ;
}
private void MonitorTmRobotBuffer1PickTask ( )
{
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//第一种情况:Buffer1的Wafer需要去PM1腔工艺
bool canPick = _tmRobot . NoTray ( 0 ) & & _buffer . HasTray ( 0 ) & & _buffer . HasWafer ( 0 ) & & ! _buffer . CheckWaferNextStepIsThis ( ModuleName . Buffer , 0 ) ;
if ( canPick )
{
if ( _pm1 . CheckWaferNextStepIsThis ( ModuleName . Buffer , 0 ) )
{
if ( ! _pm1 . IsAvailable | | _pm1 . HasTray ( 0 ) | | _pm1 . HasWafer ( 0 ) | | ! _pm1 . IsReadyForPlace ( ModuleName . TMRobot , 0 ) | |
! _pm1 . 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 ;
}
}
}
}
}
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//第二种情况:工艺开始时,如果Buffer中有Tray时,优先取Buffer中的Tray,而不是Cassette中Tray
canPick = _tmRobot . NoTray ( 0 )
& & _load . IsAvailable
& & _load . IsReadyForPlace ( ModuleName . TMRobot , 0 )
& & _load . NoTray ( 0 )
& & _load . HasWafer ( 0 )
& & _load . CheckWaferNeedProcess ( 0 , ModuleName . PM1 ) ;
if ( canPick )
{
//取Tray前判断Unload是否IsInPumping,否则就会发生TMRobot有Tray
//在等Unload Pumping完成的情况
if ( _unload . IsInPumping )
{
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 ;
}
//第一种情况:Buffer2的Wafer需要去PM2腔工艺
bool canPick = _tmRobot . NoTray ( 0 ) & & _buffer . HasTray ( 1 ) & & _buffer . HasWafer ( 1 ) & & ! _buffer . CheckWaferNextStepIsThis ( ModuleName . Buffer , 1 ) ;
if ( canPick )
{
if ( _pm2 . CheckWaferNextStepIsThis ( ModuleName . Buffer , 1 ) )
{
if ( ! _pm2 . IsAvailable | | _pm2 . HasTray ( 0 ) | | _pm2 . HasWafer ( 0 ) | | ! _pm2 . IsReadyForPlace ( ModuleName . TMRobot , 0 ) | |
! _pm2 . CheckBufferToPMTemp ( ) )
return ;
if ( _buffer . CheckWaferNextStepModuleNoTray ( 1 ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 1 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
}
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
//第二种情况:工艺开始时,如果Buffer中有Tray时,优先取Buffer中的Tray,而不是Cassette中Tray
canPick = _tmRobot . NoTray ( 0 )
& & _buffer . HasTray ( 1 )
& & _buffer . NoWafer ( 1 )
& & _load . IsAvailable
& & _load . IsReadyForPlace ( ModuleName . TMRobot , 0 )
& & _load . NoTray ( 0 )
& & _load . HasWafer ( 0 )
& & _load . CheckWaferNeedProcess ( 0 , ModuleName . PM2 ) ;
if ( canPick )
{
//取Tray前判断Unload是否IsInPumping,否则就会发生TMRobot有Tray
//在等Unload Pumping完成的情况
if ( _unload . IsInPumping )
{
return ;
}
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 1 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
private void MonitorTmRobotBuffer3PickTask ( )
{
if ( ! _tmRobot . IsAvailable | | ! _buffer . IsAvailable )
{
return ;
}
bool canPick = _tmRobot . NoTray ( 0 ) & & _buffer . HasTray ( 2 ) ;
if ( canPick )
{
if ( _buffer . GetWaferInfo ( 2 ) . TrayOriginSlot % 2 = = 0 )
{
//第一种情况 : buffer0位置没有tray, load有tray但不是去PM1的
if ( _buffer . NoTray ( 0 ) & & _load . HasTray ( 0 ) & & ! _load . CheckWaferNeedProcess ( 0 , _pm1 . Module ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
//第二种情况 : buffer0位置没有tray,load也没有tray,并且没有wafer,或者有wafer但是去PM1的
else if ( _buffer . NoTray ( 0 ) & & _load . NoTray ( 0 ) & & ( _load . CheckWaferNeedProcess ( 0 , _pm1 . Module ) | | _load . NoWafer ( 0 ) ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
//第三种情况 :buffer0位置有tray, 但是pm1没有tray
else if ( _buffer . HasTray ( 0 ) & & ! _buffer . CheckWaferNeedProcess ( 0 , _pm1 . Module ) & & _pm1 . NoTray ( 0 ) & & _pm1 . NoWafer ( 0 ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
if ( _buffer . GetWaferInfo ( 2 ) . TrayOriginSlot % 2 = = 1 )
{
//第一种情况 : buffer1位置没有tray, load有tray但不是去PM2的
if ( _buffer . NoTray ( 1 ) & & _load . HasTray ( 0 ) & & ! _load . CheckWaferNeedProcess ( 0 , _pm2 . Module ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
//第二种情况 : buffer1位置没有tray, load也没有tray, 没有wafer, 或者有wafer但是去PM2的
else if ( _buffer . NoTray ( 1 ) & & _load . NoTray ( 0 ) & & ( _load . CheckWaferNeedProcess ( 0 , _pm2 . Module ) | | _load . NoWafer ( 0 ) ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
//第三种情况 : buffer1位置有tray, 但是pm2没有tray
else if ( _buffer . HasTray ( 1 ) & & ! _buffer . CheckWaferNeedProcess ( 1 , _pm2 . Module ) & & _pm2 . NoTray ( 0 ) & & _pm2 . NoWafer ( 0 ) )
{
if ( _buffer . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( _buffer . Module , 2 , Hand . Blade1 ) )
{
_buffer . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
}
}
private void MonitorTmRobotPMPlaceTask ( )
{
if ( ! _tmRobot . IsAvailable )
{
return ;
}
//第二种情况 : TMRobot有Tray, 没有Wafer,对应Buffer有Tray,需放PM存盘
bool canPlaceNoProcess = _tmRobot . NoWafer ( 0 ) & & _tmRobot . HasTrayAndNotExceedProcessCount ( 0 ) ;
if ( canPlaceNoProcess )
{
foreach ( var pm in _lstPms )
{
int bufferIndex = 0 ;
if ( pm = = _pm2 )
{
bufferIndex = 1 ;
}
if ( _tmRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = bufferIndex
& & _buffer . HasTray ( bufferIndex )
& & _buffer . NoWafer ( bufferIndex )
& & ! _buffer . CheckWaferNeedProcess ( bufferIndex , pm . Module )
& & pm . IsAvailable
& & pm . NoTray ( 0 )
& & pm . NoWafer ( 0 )
& & pm . CheckTempBelow900 ( )
& & pm . IsReadyForPlace ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Place ( pm . Module , 0 , Hand . Blade1 ) )
{
pm . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
if ( ! _tmRobot . IsAvailable )
{
return ;
}
//第一种情况 : TMRobot有Wafer并且需要Process
bool canPlace = _tmRobot . HasWafer ( 0 ) & & _tmRobot . HasTray ( 0 ) & & _tmRobot . CheckWaferNeedProcess ( 0 ) ;
if ( canPlace )
{
foreach ( var pm in _lstPms )
{
if ( ! pm . IsAvailable
| | ! GetModule ( pm . Module ) . NoWafer ( 0 )
| | ! pm . IsReadyForPlace ( ModuleName . TMRobot , 0 )
| | ! pm . CheckTempBelow900 ( ) )
continue ;
bool blade0Place = _tmRobot . HasWafer ( 0 ) & & _tmRobot . CheckWaferNeedProcess ( 0 , pm . Module ) & & pm . CheckWaferNextStepIsThis ( ModuleName . TMRobot , 0 ) ;
if ( blade0Place )
{
Hand placeBlade = Hand . Blade1 ;
if ( _tmRobot . Place ( pm . Module , 0 , placeBlade ) )
{
pm . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
}
private void MonitorTmRobotPMPickTask ( )
{
if ( ! _tmRobot . IsAvailable )
{
return ;
}
//第一种情况 : Wafer工艺结束后需取出
if ( _tmRobot . NoWafer ( 0 ) & & _tmRobot . NoTray ( 0 ) )
{
//Wafer取出后只能去Unload冷却, Buffer3有其他用途,冷却取消
if ( _unload . HasWafer ( 0 ) | | _unload . HasTray ( 0 ) | | ! _unload . IsReadyForPlace ( ModuleName . TMRobot , 0 ) | | ! _unload . IsAvailable )
{
return ;
}
Hand pickBlade = Hand . Blade1 ;
ModuleName pickPm = ModuleName . System ;
bool canPickPM1 = false ;
bool canPickPM2 = false ;
if ( _pm1 . IsAvailable & & _pm1 . HasWafer ( 0 ) & & _pm1 . HasTray ( 0 ) & & ! _pm1 . CheckWaferNeedProcess ( 0 )
& & _pm1 . CheckTempBelow900 ( ) )
{
canPickPM1 = true ;
}
if ( _pm2 . IsAvailable & & _pm2 . HasWafer ( 0 ) & & _pm2 . HasTray ( 0 ) & & ! _pm2 . CheckWaferNeedProcess ( 0 )
& & _pm2 . CheckTempBelow900 ( ) )
{
canPickPM2 = true ;
}
if ( canPickPM1 & & ! canPickPM2 )
{
pickPm = ModuleName . PM1 ;
}
else if ( ! canPickPM1 & & canPickPM2 )
{
pickPm = ModuleName . PM2 ;
}
else if ( canPickPM1 & & canPickPM2 )
{
string pm1ProcessTime = SC . GetStringValue ( "PM.PM1.PostProcessEndTime" ) ;
string pm2ProcessTime = SC . GetStringValue ( "PM.PM2.PostProcessEndTime" ) ;
if ( DateTime . TryParse ( pm1ProcessTime , out DateTime dtPM1 )
& & DateTime . TryParse ( pm2ProcessTime , out DateTime dtPM2 ) )
{
pickPm = dtPM1 . CompareTo ( dtPM2 ) < = 0 ? ModuleName . PM1 : ModuleName . PM2 ;
}
else
{
pickPm = ModuleName . PM1 ;
}
}
if ( pickPm ! = ModuleName . System )
{
SchedulerModule pm = GetModule ( pickPm . ToString ( ) ) ;
if ( pm . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( pm . Module , 0 , pickBlade ) )
{
pm . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
if ( ! _tmRobot . IsAvailable )
{
return ;
}
//第二种情况 : PM腔有Tray没Wafer, 需取出到Buffer3
if ( _tmRobot . NoWafer ( 0 ) & & _tmRobot . NoTray ( 0 ) )
{
Hand pickBlade = Hand . Blade1 ;
foreach ( var pm in _lstPms )
{
//增加温度低于900才能Pick的限制
if ( ! pm . IsAvailable
| | pm . HasWafer ( 0 )
| | pm . NoTray ( 0 )
| | GetModule ( pm . Module ) . CheckWaferNeedProcess ( 0 , pm . Module )
| | ! pm . CheckTempBelow900 ( )
| | _buffer . HasTray ( 2 )
| | _buffer . HasWafer ( 2 ) )
continue ;
//如果对应的Buffer1/2有没超次数的Tray和无Wafer,则不取
int bufferIndex = 0 ;
if ( pm = = _pm2 )
{
bufferIndex = 1 ;
}
if ( _buffer . NoWafer ( bufferIndex ) & & _buffer . HasTrayAndNotExceedProcessCount ( bufferIndex ) )
{
return ;
}
if ( pm . IsReadyForPick ( ModuleName . TMRobot , 0 ) )
{
if ( _tmRobot . Pick ( pm . Module , 0 , pickBlade ) )
{
pm . WaitTransfer ( ModuleName . TMRobot ) ;
return ;
}
}
}
}
}
private void MonitorWaferRobotLoadPlaceTask ( )
{
if ( ! _waferRobot . IsAvailable | | ! _load . IsAvailable )
{
return ;
}
//place Load没有Wafer,没有Tray,Robot有Wafer,步骤没有完成,
//下一步不是Aligner (其它:SlitValve都关了,大气)
bool canPlace = _waferRobot . HasWafer ( 0 )
& & _load . NoWafer ( 0 )
& & _load . NoTray ( 0 )
& & _waferRobot . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy
& & ! _aligner . CheckWaferNextStepIsThis ( ModuleName . WaferRobot , 0 )
& & _waferRobot . CheckWaferNeedProcess ( 0 ) ;
if ( canPlace )
{
if ( _load . IsReadyForPlace ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Place ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
private void MonitorWaferRobotUnLoadPickTask ( )
{
if ( ! _waferRobot . IsAvailable | | ! _unload . IsAvailable )
{
return ;
}
//pick UnLoad有Wafer没有Tray,Robot没有Wafer,步骤都完成了或者下一步的模块没有片子 (其它:UnLoad 夹爪夹住,顶针下降,SlitValve都关了,大气)
bool canPick = _waferRobot . NoWafer ( 0 )
& & _unload . HasWafer ( 0 )
& & _unload . NoTray ( 0 )
& & ( _unload . CheckWaferNextStepModuleNoWafer ( 0 ) | | _unload . CheckWaferSequenceStepDone ( 0 ) )
& & _unload . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy ;
if ( canPick )
{
//下一步是Aligner并且Aligner上不允许有片子
if ( _aligner . CheckWaferNextStepIsThis ( ModuleName . UnLoad , 0 ) )
{
if ( _aligner . HasWafer ( 0 ) )
{
return ;
}
}
if ( _unload . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Pick ( _unload . Module , 0 , Hand . Blade1 ) )
{
_unload . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
private void MonitorWaferRobotAlignerPlaceTask ( )
{
if ( ! _waferRobot . IsAvailable | | ! _aligner . IsAvailable )
{
return ;
}
//place 任务还没完成,下一步是Aligner,Robot有片子,Aligner没片子
bool canPlaceAligner = _aligner . NoWafer ( 0 )
& & _waferRobot . HasWafer ( 0 )
& & ( _aligner . CheckWaferNextStepIsThis ( ModuleName . WaferRobot , 0 ) | | _waferRobot . CheckWaferSequenceStepDone ( 0 ) )
& & _waferRobot . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy ;
if ( canPlaceAligner )
{
if ( _aligner . IsReadyForPlace ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Place ( _aligner . Module , 0 , Hand . Blade1 ) )
{
_aligner . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
private void MonitorWaferRobotAlignerPickTask ( )
{
if ( ! _waferRobot . IsAvailable | | ! _aligner . IsAvailable )
{
return ;
}
//pick Aligner wafer to Load
bool canPickAligner = _aligner . HasWafer ( 0 )
& & _waferRobot . NoWafer ( 0 )
& & _aligner . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy
& & ! _aligner . CheckWaferNextStepIsThis ( ModuleName . Aligner , 0 )
& & _load . CheckWaferNextStepIsThis ( ModuleName . Aligner , 0 )
& & _load . IsReadyForPlace ( ModuleName . WaferRobot , 0 )
& & _load . IsAvailable ;
if ( canPickAligner )
{
//需要运行工艺,Load不能有片子, Load不能有Tray
if ( _aligner . CheckWaferNeedProcess ( 0 ) )
{
if ( _load . HasWafer ( 0 )
| | _load . HasTray ( 0 )
| | _tmRobot . HasTrayAndExceedProcessCount ( 0 )
| | _buffer . HasTrayAndExceedProcessCount ( 0 )
| | _buffer . HasTrayAndExceedProcessCount ( 1 )
| | _buffer . HasTrayAndExceedProcessCount ( 2 ) )
{
return ;
}
}
if ( _aligner . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Pick ( _aligner . Module , 0 , Hand . Blade1 ) )
{
_aligner . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
//pick Aligner wafer to Cassette
bool canPick = _aligner . HasWafer ( 0 )
& & _waferRobot . NoWafer ( 0 )
& & _aligner . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy
& & ! _aligner . CheckWaferNextStepIsThis ( ModuleName . Aligner , 0 )
& & _aligner . CheckWaferSequenceStepDone ( 0 ) ;
if ( canPick )
{
if ( _aligner . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Pick ( _aligner . Module , 0 , Hand . Blade1 ) )
{
_aligner . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
private void MonitorWaferRobotCassettePlaceTask ( )
{
if ( ! _waferRobot . IsAvailable )
{
return ;
}
//place 任务完成了,Robot有片子,Cassette没有片子
bool canPlaceCassette = _waferRobot . HasWafer ( 0 )
& & _waferRobot . GetWaferInfo ( 0 ) . Status ! = WaferStatus . Dummy
& & _waferRobot . CheckWaferSequenceStepDone ( 0 ) ;
if ( canPlaceCassette )
{
2023-03-13 17:37:55 +08:00
var wafer = _waferRobot . GetWaferInfo ( 0 ) ;
2023-03-03 15:42:13 +08:00
if ( GetWaferReturnedCassette ( ( ModuleName ) wafer . OriginStation ) = = ModuleName . CassAL )
{
if ( _cassetteAL . IsAvailable & & _cassetteAL . IsReadyForPlace ( ModuleName . WaferRobot , wafer . OriginSlot ) )
{
if ( _waferRobot . Place ( _cassetteAL . Module , wafer . OriginSlot , Hand . Blade1 ) )
{
_cassetteAL . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
else if ( GetWaferReturnedCassette ( ( ModuleName ) wafer . OriginStation ) = = ModuleName . CassAR )
{
if ( _cassetteAR . IsAvailable & & _cassetteAR . IsReadyForPlace ( ModuleName . WaferRobot , wafer . OriginSlot ) )
{
if ( _waferRobot . Place ( _cassetteAR . Module , wafer . OriginSlot , Hand . Blade1 ) )
{
_cassetteAR . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
}
private void MonitorWaferRobotCassettePickTask ( )
{
if ( ! _waferRobot . IsAvailable )
{
return ;
}
//pick Robot没有片子,下一步的模块没有片子
bool canPick = _waferRobot . NoWafer ( 0 ) ;
SlotItem position = GetWaferInJobQueue ( ) ;
if ( canPick & & position ! = null )
{
//下一步是Aligner并且Aligner上不允许有片子
if ( _aligner . CheckWaferNextStepIsThis ( position . Module , position . Slot ) & & _aligner . HasWafer ( 0 ) )
{
return ;
}
//如果Load腔有Wafer或者Load/TMRobot/Buffer有已用完次数的Tray,
//则WaferRobot不能从Cassette取Wafer
else if ( _load . HasWafer ( 0 )
| | ! _load . IsAvailable
| | ! _load . IsReadyForPlace ( ModuleName . WaferRobot , 0 )
| | _load . HasTrayAndExceedProcessCount ( 0 )
| | _tmRobot . HasTrayAndExceedProcessCount ( 0 ) )
{
return ;
}
//超过可以运行的石墨盘最大数
if ( GetRunWaferCount ( ) > = _maxTrayCount )
{
return ;
}
//每个腔超过2个Wafer则不在取Wafer
if ( CheckWaferNeedProcess ( position . Module , position . Slot , _pm1 . Module ) )
{
if ( GetRunWaferCount ( _pm1 . Module ) > = 2 )
{
return ;
}
}
if ( CheckWaferNeedProcess ( position . Module , position . Slot , _pm2 . Module ) )
{
if ( GetRunWaferCount ( _pm2 . Module ) > = 2 )
{
return ;
}
}
if ( position . Module = = ModuleName . CassAL )
{
if ( _cassetteAL . IsAvailable & & _cassetteAL . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Pick ( position . Module , position . Slot , Hand . Blade1 ) )
{
_cassetteAL . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
else if ( position . Module = = ModuleName . CassAR )
{
if ( _cassetteAR . IsAvailable & & _cassetteAR . IsReadyForPick ( ModuleName . WaferRobot , 0 ) )
{
if ( _waferRobot . Pick ( position . Module , position . Slot , Hand . Blade1 ) )
{
_cassetteAR . WaitTransfer ( ModuleName . WaferRobot ) ;
return ;
}
}
}
}
}
private void MonitorTrayRobotLoadPlaceTask ( )
{
if ( ! _trayRobot . IsAvailable | | ! _load . IsAvailable )
{
return ;
}
if ( GetCurrentTrayCount ( ) > = _maxTrayCount )
{
return ;
}
//place Load没有Tray,有Wafer未完成
bool canPlace = _load . NoTray ( 0 )
& & _trayRobot . HasTrayAndNotExceedProcessCount ( 0 )
& & _load . HasWafer ( 0 )
& & _load . CheckWaferNeedProcess ( 0 ) ;
if ( canPlace )
{
if ( _trayRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 0 & & _load . CheckWaferNeedProcess ( 0 , _pm2 . Module ) )
{
return ;
}
if ( _trayRobot . GetWaferInfo ( 0 ) . TrayOriginSlot % 2 = = 1 & & _load . CheckWaferNeedProcess ( 0 , _pm1 . Module ) )
{
return ;
}
//TMRobot有Tray无Wafer也不能放
if ( _tmRobot . NoWafer ( 0 ) & & _tmRobot . HasTray ( 0 ) )
{
return ;
}
if ( _load . IsReadyForPlace ( ModuleName . TrayRobot , 0 ) )
{
if ( _trayRobot . Place ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . TrayRobot ) ;
return ;
}
}
}
}
private void MonitorTrayRobotLoadPickTask ( )
{
if ( ! _trayRobot . IsAvailable | | ! _load . IsAvailable )
{
return ;
}
//pick Load有Tray,且Tray次数已使用完
bool canPick = _load . HasTrayAndExceedProcessCount ( 0 ) ;
if ( canPick )
{
SlotItem emptyTraySlot = GetTrayOrignSlot ( ModuleName . LoadLock , 0 ) ; // GetEmptyTraySlot(13); //先取Wafer再取石墨盘
if ( emptyTraySlot ! = null & & _load . HasTrayAndExceedProcessCount ( 0 ) )
{
if ( _load . IsReadyForPick ( ModuleName . TrayRobot , 0 ) )
{
if ( _trayRobot . Pick ( _load . Module , 0 , Hand . Blade1 ) )
{
_load . WaitTransfer ( ModuleName . TrayRobot ) ;
return ;
}
}
}
}
}
private void MonitorTrayRobotCassettePlaceTask ( )
{
if ( ! _trayRobot . IsAvailable | | ! _cassetteBL . IsAvailable )
{
return ;
}
//place Robot有盘 其它逻辑跟Load的Pick一致
bool canPlace = _trayRobot . HasTrayAndExceedProcessCount ( 0 )
| | _load . HasTray ( 0 )
| | ( GetWaferInJobQueue ( ) = = null & & _aligner . NoWafer ( 0 ) & & _waferRobot . NoWafer ( 0 ) & & _load . NoWafer ( 0 ) ) ;
if ( canPlace )
{
SlotItem slotItem = GetTrayOrignSlot ( ModuleName . TrayRobot , 0 ) ;
if ( slotItem ! = null )
{
if ( _cassetteBL . IsReadyForPlace ( ModuleName . TrayRobot , slotItem . Slot ) )
{
if ( _trayRobot . Place ( slotItem . Module , slotItem . Slot , Hand . Blade1 ) )
{
_cassetteBL . WaitTransfer ( ModuleName . TrayRobot ) ;
return ;
}
}
}
}
}
private void MonitorTrayRobotCassettePickTask ( )
{
if ( ! _trayRobot . IsAvailable | | ! _cassetteBL . IsAvailable )
{
return ;
}
//各个腔体运行的石墨盘总数小于设定值
if ( GetCurrentTrayCount ( ) > = _maxTrayCount )
{
return ;
}
foreach ( var pm in _lstPms )
{
if ( _load . HasWafer ( 0 ) & & _load . CheckWaferNeedProcess ( 0 , pm . Module ) & & _load . NoTray ( 0 ) & & _trayRobot . NoTray ( 0 ) )
{
if ( CheckLoadWaferNeedCassetteTray ( pm . Module ) )
{
int usedForWhichPM = 0 ;
if ( pm = = _pm2 )
{
usedForWhichPM = 1 ;
}
SlotItem slotItem = GetTraySlot ( 8 , usedForWhichPM ) ;
if ( slotItem ! = null )
{
if ( _cassetteBL . IsReadyForPick ( ModuleName . TrayRobot , slotItem . Slot ) )
{
if ( _trayRobot . Pick ( slotItem . Module , slotItem . Slot , Hand . Blade1 ) )
{
_cassetteBL . WaitTransfer ( ModuleName . TrayRobot ) ;
return ;
}
}
}
}
}
}
}
private bool CheckLoadWaferNeedCassetteTray ( ModuleName pm )
{
if ( pm = = ModuleName . PM1 )
{
if ( ( _buffer . HasTray ( 0 ) & & _buffer . NoWafer ( 0 ) )
| | ( _pm1 . HasTray ( 0 ) & & _pm1 . NoWafer ( 0 ) ) )
{
return false ;
}
}
if ( pm = = ModuleName . PM2 )
{
if ( ( _buffer . HasTray ( 1 ) & & _buffer . NoWafer ( 1 ) )
| | ( _pm2 . HasTray ( 0 ) & & _pm2 . NoWafer ( 0 ) ) )
{
return false ;
}
}
List < Tuple < ModuleName , int > > modules = new List < Tuple < ModuleName , int > > ( )
{
new Tuple < ModuleName , int > ( ModuleName . Buffer , 0 ) ,
new Tuple < ModuleName , int > ( ModuleName . Buffer , 1 ) ,
new Tuple < ModuleName , int > ( ModuleName . Buffer , 2 ) ,
new Tuple < ModuleName , int > ( ModuleName . TMRobot , 0 ) ,
new Tuple < ModuleName , int > ( ModuleName . PM1 , 0 ) ,
new Tuple < ModuleName , int > ( ModuleName . PM2 , 0 ) ,
} ;
foreach ( var module in modules )
{
if ( CheckHasTrayAndNoWaferByModule ( module . Item1 , module . Item2 , pm ) )
{
return false ;
}
}
return true ;
}
/// <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 ;
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( module ) . GetWaferInfo ( slot ) ;
2023-03-03 15:42:13 +08:00
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 ;
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( module ) . GetWaferInfo ( slot ) ;
2023-03-03 15:42:13 +08:00
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 ;
2023-03-13 17:37:55 +08:00
var wafer = WaferManager . Instance . GetWafer ( module , slot ) ;
2023-03-03 15:42:13 +08:00
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 CheckHasTrayAndNoWaferByModule ( ModuleName moduleName , int slot , ModuleName pmModule )
{
var module = GetModule ( moduleName ) ;
if ( ( module . GetWaferInfo ( slot ) . TrayOriginSlot % 2 = = 0 & & pmModule = = ModuleName . PM1 )
| | ( module . GetWaferInfo ( slot ) . TrayOriginSlot % 2 = = 1 & & pmModule = = ModuleName . PM2 ) )
{
if ( module . HasTray ( slot ) & & module . NoWafer ( slot ) )
{
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 ( )
{
2023-03-13 17:37:55 +08:00
var wafer = _buffer . GetWaferInfo ( 0 ) ;
2023-03-03 15:42:13 +08:00
if ( wafer . IsEmpty )
{
return false ;
}
if ( wafer . ProcessJob = = null )
{
return false ;
}
ProcessJobInfo pj = _lstProcessJobs . Find ( x = > x . InnerId = = wafer . ProcessJob . InnerId ) ;
if ( pj = = null )
{
return false ;
}
return true ;
}
public bool CheckWaferProcessModuleIsAvailable ( ModuleName waferModule , int waferSlot )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( waferModule ) . GetWaferInfo ( waferSlot ) ;
2023-03-03 15:42:13 +08:00
if ( wafer . IsEmpty )
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 bool _ , out string _ ) )
return true ;
}
}
return false ;
}
private SlotItem GetWaferInJobQueue ( )
{
List < Tuple < ModuleName , int > > 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 ( int i = 0 ; i < slotCount ; i + + )
{
if ( _cassetteBL . HasTrayAndNotExceedProcessCount ( i ) & & i % 2 = = usedForWhichPM )
{
return new SlotItem ( ModuleName . CassBL , i ) ;
}
}
}
}
return null ;
}
private SlotItem GetTrayOrignSlot ( ModuleName module , int slot )
{
2023-03-13 17:37:55 +08:00
var wafer = GetModule ( module ) . GetWaferInfo ( slot ) ;
2023-03-03 15:42:13 +08:00
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(WaferInfo 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 ( )
{
int waferCount = 0 ;
if ( _load . HasWafer ( 0 ) )
{
waferCount + + ;
}
if ( _unload . HasWafer ( 0 ) )
{
waferCount + + ;
}
if ( _tmRobot . HasWafer ( 0 ) )
{
waferCount + + ;
}
foreach ( SchedulerPM pm in _lstPms )
{
if ( GetModule ( pm . Module ) . HasWafer ( 0 ) )
{
waferCount + + ;
}
}
for ( int i = 0 ; i < 3 ; i + + )
{
if ( _buffer . HasWafer ( i ) )
{
waferCount + + ;
}
}
return waferCount ;
}
private int GetRunWaferCount ( ModuleName processIn )
{
int waferCount = 0 ;
if ( _load . HasWafer ( 0 ) & & ( _load . CheckWaferNeedProcess ( 0 , processIn ) | | _load . GetWaferInfo ( 0 ) . SubstHists . Select ( x = > x . locationID ) . Contains ( processIn . ToString ( ) ) ) )
{
waferCount + + ;
}
if ( _unload . HasWafer ( 0 ) & & ( _unload . CheckWaferNeedProcess ( 0 , processIn ) | | _unload . GetWaferInfo ( 0 ) . SubstHists . Select ( x = > x . locationID ) . Contains ( processIn . ToString ( ) ) ) )
{
waferCount + + ;
}
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 ( int i = 0 ; i < 3 ; i + + )
{
if ( _buffer . HasWafer ( i ) & & ( _buffer . CheckWaferNeedProcess ( i , processIn ) | | _buffer . GetWaferInfo ( i ) . SubstHists . Select ( x = > x . locationID ) . Contains ( processIn . ToString ( ) ) ) )
{
waferCount + + ;
}
}
return waferCount ;
}
private int GetCurrentTrayCount ( )
{
int trayCount = 0 ;
if ( _load . HasTray ( 0 ) )
{
trayCount + + ;
}
if ( _unload . HasTray ( 0 ) )
{
trayCount + + ;
}
if ( _tmRobot . HasTray ( 0 ) )
{
trayCount + + ;
}
foreach ( SchedulerPM pm in _lstPms )
{
if ( GetModule ( pm . Module ) . HasTray ( 0 ) )
{
trayCount + + ;
}
}
for ( int i = 0 ; i < 3 ; i + + )
{
if ( _buffer . HasTray ( i ) )
{
trayCount + + ;
}
}
return trayCount ;
}
private int GetCurrentWaferCount ( )
{
int waferCountDiv = 0 ;
int 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;
}
public Result MonitorModuleError ( )
{
bool isModuleError = false ;
bool [ ] isPMError = new bool [ 2 ] ;
for ( int i = 0 ; i < isPMError . Length ; i + + )
{
isPMError [ i ] = false ;
}
if ( _tmRobot . IsError )
isModuleError = true ;
for ( int i = 0 ; i < _lstPms . Count ; i + + ) // PM出错, 不影响其他腔体的传片
{
if ( _lstPms [ i ] . IsError )
isPMError [ i ] = true ;
}
if ( isModuleError & & ! _isModuleErrorPrevious )
{
}
else if ( ! isModuleError & & _isModuleErrorPrevious )
{
Reset ( ) ;
}
for ( int i = 0 ; i < _lstPms . Count ; i + + )
{
if ( ! isPMError [ i ] & & _isPMErrorPrevious [ i ] )
{
_lstPms [ i ] . ResetTask ( ) ;
}
_isPMErrorPrevious [ i ] = isPMError [ i ] ;
}
_isModuleErrorPrevious = isModuleError ;
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 ) )
{
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 ( _aligner . HasWafer ( 0 ) )
{
reason = $"Aligner have wafer!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
if ( _waferRobot . HasWafer ( 0 ) )
{
reason = $"WaferRobot have wafer!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
if ( _load . HasWafer ( 0 ) )
{
reason = $"Load have wafer!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
if ( _load . HasTray ( 0 ) )
{
reason = $"Load have Tray!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
if ( _unload . HasWafer ( 0 ) )
{
reason = $"UnLoad have wafer!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
if ( _unload . HasTray ( 0 ) )
{
reason = $"UnLoad have Tray!" ;
EV . PostWarningLog ( LogSource , reason ) ;
return true ;
}
return false ;
}
}
private bool CheckWaferNeedProcess ( ModuleName module , int waferSlot , ModuleName processIn = ModuleName . System )
{
2023-03-13 17:37:55 +08:00
var wafer = WaferManager . Instance . GetWafer ( module , waferSlot ) ;
2023-03-03 15:42:13 +08:00
if ( wafer = = null )
{
return false ;
}
if ( wafer . IsEmpty )
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;
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 ) )
{
if ( processIn ! = ModuleName . System )
{
return stepModule = = processIn ? true : false ;
}
else
{
return true ;
}
}
}
}
return false ;
}
}
}