AutoTransfer.cs 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Xml;
  5. using Aitex.Core.Common;
  6. using Aitex.Core.RT.DataCenter;
  7. using Aitex.Core.RT.Device;
  8. using Aitex.Core.RT.Event;
  9. using Aitex.Core.RT.Log;
  10. using Aitex.Core.RT.RecipeCenter;
  11. using Aitex.Core.RT.Routine;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Sorter.Common;
  14. using MECF.Framework.Common.DBCore;
  15. using MECF.Framework.Common.Equipment;
  16. using MECF.Framework.Common.Jobs;
  17. using MECF.Framework.Common.Schedulers;
  18. using MECF.Framework.Common.SubstrateTrackings;
  19. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
  20. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
  21. using Virgo_DRT.Modules.Schedulers;
  22. using Virgo_DRT.Scheduler;
  23. namespace Virgo_DRT.Modules
  24. {
  25. public class AutoTransfer : TransferModule
  26. {
  27. private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
  28. private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
  29. //private Object _locker = new Object();
  30. private List<SchedulerPM> _lstPms = new List<SchedulerPM>();
  31. private List<SchedulerAligner> _lstBuffers = new List<SchedulerAligner>();
  32. private List<SchedulerLoadPort> _lstLps = new List<SchedulerLoadPort>();
  33. private const string LogSource = "Scheduler";
  34. private bool _isCycleMode;
  35. private int _cycleSetPoint = 0;
  36. private int _cycledCount = 0;
  37. private int _cycledWafer = 0;
  38. private bool _isInParallelMode;
  39. private Dictionary<ModuleName, ModuleName> _mapLpPm = new Dictionary<ModuleName, ModuleName>();
  40. private Dictionary<ModuleName, ModuleName> _mapLpAligner = new Dictionary<ModuleName, ModuleName>();
  41. private List<ModuleName> _mapTarget = new List<ModuleName>();
  42. public bool HasJobRunning
  43. {
  44. get { return _lstControlJobs.Count > 0; }
  45. }
  46. public AutoTransfer()
  47. {
  48. if (SC.GetValue<bool>("System.PMAIsInstalled"))
  49. _lstPms.Add(_pma);
  50. if (SC.GetValue<bool>("System.PMBIsInstalled"))
  51. _lstPms.Add(_pmb);
  52. _lstBuffers.AddRange(new[] { _buffer1, _buffer2 });
  53. _lstLps.AddRange(new[] { _lp1, _lp2 });
  54. DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
  55. DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer);
  56. DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
  57. DATA.Subscribe("Scheduler.PjIdList", () => Array.ConvertAll(_lstProcessJobs.ToArray(), x => x.InnerId.ToString()).ToList());
  58. DATA.Subscribe("LP1.LocalJobName", () =>
  59. {
  60. if (_lstControlJobs.Exists(x => x.Name == "CJ_Local_LP1"))
  61. return "CJ_Local_LP1";
  62. return "";
  63. });
  64. DATA.Subscribe("LP1.LocalJobStatus", () =>
  65. {
  66. var jb = _lstControlJobs.Find(x => x.Name == "CJ_Local_LP1");
  67. if (jb != null)
  68. return jb.State.ToString();
  69. return "";
  70. });
  71. DATA.Subscribe("LP2.LocalJobName", () =>
  72. {
  73. if (_lstControlJobs.Exists(x => x.Name == "CJ_Local_LP2"))
  74. return "CJ_Local_LP2";
  75. return "";
  76. });
  77. DATA.Subscribe("LP2.LocalJobStatus", () =>
  78. {
  79. var jb = _lstControlJobs.Find(x => x.Name == "CJ_Local_LP2");
  80. if (jb != null)
  81. return jb.State.ToString();
  82. return "";
  83. });
  84. }
  85. public void Clear()
  86. {
  87. _efemRobot.ResetTask();
  88. foreach (var pm in _lstPms)
  89. {
  90. pm.ResetTask();
  91. }
  92. foreach (var buffer in _lstBuffers)
  93. {
  94. buffer.ResetTask();
  95. }
  96. foreach (var lp in _lstLps)
  97. {
  98. lp.ResetTask();
  99. }
  100. _lstControlJobs.Clear();
  101. _lstProcessJobs.Clear();
  102. _mapLpAligner.Clear();
  103. _mapLpPm.Clear();
  104. _isInParallelMode = false;
  105. _mapTarget.Clear();
  106. }
  107. #region Job Management
  108. public void CreateJob(Dictionary<string, object> param)
  109. {
  110. string[] slotSequence = (string[])param["SlotSequence"];
  111. string jobId = (string)param["JobId"];
  112. string module = (string)param["Module"];
  113. bool autoStart = (bool)param["AutoStart"];
  114. if (slotSequence.Length != 25)
  115. {
  116. EV.PostWarningLog(LogSource, $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 25");
  117. return;
  118. }
  119. if (!ModuleHelper.IsLoadPort(ModuleHelper.Converter(module)))
  120. {
  121. EV.PostWarningLog(LogSource, $"{module} should be LoadPort");
  122. return;
  123. }
  124. if (string.IsNullOrEmpty(jobId))
  125. {
  126. jobId = "CJ_Local_" + module;
  127. }
  128. if (_lstControlJobs.Exists(x => x.Name == jobId))
  129. {
  130. EV.PostWarningLog(LogSource, $"{jobId} already created");
  131. return;
  132. }
  133. SchedulerLoadPort lp = GetModule(module) as SchedulerLoadPort;
  134. if (!lp.CheckReadyRunJob())
  135. {
  136. EV.PostWarningLog(LogSource, $"{module} not ready");
  137. return;
  138. }
  139. ControlJobInfo cj = new ControlJobInfo();
  140. cj.Name = jobId;
  141. cj.Module = module;
  142. cj.SetState(EnumControlJobState.WaitingForStart);
  143. Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
  144. Dictionary<string, List<Tuple<ModuleName, int>>> seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
  145. Dictionary<string, string> indexSequence = new Dictionary<string, string>();
  146. bool enableGroupBySequence = SC.GetValue<bool>("Scheduler.GroupWaferBySequence");
  147. for (int i = 0; i < 25; i++)
  148. {
  149. if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
  150. continue;
  151. string groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString();
  152. indexSequence[groupName] = slotSequence[i];
  153. if (!seqSlot.ContainsKey(groupName))
  154. {
  155. seqSlot[groupName] = new bool[25];
  156. }
  157. if (!seqSlotWafers.ContainsKey(groupName))
  158. {
  159. seqSlotWafers[groupName] = new List<Tuple<ModuleName, int>>();
  160. }
  161. seqSlot[groupName][i] = true;
  162. if (!WaferManager.Instance.CheckHasWafer(module, i))
  163. {
  164. EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} not in the carrier");
  165. return;
  166. }
  167. if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), i, WaferStatus.Normal))
  168. {
  169. EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Status}");
  170. return;
  171. }
  172. if (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).ProcessState != EnumWaferProcessStatus.Idle)
  173. {
  174. EV.PostWarningLog(LogSource, $"job wafer: {module} slot {i + 1} process status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).ProcessState}");
  175. return;
  176. }
  177. //特殊场景,3寸片第一片不能取放
  178. if (i ==0 && (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Size==WaferSize.WS3))
  179. {
  180. EV.PostWarningLog(LogSource, $"job wafer: {module} 3 inch slot {i + 1} is not supported.");
  181. return;
  182. }
  183. seqSlotWafers[groupName].Add(Tuple.Create(ModuleHelper.Converter(module), i));
  184. }
  185. if (seqSlotWafers.Count == 0)
  186. {
  187. EV.PostWarningLog(LogSource, $"job has not assign wafer");
  188. return;
  189. }
  190. List<ProcessJobInfo> pjs = new List<ProcessJobInfo>();
  191. string[] seqs = seqSlot.Keys.ToArray();
  192. for (int i = 0; i < seqs.Length; i++)
  193. {
  194. ProcessJobInfo pj = new ProcessJobInfo();
  195. pj.Name = jobId + "_" + (i + 1);
  196. pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]);
  197. pj.ControlJobName = cj.Name;
  198. pj.SlotWafers = seqSlotWafers[seqs[i]];
  199. pj.SetState(EnumProcessJobState.Queued);
  200. if (!CheckSequencePmReady(pj.Sequence, out string reason))
  201. {
  202. EV.PostWarningLog(LogSource, $"no valid chamber for the {reason}");
  203. return;
  204. }
  205. if (!SC.GetValue<bool>("System.IsATMMode") && !CheckSequenceRecipeFileValid(pj.Sequence, out reason))
  206. {
  207. EV.PostWarningLog(LogSource, $"recipe file not valid in the sequence, {reason}");
  208. return;
  209. }
  210. if (!SetSequenceTemperatureInfo(pj.Sequence, out reason))
  211. {
  212. EV.PostWarningLog(LogSource, $"sequence recipe temperature not valid, {reason}");
  213. return;
  214. }
  215. pjs.Add(pj);
  216. }
  217. foreach (var pj in pjs)
  218. {
  219. cj.ProcessJobNameList.Add(pj.Name);
  220. _lstProcessJobs.Add(pj);
  221. }
  222. _lstControlJobs.Add(cj);
  223. UpdateParallelMode();
  224. }
  225. internal void StopJob(string jobName)
  226. {
  227. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
  228. if (cj == null)
  229. {
  230. EV.PostWarningLog(LogSource, $"stop job rejected, not found job with id {jobName}");
  231. return;
  232. }
  233. foreach (var pj in _lstProcessJobs)
  234. {
  235. if (pj.ControlJobName == cj.Name)
  236. {
  237. pj.SetState(EnumProcessJobState.Stopping);
  238. }
  239. }
  240. }
  241. internal void AbortJob(string jobName)
  242. {
  243. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
  244. if (cj == null)
  245. {
  246. EV.PostWarningLog(LogSource, $"abort job rejected, not found job with id {jobName}");
  247. return;
  248. }
  249. List<ProcessJobInfo> pjAbortList = new List<ProcessJobInfo>();
  250. foreach (var pj in _lstProcessJobs)
  251. {
  252. if (pj.ControlJobName == cj.Name)
  253. {
  254. pj.SetState(EnumProcessJobState.Aborting);
  255. pjAbortList.Add(pj);
  256. int unprocessed = 0;
  257. int aborted = 0;
  258. WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
  259. foreach (var waferInfo in wafers)
  260. {
  261. waferInfo.ProcessJob = null;
  262. waferInfo.NextSequenceStep = 0;
  263. if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
  264. unprocessed++;
  265. }
  266. JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
  267. }
  268. }
  269. foreach (var pj in pjAbortList)
  270. {
  271. _lstProcessJobs.Remove(pj);
  272. }
  273. _lstControlJobs.Remove(cj);
  274. }
  275. public void ResumeJob(string jobName)
  276. {
  277. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
  278. if (cj == null)
  279. {
  280. EV.PostWarningLog(LogSource, $"resume job rejected, not found job with id {jobName}");
  281. return;
  282. }
  283. if (cj.State == EnumControlJobState.Paused)
  284. {
  285. cj.SetState(EnumControlJobState.Executing);
  286. }
  287. }
  288. internal void StartJob(string jobName)
  289. {
  290. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
  291. if (cj == null)
  292. {
  293. EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}");
  294. return;
  295. }
  296. if (cj.State == EnumControlJobState.WaitingForStart)
  297. {
  298. cj.SetState(EnumControlJobState.Executing);
  299. }
  300. }
  301. internal void PauseJob(string jobName)
  302. {
  303. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
  304. if (cj == null)
  305. {
  306. EV.PostWarningLog(LogSource, $"pause job rejected, not found job with id {jobName}");
  307. return;
  308. }
  309. if (cj.State == EnumControlJobState.Executing)
  310. {
  311. cj.SetState(EnumControlJobState.Paused);
  312. }
  313. }
  314. internal void Map(string moduleName)
  315. {
  316. ModuleName target = ModuleHelper.Converter(moduleName);
  317. if (!ModuleHelper.IsLoadPort(target))
  318. {
  319. EV.PostWarningLog(LogSource, $"Invalid map target {target}");
  320. return;
  321. }
  322. if (!_mapTarget.Contains(target))
  323. {
  324. _mapTarget.Add(target);
  325. }
  326. }
  327. #endregion Job Management
  328. public Result Start(params object[] objs)
  329. {
  330. _isCycleMode = SC.GetValue<bool>("System.IsCycleMode");
  331. _cycleSetPoint = _isCycleMode ? SC.GetValue<int>("System.CycleCount") : 0;
  332. _cycledWafer = 0;
  333. _cycledCount = 0;
  334. bool hasPmOnline = false;
  335. foreach (var schedulerPm in _lstPms)
  336. {
  337. if (schedulerPm.IsAvailable)
  338. {
  339. schedulerPm.SetPMAuto();
  340. hasPmOnline = true;
  341. continue;
  342. }
  343. }
  344. if (!hasPmOnline)
  345. {
  346. EV.PostWarningLog("Scheduler", "can not change to auto mode, at least one process chamber be online");
  347. return Result.FAIL;
  348. }
  349. return Result.RUN;
  350. }
  351. public Result Monitor()
  352. {
  353. ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
  354. if (cjActive != null)
  355. {
  356. MonitorModuleTasks();
  357. }
  358. MonitorJobTasks();
  359. return Result.RUN;
  360. }
  361. #region Job task
  362. public Result MonitorJobTasks()
  363. {
  364. UpdateParallelMode();
  365. UpdateProcessJobStatus();
  366. UpdateControlJobStatus();
  367. StartNewJob();
  368. return Result.RUN;
  369. }
  370. private void UpdateParallelMode()
  371. {
  372. bool isParallel = SC.GetValue<bool>("Scheduler.IsRunInParallelMode");
  373. bool bothLpHasJob = true;
  374. Dictionary<ModuleName, Dictionary<ModuleName, float>> lpNeededPmTemperature = new Dictionary<ModuleName, Dictionary<ModuleName, float>>();
  375. foreach (var lp in _lstLps)
  376. {
  377. var cj = _lstControlJobs.Find(x => x.Module == lp.Module.ToString());
  378. bothLpHasJob = bothLpHasJob && (cj != null);
  379. if (cj != null)
  380. {
  381. lpNeededPmTemperature[lp.Module] = new Dictionary<ModuleName, float>();
  382. var pj = _lstProcessJobs.FirstOrDefault(x => x.ControlJobName == cj.Name);
  383. if (pj != null)
  384. {
  385. var seq = pj.Sequence;
  386. for (int i = 0; i < seq.Steps.Count; i++)
  387. {
  388. SequenceStepInfo stepInfo = seq.Steps[i];
  389. foreach (var module in stepInfo.StepModules)
  390. {
  391. if (ModuleHelper.IsPm(module) && !lpNeededPmTemperature[lp.Module].ContainsKey(module))
  392. {
  393. lpNeededPmTemperature[lp.Module][module] = (float) seq.Steps[i]
  394. .StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"];
  395. }
  396. }
  397. }
  398. }
  399. }
  400. }
  401. bool needSamePm = false;
  402. ModuleName pmSource = ModuleName.System;
  403. foreach (var pmNeeded in lpNeededPmTemperature)
  404. {
  405. if (pmNeeded.Value.Count == 1)
  406. {
  407. var source = pmNeeded.Value.Keys.First();
  408. if (source != pmSource)
  409. {
  410. pmSource = source;
  411. }
  412. else
  413. {
  414. needSamePm = true;
  415. break;
  416. }
  417. }
  418. }
  419. var needParallel = isParallel && bothLpHasJob && !needSamePm;
  420. if (needParallel != _isInParallelMode)
  421. {
  422. _isInParallelMode = needParallel;
  423. if (needParallel)
  424. {
  425. //aligner固定不做逻辑
  426. _mapLpAligner[ModuleName.LP1] = ModuleName.Aligner1;
  427. _mapLpAligner[ModuleName.LP2] = ModuleName.Aligner2;
  428. bool assigned =false;
  429. foreach (var pmNeeded in lpNeededPmTemperature)
  430. {
  431. if (pmNeeded.Value.Count == 1)
  432. {
  433. _mapLpPm[pmNeeded.Key] = pmNeeded.Value.Keys.First();
  434. var anotherLp = pmNeeded.Key == ModuleName.LP1 ? ModuleName.LP2 : ModuleName.LP1;
  435. var anotherPm = _mapLpPm[pmNeeded.Key]== ModuleName.PMA ? ModuleName.PMB : ModuleName.PMA;
  436. _mapLpPm[anotherLp] = anotherPm;
  437. assigned = true;
  438. break;
  439. }
  440. }
  441. if (!assigned)
  442. {
  443. _mapLpPm[ModuleName.LP1] = ModuleName.PMA;
  444. _mapLpPm[ModuleName.LP2] = ModuleName.PMB;
  445. float pmaTemp = ((SchedulerPM) GetModule(ModuleName.PMA.ToString())).Temperature;
  446. float pmbTemp = ((SchedulerPM)GetModule(ModuleName.PMB.ToString())).Temperature;
  447. float tempCurrent = Math.Abs(lpNeededPmTemperature[ModuleName.LP1][ModuleName.PMA] - pmaTemp)
  448. + Math.Abs(lpNeededPmTemperature[ModuleName.LP2][ModuleName.PMB] - pmbTemp);
  449. float tempAnother = Math.Abs(lpNeededPmTemperature[ModuleName.LP1][ModuleName.PMB] - pmbTemp)
  450. + Math.Abs(lpNeededPmTemperature[ModuleName.LP2][ModuleName.PMA] - pmaTemp);
  451. if (tempAnother < tempCurrent)
  452. {
  453. _mapLpPm[ModuleName.LP1] = ModuleName.PMB;
  454. _mapLpPm[ModuleName.LP2] = ModuleName.PMA;
  455. }
  456. }
  457. }
  458. }
  459. }
  460. private void UpdateProcessJobStatus()
  461. {
  462. foreach (var pj in _lstProcessJobs)
  463. {
  464. if (pj.State == EnumProcessJobState.Processing)
  465. {
  466. if (CheckAllWaferReturned(pj, true) )
  467. {
  468. pj.SetState(EnumProcessJobState.ProcessingComplete);
  469. JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
  470. }
  471. }
  472. else if (pj.State == EnumProcessJobState.Stopping)
  473. {
  474. if (CheckAllWaferReturned(pj, false) )
  475. {
  476. pj.SetState(EnumProcessJobState.ProcessingComplete);
  477. JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
  478. }
  479. }
  480. }
  481. }
  482. private void UpdateControlJobStatus()
  483. {
  484. if (_lstControlJobs.Count == 0)
  485. return;
  486. bool allControlJobComplete = true;
  487. List<ControlJobInfo> cjRemoveList = new List<ControlJobInfo>();
  488. foreach (var cj in _lstControlJobs)
  489. {
  490. if (cj.State == EnumControlJobState.Executing)
  491. {
  492. bool allPjCompleted = true;
  493. foreach (var pjName in cj.ProcessJobNameList)
  494. {
  495. var pj = _lstProcessJobs.Find(x => x.Name == pjName);
  496. if (pj == null)
  497. {
  498. LOG.Error($"Not find pj named {pjName} in {cj.Name}");
  499. continue;
  500. }
  501. if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
  502. {
  503. allPjCompleted = false;
  504. break;
  505. }
  506. }
  507. if (allPjCompleted)
  508. {
  509. cj.SetState(EnumControlJobState.Completed);
  510. }
  511. }
  512. LoadportCassetteState state = (LoadportCassetteState)DATA.Poll($"{cj.Module}.CassetteState");
  513. if (cj.State == EnumControlJobState.Completed && state != LoadportCassetteState.Normal)
  514. {
  515. cjRemoveList.Add(cj);
  516. }
  517. allControlJobComplete = allControlJobComplete && cj.State == EnumControlJobState.Completed;
  518. }
  519. if (_isCycleMode && _cycledCount < _cycleSetPoint)
  520. {
  521. int countPerCycle = 0;
  522. int countProcessed = 0;
  523. foreach (var pj in _lstProcessJobs)
  524. {
  525. foreach (var pjSlotWafer in pj.SlotWafers)
  526. {
  527. countPerCycle++;
  528. WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
  529. if (!wafer.IsEmpty && !CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
  530. countProcessed++;
  531. }
  532. }
  533. _cycledWafer = _cycledCount * countPerCycle + countProcessed;
  534. if (allControlJobComplete)
  535. {
  536. _cycledCount++;
  537. if (_cycledCount < _cycleSetPoint)
  538. {
  539. foreach (var cj in _lstControlJobs)
  540. {
  541. cj.SetState(EnumControlJobState.Executing);
  542. }
  543. foreach (var pj in _lstProcessJobs)
  544. {
  545. pj.SetState(EnumProcessJobState.Queued);
  546. pj.InnerId = Guid.NewGuid();
  547. foreach (var pjSlotWafer in pj.SlotWafers)
  548. {
  549. WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
  550. wafer.ProcessJob = null;
  551. wafer.NextSequenceStep = 0;
  552. wafer.ProcessState = EnumWaferProcessStatus.Idle;
  553. }
  554. }
  555. }
  556. }
  557. }
  558. foreach (var cj in cjRemoveList)
  559. {
  560. List<ProcessJobInfo> pjRemoveList = new List<ProcessJobInfo>();
  561. foreach (var pj in _lstProcessJobs)
  562. {
  563. if (pj.ControlJobName == cj.Name)
  564. pjRemoveList.Add(pj);
  565. }
  566. foreach (var pj in pjRemoveList)
  567. {
  568. _lstProcessJobs.Remove(pj);
  569. }
  570. _lstControlJobs.Remove(cj);
  571. }
  572. if (cjRemoveList.Count > 0)
  573. {
  574. UpdateParallelMode();
  575. }
  576. }
  577. private void StartNewJob()
  578. {
  579. ControlJobInfo cjActived = null;
  580. foreach (var cj in _lstControlJobs)
  581. {
  582. if (cj.State == EnumControlJobState.Executing)
  583. {
  584. cjActived = cj;
  585. foreach (var pjName in cjActived.ProcessJobNameList)
  586. {
  587. var pj = _lstProcessJobs.Find(x => x.Name == pjName);
  588. if (pj == null)
  589. {
  590. LOG.Error($"Not find pj named {pjName} in {cjActived.Name}");
  591. continue;
  592. }
  593. if (pj.State == EnumProcessJobState.Queued)
  594. {
  595. ActiveProcessJob(pj);
  596. break;
  597. }
  598. }
  599. if (!_isInParallelMode)
  600. break;
  601. }
  602. }
  603. }
  604. private bool ActiveProcessJob(ProcessJobInfo pj)
  605. {
  606. //pm is ok
  607. if (!CheckSequencePmReady( pj.Sequence, out string reason))
  608. {
  609. EV.PostWarningLog(LogSource, $"can not active {pj.Name}, {reason}");
  610. return false;
  611. }
  612. foreach (var pjSlotWafer in pj.SlotWafers)
  613. {
  614. WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
  615. wafer.ProcessJob = pj;
  616. wafer.NextSequenceStep = 0;
  617. WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString());
  618. }
  619. ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName);
  620. CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
  621. JobDataRecorder.StartPJ(pj.InnerId.ToString(), carrier.InnerId.ToString(), cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
  622. pj.SetState(EnumProcessJobState.Processing);
  623. return true;
  624. }
  625. #endregion Job task
  626. #region Module task
  627. public Result MonitorModuleTasks()
  628. {
  629. MonitorPMTask();
  630. MonitorEfemRobotTask();
  631. MonitorBufferTask();
  632. return Result.RUN;
  633. }
  634. private void MonitorBufferTask()
  635. {
  636. foreach (var schedulerBuffer in _lstBuffers)
  637. {
  638. if (!schedulerBuffer.IsAvailable
  639. || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0)
  640. )
  641. continue;
  642. if (CheckWaferNextStepIsAlign(schedulerBuffer.Module, 0))
  643. {
  644. WaferInfo wafer = WaferManager.Instance.GetWafers(schedulerBuffer.Module)[0];
  645. var job = wafer.ProcessJob;
  646. GetWaferSequenceAlignTime(schedulerBuffer.Module, 0, out float time);
  647. if (schedulerBuffer.Align(time))
  648. {
  649. wafer.NextSequenceStep++;
  650. }
  651. }
  652. }
  653. }
  654. private void MonitorEfemRobotTask()
  655. {
  656. if (!_efemRobot.IsAvailable)
  657. return;
  658. //efem robot is idle, release all the target
  659. foreach (var pm in _lstPms)
  660. {
  661. if (pm.IsWaitTransfer(ModuleName.EfemRobot))
  662. {
  663. pm.PostTransfer(ModuleName.EfemRobot);
  664. }
  665. }
  666. foreach (var buffer in _lstBuffers)
  667. {
  668. if (buffer.IsWaitTransfer(ModuleName.EfemRobot))
  669. {
  670. buffer.PostTransfer(ModuleName.EfemRobot);
  671. }
  672. }
  673. foreach (var lp in _lstLps)
  674. {
  675. if (lp.IsWaitTransfer(ModuleName.EfemRobot))
  676. {
  677. lp.PostTransfer(ModuleName.EfemRobot);
  678. }
  679. }
  680. MonitorEfemRobotMapTask();
  681. if (!_efemRobot.IsAvailable)
  682. return;
  683. MonitorEfemRobotPMTask();
  684. if (!_efemRobot.IsAvailable)
  685. return;
  686. MonitorEfemRobotBufferTask();
  687. if (!_efemRobot.IsAvailable)
  688. return;
  689. MonitorEfemRobotLoadPortTask();
  690. }
  691. private void MonitorEfemRobotMapTask()
  692. {
  693. if (!_efemRobot.IsAvailable)
  694. return;
  695. if (_mapTarget.Count > 0)
  696. {
  697. ModuleName first = _mapTarget[0];
  698. SchedulerLoadPort lp = GetModule(first.ToString()) as SchedulerLoadPort;
  699. if (lp != null && lp.IsAvailable)
  700. {
  701. _efemRobot.Map(first);
  702. _mapTarget.Remove(first);
  703. }
  704. }
  705. }
  706. private void MonitorEfemRobotPMTask()
  707. {
  708. if (!_efemRobot.IsAvailable)
  709. return;
  710. //place to pm
  711. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
  712. CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && !CheckWaferNeedAlign(ModuleName.EfemRobot,0))
  713. {
  714. foreach (var pm in _lstPms)
  715. {
  716. if (!pm.IsAvailable || !WaferManager.Instance.CheckNoWafer(pm.Module, 0) )
  717. continue;
  718. if (_isInParallelMode && GetWaferCountOutofLP(ModuleName.LP1) <= 1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1)
  719. {
  720. int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginStation;
  721. if (origin == (int)ModuleName.LP1 && _mapLpPm[ModuleName.LP1] != pm.Module)
  722. continue;
  723. if (origin == (int)ModuleName.LP2 && _mapLpPm[ModuleName.LP2] != pm.Module)
  724. continue;
  725. }
  726. if ( !pm.IsReadyForPlace(ModuleName.EfemRobot, 0))
  727. continue;
  728. if (_efemRobot.Place(pm.Module, 0, Hand.Blade1))
  729. {
  730. pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0);
  731. return;
  732. }
  733. }
  734. }
  735. if (!_efemRobot.IsAvailable)
  736. return;
  737. //pick from pm
  738. if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) )
  739. {
  740. ModuleName pickPm = ModuleName.System;
  741. int waferOriginSlot = int.MaxValue;
  742. foreach (var schedulerPm in _lstPms)
  743. {
  744. if (!schedulerPm.IsAvailable
  745. || WaferManager.Instance.CheckNoWafer(schedulerPm.Module, 0)
  746. || CheckWaferNeedProcess(schedulerPm.Module, 0, schedulerPm.Module) )
  747. continue;
  748. WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
  749. bool pickAllowed = CheckVacuumWaferHasAvailableTarget(schedulerPm.Module, 0);
  750. if (pickAllowed)
  751. {
  752. int slot = wafer.OriginSlot;
  753. if (slot < waferOriginSlot)
  754. {
  755. waferOriginSlot = slot;
  756. pickPm = schedulerPm.Module;
  757. }
  758. }
  759. }
  760. if (pickPm != ModuleName.System)
  761. {
  762. SchedulerModule pm = GetModule(pickPm.ToString());
  763. if (pm.IsReadyForPick(ModuleName.EfemRobot, 0))
  764. {
  765. if (_efemRobot.Pick(pm.Module, 0, Hand.Blade1))
  766. {
  767. pm.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0);
  768. return;
  769. }
  770. }
  771. }
  772. }
  773. }
  774. private void MonitorEfemRobotLoadPortTask()
  775. {
  776. if (!_efemRobot.IsAvailable)
  777. return;
  778. //pick
  779. if (_isInParallelMode)
  780. {
  781. int outWaferLp1 = GetWaferCountOutofLP(ModuleName.LP1);
  782. int outWaferLp2 = GetWaferCountOutofLP(ModuleName.LP2);
  783. if (outWaferLp1 <= GetMaxOutWafer() && outWaferLp2 <= GetMaxOutWafer())
  784. {
  785. foreach (var lp in _lstLps)
  786. {
  787. if (GetWaferCountOutofLP(lp.Module) >= GetMaxOutWafer())
  788. continue;
  789. if (GetWaferCountInJobQueue(lp.Module) > 0 && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
  790. {
  791. SlotItem position = GetNextWaferInJobQueue(lp.Module);
  792. if (position != null && CheckWaferPmTemperatureIsOk(position.Module, position.Slot))
  793. {
  794. if (lp.IsReadyForPick(ModuleName.EfemRobot, position.Slot))
  795. {
  796. if (_efemRobot.Pick(position.Module, position.Slot, Hand.Blade1))
  797. {
  798. lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, position.Slot);
  799. return;
  800. }
  801. }
  802. }
  803. }
  804. }
  805. }
  806. }
  807. else
  808. {
  809. if (GetWaferCountOutofLP(ModuleName.System) < GetMaxOutWafer() && GetWaferCountInJobQueue(ModuleName.System) > 0 &&
  810. WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
  811. {
  812. SlotItem position = GetNextWaferInJobQueue(ModuleName.System);
  813. if (position != null && CheckWaferPmTemperatureIsOk(position.Module, position.Slot))
  814. {
  815. SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(position.Module.ToString());
  816. if (lp.IsReadyForPick(ModuleName.EfemRobot, position.Slot))
  817. {
  818. if (_efemRobot.Pick(position.Module, position.Slot, Hand.Blade1))
  819. {
  820. lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, position.Slot);
  821. return;
  822. }
  823. }
  824. }
  825. }
  826. }
  827. if (!_efemRobot.IsAvailable)
  828. return;
  829. //place
  830. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
  831. !CheckWaferNeedProcess(ModuleName.EfemRobot, 0))
  832. {
  833. SlotItem destination = GetWaferReturnLoadPort(_efemRobot.Module, 0);
  834. if (destination != null)
  835. {
  836. SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(destination.Module.ToString());
  837. if (lp.IsReadyForPlace(ModuleName.EfemRobot, destination.Slot))
  838. {
  839. if (_efemRobot.Place(destination.Module, destination.Slot, Hand.Blade1))
  840. {
  841. lp.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, destination.Slot);
  842. return;
  843. }
  844. }
  845. }
  846. }
  847. }
  848. private void MonitorEfemRobotBufferTask()
  849. {
  850. if (!_efemRobot.IsAvailable)
  851. return;
  852. //place to buffer
  853. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
  854. CheckWaferNeedAlign(ModuleName.EfemRobot, 0))
  855. {
  856. foreach (var buffer in _lstBuffers)
  857. {
  858. if (!buffer.IsAvailable || !WaferManager.Instance.CheckNoWafer(buffer.Module, 0))
  859. continue;
  860. if (_isInParallelMode && GetWaferCountOutofLP(ModuleName.LP1)<=1 && GetWaferCountOutofLP(ModuleName.LP2) <= 1)
  861. {
  862. int origin = WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginStation;
  863. if (origin == (int)ModuleName.LP1 && _mapLpAligner[ModuleName.LP1] != buffer.Module)
  864. continue;
  865. if (origin == (int)ModuleName.LP2 && _mapLpAligner[ModuleName.LP2] != buffer.Module)
  866. continue;
  867. }
  868. if (!buffer.IsReadyForPlace(ModuleName.EfemRobot, 0))
  869. continue;
  870. if (_efemRobot.Place(buffer.Module, 0, Hand.Blade1))
  871. {
  872. buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0);
  873. return;
  874. }
  875. }
  876. }
  877. if (!_efemRobot.IsAvailable)
  878. return;
  879. //pick from buffer
  880. if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
  881. {
  882. ModuleName pickBuffer = ModuleName.System;
  883. int waferOriginSlot = int.MaxValue;
  884. foreach (var schedulerBuffer in _lstBuffers)
  885. {
  886. if (!schedulerBuffer.IsAvailable
  887. || WaferManager.Instance.CheckNoWafer(schedulerBuffer.Module, 0)
  888. || CheckWaferNeedAlign(schedulerBuffer.Module, 0 ))
  889. continue;
  890. WaferInfo wafer = WaferManager.Instance.GetWafer(schedulerBuffer.Module, 0);
  891. bool pickAllowed = CheckBufferWaferHasAvailableTarget(schedulerBuffer.Module, 0);
  892. if (pickAllowed)
  893. {
  894. int slot = wafer.OriginSlot;
  895. if (slot < waferOriginSlot)
  896. {
  897. waferOriginSlot = slot;
  898. pickBuffer = schedulerBuffer.Module;
  899. }
  900. }
  901. }
  902. if (pickBuffer != ModuleName.System)
  903. {
  904. SchedulerModule buffer = GetModule(pickBuffer.ToString());
  905. if (buffer.IsReadyForPick(ModuleName.EfemRobot, 0))
  906. {
  907. if (_efemRobot.Pick(buffer.Module, 0, Hand.Blade1))
  908. {
  909. buffer.WaitTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0);
  910. return;
  911. }
  912. }
  913. }
  914. }
  915. }
  916. private void MonitorPMTask()
  917. {
  918. bool robotWaferAssigned = false;
  919. bool aligner1WaferAssigned = false;
  920. bool aligner2WaferAssigned = false;
  921. foreach (var pm in _lstPms)
  922. {
  923. if (!pm.IsAvailable)
  924. continue;
  925. if (WaferManager.Instance.CheckHasWafer(pm.Module, 0))
  926. {
  927. if (CheckWaferNeedProcess(pm.Module, 0, pm.Module))
  928. {
  929. WaferInfo wafer = WaferManager.Instance.GetWafer(pm.Module, 0);
  930. var recipeName = pm.Module == ModuleName.PMA
  931. ? wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PMARecipe"]
  932. : wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["PMBRecipe"];
  933. if (pm.Process((string)recipeName, false, true))
  934. {
  935. WaferManager.Instance.GetWafer(pm.Module, 0).NextSequenceStep++;
  936. continue;
  937. }
  938. }
  939. else
  940. {
  941. if (!pm.IsReadyForPick(ModuleName.EfemRobot, 0))
  942. {
  943. pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0);
  944. }
  945. }
  946. }
  947. else //no wafer
  948. {
  949. if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.Aligner1, 0)
  950. && WaferManager.Instance.CheckNoWafer(ModuleName.Aligner2, 0) )
  951. {
  952. ModuleName source = ModuleName.System;
  953. if (_isInParallelMode)
  954. {
  955. foreach (var moduleName in _mapLpPm)
  956. {
  957. if (moduleName.Value == pm.Module)
  958. source = moduleName.Key;
  959. }
  960. }
  961. SlotItem item = GetNextWaferInJobQueue(source);
  962. if (item != null && CheckWaferNeedProcess(item.Module, item.Slot, pm.Module))
  963. {
  964. if (GetWaferTemperatureSetInRecipe(item.Module, item.Slot, pm.Module, out float temp) && !pm.IsTemperatureReady(temp))
  965. {
  966. pm.Preheating(temp);
  967. continue;
  968. }
  969. }
  970. }
  971. if (!pm.IsAvailable)
  972. continue;
  973. if (!robotWaferAssigned && CheckWaferNeedProcess(ModuleName.EfemRobot, 0, pm.Module) && CheckWaferNextProcessIn(ModuleName.EfemRobot, 0, pm.Module))
  974. {
  975. robotWaferAssigned = true;
  976. GetWaferTemperatureSetInRecipe(ModuleName.EfemRobot, 0, pm.Module, out float temp);
  977. if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0) || !pm.IsTemperatureReady(temp))
  978. {
  979. pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp);
  980. }
  981. }
  982. if (!pm.IsAvailable)
  983. continue;
  984. if (!aligner1WaferAssigned && CheckWaferNeedProcess(ModuleName.Aligner1, 0, pm.Module))
  985. {
  986. aligner1WaferAssigned = true;
  987. GetWaferTemperatureSetInRecipe(ModuleName.Aligner1, 0, pm.Module, out float temp);
  988. if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0) || !pm.IsTemperatureReady(temp))
  989. {
  990. pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp);
  991. }
  992. }
  993. if (!pm.IsAvailable)
  994. continue;
  995. if (!aligner2WaferAssigned && CheckWaferNeedProcess(ModuleName.Aligner2, 0, pm.Module))
  996. {
  997. aligner2WaferAssigned = true;
  998. GetWaferTemperatureSetInRecipe(ModuleName.Aligner2, 0, pm.Module, out float temp);
  999. if (!pm.IsReadyForPlace(ModuleName.EfemRobot, 0) || !pm.IsTemperatureReady(temp))
  1000. {
  1001. pm.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0, temp);
  1002. }
  1003. }
  1004. if (!pm.IsAvailable)
  1005. continue;
  1006. }
  1007. }
  1008. }
  1009. #endregion Module task
  1010. #region Logic Check
  1011. private bool CheckSequencePmReady(SequenceInfo seq, out string reason)
  1012. {
  1013. for (int i = 0; i < seq.Steps.Count; i++)
  1014. {
  1015. SequenceStepInfo stepInfo = seq.Steps[i];
  1016. bool hasPm = false;
  1017. foreach (var module in stepInfo.StepModules)
  1018. {
  1019. if (ModuleHelper.IsPm(module))
  1020. {
  1021. PM pm = DEVICE.GetDevice<PM>(module.ToString());
  1022. if (pm.IsInstalled)
  1023. {
  1024. hasPm = true;
  1025. break;
  1026. }
  1027. }
  1028. else
  1029. {
  1030. hasPm = true; // other modules default ok
  1031. }
  1032. }
  1033. if (!hasPm)
  1034. {
  1035. reason = $"Step {i + 1} no valid PM, " + string.Join("|", stepInfo.StepModules);
  1036. return false;
  1037. }
  1038. }
  1039. reason = "";
  1040. return true;
  1041. }
  1042. protected int GetUnprocessedWaferCount()
  1043. {
  1044. int count = 0;
  1045. foreach (ProcessJobInfo pj in _lstProcessJobs)
  1046. {
  1047. if (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused)
  1048. count += GetUnprocessedWaferCount(pj);
  1049. }
  1050. return count;
  1051. }
  1052. protected int GetUnprocessedWaferCount(ProcessJobInfo pj)
  1053. {
  1054. int count = 0;
  1055. for (int i = 0; i < pj.SlotWafers.Count; ++i)
  1056. {
  1057. WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
  1058. if (wafer.IsEmpty)
  1059. continue;
  1060. if (CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
  1061. count++;
  1062. }
  1063. return count;
  1064. }
  1065. protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
  1066. {
  1067. for (int i = 0; i < pj.SlotWafers.Count; ++i)
  1068. {
  1069. WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
  1070. if (wafer.IsEmpty)
  1071. return false;
  1072. if (checkAllProcessed && CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
  1073. return false;
  1074. }
  1075. return true;
  1076. }
  1077. private bool CheckWaferNextStepIsAlign(ModuleName module, int slot)
  1078. {
  1079. if (!WaferManager.Instance.CheckHasWafer(module, slot))
  1080. return false;
  1081. WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
  1082. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  1083. return false;
  1084. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  1085. return false;
  1086. if (wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner1)
  1087. || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner2))
  1088. return true;
  1089. return false;
  1090. }
  1091. private bool GetWaferTemperatureSetInRecipe(ModuleName waferModule, int waferSlot, ModuleName pmModule, out float temp)
  1092. {
  1093. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1094. var seq = wafer.ProcessJob.Sequence;
  1095. for (int i = 0; i < seq.Steps.Count; i++)
  1096. {
  1097. SequenceStepInfo stepInfo = seq.Steps[i];
  1098. foreach (var module in stepInfo.StepModules)
  1099. {
  1100. if ( module == pmModule)
  1101. {
  1102. temp = (float)seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"] ;
  1103. return true;
  1104. }
  1105. }
  1106. }
  1107. temp = 0;
  1108. LOG.Error($"Can not find wafer {waferModule} {waferSlot+1} temperature set in recipe");
  1109. return false;
  1110. }
  1111. private bool CheckWaferPmTemperatureIsOk(ModuleName waferModule, int waferSlot)
  1112. {
  1113. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1114. if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  1115. return false;
  1116. var seq = wafer.ProcessJob.Sequence;
  1117. for (int i = 0; i < seq.Steps.Count; i++)
  1118. {
  1119. SequenceStepInfo stepInfo = seq.Steps[i];
  1120. bool stepOk = false;
  1121. foreach (var module in stepInfo.StepModules)
  1122. {
  1123. if (ModuleHelper.IsPm(module))
  1124. {
  1125. float tempNeeded = (float)seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"];
  1126. if ((GetModule(module.ToString()) as SchedulerPM).IsTemperatureReady(tempNeeded))
  1127. {
  1128. stepOk = true;
  1129. break;
  1130. }
  1131. }
  1132. else
  1133. {
  1134. stepOk = true;
  1135. }
  1136. }
  1137. if (!stepOk)
  1138. return false;
  1139. }
  1140. return true;
  1141. }
  1142. private bool CheckWaferNeedAlign(ModuleName waferModule, int waferSlot)
  1143. {
  1144. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1145. if (wafer.IsEmpty)
  1146. return false;
  1147. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  1148. return false;
  1149. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  1150. return false;
  1151. if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules
  1152. .Contains(ModuleName.Aligner1) && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules
  1153. .Contains(ModuleName.Aligner2))
  1154. return false;
  1155. return true;
  1156. }
  1157. private bool CheckWaferNextProcessIn(ModuleName waferModule, int waferSlot, ModuleName chamber)
  1158. {
  1159. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1160. if (wafer.IsEmpty ||
  1161. wafer.ProcessJob == null ||
  1162. wafer.ProcessJob.Sequence == null ||
  1163. wafer.ProcessJob.Sequence.Steps == null ||
  1164. wafer.ProcessJob.Sequence.Steps.Count <= wafer.NextSequenceStep ||
  1165. wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep] == null ||
  1166. wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
  1167. {
  1168. return false;
  1169. }
  1170. if (_isInParallelMode && _mapLpPm[(ModuleName)wafer.OriginStation] != chamber)
  1171. return false;
  1172. return wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(chamber);
  1173. }
  1174. public bool CheckWaferNeedProcess(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
  1175. {
  1176. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1177. if (wafer.IsEmpty)
  1178. return false;
  1179. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  1180. return false;
  1181. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  1182. return false;
  1183. for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
  1184. {
  1185. if (wafer.ProcessJob.Sequence.Steps[i].StepModules
  1186. .Contains(ModuleName.PMA) || wafer.ProcessJob.Sequence.Steps[i].StepModules
  1187. .Contains(ModuleName.PMB))
  1188. {
  1189. if (processIn == ModuleName.System)
  1190. return true;
  1191. if (_isInParallelMode && _mapLpPm[(ModuleName) wafer.OriginStation] != processIn)
  1192. return false;
  1193. if (wafer.ProcessJob.Sequence.Steps[i].StepModules
  1194. .Contains(processIn))
  1195. return true;
  1196. }
  1197. }
  1198. return false;
  1199. }
  1200. private bool CheckVacuumWaferHasAvailableTarget(ModuleName waferModule, int waferSlot)
  1201. {
  1202. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1203. //System.Diagnostics.Trace.Assert(!wafer.IsEmpty);
  1204. //if (CheckWaferNeedProcess(waferModule, waferSlot))
  1205. //{
  1206. // // Check for an empty PM
  1207. // foreach (var pm in _lstPms)
  1208. // {
  1209. // if (WaferManager.Instance.CheckNoWafer(pm.Module, 0))
  1210. // {
  1211. // if (pm.IsAvailable == false)
  1212. // continue;
  1213. // if (!CheckWaferNextProcessIn(waferModule, waferSlot, pm.Module))
  1214. // continue;
  1215. // return true;
  1216. // }
  1217. // }
  1218. //}
  1219. //else
  1220. {
  1221. // No more processing needed, check for a outbound BUFFER slot
  1222. foreach (var buffer in _lstBuffers)
  1223. {
  1224. if (!buffer.IsAvailable)
  1225. continue;
  1226. if (WaferManager.Instance.CheckNoWafer(buffer.Module, 0))
  1227. {
  1228. return true;
  1229. }
  1230. }
  1231. }
  1232. return false;
  1233. }
  1234. private bool CheckBufferWaferHasAvailableTarget(ModuleName waferModule, int waferSlot)
  1235. {
  1236. WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
  1237. //System.Diagnostics.Trace.Assert(!wafer.IsEmpty);
  1238. if (!CheckWaferNeedProcess(waferModule, waferSlot))
  1239. return true;
  1240. // Check for an empty PM
  1241. foreach (var pm in _lstPms)
  1242. {
  1243. if (WaferManager.Instance.CheckNoWafer(pm.Module, 0))
  1244. {
  1245. if (pm.IsAvailable == false)
  1246. continue;
  1247. if (!CheckWaferNextProcessIn(waferModule, waferSlot, pm.Module))
  1248. continue;
  1249. return true;
  1250. }
  1251. }
  1252. return false;
  1253. }
  1254. private bool SetSequenceTemperatureInfo(SequenceInfo seq, out string reason)
  1255. {
  1256. for (int i = 0; i < seq.Steps.Count; i++)
  1257. {
  1258. SequenceStepInfo stepInfo = seq.Steps[i];
  1259. foreach (var module in stepInfo.StepModules)
  1260. {
  1261. if (ModuleHelper.IsPm(module))
  1262. {
  1263. string attr = module == ModuleName.PMA ? "PMARecipe" : "PMBRecipe";
  1264. if (stepInfo.StepParameter.ContainsKey(attr)
  1265. && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr]))
  1266. {
  1267. var recipeName = (string)stepInfo.StepParameter[attr];
  1268. if (!string.IsNullOrEmpty(recipeName))
  1269. {
  1270. var recipeContent =
  1271. RecipeFileManager.Instance.LoadRecipe($"", recipeName, false);
  1272. if (string.IsNullOrEmpty(recipeContent))
  1273. {
  1274. reason = $"Can not find recipe file{recipeName}";
  1275. return false;
  1276. }
  1277. try
  1278. {
  1279. XmlDocument xml = new XmlDocument();
  1280. xml.LoadXml(recipeContent);
  1281. var substrateTemp = xml.DocumentElement.HasAttribute("SubstrateTemp") ? xml.DocumentElement.Attributes["SubstrateTemp"].Value : "";
  1282. if (!float.TryParse(substrateTemp, out float temp))
  1283. {
  1284. reason = $"Invalid substrate temperature in recipe head {recipeName}";
  1285. return false;
  1286. }
  1287. seq.Steps[i].StepParameter[module == ModuleName.PMA ? "PMATemp" : "PMBTemp"] = temp;
  1288. }
  1289. catch (Exception ex)
  1290. {
  1291. LOG.Write(ex);
  1292. reason = $"recipe not valid, {recipeName}";
  1293. return false;
  1294. }
  1295. }
  1296. }
  1297. }
  1298. }
  1299. }
  1300. reason = "";
  1301. return true;
  1302. }
  1303. private bool CheckSequenceRecipeFileValid(SequenceInfo seq, out string reason)
  1304. {
  1305. for (int i = 0; i < seq.Steps.Count; i++)
  1306. {
  1307. SequenceStepInfo stepInfo = seq.Steps[i];
  1308. foreach (var module in stepInfo.StepModules)
  1309. {
  1310. if (ModuleHelper.IsPm(module))
  1311. {
  1312. string attr = module==ModuleName.PMA ? "PMARecipe" : "PMBRecipe";
  1313. if (stepInfo.StepParameter.ContainsKey(attr)
  1314. && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr]))
  1315. {
  1316. var recipeName = (string)stepInfo.StepParameter[attr];
  1317. if (!string.IsNullOrEmpty(recipeName))
  1318. {
  1319. var recipeContent =
  1320. RecipeFileManager.Instance.LoadRecipe($"", recipeName, false);
  1321. if (string.IsNullOrEmpty(recipeContent))
  1322. {
  1323. reason = $"Can not find recipe file{recipeName}";
  1324. return false;
  1325. }
  1326. }
  1327. }
  1328. }
  1329. }
  1330. }
  1331. reason = "";
  1332. return true;
  1333. }
  1334. private bool GetWaferSequenceAlignTime(ModuleName module, int slot, out float time)
  1335. {
  1336. time = 0;
  1337. if (!WaferManager.Instance.CheckHasWafer(module, slot))
  1338. return false;
  1339. WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
  1340. if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
  1341. return false;
  1342. if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
  1343. return false;
  1344. if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner1)
  1345. && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner2))
  1346. return false;
  1347. if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter.ContainsKey("CoolingTime"))
  1348. return false;
  1349. if (!float.TryParse((string)wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"],
  1350. out time))
  1351. return false;
  1352. return true;
  1353. }
  1354. private int GetWaferCountOutofLP(ModuleName lp)
  1355. {
  1356. int count = 0;
  1357. var lstPosition = new List<ModuleName>()
  1358. {
  1359. ModuleName.EfemRobot, ModuleName.Aligner1, ModuleName.Aligner2, ModuleName.PMA, ModuleName.PMB,
  1360. };
  1361. foreach (var moduleName in lstPosition)
  1362. {
  1363. if (WaferManager.Instance.CheckHasWafer(moduleName, 0))
  1364. {
  1365. if (lp == ModuleName.System ||
  1366. WaferManager.Instance.GetWafer(moduleName, 0).OriginStation == (int) lp)
  1367. count++;
  1368. }
  1369. }
  1370. return count;
  1371. }
  1372. private SlotItem GetWaferReturnLoadPort(ModuleName module, int slot)
  1373. {
  1374. WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
  1375. if (!wafer.IsEmpty)
  1376. {
  1377. return new SlotItem((ModuleName)wafer.OriginStation, wafer.OriginSlot);
  1378. }
  1379. return null;
  1380. }
  1381. private int GetWaferCountInJobQueue(ModuleName sourceLp)
  1382. {
  1383. int count = 0;
  1384. foreach (var lp in _lstLps)
  1385. {
  1386. for (int i = 0; i < 25; i++)
  1387. {
  1388. if (CheckWaferNeedProcess(lp.Module, i) && (sourceLp==ModuleName.System || sourceLp==lp.Module))
  1389. count++;
  1390. }
  1391. }
  1392. return count;
  1393. }
  1394. private SlotItem GetNextWaferInJobQueue(ModuleName sourceLp)
  1395. {
  1396. foreach (var cj in _lstControlJobs)
  1397. {
  1398. if (sourceLp!=ModuleName.System && (cj.Module !=sourceLp.ToString()))
  1399. continue;
  1400. if (cj.State == EnumControlJobState.Executing)
  1401. {
  1402. foreach (var pj in _lstProcessJobs)
  1403. {
  1404. if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
  1405. {
  1406. foreach (var pjSlotWafer in pj.SlotWafers)
  1407. {
  1408. if (CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
  1409. return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
  1410. }
  1411. }
  1412. }
  1413. }
  1414. }
  1415. return null;
  1416. }
  1417. private int GetMaxOutWafer()
  1418. {
  1419. return _isInParallelMode ? 1 : 2;
  1420. }
  1421. #endregion Logic Check
  1422. }
  1423. }