SchedulerSequenceManager.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. using MECF.Framework.Common.RecipeCenter;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.Schedulers;
  9. using Aitex.Core.Common;
  10. using MECF.Framework.Common.CommonData;
  11. using System.Windows;
  12. using Aitex.Core.RT.IOCore;
  13. using Aitex.Core.RT.Log;
  14. using Aitex.Core.Util;
  15. using MECF.Framework.Common.Routine;
  16. using PunkHPX8_RT.Modules;
  17. using Aitex.Core.RT.Fsm;
  18. using MECF.Framework.Common.SubstrateTrackings;
  19. using MECF.Framework.Common.ToolLayout;
  20. using MECF.Framework.RT.Core.Equipments;
  21. using MECF.Framework.Common.ProcessCell;
  22. using SecsGem.Core.ItemModel;
  23. using PunkHPX8_RT.Modules.Transporter;
  24. using PunkHPX8_Core;
  25. using Aitex.Core.RT.SCCore;
  26. using PunkHPX8_RT.Modules.SRD;
  27. using PunkHPX8_RT.Devices.EFEM;
  28. using Aitex.Sorter.Common;
  29. using PunkHPX8_RT.Modules.Reservoir;
  30. using PunkHPX8_RT.Modules.PlatingCell;
  31. using PunkHPX8_RT.Modules.VpwMain;
  32. using PunkHPX8_RT.Modules.VpwCell;
  33. namespace PunkHPX8_RT.Schedulers
  34. {
  35. public class SchedulerSequenceManager : Singleton<SchedulerSequenceManager>
  36. {
  37. #region 常量
  38. private const string ENGINEERING = "Engineering";
  39. private const string PRODUCTION = "Production";
  40. private const string TRNPA = "TRNPA";
  41. private const string TRNPB = "TRNPB";
  42. #endregion
  43. #region 内部变量
  44. /// <summary>
  45. /// VPW是否包含相同尺寸
  46. /// </summary>
  47. private bool _vpwHasSameSize = false;
  48. #endregion
  49. #region 属性
  50. /// <summary>
  51. /// VPW是否包含相同尺寸
  52. /// </summary>
  53. public bool VPWHasSameSize
  54. {
  55. get { return _vpwHasSameSize; }
  56. }
  57. #endregion
  58. /// <summary>
  59. /// 初始化
  60. /// </summary>
  61. public void ConfirmVPW()
  62. {
  63. _vpwHasSameSize = CheckSystemHasTheSameSizeVpw();
  64. }
  65. /// <summary>
  66. /// 解析Wafer所有调度工序
  67. /// </summary>
  68. /// <param name="sequenceRecipe"></param>
  69. /// <returns></returns>
  70. public List<SchedulerSequence> AnalyWaferAllSchedulerSequence(WaferInfo waferInfo,ModuleName vpw, SequenceRecipe sequenceRecipe)
  71. {
  72. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  73. int index = 0;
  74. MoveItem moveItem = new MoveItem((ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot, ModuleName.Aligner1, 0,
  75. Hand.Blade1,Flip.Upper,Flip.Upper);
  76. SchedulerSequence efemRobotSequence = CreateEfemRobotSequence(moveItem, null, sequenceRecipe.SubstrateSize, ref index);
  77. schedulerSequences.Add(efemRobotSequence);
  78. SchedulerSequence alignerSequence = CreateAlignerSequence(sequenceRecipe,sequenceRecipe.SubstrateSize, ref index);
  79. schedulerSequences.Add(alignerSequence);
  80. MoveItem alignerToMoveItem = new MoveItem(ModuleName.Aligner1, 0, vpw, 0,Hand.Blade1, Flip.Upper, Flip.Upper);
  81. SchedulerSequence alignerRobotSequence = CreateEfemRobotSequence(alignerToMoveItem, null, sequenceRecipe.SubstrateSize, ref index);
  82. schedulerSequences.Add(alignerRobotSequence);
  83. //解析sequence recipe后续的工序
  84. var sequences = AnalyseSequenceRecipeScheduler(sequenceRecipe,vpw,false);
  85. if (sequences.Count == 0)
  86. {
  87. return schedulerSequences;
  88. }
  89. SchedulerSequence firstSequence = sequences[0];
  90. if (firstSequence.ModuleType != ModuleType.VPW)
  91. {
  92. return schedulerSequences;
  93. }
  94. firstSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(vpw);
  95. firstSequence.ModuleName = vpw;
  96. //调整工序后面的索引
  97. foreach (SchedulerSequence item in sequences)
  98. {
  99. item.SequenceIndex = index;
  100. index++;
  101. }
  102. schedulerSequences.AddRange(sequences);
  103. //若经过srd
  104. if (SequenceRecipeManager.Instance.IsContainedSrd(sequenceRecipe))
  105. {
  106. SrdRecipe srdRecipe = SequenceRecipeManager.Instance.GetSrdRecipeBySequenceRecipe(sequenceRecipe);
  107. if (srdRecipe != null)
  108. {
  109. //从VPW取至SRD
  110. MoveItem lastToSrdItem = new MoveItem();
  111. lastToSrdItem.SourceModule = vpw;
  112. //A面
  113. lastToSrdItem.SourceSlot = 0;
  114. lastToSrdItem.SourceType = ModuleType.VPW;
  115. lastToSrdItem.DestinationType = ModuleType.SRD;
  116. lastToSrdItem.SourceSlot = 0;
  117. lastToSrdItem.DestinationModule = ModuleName.Unknown;
  118. lastToSrdItem.RobotHand = Hand.Blade1;
  119. lastToSrdItem.PickRobotFlip = Flip.Upper;
  120. lastToSrdItem.PlaceRobotFlip = Flip.Upper;
  121. SchedulerSequence lastToSrdSequence = CreateEfemRobotSequence(lastToSrdItem, null,sequenceRecipe.SubstrateSize, ref index);
  122. schedulerSequences.Add(lastToSrdSequence);
  123. SchedulerSequence srdSequence = CreateSRDSequence(srdRecipe,sequenceRecipe.SubstrateSize, ref index);
  124. schedulerSequences.Add(srdSequence);
  125. //SRD完成后回至LoadPort
  126. MoveItem srdToLoadPortItem = new MoveItem();
  127. srdToLoadPortItem.SourceModule = ModuleName.Unknown;
  128. srdToLoadPortItem.SourceType = ModuleType.SRD;
  129. srdToLoadPortItem.SourceSlot = 0;
  130. srdToLoadPortItem.DestinationType = ModuleType.LoadPort;
  131. srdToLoadPortItem.DestinationModule = (ModuleName)waferInfo.OriginStation;
  132. srdToLoadPortItem.DestinationSlot = waferInfo.OriginSlot;
  133. srdToLoadPortItem.RobotHand = Hand.Blade1;
  134. lastToSrdItem.PickRobotFlip = Flip.Upper;
  135. lastToSrdItem.PlaceRobotFlip = Flip.Upper;
  136. SchedulerSequence srdToLoadPortSequence = CreateEfemRobotSequence(srdToLoadPortItem, null,sequenceRecipe.SubstrateSize, ref index);
  137. schedulerSequences.Add(srdToLoadPortSequence);
  138. }
  139. else
  140. {
  141. LOG.WriteBackgroundLog(eEvent.ERR_SEQUENCE, "System", $"{sequenceRecipe.Ppid} srd recipe is invalid");
  142. return new List<SchedulerSequence>();
  143. }
  144. }
  145. else
  146. {
  147. //若无SRD,直接从VPW转LoadPort
  148. MoveItem srdToLoadPortItem = new MoveItem();
  149. srdToLoadPortItem.SourceModule = vpw;
  150. srdToLoadPortItem.SourceType = ModuleType.VPW;
  151. srdToLoadPortItem.SourceSlot = 0;
  152. srdToLoadPortItem.DestinationType = ModuleType.LoadPort;
  153. srdToLoadPortItem.DestinationModule = (ModuleName)waferInfo.OriginStation;
  154. srdToLoadPortItem.DestinationSlot = waferInfo.OriginSlot;
  155. srdToLoadPortItem.RobotHand = Hand.Blade1;
  156. srdToLoadPortItem.PickRobotFlip = Flip.Upper;
  157. srdToLoadPortItem.PlaceRobotFlip = Flip.Upper;
  158. SchedulerSequence pufToLoaderSequence = CreateEfemRobotSequence(srdToLoadPortItem, null,sequenceRecipe.SubstrateSize, ref index);
  159. schedulerSequences.Add(pufToLoaderSequence);
  160. }
  161. return schedulerSequences;
  162. }
  163. /// <summary>
  164. /// 解析Dummy Wafer所有调度工序
  165. /// </summary>
  166. /// <param name="sequenceRecipe"></param>
  167. /// <returns></returns>
  168. public List<SchedulerSequence> AnalyDummyWaferAllSchedulerSequence(SequenceRecipe sequenceRecipe, ModuleName vpw, WaferInfo waferInfo)
  169. {
  170. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  171. int index = 0;
  172. MoveItem moveItem = new MoveItem((ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot, ModuleName.Aligner1, 0,
  173. Hand.Blade1, Flip.Upper, Flip.Upper);
  174. SchedulerSequence efemRobotSequence = CreateEfemRobotSequence(moveItem, null, sequenceRecipe.SubstrateSize, ref index);
  175. schedulerSequences.Add(efemRobotSequence);
  176. SchedulerSequence alignerSequence = CreateAlignerSequence(sequenceRecipe,sequenceRecipe.SubstrateSize, ref index);
  177. schedulerSequences.Add(alignerSequence);
  178. MoveItem alignerToMoveItem = new MoveItem(ModuleName.Aligner1, 0, vpw, 0, Hand.Blade1, Flip.Upper, Flip.Upper);
  179. SchedulerSequence alignerRobotSequence = CreateEfemRobotSequence(alignerToMoveItem, null, sequenceRecipe.SubstrateSize, ref index);
  180. schedulerSequences.Add(alignerRobotSequence);
  181. //解析sequence recipe后续的工序
  182. var sequences = AnalyseSequenceRecipeScheduler(sequenceRecipe,vpw, true);
  183. if (sequences.Count == 0)
  184. {
  185. return schedulerSequences;
  186. }
  187. if (_vpwHasSameSize)
  188. {
  189. SchedulerSequence firstSequence = sequences[0];
  190. if (firstSequence.ModuleType != ModuleType.VPW)
  191. {
  192. return schedulerSequences;
  193. }
  194. firstSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(vpw);
  195. firstSequence.ModuleName = vpw;
  196. }
  197. else
  198. {
  199. SchedulerSequence firstSequence = sequences[0];
  200. if (firstSequence.ModuleType != ModuleType.EfemRobot)
  201. {
  202. return schedulerSequences;
  203. }
  204. MoveItem firstMoveItem=firstSequence.Parameters as MoveItem;
  205. firstMoveItem.SourceModule = vpw;
  206. }
  207. //调整工序后面的索引
  208. foreach (SchedulerSequence item in sequences)
  209. {
  210. item.SequenceIndex = index;
  211. index++;
  212. }
  213. schedulerSequences.AddRange(sequences);
  214. SchedulerSequence lastSequence=sequences[sequences.Count - 1];
  215. //若无SRD,直接从VPW转LoadPort
  216. MoveItem srdToDummyItem = new MoveItem();
  217. srdToDummyItem.SourceModule = vpw;
  218. srdToDummyItem.SourceType = ModuleType.VPW;
  219. srdToDummyItem.SourceSlot = 0;
  220. srdToDummyItem.DestinationType = ModuleType.Dummy;
  221. srdToDummyItem.DestinationModule = (ModuleName)waferInfo.OriginStation;
  222. srdToDummyItem.DestinationSlot = waferInfo.OriginSlot;
  223. srdToDummyItem.RobotHand = Hand.Blade1;
  224. srdToDummyItem.PickRobotFlip = Flip.Upper;
  225. srdToDummyItem.PlaceRobotFlip = Flip.Upper;
  226. SchedulerSequence toDummySequence = CreateEfemRobotSequence(srdToDummyItem, null, sequenceRecipe.SubstrateSize, ref index);
  227. schedulerSequences.Add(toDummySequence);
  228. return schedulerSequences;
  229. }
  230. /// <summary>
  231. /// 分析Sequence recipe对应的调度步骤
  232. /// </summary>
  233. /// <param name="sequenceRecipe"></param>
  234. /// <returns></returns>
  235. private List<SchedulerSequence> AnalyseSequenceRecipeScheduler(SequenceRecipe sequenceRecipe,ModuleName vpw,bool isDummy)
  236. {
  237. List<SchedulerSequence> schedulerSequences= new List<SchedulerSequence>();
  238. List<SchedulerSequence> tmpLst = new List<SchedulerSequence>();
  239. var processResult = AnalyseLastProcessRecipeIndex(sequenceRecipe.Recipes);
  240. bool isExistSrd = sequenceRecipe.Recipes.FindIndex(O=>O.ToLower().EndsWith("srd.rcp"))!=-1;
  241. int lastIndex = isExistSrd ? sequenceRecipe.Recipes.Count - 2 : sequenceRecipe.Recipes.Count - 1;
  242. for(int i=0;i<sequenceRecipe.Recipes.Count;i++)
  243. {
  244. string item = sequenceRecipe.Recipes[i];
  245. if(item.ToLower().EndsWith("srd.rcp"))//跳过SRD
  246. {
  247. continue;
  248. }
  249. SchedulerSequence schedulerSequence = new SchedulerSequence();
  250. schedulerSequence.ModuleName = ModuleName.Unknown;
  251. schedulerSequence.ModuleType=SequenceRecipeManager.Instance.GetModuleType(item);
  252. schedulerSequence.SequenceIndex=i;
  253. schedulerSequence.WaferSize = sequenceRecipe.SubstrateSize;
  254. MECF.Framework.Common.RecipeCenter.RecipeType recipeType =SequenceRecipeManager.Instance.GetRecipeType(item);
  255. if (item.ToLower().EndsWith("dep.rcp"))
  256. {
  257. if (isDummy)
  258. {
  259. DqdrRecipe dqdrRecipe=SequenceRecipeManager.Instance.GetDqdrRecipeByDepRecipe(item);
  260. if (dqdrRecipe == null)
  261. {
  262. return schedulerSequences;
  263. }
  264. schedulerSequence.Recipe=dqdrRecipe;
  265. }
  266. else
  267. {
  268. schedulerSequence.Recipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType, item, recipeType);
  269. }
  270. }
  271. else
  272. {
  273. schedulerSequence.Recipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType, item, recipeType);
  274. }
  275. schedulerSequence.SequenceType = sequenceRecipe.SequenceType;
  276. schedulerSequence.State = RState.Init;
  277. schedulerSequence.MaterialType = MaterialType.Wafer;
  278. tmpLst.Add(schedulerSequence);
  279. if (i != lastIndex)
  280. {
  281. string nextModule = sequenceRecipe.Recipes[i + 1];
  282. schedulerSequence.NextModuleType = SequenceRecipeManager.Instance.GetModuleType(nextModule);
  283. MECF.Framework.Common.RecipeCenter.RecipeType nextRecipeType = SequenceRecipeManager.Instance.GetRecipeType(nextModule);
  284. if (item.ToLower().EndsWith("dep.rcp"))
  285. {
  286. if (isDummy)
  287. {
  288. DqdrRecipe dqdrRecipe = SequenceRecipeManager.Instance.GetDqdrRecipeByDepRecipe(nextModule);
  289. if (dqdrRecipe == null)
  290. {
  291. return schedulerSequences;
  292. }
  293. schedulerSequence.NextRecipe = dqdrRecipe;
  294. }
  295. else
  296. {
  297. schedulerSequence.NextRecipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType, nextModule, nextRecipeType);
  298. }
  299. }
  300. else
  301. {
  302. schedulerSequence.NextRecipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType, nextModule, nextRecipeType);
  303. }
  304. }
  305. schedulerSequence.IsProcessSequece = true;
  306. if(i==processResult.lastIndex)
  307. {
  308. schedulerSequence.IsLastProcessSequence = true;
  309. }
  310. }
  311. int index = 0;
  312. for(int i=0;i<tmpLst.Count;i++)
  313. {
  314. //不同尺寸的Dummy wafer跳过VPW recipe步骤
  315. if (_vpwHasSameSize || !isDummy || tmpLst[i].ModuleType!=ModuleType.VPW)
  316. {
  317. tmpLst[i].SequenceIndex = 0;
  318. schedulerSequences.Add(tmpLst[i]);
  319. index++;
  320. }
  321. if (i < tmpLst.Count - 1)
  322. {
  323. MoveItem moveItem = new MoveItem();
  324. moveItem.SourceModule = tmpLst[i].ModuleName;
  325. moveItem.SourceType = tmpLst[i].ModuleType;
  326. moveItem.SourceSlot = 0;
  327. moveItem.DestinationModule = tmpLst[i + 1].ModuleName;
  328. moveItem.DestinationSlot = 0;
  329. moveItem.DestinationType = tmpLst[i+1].ModuleType;
  330. moveItem.RobotHand = Hand.Blade2;
  331. //源来自于Plating cell,向下取
  332. if (tmpLst[i].ModuleType == ModuleType.PlatingCell)
  333. {
  334. moveItem.PickRobotFlip = Flip.Down;
  335. }
  336. else
  337. {
  338. moveItem.PickRobotFlip = Flip.Upper;
  339. }
  340. //目标来自于Plating cell,向下放
  341. if (tmpLst[i + 1].ModuleType == ModuleType.PlatingCell)
  342. {
  343. moveItem.PlaceRobotFlip = Flip.Down;
  344. }
  345. else
  346. {
  347. moveItem.PlaceRobotFlip = Flip.Upper;
  348. }
  349. SchedulerSequence robotSequence = CreateEfemRobotSequence(moveItem,null,sequenceRecipe.SubstrateSize, ref index);
  350. schedulerSequences.Add(robotSequence);
  351. }
  352. else
  353. {
  354. //生产片最后退至VPW中转
  355. MoveItem moveItem = new MoveItem();
  356. moveItem.SourceModule = tmpLst[i].ModuleName;
  357. moveItem.SourceType = tmpLst[i].ModuleType;
  358. moveItem.SourceSlot = 0;
  359. moveItem.DestinationModule = vpw;
  360. moveItem.DestinationSlot = 0;
  361. moveItem.DestinationType = ModuleType.VPW;
  362. moveItem.RobotHand = Hand.Blade2;
  363. //源来自于Plating cell,向下取
  364. if (tmpLst[i].ModuleType == ModuleType.PlatingCell)
  365. {
  366. moveItem.PickRobotFlip = Flip.Down;
  367. }
  368. else
  369. {
  370. moveItem.PickRobotFlip = Flip.Upper;
  371. }
  372. moveItem.PlaceRobotFlip = Flip.Upper;
  373. SchedulerSequence robotSequence = CreateEfemRobotSequence(moveItem, null, sequenceRecipe.SubstrateSize, ref index);
  374. schedulerSequences.Add(robotSequence);
  375. }
  376. }
  377. return schedulerSequences;
  378. }
  379. /// <summary>
  380. /// 分析最后加工recipe索引
  381. /// </summary>
  382. /// <param name="recipes"></param>
  383. /// <returns></returns>
  384. private (int lastIndex,List<int> processIndexList) AnalyseLastProcessRecipeIndex(List<string> recipes)
  385. {
  386. int index = 0;
  387. List<int> lst = new List<int>();
  388. for(int i=0;i<recipes.Count; i++)
  389. {
  390. string item=recipes[i];
  391. if(item.ToLower().EndsWith("dep.rcp"))
  392. {
  393. index = i;
  394. if(lst.Contains(i))
  395. {
  396. lst.Add(i);
  397. }
  398. }
  399. }
  400. if(lst.Count==0)
  401. {
  402. lst.Add(0);
  403. }
  404. return (index,lst);
  405. }
  406. /// <summary>
  407. /// 创建EFEM Robot步骤
  408. /// </summary>
  409. /// <param name="index"></param>
  410. /// <returns></returns>
  411. private SchedulerSequence CreateEfemRobotSequence(MoveItem moveItem,List<SchedulerSyncModuleMessage> synModules,int waferSize,ref int index)
  412. {
  413. SchedulerSequence sequence = new SchedulerSequence();
  414. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot);
  415. sequence.SequenceIndex= index;
  416. sequence.ModuleName=ModuleName.EfemRobot;
  417. sequence.State = RState.Init;
  418. sequence.Recipe = null;
  419. sequence.ModuleType=ModuleType.EfemRobot;
  420. sequence.Parameters =moveItem;
  421. sequence.MaterialType = MaterialType.Wafer;
  422. sequence.SynchronousModuleMessages = synModules;
  423. sequence.WaferSize = waferSize;
  424. index++;
  425. return sequence;
  426. }
  427. /// <summary>
  428. /// 创建Aligner步骤
  429. /// </summary>
  430. /// <param name="index"></param>
  431. /// <returns></returns>
  432. private SchedulerSequence CreateAlignerSequence(SequenceRecipe recipe,int waferSize,ref int index)
  433. {
  434. SchedulerSequence sequence = new SchedulerSequence();
  435. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Aligner1);
  436. sequence.SequenceIndex = index;
  437. sequence.ModuleName = ModuleName.Aligner1;
  438. sequence.State = RState.Init;
  439. sequence.Recipe = recipe;
  440. sequence.ModuleType = ModuleType.Aligner;
  441. sequence.Parameters = null;
  442. sequence.MaterialType = MaterialType.Wafer;
  443. sequence.WaferSize = waferSize;
  444. index++;
  445. return sequence;
  446. }
  447. /// <summary>
  448. /// 创建Loader步骤
  449. /// </summary>
  450. /// <param name="index"></param>
  451. /// <returns></returns>
  452. private SchedulerSequence CreateSRDSequence(SrdRecipe recipe,int waferSize,ref int index)
  453. {
  454. SchedulerSequence sequence = new SchedulerSequence();
  455. sequence.SequenceIndex = index;
  456. sequence.State = RState.Init;
  457. sequence.Recipe = recipe;
  458. sequence.ModuleType = ModuleType.SRD;
  459. sequence.MaterialType = MaterialType.Wafer;
  460. sequence.WaferSize= waferSize;
  461. index++;
  462. return sequence;
  463. }
  464. /// <summary>
  465. /// 根据模块类型获取可用模块
  466. /// </summary>
  467. /// <param name="moduleType"></param>
  468. /// <returns></returns>
  469. public ModuleName GetAvaibleModuleCell(string sequenceType,ModuleType moduleType)
  470. {
  471. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  472. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  473. foreach (var item in entities)
  474. {
  475. bool result = CheckAvaibleModule(item,moduleType,sequenceType);
  476. if (result)
  477. {
  478. avaibles.Add(item);
  479. }
  480. }
  481. return GetMinTimeToReadyModule(avaibles,moduleType);
  482. }
  483. /// <summary>
  484. /// 根据化学液计算时间获取可用PlatingCellCell(参考其他PlatingCell剩余时间)
  485. /// </summary>
  486. /// <param name="chemistry"></param>
  487. /// <returns></returns>
  488. public (ModuleName platingCellModule, ModuleName rinseModule) CalculateAvaiblePlatingCellCellByChemistry(string chemistry, string startRinse, string sequenceType, string waferHolderId,
  489. int waferSize,DateTime startTime, int depRecipeTimeLength, int qdrRecipeTimeLength, bool checkConflict,
  490. SchedulerModulePartTime platingCellPartTime, SchedulerModulePartTime qdrParTime, ref bool isExistEnablePlatingCell)
  491. {
  492. bool isShowLog = SC.GetValue<bool>("Scheduler.IsShowLog");
  493. if (!Enum.TryParse(startRinse, out ModuleName startRinseModule) )
  494. {
  495. startRinse = "";
  496. }
  497. isExistEnablePlatingCell = false;
  498. return (ModuleName.Unknown, ModuleName.Unknown);
  499. }
  500. /// <summary>
  501. /// 检验模块是否可用
  502. /// </summary>
  503. /// <param name="item"></param>
  504. /// <returns></returns>
  505. public bool CheckAvaibleModule(IModuleEntity item,ModuleType moduleType,string sequenceType)
  506. {
  507. if (item.IsDisable)
  508. {
  509. return false;
  510. }
  511. if (!item.IsAuto)
  512. {
  513. return false;
  514. }
  515. if (item.IsError)
  516. {
  517. return false;
  518. }
  519. if (item.IsInit)
  520. {
  521. return false;
  522. }
  523. if (moduleType==ModuleType.PlatingCell)
  524. {
  525. if(item.IsProduction && sequenceType == ENGINEERING)
  526. return false;
  527. if (item.IsEngineering && sequenceType == PRODUCTION)
  528. return false;
  529. }
  530. return true;
  531. }
  532. /// <summary>
  533. /// 获取剩余时间最小的模块
  534. /// </summary>
  535. /// <param name="avaibles"></param>
  536. /// <returns></returns>
  537. private ModuleName GetMinTimeToReadyModule(List<IModuleEntity> avaibles,ModuleType moduleType)
  538. {
  539. if (avaibles.Count == 1)
  540. {
  541. return avaibles[0].Module;
  542. }
  543. int timeToReady = int.MaxValue;
  544. IModuleEntity selectedModule = null;
  545. List<IModuleEntity> idleModuleEtities = new List<IModuleEntity>();
  546. foreach (var item in avaibles)
  547. {
  548. if (item.IsIdle)
  549. {
  550. if(moduleType!=ModuleType.PlatingCell)
  551. {
  552. return item.Module;
  553. }
  554. idleModuleEtities.Add(item);
  555. }
  556. if (item.TimeToReady < timeToReady&&idleModuleEtities.Count==0)
  557. {
  558. timeToReady = item.TimeToReady;
  559. selectedModule = item;
  560. }
  561. }
  562. if (selectedModule != null)
  563. {
  564. return selectedModule.Module;
  565. }
  566. return ModuleName.Unknown;
  567. }
  568. /// <summary>
  569. /// 根据化学液获取可用的PlatingCell集合
  570. /// </summary>
  571. /// <param name="chemistry"></param>
  572. /// <returns></returns>
  573. public List<PlatingCellEntity> GetAvaiblePlatingCellList(string chemistry, string sequenceType, int waferSize, bool isEmpty)
  574. {
  575. List<IModuleEntity> reservoirEntities = Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.Reservoir);
  576. List<string> avaibles = new List<string>();
  577. foreach (IModuleEntity item in reservoirEntities)
  578. {
  579. ReservoirEntity entity = item as ReservoirEntity;
  580. if (entity.Chemistry == chemistry && entity.IsAuto && entity.IsInitialized)
  581. {
  582. avaibles.Add(entity.Module.ToString());
  583. }
  584. }
  585. List<PlatingCellEntity> metals = new List<PlatingCellEntity>();
  586. foreach (string item in avaibles)
  587. {
  588. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
  589. if (reservoirItem == null)
  590. {
  591. continue;
  592. }
  593. foreach (PlatingCellItem subItem in reservoirItem.PlatingCells)
  594. {
  595. PlatingCellEntity entity = Singleton<RouteManager>.Instance.GetModule<PlatingCellEntity>(subItem.ModuleName);
  596. if (!CheckAvaibleModule(entity, ModuleType.PlatingCell, sequenceType))
  597. {
  598. continue;
  599. }
  600. if (entity.MetalWaferSize != waferSize)
  601. {
  602. continue;
  603. }
  604. if (!isEmpty || (isEmpty && entity.WaferInfo.IsEmpty))
  605. {
  606. metals.Add(entity);
  607. }
  608. }
  609. }
  610. return metals;
  611. }
  612. /// <summary>
  613. /// 获取可用的VPW集合
  614. /// </summary>
  615. /// <param name="chemistry"></param>
  616. /// <returns></returns>
  617. public List<VpwCellEntity> GetAvaibleVpwList(int waferSize, bool isEmpty)
  618. {
  619. List<IModuleEntity> vpwEtities = Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.VPW);
  620. List<string> avaibles = new List<string>();
  621. List<VpwCellEntity> vpws = new List<VpwCellEntity>();
  622. foreach (IModuleEntity item in vpwEtities)
  623. {
  624. VpwCellEntity entity = (VpwCellEntity)item;
  625. if (!CheckAvaibleModule(entity, ModuleType.VPW, ""))
  626. {
  627. continue;
  628. }
  629. if (entity.VpwWaferSize != waferSize)
  630. {
  631. continue;
  632. }
  633. if (!isEmpty || (isEmpty && entity.WaferInfo == null))
  634. {
  635. vpws.Add(entity);
  636. }
  637. }
  638. return vpws;
  639. }
  640. /// <summary>
  641. /// 检验VPW是否相同尺寸
  642. /// </summary>
  643. /// <returns></returns>
  644. private bool CheckSystemHasTheSameSizeVpw()
  645. {
  646. VpwCellEntity vpwCellEntity1 = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(ModuleName.VPW1.ToString());
  647. VpwCellEntity vpwCellEntity2 = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(ModuleName.VPW2.ToString());
  648. if (vpwCellEntity1 == null || vpwCellEntity2 == null)
  649. {
  650. return false;
  651. }
  652. if (!vpwCellEntity1.IsAuto || !vpwCellEntity2.IsAuto)
  653. {
  654. return false;
  655. }
  656. if(vpwCellEntity1.IsDisable || vpwCellEntity2.IsDisable)
  657. {
  658. return false;
  659. }
  660. if (vpwCellEntity1.VpwWaferSize != vpwCellEntity2.VpwWaferSize)
  661. {
  662. return false;
  663. }
  664. return true;
  665. }
  666. }
  667. }