SchedulerSequenceManager.cs 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  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.WaferHolder;
  11. using MECF.Framework.Common.CommonData;
  12. using System.Windows;
  13. using Aitex.Core.RT.IOCore;
  14. using Aitex.Core.RT.Log;
  15. using Aitex.Core.Util;
  16. using MECF.Framework.Common.Routine;
  17. using CyberX8_RT.Modules;
  18. using Aitex.Core.RT.Fsm;
  19. using CyberX8_RT.Modules.PUF;
  20. using CyberX8_RT.Modules.Dummy;
  21. using MECF.Framework.Common.SubstrateTrackings;
  22. using MECF.Framework.Common.ToolLayout;
  23. using CyberX8_RT.Modules.Metal;
  24. using CyberX8_RT.Modules.Rinse;
  25. using MECF.Framework.RT.Core.Equipments;
  26. using MECF.Framework.Common.ProcessCell;
  27. using SecsGem.Core.ItemModel;
  28. using CyberX8_RT.Modules.Transporter;
  29. using CyberX8_Core;
  30. using Aitex.Core.RT.SCCore;
  31. using CyberX8_RT.Modules.Dryer;
  32. using CyberX8_RT.Modules.Prewet;
  33. using CyberX8_RT.Modules.SRD;
  34. using CyberX8_RT.Modules.Reservoir;
  35. using CyberX8_RT.Schedulers.Puf;
  36. using CyberX8_RT.Modules.Loader;
  37. using CyberX8_RT.Schedulers.Transporter;
  38. using CyberX8_RT.Schedulers.Loader;
  39. using CyberX8_RT.Devices.EFEM;
  40. namespace CyberX8_RT.Schedulers
  41. {
  42. public class SchedulerSequenceManager : Singleton<SchedulerSequenceManager>
  43. {
  44. #region 常量
  45. private const string ENGINEERING = "Engineering";
  46. private const string PRODUCTION = "Production";
  47. private const string TRNPA = "TRNPA";
  48. private const string TRNPB = "TRNPB";
  49. #endregion
  50. /// <summary>
  51. /// 解析Wafer所有调度工序
  52. /// </summary>
  53. /// <param name="sequenceRecipe"></param>
  54. /// <returns></returns>
  55. public List<SchedulerSequence> AnalyWaferAllSchedulerSequence(WaferInfo waferInfo,ModuleName pufModule,string side,WaferHolderInfo waferHolderInfo,SequenceRecipe sequenceRecipe)
  56. {
  57. waferInfo.LoaderSide = side;
  58. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  59. int index = 0;
  60. MoveItem moveItem = new MoveItem((ModuleName)waferInfo.OriginStation, waferInfo.OriginSlot, ModuleName.Aligner1, 0, Aitex.Sorter.Common.Hand.Blade1);
  61. SchedulerSequence efemRobotSequence = CreateEfemRobotSequence(moveItem,null,sequenceRecipe.SubstrateSize,ref index);
  62. schedulerSequences.Add(efemRobotSequence);
  63. SchedulerSequence alignerSequence=CreateAlignerSequence(sequenceRecipe.AlignmentAngle,sequenceRecipe.SubstrateSize,ref index);
  64. schedulerSequences.Add(alignerSequence);
  65. //从Aligner至Puf B面
  66. MoveItem moveItem2 = new MoveItem(ModuleName.Aligner1, 0, pufModule, 1, Aitex.Sorter.Common.Hand.Blade1);
  67. SchedulerSequence secondEfemRobotSequence = CreateEfemRobotSequence(moveItem2,null,sequenceRecipe.SubstrateSize, ref index);
  68. schedulerSequences.Add(secondEfemRobotSequence);
  69. SchedulerSequence pufSequence=CreatePufSequence(pufModule,sequenceRecipe,side,true,ref index);
  70. schedulerSequences.Add(pufSequence);
  71. ////Loader
  72. //SchedulerSequence loaderSequence = CreateLoaderSequence(ref index);
  73. //schedulerSequences.Add(loaderSequence);
  74. ////wafer holder装载后的recipe工序
  75. //List<SchedulerSequence> waferHolderAfterLoadedAllSequences = WaferHolderAfterLoadedAllSchedulerSequences(waferHolderInfo, sequenceRecipe, ref index);
  76. //schedulerSequences.AddRange(waferHolderAfterLoadedAllSequences);
  77. ////buffer模块至Loader
  78. //ModuleName bufferModule = ConvertToBufferModule(waferHolderInfo.BufferId);
  79. //WaferHolderMoveItem bufferToLoaderItem = new WaferHolderMoveItem(bufferModule,ModuleType.Buffer , ModuleName.Loader1, ModuleType.Loader);
  80. //SchedulerSequence bufferToLoaderSequence = CreateLoaderTransporterSequence(bufferToLoaderItem, ref index);
  81. //schedulerSequences.Add(bufferToLoaderSequence);
  82. ////Loader
  83. //SchedulerSequence backLoaderSequence = CreateLoaderSequence(ref index);
  84. //schedulerSequences.Add(backLoaderSequence);
  85. //puf模块
  86. SchedulerSequence backPufSequence = CreatePufSequence(pufModule,sequenceRecipe,"",false, ref index);
  87. schedulerSequences.Add(backPufSequence);
  88. //若经过srd
  89. if(SequenceRecipeManager.Instance.IsContainedSrd(sequenceRecipe))
  90. {
  91. SrdRecipe srdRecipe=SequenceRecipeManager.Instance.GetSrdRecipeBySequenceRecipe(sequenceRecipe);
  92. if(srdRecipe!=null)
  93. {
  94. MoveItem pufToSrdItem = new MoveItem();
  95. pufToSrdItem.SourceModule = pufModule;
  96. //A面
  97. pufToSrdItem.SourceSlot = 0;
  98. pufToSrdItem.DestinationType = ModuleType.SRD;
  99. pufToSrdItem.SourceSlot = 0;
  100. pufToSrdItem.DestinationModule = ModuleName.Unknown;
  101. pufToSrdItem.RobotHand = Aitex.Sorter.Common.Hand.Blade1;
  102. SchedulerSequence backEfemRobotSequence = CreateEfemRobotSequence(pufToSrdItem,null,sequenceRecipe.SubstrateSize, ref index);
  103. schedulerSequences.Add(backEfemRobotSequence);
  104. SchedulerSequence srdSequence = CreateSRDSequence(srdRecipe, ref index);
  105. schedulerSequences.Add(srdSequence);
  106. MoveItem srdToLoadPortItem = new MoveItem();
  107. srdToLoadPortItem.SourceModule = ModuleName.Unknown;
  108. srdToLoadPortItem.SourceType = ModuleType.SRD;
  109. srdToLoadPortItem.SourceSlot = 0;
  110. srdToLoadPortItem.DestinationType = ModuleType.LoadPort;
  111. srdToLoadPortItem.DestinationModule = (ModuleName)waferInfo.OriginStation;
  112. srdToLoadPortItem.DestinationSlot = waferInfo.OriginSlot;
  113. srdToLoadPortItem.RobotHand = Aitex.Sorter.Common.Hand.Blade1;
  114. SchedulerSequence srdToLoadPortSequence = CreateEfemRobotSequence(srdToLoadPortItem,null,sequenceRecipe.SubstrateSize, ref index);
  115. schedulerSequences.Add(srdToLoadPortSequence);
  116. }
  117. else
  118. {
  119. LOG.WriteLog(eEvent.ERR_SEQUENCE, "System", $"{sequenceRecipe.Ppid} srd recipe is invalid");
  120. return new List<SchedulerSequence>();
  121. }
  122. }
  123. else
  124. {
  125. MoveItem pufToLoadPortItem=new MoveItem(pufModule,0,(ModuleName)waferInfo.OriginStation,
  126. waferInfo.OriginSlot,Aitex.Sorter.Common.Hand.Blade1);
  127. SchedulerSequence pufToLoaderSequence=CreateEfemRobotSequence(pufToLoadPortItem,null,sequenceRecipe.SubstrateSize, ref index);
  128. schedulerSequences.Add(pufToLoaderSequence);
  129. }
  130. return schedulerSequences;
  131. }
  132. /// <summary>
  133. /// 解析WaferHolder的所有工序
  134. /// </summary>
  135. /// <param name="waferHolderInfo"></param>
  136. /// <param name="sequenceRecipe"></param>
  137. /// <returns></returns>
  138. public List<SchedulerSequence> AnalyWaferHolderAllSchedulerSequence(WaferHolderInfo waferHolderInfo, SequenceRecipe sequenceRecipe,int waferCount)
  139. {
  140. int index = 0;
  141. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  142. //Buffer To Loader
  143. ModuleName currentLocationModuleName = (ModuleName)Enum.Parse(typeof(ModuleName), waferHolderInfo.CurrentLocation);
  144. TransporterAction transporterAction = GenerateTransporterTransferAction(currentLocationModuleName, ModuleType.Buffer, ModuleName.Loader1, ModuleType.Loader);
  145. string strTRNP = AnalyseLoadTransporterSide(sequenceRecipe, waferCount);
  146. List<SchedulerSyncModuleMessage> synModules = GenerateLoaderTransporterSyncModuleMessage(strTRNP);
  147. SchedulerSequence bufferToLoaderSequence = CreateLoaderTransporterSequence(transporterAction,synModules,waferHolderInfo.WaferSize, ref index);
  148. schedulerSequences.Add(bufferToLoaderSequence);
  149. //尺寸不一致
  150. bool needFlip = CheckLoaderWaferSizeNotEqual() && waferCount == 2;
  151. //Loader
  152. LoaderParameter parameter = new LoaderParameter();
  153. parameter.WaferCount= needFlip?1: waferCount;
  154. parameter.LoadCompleteToTransporterSide = strTRNP;
  155. parameter.NeedWaitFlip = needFlip;
  156. SchedulerSequence loaderSequence = CreateLoaderSequence(parameter,sequenceRecipe.SubstrateSize, ref index);
  157. schedulerSequences.Add(loaderSequence);
  158. if (needFlip)
  159. {
  160. string reverse = GetReverseTransporterLocation(strTRNP);
  161. TransporterAction flipAction = GenerateTransporterFlipAction(reverse);
  162. SchedulerSequence flipSequence=CreateLoaderTransporterSequence(flipAction,null,sequenceRecipe.SubstrateSize, ref index);
  163. schedulerSequences.Add(flipSequence);
  164. //Loader
  165. LoaderParameter reverseParameter = new LoaderParameter();
  166. reverseParameter.WaferCount = 1;
  167. reverseParameter.LoadCompleteToTransporterSide = reverse;
  168. reverseParameter.NeedWaitFlip = false;
  169. SchedulerSequence reverseLoadSequence = CreateLoaderSequence(reverseParameter,sequenceRecipe.SubstrateSize, ref index);
  170. schedulerSequences.Add(reverseLoadSequence);
  171. }
  172. //wafer holder装载后的recipe工序
  173. List<SchedulerSequence> waferHolderAfterLoadedAllSequences = WaferHolderAfterLoadedAllSchedulerSequences(waferHolderInfo, sequenceRecipe,ref index);
  174. schedulerSequences.AddRange(waferHolderAfterLoadedAllSequences);
  175. return schedulerSequences;
  176. }
  177. /// <summary>
  178. /// 解析LoaderTransporter放至Loader第一次确定TRNP的方向
  179. /// </summary>
  180. /// <param name="sequenceRecipe"></param>
  181. /// <param name="waferCount"></param>
  182. /// <returns></returns>
  183. private string AnalyseLoadTransporterSide(SequenceRecipe sequenceRecipe,int waferCount)
  184. {
  185. int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize");
  186. int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize");
  187. //单片,同时loader两边尺寸不一致
  188. if (waferCount == 1 && sideAWaferSize != sideBWaferSize)
  189. {
  190. //recipe使用B面工艺,但loader A面与recipe尺寸一致
  191. if (sequenceRecipe.LastSingleWaferToSideB && sequenceRecipe.SubstrateSize == sideAWaferSize)
  192. {
  193. return "TRNPB";
  194. }
  195. //recipe使用A面工艺,但loader B面与recipe尺寸一致
  196. else if (!sequenceRecipe.LastSingleWaferToSideB && sequenceRecipe.SubstrateSize == sideBWaferSize)
  197. {
  198. return "TRNPB";
  199. }
  200. }
  201. return "TRNPA";
  202. }
  203. private string GetReverseTransporterLocation(string strTrn)
  204. {
  205. return strTrn == TRNPA ? TRNPB : TRNPA;
  206. }
  207. /// <summary>
  208. /// 创建Transporter transfer指令
  209. /// </summary>
  210. /// <param name="source"></param>
  211. /// <param name="sourceType"></param>
  212. /// <param name="dest"></param>
  213. /// <param name="destType"></param>
  214. /// <returns></returns>
  215. private TransporterAction GenerateTransporterTransferAction(ModuleName source,ModuleType sourceType,ModuleName dest,ModuleType destType)
  216. {
  217. TransporterAction transporterAction = new TransporterAction();
  218. transporterAction.ActionMsg = TransporterMSG.Transfer;
  219. WaferHolderMoveItem waferHolderMoveItem = new WaferHolderMoveItem(source, sourceType, dest, destType);
  220. transporterAction.Parameter = waferHolderMoveItem;
  221. return transporterAction;
  222. }
  223. /// <summary>
  224. /// 创建Transporter pickup指令
  225. /// </summary>
  226. /// <param name="source"></param>
  227. /// <param name="sourceType"></param>
  228. /// <param name="dest"></param>
  229. /// <param name="destType"></param>
  230. /// <returns></returns>
  231. private TransporterAction GenerateTransporterFlipAction(string strTransporter)
  232. {
  233. TransporterAction transporterAction = new TransporterAction();
  234. transporterAction.ActionMsg = TransporterMSG.Flip;
  235. transporterAction.Parameter = strTransporter;
  236. return transporterAction;
  237. }
  238. /// <summary>
  239. /// 检验Loader两边waferSize不一致
  240. /// </summary>
  241. /// <returns></returns>
  242. private bool CheckLoaderWaferSizeNotEqual()
  243. {
  244. int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize");
  245. int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize");
  246. return sideAWaferSize != sideBWaferSize;
  247. }
  248. /// <summary>
  249. /// 创建LoaderTrasporter同步模块消息
  250. /// </summary>
  251. /// <param name="tranporter"></param>
  252. /// <returns></returns>
  253. private List<SchedulerSyncModuleMessage> GenerateLoaderTransporterSyncModuleMessage(string tranporter)
  254. {
  255. List<SchedulerSyncModuleMessage> synModules = new List<SchedulerSyncModuleMessage>();
  256. SchedulerSyncModuleMessage syncModuleMessage = new SchedulerSyncModuleMessage();
  257. syncModuleMessage.ModuleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(ModuleName.Loader1.ToString());
  258. syncModuleMessage.ModuleMsg = LoaderMSG.PrepareForPlace.ToString();
  259. syncModuleMessage.parameters = new object[] { tranporter };
  260. synModules.Add(syncModuleMessage);
  261. return synModules;
  262. }
  263. /// <summary>
  264. /// Dummy Wafer对应WaferHolder任务
  265. /// </summary>
  266. /// <param name="waferHolderInfo"></param>
  267. /// <returns></returns>
  268. public List<SchedulerSequence> AnalyseDummyWaferHolderAllSchedulerSequence(WaferHolderInfo waferHolderInfo,int waferCount)
  269. {
  270. int index = 0;
  271. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  272. string strTRNP = AnalyseLoadTransporterSide(waferHolderInfo.SequenceRecipe, waferCount);
  273. //Buffer To Loader
  274. ModuleName currentLocationModuleName = (ModuleName)Enum.Parse(typeof(ModuleName), waferHolderInfo.CurrentLocation);
  275. ModuleName bufferModule = (ModuleName)Enum.Parse(typeof(ModuleName), waferHolderInfo.OriginalBuffer);
  276. List<SchedulerSyncModuleMessage> synModules = GenerateLoaderTransporterSyncModuleMessage(strTRNP);
  277. TransporterAction transporterAction = GenerateTransporterTransferAction(currentLocationModuleName, ModuleType.Buffer, ModuleName.Loader1, ModuleType.Loader);
  278. SchedulerSequence bufferToLoaderSequence = CreateLoaderTransporterSequence(transporterAction,synModules,waferHolderInfo.WaferSize, ref index);
  279. schedulerSequences.Add(bufferToLoaderSequence);
  280. //尺寸不一致
  281. bool needFlip = CheckLoaderWaferSizeNotEqual() && waferCount == 2;
  282. //Loader
  283. LoaderParameter parameter = new LoaderParameter();
  284. parameter.WaferCount = needFlip ? 1 : waferCount; ;
  285. parameter.LoadCompleteToTransporterSide = strTRNP;
  286. parameter.NeedWaitFlip = needFlip;
  287. SchedulerSequence loaderSequence = CreateLoaderSequence(parameter,waferHolderInfo.WaferSize,ref index);
  288. schedulerSequences.Add(loaderSequence);
  289. if (needFlip)
  290. {
  291. string reverse = GetReverseTransporterLocation(strTRNP);
  292. TransporterAction flipAction = GenerateTransporterFlipAction(reverse);
  293. SchedulerSequence flipSequence = CreateLoaderTransporterSequence(flipAction, null,waferHolderInfo.WaferSize, ref index);
  294. schedulerSequences.Add(flipSequence);
  295. //Loader
  296. LoaderParameter reverseParameter = new LoaderParameter();
  297. reverseParameter.WaferCount = 1;
  298. reverseParameter.LoadCompleteToTransporterSide = reverse;
  299. reverseParameter.NeedWaitFlip = false;
  300. SchedulerSequence reverseLoadSequence = CreateLoaderSequence(reverseParameter,waferHolderInfo.WaferSize, ref index);
  301. schedulerSequences.Add(reverseLoadSequence);
  302. }
  303. //Loader To Buffer
  304. TransporterAction loaderMoveToBufferAction=GenerateTransporterTransferAction (ModuleName.Loader1, ModuleType.Loader,
  305. bufferModule, ModuleType.Buffer);
  306. SchedulerSequence loaderToBufferSequence = CreateLoaderTransporterSequence(loaderMoveToBufferAction,null,waferHolderInfo.WaferSize, ref index);
  307. schedulerSequences.Add(loaderToBufferSequence);
  308. return schedulerSequences;
  309. }
  310. /// <summary>
  311. /// 解析Dummy Wafer所有调度工序
  312. /// </summary>
  313. /// <param name="sequenceRecipe"></param>
  314. /// <returns></returns>
  315. public List<SchedulerSequence> AnalyDummyWaferAllSchedulerSequence(SequenceRecipe sequenceRecipe,WaferInfo waferInfo, ModuleName pufModule,string side)
  316. {
  317. waferInfo.LoaderSide = side;
  318. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  319. int index = 0;
  320. //DummyCassete至Aligner
  321. MoveItem moveItem = new MoveItem((ModuleName)waferInfo.Station, waferInfo.Slot, ModuleName.Aligner1, 0, Aitex.Sorter.Common.Hand.Blade1);
  322. SchedulerSequence secondEfemRobotSequence = CreateEfemRobotSequence(moveItem, null,sequenceRecipe.SubstrateSize, ref index);
  323. schedulerSequences.Add(secondEfemRobotSequence);
  324. //Aligner
  325. SchedulerSequence alignerSequence = null;
  326. if (sequenceRecipe == null)
  327. {
  328. alignerSequence= CreateAlignerSequence(0,sequenceRecipe.SubstrateSize, ref index);
  329. }
  330. else
  331. {
  332. alignerSequence=CreateAlignerSequence(sequenceRecipe.AlignmentAngle,sequenceRecipe.SubstrateSize, ref index);
  333. }
  334. schedulerSequences.Add(alignerSequence);
  335. //Aligner至Puf
  336. MoveItem alignerToPufMoveItem = new MoveItem(ModuleName.Aligner1, 0, pufModule, 1, Aitex.Sorter.Common.Hand.Blade1);
  337. SchedulerSequence alignerToPufEfemRobotSequence = CreateEfemRobotSequence(alignerToPufMoveItem, null,sequenceRecipe.SubstrateSize, ref index);
  338. schedulerSequences.Add(alignerToPufEfemRobotSequence);
  339. SchedulerSequence pufSequence = CreatePufSequence(pufModule,sequenceRecipe, side,true, ref index);
  340. schedulerSequences.Add(pufSequence);
  341. return schedulerSequences;
  342. }
  343. /// <summary>
  344. /// Loader装载后Recipe工序
  345. /// </summary>
  346. /// <param name="waferHolderInfo"></param>
  347. /// <param name="sequenceRecipe"></param>
  348. /// <param name="index"></param>
  349. /// <returns></returns>
  350. private List<SchedulerSequence> WaferHolderAfterLoadedAllSchedulerSequences(WaferHolderInfo waferHolderInfo,SequenceRecipe sequenceRecipe,ref int index)
  351. {
  352. List<SchedulerSequence> schedulerSequences = new List<SchedulerSequence>();
  353. if(!Enum.TryParse(waferHolderInfo.OriginalBuffer,out ModuleName moduleName))
  354. {
  355. return schedulerSequences;
  356. }
  357. //Loader To Buffer
  358. TransporterAction loaderMoveToBufferAction = GenerateTransporterTransferAction(ModuleName.Loader1, ModuleType.Loader,
  359. moduleName, ModuleType.Buffer);
  360. SchedulerSequence loaderToBufferSequence = CreateLoaderTransporterSequence(loaderMoveToBufferAction,null,sequenceRecipe.SubstrateSize, ref index);
  361. schedulerSequences.Add(loaderToBufferSequence);
  362. //解析sequence recipe后续的工序
  363. var result = AnalyseSequenceRecipeScheduler(sequenceRecipe);
  364. //buffer to recipe第一个工序
  365. TransporterAction bufferToFirstAction = GenerateTransporterTransferAction(moduleName, ModuleType.Buffer, ModuleName.Unknown, result.firstModuleType);
  366. SchedulerSequence bufferSequence = CreateLoaderTransporterSequence(bufferToFirstAction,null,sequenceRecipe.SubstrateSize, ref index);
  367. schedulerSequences.Add(bufferSequence);
  368. //调整工序后面的索引
  369. foreach (SchedulerSequence item in result.sequences)
  370. {
  371. item.SequenceIndex = index;
  372. index++;
  373. }
  374. schedulerSequences.AddRange(result.sequences);
  375. //从recipe最后工序
  376. TransporterAction lastToBufferAction = GenerateTransporterTransferAction(ModuleName.Unknown, result.lastModuleType, moduleName, ModuleType.Buffer);
  377. SchedulerSequence lastToBufferSequence = CreateLoaderTransporterSequence(lastToBufferAction,null,sequenceRecipe.SubstrateSize, ref index);
  378. schedulerSequences.Add(lastToBufferSequence);
  379. return schedulerSequences;
  380. }
  381. /// <summary>
  382. /// 分析Sequence recipe对应的调度步骤
  383. /// </summary>
  384. /// <param name="sequenceRecipe"></param>
  385. /// <returns></returns>
  386. private (ModuleType firstModuleType,List<SchedulerSequence> sequences,ModuleType lastModuleType) AnalyseSequenceRecipeScheduler(SequenceRecipe sequenceRecipe)
  387. {
  388. ModuleType firstModuleType = default;
  389. ModuleType lastModuleType = default;
  390. List<SchedulerSequence> schedulerSequences= new List<SchedulerSequence>();
  391. List<SchedulerSequence> tmpLst = new List<SchedulerSequence>();
  392. var processResult = AnalyseLastProcessRecipeIndex(sequenceRecipe.Recipes);
  393. bool isExistSrd = sequenceRecipe.Recipes.FindIndex(O=>O.ToLower().EndsWith("srd.rcp"))!=-1;
  394. int lastIndex = isExistSrd ? sequenceRecipe.Recipes.Count - 2 : sequenceRecipe.Recipes.Count - 1;
  395. for(int i=0;i<sequenceRecipe.Recipes.Count;i++)
  396. {
  397. string item = sequenceRecipe.Recipes[i];
  398. if(item.ToLower().EndsWith("srd.rcp"))//跳过SRD
  399. {
  400. continue;
  401. }
  402. SchedulerSequence schedulerSequence = new SchedulerSequence();
  403. schedulerSequence.ModuleName = ModuleName.Unknown;
  404. schedulerSequence.ModuleType=SequenceRecipeManager.Instance.GetModuleType(item);
  405. schedulerSequence.SequenceIndex=i;
  406. schedulerSequence.WaferSize = sequenceRecipe.SubstrateSize;
  407. MECF.Framework.Common.RecipeCenter.RecipeType recipeType =SequenceRecipeManager.Instance.GetRecipeType(item);
  408. schedulerSequence.Recipe = SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType,item, recipeType);
  409. schedulerSequence.SequenceType = sequenceRecipe.SequenceType;
  410. schedulerSequence.State = RState.Init;
  411. schedulerSequence.MaterialType = MaterialType.WaferHolder;
  412. tmpLst.Add(schedulerSequence);
  413. if (i == 0)
  414. {
  415. firstModuleType = schedulerSequence.ModuleType;
  416. }
  417. if(i==lastIndex)
  418. {
  419. lastModuleType = schedulerSequence.ModuleType;
  420. }
  421. else
  422. {
  423. string nextModule = sequenceRecipe.Recipes[i + 1];
  424. schedulerSequence.NextModuleType= SequenceRecipeManager.Instance.GetModuleType(nextModule);
  425. MECF.Framework.Common.RecipeCenter.RecipeType nextRecipeType = SequenceRecipeManager.Instance.GetRecipeType(nextModule);
  426. schedulerSequence.NextRecipe= SequenceRecipeManager.Instance.LoadSequenceTypeRecipe(sequenceRecipe.SequenceType,nextModule,nextRecipeType);
  427. }
  428. schedulerSequence.IsProcessSequece = true;
  429. if(i==processResult.lastIndex)
  430. {
  431. schedulerSequence.IsLastProcessSequence = true;
  432. }
  433. }
  434. int index = 0;
  435. for(int i=0;i<tmpLst.Count;i++)
  436. {
  437. tmpLst[i].SequenceIndex = 0;
  438. schedulerSequences.Add(tmpLst[i]);
  439. index++;
  440. if(i<tmpLst.Count-1)
  441. {
  442. TransporterAction transporterAction = new TransporterAction();
  443. transporterAction.ActionMsg = TransporterMSG.Transfer;
  444. WaferHolderMoveItem moveItem = new WaferHolderMoveItem(ModuleName.Unknown, tmpLst[i].ModuleType, ModuleName.Unknown, tmpLst[i + 1].ModuleType);
  445. transporterAction.Parameter = moveItem;
  446. SchedulerSequence schedulerSequence=CreateProcessTransporterSequence(transporterAction,sequenceRecipe.SubstrateSize,ref index);
  447. schedulerSequences.Add(schedulerSequence);
  448. }
  449. }
  450. return (firstModuleType,schedulerSequences,lastModuleType);
  451. }
  452. /// <summary>
  453. /// 分析最后加工recipe索引
  454. /// </summary>
  455. /// <param name="recipes"></param>
  456. /// <returns></returns>
  457. private (int lastIndex,List<int> processIndexList) AnalyseLastProcessRecipeIndex(List<string> recipes)
  458. {
  459. int index = 0;
  460. List<int> lst = new List<int>();
  461. for(int i=0;i<recipes.Count; i++)
  462. {
  463. string item=recipes[i];
  464. if(item.ToLower().EndsWith("dep.rcp"))
  465. {
  466. index = i;
  467. if(lst.Contains(i))
  468. {
  469. lst.Add(i);
  470. }
  471. }
  472. }
  473. if(lst.Count==0)
  474. {
  475. lst.Add(0);
  476. }
  477. return (index,lst);
  478. }
  479. /// <summary>
  480. /// 创建EFEM Robot步骤
  481. /// </summary>
  482. /// <param name="index"></param>
  483. /// <returns></returns>
  484. private SchedulerSequence CreateEfemRobotSequence(MoveItem moveItem,List<SchedulerSyncModuleMessage> synModules,int waferSize,ref int index)
  485. {
  486. SchedulerSequence sequence = new SchedulerSequence();
  487. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot);
  488. sequence.SequenceIndex= index;
  489. sequence.ModuleName=ModuleName.EfemRobot;
  490. sequence.State = RState.Init;
  491. sequence.Recipe = null;
  492. sequence.ModuleType=ModuleType.EfemRobot;
  493. sequence.Parameters =moveItem;
  494. sequence.MaterialType = MaterialType.Wafer;
  495. sequence.SynchronousModuleMessages = synModules;
  496. sequence.WaferSize = waferSize;
  497. index++;
  498. return sequence;
  499. }
  500. /// <summary>
  501. /// 创建Aligner步骤
  502. /// </summary>
  503. /// <param name="index"></param>
  504. /// <returns></returns>
  505. private SchedulerSequence CreateAlignerSequence(double angle,int waferSize,ref int index)
  506. {
  507. SchedulerSequence sequence = new SchedulerSequence();
  508. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Aligner1);
  509. sequence.SequenceIndex = index;
  510. sequence.ModuleName = ModuleName.Aligner1;
  511. sequence.State = RState.Init;
  512. sequence.Recipe = null;
  513. sequence.ModuleType = ModuleType.Aligner;
  514. sequence.Parameters = angle;
  515. sequence.MaterialType = MaterialType.Wafer;
  516. sequence.WaferSize = waferSize;
  517. index++;
  518. return sequence;
  519. }
  520. /// <summary>
  521. /// 创建PUF步骤
  522. /// </summary>
  523. /// <param name="pufModuleName"></param>
  524. /// <param name="index"></param>
  525. /// <returns></returns>
  526. private SchedulerSequence CreatePufSequence(ModuleName pufModuleName,SequenceRecipe sequenceRecipe,string side,bool forward,ref int index)
  527. {
  528. SchedulerSequence sequence = new SchedulerSequence();
  529. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(pufModuleName);
  530. sequence.SequenceIndex = index;
  531. sequence.ModuleName = pufModuleName;
  532. sequence.State = RState.Init;
  533. sequence.Recipe = sequenceRecipe;
  534. PufSchedulerParameter parameter = new PufSchedulerParameter()
  535. {
  536. IsForward = forward,
  537. Side = side,
  538. };
  539. sequence.Parameters = parameter;
  540. sequence.IsWaitNotify = !forward;
  541. sequence.ModuleType = ModuleType.PUF;
  542. sequence.MaterialType = MaterialType.Wafer;
  543. sequence.WaferSize = sequenceRecipe.SubstrateSize;
  544. index++;
  545. return sequence;
  546. }
  547. /// <summary>
  548. /// 创建Loader步骤
  549. /// </summary>
  550. /// <param name="index"></param>
  551. /// <returns></returns>
  552. private SchedulerSequence CreateLoaderSequence(LoaderParameter parameter,int waferSize,ref int index)
  553. {
  554. SchedulerSequence sequence = new SchedulerSequence();
  555. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Loader1);
  556. sequence.SequenceIndex = index;
  557. sequence.ModuleName = ModuleName.Loader1;
  558. sequence.State = RState.Init;
  559. sequence.Recipe = null;
  560. sequence.Parameters = parameter;
  561. sequence.ModuleType = ModuleType.Loader;
  562. sequence.MaterialType = MaterialType.WaferHolder;
  563. sequence.WaferSize = waferSize;
  564. index++;
  565. return sequence;
  566. }
  567. /// <summary>
  568. /// 创建Loader步骤
  569. /// </summary>
  570. /// <param name="index"></param>
  571. /// <returns></returns>
  572. private SchedulerSequence CreateSRDSequence(SrdRecipe recipe,ref int index)
  573. {
  574. SchedulerSequence sequence = new SchedulerSequence();
  575. sequence.SequenceIndex = index;
  576. sequence.State = RState.Init;
  577. sequence.Recipe = recipe;
  578. sequence.ModuleType = ModuleType.SRD;
  579. sequence.MaterialType = MaterialType.Wafer;
  580. index++;
  581. return sequence;
  582. }
  583. /// <summary>
  584. /// 创建LoaderTransporter步骤
  585. /// </summary>
  586. /// <param name="index"></param>
  587. /// <returns></returns>
  588. private SchedulerSequence CreateLoaderTransporterSequence(TransporterAction transporterAction, List<SchedulerSyncModuleMessage> synModules,int waferSize, ref int index)
  589. {
  590. SchedulerSequence sequence = new SchedulerSequence();
  591. sequence.ModuleType = ModuleType.Transporter;
  592. sequence.ModuleName = ModuleName.Transporter2;
  593. sequence.SequenceIndex = index;
  594. sequence.State = RState.Init;
  595. sequence.Recipe = null;
  596. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Transporter2);
  597. sequence.Parameters = transporterAction;
  598. sequence.MaterialType = MaterialType.WaferHolder;
  599. sequence.SynchronousModuleMessages = synModules;
  600. sequence.WaferSize = waferSize;
  601. index++;
  602. return sequence;
  603. }
  604. /// <summary>
  605. /// 创建LoaderTransporter步骤
  606. /// </summary>
  607. /// <param name="index"></param>
  608. /// <returns></returns>
  609. private SchedulerSequence CreateProcessTransporterSequence(TransporterAction transporterAction,int waferSize, ref int index)
  610. {
  611. SchedulerSequence sequence = new SchedulerSequence();
  612. sequence.ModuleType = ModuleType.Transporter;
  613. sequence.ModuleName = ModuleName.Transporter1;
  614. sequence.SequenceIndex = index;
  615. sequence.State = RState.Init;
  616. sequence.Recipe = null;
  617. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Transporter1);
  618. sequence.Parameters= transporterAction;
  619. sequence.MaterialType = MaterialType.WaferHolder;
  620. sequence.WaferSize = waferSize;
  621. index++;
  622. return sequence;
  623. }
  624. /// <summary>
  625. /// 获取可用Dummy slot
  626. /// </summary>
  627. /// <param name="moduleType"></param>
  628. /// <returns></returns>
  629. public (ModuleName moduleName, int slot) GetAvaibleDummySlots(WaferSize waferSize)
  630. {
  631. if (ModuleHelper.IsInstalled(ModuleName.Dummy1))
  632. {
  633. DummyEntity dummyEntity = Singleton<RouteManager>.Instance.GetModule<DummyEntity>(ModuleName.Dummy1.ToString());
  634. DummyDevice dummyDevice = Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(0);
  635. if (dummyDevice != null && dummyDevice.HasCassette && dummyDevice.WaferSize == waferSize)
  636. {
  637. for (int i = 0; i < dummyEntity.MaxSlotNumber; i++)
  638. {
  639. if (WaferManager.Instance.CheckNoWafer(ModuleName.Dummy1, i))
  640. {
  641. return (ModuleName.Dummy1, i);
  642. }
  643. }
  644. }
  645. }
  646. if (ModuleHelper.IsInstalled(ModuleName.Dummy2))
  647. {
  648. DummyEntity dummyEntity = Singleton<RouteManager>.Instance.GetModule<DummyEntity>(ModuleName.Dummy2.ToString());
  649. DummyDevice dummyDevice = Singleton<RouteManager>.Instance.EFEM.GetDummyDevice(1);
  650. if (dummyDevice != null && dummyDevice.HasCassette && dummyDevice.WaferSize == waferSize)
  651. {
  652. for (int i = 0; i < dummyEntity.MaxSlotNumber; i++)
  653. {
  654. if (WaferManager.Instance.CheckNoWafer(ModuleName.Dummy2, i))
  655. {
  656. return (ModuleName.Dummy2, i);
  657. }
  658. }
  659. }
  660. }
  661. return (ModuleName.Unknown, -1);
  662. }
  663. /// <summary>
  664. /// 根据模块类型获取可用模块
  665. /// </summary>
  666. /// <param name="moduleType"></param>
  667. /// <returns></returns>
  668. public ModuleName GetAvaibleModuleCell(string sequenceType,ModuleType moduleType, ModuleName moduleName = ModuleName.Unknown)
  669. {
  670. if (ModuleHelper.IsMetal(moduleName))
  671. {
  672. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  673. return GetMetalAvaibleRinseModule(entities, moduleName);
  674. }
  675. else
  676. {
  677. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  678. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  679. foreach (var item in entities)
  680. {
  681. bool result = CheckAvaibleModule(item,moduleType,sequenceType);
  682. if (result)
  683. {
  684. avaibles.Add(item);
  685. }
  686. }
  687. return GetMinTimeToReadyModule(avaibles,moduleType);
  688. }
  689. }
  690. /// <summary>
  691. /// 根据模块类型获取可用模块(不包含WH)
  692. /// </summary>
  693. /// <param name="moduleType"></param>
  694. /// <returns></returns>
  695. public ModuleName GetAvaibleEmptyModuleCell(ModuleType moduleType,string sequenceType, ModuleName moduleName = ModuleName.Unknown)
  696. {
  697. if (ModuleHelper.IsMetal(moduleName))
  698. {
  699. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  700. return GetMetalAvaibleEmptyRinseModule(entities, moduleName);
  701. }
  702. else
  703. {
  704. List<IModuleEntity> entities = Singleton<RouteManager>.Instance.GetModulesByModuleType(moduleType);
  705. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  706. foreach (var item in entities)
  707. {
  708. bool result = CheckAvaibleModule(item,moduleType,sequenceType);
  709. if (result&&!WaferHolderManager.Instance.HasWaferHolder(item.Module.ToString()))
  710. {
  711. avaibles.Add(item);
  712. }
  713. }
  714. return avaibles.Count != 0 ? avaibles[0].Module : ModuleName.Unknown;
  715. }
  716. }
  717. /// <summary>
  718. /// 根据化学液计算时间获取可用MetalCell(参考其他Metal剩余时间)
  719. /// </summary>
  720. /// <param name="chemistry"></param>
  721. /// <returns></returns>
  722. public ModuleName CalculateAvaibleMetalCellByChemistry(string chemistry,string startRinse,string sequenceType,int waferSize,ref bool isExistEnableMetal)
  723. {
  724. if(!Enum.TryParse(startRinse,out ModuleName startRinseModule)||!ModuleHelper.IsRinse(startRinseModule))
  725. {
  726. startRinse = "";
  727. }
  728. isExistEnableMetal = false;
  729. List<MetalEntity> moduleEntities = GetAvaibleMetalList(chemistry,sequenceType,waferSize,true);
  730. List<IModuleEntity> avaibleMetalEntities = new List<IModuleEntity>();
  731. foreach (var item in moduleEntities)
  732. {
  733. if(CheckAvaibleModule(item,ModuleType.Metal,sequenceType))
  734. {
  735. if (item.WaferHolderInfo == null)
  736. {
  737. if (CheckMetalModuleRinseAvaible(item, startRinse))
  738. {
  739. avaibleMetalEntities.Add(item);
  740. }
  741. }
  742. isExistEnableMetal = true;
  743. }
  744. }
  745. if (avaibleMetalEntities.Count > 0)
  746. {
  747. return GetMinUsageMetal(avaibleMetalEntities);
  748. }
  749. return ModuleName.Unknown;
  750. }
  751. /// <summary>
  752. /// 根据化学液获取可用Metal
  753. /// </summary>
  754. /// <param name="chemistry"></param>
  755. /// <param name="sequenceType"></param>
  756. /// <returns></returns>
  757. public bool CalculateAvaibleMetalCellByChemistry(string chemistry,string sequenceType,int waferSize)
  758. {
  759. List<MetalEntity> moduleEntities = GetAvaibleMetalList(chemistry, sequenceType,waferSize,false);
  760. return moduleEntities.Count != 0;
  761. }
  762. /// <summary>
  763. /// 检验Metal模块Rinse可用性
  764. /// </summary>
  765. /// <param name="item"></param>
  766. /// <returns></returns>
  767. private bool CheckMetalModuleRinseAvaible(MetalEntity item,string startRinse)
  768. {
  769. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(item.Module.ToString());
  770. List<string> sharedRinseItems = new List<string>();
  771. List<string> singleRinseItems = new List<string>();
  772. foreach (var cellItem in rinseItems)
  773. {
  774. RinseEntity rinseEntity = Singleton<RouteManager>.Instance.GetModule<RinseEntity>(cellItem.ModuleName);
  775. if (!CellItemManager.Instance.CheckRinseIsShared(cellItem.ModuleName))
  776. {
  777. if (CheckAvaibleModule(rinseEntity, ModuleType.Rinse, "") && rinseEntity.WaferHolderInfo == null)
  778. {
  779. singleRinseItems.Add(cellItem.ModuleName);
  780. }
  781. }
  782. else
  783. {
  784. if (CheckAvaibleModule(rinseEntity,ModuleType.Rinse,"") && rinseEntity.WaferHolderInfo == null)
  785. {
  786. sharedRinseItems.Add(cellItem.ModuleName);
  787. }
  788. //增加自己
  789. if (cellItem.ModuleName == startRinse && rinseEntity != null && (rinseEntity.IsIdle||rinseEntity.State==(int)RinseState.KeepWeting))
  790. {
  791. sharedRinseItems.Add(startRinse);
  792. }
  793. }
  794. }
  795. //独立的Rinse集合
  796. if(singleRinseItems.Count!=0)
  797. {
  798. bool result = CheckSingleRinseItemsCanUsed(singleRinseItems, item.Module.ToString());
  799. if(result)
  800. {
  801. return true;
  802. }
  803. }
  804. //仅剩下共享Rinse
  805. List<string> avaibleSharedList = new List<string>();
  806. if (sharedRinseItems.Count != 0)
  807. {
  808. foreach (string sharedRinse in sharedRinseItems)
  809. {
  810. RinseEntity rinseEntity = Singleton<RouteManager>.Instance.GetModule<RinseEntity>(sharedRinse);
  811. if (rinseEntity.IsBusy&&sharedRinse!=startRinse)
  812. {
  813. continue;
  814. }
  815. //检验共享Rinse是否可用
  816. if (CheckShardRinseCanUse(sharedRinse, item.Module.ToString(),startRinse))
  817. {
  818. avaibleSharedList.Add(sharedRinse);
  819. }
  820. }
  821. }
  822. if (avaibleSharedList.Count != 0)
  823. {
  824. var result = CalculateMetalReservoirAllBusyMetalCount(item.Module.ToString());
  825. if (result.success)
  826. {
  827. bool transporterTransfering = CheckProcessTransporterTransfering(avaibleSharedList);
  828. if(transporterTransfering)
  829. {
  830. return result.busyCount + 1 < avaibleSharedList.Count;
  831. }
  832. else
  833. {
  834. return result.busyCount < avaibleSharedList.Count+singleRinseItems.Count;
  835. }
  836. }
  837. }
  838. return false;
  839. }
  840. /// <summary>
  841. /// 检验Process transporter正在Transfer WH移动至Rinse
  842. /// </summary>
  843. /// <returns></returns>
  844. private bool CheckProcessTransporterTransfering(List<string> rinseList)
  845. {
  846. TransporterEntity processTransporterEntity = Singleton<RouteManager>.Instance.GetModule<TransporterEntity>(ModuleName.Transporter1.ToString());
  847. if(processTransporterEntity!=null)
  848. {
  849. if (processTransporterEntity.IsBusy)
  850. {
  851. string targetCell = processTransporterEntity.TargetCell;
  852. if (rinseList.Contains(targetCell))
  853. {
  854. return true;
  855. }
  856. }
  857. }
  858. return false;
  859. }
  860. /// <summary>
  861. /// 计算Metal所在Reservoir Busy Metal数量
  862. /// </summary>
  863. /// <param name="item"></param>
  864. /// <returns></returns>
  865. private (bool success,int busyCount) CalculateMetalReservoirAllBusyMetalCount(string metalName)
  866. {
  867. string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(metalName);
  868. if (string.IsNullOrEmpty(reservoirName))
  869. {
  870. return (false,0);
  871. }
  872. List<string> metals = ReservoirItemManager.Instance.GetMetalsByReservoir(reservoirName);
  873. int count = 0;
  874. foreach (string item in metals)
  875. {
  876. if (metalName == item)
  877. {
  878. continue;
  879. }
  880. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(item);
  881. if (metalEntity.IsBusy || metalEntity.WaferHolderInfo != null)
  882. {
  883. count++;
  884. }
  885. }
  886. return (true,count);
  887. }
  888. /// <summary>
  889. /// 检验独立Rinse是否可用
  890. /// </summary>
  891. /// <param name="singleRinseItems"></param>
  892. /// <param name="metalName"></param>
  893. /// <returns></returns>
  894. private bool CheckSingleRinseItemsCanUsed(List<string> singleRinseItems, string metalName)
  895. {
  896. var result = CalculateMetalReservoirAllBusyMetalCount(metalName);
  897. if(result.success)
  898. {
  899. bool transporterTransfering = CheckProcessTransporterTransfering(singleRinseItems);
  900. if (transporterTransfering)
  901. {
  902. return result.busyCount + 1 < singleRinseItems.Count;
  903. }
  904. else
  905. {
  906. return result.busyCount < singleRinseItems.Count;
  907. }
  908. }
  909. return false;
  910. }
  911. /// <summary>
  912. /// 检验共享Rinse是否可用
  913. /// </summary>
  914. /// <param name="sharedRinse"></param>
  915. /// <param name="metalName"></param>
  916. /// <returns></returns>
  917. private bool CheckShardRinseCanUse(string sharedRinse, string metalName,string startRinse)
  918. {
  919. string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(metalName);
  920. List<string> shardReservoirs = CellItemManager.Instance.GetReservoirsBySharedRinse(sharedRinse);
  921. if (shardReservoirs == null || shardReservoirs.Count == 0)
  922. {
  923. return false;
  924. }
  925. foreach (string reservoir in shardReservoirs)
  926. {
  927. if (reservoir==reservoirName)
  928. {
  929. continue;
  930. }
  931. List<string> metals=ReservoirItemManager.Instance.GetMetalsByReservoir(reservoir);
  932. int metalCount = 0;
  933. int busyMetalCount = 0;
  934. foreach(string metal in metals)
  935. {
  936. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(metal);
  937. if(metalEntity.IsAuto&&metalEntity.IsInitialized)
  938. {
  939. metalCount++;
  940. }
  941. if(metalEntity.IsBusy||metalEntity.WaferHolderInfo!=null)
  942. {
  943. busyMetalCount++;
  944. }
  945. }
  946. List<string> reservoirRinseLst = CellItemManager.Instance.GetRinsesByReservoir(reservoir);
  947. int rinseCount = 0;
  948. int busyRinseCount = 0;
  949. foreach(string rinseItem in reservoirRinseLst)
  950. {
  951. RinseEntity rinseEntity = Singleton<RouteManager>.Instance.GetModule<RinseEntity>(rinseItem);
  952. if(rinseEntity.IsAuto&&rinseEntity.IsInitialized)
  953. {
  954. rinseCount++;
  955. }
  956. if (rinseItem == sharedRinse)
  957. {
  958. continue;
  959. }
  960. if (rinseItem == startRinse)
  961. {
  962. continue;
  963. }
  964. if(rinseEntity.IsBusy||rinseEntity.WaferHolderInfo!=null)
  965. {
  966. busyRinseCount++;
  967. }
  968. }
  969. int resRinseCount=rinseCount- busyRinseCount;
  970. //计算剩余Rinse数量小于等于busy metal数量,则不可用
  971. if (resRinseCount <= busyMetalCount)
  972. {
  973. return false;
  974. }
  975. }
  976. return true;
  977. }
  978. /// <summary>
  979. /// 检验模块是否可用(不包含WH)
  980. /// </summary>
  981. /// <param name="item"></param>
  982. /// <returns></returns>
  983. private bool CheckAvaibleEmptyModule(IModuleEntity item,ModuleType moduleType,string sequenceType)
  984. {
  985. if (!CheckAvaibleModule(item, moduleType, sequenceType))
  986. {
  987. return false;
  988. }
  989. if (!ModuleHelper.IsSRD(item.Module))
  990. {
  991. WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(item.Module.ToString());
  992. if (waferHolderInfo == null)
  993. {
  994. return true;
  995. }
  996. }
  997. else
  998. {
  999. if (!WaferManager.Instance.CheckHasWafer(item.Module, 0))
  1000. {
  1001. return true;
  1002. }
  1003. }
  1004. return false;
  1005. }
  1006. /// <summary>
  1007. /// 检验模块是否可用
  1008. /// </summary>
  1009. /// <param name="item"></param>
  1010. /// <returns></returns>
  1011. public bool CheckAvaibleModule(IModuleEntity item,ModuleType moduleType,string sequenceType)
  1012. {
  1013. if (item.IsDisable)
  1014. {
  1015. return false;
  1016. }
  1017. if (!item.IsAuto)
  1018. {
  1019. return false;
  1020. }
  1021. if (item.IsError)
  1022. {
  1023. return false;
  1024. }
  1025. if (item.IsInit)
  1026. {
  1027. return false;
  1028. }
  1029. if (moduleType==ModuleType.Metal)
  1030. {
  1031. if(item.IsProduction && sequenceType == ENGINEERING)
  1032. return false;
  1033. if (item.IsEngineering && sequenceType == PRODUCTION)
  1034. return false;
  1035. }
  1036. return true;
  1037. }
  1038. /// <summary>
  1039. /// 获取剩余时间最小的模块
  1040. /// </summary>
  1041. /// <param name="avaibles"></param>
  1042. /// <returns></returns>
  1043. private ModuleName GetMinTimeToReadyModule(List<IModuleEntity> avaibles,ModuleType moduleType)
  1044. {
  1045. if (avaibles.Count == 1)
  1046. {
  1047. return avaibles[0].Module;
  1048. }
  1049. int timeToReady = int.MaxValue;
  1050. IModuleEntity selectedModule = null;
  1051. List<IModuleEntity> idleModuleEtities = new List<IModuleEntity>();
  1052. foreach (var item in avaibles)
  1053. {
  1054. if (item.IsIdle)
  1055. {
  1056. if(moduleType!=ModuleType.Metal)
  1057. {
  1058. return item.Module;
  1059. }
  1060. idleModuleEtities.Add(item);
  1061. }
  1062. if (item.TimeToReady < timeToReady&&idleModuleEtities.Count==0)
  1063. {
  1064. timeToReady = item.TimeToReady;
  1065. selectedModule = item;
  1066. }
  1067. }
  1068. if (idleModuleEtities.Count != 0)
  1069. {
  1070. return GetMinUsageMetal(idleModuleEtities);
  1071. }
  1072. if (selectedModule != null)
  1073. {
  1074. return selectedModule.Module;
  1075. }
  1076. return ModuleName.Unknown;
  1077. }
  1078. /// <summary>
  1079. /// 获取电量最小的Metal
  1080. /// </summary>
  1081. /// <param name="idleModuleEntities"></param>
  1082. /// <returns></returns>
  1083. private ModuleName GetMinUsageMetal(List<IModuleEntity> idleModuleEntities)
  1084. {
  1085. double usage = double.MaxValue;
  1086. ModuleName selectedModuleName = ModuleName.Unknown;
  1087. foreach (var item in idleModuleEntities)
  1088. {
  1089. MetalEntity metalEntity= item as MetalEntity;
  1090. if(metalEntity!=null)
  1091. {
  1092. MetalUsage metalUsage = metalEntity.MetalUsage;
  1093. if (metalUsage == null)
  1094. {
  1095. return metalEntity.Module;
  1096. }
  1097. if (metalUsage.TotalUsage < usage)
  1098. {
  1099. usage= metalUsage.TotalUsage;
  1100. selectedModuleName = metalEntity.Module;
  1101. }
  1102. }
  1103. }
  1104. return selectedModuleName;
  1105. }
  1106. /// <summary>
  1107. /// 获取Metal可用的Rinse模块
  1108. /// </summary>
  1109. /// <param name="metalName"></param>
  1110. /// <returns></returns>
  1111. private ModuleName GetMetalAvaibleRinseModule(List<IModuleEntity> items, ModuleName metalName)
  1112. {
  1113. int metalId = CellItemManager.Instance.GetCellIdByModuleName(metalName.ToString());
  1114. if (metalId == 0)
  1115. {
  1116. return ModuleName.Unknown;
  1117. }
  1118. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(metalName.ToString());
  1119. if (rinseItems.Count == 0)
  1120. {
  1121. return ModuleName.Unknown;
  1122. }
  1123. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  1124. foreach (var item in items)
  1125. {
  1126. LayoutCellItem cellItem = rinseItems.Find(O => O.ModuleName == item.Module.ToString());
  1127. if (cellItem != null)
  1128. {
  1129. RinseEntity rinseEntity = (RinseEntity)item;
  1130. if (rinseEntity.IsInitialized && rinseEntity.IsAuto)
  1131. {
  1132. avaibles.Add(rinseEntity);
  1133. }
  1134. }
  1135. }
  1136. int minInterval = int.MaxValue;
  1137. IModuleEntity moduleEntity = null;
  1138. foreach (var item in avaibles)
  1139. {
  1140. LayoutCellItem cellItem = rinseItems.Find(O => O.ModuleName == item.Module.ToString());
  1141. if (cellItem != null)
  1142. {
  1143. int abiasId = Math.Abs(metalId - cellItem.CellID);
  1144. if (abiasId < minInterval)
  1145. {
  1146. minInterval = abiasId;
  1147. moduleEntity = item;
  1148. }
  1149. }
  1150. }
  1151. if (moduleEntity != null)
  1152. {
  1153. return moduleEntity.Module;
  1154. }
  1155. return ModuleName.Unknown;
  1156. }
  1157. /// <summary>
  1158. /// 检验Metal可用的Rinse模块
  1159. /// </summary>
  1160. /// <param name="metalName"></param>
  1161. /// <returns></returns>
  1162. private ModuleName GetMetalAvaibleEmptyRinseModule(List<IModuleEntity> items, ModuleName metalName)
  1163. {
  1164. int metalId = CellItemManager.Instance.GetCellIdByModuleName(metalName.ToString());
  1165. if (metalId == 0)
  1166. {
  1167. return ModuleName.Unknown;
  1168. }
  1169. List<LayoutCellItem> rinseItems = CellItemManager.Instance.GetRinseItemsByMetal(metalName.ToString());
  1170. if (rinseItems.Count == 0)
  1171. {
  1172. return ModuleName.Unknown;
  1173. }
  1174. List<IModuleEntity> avaibles = new List<IModuleEntity>();
  1175. List<ModuleName> sharedRinseList = new List<ModuleName>();
  1176. foreach (var item in items)
  1177. {
  1178. LayoutCellItem cellItem = rinseItems.Find(O => O.ModuleName == item.Module.ToString());
  1179. if (cellItem != null)
  1180. {
  1181. RinseEntity rinseEntity = (RinseEntity)item;
  1182. if (rinseEntity.IsIdle && rinseEntity.IsAuto && rinseEntity.WaferHolderInfo == null)
  1183. {
  1184. avaibles.Add(rinseEntity);
  1185. if(CellItemManager.Instance.CheckRinseIsShared(rinseEntity.Module.ToString()))
  1186. {
  1187. sharedRinseList.Add(rinseEntity.Module);
  1188. }
  1189. }
  1190. }
  1191. }
  1192. int minInterval = int.MaxValue;
  1193. IModuleEntity moduleEntity = null;
  1194. foreach (var item in avaibles)
  1195. {
  1196. if (sharedRinseList.Contains(item.Module))
  1197. {
  1198. continue;
  1199. }
  1200. LayoutCellItem cellItem = rinseItems.Find(O => O.ModuleName == item.Module.ToString());
  1201. if (cellItem != null)
  1202. {
  1203. int abiasId = Math.Abs(metalId - cellItem.CellID);
  1204. if (abiasId < minInterval)
  1205. {
  1206. minInterval = abiasId;
  1207. moduleEntity = item;
  1208. }
  1209. }
  1210. }
  1211. if (moduleEntity != null)
  1212. {
  1213. return moduleEntity.Module;
  1214. }
  1215. else if(sharedRinseList.Count!=0)
  1216. {
  1217. return sharedRinseList[0];
  1218. }
  1219. return ModuleName.Unknown;
  1220. }
  1221. /// <summary>
  1222. /// 检验Metal cell recipe时间是否可用
  1223. /// </summary>
  1224. /// <param name="depRecipe"></param>
  1225. /// <returns></returns>
  1226. public bool CheckMetalCellRecipeTimeAvaible(IModuleEntity metalEntity,DepRecipe depRecipe)
  1227. {
  1228. List<IModuleEntity> metalEntities=Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.Metal);
  1229. int maxTimeToReady = 0;
  1230. foreach (MetalEntity item in metalEntities)
  1231. {
  1232. if (metalEntity.Module == item.Module)
  1233. {
  1234. continue;
  1235. }
  1236. if(item.IsBusy)
  1237. {
  1238. if(maxTimeToReady>item.TimeToReady)
  1239. {
  1240. maxTimeToReady = item.TimeToReady;
  1241. }
  1242. }
  1243. }
  1244. int transferOffSecond = SC.GetValue<int>("Transporter.TransporterTransferOffSeconds");
  1245. int recipeTotalTime = depRecipe.CalculateRecipeTotalTime();
  1246. //增加了Transporter最大传输时间和最小传输时间的差值
  1247. if (recipeTotalTime>=maxTimeToReady+transferOffSecond)
  1248. {
  1249. return true;
  1250. }
  1251. return false;
  1252. }
  1253. /// <summary>
  1254. /// 根据化学液获取可用的metal集合
  1255. /// </summary>
  1256. /// <param name="chemistry"></param>
  1257. /// <returns></returns>
  1258. public List<MetalEntity> GetAvaibleMetalList(string chemistry, string sequenceType,int waferSize, bool isEmpty)
  1259. {
  1260. List<IModuleEntity> reservoirEntities = Singleton<RouteManager>.Instance.GetModulesByModuleType(ModuleType.Reservoir);
  1261. List<string> avaibles = new List<string>();
  1262. foreach (IModuleEntity item in reservoirEntities)
  1263. {
  1264. ReservoirEntity entity = item as ReservoirEntity;
  1265. if (entity.Chemistry == chemistry && entity.IsAuto && entity.IsInitialized)
  1266. {
  1267. avaibles.Add(entity.Module.ToString());
  1268. }
  1269. }
  1270. List<MetalEntity> metals = new List<MetalEntity>();
  1271. foreach (string item in avaibles)
  1272. {
  1273. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(item);
  1274. if (reservoirItem == null)
  1275. {
  1276. continue;
  1277. }
  1278. foreach (MetalItem subItem in reservoirItem.MetalCells)
  1279. {
  1280. MetalEntity entity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>($"Metal{subItem.MetalID}");
  1281. if (!CheckAvaibleModule(entity, ModuleType.Metal, sequenceType))
  1282. {
  1283. continue;
  1284. }
  1285. if (entity.MetalWaferSize != waferSize)
  1286. {
  1287. continue;
  1288. }
  1289. if (!isEmpty || (isEmpty && entity.WaferHolderInfo == null))
  1290. {
  1291. metals.Add(entity);
  1292. }
  1293. }
  1294. }
  1295. return metals;
  1296. }
  1297. /// <summary>
  1298. /// 获取上一个Metal
  1299. /// </summary>
  1300. /// <param name="sequenceIndex"></param>
  1301. /// <param name="sequences"></param>
  1302. /// <returns></returns>
  1303. public ModuleName GetPreMetalModuleName(int sequenceIndex,List<SchedulerSequence> sequences)
  1304. {
  1305. for(int i = sequenceIndex - 1; i >= 0; i--)
  1306. {
  1307. SchedulerSequence schedulerSequence= sequences[i];
  1308. if (schedulerSequence.ModuleType == ModuleType.Metal && ModuleHelper.IsMetal(schedulerSequence.ModuleName))
  1309. {
  1310. return schedulerSequence.ModuleName;
  1311. }
  1312. }
  1313. return ModuleName.Unknown;
  1314. }
  1315. }
  1316. }