123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using System.Timers;
- using Aitex.Core.Common;
- using Aitex.Core.RT.DataCenter;
- using Aitex.Core.RT.Device;
- using Aitex.Core.RT.Event;
- using Aitex.Core.RT.Log;
- using Aitex.Core.RT.OperationCenter;
- using Aitex.Core.RT.RecipeCenter;
- using Aitex.Core.RT.Routine;
- using Aitex.Core.RT.SCCore;
- using Aitex.Core.Util;
- using Aitex.Sorter.Common;
- using MECF.Framework.Common.DBCore;
- using MECF.Framework.Common.Equipment;
- using MECF.Framework.Common.Jobs;
- using MECF.Framework.Common.Schedulers;
- using MECF.Framework.Common.SubstrateTrackings;
- using MECF.Framework.RT.ModuleLibrary.PMModules;
- using MECF.Framework.RT.ModuleLibrary.SystemModules;
- using MECF.Framework.RT.ModuleLibrary.SystemModules.Routines;
- using EfemDualSchedulerLib.Schedulers;
- using MECF.Framework.Common.DataCenter;
- using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadLocks;
- using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
- using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
- using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots;
- using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.TMs;
- using JetVirgoPM.PMs.RecipeExecutors;
- namespace EfemDualSchedulerLib
- {
- /// <summary>
- /// 自动传输
- /// </summary>
- public partial class AutoTransfer : SchedulerModuleFactory, IAutoTransfer
- {
- #region 常量
- /// <summary>
- /// ProcessJob状态变化
- /// </summary>
- private const string E40ProcessStateChanged = "E40ProcessStateChanged";
- #endregion
- //const Hand Hand_Dual = Hand.Blade1;
- //const Hand Hand_Single = Hand.Blade2;
- //用于避免两爪都有wafer,放了一片就又去LoadPort Pick
- private bool EfemRobotPickAllowable = true;
- private bool _isRunningInParallelMode;
- private List<ModuleName> _mapTarget = new List<ModuleName>();
- private List<ControlJobInfo> _lstControlJobs = new List<ControlJobInfo>();
- private List<ProcessJobInfo> _lstProcessJobs = new List<ProcessJobInfo>();
- //private Object _locker = new Object();
- private List<SchedulerPM> _lstPms = new List<SchedulerPM>();
- private List<SchedulerLoadPort> _lstLps = new List<SchedulerLoadPort>();
- private List<SchedulerLoadLock> _lstLls = new List<SchedulerLoadLock>();
- private List<SchedulerAligner> _lstAligners = new List<SchedulerAligner>();
- private List<SchedulerAligner> _lstCoolings = new List<SchedulerAligner>();
- private List<SchedulerPM> _lstPmsCurrentSequence = new List<SchedulerPM>();
- private R_TRIG _trigLp1JobComplete = new R_TRIG();
- private R_TRIG _trigLp2JobComplete = new R_TRIG();
- private R_TRIG _trigLp3JobComplete = new R_TRIG();
- private Dictionary<ModuleName, R_TRIG> _checkNoCarrierByModule = new Dictionary<ModuleName, R_TRIG>();
- private Dictionary<string, float> _temperatureSetpointDic = new Dictionary<string, float>();
- private Dictionary<string, R_TRIG> _temperatureTrigDic = new Dictionary<string, R_TRIG>();
- private Dictionary<string, List<string>> currentSlotSequenceList = new Dictionary<string, List<string>>()
- {
- {"LP1",Enumerable.Repeat("",25).ToList()},
- {"LP2",Enumerable.Repeat("",25).ToList()},
- {"LP3",Enumerable.Repeat("",25).ToList()}
- };
- private const string LogSource = "Scheduler";
- private int[] _pmSlots = new int[] { 0, 1 };
- private int[] _llSlots = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 };
- private Dictionary<ModuleName, Tuple<R_TRIG, DeviceTimer>> _pmSwapWaitTimeOut = new Dictionary<ModuleName, Tuple<R_TRIG, DeviceTimer>>();
- public bool PreheatDone { get; set; }
- //private bool _isCycleMode;
- //private int _cycleSetPoint = 0;
- //private int _cycledCount = 0;
- //private int _cycledWafer = 0;
- private SchedulerFACallback _faCallback;
- private SchedulerDBCallback _dbCallback;
- //private float _throughput;
- //private DeviceTimer _throughputTimer = new DeviceTimer();
- //private int _processedWaferCountInFinishedCJ;
- class CycleData
- {
- public DateTime StartTime { get; private set; }
- public TimeSpan EscapeTime => _lpCycleTime.Count == 0 ? TimeSpan.Zero : DateTime.Now.Subtract(_lpCycleTime.Values.Min());
- public bool IsCycleMode => SC.GetValue<bool>("System.IsCycleMode");
- public string CycleBy => SC.GetStringValue("System.CycleBy");
- public int CycleCountSetPoint => SC.GetValue<int>("System.CycleCount");// 设置的循环次数
- public int CycledCount => _lpCycleCount.Count == 0 ? 0:_lpCycleCount.Values.Min();// 已处理的循环次数
- public int CycleWaferCountSetPoint => SC.GetValue<int>("System.CycleWaferCount");// 设置的晶圆片数
- public int CycledWaferCount => _lpCycleWafer.Values.Sum(); // 已处理的晶圆片数
- private Dictionary<ModuleName, int> _lpCycleCount = new Dictionary<ModuleName, int>();
- private Dictionary<ModuleName, DateTime> _lpCycleTime = new Dictionary<ModuleName, DateTime>();
- private Dictionary<ModuleName, int> _lpCycleWafer = new Dictionary<ModuleName, int>();
- public void Start(ModuleName lpModule, bool isReset)
- {
- LOG.Info("Cycle: Start cycle data");
- if (isReset) Reset();
- _lpCycleCount[lpModule] = 0;
- _lpCycleTime[lpModule] = DateTime.Now;
- _lpCycleWafer[lpModule] = 0;
- }
- public void Reset()
- {
- LOG.Info("Cycle: Reset cycle data");
- _lpCycleCount.Clear();
- _lpCycleTime.Clear();
- _lpCycleWafer.Clear();
- }
- //public void BeginOrAddCycle(int setpoint)
- //{
- // if (IsCycleMode) // add
- // {
- // CycleWaferCountSetPoint += setpoint;
- // LOG.Info($"Cycle: Add {setpoint} wafers, total cycle count = {CycleWaferCountSetPoint}");
- // }
- // else // begin
- // {
- // IsCycleMode = true;
- // StartTime = DateTime.Now;
- // CycleWaferCountSetPoint = setpoint;
- // CycledWaferCount = 0;
- // LOG.Info($"Cycle: Begin {setpoint} wafers");
- // }
- //}
- public bool IsCycleEnd(ModuleName lpModule)
- {
- if (!IsCycleMode)
- return true;
- return (CycleBy == "WaferCount" && CycledWaferCount >= CycleWaferCountSetPoint) ||
- (CycleBy == "LotCount" && _lpCycleCount[lpModule] >= CycleCountSetPoint);
- }
- public bool IsCycleEnd()
- {
- if (!IsCycleMode)
- return true;
- return (CycleBy == "WaferCount" && CycledWaferCount >= CycleWaferCountSetPoint) ||
- (CycleBy == "LotCount" && _lpCycleCount.Values.Count > 0 && _lpCycleCount.Values.Min() >= CycleCountSetPoint);
- }
- public void Increase(ModuleName lpModule, int waferCount, int count = 1)
- {
- IncreaseWaferCount(lpModule, waferCount);
- IncreaseCount(lpModule, count);
- }
- public void IncreaseWaferCount(ModuleName lpModule, int waferCount)
- {
- _lpCycleWafer[lpModule]++;
- LOG.Info($"Cycle: finished {CycledWaferCount} wafer(s)");
- }
- public void IncreaseCount(ModuleName lpModule, int count = 1)
- {
- _lpCycleCount[lpModule]++;
- LOG.Info($"Cycle: finished {CycledCount} Count(s)");
- }
- }
- class ThroughputData
- {
- public bool IsCalcing { get; private set; } = false;
- public DateTime CacledLastTime { get; private set; } = DateTime.MinValue; // 创建时间或者计算时间
- public double CalcedTotalTimeSeconds { get; private set; } = 0; // 总的计算时间
- public int CalcedProcessedCount { get; private set; } = 0; // 已计算完的总数(control job)
- public double TotalTimeSeconds { get; private set; }
- public DateTime CaclingLastTime { get; private set; } = DateTime.MinValue; // 创建时间或者计算时间
- public int CalcingProcessedCount { get; private set; } = 0;// 正在计算的总数(control job)
- public int ProcessedCount => CalcedProcessedCount + CalcingProcessedCount;
- public double Throughput { get; private set; }
- public double LiveThroughput { get; private set; }
- public void BeginCalc()
- {
- if (IsCalcing) return;
- IsCalcing = true;
- CalcedTotalTimeSeconds = 0;
- CacledLastTime = DateTime.Now;
- CaclingLastTime = DateTime.Now;
- LOG.Info("Throughput: Begin");
- }
- public void Pause()
- {
- if (!IsCalcing)
- {
- IsCalcing = false;
- //LOG.Info("Throughput: Pause");
- }
- }
- public void Reset()
- {
- CacledLastTime = DateTime.Now;
- CalcedTotalTimeSeconds = 0;
- CalcedProcessedCount = 0;
- CaclingLastTime = DateTime.Now;
- CalcedProcessedCount = 0;
- CalcingProcessedCount = 0;
- Throughput = 0;
- LiveThroughput = 0;
- LOG.Info("Throughput: Reset");
- }
- public void UpdateCalced(int calcedCount)
- {
- CalcedProcessedCount += calcedCount;
- CalcingProcessedCount -= calcedCount;
- if (CalcingProcessedCount < 0) CalcingProcessedCount = 0;
- CalcedTotalTimeSeconds += DateTime.Now.Subtract(CacledLastTime).TotalSeconds;
- CacledLastTime = DateTime.Now;
- }
- public void UpdateCalcing(int calcingCount)
- {
- DateTime now = DateTime.Now;
- double seconds_this = now.Subtract(CaclingLastTime).TotalSeconds;
- int calcingCount_this = calcingCount - CalcingProcessedCount;
- double count_this = ProcessedCount + calcingCount;
- LiveThroughput = 3600 / (seconds_this / calcingCount_this);
- TotalTimeSeconds = CalcedTotalTimeSeconds + seconds_this;
- Throughput = 3600 * count_this / TotalTimeSeconds;
- LOG.Info($"Throughput: {Throughput}, Finished {count_this} wafer(s) in {(int)TotalTimeSeconds} seconds;" +
- $" {LiveThroughput} last wafer in {(int)seconds_this} seconds");
- CaclingLastTime = now;
- CalcingProcessedCount = calcingCount;
- }
- }
- private CycleData _CycleData = new CycleData();
- private ThroughputData _throughputData = new ThroughputData();
- private bool _isAutoUnloadFoup
- {
- get
- {
- return SC.GetValue<bool>("EFEM.LoadPort.EnableAutoUnloadFoup");
- }
- }
- private bool _PMA1Disabled;
- private bool _PMA2Disabled;
- private bool _PMB1Disabled;
- private bool _PMB2Disabled;
- private ModuleName _TMRobotBlade1Station = ModuleName.System;
- private Dictionary<ModuleName, bool> _loadlockCooling = new Dictionary<ModuleName, bool>();
- Queue<Action> tmRobotActions = new Queue<Action>() { };
- Queue<Action> efemRobotActions = new Queue<Action>() { };
- public AutoTransfer(EquipmentManager equipment)
- {
- _PMA1Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.PMAChamber1Disabled.IsInstalled");
- _PMA2Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.PMAChamber2Disabled.IsInstalled");
- _PMB1Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.PMBChamber1Disabled.IsInstalled");
- _PMB2Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.PMBChamber2Disabled.IsInstalled");
- _faCallback = new SchedulerFACallback();
- _dbCallback = new SchedulerDBCallback();
- if (SC.GetValueOrDefault<bool>("System.SetUp.PMA.IsInstalled"))
- _lstPms.Add(_pm1);
- if (SC.GetValueOrDefault<bool>("System.SetUp.PMB.IsInstalled"))
- _lstPms.Add(_pm2);
- //if (SC.GetValueOrDefault<bool>("System.SetUp.PMC.IsInstalled"))
- // _lstPms.Add(_pm3);
- if (SC.GetValueOrDefault<bool>("System.SetUp.LLA.IsInstalled"))
- _lstLls.Add(_loadlockA);
- if (SC.GetValueOrDefault<bool>("System.SetUp.LLB.IsInstalled"))
- _lstLls.Add(_loadlockB);
- if (SC.GetValueOrDefault<bool>("System.SetUp.Aligner1.IsInstalled"))
- _lstAligners.Add(_aligner1);
- if (SC.GetValueOrDefault<bool>("System.SetUp.Aligner2.IsInstalled"))
- _lstAligners.Add(_aligner2);
- if (SC.GetValueOrDefault<bool>("System.SetUp.Cooling1.IsInstalled"))
- _lstCoolings.Add(_cooling1);
- if (SC.GetValueOrDefault<bool>("System.SetUp.Cooling2.IsInstalled"))
- _lstCoolings.Add(_cooling2);
- if (SC.GetValueOrDefault<bool>("System.SetUp.LP1.IsInstalled"))
- {
- _lstLps.Add(_lp1);
- _checkNoCarrierByModule[_lp1.Module] = new R_TRIG();
- }
- if (SC.GetValueOrDefault<bool>("System.SetUp.LP2.IsInstalled"))
- {
- _lstLps.Add(_lp2);
- _checkNoCarrierByModule[_lp2.Module] = new R_TRIG();
- }
- if (SC.GetValueOrDefault<bool>("System.SetUp.LP3.IsInstalled"))
- {
- _lstLps.Add(_lp3);
- _checkNoCarrierByModule[_lp3.Module] = new R_TRIG();
- }
- _pmSwapWaitTimeOut.Clear();
- _lstPms.ForEach(p=>_pmSwapWaitTimeOut[p.Module] = new Tuple<R_TRIG, DeviceTimer>(new R_TRIG(),new DeviceTimer()));
- //临时办法,设备异常后进行reset,重新home后reset机械手task
- OP.Subscribe($"{ModuleName.TM}.ResetTask", (string cmd, object[] args) =>
- {
- _tmRobot.ResetTask();
- return true;
- });
- OP.Subscribe($"{ModuleName.EFEM}.ResetTask", (string cmd, object[] args) =>
- {
- _efem.ResetTask();
- return true;
- });
- DATA.Subscribe("Scheduler.IsCycleMode", () => _CycleData.IsCycleMode);
- DATA.Subscribe("Scheduler.CycleBy", () => _CycleData.CycleBy);
- DATA.Subscribe("Scheduler.CycleCountSetPoint", () => _CycleData.CycleCountSetPoint);
- DATA.Subscribe("Scheduler.CycledCount", () => _CycleData.CycledCount);
- DATA.Subscribe("Scheduler.CycleWaferCountSetPoint", () => _CycleData.CycleWaferCountSetPoint);
- DATA.Subscribe("Scheduler.CycledWaferCount", () => _CycleData.CycledWaferCount);
- DATA.Subscribe("Scheduler.CycleEscapeTime", () => _CycleData.EscapeTime);
- DATA.Subscribe("Scheduler.Throughput", () => _throughputData.Throughput);
- DATA.Subscribe("Scheduler.LiveThroughput", () => _throughputData.LiveThroughput);
- DATA.Subscribe("System.Scheduler.RunningRecipeList", () => _GetRunningRecipeList());
- DATA.Subscribe("Scheduler.CjIdList", () => _GetRunningCjIdList());
- DATA.Subscribe("Scheduler.CurrentRecipeList", () =>
- {
- return _lstProcessJobs;
- });
- for (int j=1; j<= _lstLps.Count;j++)
- {
- int lpIndex = j;
- ModuleName lp = _lstLps[lpIndex-1].Module;
- DATA.Subscribe($"{lp}.LocalJobName", () =>
- {
- var jb = _lstControlJobs.Find(x => x.Module == $"{lp}");
- if (jb != null)
- return jb.Name;
- return "";
- });
- DATA.Subscribe($"{lp}.JobLotName", () =>
- {
- var cj = _lstControlJobs.FirstOrDefault(x => x.Module == $"{lp}");
- if (cj != null)
- return cj.LotName;
- return "";
- });
- DATA.Subscribe($"{lp}.LocalJobStatus", () =>
- {
- var jb = _lstControlJobs.Find(x => x.Module == $"{lp}");
- if (jb != null)
- return jb.State.ToString();
- return "";
- });
- DATA.Subscribe($"{lp}.CurrentRecipeList", () =>
- {
- List<string> result = Enumerable.Repeat("", 25).ToList();
- for (int i = 0; i < _lstProcessJobs.Count; i++)
- {
- if (_lstProcessJobs[i].SlotWafers != null)
- {
- foreach (var wafers in _lstProcessJobs[i].SlotWafers)
- {
- if (wafers.Item1 == lp)
- {
- result[wafers.Item2] = _lstProcessJobs[i].Sequence.Name;
- }
- }
- }
- }
- return result;
- });
- }
- tmRobotActions.Enqueue(MonitorTmRobotPMPickAndPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMAPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMBPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMAPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMBPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMAPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMBPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotLoadLockPickTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMAPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMBPlaceTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMAPickTask);
- tmRobotActions.Enqueue(MonitorTmRobotPMBPickTask);
- tmRobotActions.Enqueue(MonitorTmRobotLoadLockPlaceTask);
- //tmRobotActions.Enqueue(MonitorTmRobotGoToTask);
- efemRobotActions.Enqueue(MonitorEfemRobotAlignerPickTask);
- efemRobotActions.Enqueue(MonitorEfemRobotAlignerPlaceTask);
- efemRobotActions.Enqueue(MonitorEfemRobotLoadLockPlaceTask);
- efemRobotActions.Enqueue(MonitorEfemRobotLoadLockPickTask);
- efemRobotActions.Enqueue(MonitorEfemRobotCoolingPickTask);
- efemRobotActions.Enqueue(MonitorEfemRobotCoolingPlaceTask);
- efemRobotActions.Enqueue(MonitorEfemRobotLoadPortPickTask);
- efemRobotActions.Enqueue(MonitorEfemRobotLoadPortPlaceTask);
- }
- private List<string> _GetRunningCjIdList()
- {
- return _lstControlJobs/*.Where(o => o.State == EnumControlJobState.Executing
- || o.State == EnumControlJobState.Paused)*/.Select(o => o.InnerId.ToString()).ToList();
- }
- const string StrProcessRecipe = "ProcessRecipe";
- const string StrRecipe = "Recipe";
- private List<string> _GetRunningRecipeList()
- {
- var runningCjList = _lstControlJobs.Where(o => o.State == EnumControlJobState.Executing
- || o.State == EnumControlJobState.Paused).Select(o => o.Name).ToList();
- return _lstProcessJobs.Where(o => runningCjList.Contains(o.ControlJobName))
- .SelectMany(a => a.Sequence.Steps.SelectMany(b => b.StepParameter.Where(c => c.Key == StrProcessRecipe || c.Key == StrRecipe))).Select(d => d.Value as string)
- .Where(o => !string.IsNullOrWhiteSpace(o)).ToList();
- }
- public bool HasJobRunning
- {
- get { return _lstControlJobs.Count > 0; }
- }
- public void Clear()
- {
- _tmRobot.ResetTask();
- _efem.ResetTask();
- foreach (var pm in _lstPms)
- {
- pm.ResetTask();
- }
- //foreach (var lp in _lstLps)
- //{
- // lp.ResetTask();
- //}
- _lstControlJobs.Clear();
- _lstProcessJobs.Clear();
- _temperatureSetpointDic.Clear();
- _temperatureTrigDic.Clear();
- _CycleData.Reset();
- }
- #region Job Management
- public bool CreateJob(Dictionary<string, object> param)
- {
- string reason;
- string[] slotSequence = (string[])param["SlotSequence"];
- string jobId = (string)param["JobId"];
- string module = (string)param["Module"];
- PreheatDone = false;
- bool autoStart = (bool)param["AutoStart"];
- string lotId = jobId;
- if (param.ContainsKey("LotId"))
- lotId = (string)param["LotId"];
- if(!_efem.Blade1Enable && !_efem.Blade2Enable)
- {
- EV.PostWarningLog(LogSource, $"EFEM lower blade and EFEM upper blade are not enabled ");
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!_tmRobot.Blade1Enable && !_tmRobot.Blade2Enable)
- {
- EV.PostWarningLog(LogSource, $"TM lower blade and TM upper blade are not enabled ");
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!ValidateSequence(slotSequence, out reason))
- {
- EV.PostWarningLog(LogSource, $"{reason}");
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (slotSequence.Length != 25)
- {
- reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be 25";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!ModuleHelper.IsLoadPort(ModuleHelper.Converter(module)))
- {
- reason = $"{module} should be LP";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (string.IsNullOrEmpty(jobId))
- {
- jobId = "CJ_Local_" + module;
- }
- if (_lstControlJobs.Exists(x => x.Name == jobId))
- {
- reason = $"LotID : {jobId} already created";
- EV.PostAlarmLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- var sameLotId = _lstLps.Select(p => CarrierManager.Instance.GetCarrier(p.Module).LotId).Where(p => !string.IsNullOrWhiteSpace(p)).GroupBy(p => p).Where(p => p.Count() > 1);
- if(sameLotId != null && sameLotId.Count() >0)
- {
- reason = $"The Carrier's LotIds on the {_lstLps.Count} LoadPorts are the same , {sameLotId.ToList()[0].Key} .";
- EV.PostAlarmLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- SchedulerLoadPort lp = GetModule(module) as SchedulerLoadPort;
- if (!lp.CheckReadyRunJob())
- {
- reason = $"{module} not ready";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- ControlJobInfo cj = new ControlJobInfo();
- cj.Name = jobId;
- cj.Module = module;
- cj.LotName = jobId;
- cj.LotInnerId = Guid.NewGuid();
- cj.LotWafers = new List<WaferInfo>();
- cj.SetState(EnumControlJobState.WaitingForStart);
- Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
- Dictionary<string, List<Tuple<ModuleName, int>>> seqSlotWafers = new Dictionary<string, List<Tuple<ModuleName, int>>>();
- Dictionary<string, string> indexSequence = new Dictionary<string, string>();
- bool enableGroupBySequence = SC.GetValue<bool>("System.Scheduler.GroupWaferBySequence");
- string WaferAssociationInfo = $"WaferAssociationInfo({module}):";
- for (int i = 0; i < 25; i++)
- {
- WaferAssociationInfo = WaferAssociationInfo + string.Format(" slot{0} -- {1};", i + 1, slotSequence[i]);
- if (string.IsNullOrEmpty(slotSequence[i]) || string.IsNullOrEmpty(slotSequence[i].Trim()))
- continue;
- string groupName = enableGroupBySequence ? slotSequence[i].Trim() : i.ToString();
- indexSequence[groupName] = slotSequence[i];
- if (!seqSlot.ContainsKey(groupName))
- {
- seqSlot[groupName] = new bool[25];
- }
- if (!seqSlotWafers.ContainsKey(groupName))
- {
- seqSlotWafers[groupName] = new List<Tuple<ModuleName, int>>();
- }
- seqSlot[groupName][i] = true;
- if (!WaferManager.Instance.CheckHasWafer(module, i))
- {
- reason = $"job wafer: {module} slot {i + 1} not in the carrier";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), i, WaferStatus.Normal))
- {
- reason = $"job wafer: {module} slot {i + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).Status}";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- var wafer = WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i);
- if (wafer == null || wafer.IsEmpty)
- {
- reason = $"specifies wafer: {module} slot {i + 1} not in the carrier";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!ModuleHelper.IsLoadPort(ModuleHelper.Converter(wafer.WaferOrigin.Split('.')[0])))
- {
- reason = $"specifies wafer: {module} slot {i + 1} not origin LP";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (wafer.ProcessState != EnumWaferProcessStatus.Idle)
- {
- reason = $"specifies wafer: {module} slot {i + 1} process state is not idle";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- seqSlotWafers[groupName].Add(Tuple.Create(ModuleHelper.Converter(module), i));
- cj.LotWafers.Add(WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i));
- WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), i).PPID = slotSequence[i];
- }
- currentSlotSequenceList[module] = slotSequence.Reverse().ToList();
- EV.PostInfoLog(LogSource, WaferAssociationInfo);
- if (seqSlotWafers.Count == 0)
- {
- reason = $"Can not create job, no wafer assigned";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- List<ProcessJobInfo> pjs = new List<ProcessJobInfo>();
- string[] seqs = seqSlot.Keys.ToArray();
- for (int i = 0; i < seqs.Length; i++)
- {
- ProcessJobInfo pj = new ProcessJobInfo();
- pj.Name = jobId + "_" + (i + 1);
- pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]);
- pj.ControlJobName = cj.Name;
- pj.LotName = lotId;
- pj.SlotWafers = seqSlotWafers[seqs[i]];
- pj.SetState(EnumProcessJobState.Queued);
- if (!CheckSequencePmReady(pj.Sequence, null, out _, out string innerReason))
- {
- reason = $"no valid chamber for the {innerReason}";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!CheckSequenceRecipeFileValid(pj.Sequence, out reason))
- {
- reason = $"recipe file not valid in the sequence, {reason}";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (!CheckSequenceOrderOk(pj.Sequence, out reason))
- {
- reason = $"sequence path not valid, {reason}";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- if (CheckSequenceNeedDummyWafer(pj.Sequence))
- {
- reason = $"create job failed, no valid dummy wafer exist";
- EV.PostWarningLog(LogSource, reason);
- _faCallback.JobCreateFailed(module, lotId, jobId, "");
- return false;
- }
- pjs.Add(pj);
- }
- foreach (var pj in pjs)
- {
- cj.ProcessJobNameList.Add(pj.Name);
- _lstProcessJobs.Add(pj);
- }
- _lstControlJobs.Add(cj);
- int totalWafer = 0;
- foreach (var pj in pjs)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- wafer.ProcessJob = pj;
- WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
- WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
- WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), lotId);
- WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, lotId);
- totalWafer++;
- }
- }
- _faCallback.JobCreated(cj, GetFirstProcessJob(cj));
- CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
- JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
- return true;
- }
- public bool CreateControlJob(string jobId, string module, List<string> pjIDs, bool isAutoStart)
- {
- if (_lstControlJobs.Exists(x => x.Name == jobId))
- {
- EV.PostWarningLog(LogSource, $"{jobId} is already created");
- return false;
- }
- if (!ModuleHelper.IsLoadPort(ModuleHelper.Converter(module)))
- {
- EV.PostWarningLog(LogSource, $"{module} should be LoadPort");
- return false;
- }
- LoadPort lp = DEVICE.GetDevice<LoadPort>($"{module}");
- if (!lp.IsIdle)
- {
- EV.PostWarningLog(LogSource, $"{module} is not idle");
- return false;
- }
- if (!lp.IsMapped)
- {
- EV.PostWarningLog(LogSource, $"{module} is not mapped");
- return false;
- }
- if (!lp.IsPresent)
- {
- EV.PostWarningLog(LogSource, $"{module} is not present");
- return false;
- }
- foreach (var _lp in _lstLps)
- {
- if (_lp.Module.ToString() == module)
- {
- if (!_lp.IsOnline)
- {
- EV.PostWarningLog(LogSource, $"{module} is not online");
- return false;
- }
- if (_lp.IsError)
- {
- EV.PostWarningLog(LogSource, $"{module} is error");
- return false;
- }
- }
- }
- if (_lstProcessJobs.Count <= 0) //判断上一步ProcessJob是否创建成功
- {
- EV.PostWarningLog(LogSource, $"process job is not exist");
- return false;
- }
- ControlJobInfo cj = new ControlJobInfo();
- cj.Name = jobId;
- cj.Module = module;
- cj.SetState(EnumControlJobState.WaitingForStart);
- cj.LotName = jobId;
- cj.LotWafers = new List<WaferInfo>();
- int totalWafer = 0;
- foreach (var pjName in pjIDs)
- {
- var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
- if (pj == null)
- {
- LOG.Info($"not find {pjName} while create control job");
- continue;
- }
- var slotWafers = new List<Tuple<ModuleName, int>>();
- foreach (var slotWafer in pj.SlotWafers)
- {
- if (!WaferManager.Instance.CheckHasWafer(module, slotWafer.Item2))
- {
- EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} not in the carrier");
- return false;
- }
- if (!WaferManager.Instance.CheckWafer(ModuleHelper.Converter(module), slotWafer.Item2, WaferStatus.Normal))
- {
- EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).Status}");
- return false;
- }
- if (WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).ProcessState != EnumWaferProcessStatus.Idle)
- {
- EV.PostWarningLog(LogSource, $"job wafer: {module} slot {slotWafer.Item2 + 1} process status is {WaferManager.Instance.GetWafer(ModuleHelper.Converter(module), slotWafer.Item2).ProcessState}");
- return false;
- }
- slotWafers.Add(Tuple.Create(ModuleHelper.Converter(module), slotWafer.Item2));
- totalWafer++;
- }
- pj.ControlJobName = jobId;
- cj.ProcessJobNameList.Add(pj.Name);
- pj.SlotWafers = slotWafers;
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- cj.LotWafers.Add(wafer);
- WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
- WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
- //WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), jobId);
- }
- }
- _lstControlJobs.Add(cj);
- CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
- JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
- return true;
- }
- public bool CreateProcessJob(string jobId, string sequenceName, List<int> slotNumbers, bool isAutoStart)
- {
- var sequenceInfo = SequenceInfoHelper.GetInfo(sequenceName);
- #region 模块检查
- if (!CheckSequenceAlignerReady(sequenceInfo, out string reason))
- {
- EV.PostWarningLog(LogSource, $"Aligner is not ready for the {reason}");
- return false;
- }
- if (!CheckSequencePMReady(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"PM is not ready for the {reason}");
- return false;
- }
- #endregion
- #region Sequence检查
- if (!CheckSequenceAlignerOrder(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"Aligner order is not valid for the {reason}");
- return false;
- }
- if (!CheckSequencePMOrder(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"PM order is not valid, {reason}");
- return false;
- }
- #endregion
- var slotWafers = new List<Tuple<ModuleName, int>>();
- foreach (var slot in slotNumbers)
- {
- slotWafers.Add(Tuple.Create(ModuleName.System, slot));
- }
- ProcessJobInfo pj = new ProcessJobInfo();
- pj.Name = jobId;
- pj.Sequence = sequenceInfo;
- pj.SlotWafers = slotWafers;
- pj.SetState(EnumProcessJobState.Queued);
- pj.CreateTime = DateTime.Now;
- _lstProcessJobs.Add(pj);
- return true;
- }
- /// <summary>
- /// 创建ControlJob
- /// </summary>
- /// <param name="controlJobId"></param>
- /// <param name="moduleName"></param>
- /// <param name="carrierId"></param>
- /// <param name="processJobs"></param>
- /// <param name="reason"></param>
- /// <returns></returns>
- public void CreateControlJob(string controlJobId, string carrierId, List<string> processJobs)
- {
- ControlJobInfo cj = new ControlJobInfo();
- cj.Name = controlJobId;
- cj.LotName = carrierId;
- cj.LotInnerId = Guid.NewGuid();
- cj.LotWafers = new List<WaferInfo>();
- cj.ProcessJobNameList = processJobs;
- cj.SetState(EnumControlJobState.WaitingForStart);
- cj.CreateTime = DateTime.Now;
- List<string> processJobsId = new List<string>();
- for (int i=0;i<processJobs.Count;i++)
- {
- ProcessJobInfo pj = _lstProcessJobs.Find(O => O.Name == processJobs[i]);
- if (pj != null)
- {
- if (pj.SlotWafers != null&&!processJobsId.Contains(pj.Name))
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
- cj.LotWafers.Add(wafer);
- }
- processJobsId.Add(pj.Name);
- }
- pj.ControlJobName = cj.Name;
- }
- }
- _lstControlJobs.Add(cj);
- _faCallback.JobCreated(cj, GetFirstProcessJob(cj));
- //CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
- //JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
- }
- /// <summary>
- /// 检验创建ControlJob的条件
- /// </summary>
- /// <returns></returns>
- public bool CheckCreateControlJobCondition(List<string> modules, out string reason)
- {
- reason = "";
- if (!_efem.Blade1Enable && !_efem.Blade2Enable)
- {
- reason = $"EFEM lower blade and EFEM upper blade are not enabled ";
- EV.PostWarningLog(LogSource, reason);
- return false;
- }
- if (!_tmRobot.Blade1Enable && !_tmRobot.Blade2Enable)
- {
- reason = "TM lower blade and TM upper blade are not enabled ";
- EV.PostWarningLog(LogSource, reason);
- return false;
- }
- foreach (string module in modules)
- {
- SchedulerLoadPort lp = GetModule(module) as SchedulerLoadPort;
- if (!lp.CheckReadyRunJob())
- {
- reason = $"{module} not ready";
- EV.PostWarningLog(LogSource, reason);
- return false;
- }
- }
- return true;
- }
- /// <summary>
- /// 创建ProcessJob
- /// </summary>
- /// <param name="jobId"></param>
- /// <param name="sequenceName"></param>
- /// <returns></returns>
- public bool CreateProcessJob(string jobId, string sequenceName,string carrierId,out string reason)
- {
- reason = "";
- List<string> sequences = RecipeFileManager.Instance.GetSequenceNameList();
- if(!sequences.Contains(sequenceName))
- {
- reason = $"sequence[{sequenceName}] is not exist!";
- EV.PostWarningLog(LogSource,reason);
- return false;
- }
- var sequenceInfo = SequenceInfoHelper.GetInfo(sequenceName);
- #region 模块检查
- if (!CheckSequencePMReady(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"PM is not ready for the {reason}");
- return false;
- }
- if (!CheckSequenceAlignerReady(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"Aligner is not ready for the {reason}");
- return false;
- }
- #endregion
- #region Sequence检查
- if (!CheckSequenceAlignerOrder(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"Aligner order is not valid for the {reason}");
- return false;
- }
- if (!CheckSequencePMOrder(sequenceInfo, out reason))
- {
- EV.PostWarningLog(LogSource, $"PM order is not valid, {reason}");
- return false;
- }
- #endregion
- ProcessJobInfo pj = new ProcessJobInfo();
- pj.Name = jobId;
- pj.Sequence = sequenceInfo;
- pj.LotName = carrierId;
- pj.CreateTime = DateTime.Now;
- pj.SetState(EnumProcessJobState.Queued);
- _lstProcessJobs.Add(pj);
- return true;
- }
- /// <summary>
- /// 更新processId对应的Wafer
- /// </summary>
- /// <param name="processJobId"></param>
- public void UpdateProcessJobSlotWafer(string processJobId,string moduleName,List<int> slots)
- {
- ProcessJobInfo pj = _lstProcessJobs.FirstOrDefault(O => O.Name == processJobId);
- if (pj != null)
- {
- pj.SlotWafers = new List<Tuple<ModuleName, int>>();
- for(int i=0;i<slots.Count; i++)
- {
- pj.SlotWafers.Add(Tuple.Create(ModuleHelper.Converter(moduleName), slots[i] > 1 ? slots[i]-1:0));
- }
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- wafer.ProcessJob = pj;
- WaferDataRecorder.SetWaferSequence(wafer.InnerId.ToString(), pj.Sequence.Name);
- WaferDataRecorder.SetWaferLotId(wafer.InnerId.ToString(), pj.LotName);
- WaferManager.Instance.UpdateWaferLotId(pjSlotWafer.Item1, pjSlotWafer.Item2, pj.LotName);
- }
- //由于原来逻辑是根据PJ的Queued状态才会启动任务,因此暂时先注释
- //pj.SetState(EnumProcessJobState.SetUp);
- OP.DoOperation(E40ProcessStateChanged, pj.Name, EnumProcessJobState.SetUp);
- }
- }
- /// <summary>
- /// 更新ControlJob Module信息
- /// </summary>
- /// <param name="controlJobId"></param>
- /// <param name="moduleName"></param>
- public void UpdateControlJobModule(string controlJobId,string moduleName)
- {
- ControlJobInfo cj = _lstControlJobs.FirstOrDefault(O => O.Name == controlJobId);
- if (cj != null)
- {
- cj.Module = moduleName;
- CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
- int totalWafer = 0;
- for (int i = 0; i < cj.ProcessJobNameList.Count; i++)
- {
- ProcessJobInfo pj = _lstProcessJobs.Find(O => O.Name == cj.ProcessJobNameList[i]);
- if (pj != null && pj.SlotWafers != null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- ///创建时没有Wafer信息
- if (cj.LotWafers.Count == 0)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- WaferDataRecorder.SetCjInfo(wafer.InnerId.ToString(), cj.InnerId.ToString());
- cj.LotWafers.Add(wafer);
- }
- totalWafer++;
- }
- }
- }
- _faCallback.JobWaitingForStart(cj, GetFirstProcessJob(cj));
- JobDataRecorder.StartCJ(cj.InnerId.ToString(), carrier.InnerId.ToString(), cj.Name, cj.Module, cj.Module, totalWafer);
- }
- }
- private bool CheckSequenceAlignerReady(SequenceInfo seq, out string reason)
- {
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsAligner(module))
- {
- if (!GetModule(module.ToString()).IsOnline)
- {
- reason = $"Step {i + 1}, {module} is not online";
- return false;
- }
- //if (!_aligner.IsIdle)
- //{
- // reason = $"Step {i + 1}, {module} is not idle";
- // return false;
- //}
- if (GetModule(module.ToString()).IsError)
- {
- reason = $"Step {i + 1}, {module} is error";
- return false;
- }
- }
- }
- }
- reason = string.Empty;
- return true;
- }
- private bool CheckSequenceAlignerOrder(SequenceInfo seq, out string reason)
- {
- int alignerCount = 0;
- int alignerIndex = -1;
- int llIndex = -1;
- int pmIndex = -1;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsAligner(module))
- {
- alignerCount++;
- alignerIndex = i;
- if (i == seq.Steps.Count - 1)
- {
- reason = $"Step {i + 1}, {module} can not be the last step";
- return false;
- }
- }
- if (ModuleHelper.IsLoadLock(module))
- {
- if (llIndex == -1 || llIndex > i)
- llIndex = i;
- }
- if (ModuleHelper.IsPm(module))
- {
- pmIndex = i;
- }
- }
- }
- if (alignerCount >= 2)
- {
- reason = $"Step {alignerIndex + 1}, Aligner step can appear once at most in sequence";
- return false;
- }
- else if (alignerCount == 1)
- {
- if (llIndex != -1 && alignerIndex > llIndex)
- {
- reason = $"Step {alignerIndex + 1}, Aligner step should be in front of LoadLock step";
- return false;
- }
- if (pmIndex != -1 && alignerIndex > pmIndex)
- {
- reason = $"Step {alignerIndex + 1}, Aligner step should be in front of PM step";
- return false;
- }
- }
- reason = string.Empty;
- return true;
- }
- private bool CheckSequencePMReady(SequenceInfo seq, out string reason)
- {
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- if (stepInfo.StepModules.Count == 0)
- {
- reason = $"Step {i + 1}, no PM is selected";
- return false;
- }
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- foreach (var pm in _lstPms)
- {
- if (pm.Module == module)
- {
- if (!pm.IsOnline)
- {
- reason = $"Step {i + 1}, selected {module} is not online";
- return false;
- }
- //if (!pm.IsIdle)
- //{
- // reason = $"Step {i + 1}, selected {module} is not idle";
- // return false;
- //}
- if (pm.IsError)
- {
- reason = $"Step {i + 1}, selected {module} is error";
- return false;
- }
- #region Check Recipe File Valid
- var recipeContent = RecipeFileManager.Instance.LoadRecipe("", stepInfo.StepParameter[$"{module}Recipe"].ToString(), false);
- if (string.IsNullOrEmpty(recipeContent))
- {
- reason = $"Step {i + 1}, can not find recipe file {stepInfo.RecipeName}";
- return false;
- }
- #endregion
- }
- }
- }
- }
- }
- reason = "";
- return true;
- }
- private bool CheckSequencePMOrder(SequenceInfo seq, out string reason)
- {
- int pmCount = 0;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- pmCount++;
- break;
- }
- }
- }
- if (pmCount == 0)
- {
- reason = $"Sequence must contains PM step";
- return false;
- }
- if (pmCount >= 2)
- {
- reason = $"PM step only can appear once in sequence";
- return false;
- }
- reason = string.Empty;
- return true;
- }
- internal ProcessJobInfo GetFirstProcessJob(ControlJobInfo cj)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name)
- return pj;
- }
- return null;
- }
- public bool StopJob(string jobName)
- {
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
- if (cj == null)
- {
- EV.PostWarningLog(LogSource, $"stop job rejected, not found job with id {jobName}");
- return false;
- }
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name)
- {
- pj.SetState(EnumProcessJobState.Stopping);
- OP.DoOperation(E40ProcessStateChanged, pj.Name, EnumProcessJobState.Stopping);
- }
- }
- cj.SetState(EnumControlJobState.Completed);
- _faCallback.JobStopped(cj, GetFirstProcessJob(cj));
- _dbCallback.LotFinished(cj);
- return true;
- }
- public bool AbortJob(string jobName)
- {
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
- if (cj == null)
- {
- EV.PostWarningLog(LogSource, $"abort job rejected, not found job with id {jobName}");
- return false;
- }
- int unprocessed_cj = 0;
- int aborted_cj = 0;
- List<ProcessJobInfo> pjAbortList = new List<ProcessJobInfo>();
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name)
- {
- pj.SetState(EnumProcessJobState.Aborting);
- OP.DoOperation(E40ProcessStateChanged, pj.Name, EnumProcessJobState.Aborting);
- pjAbortList.Add(pj);
- int unprocessed = 0;
- int aborted = 0;
- WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
- foreach (var waferInfo in wafers)
- {
- waferInfo.ProcessJob = null;
- waferInfo.NextSequenceStep = 0;
- if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
- {
- unprocessed++;
- unprocessed_cj++;
- }
- }
- JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
- }
- }
- foreach (var pj in pjAbortList)
- {
- _lstProcessJobs.Remove(pj);
- }
- cj.SetState(EnumControlJobState.Completed);
- _lstControlJobs.Remove(cj);
- JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
- _faCallback.JobAborted(cj, GetFirstProcessJob(cj));
- _dbCallback.LotFinished(cj);
- _temperatureSetpointDic.Clear();
- _temperatureTrigDic.Clear();
- return true;
- }
- public bool ResumeJob(string jobName)
- {
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
- if (cj == null)
- {
- EV.PostWarningLog(LogSource, $"resume job rejected, not found job with id {jobName}");
- return false;
- }
- if (cj.State == EnumControlJobState.Paused)
- {
- cj.SetState(EnumControlJobState.Executing);
- }
- _faCallback.JobResumed(cj, GetFirstProcessJob(cj));
- return true;
- }
- private void CheckRecipeTemperatureAlarmMessage(ControlJobInfo cj)
- {
- try
- {
- if(cj == null || _lstProcessJobs == null)
- {
- return;
- }
- if (!SC.IsATMMode)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name)
- {
- SlotItem slotItem = null;
- if (pj.SlotWafers != null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2))
- {
- slotItem = new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- break;
- }
- }
- }
- if (slotItem != null)
- {
- const string _gt = "greater than";
- foreach (var pm in _lstPms)
- {
- if (CheckWaferNeedProcessPre(slotItem.Module, slotItem.Slot, pm.Module) && GetWaferTemperatureSetInRecipe(slotItem.Module, slotItem.Slot, pm.Module, out double temp1, out double temp2))
- {
- if (pm.CheckTemp1Alarm(temp1))
- {
- EV.PostWarningLog(LogSource, $"Chamber 1 Temperature {_gt} LEHeater1 with {pm.Module}1");
- }
- if (pm.CheckTemp2Alarm(temp2))
- {
- EV.PostWarningLog(LogSource, $"Chamber 2 Temperature {_gt} LEHeater2 with {pm.Module}2");
- }
- }
- }
- }
- }
- }
- }
- }
- catch(Exception ex)
- {
- LOG.Write(ex);
- }
- }
- public bool StartJob(string jobName)
- {
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
- if (cj == null)
- {
- EV.PostWarningLog(LogSource, $"start job rejected, not found job with id {jobName}");
- return false;
- }
- if (_CycleData.IsCycleMode)
- {
- _CycleData.Start(ModuleHelper.Converter(cj.Module), _lstControlJobs.All(p => p.State == EnumControlJobState.WaitingForStart));
- }
- CheckRecipeTemperatureAlarmMessage(cj);
- if (cj.State == EnumControlJobState.WaitingForStart)
- {
- cj.SetState(EnumControlJobState.Executing);
- (GetModule(cj.Module) as SchedulerLoadPort).NoteJobStart();
- //if (cj.IsCycleMode)
- //{
- // _CycleData.BeginOrAddCycle(cj.CycleWaferCountSP);
- //}
- cj.BeginTime = DateTime.Now;
- cj.LotInnerId = Guid.NewGuid();
- _dbCallback.LotCreated(cj);
- _faCallback.JobStarted(cj, GetFirstProcessJob(cj));
- //foreach (var pj in _lstProcessJobs)
- //{
- // if (pj.ControlJobName == cj.Name)
- // {
- // pj.SetState(EnumProcessJobState.Processing);
- // }
- //}
- }
- return true;
- }
- public bool PauseJob(string jobName)
- {
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == jobName);
- if (cj == null)
- {
- EV.PostWarningLog(LogSource, $"pause job rejected, not found job with id {jobName}");
- return false;
- }
- if (cj.State == EnumControlJobState.Executing)
- {
- cj.SetState(EnumControlJobState.Paused);
- }
- _faCallback.JobPaused(cj, GetFirstProcessJob(cj));
- return true;
- }
- public void Abort()
- {
- }
- public bool IsCJExisted(string CJID)
- {
- return _lstControlJobs.Exists(x => x.Name == CJID);
- }
- public void ModuleError(string moduleName)
- {
- GetModule(moduleName).ResetTask();
- PauseJob(string.Empty);
- }
- public void Map(string moduleName)
- {
- ModuleName target = ModuleHelper.Converter(moduleName);
- if (!ModuleHelper.IsLoadPort(target))
- {
- EV.PostWarningLog(LogSource, $"Invalid map target {target}");
- return;
- }
- if (!_mapTarget.Contains(target))
- {
- _mapTarget.Add(target);
- }
- }
- #endregion
- private string CheckAlignerHasWafer()
- {
- var waferInfo = string.Empty;
- foreach (var schedulerAligner in _lstAligners)
- {
- if (schedulerAligner.IsAvailable)
- {
- if (WaferManager.Instance.CheckHasWafer(schedulerAligner.Module, 0))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{schedulerAligner.Module}";
- }
- }
- return waferInfo;
- }
- private string CheckLlHasWafer()
- {
- var waferInfo = string.Empty;
- foreach (var schedulerLl in _lstLls)
- {
- if (schedulerLl.IsAvailable && WaferManager.Instance.AllLocationWafers.ContainsKey(schedulerLl.Module))
- {
- var list = WaferManager.Instance.AllLocationWafers[schedulerLl.Module];
- if (list != null && list.Count > 0)
- {
- foreach (var childItem in list.Keys)
- {
- if (WaferManager.Instance.CheckHasWafer(schedulerLl.Module, childItem))
- {
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{schedulerLl.Module}";
- break;
- }
- }
- }
- }
- }
- return waferInfo;
- }
- private string CheckCoolingHasWafer()
- {
- var waferInfo = string.Empty;
- foreach (var schedulerCool in _lstCoolings)
- {
- if (schedulerCool.IsAvailable)
- {
- if (WaferManager.Instance.CheckHasWafer(schedulerCool.Module, 0))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{schedulerCool.Module}";
- }
- }
- return waferInfo;
- }
- private string CheckEfemRobotHasWafer()
- {
- var waferInfo = string.Empty;
- if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.EfemRobot} primary arm";
- if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.EfemRobot} secondly arm";
- return waferInfo;
- }
- public Result Start(params object[] objs)
- {
- _ValueDict.Clear();
- var waferInfo = "";
- bool hasPmOnline = false;
- foreach (var schedulerPm in _lstPms)
- {
- if (schedulerPm.IsAvailable)
- {
- hasPmOnline = true;
- if(WaferManager.Instance.AllLocationWafers.ContainsKey(schedulerPm.Module))
- {
- var list = WaferManager.Instance.AllLocationWafers[schedulerPm.Module];
- if(list != null && list.Count > 0)
- {
- foreach(var item in list.Keys)
- {
- if (WaferManager.Instance.CheckHasWafer(schedulerPm.Module, item))
- {
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{schedulerPm.Module}";
- break;
- }
- }
- }
- }
- //if (WaferManager.Instance.CheckHasWafer(schedulerPm.Module, 0))
- // waferInfo += $"{(waferInfo == "" ? "" : ", ")}{schedulerPm.Module}";
- }
- }
- waferInfo += CheckAlignerHasWafer();
- waferInfo += CheckLlHasWafer();
- waferInfo += CheckCoolingHasWafer();
- waferInfo += CheckEfemRobotHasWafer();
- bool hasTMOnline = false;
- if (_tmRobot.IsAvailable)
- hasTMOnline = true;
- if (Converter.MapBladeToSlots(Hand.Blade1).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.TMRobot} primary arm";
- if (Converter.MapBladeToSlots(Hand.Blade2).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)))
- waferInfo += $"{(waferInfo == "" ? "" : ", ")}{ModuleName.TMRobot} secondly arm";
- if (!hasPmOnline || !hasTMOnline)
- {
- var content = hasPmOnline ? "" : "both process chamber";
- content += hasTMOnline ? "" : $"{(content == "" ? "" : ", ")}TM";
- EV.PostWarningLog("Scheduler", $"can not change to auto mode, {content} is busy or offline");
- return Result.FAIL;
- }
- if (waferInfo != "")
- {
- EV.PostWarningLog("Scheduler", $"can not change to auto mode, {waferInfo} wafer presence.");
- return Result.FAIL;
- }
- if (!_efem.IsOnline)
- {
- EV.PostWarningLog("Scheduler", $"can not change to auto mode, EFEM is offline");
- return Result.FAIL;
- }
- return Result.RUN;
- }
- public Result Monitor()
- {
- UploadWaferEndToEap();
- MonitorJobTasks();
- MonitorCleanTasks();
- MonitorEfemRobotMapTask();
- ControlJobInfo cjActive = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
- if (cjActive != null)
- {
- MonitorModuleTasks();
- }
- return Result.RUN;
- }
- private void UploadWaferEndToEap()
- {
- foreach(var lp in _lstLps)
- {
- for (int i = 0; i < 25; i++)
- {
- if (lp.FirstDetectWaferArrive(i))
- {
- ProcessJobInfo pj = WaferManager.Instance.GetWafer(lp.Module, i).ProcessJob;
- if (pj == null)
- continue;
- var processState = lp.GetWaferInfo(i).ProcessState;
- if (processState == EnumWaferProcessStatus.Failed || processState == EnumWaferProcessStatus.Completed)
- {
- _faCallback.JobWaferEnd(pj, lp.Module.ToString(), i);
- }
- }
- }
- }
- }
- #region Job task
- public Result MonitorJobTasks()
- {
- UpdateParallelMode();
- CalcingThroughput();
- UpdateProcessJobStatus();
- UpdateControlJobStatus();
- //if (GetUnprocessedWaferCount() < SC.GetValue<int>("System.Scheduler.WaferCountBelowWhichStartNewProcessJob"))
- {
- StartNewJob();
- }
- return Result.RUN;
- }
- //only for pj in process
- protected int GetUnprocessedWaferCount()
- {
- int count = 0;
- foreach (ProcessJobInfo pj in _lstProcessJobs)
- {
- if (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused)
- count += GetUnprocessedWaferCount(pj);
- }
- if (CheckWaferNeedProcess(WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0)))
- count++;
- if (CheckWaferNeedProcess(WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1)))
- count++;
- foreach(var item in _lstAligners)
- {
- if(CheckWaferNeedProcess(WaferManager.Instance.GetWafer(item.Module, 0))) count++;
- }
-
- return count;
- }
- protected int GetUnprocessedWaferCount(ProcessJobInfo pj)
- {
- int count = 0;
- if(pj.SlotWafers==null)
- {
- return 0;
- }
- for (int i = 0; i < pj.SlotWafers.Count; ++i)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
- if (wafer.IsEmpty)
- continue;
- if (CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
- count++;
- }
- return count;
- }
- protected bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
- {
- if(pj.SlotWafers==null)
- {
- return false;
- }
- for (int i = 0; i < pj.SlotWafers.Count; ++i)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
- if (wafer.IsEmpty)
- return false;
- if (checkAllProcessed && CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2))
- return false;
- }
- return true;
- }
- protected bool CheckAllDummyWaferReturned()
- {
- foreach (var schedulerPm in _lstPms)
- {
- if (WaferManager.Instance.CheckWaferIsDummy(schedulerPm.Module, 0))
- return false;
- }
- if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 0))
- return false;
- if (WaferManager.Instance.CheckWaferIsDummy(_tmRobot.Module, 1))
- return false;
- return true;
- }
- protected bool CheckAllPmCleaned(ProcessJobInfo pj)
- {
- foreach (var schedulerPm in _lstPms)
- {
- if (CheckNeedRunClean(schedulerPm.Module, out _, out _))
- {
- foreach (var sequenceStepInfo in pj.Sequence.Steps)
- {
- if (sequenceStepInfo.StepModules.Contains(schedulerPm.Module))
- return false;
- }
- }
- }
- return true;
- }
- private void UpdateProcessJobStatus()
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.State == EnumProcessJobState.Processing)
- {
- if (CheckAllWaferReturned(pj, true) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned())
- {
- pj.SetState(EnumProcessJobState.ProcessingComplete);
- pj.EndTime = DateTime.Now;
- OP.DoOperation(E40ProcessStateChanged, pj.Name,EnumProcessJobState.ProcessingComplete);
- JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
- }
- }
- else if (pj.State == EnumProcessJobState.Stopping)
- {
- if (CheckAllWaferReturned(pj, false) && CheckAllPmCleaned(pj) && CheckAllDummyWaferReturned())
- {
- pj.SetState(EnumProcessJobState.ProcessingComplete);
- pj.EndTime = DateTime.Now;
- OP.DoOperation(E40ProcessStateChanged, pj.Name,EnumProcessJobState.Complete);
- JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
- }
- }
- }
- }
- private void UpdateParallelMode()
- {
- bool enableParallel = SC.GetValue<bool>("System.Scheduler.IsRunInParallelMode");
- int hasJobLpCount = 0;
- _isRunningInParallelMode = enableParallel;
- List<ModuleName> pmUsed = new List<ModuleName>();
- foreach (var lp in _lstLps)
- {
- var cj = _lstControlJobs.Find(x => x.Module == lp.Module.ToString());
- if (cj != null)
- {
- hasJobLpCount++;
- var pj = _lstProcessJobs.FirstOrDefault(x => x.ControlJobName == cj.Name);
- if (pj != null)
- {
- var seq = pj.Sequence;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module) && !pmUsed.Contains(module))
- pmUsed.Add(module);
- }
- }
- }
- }
- }
- _isRunningInParallelMode = enableParallel && hasJobLpCount > 1 && pmUsed.Count > 1;
- }
- private void UpdateControlJobStatus()
- {
- if (_lstControlJobs.Count == 0)
- return;
- List<ControlJobInfo> cjRemoveList = new List<ControlJobInfo>();
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- bool allPjCompleted = true;
- foreach (var pjName in cj.ProcessJobNameList)
- {
- var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
- if (pj == null) { LOG.Error($"Not find pj named {pjName} in {cj.Name}"); continue; }
- if (pj.State != EnumProcessJobState.Complete &&
- pj.State != EnumProcessJobState.ProcessingComplete)
- {
- allPjCompleted = false; break;
- }
- if (allPjCompleted)
- {
- if (pj.SlotWafers != null)
- {
- pj.SlotWafers.ForEach(p =>
- {
- if (ModuleHelper.IsLoadPort(p.Item1))
- {
- allPjCompleted = allPjCompleted && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(p.Item1.ToString()), p.Item2);
- }
- });
- }
- }
- }
- if (allPjCompleted)
- {
- if (!_CycleData.IsCycleMode || (_CycleData.IsCycleMode && _CycleData.IsCycleEnd(ModuleHelper.Converter(cj.Module))))
- CompleteJobClean(cj);
- UploadWaferEndToEap();
- _FinishCJ(cj);
- cj.EndTime = DateTime.Now;
- string strInfo = $"{cj.Module} has finished: \r\n\r\nProcessed wafer number: {cj.LotWafers.Count} \r\nStart time: {cj.BeginTime} \r\nEnd time: {cj.EndTime} \r\nDuration: {(cj.EndTime - cj.BeginTime).TotalSeconds:F0} sec";
- EV.PostInfoLog("Scheduler", strInfo);
- if (SC.GetValue<bool>("System.Job.EnablePopDialogWhenJobDone"))
- {
- EV.PostPopDialogMessage(EventLevel.Information, "System Information", strInfo);
- }
- }
- }
- }
- if (_lstControlJobs.Any(cj => cj.State == EnumControlJobState.Completed) && _CycleData.IsCycleMode)
- {
- var completeCJs = from cj in _lstControlJobs
- where cj.State == EnumControlJobState.Completed
- select cj;
- var otherCJs = from cj in _lstControlJobs
- where cj.State != EnumControlJobState.Completed
- select cj;
- _lstControlJobs = otherCJs.Concat(completeCJs).ToList();
- _lstControlJobs.ForEach(cj =>
- {
- if (cj.State == EnumControlJobState.Completed)
- {
- _CycleData.IncreaseCount(ModuleHelper.Converter(cj.Module));
- if (_CycleData.IsCycleEnd(ModuleHelper.Converter(cj.Module)))
- return;
- cj.SetState(EnumControlJobState.Executing);
- cj.BeginTime = DateTime.Now;
- cj.LotWafers.ForEach(x =>
- {
- x.NextSequenceStep = 0;
- x.ProcessState = EnumWaferProcessStatus.Idle;
- });
- foreach (var pjName in cj.ProcessJobNameList)
- {
- var pj = _lstProcessJobs.Find(x => x.Name == pjName);
- if (pj == null)
- {
- LOG.Error($"Not find pj named {pjName} in {cj.Name}");
- continue;
- }
- pj.SetState(EnumProcessJobState.Queued);
- }
- }
- });
- }
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Completed
- && (!_CycleData.IsCycleMode || _CycleData.IsCycleMode && _CycleData.IsCycleEnd(ModuleHelper.Converter(cj.Module)))
- && (!_isAutoUnloadFoup || (_isAutoUnloadFoup && (GetModule(cj.Module.ToString()) as SchedulerLoadPort).IsUnloaded)))
- {
- (GetModule(cj.Module) as SchedulerLoadPort).NoteJobComplete();
- cjRemoveList.Add(cj);
- }
- }
- foreach (var cj in cjRemoveList)
- {
- List<ProcessJobInfo> pjRemoveList = _lstProcessJobs.Where(o => o.ControlJobName == cj.Name).ToList();
- pjRemoveList.ForEach(o => _lstProcessJobs.Remove(o));
- _lstControlJobs.Remove(cj);
- CalcedThroughput(pjRemoveList);
- }
- ControlJobInfo cjActived = null;
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- cjActived = cj;
- break;
- }
- }
- if (cjActived != null)
- {
- bool allPjResouceOk = true;
- string reason = string.Empty;
- foreach (var pjName in cjActived.ProcessJobNameList)
- {
- var pj = _lstProcessJobs.Find(x => x.Name == pjName);
- if (pj == null)
- {
- LOG.Error($"Not find pj named {pjName} in {cjActived.Name}");
- continue;
- }
- if (pj.State != EnumProcessJobState.Complete && pj.State != EnumProcessJobState.ProcessingComplete)
- {
- if (!CheckSequencePmReady(pj.Sequence, null, out _, out reason))
- {
- allPjResouceOk = false;
- break;
- }
- }
- }
- if (!allPjResouceOk)
- {
- cjActived.SetState(EnumControlJobState.Paused);
- EV.PostWarningLog(LogSource, $"{cjActived.Module} paused, {reason}");
- }
- }
- }
- private void _FinishCJ(ControlJobInfo cj)
- {
- cj.SetState(EnumControlJobState.Completed);
- int unprocessed_cj = 0;
- int aborted_cj = 0;
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name)
- {
- int unprocessed = 0;
- int aborted = 0;
- WaferInfo[] wafers = WaferManager.Instance.GetWaferByProcessJob(pj.Name);
- foreach (var waferInfo in wafers)
- {
- waferInfo.ProcessJob = null;
- waferInfo.NextSequenceStep = 0;
- if (waferInfo.ProcessState != EnumWaferProcessStatus.Completed)
- {
- unprocessed++;
- unprocessed_cj++;
- }
- }
- JobDataRecorder.EndPJ(pj.InnerId.ToString(), aborted, unprocessed);
- }
- }
- JobDataRecorder.EndCJ(cj.InnerId.ToString(), aborted_cj, unprocessed_cj);
- _faCallback.JobFinished(cj, GetFirstProcessJob(cj));
- _dbCallback.LotFinished(cj);
- }
- //private bool _HandleFinishedCycleCJ(ControlJobInfo cj)
- //{
- // //if (!cj.IsCycleMode) return false;
- // int countProcessed = 0;
- // foreach (var pjName in cj.ProcessJobNameList)
- // {
- // var pj = _lstProcessJobs.FirstOrDefault(x => x.Name == pjName);
- // if (pj == null) { LOG.Error($"Not find pj named {pjName} in {cj.Name}"); continue; }
- // if (pj.State == EnumProcessJobState.Complete || pj.State == EnumProcessJobState.ProcessingComplete)
- // {
- // foreach (var pjSlotWafer in pj.SlotWafers)
- // {
- // WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- // if (!wafer.IsEmpty && !CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
- // countProcessed++;
- // }
- // }
- // }
- // _CycleData.Increase(countProcessed);
- // int leftCount = _CycleData.CycleWaferCountSetPoint - _CycleData.CycledWaferCount;
- // // finished cycle
- // if (leftCount <= 0) return false;
- // // 移除老的cj
- // var pjList = _lstProcessJobs.Where(o => o.ControlJobName == cj.Name).ToList();
- // CalcedThroughput(pjList);
- // pjList.ForEach(o => _lstProcessJobs.Remove(o));
- // _lstControlJobs.Remove(cj);
- // // 模拟 LP unload / load
- // {
- // ModuleName mName = ModuleHelper.Converter(cj.Module);
- // var wafers_old = WaferManager.Instance.GetWafers(mName).ToList();
- // WaferManager.Instance.DeleteWafer(mName, 0, SC.GetValue<int>($"EFEM.LoadPort.CassetteSlotNumber"));
- // CarrierManager.Instance.DeleteCarrier(cj.Module);
- // CarrierManager.Instance.CreateCarrier(cj.Module);
- // foreach (var wafer in wafers_old)
- // {
- // if (wafer.Status != WaferStatus.Normal) continue;
- // var newWafer = WaferManager.Instance.CreateWafer(mName, wafer.Slot, wafer.Status);
- // newWafer.PPID = wafer.PPID;
- // CarrierManager.Instance.RegisterCarrierWafer(cj.Module, wafer.Slot, newWafer);
- // }
- // }
- // // 产生新的cj
- // ControlJobInfo newCj = new ControlJobInfo();
- // newCj.Name = cj.Name;
- // newCj.Module = cj.Module;
- // newCj.LotName = cj.LotName;
- // //newCj.IsCycleMode = cj.IsCycleMode;
- // //newCj.CycleWaferCountSP = cj.CycleWaferCountSP;
- // //newCj.CycledWaferCount = _CycleData.CycledWaferCount;
- // newCj.LotInnerId = Guid.NewGuid();
- // newCj.LotWafers = cj.LotWafers.Take(leftCount).ToList();
- // int addedCount = 0;
- // List<ProcessJobInfo> newPjList = new List<ProcessJobInfo>();
- // //int toAddCount = Math.Min(leftCount, cj.LotWafers.Count);
- // for (int ii = 0; ii < cj.ProcessJobNameList.Count; ii++)
- // {
- // string pjName = cj.ProcessJobNameList[ii];
- // var pj = pjList.FirstOrDefault(o => o.ControlJobName == cj.Name && o.Name == pjName);
- // if (pj == null) continue;
- // int toAddCount = Math.Min(leftCount - addedCount, cj.LotWafers.Count);
- // if (toAddCount <= 0) break;
- // addedCount += toAddCount;
- // ProcessJobInfo newPj = new ProcessJobInfo();
- // newPj.Name = pj.Name;
- // newPj.Sequence = pj.Sequence;
- // newPj.ControlJobName = pj.ControlJobName;
- // newPj.SlotWafers = pj.SlotWafers.Take(toAddCount).ToList();
- // newPj.SetState(EnumProcessJobState.Queued);
- // _lstProcessJobs.Add(newPj);
- // newCj.ProcessJobNameList.Add(pj.Name);
- // newPjList.Add(newPj);
- // }
- // _lstControlJobs.Add(newCj);
- // // 开始新的cj
- // newCj.SetState(EnumControlJobState.Executing);
- // newCj.LotInnerId = Guid.NewGuid();
- // newCj.BeginTime = DateTime.Now;
- // _dbCallback.LotCreated(newCj);
- // newPjList.ForEach(o => ActiveProcessJob(o));
- // return true;
- //}
- public bool CheckAllJobDone()
- {
- for(int i = 0; i < _lstLps.Count; i++)
- {
- var lp = _lstLps[i];
- if (lp != null && lp.IsAvailable)
- {
- _trigLp1JobComplete.CLK = CheckJobComplete(lp.Module.ToString());
- if (_trigLp1JobComplete.Q)
- {
- if (_isAutoUnloadFoup)
- {
- lp.Unload();
- }
- EV.Notify("CARRIER_PROCESS_COMPLETE", new SerializableDictionary<string, object>()
- {
- { "PortID", i+1},
- { "PORT_ID", i+1},
- { "CarrierID", CarrierManager.Instance.GetCarrier(lp.Module.ToString()).CarrierId},
- { "CAR_ID", CarrierManager.Instance.GetCarrier(lp.Module.ToString()).CarrierId}
- });
- }
- }
- }
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
- return false;
- }
- return _lstLps.All(p => p.IsAvailable);
- }
- private bool CheckJobComplete(string lp = null)
- {
- if (_lstProcessJobs.Count == 0)
- return false;
- if (_lstControlJobs.Count == 0)
- return false;
- if (_CycleData.IsCycleMode && !_CycleData.IsCycleEnd())
- return false;
- if (lp != null)
- {
- var cj = _lstControlJobs.Find(x => x.Module == lp);
- if (cj == null)
- return false;
- }
- foreach (var pj in _lstProcessJobs)
- {
- if (lp == null)
- {
- if (pj.State != EnumProcessJobState.ProcessingComplete)
- {
- return false;
- }
- }
- }
- foreach (var cj in _lstControlJobs)
- {
- if (lp == null)
- {
- if (cj.State != EnumControlJobState.Completed)
- {
- return false;
- }
- }
- else
- {
- if (cj.Module == lp && cj.State != EnumControlJobState.Completed)
- {
- return false;
- }
- }
- }
- return true;
- }
- private void StartNewJob()
- {
- ControlJobInfo cjActived = null;
- bool enableParallel = SC.GetValue<bool>("System.Scheduler.IsRunInParallelMode");
- List<ModuleName> pmOccupied = GetPmUsedInRunningPj();
- var orderedLstCJs = _lstControlJobs.OrderBy(x => x.BeginTime);
- foreach (var cj in orderedLstCJs)
- {
- if (cj.State != EnumControlJobState.Executing)
- continue;
- cjActived = cj;
- foreach (var pjName in cjActived.ProcessJobNameList)
- {
- var pj = _lstProcessJobs.Find(x => x.Name == pjName);
- if (pj == null)
- {
- LOG.Error($"Not find pj named {pjName} in {cjActived.Name}");
- continue;
- }
- if (pj.State == EnumProcessJobState.Queued)
- {
- var pmIsReady = CheckSequencePmReady(pj.Sequence, pmOccupied, out var pmUsed, out string reason);
- if (pmUsed.Count > 0)
- {
- var needPreClean = pmUsed.Any(x =>
- {
- return SC.GetValue<bool>($"{x.ToString()}.JobClean.IsEnabled") && SC.GetValue<bool>($"{x.ToString()}.JobClean.EnablePreJobClean");
- });
- if (needPreClean && !pmIsReady)
- break;
- ActiveProcessJob(pj);
- foreach (var moduleName in pmUsed)
- {
- if (!pmOccupied.Contains(moduleName))
- pmOccupied.Add(moduleName);
- }
- break;
- }
- }
- }
- if (!_isRunningInParallelMode)
- continue;
- }
- }
- private List<ModuleName> GetPmUsedInRunningPj()
- {
- var pmUsed = new List<ModuleName>();
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State != EnumControlJobState.Executing && cj.State != EnumControlJobState.Paused)
- continue;
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused))
- {
- for (int i = 0; i < pj.Sequence.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = pj.Sequence.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module) && !pmUsed.Contains(module))
- {
- pmUsed.Add(module);
- }
- }
- }
- }
- }
- }
- return pmUsed;
- }
- //private bool CheckSequencePmReady(SequenceInfo seq, out string reason)
- //{
- // for (int i = 0; i < seq.Steps.Count; i++)
- // {
- // SequenceStepInfo stepInfo = seq.Steps[i];
- // bool hasPm = false;
- // foreach (var module in stepInfo.StepModules)
- // {
- // if (ModuleHelper.IsPm(module))
- // {
- // PM pm = DEVICE.GetDevice<PM>(module.ToString());
- // if (pm.IsInstalled && !pm.IsError)
- // {
- // hasPm = true;
- // break;
- // }
- // }
- // else
- // {
- // hasPm = true; // other modules default ok
- // }
- // }
- // if (!hasPm)
- // {
- // reason = $"Step {i + 1} no valid PM, " + string.Join("|", stepInfo.StepModules);
- // return false;
- // }
- // }
- // reason = "";
- // return true;
- //}
- private bool CheckSequencePmReady(SequenceInfo seq, List<ModuleName> pmOccupied, out List<ModuleName> pmUsed, out string reason)
- {
- pmUsed = new List<ModuleName>();
- reason = "";
- bool pmIsReady = true;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- bool hasPm = false;
- foreach (var module in stepInfo.StepModules)
- {
- if (!ModuleHelper.IsPm(module))
- {
- hasPm = true;
- break;
- }
- PMModuleBase pm = null;
- pm = EquipmentManager.Modules[module] as PMModuleBase;
- if(pm != null && !pm.IsOnline)
- {
- reason = $"The selected sequence({string.Join("|", stepInfo.StepModules)}) of {module} chamber must be online";
- return false;
- }
- if (pm.IsInstalled && (pmOccupied == null || !pmOccupied.Contains(ModuleHelper.Converter(pm.Module))))
- {
- hasPm = true;
- }
- if (!pmUsed.Contains(ModuleHelper.Converter(pm.Module)))
- pmUsed.Add(ModuleHelper.Converter(pm.Module));
- }
- if (pmIsReady && !hasPm)
- {
- reason = $"Step {i + 1} no valid PM, " + string.Join("|", stepInfo.StepModules);
- pmIsReady = false;
- }
- }
- return pmIsReady;
- }
- private bool CheckSequenceRecipeFileValidTobedone(SequenceInfo seq, out string reason)
- {
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- var recipeContent =
- RecipeFileManager.Instance.LoadRecipe($"{module}\\", stepInfo.RecipeName, false);
- if (string.IsNullOrEmpty(recipeContent))
- {
- reason = $"Can not find recipe file {module}\\{stepInfo.RecipeName}";
- return false;
- }
- string cleanRecipeName = "";
- if (stepInfo.CleanInterval > 0
- && stepInfo.StepParameter.ContainsKey("CleanRecipeNoWafer")
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter["CleanRecipeNoWafer"]))
- {
- cleanRecipeName = (string)stepInfo.StepParameter["CleanRecipeNoWafer"];
- if (!string.IsNullOrEmpty(cleanRecipeName))
- {
- recipeContent =
- RecipeFileManager.Instance.LoadRecipe($"{module}\\", cleanRecipeName, false);
- if (string.IsNullOrEmpty(recipeContent))
- {
- reason = $"Can not find recipe file {module}\\{cleanRecipeName}";
- return false;
- }
- }
- }
- if (stepInfo.CleanInterval > 0
- && stepInfo.StepParameter.ContainsKey("CleanRecipeWafer")
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter["CleanRecipeWafer"]))
- {
- cleanRecipeName = (string)stepInfo.StepParameter["CleanRecipeWafer"];
- if (!string.IsNullOrEmpty(cleanRecipeName))
- {
- recipeContent =
- RecipeFileManager.Instance.LoadRecipe($"{module}\\", cleanRecipeName, false);
- if (string.IsNullOrEmpty(recipeContent))
- {
- reason = $"Can not find recipe file {module}\\{cleanRecipeName}";
- return false;
- }
- }
- }
- }
- }
- }
- reason = "";
- return true;
- }
- private bool CheckSequenceRecipeFileValid(SequenceInfo seq, out string reason)
- {
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- string pmRecipeName = module+ "Recipe";
- string recipeContent = RecipeFileManager.Instance.LoadRecipe("", stepInfo.StepParameter[pmRecipeName].ToString(), false);
- if (string.IsNullOrEmpty(recipeContent))
- {
- reason = $"Can not find recipe file {stepInfo.StepParameter[$"{module}Recipe"].ToString()}";
- return false;
- }
- if (Recipe.Parse(module.ToString(), recipeContent, out RecipeHead recipeHead, out var recipeSteps))
- {
- if(recipeHead != null && !string.IsNullOrWhiteSpace(recipeHead.NotToPurgeOrVent))
- {
- if(bool.TryParse(recipeHead.NotToPurgeOrVent, out bool isNotToPurgeOrVent))
- {
- if(isNotToPurgeOrVent)
- {
- reason = $"Check recipe checked(Not To Purge OR Vent)";
- return false;
- }
- }
- }
- }
- }
- }
- }
- reason = "";
- return true;
- }
- private bool CheckSequenceOrderOk(SequenceInfo seq, out string reason)
- {
- reason = "";
- bool foundPm = false;
- bool isLLBeforePm = false;
- bool isLLAfterPm = false;
- bool isAlignerAfterLL = false;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- foundPm = true;
- }
- if (!foundPm && ModuleHelper.IsLoadLock(module))
- {
- isLLBeforePm = true;
- }
- if (foundPm && ModuleHelper.IsLoadLock(module))
- {
- isLLAfterPm = true;
- }
- if (ModuleHelper.IsAligner(module) && (isLLBeforePm || foundPm))
- {
- isAlignerAfterLL = true;
- }
- }
- }
- if (!isLLBeforePm)
- {
- reason = $"not found LL before PM;";
- return false;
- }
- if (!isLLAfterPm)
- {
- reason = $"not found LL after PM;";
- return false;
- }
- if (!foundPm)
- {
- reason = $"not found PM in the sequence file;";
- return false;
- }
- if (isAlignerAfterLL)
- {
- reason = "Aligner after LL not support";
- return false;
- }
- List<ModuleName> preStepModules = new List<ModuleName>();
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (preStepModules.Count > 0)
- {
- //aligner前后不能是TMRobot
- if (ModuleHelper.IsAligner(module) && preStepModules.Exists(x => ModuleHelper.IsTM(x) || ModuleHelper.IsTMRobot(x)))
- {
- reason = $"Step {i + 1} is valid , TMRobot can't after Aligner";
- return false;
- }
- if ((ModuleHelper.IsTM(module) || ModuleHelper.IsTMRobot(module)) && preStepModules.Exists(x => ModuleHelper.IsAligner(x)))
- {
- reason = $"Step {i + 1} is valid , TMRobot can't before Aligner";
- return false;
- }
- //Cooling前后不能是TMRobot
- if (ModuleHelper.IsCooling(module) && preStepModules.Exists(x => ModuleHelper.IsTM(x) || ModuleHelper.IsTMRobot(x)))
- {
- reason = $"Step {i + 1} is valid , TMRobot can't after Cooling";
- return false;
- }
- if ((ModuleHelper.IsTM(module) || ModuleHelper.IsTMRobot(module)) && preStepModules.Exists(x => ModuleHelper.IsCooling(x)))
- {
- reason = $"Step {i + 1} is valid , TMRobot can't before Cooling";
- return false;
- }
- //PM前后不能是EfemRobot
- if (ModuleHelper.IsPm(module) && preStepModules.Exists(x => ModuleHelper.IsEfem(x) || ModuleHelper.IsEfemRobot(x)))
- {
- reason = $"Step {i + 1} is valid , EfemRobot can't after Pm";
- return false;
- }
- if ((ModuleHelper.IsEfem(module) || ModuleHelper.IsEfemRobot(module)) && preStepModules.Exists(x => ModuleHelper.IsPm(x)))
- {
- reason = $"Step {i + 1} is valid , EfemRobot can't before Pm";
- return false;
- }
- }
- preStepModules = stepInfo.StepModules;
- }
- }
- return true;
- }
- private bool CheckSequenceNeedDummyWafer(SequenceInfo seq)
- {
- bool needDummyWafer = false;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- if (stepInfo.CleanInterval > 0
- && stepInfo.StepParameter.ContainsKey("CleanRecipeWafer")
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter["CleanRecipeWafer"]))
- {
- needDummyWafer = true;
- break;
- }
- }
- }
- if (needDummyWafer)
- break;
- }
- return needDummyWafer;
- }
- private bool ActiveProcessJob(ProcessJobInfo pj)
- {
- //pm is ok
- if (!CheckSequencePmReady(pj.Sequence, null, out _, out string reason))
- {
- EV.PostWarningLog(LogSource, $"can not active {pj.Name}, {reason}");
- return false;
- }
- _lstPmsCurrentSequence.Clear();
- for (int i = 0; i < pj.Sequence.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = pj.Sequence.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- var pm = _lstPms.Find(x => x.Module == module);
- if (pm != null)
- _lstPmsCurrentSequence.Add(pm);
- }
- }
- }
- if (pj.SlotWafers != null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- wafer.ProcessJob = pj;
- wafer.NextSequenceStep = 0;
- WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), pj.InnerId.ToString());
- }
- }
- ControlJobInfo cj = _lstControlJobs.Find(x => x.Name == pj.ControlJobName);
- CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
- if (pj.SlotWafers != null)
- {
- JobDataRecorder.StartPJ(pj.InnerId.ToString(), carrier.InnerId.ToString(), cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);
- }
- pj.SetState(EnumProcessJobState.Processing);
- pj.BeginTime = DateTime.Now;
- OP.DoOperation(E40ProcessStateChanged, pj.Name, EnumProcessJobState.Processing);
- PreJobClean(cj);
- return true;
- }
- #endregion
- #region Module task
- public Result MonitorModuleTasks()
- {
- MonitorPMTask();
- MonitorEfemRobotTask();
- for (int i = 0; i < tmRobotActions.Count; i++)
- {
- MonitorTmRobotTask();
- }
- MonitorTmRobotGoToTask();
- MonitorLoadLockTask();
- MonitorInterlockTask();
- MonitorAlignerTask();
- MonitorCoolingTask();
- return Result.RUN;
- }
- private void MonitorInterlockTask()
- {
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused ||
- cj.State == EnumControlJobState.WaitingForStart)
- {
- if (!string.IsNullOrEmpty(cj.Module))
- {
- var lp = GetModule(cj.Module);
- _checkNoCarrierByModule[lp.Module].CLK = CarrierManager.Instance.CheckNoCarrier(lp.Module, 0);
- if (_checkNoCarrierByModule[lp.Module].Q)
- {
- EV.PostAlarmLog(lp.Module.ToString(), "Cassette removed while job not finished.");
- //Singleton<RouteManager>.Instance.PostMsg(RouteManager.MSG.ERROR);
- }
- }
- }
- }
- }
- private void MonitorAlignerTask()
- {
- foreach (var aligner in _lstAligners)
- {
- if (!aligner.IsAvailable)
- continue;
- if (aligner.CheckWaferNextStepIsThisModule(aligner.Module, 0))
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(aligner.Module, 0);
- if (aligner.Align(wafer.InnerId.ToString()))
- {
- wafer.NextSequenceStep++;
- }
- }
- }
- }
- private void MonitorCoolingTask()
- {
- foreach (var cooling in _lstCoolings)
- {
- if (!cooling.IsAvailable)
- continue;
- if (cooling.CheckWaferNextStepIsThisModule(cooling.Module, 0))
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(cooling.Module, 0);
- GetWaferSequenceCoolingTime(cooling.Module, 0, out int coolingTime);
- if (cooling.Cooling(coolingTime))
- {
- wafer.NextSequenceStep++;
- }
- }
- }
- }
- //private void MonitorBufferTask()
- //{
- // foreach (var buffer in _lstBuffers)
- // {
- // if (!buffer.IsAvailable)
- // continue;
- // }
- //}
- private void MonitorLoadLockTask()
- {
- foreach (var ll in _lstLls)
- {
- if (!ll.IsAvailable)
- continue;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (ll.FirstDetectWaferArrive(i))
- {
- ll.PostTransfer(ll.Module, EnumTransferType.Place, i);
- }
- }
- }
- // bool isPrepareTransferForEfemobotPlace = GetWaferCountInJobQueue() > 0;
- // foreach (var ll in _lstLls)
- // {
- // if (ll.Entity.IsPrepareTransfer)
- // {
- // return;
- // }
- // var deviceLL = DEVICE.GetDevice<LoadLock>(ll.Module.ToString());
- // //if (ll.CheckAtAtm() && (ll.Entity.IsCooling || deviceLL.CheckDoorOpen()))
- // if (deviceLL.CheckDoorOpen())
- // {
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // int emptySlot = 0;
- // foreach (var wafer in wafers)
- // {
- // if (wafer.IsEmpty || wafer.ProcessState != EnumWaferProcessStatus.Idle)
- // emptySlot++;
- // }
- // if (emptySlot >= GetWaferCountInJobQueue())
- // {
- // isPrepareTransferForEfemobotPlace = false;
- // break;
- // }
- // }
- // }
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsAvailable)
- // continue;
- // var deviceLL = DEVICE.GetDevice<LoadLock>(ll.Module.ToString());
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // var isEmptyLL = true;
- // bool isPrepareTransferForEfemobotPick = true;
- // for (int i = 0; i <= 5;)
- // {
- // var wafer0 = WaferManager.Instance.GetWafer(ll.Module, i);
- // var wafer1 = WaferManager.Instance.GetWafer(ll.Module, i + 1);
- // if (!wafer0.IsEmpty || !wafer1.IsEmpty)
- // isEmptyLL = false;
- // if (wafer0.IsEmpty && wafer1.IsEmpty && GetVacuumWafer() > 0)
- // isPrepareTransferForEfemobotPick = false;
- // if ((!wafer0.IsEmpty && wafer0.ProcessState == EnumWaferProcessStatus.Idle) ||
- // (!wafer1.IsEmpty && wafer1.ProcessState == EnumWaferProcessStatus.Idle))
- // isPrepareTransferForEfemobotPick = false;
- // i += 2;
- // }
- // if (isEmptyLL)
- // isPrepareTransferForEfemobotPick = false;
- // if (isPrepareTransferForEfemobotPlace && isEmptyLL && (_tmDevice.CheckSlitValveClose(ll.Module) || GetVacuumWafer() == 0) &&
- // !ll.Entity.IsPrepareTransferReady(ModuleName.EfemRobot, EnumTransferType.Place))
- // {
- // ll.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Place, 0);
- // return;
- // }
- // if (isPrepareTransferForEfemobotPick)
- // {
- // if (!ll.Entity.IsPrepareTransferReady(ModuleName.EfemRobot, EnumTransferType.Pick))
- // {
- // if (!_loadlockCooling.ContainsKey(ll.Module))
- // _loadlockCooling.Add(ll.Module, false);
- // _loadlockCooling[ll.Module] = false;
- // ll.PrepareTransfer(ModuleName.EfemRobot, EnumTransferType.Pick, 0);
- // return;
- // }
- // //TODO, cooling 要在 Open ATM door 之前做,PrepareTransfer 需要分开 [2021/7/3 TerryLu]
- // if (ll.Entity.IsPreCoolingDone())
- // {
- // foreach (var wafer in wafers)
- // {
- // if (wafer != null && !wafer.IsEmpty && GetWaferSequenceLoadLockCoolingTime(ll.Module, wafer.Slot, out int coolingTime))
- // {
- // _loadlockCooling[ll.Module] = true;
- // ll.Cooling(coolingTime);
- // break;
- // }
- // }
- // if (_loadlockCooling[ll.Module])
- // {
- // foreach (var wafer in wafers)
- // {
- // if (wafer != null && !wafer.IsEmpty)
- // {
- // wafer.NextSequenceStep++;
- // }
- // }
- // }
- // }
- // }
- // bool isPrepareTransferForTMRobot = true;
- // bool isAllEmpty = true;
- // foreach (var wafer in wafers)
- // {
- // if (!wafer.IsEmpty)
- // isAllEmpty = false;
- // if (wafer.IsEmpty && GetATMWafer() > 0)
- // {
- // isPrepareTransferForTMRobot = false;
- // break;
- // }
- // if (wafer.ProcessState != EnumWaferProcessStatus.Idle)
- // {
- // isPrepareTransferForTMRobot = false;
- // break;
- // }
- // }
- // if (isAllEmpty)
- // {
- // if (GetVacuumWafer() == 0)
- // {
- // isPrepareTransferForTMRobot = false;
- // }
- // else
- // {
- // foreach (var anotherLL in _lstLls)
- // {
- // if (!anotherLL.IsOnline || anotherLL == ll)
- // continue;
- // var anotherLLWafers = WaferManager.Instance.GetWafers(anotherLL.Module).ToList();
- // int count = 0;
- // for (int i = 0; i <= 5;)
- // {
- // if (WaferManager.Instance.CheckNoWafer(anotherLL.Module, i) && WaferManager.Instance.CheckNoWafer(anotherLL.Module, i + 1))
- // {
- // count++;
- // }
- // i += 2;
- // }
- // if (count >= GetVacuumWafer())
- // {
- // isPrepareTransferForTMRobot = false;
- // break;
- // }
- // }
- // }
- // }
- // if (isPrepareTransferForTMRobot && !ll.Entity.IsPrepareTransferReady(ModuleName.TMRobot, EnumTransferType.Pick))
- // {
- // ll.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Pick, 0);
- // continue;
- // }
- // }
- }
- private void MonitorPMTask()
- {
- foreach (var pm in _lstPms)
- {
- if (!pm.IsAvailable)
- continue;
- if (WaferManager.Instance.CheckHasWafer(pm.Module, 0) || WaferManager.Instance.CheckHasWafer(pm.Module, 1))
- {
- if (CheckNeedRunClean(pm.Module, out bool withWafer, out string recipe) && withWafer
- && WaferManager.Instance.GetWafer(pm.Module, 0).Status == WaferStatus.Dummy
- && WaferManager.Instance.GetWafer(pm.Module, 0).ProcessState == EnumWaferProcessStatus.Wait
- && WaferManager.Instance.GetWafer(pm.Module, 1).Status == WaferStatus.Dummy
- && WaferManager.Instance.GetWafer(pm.Module, 1).ProcessState == EnumWaferProcessStatus.Wait)
- {
- pm.Process(recipe, true, withWafer);
- continue;
- }
- var wafer0 = WaferManager.Instance.GetWafer(pm.Module, 0);
- var wafer1 = WaferManager.Instance.GetWafer(pm.Module, 1);
- if (CheckCanProcess(pm.Module))
- {
- WaferInfo wafer = wafer0.Status != WaferStatus.Empty ? wafer0 : wafer1;
- if (pm.Process(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter[$"{pm.Module}Recipe"].ToString(), false, true))
- {
- if (wafer0.Status != WaferStatus.Empty)
- wafer0.NextSequenceStep++;
- if (wafer1.Status != WaferStatus.Empty)
- wafer1.NextSequenceStep++;
- continue;
- }
- }
- }
- else
- {
- if (CheckNeedRunClean(pm.Module, out bool withWafer, out string recipe) && !withWafer)
- {
- pm.Process(recipe, true, withWafer);
- continue;
- }
- if (!SC.IsATMMode)
- {
- if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0)
- && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1)
- && _lstAligners.All(p => WaferManager.Instance.CheckNoWafer(p.Module, 0))
- && Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p))
- && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p))
- && _lstCoolings.All(p => WaferManager.Instance.CheckNoWafer(p.Module, 0))
- && _lstPms.All(p => _pmSlots.All(s => WaferManager.Instance.CheckNoWafer(p.Module, s)))
- && _lstLls.All(p => _llSlots.All(s => WaferManager.Instance.CheckNoWafer(p.Module, s)))
- )
- {
- SlotItem item = GetNextWaferInJobQueue(ModuleName.System, pm.Module);
- if (item != null && CheckWaferNeedProcessPre(item.Module, item.Slot, pm.Module))
- {
- if (GetWaferTemperatureSetInRecipe(item.Module, item.Slot, pm.Module, out double temp1, out double temp2) && !pm.CheckTempReady(temp1, temp2))
- {
- //if (temp1 != 0 && temp2 != 0)
- {
- pm.Preheating(temp1, temp2);
- continue;
- }
- }
- }
- }
- }
- }
- //if (!pm.IsAvailable)
- // continue;
- //var wafers = FindAllLoadLockSlotForTMRobotPick();
- //if (wafers.Count > 0)
- //{
- // if (wafers.Any(x => CheckWaferNeedProcess(x.Item1.Module, x.Item2, pm.Module)))
- // {
- // for (int i = 0; i < WaferManager.Instance.GetWafers(pm.Module).Length; i++)
- // {
- // if (WaferManager.Instance.CheckNoWafer(pm.Module, i) && !pm.IsReadyForPlace(ModuleName.TMRobot, Hand.Blade1, i))
- // {
- // pm.PrepareTransfer(ModuleName.TMRobot, EnumTransferType.Place, i);
- // return;
- // }
- // }
- // }
- //}
- //else
- //{
- // if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0)
- // && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1)
- // && WaferManager.Instance.CheckNoWafer(pm.Module, 0)
- // && WaferManager.Instance.CheckNoWafer(pm.Module, 1)
- // && _tmRobot.IsAvailable
- // && !pm.CheckSlitValveClose())
- // {
- // pm.CloseSlitValve();
- // return;
- // }
- //}
- }
- }
- public bool CheckLLANoWafer()
- {
- var _LLANoWafer = true;
- for (int _llacount = 0; _llacount <= 7; _llacount++)
- {
- _LLANoWafer = WaferManager.Instance.CheckNoWafer(ModuleName.LLA, _llacount);
- }
- return _LLANoWafer;
- }
- public bool CheckLLBNoWafer()
- {
- var _LLBNoWafer = true;
- for (int _llbcount = 0; _llbcount <= 7; _llbcount++)
- {
- _LLBNoWafer = WaferManager.Instance.CheckNoWafer(ModuleName.LLB, _llbcount);
- }
- return _LLBNoWafer;
- }
- private void MonitorTmRobotTask()
- {
- if (_tmRobot.FirstDetectWaferArrive(0) && _tmRobot.CheckWaferNextStepIsThisModule(ModuleName.TMRobot, (int)ArmBlade.ArmAFork0))
- GetModule(_tmRobot.Module).GetWaferInfo((int)ArmBlade.ArmAFork0).NextSequenceStep++;
- if (_tmRobot.FirstDetectWaferArrive(1) && _tmRobot.CheckWaferNextStepIsThisModule(ModuleName.TMRobot, (int)ArmBlade.ArmBFork1))
- GetModule(_tmRobot.Module).GetWaferInfo((int)ArmBlade.ArmBFork1).NextSequenceStep++;
- if(SC.IsDoubleFork)
- {
- if (_tmRobot.FirstDetectWaferArrive(2) && _tmRobot.CheckWaferNextStepIsThisModule(ModuleName.TMRobot, (int)ArmBlade.ArmAFork2))
- GetModule(_tmRobot.Module).GetWaferInfo((int)ArmBlade.ArmAFork2).NextSequenceStep++;
- if (_tmRobot.FirstDetectWaferArrive(3) && _tmRobot.CheckWaferNextStepIsThisModule(ModuleName.TMRobot, (int)ArmBlade.ArmBFork3))
- GetModule(_tmRobot.Module).GetWaferInfo((int)ArmBlade.ArmBFork3).NextSequenceStep++;
- }
- if (!_tmRobot.IsAvailable)
- return;
- //TM robot is idle, release all the target
- foreach (var ll in _lstLls)
- {
- if (ll.IsWaitTransfer(ModuleName.TMRobot))
- ll.StopWaitTransfer(ModuleName.TMRobot);
- }
- foreach (var pm in _lstPms)
- {
- if (pm.IsWaitTransfer(ModuleName.TMRobot))
- pm.StopWaitTransfer(ModuleName.TMRobot);
- }
- //MonitorTmRobotDummyWaferBufferTask();
- //if (!_tmRobot.IsAvailable)
- // return;
- if (!_tmRobot.IsAvailable)
- return;
- tmRobotActions.FirstOrDefault(p=>p== MonitorTmRobotPMPickAndPlaceTask)?.Invoke();
- if (!_tmRobot.IsAvailable)
- return;
- var act = tmRobotActions.Peek();
- act.Invoke();
- if (!_tmRobot.IsAvailable)
- return;
- if (act == MonitorTmRobotLoadLockPickTask)
- {
- List<Tuple<SchedulerLoadLock, int>> availableLoadLockSlots = FindAllLoadLockSlotForTMRobotPick();
- if (availableLoadLockSlots.Count > 0)
- {
- Tuple<SchedulerLoadLock, int> firstSlot = GetWaferOrderInJobQueue(availableLoadLockSlots);
- if (firstSlot != null)
- {
- SchedulerLoadLock ll = firstSlot.Item1;
- int pickSlot = firstSlot.Item2;
- if (!ll.IsAvailable)
- return;
- }
- }
- }
- if (act == MonitorTmRobotLoadLockPlaceTask && _lstLls.All(x => !x.IsAvailable))
- return;
- tmRobotActions.Enqueue(tmRobotActions.Dequeue());
- //MonitorTmRobotLoadLockPickTask();
- //if (!_tmRobot.IsAvailable)
- // return;
- //MonitorTmRobotPMPickTask();
- //if (!_tmRobot.IsAvailable)
- // return;
- //MonitorTmRobotLoadLockPlaceTask();
- //if (!_tmRobot.IsAvailable)
- // return;
- //MonitorTmRobotPMPlaceTask();
- //if (!_tmRobot.IsAvailable)
- // return;
- //MonitorTmRobotGoToTask();
- }
- private void MonitorTmRobotLoadLockPlaceTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (SC.IsDoubleFork && _lstLls.Any(x => !x.IsAvailable))
- return;
- //place to ll
- bool blade0HasWaferAndProcessed = _tmRobot.Blade1Enable && CheckHasWaferAndNextStepIsLoadLock(Hand.Blade1);
- bool blade1HasWaferAndProcessed = _tmRobot.Blade2Enable && CheckHasWaferAndNextStepIsLoadLock(Hand.Blade2);
- if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed)
- {
- Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2;
- var panAndSlots = Converter.GetPanAndSlotFromPlace(placeBlade);
- foreach (var ll in _lstLls)
- {
- if (!ll.IsAvailable)
- continue;
- if (panAndSlots.Item2.Count() >0 && !panAndSlots.Item2.All(p=> CheckWaferNextStepIsLoadLock(ModuleName.TMRobot, p, ll.Module))) continue;
- var placeSlot = GetAvilableLoadLockSlotForTMRobotPlace(placeBlade,ll);
- if (placeSlot != null && placeSlot.Count() > 0)
- {
- if (_tmRobot.Place(ll.Module, Converter.MapPanToLLSlot(panAndSlots.Item1, placeSlot.ToArray()), placeBlade, panAndSlots.Item1, 0, 0, false))
- {
- Array.ForEach(panAndSlots.Item2, p=> WaferManager.Instance.GetWafer(ModuleName.TMRobot, p).NextSequenceStep++);
- if (SC.IsDoubleFork)
- _lstLls.All(p => p.WaitTransfer(ModuleName.TMRobot));
- else
- ll.WaitTransfer(ModuleName.TMRobot);
-
- return;
- }
- }
- }
- }
- if (GetEmptySlotInPM() < 1)
- return;
- }
- private void MonitorTmRobotLoadLockPickTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (SC.IsDoubleFork && _lstLls.Any(x => !x.IsAvailable))
- return;
- if (!CanTmRobotLoadLockPick())
- return;
- //pick from ll
- bool blade1EmptyAndEnable = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- bool blade2EmptyAndEnable = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- if (blade1EmptyAndEnable || blade2EmptyAndEnable)
- {
- //if (_lstLls.All(x => !x.IsAvailable))
- // return;
- List<Tuple<SchedulerLoadLock, int>> availableLoadLockSlots = FindAllLoadLockSlotForTMRobotPick();
- if (availableLoadLockSlots.Count > 0)
- {
- var targetLoadLock = TryFindLLAndPairSlot(availableLoadLockSlots);
- if (targetLoadLock == null) return;
- var slots = targetLoadLock.Item2;
- var ll = targetLoadLock.Item1;
- Hand pickBlade = Hand.Blade1;
- foreach (var slot in slots)
- {
- if ((blade1EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(ll.Module, slot, 0)) ||
- (blade1EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(ll.Module, slot, 1)))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(ll.Module, slot, 1) ||
- (blade2EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(ll.Module, slot, 0)))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- }
- if (slots.All(p => ll.IsReadyForPick(ModuleName.TMRobot, pickBlade, p)) &&
- _tmRobot.Pick(ll.Module, slots.ToArray(), pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, slots.ToArray()).Item1, 0, 0, false))
- {
- if (SC.IsDoubleFork)
- _lstLls.All(p => p.WaitTransfer(ModuleName.TMRobot));
- else
- ll.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- private R_TRIG tmRobotGotoLoadLockTrig = new R_TRIG();
- private R_TRIG tmRobotGotoPMTrig = new R_TRIG();
- SchedulerPM gotoPm = null;
- private void MonitorTmRobotGoToTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (!SC.IsDoubleFork)
- return;
- if (_lstLps.SelectMany(p => WaferManager.Instance.GetWafers(p.Module).Where(m => !m.IsEmpty && m.ProcessJob != null && m.ProcessJob.Sequence != null))
- .Select(w => w.ProcessJob.Sequence.Name).GroupBy(p => p).Count() > 1)
- return;
- if ((_tmRobot.Blade1Enable ^ _tmRobot.Blade2Enable) &&
- (Converter.MapBladeToSlots(Hand.Blade1).Any(p => WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p)) ||
- Converter.MapBladeToSlots(Hand.Blade2).Any(p => WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, p))))
- return;
- if ((_tmRobot.Blade1Enable ^ _tmRobot.Blade2Enable) ||
- (_lstLls.SelectMany(ll => WaferManager.Instance.GetWafers(ll.Module).Where(w => CheckWaferNeedProcess(w))).Count() < 1 && GetUnprocessedWaferCount() < 1) ||
- (_tmRobot.Blade1Enable && _tmRobot.Blade2Enable &&
- (Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)) ^
- Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)))))
- {
- Hand pickBlade = (Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)) && _tmRobot.Blade1Enable) ? Hand.Blade1 : Hand.Blade2;
- Hand placeBlade = pickBlade == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1;
- SchedulerPM gotoPm = null;
- foreach (var pm in _lstPms)
- {
- if (_pmSlots.All(p => WaferManager.Instance.CheckNoWafer(pm.Module, p))
- || (Converter.MapBladeToSlots(placeBlade).Any(p=>WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot,p))
- && !CheckCanPlaceWaferToPM(pm.Module, placeBlade)))
- continue;
- if (gotoPm == null || (pm.WaferArriveTicks[0] < gotoPm.WaferArriveTicks[0]))
- {
- gotoPm = pm;
- }
- }
- if(gotoPm != null && _tmRobot.PreviousTarget != gotoPm.Module)
- {
- var slots = _pmSlots.Where(p=>WaferManager.Instance.CheckHasWafer(gotoPm.Module,p)).ToArray();
- _tmRobot.Goto(gotoPm.Module, slots, pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, slots).Item1);
- }
- }
- }
- private bool CanTmRobotLoadLockPick()
- {
- //单手臂时1片就允许TMRobot取片
- var StartPickCount = (_PMA1Disabled || _PMA2Disabled || _PMB1Disabled || _PMB2Disabled) ? 0 : 1;
- var targetWafers = FindAllLoadLockSlotForTMRobotPick();
- if ((targetWafers.Count <= StartPickCount
- && GetUnprocessedWaferCount() >= 1
- && WaferManager.Instance.GetWafers(ModuleName.TMRobot).All(x => x.IsEmpty)
- && CheckSequenceNameAndNeedProcess(targetWafers)) ||
- (SC.IsDoubleFork && !ExistPairWafer(targetWafers) && CheckSequenceNameAndNeedProcess(targetWafers))
- )
- return false;
- var tmWafers = WaferManager.Instance.GetWafers(ModuleName.TMRobot);
- for (int i = 0; i < tmWafers.Length; i++)
- {
- //disable功能启用后只允许单手臂动作
- if (!tmWafers[i].IsEmpty && (_PMA1Disabled || _PMA2Disabled || _PMB1Disabled || _PMB2Disabled))
- return false;
- if (!tmWafers[i].IsEmpty && !CheckWaferNeedProcess(tmWafers[i]))
- return false;
- }
- foreach (var pm in _lstPms)
- {
- var pmWafer0 = WaferManager.Instance.GetWafer(pm.Module, 0);
- var pmWafer1 = WaferManager.Instance.GetWafer(pm.Module, 1);
- //如果腔体中两片都满了,则跳过
- if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
- continue;
- //如果腔体中一片为空,则取一片相同recipeName的放入
- if (!pmWafer0.IsEmpty)
- {
- var wafer = pmWafer0;
- if (!CheckWaferNeedProcess(wafer))
- continue;
- //判断TMRobot是否已经存在相同recipeName的wafer
- for (int i = 0; i < tmWafers.Length; i++)
- {
- if (CheckWaferNeedProcessBySlot(tmWafers[i], pm.Module, 1)
- && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- return false;
- }
- }
- if (!pmWafer1.IsEmpty)
- {
- var wafer = pmWafer1;
- if (!CheckWaferNeedProcess(wafer))
- continue;
- //判断TMRobot是否已经存在相同recipeName的wafer
- for (int i = 0; i < tmWafers.Length; i++)
- {
- if (CheckWaferNeedProcessBySlot(tmWafers[i], pm.Module, 0)
- && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- return false;
- }
- }
- }
- return true;
- }
- private bool CheckCanPlaceWaferToPM(ModuleName pm, Hand placeBlade)
- {
- var pmSlotAndHandSlot = new Dictionary<int, int>() { { _pmSlots[0], (int)placeBlade }, { _pmSlots[1], ((int)placeBlade) + 2 } };
- foreach (var item in pmSlotAndHandSlot)
- {
- if(WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, item.Value) &&
- !CheckWaferNeedProcessBySlot(WaferManager.Instance.GetWafer(ModuleName.TMRobot, item.Value), pm,item.Key))
- {
- return false;
- }
- }
- return true;
- }
- private void MonitorTmRobotPMPickAndPlaceTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (!SC.IsDoubleFork)
- return;
- if (_tmRobot.Blade1Enable && _tmRobot.Blade2Enable &&
- (Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)) ^
- Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p))))
- {
- Hand pickBlade = Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p)) ? Hand.Blade1 : Hand.Blade2;
- Hand placeBlade = pickBlade == Hand.Blade1 ? Hand.Blade2 : Hand.Blade1;
- SchedulerPM swapPm = null;
- foreach (var pm in _lstPms)
- {
- if (!pm.IsAvailable || _pmSlots.All(p=> WaferManager.Instance.CheckNoWafer(pm.Module, p))
- || _pmSlots.Any(p=> CheckWaferNeedProcess(pm.Module, p, pm.Module))
- || _pmSlots.Any(p=> !pm.IsReadyForPick(ModuleName.TMRobot, pickBlade, p))
- || !CheckCanPlaceWaferToPM(pm.Module, placeBlade))
- continue;
- if (swapPm == null || (pm.WaferArriveTicks[0] < swapPm.WaferArriveTicks[0]))
- {
- swapPm = pm;
- }
- }
- if (swapPm != null && GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, swapPm.Module, out double temp1, out double temp2))
- {
- var panAndSlotFromPlace = Converter.GetPanAndSlotFromPlace(placeBlade);
- var pickSlot = _pmSlots.Where(p => WaferManager.Instance.CheckHasWafer(swapPm.Module, p)).ToArray();
- var panAndSlotFromPick = Converter.GetPanAndSlotFromPick(pickBlade, pickSlot);
- if (_tmRobot.PickAndPlace(swapPm.Module, pickBlade, panAndSlotFromPick.Item1, pickSlot, placeBlade, panAndSlotFromPlace.Item1, Converter.MapPanToPmSlot(panAndSlotFromPlace.Item1), temp1, temp2))
- {
- ResetPmSwapWaitTimeOut(swapPm.Module);
- swapPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- private void MonitorTmRobotPMAPlaceTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (!_pm1.IsAvailable)
- return;
- //place
- bool blade0HasWaferAndNeedProcesse = _tmRobot.Blade1Enable && CheckHasWaferAndNeedProcess(Hand.Blade1);
- bool blade1HasWaferAndNeedProcesse = _tmRobot.Blade2Enable && CheckHasWaferAndNeedProcess(Hand.Blade2);
- if (blade0HasWaferAndNeedProcesse || blade1HasWaferAndNeedProcesse)
- {
- Hand placeBlade = blade0HasWaferAndNeedProcesse ? Hand.Blade1 : Hand.Blade2;
- //var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
- //foreach (var schedulerPm in _lstPms)
- {
- var schedulerPm = _pm1;
- if (!schedulerPm.IsAvailable)
- return;
- var pmWafer0 = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
- var pmWafer1 = WaferManager.Instance.GetWafer(schedulerPm.Module, 1);
- //如果腔体中两片都满了,则不允许放入
- if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
- return;
- if (blade0HasWaferAndNeedProcesse && blade1HasWaferAndNeedProcesse)
- {
- var targetHands = CheckCanPlaceWaferToPM(new Hand[] { Hand.Blade1, Hand.Blade2 }, schedulerPm.Module);
- if (targetHands.Count > 1)
- {
- placeBlade = Hand.Blade1;
- if (GetHandWafers(Hand.Blade2).Select(p => p.OriginSlot).Min() < GetHandWafers(Hand.Blade1).Select(p => p.OriginSlot).Min())
- {
- placeBlade = Hand.Blade2;
- }
- }
- else if (targetHands.Count == 1)
- placeBlade = targetHands[0];
- }
- var panAndSlot = Converter.GetPanAndSlotFromPlace(placeBlade);
- //如果腔体中两片都为空
- if (pmWafer0.IsEmpty && pmWafer1.IsEmpty)
- {
- if (SC.IsDoubleFork)
- {
- if (_PMA1Disabled || _PMA2Disabled) return;
- if (!_pmSlots.All(p => WaferManager.Instance.CheckNoWafer(schedulerPm.Module, p))) return;
- var wafers = GetHandWafers(placeBlade);
- for(int i = 0;i< wafers.Length; i++)
- {
- if (!CheckCanPlaceWaferToPM(schedulerPm.Module, i, wafers[i])) return;
- }
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, panAndSlot.Item2[0], ModuleName.PMA, out double temp1, out double temp2))
- {
- var pmSlots = Converter.MapPanToPmSlot(panAndSlot.Item1);
- if (pmSlots != null && _tmRobot.Place(schedulerPm.Module, pmSlots, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- else
- {
- Dictionary<int, bool> targetSlots = new Dictionary<int, bool>() { { 0, _PMA1Disabled }, { 1, _PMA2Disabled } };
- foreach(var targetSlot in targetSlots.Keys)
- {
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, targetSlot) &&
- CheckCanPlaceWaferToPM(schedulerPm.Module, targetSlot, WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade)) &&
- !targetSlots[targetSlot])
- {
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMA, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { targetSlot}, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- }
- if (SC.IsDoubleFork) return;
- //如果腔体中一片为空,则取一片相同recipeName的放入
- if (!pmWafer0.IsEmpty)
- {
- var pmWafer = pmWafer0;
- if (!CheckWaferNeedProcess(pmWafer))
- return;
- int placeSlot = 1;
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, placeSlot))
- {
- if (!GetSameRecipeNameByHand(schedulerPm, placeSlot, out Hand newPlaceBlade))
- return;
- placeBlade = newPlaceBlade;
- if (_PMA2Disabled)
- return;
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMA, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { placeSlot }, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- if (!pmWafer1.IsEmpty)
- {
- var pmWafer = pmWafer1;
- if (!CheckWaferNeedProcess(pmWafer))
- return;
- int placeSlot = 0;
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, placeSlot))
- {
- if (!GetSameRecipeNameByHand(schedulerPm, placeSlot, out Hand newPlaceBlade))
- return;
- placeBlade = newPlaceBlade;
- if (_PMA1Disabled)
- return;
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMA, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { placeSlot }, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- }
- }
- private void MonitorTmRobotPMBPlaceTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- if (!_pm2.IsAvailable)
- return;
- //place
- bool blade0HasWaferAndNeedProcesse = _tmRobot.Blade1Enable && CheckHasWaferAndNeedProcess(Hand.Blade1);
- bool blade1HasWaferAndNeedProcesse = _tmRobot.Blade2Enable && CheckHasWaferAndNeedProcess(Hand.Blade2);
- if (blade0HasWaferAndNeedProcesse || blade1HasWaferAndNeedProcesse)
- {
- Hand placeBlade = blade0HasWaferAndNeedProcesse ? Hand.Blade1 : Hand.Blade2;
- var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade);
- //foreach (var schedulerPm in _lstPms)
- {
- var schedulerPm = _pm2;
- if (!schedulerPm.IsAvailable)
- return;
- var pmWafer0 = WaferManager.Instance.GetWafer(schedulerPm.Module, 0);
- var pmWafer1 = WaferManager.Instance.GetWafer(schedulerPm.Module, 1);
- //如果腔体中两片都满了,则不允许放入
- if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
- return;
- if (blade0HasWaferAndNeedProcesse && blade1HasWaferAndNeedProcesse)
- {
- var targetHands = CheckCanPlaceWaferToPM(new Hand[] { Hand.Blade1, Hand.Blade2 }, schedulerPm.Module);
- if (targetHands.Count > 1)
- {
- placeBlade = Hand.Blade1;
- if (GetHandWafers(Hand.Blade2).Select(p => p.OriginSlot).Min() < GetHandWafers(Hand.Blade1).Select(p => p.OriginSlot).Min())
- {
- placeBlade = Hand.Blade2;
- }
- }
- else if (targetHands.Count == 1)
- placeBlade = targetHands[0];
- }
- var panAndSlot = Converter.GetPanAndSlotFromPlace(placeBlade);
- //如果腔体中两片都为空
- if (pmWafer0.IsEmpty && pmWafer1.IsEmpty)
- {
- if (SC.IsDoubleFork)
- {
- if (_PMB1Disabled || _PMB2Disabled) return;
- var wafers = GetHandWafers(placeBlade);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (!CheckCanPlaceWaferToPM(schedulerPm.Module, i, wafers[i])) return;
- }
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, panAndSlot.Item2[0], ModuleName.PMB, out double temp1, out double temp2))
- {
- var pmSlots = Converter.MapPanToPmSlot(panAndSlot.Item1);
- if (pmSlots != null && _tmRobot.Place(schedulerPm.Module, pmSlots, placeBlade, panAndSlot.Item1,temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- else
- {
- Dictionary<int, bool> targetSlots = new Dictionary<int, bool>() { { 0, _PMB1Disabled }, { 1, _PMB2Disabled } };
- foreach (var targetSlot in targetSlots.Keys)
- {
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, targetSlot)
- && CheckCanPlaceWaferToPM(schedulerPm.Module, targetSlot, WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)placeBlade))
- && !targetSlots[targetSlot])
- {
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMB, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { targetSlot }, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- }
- if (SC.IsDoubleFork) return;
- //如果腔体中一片为空,则取一片相同recipeName的放入
- if (!pmWafer0.IsEmpty)
- {
- var pmWafer = pmWafer0;
- if (!CheckWaferNeedProcess(pmWafer))
- return;
- int placeSlot = 1;
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, placeSlot))
- {
- if (!GetSameRecipeNameByHand(schedulerPm, placeSlot, out Hand newPlaceBlade))
- return;
- placeBlade = newPlaceBlade;
- if (_PMB2Disabled)
- return;
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMB, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { placeSlot }, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- if (!pmWafer1.IsEmpty)
- {
- var pmWafer = pmWafer1;
- if (!CheckWaferNeedProcess(pmWafer))
- return;
- int placeSlot = 0;
- if (WaferManager.Instance.CheckNoWafer(schedulerPm.Module, placeSlot))
- {
- if (!GetSameRecipeNameByHand(schedulerPm, placeSlot, out Hand newPlaceBlade))
- return;
- placeBlade = newPlaceBlade;
- if (_PMB1Disabled)
- return;
- if (GetWaferTemperatureSetInRecipe(ModuleName.TMRobot, (int)placeBlade, ModuleName.PMB, out double temp1, out double temp2))
- {
- if (_tmRobot.Place(schedulerPm.Module, new int[] { placeSlot }, placeBlade, panAndSlot.Item1, temp1, temp2, true))
- {
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- }
- }
- private bool GetSameRecipeNameByHand(SchedulerPM schedulerPm, int placeSlot, out Hand placeHand)
- {
- placeHand = Hand.Blade1;
- if (_tmRobot.Blade1Enable && CheckHasWaferAndNeedProcess(Hand.Blade1) &&
- CheckCanPlaceWaferToPM(schedulerPm.Module, placeSlot, WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)Hand.Blade1)))
- {
- placeHand = Hand.Blade1;
- return true;
- }
- else if (_tmRobot.Blade2Enable && CheckHasWaferAndNeedProcess(Hand.Blade2) &&
- CheckCanPlaceWaferToPM(schedulerPm.Module, placeSlot, WaferManager.Instance.GetWafer(ModuleName.TMRobot, (int)Hand.Blade2)))
- {
- placeHand = Hand.Blade2;
- return true;
- }
- return false;
- }
- private void MonitorTmRobotPMAPickTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- bool blade1EmptyAndEnable = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- bool blade2EmptyAndEnable = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- // pick
- if (blade1EmptyAndEnable || blade2EmptyAndEnable)
- {
- //foreach (var schedulerPm in _lstPms)
- {
- var schedulerPm = _pm1;
- if (!schedulerPm.IsAvailable)
- return;
- var canPickSlotAndHand = new Dictionary<int, Tuple<Hand,double,double>>();
- var targetSlotAndHandSlots = new Dictionary<int, Tuple<int, int>>() { { 0, new Tuple<int, int>(0, 1) }, { 1, new Tuple<int, int>(0, 1) } };
- foreach(var targetSlot in targetSlotAndHandSlots.Keys)
- {
- if (IsExistSwap(schedulerPm.Module, targetSlot)) return;
- if (CheckCanPickWaferFromPM(schedulerPm.Module, targetSlot) &&
- GetWaferTemperatureSetInRecipe(schedulerPm.Module, targetSlot, ModuleName.PMA, out double temp1, out double temp2))
- {
- Hand pickBlade;
- if ((blade1EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item1)) ||
- (blade1EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item2)))
- {
- pickBlade = Hand.Blade1;
- }
- else if ((blade2EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item2)) ||
- (blade2EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item1)))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (schedulerPm.IsReadyForPick(ModuleName.TMRobot, pickBlade, targetSlot))
- {
- if (!SC.IsDoubleFork && _tmRobot.Pick(schedulerPm.Module, new int[] { targetSlot }, pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, new int[] { targetSlot }).Item1, temp1, temp2, true))
- {
- ResetPmSwapWaitTimeOut(schedulerPm.Module);
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- canPickSlotAndHand[targetSlot] = new Tuple<Hand, double, double>(pickBlade, temp1, temp2);
- }
- }
- }
- if (canPickSlotAndHand.Count>0)
- {
- if (!SC.IsDoubleFork && canPickSlotAndHand.Count > 1) canPickSlotAndHand.Remove(1);
- var firstSlot= canPickSlotAndHand.Keys.First();
- var pickBlade = canPickSlotAndHand[firstSlot].Item1;
- var temp1 = canPickSlotAndHand[firstSlot].Item2;
- var temp2 = canPickSlotAndHand[firstSlot].Item3;
- if (_tmRobot.Pick(schedulerPm.Module, canPickSlotAndHand.Keys.ToArray(), pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, canPickSlotAndHand.Keys.ToArray()).Item1, temp1, temp2, true))
- {
- ResetPmSwapWaitTimeOut(schedulerPm.Module);
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- private void MonitorTmRobotPMBPickTask()
- {
- if (!_tmRobot.IsAvailable)
- return;
- bool blade1EmptyAndEnable = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- bool blade2EmptyAndEnable = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- // pick
- if (blade1EmptyAndEnable || blade2EmptyAndEnable)
- {
- //foreach (var schedulerPm in _lstPms)
- {
- var schedulerPm = _pm2;
- if (!schedulerPm.IsAvailable)
- return;
- var canPickSlotAndHand = new Dictionary<int, Tuple<Hand, double, double>>();
- var targetSlotAndHandSlots = new Dictionary<int, Tuple<int, int>>() { { 0, new Tuple<int, int>(0, 1) }, { 1, new Tuple<int, int>(0, 1) } };
- foreach(var targetSlot in targetSlotAndHandSlots.Keys)
- {
- if (IsExistSwap(schedulerPm.Module, targetSlot)) return;
- if (CheckCanPickWaferFromPM(schedulerPm.Module, targetSlot) &&
- GetWaferTemperatureSetInRecipe(schedulerPm.Module, targetSlot, ModuleName.PMB, out double temp1, out double temp2))
- {
- Hand pickBlade;
- if ((blade1EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item1)) ||
- (blade1EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item2)))
- {
- pickBlade = Hand.Blade1;
- }
- else if ((blade2EmptyAndEnable && _tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item2)) ||
- (blade2EmptyAndEnable && !_tmRobot.CheckWaferNextStepIsThisModuleSlot(schedulerPm.Module, targetSlot, targetSlotAndHandSlots[targetSlot].Item1)))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (schedulerPm.IsReadyForPick(ModuleName.TMRobot, pickBlade, targetSlot))
- {
- if (!SC.IsDoubleFork && _tmRobot.Pick(schedulerPm.Module, new int[] { targetSlot }, pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, new int[] { targetSlot }).Item1, temp1, temp2, true))
- {
- ResetPmSwapWaitTimeOut(schedulerPm.Module);
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- canPickSlotAndHand[targetSlot] = new Tuple<Hand, double, double>(pickBlade, temp1, temp2);
- }
- }
- }
- if (canPickSlotAndHand.Count > 0)
- {
- if (!SC.IsDoubleFork && canPickSlotAndHand.Count > 1) canPickSlotAndHand.Remove(1);
- var firstSlot = canPickSlotAndHand.Keys.First();
- var pickBlade = canPickSlotAndHand[firstSlot].Item1;
- var temp1 = canPickSlotAndHand[firstSlot].Item2;
- var temp2 = canPickSlotAndHand[firstSlot].Item3;
- if (_tmRobot.Pick(schedulerPm.Module, canPickSlotAndHand.Keys.ToArray(), pickBlade, Converter.GetPanAndSlotFromPick(pickBlade, canPickSlotAndHand.Keys.ToArray()).Item1, temp1, temp2, true))
- {
- ResetPmSwapWaitTimeOut(schedulerPm.Module);
- schedulerPm.WaitTransfer(ModuleName.TMRobot);
- return;
- }
- }
- }
- }
- }
- static readonly List<string> llNameList = new List<string>()
- { "IsAvailable", "Task", "IsOnline", "IsError" , "IsIdle", "IsBusy", "IsPrepareTransfer", "IsCooling", "IsAtm", "IsVacuum", "Cooling", "WaitTransfer"
- , "Wafer0", "Wafer1", "Wafer2", "Wafer3", "Wafer4", "Wafer5"
- , "NextStep0", "NextStep1", "NextStep2", "NextStep3", "NextStep4", "NextStep5"
- , "need0", "need1", "need2", "need3", "need4", "need5"};
- static readonly List<string> efemNameList = new List<string>()
- { "IsAvailable","IsOnline","IsReady","Task","IsError"," WaitTransfer"
- , "Wafer0", "Wafer1", "Wafer2"
- , "NextStep0", "NextStep1", "NextStep2"
- , "need0", "need1", "need2"};
- static readonly List<string> tmRobotNameList = new List<string>()
- { "IsAvailable","IsOnline","IsError","Task","IsError"," WaitTransfer"
- , "Wafer0", "Wafer1", "Wafer2", "Wafer3"
- , "NextStep0", "NextStep1", "NextStep2", "NextStep3"
- , "need0", "need1", "need2", "need3"};
- static readonly List<string> pmNameList = new List<string>()
- { "IsAvailable","IsOnline","IsError","TaskDone","IsError"," WaitTransfer"
- , "Wafer0", "Wafer1", "Wafer2", "Wafer3"
- , "NextStep0", "NextStep1", "NextStep2", "NextStep3"
- , "need0", "need1", "need2", "need3"};
- static readonly List<string> lpNameList = new List<string>()
- { "IsAvailable","Task","IsOnline","IsError","IsReady"};
- private int _GetWaferNextStepId(ModuleName module, int slotId)
- {
- if (!WaferManager.Instance.IsWaferSlotLocationValid(module, slotId)) return -1;
- var wafer = WaferManager.Instance.GetWafer(module, slotId);
- return wafer.NextSequenceStep;
- }
- private string _GetWaferOrigin(ModuleName module, int slotId)
- {
- if (!WaferManager.Instance.IsWaferSlotLocationValid(module, slotId)) return "";
- var wafer = WaferManager.Instance.GetWafer(module, slotId);
- return wafer.WaferOrigin;
- }
- private bool GetWaferProcessAccess(WaferInfo wafer)
- {
- if (wafer.ProcessJob == null || string.IsNullOrEmpty(wafer.ProcessJob.Name))
- return false;
- return GetPMOccupiedCount(wafer.ProcessJob.Name) > GetWaitingProcessWaferCount(wafer.ProcessJob.Name);
- }
- private int GetPMOccupiedCount(string pjName)
- {
- List<ModuleName> location = new List<ModuleName>();
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.Name != pjName)
- continue;
- if (pj.State != EnumProcessJobState.Processing)
- continue;
- foreach (var step in pj.Sequence.Steps)
- {
- foreach (var module in step.StepModules)
- {
- if (ModuleHelper.IsPm(module) && !location.Exists(x => x == module))
- location.Add(module);
- }
- }
- }
- return location.Count;
- }
- private int GetWaitingProcessWaferCount(string pjName)
- {
- List<Tuple<ModuleName, int>> location = new List<Tuple<ModuleName, int>>()
- {
- Tuple.Create(ModuleName.TMRobot, 0),
- Tuple.Create(ModuleName.TMRobot, 1),
- Tuple.Create(ModuleName.LLA, 0),
- Tuple.Create(ModuleName.LLB, 0),
- Tuple.Create(ModuleName.Aligner1, 0),
- Tuple.Create(ModuleName.Aligner2, 0),
- Tuple.Create(ModuleName.Cooling1, 0),
- Tuple.Create(ModuleName.Cooling2, 0),
- Tuple.Create(ModuleName.PMA, 0),
- Tuple.Create(ModuleName.PMB, 0),
- //Tuple.Create(ModuleName.PMC, 0),
- };
- location.Where(p => p.Item1 != ModuleName.EfemRobot && p.Item1 != ModuleName.TMRobot && !SC.GetValueOrDefault<bool>($"System.SetUp.{p.Item1.ToString()}.IsInstalled"))
- .ToList().ForEach(p => location.Remove(p));
- int count = 0;
- foreach (var tuple in location)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(tuple.Item1, tuple.Item2);
- if (wafer.IsEmpty)
- continue;
- if (wafer.ProcessJob != null && wafer.ProcessJob.Name == pjName)
- count++;
- }
- return count;
- }
- Dictionary<string, Dictionary<string, List<object>>> _ValueDict = new Dictionary<string, Dictionary<string, List<object>>>();
- //private void PrintVariables(string key, List<string> names, params object[] values)
- //{
- // StackTrace trace = new StackTrace(true);
- // var frames = trace.GetFrames();//1代表上级,2代表上上级,以此类推
- // if (frames.Length < 2) return;
- // var frame1 = frames[1];
- // var method1 = frame1.GetMethod();
- // if (method1 == null) return;
- // string methodName = method1.Name;
- // var newList = values.ToList();
- // if (!_ValueDict.ContainsKey(methodName))
- // {
- // _ValueDict[methodName] = new Dictionary<string, List<object>>() { { key, newList } };
- // LOG.Debug($"{methodName} Key={key} Values({_ToString(names, newList)})");
- // }
- // else
- // {
- // var dict = _ValueDict[methodName];
- // if (dict.ContainsKey(key))
- // {
- // var list = dict[key];
- // StringBuilder builder = new StringBuilder();
- // for (int ii = 0; ii < names.Count; ii++)
- // {
- // if (list[ii].Equals(newList[ii])) continue;
- // builder.Append($",{names[ii]}({list[ii]} --> {newList[ii]})");
- // list[ii] = newList[ii];
- // }
- // if (builder.Length > 0)
- // {
- // LOG.Debug($"{methodName} Key={key} {builder.ToString()}");
- // }
- // }
- // else
- // {
- // _ValueDict[methodName].Add(key, newList);
- // LOG.Debug($"{methodName} Key={key} Values({_ToString(names, newList)})");
- // }
- // }
- //}
- private string _ToString(List<string> names, List<object> objList)
- {
- StringBuilder builder = new StringBuilder();
- for (int ii = 0; ii < names.Count; ii++)
- {
- builder.Append($",{names[ii]}={objList[ii]}");
- }
- return builder.ToString().Trim(',');
- }
- #region EfemRobotTask
- private void MonitorEfemRobotMapTask()
- {
- if (!_efem.IsAvailable)
- return;
- if (_mapTarget.Count > 0)
- {
- ModuleName first = _mapTarget[0];
- foreach (var cj in _lstControlJobs)
- {
- if (cj.Module != first.ToString())
- continue;
- if (cj.State == EnumControlJobState.Executing || cj.State == EnumControlJobState.Paused)
- {
- EV.PostWarningLog("System", $"{first} is running, can not map again");
- _mapTarget.Remove(first);
- return;
- }
- }
- SchedulerLoadPort lp = GetModule(first.ToString()) as SchedulerLoadPort;
- if (lp != null && lp.IsAvailable)
- {
- _efem.Map(first);
- _mapTarget.Remove(first);
- }
- }
- }
- private void MonitorEfemRobotTask()
- {
- if (_efem.FirstDetectWaferArrive(0) && _efem.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, 0))
- GetModule(_efem.Module).GetWaferInfo(0).NextSequenceStep++;
- if (_efem.FirstDetectWaferArrive(1) && _efem.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, 1))
- GetModule(_efem.Module).GetWaferInfo(1).NextSequenceStep++;
- if (!_efem.IsAvailable)
- return;
- ////efem robot is idle, release all the target
- foreach (var ll in _lstLls)
- {
- if (ll.IsWaitTransfer(ModuleName.EfemRobot))
- ll.StopWaitTransfer(ModuleName.EfemRobot);
- }
- foreach (var al in _lstAligners)
- {
- if (al.IsWaitTransfer(ModuleName.EfemRobot))
- al.StopWaitTransfer(ModuleName.EfemRobot);
- }
- foreach (var bf in _lstCoolings)
- {
- if (bf.IsWaitTransfer(ModuleName.EfemRobot))
- bf.StopWaitTransfer(ModuleName.EfemRobot);
- }
- foreach (var lp in _lstLps)
- {
- if (lp.IsWaitTransfer(ModuleName.EfemRobot))
- lp.StopWaitTransfer(ModuleName.EfemRobot);
- }
- if (!_efem.IsAvailable)
- return;
- var act = efemRobotActions.Peek();
- act.Invoke();
- if (!_efem.IsAvailable)
- return;
- efemRobotActions.Enqueue(efemRobotActions.Dequeue());
- //if (!_efem.IsAvailable)
- // return;
- //MonitorEfemRobotAlignerTask();
- //if (!_efem.IsAvailable)
- // return;
- //MonitorEfemRobotLoadLockTask();
- //if (_aligner.HasWafer(0) && (!_efem.Blade1Enable || !_efem.Blade2Enable))
- // return;
- //if (_aligner.HasWafer(0) && (_efem.HasWafer(0) || _efem.HasWafer(1)))
- // return;
- //if (!_efem.IsAvailable)
- // return;
- //MonitorEfemRobotLoadPortTask();
- //MonitorEfemRobotGoToTask();
- }
- private void MonitorEfemRobotLoadPortPickTask()
- {
- if (!_efem.IsAvailable)
- return;
- if ((_aligner1.HasWafer(0) || _aligner2.HasWafer(0)) && (!_efem.Blade1Enable || !_efem.Blade2Enable))
- return;
- int waferCount = 0;
- if (_aligner1.HasWafer(0)) waferCount++;
- if (_aligner2.HasWafer(0)) waferCount++;
- if (_efem.HasWafer(0)) waferCount++;
- if (_efem.HasWafer(1)) waferCount++;
- if (waferCount >= 2)
- return;
- if (_lstLls.Any(x => GetEmptySlotInLoadLock(x) < 4) ||
- _lstLls.Any(x => GetNoNeedProcessInLoadLock(x) >= 4))
- return;
- //pick
- bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0);
- bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1);
- if (GetWaferCountInJobQueue() > 0 && (blade1EmptyAndEnable || blade2EmptyAndEnable) && EfemRobotPickAllowable)
- {
- SlotItem position = GetWaferInJobQueue();
- if (position != null && (SC.IsATMMode || CheckWaferPmTemperatureIsOk(position.Module, position.Slot)))
- {
- SchedulerLoadPort lp = GetModule(position.Module.ToString()) as SchedulerLoadPort;
- Hand pickBlade;
- if (blade1EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1))
- {
- pickBlade = Hand.Blade2;
- }
- else if (blade1EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 1))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(position.Module, position.Slot, 0))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (lp != null && lp.IsReadyForPick(ModuleName.EfemRobot, pickBlade, position.Slot))
- {
- //WaferManager.Instance.GetWafer(position.Module, position.Slot).NextSequenceStep++;
- if (GetModule(position.Module.ToString()).CheckWaferNextStepModuleNoWafer(position.Slot))
- {
- ProcessJobInfo pj = lp.GetWaferInfo(position.Slot).ProcessJob;
- _faCallback.JobWaferStart(pj, position.Module.ToString(), position.Slot);
- if (_efem.Pick(position.Module, position.Slot, pickBlade))
- {
- lp.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- }
- }
- }
- private bool CheckWaferPmTemperatureIsOk(ModuleName waferModule, int waferSlot)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty || wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- var seq = wafer.ProcessJob.Sequence;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- bool stepOk = false;
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- var realmodule = module.ToString();
- string recipeName = realmodule + "Recipe";
- LoadRecipe(realmodule, seq.Steps[i].StepParameter[recipeName].ToString(), out double chambertemp1, out double chambertemp2);
- if ((GetModule(realmodule.ToString()) as SchedulerPM).CheckTransferTempReady(chambertemp1, chambertemp2))
- {
- stepOk = true;
- break;
- }
- }
- else
- {
- stepOk = true;
- }
- }
- if (!stepOk)
- return false;
- }
- return true;
- }
- private void MonitorEfemRobotLoadPortPlaceTask()
- {
- if (!_efem.IsAvailable)
- return;
- //place
- bool blade0HasWaferAndProcessed = _efem.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
- !CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && !CheckWaferNextStepIsCooling(ModuleName.EfemRobot, 0);
- bool blade1HasWaferAndProcessed = _efem.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) &&
- !CheckWaferNeedProcess(ModuleName.EfemRobot, 1) && !CheckWaferNextStepIsCooling(ModuleName.EfemRobot, 1);
- if (blade0HasWaferAndProcessed || blade1HasWaferAndProcessed)
- {
- Hand placeBlade = blade0HasWaferAndProcessed ? Hand.Blade1 : Hand.Blade2;
- if (blade0HasWaferAndProcessed && blade1HasWaferAndProcessed)
- {
- if (WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginSlot <
- WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginSlot)
- {
- placeBlade = Hand.Blade2;
- }
- }
- SlotItem destination = GetWaferReturnLoadPort(ModuleName.EfemRobot, (int)placeBlade);
- if (destination != null && ModuleHelper.IsLoadPort(destination.Module))
- {
- SchedulerLoadPort lp = (SchedulerLoadPort)GetModule(destination.Module.ToString());
- if (lp.IsReadyForPlace(ModuleName.EfemRobot, placeBlade, destination.Slot))
- {
- if (_efem.Place(destination.Module, destination.Slot, placeBlade))
- {
- lp.WaitTransfer(ModuleName.EfemRobot);
- if (_CycleData.IsCycleMode)
- _CycleData.IncreaseWaferCount(lp.Module, 1);
- //_cycledTotalWafer++;
- //if (SC.ContainsItem("System.TotalCycledWafer"))
- // SC.SetItemValue("System.TotalCycledWafer", _cycledTotalWafer);
- return;
- }
- }
- }
- }
- }
- private void MonitorEfemRobotLoadLockPickTask()
- {
- if (!_efem.IsAvailable)
- return;
- if ((_cooling1.HasWafer(0) || _cooling2.HasWafer(0)) && (!_efem.Blade1Enable || !_efem.Blade2Enable))
- return;
- int waferCount = 0;
- if (_cooling1.HasWafer(0)) waferCount++;
- if (_cooling2.HasWafer(0)) waferCount++;
- if (_efem.HasWafer(0)) waferCount++;
- if (_efem.HasWafer(1)) waferCount++;
- if (waferCount >= 2)
- return;
- bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0);
- bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1);
- if (!blade1EmptyAndEnable && !blade2EmptyAndEnable) return;
- if ((CheckWaferNeedProcess(ModuleName.EfemRobot, 0) || CheckWaferNeedProcess(ModuleName.EfemRobot, 1)))
- {
- var wafers = WaferManager.Instance.GetWafers(ModuleName.EfemRobot).Where(p=>!p.IsEmpty).ToList();
- if(wafers.Any(p=> p.ProcessJob.Sequence.Steps[p.NextSequenceStep].StepModules.Any(m=>ModuleHelper.IsLoadLock(m) && GetEmptySlotInLoadLock(_lstLls.FirstOrDefault(t=>t.Module==m)) > 4)))
- return;
- }
-
- //List<WaferInfo> canPickWafers = new List<WaferInfo>();
- WaferInfo canPickWafers = null;
- SchedulerLoadLock selectLL = null;
- foreach (var ll in _lstLls)
- {
- var llWafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < llWafers.Length; i++)
- {
- if (!CheckWaferNeedProcess(ll.Module, i) &&
- ll.IsReadyForPick(ModuleName.EfemRobot, Hand.Blade1, i))
- {
- if (canPickWafers == null || (canPickWafers != null && canPickWafers.OriginSlot > llWafers[i].OriginSlot))
- {
- canPickWafers = llWafers[i];
- selectLL = ll;
- }
- }
- }
- }
- if (canPickWafers == null || selectLL == null || !selectLL.IsAvailable)
- return;
- if (canPickWafers != null && selectLL != null)
- {
- Hand pickBlade;
- if ((blade1EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(selectLL.Module, canPickWafers.Slot, 0)) ||
- (blade1EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(selectLL.Module, canPickWafers.Slot, 1)))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(selectLL.Module, canPickWafers.Slot, 1) ||
- (blade2EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(selectLL.Module, canPickWafers.Slot, 0)))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (selectLL.IsReadyForPick(ModuleName.EfemRobot, pickBlade, canPickWafers.Slot))
- {
- if (_efem.Pick(selectLL.Module, canPickWafers.Slot, pickBlade))
- {
- selectLL.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- if (!_efem.IsAvailable)
- return;
- }
- private void MonitorEfemRobotLoadLockPlaceTask()
- {
- if (!_efem.IsAvailable)
- return;
- //place
- foreach (var ll in _lstLls)
- {
- if (!ll.IsAvailable)
- continue;
- bool blade1NeedPlace = _efem.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedProcess(ModuleName.EfemRobot, 0) && !CheckWaferNextStepIsAlign(ModuleName.EfemRobot, 0);
- bool blade2NeedPlace = _efem.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedProcess(ModuleName.EfemRobot, 1) && !CheckWaferNextStepIsAlign(ModuleName.EfemRobot, 1);
- if (!blade1NeedPlace && !blade2NeedPlace)
- {
- EfemRobotPickAllowable = true;
- }
- else
- {
- EfemRobotPickAllowable = false;
- }
- if (blade1NeedPlace || blade2NeedPlace)
- {
- Hand placeBlade = blade1NeedPlace ? Hand.Blade1 : Hand.Blade2;
- if (!CheckWaferNextStepIsLoadLock(ModuleName.EfemRobot, (int)placeBlade, ll.Module))
- continue;
- int placeSlot = Int32.MaxValue;
- if (blade1NeedPlace || blade2NeedPlace)
- {
- if (SC.IsDoubleFork && !TryFindNeedPairLoadLock(ModuleName.EfemRobot, placeBlade, ll)) continue;
- for (int i = 0; i < 6; i++)
- {
- if (ll.IsReadyForPlace(ModuleName.EfemRobot, placeBlade, i, true))
- {
- placeSlot = i;
- break;
- }
- }
- }
- if (placeSlot != Int32.MaxValue)
- {
- if (_efem.Place(ll.Module, (int)placeSlot, placeBlade))
- {
- WaferManager.Instance.GetWafer(ModuleName.EfemRobot, (int)placeBlade).NextSequenceStep++;
- ll.WaitTransfer(ModuleName.EfemRobot, (int)placeSlot);
- return;
- }
- }
- }
- }
- }
- private void MonitorEfemRobotAlignerPickTask()
- {
- if (!_efem.IsAvailable)
- return;
- //pick from aligner
- bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0);
- bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1);
- if (blade1EmptyAndEnable || blade2EmptyAndEnable)
- {
- foreach (var aligner in GetWaferOrderInJobQueue(_lstAligners))
- {
- if (!_efem.IsAvailable)
- return;
- if (!aligner.IsAvailable)
- continue;
- if (aligner.HasWafer(0) && !aligner.CheckWaferNextStepIsThisModule(aligner.Module, 0))
- {
- var wafer = WaferManager.Instance.GetWafer(aligner.Module, 0);
- var nextModules = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules;
- if (nextModules.Any(p => ModuleHelper.IsLoadLock(p)) && _lstLls.Where(p => nextModules.Contains(p.Module)).All(x => GetNoNeedProcessInLoadLock(x) >=4))
- continue;
- if ((_efem.Blade1Enable ^ _efem.Blade2Enable) && nextModules.Any(p => ModuleHelper.IsLoadLock(p)) && _lstLls.Where(p => nextModules.Contains(p.Module)).All(x => GetNoNeedProcessInLoadLock(x)>0))
- continue;
- Hand pickBlade;
- if (blade1EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(aligner.Module, 0, 0))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(aligner.Module, 0, 1))
- {
- pickBlade = Hand.Blade2;
- }
- else if (blade1EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(aligner.Module, 0, 1))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(aligner.Module, 0, 0))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (aligner.IsReadyForPick(ModuleName.EfemRobot, pickBlade, 0))
- {
- if (_efem.Pick(aligner.Module, 0, pickBlade))
- {
- aligner.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- }
- }
- }
- private void MonitorEfemRobotAlignerPlaceTask()
- {
- if (!_efem.IsAvailable)
- return;
- //place to aligner
- bool blade1NeedAlign = _efem.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
- CheckWaferNextStepIsAlign(ModuleName.EfemRobot, 0);
- bool blade2NeedAlign = _efem.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) &&
- CheckWaferNextStepIsAlign(ModuleName.EfemRobot, 1);
- if (blade1NeedAlign || blade2NeedAlign)
- {
- Hand placeBlade = blade1NeedAlign ? Hand.Blade1 : Hand.Blade2;
- if (blade1NeedAlign && blade2NeedAlign &&
- WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 1).OriginSlot <
- WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).OriginSlot)
- placeBlade = Hand.Blade2;
- foreach (var aligner in _lstAligners)
- {
- if (!_efem.IsAvailable)
- return;
- if (!aligner.IsAvailable)
- continue;
- if (!aligner.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade))
- continue;
- if (aligner.IsReadyForPlace(ModuleName.EfemRobot, placeBlade, 0))
- {
- if (_efem.Place(aligner.Module, 0, placeBlade))
- {
- aligner.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- }
- }
- private void MonitorEfemRobotCoolingPickTask()
- {
- if (!_efem.IsAvailable)
- return;
- //pick from Cooling
- bool blade1EmptyAndEnable = _efem.Blade1Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0);
- bool blade2EmptyAndEnable = _efem.Blade2Enable && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1);
- if (blade1EmptyAndEnable || blade2EmptyAndEnable)
- {
- foreach (var cooling in GetWaferOrderInJobQueue(_lstCoolings))
- {
- if (!_efem.IsAvailable)
- return;
- if (!cooling.IsAvailable)
- continue;
- Hand pickBlade;
- if (blade1EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(cooling.Module, 0, 0))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && _efem.CheckWaferNextStepIsThisModuleSlot(cooling.Module, 0, 1))
- {
- pickBlade = Hand.Blade2;
- }
- else if (blade1EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(cooling.Module, 0, 1))
- {
- pickBlade = Hand.Blade1;
- }
- else if (blade2EmptyAndEnable && !_efem.CheckWaferNextStepIsThisModuleSlot(cooling.Module, 0, 0))
- {
- pickBlade = Hand.Blade2;
- }
- else
- {
- return;
- }
- if (cooling.HasWafer(0) && !cooling.CheckWaferNextStepIsThisModule(cooling.Module, 0))
- {
- if (cooling.IsReadyForPick(ModuleName.EfemRobot, pickBlade, 0))
- {
- if (_efem.Pick(cooling.Module, 0, pickBlade))
- {
- cooling.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- }
- }
- }
- private void MonitorEfemRobotCoolingPlaceTask()
- {
- if (!_efem.IsAvailable)
- return;
- //place to aligner
- bool blade1NeedCooling = _efem.Blade1Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) &&
- CheckWaferNextStepIsCooling(ModuleName.EfemRobot, 0);
- bool blade2NeedCooling = _efem.Blade2Enable && WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) &&
- CheckWaferNextStepIsCooling(ModuleName.EfemRobot, 1);
- if (blade1NeedCooling || blade2NeedCooling)
- {
- Hand placeBlade = blade1NeedCooling ? Hand.Blade1 : Hand.Blade2;
- foreach (var cooling in _lstCoolings)
- {
- if (!_efem.IsAvailable)
- return;
- if (!cooling.IsAvailable)
- continue;
- if (!cooling.CheckWaferNextStepIsThisModule(ModuleName.EfemRobot, (int)placeBlade))
- continue;
- if (cooling.IsReadyForPlace(ModuleName.EfemRobot, placeBlade, 0))
- {
- if (_efem.Place(cooling.Module, 0, placeBlade))
- {
- cooling.WaitTransfer(ModuleName.EfemRobot);
- return;
- }
- }
- }
- }
- }
- #endregion
- //private void MonitorEfemRobotGoToTask()
- //{
- // if (!_efem.IsAvailable)
- // return;
- // SchedulerLoadLock gotoLL = null;
- // Hand gotoBlade = Hand.Both;
- // int gotoSlot = int.MaxValue;
- // bool arm1Empty = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1);
- // bool arm2Empty = WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 2);
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsOnline)
- // continue;
- // if (!ll.Entity.IsPrepareTransfer)
- // continue;
- // if (arm1Empty && arm2Empty)
- // {
- // for (int i = 0; i <= 5; i++)
- // {
- // var wafer = WaferManager.Instance.GetWafer(ll.Module, i);
- // if (wafer != null && !wafer.IsEmpty && wafer.ProcessState == EnumWaferProcessStatus.Completed)
- // {
- // gotoLL = ll;
- // gotoBlade = Hand.Both;
- // gotoSlot = 0;
- // break;
- // }
- // }
- // }
- // else
- // {
- // if (!arm1Empty && !arm2Empty)
- // {
- // for (int i = 0; i <= 1; i++)
- // {
- // if (WaferManager.Instance.CheckNoWafer(ll.Module, i) &&
- // WaferManager.Instance.CheckNoWafer(ll.Module, i + 2) &&
- // WaferManager.Instance.CheckNoWafer(ll.Module, i + 4))
- // {
- // gotoBlade = Hand.Both;
- // gotoSlot = i;
- // gotoLL = ll;
- // break;
- // }
- // else if (WaferManager.Instance.CheckNoWafer(ll.Module, i) &&
- // WaferManager.Instance.CheckNoWafer(ll.Module, i + 2))
- // {
- // gotoBlade = Hand.Blade1;
- // gotoSlot = i;
- // gotoLL = ll;
- // break;
- // }
- // if (ll.IsReadyForPlace(ModuleName.EfemRobot, Hand.Blade2, i + 4))
- // {
- // gotoBlade = Hand.Blade2;
- // gotoSlot = i + 4;
- // gotoLL = ll;
- // break;
- // }
- // }
- // }
- // else if (!arm1Empty)
- // {
- // for (int i = 0; i <= 1; i++)
- // {
- // if (WaferManager.Instance.CheckNoWafer(ll.Module, i) &&
- // WaferManager.Instance.CheckNoWafer(ll.Module, i + 2) &&
- // WaferManager.Instance.CheckNoWafer(ll.Module, i + 4))
- // {
- // gotoBlade = Hand.Both;
- // gotoSlot = i;
- // gotoLL = ll;
- // break;
- // }
- // }
- // }
- // else
- // {
- // for (int i = 0; i <= 1; i++)
- // {
- // if (ll.IsReadyForPlace(ModuleName.EfemRobot, Hand.Blade2, i + 4))
- // {
- // gotoBlade = Hand.Blade2;
- // gotoSlot = i + 4;
- // gotoLL = ll;
- // break;
- // }
- // }
- // if (gotoSlot == Int32.MaxValue)
- // {
- // for (int i = 0; i <= 5; i++)
- // {
- // if (ll.IsReadyForPlace(ModuleName.EfemRobot, Hand.Blade2, i))
- // {
- // gotoBlade = Hand.Blade2;
- // gotoSlot = i + 4;
- // gotoLL = ll;
- // break;
- // }
- // }
- // }
- // }
- // }
- // if (gotoLL != null && gotoSlot != int.MaxValue)
- // break;
- // }
- // if (gotoLL != null && gotoSlot != int.MaxValue)
- // {
- // if (_efem.PreviousTarget == gotoLL.Module)
- // return;
- // if (_efem.Goto(gotoLL.Module, gotoSlot, gotoBlade))
- // {
- // gotoLL.WaitTransfer(ModuleName.EfemRobot);
- // return;
- // }
- // }
- //}
- private SlotItem GetNextWaferInJobQueue(ModuleName lpModule, ModuleName pmModule)
- {
- if (!_isRunningInParallelMode)
- {
- foreach (var cj in _lstControlJobs)
- {
- if (lpModule != ModuleName.System && (cj.Module != lpModule.ToString()))
- continue;
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2, pmModule))
- return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- }
- }
- }
- }
- }
- return null;
- }
- //parallel mode
- Dictionary<string, SlotItem> pjWafer = new Dictionary<string, SlotItem>();
- Dictionary<string, List<ModuleName>> pmUsed = new Dictionary<string, List<ModuleName>>();
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State != EnumControlJobState.Executing)
- continue;
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (CheckWaferNeedProcessAndPMAvailable(pjSlotWafer.Item1, pjSlotWafer.Item2))
- {
- pjWafer[pj.Name] = new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- break;
- }
- }
- }
- }
- }
- if (pjWafer.Count == 0)
- return null;
- if (pjWafer.Count == 1)
- return pjWafer.Values.First();
- string preferPj = pjWafer.Keys.First();
- int runningWaferCount = GetWaitingProcessWaferCount(preferPj);
- foreach (var slotItem in pjWafer)
- {
- if (slotItem.Key == preferPj)
- continue;
- int count = GetWaitingProcessWaferCount(slotItem.Key);
- if (count <= runningWaferCount)
- {
- preferPj = slotItem.Key;
- runningWaferCount = count;
- }
- }
- return pjWafer[preferPj];
- }
- public bool CheckWaferNeedProcessAndPMAvailable(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty)
- return false;
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Any(p => ModuleHelper.IsPm(p)))
- {
- var hasPmAvailable = false;
- foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
- {
- SchedulerPM pm = _lstPms.FirstOrDefault(p=>p.Module == stepModule);
-
- if (pm != null)
- {
- if (pm.IsAvailable || (pm.IsOnline && pm.Task != SchedulerModule.TaskType.PreJobProcess))
- {
- hasPmAvailable = true;
- break;
- }
- }
- }
- if (!hasPmAvailable)
- return false;
- if (processIn == ModuleName.System)
- return true;
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules
- .Contains(processIn))
- return true;
- }
- }
- return false;
- }
- public bool LoadRecipe(string module, string CurrentRecipeBaseName, out double temp1, out double temp2)
- {
- var CurrentRecipeContent = RecipeFileManager.Instance.LoadRecipe("", CurrentRecipeBaseName, true);
- temp1 = 0;
- temp2 = 0;
- if (string.IsNullOrEmpty(CurrentRecipeContent))
- {
- EV.PostInfoLog(ModuleName.System.ToString(), $"error during read recipe file {CurrentRecipeBaseName}");
- return false;
- }
- if (!Recipe.Parse(module, CurrentRecipeContent, out RecipeHead recipeHead, out var recipeSteps))
- {
- return false;
- }
- temp1 = GetChamber1Temp(recipeHead);
- temp2 = GetChamber2Temp(recipeHead);
- return true;
- }
- public double GetChamber1Temp(RecipeHead CurrentRecipeHead)
- {
- if (CurrentRecipeHead != null)
- {
- if (!string.IsNullOrEmpty(CurrentRecipeHead.Chamber1Temperature))
- {
- double setpoint = Convert.ToDouble(CurrentRecipeHead.Chamber1Temperature);
- if (setpoint > 0 && setpoint < 600)
- return setpoint;
- }
- }
- return 0;
- }
- public double GetChamber2Temp(RecipeHead CurrentRecipeHead)
- {
- if (CurrentRecipeHead != null)
- {
- if (!string.IsNullOrEmpty(CurrentRecipeHead.Chamber2Temperature))
- {
- double setpoint = Convert.ToDouble(CurrentRecipeHead.Chamber2Temperature);
- if (setpoint > 0 && setpoint < 600)
- return setpoint;
- }
- }
- return 0;
- }
- private bool GetWaferTemperatureSetInRecipe(ModuleName waferModule, int waferSlot, ModuleName pmModule, out double temp1, out double temp2)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if(!wafer.IsEmpty && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && ModuleHelper.IsPm(pmModule))
- {
- var seq = wafer.ProcessJob.Sequence;
- string recipeName = pmModule.ToString() + "Recipe";
- SequenceStepInfo stepInfo = seq.Steps.FirstOrDefault(p=>p.StepModules.Contains(pmModule));
- if (stepInfo != null && stepInfo.StepParameter != null && stepInfo.StepParameter.ContainsKey(recipeName))
- {
- LoadRecipe(pmModule.ToString(), stepInfo.StepParameter[recipeName].ToString(), out double chambertemp1, out double chambertemp2);
- temp1 = chambertemp1;
- temp2 = chambertemp2;
- return true;
- }
- }
- temp1 = 0;
- temp2 = 0;
- LOG.Error($"Can not find wafer {waferModule} {waferSlot + 1} temperature set in recipe");
- return false;
- }
- #endregion
- #region Logic Check
- private bool CheckLoadLockAvaiableForTMRobot()
- {
- bool isPrepareTransferForTMobot = GetVacuumWafer() == 0;
- foreach (var ll in _lstLls)
- {
- if (!ll.IsAvailable)
- continue;
- var deviceLL = DEVICE.GetDevice<LoadLock>(ll.Module.ToString());
- var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- for (int i = 0; i <= 5;)
- {
- var wafer0 = WaferManager.Instance.GetWafer(ll.Module, i);
- var wafer1 = WaferManager.Instance.GetWafer(ll.Module, i + 1);
- if ((!wafer0.IsEmpty && wafer0.ProcessState == EnumWaferProcessStatus.Idle) ||
- (!wafer1.IsEmpty && wafer1.ProcessState == EnumWaferProcessStatus.Idle))
- {
- isPrepareTransferForTMobot = true;
- break;
- }
- i += 2;
- }
- }
- return isPrepareTransferForTMobot;
- }
- //private bool CheckPMTemperature(string module)
- //{
- // var pmDevice = DEVICE.GetDevice<SpinelPM>(module);
- // if (pmDevice != null && _temperatureSetpointDic.ContainsKey(module) && _temperatureSetpointDic[module] > 0)
- // {
- // if (!pmDevice.CheckHeater1Temperature(_temperatureSetpointDic[module]) ||
- // !pmDevice.CheckHeater2Temperature(_temperatureSetpointDic[module]))
- // {
- // if (!_temperatureTrigDic.ContainsKey(module))
- // _temperatureTrigDic.Add(module, new R_TRIG());
- // _temperatureTrigDic[module].CLK = true;
- // if (_temperatureTrigDic[module].Q)
- // {
- // EV.PostWarningLog("Scheduler", $"{module} heater temperature is not in the scope");
- // }
- // pmDevice.SetHeater1(_temperatureSetpointDic[module]);
- // pmDevice.SetHeater2(_temperatureSetpointDic[module]);
- // }
- // if (pmDevice.CheckHeater1Temperature(_temperatureSetpointDic[module]) &&
- // pmDevice.CheckHeater2Temperature(_temperatureSetpointDic[module]))
- // {
- // return true;
- // }
- // }
- // else
- // return true;
- // return false;
- //}
- private bool CheckWaferNextProcessIsPM(ModuleName waferModule, int waferSlot)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty)
- return false;
- if (wafer.ProcessJob == null ||
- wafer.ProcessJob.Sequence == null ||
- wafer.ProcessJob.Sequence.Steps == null ||
- wafer.ProcessJob.Sequence.Steps.Count <= wafer.NextSequenceStep ||
- wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep] == null ||
- wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- {
- return false;
- }
- return wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Any(x => ModuleHelper.IsPm(x));
- }
- private bool CheckWaferNextProcessIsPMAvaiable(ModuleName waferModule, int waferSlot)
- {
- if (!CheckWaferNextProcessIsPM(waferModule, waferSlot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules)
- {
- if (_lstPms.Any(pm => pm.Module == stepModule && pm.IsAvailable && WaferManager.Instance.CheckNoWafer(pm.Module, waferSlot)))
- {
- return true;
- }
- }
- return false;
- }
- private bool CheckNeedRunClean(ModuleName module, out bool withWafer, out string recipeName)
- {
- recipeName = string.Empty;
- withWafer = false;
- return false;
- SequenceInfo seq = GetCurrentSequenceInfo();
- int waferProcessed = StatsDataManager.Instance.GetValue($"{module}.WaferProcessedSincePreviousClean");
- if (seq == null)
- return false;
- foreach (var stepInfo in seq.Steps)
- {
- if (!stepInfo.StepModules.Contains(module))
- continue;
- if (stepInfo.StepParameter.ContainsKey("CleanRecipeNoWafer")
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter["CleanRecipeNoWafer"]))
- {
- if (stepInfo.CleanInterval > 0 && waferProcessed >= stepInfo.CleanInterval)
- {
- recipeName = (string)stepInfo.StepParameter["CleanRecipeNoWafer"];
- withWafer = false;
- return true;
- }
- }
- if (stepInfo.StepParameter.ContainsKey("CleanRecipeWafer")
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter["CleanRecipeWafer"]))
- {
- if (stepInfo.CleanInterval > 0 && waferProcessed >= stepInfo.CleanInterval)
- {
- recipeName = (string)stepInfo.StepParameter["CleanRecipeWafer"];
- withWafer = true;
- return true;
- }
- }
- }
- return false;
- }
- //private bool CheckVacuumWaferHasAvailableTarget(ModuleName waferModule, int waferSlot, ModuleName chamberSwappable)
- //{
- // WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- // //System.Diagnostics.Trace.Assert(!wafer.IsEmpty);
- // if (CheckWaferNeedProcess(waferModule, waferSlot))
- // {
- // // Check for an empty PM
- // foreach (var pm in _lstPms)
- // {
- // if (WaferManager.Instance.CheckNoWafer(pm.Module, 0) || pm.Module == chamberSwappable)
- // {
- // if (pm.IsAvailable == false)
- // continue;
- // if (!CheckWaferNextProcessIn(waferModule, waferSlot, pm.Module))
- // continue;
- // return true;
- // }
- // }
- // }
- // else
- // {
- // // No more processing needed, check for a outbound loadlock slot
- // return true;
- // }
- // return false;
- //}
- //private bool CheckWaferNextProcessIn(ModuleName waferModule, int waferSlot, ModuleName chamber)
- //{
- // WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- // if (wafer.ProcessJob == null ||
- // wafer.ProcessJob.Sequence == null ||
- // wafer.ProcessJob.Sequence.Steps == null ||
- // wafer.ProcessJob.Sequence.Steps.Count <= wafer.NextSequenceStep ||
- // wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep] == null ||
- // wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- // {
- // return false;
- // }
- // return wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(chamber);
- //}
- private SequenceInfo GetCurrentSequenceInfo()
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.State == EnumProcessJobState.Processing)
- {
- return pj.Sequence;
- }
- }
- return null;
- }
- private bool GetWaferSequenceAlignAngle(ModuleName module, int slot, out double angle)
- {
- angle = 0;
- if (!WaferManager.Instance.CheckHasWafer(module, slot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner))
- return false;
- angle = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].AlignAngle;
- return true;
- }
- private bool GetWaferSequenceCoolingTime(ModuleName module, int slot, out int coolingTime)
- {
- coolingTime = 0;
- if (!WaferManager.Instance.CheckHasWafer(module, slot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(module))
- return false;
- if (!int.TryParse(wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepParameter["CoolingTime"].ToString(),
- out coolingTime))
- {
- coolingTime = SC.GetValueOrDefault<int>("System.DefaultCoolingTime");
- EV.PostWarningLog("Scheduler", $"Sequence step LL cooling time is not valid, instead with the SC default value {coolingTime} seconds");
- return false;
- }
- return true;
- }
- private bool CheckWaferNextStepIsLoadLock(ModuleName module, int slot, ModuleName LL = ModuleName.System)
- {
- if (!WaferManager.Instance.CheckHasWafer(module, slot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- if (LL != ModuleName.System && !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(LL))
- return false;
- if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.LLA) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.LLB))
- return false;
- return true;
- }
- private bool CheckWaferNextStepIsAlign(ModuleName module, int slot)
- {
- if (!WaferManager.Instance.CheckHasWafer(module, slot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.AlignerA) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.AlignerB) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner1) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Aligner2))
- return false;
- return true;
- }
- private bool CheckWaferNextStepIsCooling(ModuleName module, int slot)
- {
- if (!WaferManager.Instance.CheckHasWafer(module, slot))
- return false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- if (!wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling1) &&
- !wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules.Contains(ModuleName.Cooling2))
- return false;
- return true;
- }
- public bool CheckWaferNeedProcess(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty)
- return false;
- if (wafer.Status == WaferStatus.Dummy && wafer.ProcessState == EnumWaferProcessStatus.Wait)
- {
- if (ModuleHelper.IsPm(processIn))
- {
- return (CheckNeedRunClean(processIn, out bool withWafer, out _) && withWafer);
- }
- return true;
- }
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- return false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (processIn != ModuleName.System && wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(processIn))
- {
- return true;
- }
- }
- bool hasPm = false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
- {
- if (ModuleHelper.IsPm(stepModule))
- {
- hasPm = true;
- break;
- }
- }
- if (hasPm)
- break;
- }
- if (processIn == ModuleName.System && hasPm)
- return true;
- return false;
- }
- public bool CheckWaferNeedProcessPre(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty)
- return false;
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- return false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Any(p => ModuleHelper.IsPm(p)))
- {
- if (processIn == ModuleName.System)
- return true;
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(processIn))
- {
- return true;
- }
- }
- }
- return false;
- }
- public bool CheckWaferNeedProcessBySlot(ModuleName waferModule, int waferSlot, ModuleName processIn, int pmSlot)
- {
- var result = CheckWaferNeedProcess(waferModule, waferSlot, processIn);
- if (result && pmSlot >= 0)
- {
- if (ModuleHelper.IsPm(processIn))
- {
- result = false;
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(processIn)
- && wafer.ProcessJob.Sequence.Steps[i].StepParameter.ContainsKey(processIn.ToString())
- )
- {
- var slotList = wafer.ProcessJob.Sequence.Steps[i].StepParameter[processIn.ToString()];
- result = (slotList != null && slotList.ToString().IndexOf(pmSlot.ToString()) > -1);
- }
- }
- }
- }
- return result;
- }
- public bool CheckWaferNeedProcessBySlot(WaferInfo wafer, ModuleName processIn, int slot)
- {
- var result = CheckWaferNeedProcess(wafer, processIn);
- if (result && slot >= 0)
- {
- if(ModuleHelper.IsPm(processIn))
- {
- result = false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(processIn)
- && wafer.ProcessJob.Sequence.Steps[i].StepParameter.ContainsKey(processIn.ToString())
- )
- {
- var slotList = wafer.ProcessJob.Sequence.Steps[i].StepParameter[processIn.ToString()];
- result = (slotList != null && slotList.ToString().IndexOf(slot.ToString())>-1);
- }
- }
- }
- }
- return result;
- }
- public bool CheckWaferNeedProcess(WaferInfo wafer, ModuleName processIn = ModuleName.System)
- {
- if (wafer.IsEmpty)
- return false;
- if (wafer.Status == WaferStatus.Dummy && wafer.ProcessState == EnumWaferProcessStatus.Wait)
- {
- if (ModuleHelper.IsPm(processIn))
- {
- return (CheckNeedRunClean(processIn, out bool withWafer, out _) && withWafer);
- }
- return true;
- }
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- return false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- if (processIn != ModuleName.System && wafer.ProcessJob.Sequence.Steps[i].StepModules.Contains(processIn))
- {
- return true;
- }
- }
- bool hasPm = false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
- {
- if (ModuleHelper.IsPm(stepModule))
- {
- hasPm = true;
- break;
- }
- }
- if (hasPm)
- break;
- }
- if (processIn == ModuleName.System && hasPm)
- return true;
- return false;
- }
- public bool CheckWaferNeedGotoPM(ModuleName waferModule, int waferSlot, ModuleName processIn = ModuleName.System)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- if (wafer.IsEmpty)
- return false;
- if (wafer.Status == WaferStatus.Dummy && wafer.ProcessState == EnumWaferProcessStatus.Wait)
- {
- if (ModuleHelper.IsPm(processIn))
- {
- return (CheckNeedRunClean(processIn, out bool withWafer, out _) && withWafer);
- }
- return true;
- }
- if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null)
- return false;
- if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- return false;
- if (processIn != ModuleName.System && !wafer.ProcessJob.Sequence.Steps.Any(x => x.StepModules.Contains(processIn)))
- {
- return false;
- }
- bool hasPm = false;
- for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- {
- foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
- {
- if (ModuleHelper.IsPm(stepModule))
- {
- hasPm = true;
- break;
- }
- }
- if (hasPm)
- break;
- }
- if (processIn == ModuleName.System && !hasPm)
- return false;
- return true;
- }
- //public bool CheckWaferNeedGotoPM(WaferInfo wafer, ModuleName processIn = ModuleName.System)
- //{
- // if (wafer.IsEmpty)
- // return false;
- // if (wafer.Status == WaferStatus.Dummy && wafer.ProcessState == EnumWaferProcessStatus.Wait)
- // {
- // if (ModuleHelper.IsPm(processIn))
- // {
- // return (CheckNeedRunClean(processIn, out bool withWafer, out _) && withWafer);
- // }
- // return true;
- // }
- // if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null)
- // return false;
- // if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count || wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules == null)
- // return false;
- // if (processIn != ModuleName.System && !wafer.ProcessJob.Sequence.Steps.Any(x => x.StepModules.Contains(processIn)))
- // {
- // return false;
- // }
- // bool hasPm = false;
- // for (int i = wafer.NextSequenceStep; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
- // {
- // foreach (var stepModule in wafer.ProcessJob.Sequence.Steps[i].StepModules)
- // {
- // if (ModuleHelper.IsPm(stepModule))
- // {
- // hasPm = true;
- // break;
- // }
- // }
- // if (hasPm)
- // break;
- // }
- // if (processIn == ModuleName.System && !hasPm)
- // return false;
- // return true;
- //}
- //public bool CheckWaferSequenceStepDone(ModuleName waferModule, int waferSlot)
- //{
- // WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- // if (wafer.IsEmpty)
- // return false;
- // if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- // return false;
- // if (wafer.NextSequenceStep < wafer.ProcessJob.Sequence.Steps.Count)
- // return false;
- // return true;
- //}
- //public bool CheckWaferProcessModuleIsAvailable(ModuleName waferModule, int waferSlot)
- //{
- // WaferInfo wafer = WaferManager.Instance.GetWafer(waferModule, waferSlot);
- // if (wafer.IsEmpty)
- // return false;
- // if (wafer.ProcessJob == null || wafer.ProcessJob.Sequence == null)
- // return false;
- // if (wafer.NextSequenceStep >= wafer.ProcessJob.Sequence.Steps.Count)
- // return false;
- // foreach (var step in wafer.ProcessJob.Sequence.Steps)
- // {
- // foreach (var module in step.StepModules)
- // {
- // if (WaferManager.Instance.CheckNoWafer(module, 0)
- // && _lstPms.Find(x => x.Module == module).IsAvailable
- // && !CheckNeedRunClean(module, out bool _, out string _))
- // return true;
- // }
- // }
- // return false;
- //}
- //private int GetATMWafer()
- //{
- // int count = GetWaferCountInJobQueue();
- // if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0))
- // count++;
- // if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1))
- // count++;
- // if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 2))
- // count++;
- // return count;
- //}
- private int GetVacuumWafer()
- {
- int count = 0;
- foreach (var schedulerPm in _lstPms)
- {
- if (schedulerPm == null ||
- (!schedulerPm.IsOnline))
- continue;
- if (WaferManager.Instance.CheckHasWafer(schedulerPm.Module, 0) || WaferManager.Instance.CheckHasWafer(schedulerPm.Module, 1))
- count++;
- }
- if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1))
- count++;
- if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
- count++;
- return count;
- }
- //private int GetVacuumProcessedWafer()
- //{
- // int count = 0;
- // foreach (var schedulerPm in _lstPmsCurrentSequence)
- // {
- // if (schedulerPm == null)
- // continue;
- // if (WaferManager.Instance.CheckHasWafer(schedulerPm.Module, 0)
- // && schedulerPm.IsAvailable
- // && !CheckWaferNeedProcess(schedulerPm.Module, 0)
- // && !WaferManager.Instance.CheckWaferIsDummy(schedulerPm.Module, 0))
- // count++;
- // }
- // if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) && !CheckWaferNeedProcess(ModuleName.TMRobot, 0) && !WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 0))
- // count++;
- // if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) && !CheckWaferNeedProcess(ModuleName.TMRobot, 1) && !WaferManager.Instance.CheckWaferIsDummy(ModuleName.TMRobot, 1))
- // count++;
- // return count;
- //}
- //private int GetUnprocessedWafer()
- //{
- // int count = 0;
- // foreach (var cj in _lstControlJobs)
- // {
- // if (cj.State == EnumControlJobState.Executing)
- // {
- // foreach (var pj in _lstProcessJobs)
- // {
- // if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing)
- // {
- // foreach (var pjSlotWafer in pj.SlotWafers)
- // {
- // if (CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
- // count++;
- // }
- // }
- // }
- // }
- // }
- // foreach (var ll in _lstLls)
- // {
- // if (CheckWaferNeedProcess(ll.Module, 0))
- // count++;
- // if (CheckWaferNeedProcess(ll.Module, 1))
- // count++;
- // if (CheckWaferNeedProcess(ll.Module, 2))
- // count++;
- // if (CheckWaferNeedProcess(ll.Module, 3))
- // count++;
- // if (CheckWaferNeedProcess(ll.Module, 4))
- // count++;
- // if (CheckWaferNeedProcess(ll.Module, 5))
- // count++;
- // }
- // if (CheckWaferNeedProcess(ModuleName.TMRobot, 0))
- // count++;
- // if (CheckWaferNeedProcess(ModuleName.TMRobot, 1))
- // count++;
- // if (CheckWaferNeedProcess(ModuleName.TMRobot, 2))
- // count++;
- // if (CheckWaferNeedProcess(ModuleName.TMRobot, 3))
- // count++;
- // return count;
- //}
- //private int GetAvailablePmCount()
- //{
- // int count = 0;
- // foreach (var pm in _lstPms)
- // {
- // if (!pm.IsAvailable)
- // continue;
- // if (WaferManager.Instance.CheckNoWafer(pm.Module, 0))
- // count++;
- // }
- // return count;
- //}
- private SlotItem GetWaferInJobQueue()
- {
- SlotItem slotItem = null;
- bool enableParallel = SC.GetValue<bool>("System.Scheduler.IsRunInParallelMode");
- var OrderedLstCJs = _lstControlJobs.OrderBy(x => x.BeginTime);
- if (enableParallel)
- {
- var priorityFindWaferGotoPMA = GetWaferCountLoadLockToPM(ModuleName.PMA) <= GetWaferCountLoadLockToPM(ModuleName.PMB);
- var priorityFindWaferGotoPMB = GetWaferCountLoadLockToPM(ModuleName.PMA) > GetWaferCountLoadLockToPM(ModuleName.PMB);
- foreach (var cj in OrderedLstCJs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (priorityFindWaferGotoPMA)
- {
- if (CheckWaferNeedGotoPM(pjSlotWafer.Item1, pjSlotWafer.Item2, ModuleName.PMA))
- {
- return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- }
- }
- if (priorityFindWaferGotoPMB)
- {
- if (CheckWaferNeedGotoPM(pjSlotWafer.Item1, pjSlotWafer.Item2, ModuleName.PMB))
- {
- return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- }
- }
- }
- }
- }
- }
- }
- }
- if (slotItem == null)
- {
- foreach (var cj in OrderedLstCJs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
- {
- return new SlotItem(pjSlotWafer.Item1, pjSlotWafer.Item2);
- }
- }
- }
- }
- }
- }
- }
- return slotItem;
- }
- private Tuple<SchedulerLoadLock, int> GetWaferOrderInJobQueue(List<Tuple<SchedulerLoadLock, int>> llSlots)
- {
- foreach (var cj in _lstControlJobs.OrderBy(p=>p.BeginTime))
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- foreach (var slot in llSlots)
- {
- var wafer = WaferManager.Instance.GetWafer(slot.Item1.Module, slot.Item2);
- if (wafer.OriginStation == (int)pjSlotWafer.Item1 && wafer.OriginSlot == pjSlotWafer.Item2)
- return slot;
- }
- }
- }
- }
- }
- }
- return null;
- }
- //用于Aligners、Coolings排序
- private List<SchedulerAligner> GetWaferOrderInJobQueue(List<SchedulerAligner> moduleSlots)
- {
- List<SchedulerAligner> result = new List<SchedulerAligner>();
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- foreach (var moduleSlot in moduleSlots)
- {
- var wafer = WaferManager.Instance.GetWafer(moduleSlot.Module, 0);
- if (wafer.OriginStation == (int)pjSlotWafer.Item1 && wafer.OriginSlot == pjSlotWafer.Item2)
- result.Add(moduleSlot);
- }
- }
- }
- }
- }
- }
- return result;
- }
- private List<WaferInfo> SortWaferByJobQueue(List<WaferInfo> originWafers)
- {
- List<WaferInfo> result = new List<WaferInfo>();
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- foreach (var wafer in originWafers)
- {
- if (wafer.OriginStation == (int)pjSlotWafer.Item1 && wafer.OriginSlot == pjSlotWafer.Item2)
- result.Add(wafer);
- }
- }
- }
- }
- }
- }
- return result;
- }
- private bool CheckWaferInJobQueue(ModuleName module, int slot)
- {
- foreach (var cj in _lstControlJobs)
- {
- if (cj.State == EnumControlJobState.Executing)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pj.ControlJobName == cj.Name && pj.State == EnumProcessJobState.Processing&&pj.SlotWafers!=null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- if (pjSlotWafer.Item1 == module && pjSlotWafer.Item2 == slot && CheckWaferNeedProcess(pjSlotWafer.Item1, pjSlotWafer.Item2))
- {
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
- private int GetWaferCountInJobQueue()
- {
- int count = 0;
- foreach (var lp in _lstLps)
- {
- for (int i = 0; i < 25; i++)
- {
- if (CheckWaferNeedProcess(lp.Module, i))
- count++;
- }
- }
- return count;
- }
- //private SchedulerLoadLock GetCurrentLoadLockForTMPlace()
- //{
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsAvailable)
- // continue;
- // //if (!ll.CheckAtVacuum())
- // // continue;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // if (wafers.Any(x => x.ProcessState == EnumWaferProcessStatus.Completed))
- // {
- // for (int i = 0; i < 5;)
- // {
- // if ((WaferManager.Instance.CheckNoWafer(ll.Module, i))
- // && (WaferManager.Instance.CheckNoWafer(ll.Module, i + 1)))
- // {
- // return ll;
- // }
- // i += 2;
- // }
- // }
- // }
- // SchedulerLoadLock currentLoadLock = null;
- // DateTime dtMin = DateTime.MaxValue;
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsAvailable || !ll.CheckAtVacuum())
- // continue;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // DateTime dtCurrentLL = DateTime.MaxValue;
- // foreach (var wafer in wafers)
- // {
- // if (wafer != null && !wafer.IsEmpty && wafer.SubstHists.Length > 0)
- // {
- // var dt = wafer.SubstHists[wafer.SubstHists.Length - 1].AccessTime;
- // if (dt.CompareTo(dtMin) < 0)
- // dtCurrentLL = dt;
- // }
- // }
- // if (dtCurrentLL.CompareTo(dtMin) < 0)
- // {
- // dtMin = dtCurrentLL;
- // currentLoadLock = ll;
- // }
- // }
- // foreach (var ll in _lstLls)
- // {
- // if (currentLoadLock != null && currentLoadLock != ll)
- // continue;
- // for (int i = 0; i < 5;)
- // {
- // if ((WaferManager.Instance.CheckNoWafer(ll.Module, i))
- // && (WaferManager.Instance.CheckNoWafer(ll.Module, i + 1)))
- // {
- // return currentLoadLock;
- // }
- // i += 2;
- // }
- // currentLoadLock = null;//no empty slot
- // }
- // return currentLoadLock;
- //}
- //private SchedulerLoadLock GetCurrentLoadLockForTMPick()
- //{
- // SchedulerLoadLock currentLoadLock = null;
- // DateTime dtMin = DateTime.MaxValue;
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsAvailable || !ll.CheckAtVacuum())
- // continue;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // DateTime dtCurrentLL = DateTime.MaxValue;
- // foreach (var wafer in wafers)
- // {
- // if (wafer != null && !wafer.IsEmpty && wafer.ProcessState == EnumWaferProcessStatus.Idle && wafer.SubstHists.Length > 0)
- // {
- // var dt = wafer.SubstHists[wafer.SubstHists.Length - 1].AccessTime;
- // if (dt.CompareTo(dtMin) < 0)
- // dtCurrentLL = dt;
- // }
- // }
- // if (dtCurrentLL.CompareTo(dtMin) < 0)
- // {
- // dtMin = dtCurrentLL;
- // currentLoadLock = ll;
- // }
- // }
- // return currentLoadLock;
- //}
- //private SchedulerLoadLock GetCurrentLoadLockForEfem()
- //{
- // SchedulerLoadLock currentLoadLock = null;
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsOnline)
- // continue;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- // if (loadlockDevice.CheckDoorOpen())
- // {
- // foreach (var wafer in wafers)
- // {
- // if (wafer != null && !wafer.IsEmpty && wafer.ProcessState == EnumWaferProcessStatus.Idle)
- // {
- // currentLoadLock = ll;
- // break;
- // }
- // }
- // if (!wafers.Any(x => x.IsEmpty))
- // {
- // currentLoadLock = null;
- // }
- // }
- // }
- // return currentLoadLock;
- //}
- private int GetEmptySlotInCurrentLoadLock()
- {
- int count = 0;
- //SchedulerLoadLock currentLoadLock = GetCurrentLoadLockForEfem();
- foreach (var ll in _lstLls)
- {
- if (!ll.IsOnline)
- continue;
- //if (currentLoadLock != null && currentLoadLock != ll)
- // continue;
- //var loadlockDevice = DEVICE.GetDevice<SpinelLoadLock>(ll.Module.ToString());
- var wafers = WaferManager.Instance.GetWafers(ll.Module).ToList();
- //if (loadlockDevice.CheckDoorOpen())
- {
- for (int i = 0; i <= 1; i++)
- {
- var wafer0 = WaferManager.Instance.GetWafer(ll.Module, i);
- var wafer1 = WaferManager.Instance.GetWafer(ll.Module, i + 2);
- var wafer2 = WaferManager.Instance.GetWafer(ll.Module, i + 4);
- if (wafer0 != null && wafer0.IsEmpty)
- count++;
- if (wafer1 != null && wafer1.IsEmpty)
- count++;
- if (wafer2 != null && wafer2.IsEmpty)
- count++;
- if (count > 0)
- break;
- }
- }
- }
- if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 0) && CheckWaferNeedProcess(ModuleName.EfemRobot, 0))
- count--;
- if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 1) && CheckWaferNeedProcess(ModuleName.EfemRobot, 1))
- count--;
- if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, 2) && CheckWaferNeedProcess(ModuleName.EfemRobot, 2))
- count--;
- return count < 0 ? 0 : count;
- }
- private int GetEmptySlotInLoadLock(SchedulerLoadLock ll)
- {
- int count = 0;
- {
- if (!ll.IsOnline)
- return count;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty)
- count++;
- }
- }
- return count;
- }
- private int GetEmptySlotInLoadLock()
- {
- int count = 0;
- foreach (var ll in _lstLls)
- {
- if (!ll.IsOnline)
- continue;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty)
- count++;
- }
- }
- return count;
- }
- private int GetEmptySlotInPM()
- {
- int count = 0;
- foreach (var pm in _lstPms)
- {
- if (!pm.IsOnline)
- continue;
- var wafers = WaferManager.Instance.GetWafers(pm.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty)
- count++;
- }
- }
- return count;
- }
- private int GetEmptySlotInPMA()
- {
- int count = 0;
- if (!_pm1.IsOnline)
- return count;
- var wafers = WaferManager.Instance.GetWafers(_pm1.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty)
- count++;
- }
- return count;
- }
- private int GetEmptySlotInPMB()
- {
- int count = 0;
- if (!_pm2.IsOnline)
- return count;
- var wafers = WaferManager.Instance.GetWafers(_pm2.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty)
- count++;
- }
- return count;
- }
- //private bool CheckAlignerWaferCanPick(WaferInfo wafer, ModuleName aligner)
- //{
- // if (wafer == null || wafer.IsEmpty || wafer.ProcessJob == null ||
- // wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null || wafer.ProcessJob.Sequence.Steps.Count == 0)
- // return false;
- // var stepModules = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep].StepModules;
- // int count = 0;
- // int waferCount = 0;
- // if (stepModules == null || stepModules.Count == 0)
- // {
- // return false;
- // }
- // foreach (var pm in _lstPms)
- // {
- // if (pm.IsOnline && stepModules.Contains(pm.Module))
- // {
- // count++;
- // if (WaferManager.Instance.CheckHasWafer(pm.Module, 0))
- // waferCount++;
- // }
- // }
- // if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
- // {
- // count++;
- // }
- // else if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
- // {
- // var robotWafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) ? 0 : 1);
- // if (robotWafer != null && !robotWafer.IsEmpty && robotWafer.ProcessJob != null &&
- // robotWafer.ProcessJob.Sequence != null || robotWafer.ProcessJob.Sequence.Steps != null && robotWafer.ProcessJob.Sequence.Steps.Count > 0)
- // {
- // stepModules = robotWafer.ProcessJob.Sequence.Steps[robotWafer.NextSequenceStep].StepModules;
- // if (stepModules != null && stepModules.Count > 0)
- // {
- // if (stepModules.Contains(aligner))
- // {
- // count++;
- // }
- // }
- // }
- // }
- // return count - waferCount > 0;
- //}
- //private bool CheckWaferCanPick(WaferInfo wafer)
- //{
- // if (wafer == null || wafer.IsEmpty || wafer.ProcessJob == null ||
- // wafer.ProcessJob.Sequence == null || wafer.ProcessJob.Sequence.Steps == null || wafer.ProcessJob.Sequence.Steps.Count == 0)
- // return false;
- // var stepModules = wafer.ProcessJob.Sequence.Steps[wafer.NextSequenceStep + 1].StepModules;
- // int count = 0;
- // int waferCount = 0;
- // if (stepModules == null || stepModules.Count == 0)
- // {
- // return false;
- // }
- // if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1))
- // {
- // count++;
- // }
- // return count - waferCount > 0;
- //}
- private SlotItem GetWaferReturnLoadPort(ModuleName module, int slot)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(module, slot);
- if (!wafer.IsEmpty)
- {
- return new SlotItem((ModuleName)wafer.OriginStation, wafer.OriginSlot);
- }
- return null;
- }
- private bool CheckSequenceRobotSlotEnable(bool blade1Enable, bool blade2Enable, string slotSelection, string title, out string errorMsg)
- {
- errorMsg = string.Empty;
- if(!string.IsNullOrWhiteSpace(slotSelection))
- {
- var dic = new Dictionary<int, bool>() { { 0, blade1Enable }, { 1, blade2Enable } };
- var pos = new string[] { "lower", "upper" };
- foreach (var index in dic.Keys)
- {
- if (slotSelection.Contains(index.ToString()) && !dic[index])
- {
- errorMsg = $"{title} {pos[index]} blade is not enabled ";
- return false;
- }
- }
- }
- return true;
- }
- private bool ValidateSequence(string[] seqs, out string reason)
- {
- reason = string.Empty;
- bool isAllSequenceNull = true;
- for (int i = 0; i < seqs.Length; i++)
- {
- if (string.IsNullOrEmpty(seqs[i]))
- continue;
- var sequence = SequenceInfoHelper.GetInfo(seqs[i]);
- if ((sequence == null || sequence.Steps == null || sequence.Steps.Count == 0) && !string.IsNullOrEmpty(sequence.Name))
- {
- reason = $"Invalid sequence {seqs[i]}";
- return false;
- }
- isAllSequenceNull = false;
- foreach (var step in sequence.Steps)
- {
- foreach (var module in step.StepModules)
- {
- if (ModuleHelper.IsEfem(module) || ModuleHelper.IsEfemRobot(module))
- {
- }
- else if (ModuleHelper.IsTM(module) || ModuleHelper.IsTMRobot(module))
- {
- }
- else if (ModuleHelper.IsPm(module))
- {
- string pmInstall = $"System.SetUp.{module}.IsInstalled";
- if (!SC.GetValueOrDefault<bool>(pmInstall))
- {
- reason = $"Invalid sequence {seqs[i]}, {module} is uninstalled";
- return false;
- }
- }
- else if (!SC.GetValueOrDefault<bool>($"System.SetUp.{module}.IsInstalled"))
- {
- reason = $"Invalid sequence {seqs[i]}, {module} is uninstalled";
- return false;
- }
- }
- if (step.StepModules.Any(p => ModuleHelper.IsEfemRobot(p)))
- {
- string slotSelection = step.StepParameter.ContainsKey("SlotSelection") ? step.StepParameter["SlotSelection"].ToString() : string.Empty;
- if(!CheckSequenceRobotSlotEnable(_efem.Blade1Enable, _efem.Blade2Enable, slotSelection, "efem robot", out reason))
- {
- reason = $"Invalid sequence {seqs[i]}, {reason}";
- return false;
- }
- }
- if (step.StepModules.Any(p => ModuleHelper.IsTMRobot(p)))
- {
- string slotSelection = step.StepParameter.ContainsKey("SlotSelection") ? step.StepParameter["SlotSelection"].ToString() : string.Empty;
- if (!CheckSequenceRobotSlotEnable(_tmRobot.Blade1Enable, _tmRobot.Blade2Enable, slotSelection, "tm robot", out reason))
- {
- reason = $"Invalid sequence {seqs[i]}, {reason}";
- return false;
- }
- }
- if (step.StepModules.Any(x => x == ModuleName.Aligner1))
- {
- if (!SC.GetValueOrDefault<bool>("System.SetUp.Aligner1.IsInstalled"))
- {
- reason = $"Invalid sequence {seqs[i]}, Aligner1 is uninstalled";
- return false;
- }
- if (step.AlignAngle < 0 || step.AlignAngle > 360)
- {
- reason = $"Invalid sequence {seqs[i]}, Aligner1 angle parameter is not valid";
- return false;
- }
- }
- if (step.StepModules.Any(x => x == ModuleName.Aligner2))
- {
- if (!SC.GetValueOrDefault<bool>("System.SetUp.Aligner2.IsInstalled"))
- {
- reason = $"Invalid sequence {seqs[i]}, Aligner2 is uninstalled";
- return false;
- }
- if (step.AlignAngle < 0 || step.AlignAngle > 360)
- {
- reason = $"Invalid sequence {seqs[i]}, Aligner2 angle parameter is not valid";
- return false;
- }
- }
- }
- }
- if (isAllSequenceNull)
- {
- reason = $"Invalid sequence, sequence are all null ";
- return false;
- }
- return true;
- }
- private void CalcedThroughput(List<ProcessJobInfo> pjRemoveList)
- {
- int count = 0;
- foreach (var pj in pjRemoveList)
- {
- if (pj.SlotWafers != null)
- {
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo waferInfo = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- if (waferInfo.ProcessState == EnumWaferProcessStatus.Completed
- && waferInfo.SubstTransStatus == SubstrateTransportStatus.AtDestination)
- {
- count++;
- }
- }
- }
- }
- _throughputData.UpdateCalced(count);
- }
- private void CalcingThroughput()
- {
- if (!_lstControlJobs.Any())
- {
- _throughputData.Pause();
- return;
- }
- if (!_lstControlJobs.Any(x => x.State == EnumControlJobState.Executing))
- {
- _throughputData.Pause();
- return;
- }
- _throughputData.BeginCalc();
- int count = 0;
- foreach (var pj in _lstProcessJobs)
- {
- if(pj.SlotWafers==null)
- {
- continue;
- }
- foreach (var pjSlotWafer in pj.SlotWafers)
- {
- WaferInfo waferInfo = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
- if (waferInfo.ProcessState == EnumWaferProcessStatus.Completed
- && waferInfo.SubstTransStatus == SubstrateTransportStatus.AtDestination)
- {
- count++;
- }
- }
- }
- if (count > _throughputData.CalcingProcessedCount)
- {
- _throughputData.UpdateCalcing(count);
- }
- }
- #endregion
- #region Checked
- public bool CheckCanProcess(ModuleName pmModule)
- {
- var wafer0 = WaferManager.Instance.GetWafer(pmModule, 0);
- var wafer1 = WaferManager.Instance.GetWafer(pmModule, 1);
- bool _PM1Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.{pmModule}Chamber1Disabled.IsInstalled");
- bool _PM2Disabled = SC.GetValueOrDefault<bool>($"System.SetUp.{pmModule}Chamber2Disabled.IsInstalled");
- //如果PM腔体中有wafer,但不需要process,则不允许PM进行Process
- if (!wafer0.IsEmpty && !CheckWaferNeedProcessBySlot(pmModule, 0, pmModule,0))
- {
- return false;
- }
- if (!wafer1.IsEmpty && !CheckWaferNeedProcessBySlot(pmModule, 1, pmModule,1))
- {
- return false;
- }
- //如果PM腔体中两片wafer都需要Process,并且recipe名字相同,则允许process
- if (CheckWaferNeedProcessBySlot(pmModule, 0, pmModule,0)
- && CheckWaferNeedProcessBySlot(pmModule, 1, pmModule,1)
- && wafer0.ProcessJob.Sequence.Name == wafer1.ProcessJob.Sequence.Name)
- {
- return true;
- }
- //如果PM腔体中只有一片wafer需要Process,并且LLA/LLB/TMRobot中找不到相同SequenceName的wafer时,允许process
- if (CheckWaferNeedProcessBySlot(pmModule, 0, pmModule,0))
- {
- var pmWafer = WaferManager.Instance.GetWafer(pmModule, 0);
- if (pmWafer.ProcessJob != null)
- {
- if (_PM2Disabled)
- return true;
- if (GetSameSequenceUnprocessedWaferCount(new List<ModuleName>(_lstLls.Select(p=>p.Module)) { ModuleName.TMRobot }, pmWafer.ProcessJob.Sequence.Name, pmModule, 1) == 0)
- return true;
- if (CheckUnprocessedWaferByStation(pmModule, 1,pmWafer))
- return true;
- }
- }
- if (CheckWaferNeedProcessBySlot(pmModule, 1, pmModule,1))
- {
- var pmWafer = WaferManager.Instance.GetWafer(pmModule, 1);
- if (pmWafer.ProcessJob != null)
- {
- if (_PM1Disabled)
- return true;
- if (GetSameSequenceUnprocessedWaferCount(new List<ModuleName>(_lstLls.Select(p => p.Module)) { ModuleName.TMRobot }, pmWafer.ProcessJob.Sequence.Name, pmModule, 0) == 0)
- return true;
- if (CheckUnprocessedWaferByStation(pmModule, 0, pmWafer))
- return true;
- }
- }
- return false;
- }
- public bool CheckCanPlaceWaferToPM(ModuleName pmModule, int slot, WaferInfo wafer)
- {
- if (!_tmRobot.IsAvailable)
- return false;
- if (!CheckWaferNeedProcessBySlot(wafer, pmModule, slot))
- return false;
- var wafer0 = WaferManager.Instance.GetWafer(pmModule, 0);
- if (!wafer0.IsEmpty && !CheckWaferNeedProcessBySlot(wafer0, pmModule, 0))
- {
- return false;
- }
- var wafer1 = WaferManager.Instance.GetWafer(pmModule, 1);
- if (!wafer1.IsEmpty && !CheckWaferNeedProcessBySlot(wafer1, pmModule, 1))
- {
- return false;
- }
- if (CheckWaferNeedProcessBySlot(wafer0, pmModule, 0)
- && CheckWaferNeedProcessBySlot(wafer, pmModule, slot)
- && wafer0.ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- return true;
- if (CheckWaferNeedProcessBySlot(wafer1, pmModule, 1)
- && CheckWaferNeedProcessBySlot(wafer, pmModule, slot)
- && wafer1.ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- return true;
- if (wafer0.IsEmpty
- && wafer1.IsEmpty
- && CheckWaferNeedProcessBySlot(wafer, pmModule, slot))
- return true;
- return false;
- }
- public bool CheckCanPickWaferFromPM(ModuleName pmModule, int slot)
- {
- if (!_tmRobot.IsAvailable)
- return false;
- var wafer = WaferManager.Instance.GetWafer(pmModule, slot);
- if (!wafer.IsEmpty
- && wafer.ProcessJob != null
- && wafer.ProcessJob.Sequence != null
- && wafer.ProcessJob.Sequence.Steps != null
- && wafer.ProcessState == EnumWaferProcessStatus.Completed)
- return true;
- return false;
- }
- public int GetSameSequenceUnprocessedWaferCount(List<ModuleName> modules, string sequenceName, ModuleName processIn, int slot)
- {
- int count = 0;
- for (int i = 0; i < modules.Count; i++)
- {
- var wafers = WaferManager.Instance.GetWafers(modules[i]);
- for (int j = 0; j < wafers.Length; j++)
- {
- if (CheckWaferNeedProcessBySlot(wafers[j], processIn, slot)
- && wafers[j].ProcessJob != null
- && wafers[j].ProcessJob.Sequence.Name == sequenceName)
- count++;
- }
- }
- return count;
- }
- public bool CheckUnprocessedWaferByStation(ModuleName processIn, int slot, WaferInfo sourceWafer)
- {
- var modules = new List<ModuleName>() { ModuleName.LP1, ModuleName.LP2, ModuleName.LP3, ModuleName.Aligner1,
- ModuleName.Aligner2, ModuleName.LLA, ModuleName.LLB, ModuleName.TMRobot, ModuleName.EfemRobot };
- modules.Where(p => p != ModuleName.EfemRobot && p != ModuleName.TMRobot && !SC.GetValueOrDefault<bool>($"System.SetUp.{p}.IsInstalled")).ToList()
- .ForEach(p => modules.Remove(p));
- return !modules.Any(p => WaferManager.Instance.GetWafers(p).Any(wafer => CheckWaferNeedProcessBySlot(wafer, processIn, slot)
- && wafer.OriginStation == sourceWafer.OriginStation
- && wafer.ProcessJob != null
- && wafer.ProcessJob.Sequence.Name == sourceWafer.ProcessJob.Sequence.Name));
- }
- public int? GetAvilableLoadLockSlotForEfemRobotPlace(SchedulerLoadLock ll)
- {
- if (!ll.IsAvailable)
- return null;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i].IsEmpty && ll.IsReadyForPlace(ModuleName.TMRobot, Hand.Blade1, i))
- return i;
- }
- return null;
- }
- public List<int> GetAvilableLoadLockSlotForTMRobotPlace(Hand blade, SchedulerLoadLock ll)
- {
- if (!ll.IsAvailable)
- return null;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- var waferLen = wafers.Length;
- for (int i = 0; i < waferLen; i++)
- {
- var slots = TryGetPairSlot(i);
- if (slots.Count > 0 && slots.All(p => wafers[i].IsEmpty && ll.IsReadyForPlace(ModuleName.TMRobot, blade, p)))
- return slots;
- }
- return null;
- }
- //public int? GetAvilableLoadLockSlotForTMRobotPick(SchedulerLoadLock ll)
- //{
- // if (!ll.IsAvailable)
- // return null;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module);
- // foreach (var pm in _lstPms)
- // {
- // var pmWafer0 = WaferManager.Instance.GetWafer(pm.Module, 0);
- // var pmWafer1 = WaferManager.Instance.GetWafer(pm.Module, 1);
- // //如果腔体中两片都满了,则跳过
- // if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
- // continue;
- // //如果腔体中两片都为空,则取一片放入
- // if (pmWafer0.IsEmpty && pmWafer1.IsEmpty)
- // {
- // for (int i = 0; i < wafers.Length; i++)
- // {
- // if (!wafers[i].IsEmpty
- // && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- // && CheckWaferNeedProcess(ll.Module, i))
- // return i;
- // }
- // }
- // //如果腔体中一片为空,则取一片相同recipeName的放入
- // if (!pmWafer0.IsEmpty || !pmWafer1.IsEmpty)
- // {
- // var wafer = !pmWafer0.IsEmpty ? pmWafer0 : pmWafer1;
- // if (!CheckWaferNeedProcess(wafer))
- // return null;
- // var tmWafers = WaferManager.Instance.GetWafers(ModuleName.TMRobot);
- // //判断TMRobot是否已经存在相同recipeName的wafer
- // for (int i = 0; i < tmWafers.Length; i++)
- // {
- // if (CheckWaferNeedProcess(tmWafers[i])
- // && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- // return null;
- // }
- // for (int i = 0; i < wafers.Length; i++)
- // {
- // if (!wafers[i].IsEmpty
- // && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- // && CheckWaferNeedProcess(ll.Module, i)
- // && wafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- // return i;
- // }
- // }
- // }
- // return null;
- //}
- //public List<Tuple<SchedulerLoadLock, int>> GetAvilableLoadLockSlotForTMRobotPick()
- //{
- // List<Tuple<SchedulerLoadLock, int>> result = new List<Tuple<SchedulerLoadLock, int>>();
- // foreach (var ll in _lstLls)
- // {
- // if (!ll.IsAvailable)
- // continue;
- // var wafers = WaferManager.Instance.GetWafers(ll.Module);
- // foreach (var pm in _lstPms)
- // {
- // var pmWafer0 = WaferManager.Instance.GetWafer(pm.Module, 0);
- // var pmWafer1 = WaferManager.Instance.GetWafer(pm.Module, 1);
- // //如果腔体中两片都满了,则跳过
- // if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty)
- // continue;
- // //如果腔体中两片都为空,则取一片放入
- // if (pmWafer0.IsEmpty && pmWafer1.IsEmpty)
- // {
- // for (int i = 0; i < wafers.Length; i++)
- // {
- // if (!wafers[i].IsEmpty
- // && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- // && CheckWaferNeedProcess(ll.Module, i, pm.Module)
- // && !result.Exists(x => x.Item1 == ll && x.Item2 == i))
- // result.Add(new Tuple<SchedulerLoadLock, int>(ll, i));
- // }
- // }
- // //如果腔体中一片为空,则取一片相同recipeName的放入
- // if (!pmWafer0.IsEmpty || !pmWafer1.IsEmpty)
- // {
- // var wafer = !pmWafer0.IsEmpty ? pmWafer0 : pmWafer1;
- // if (!CheckWaferNeedProcess(wafer))
- // continue;
- // var tmWafers = WaferManager.Instance.GetWafers(ModuleName.TMRobot);
- // //判断TMRobot是否已经存在相同recipeName的wafer
- // for (int i = 0; i < tmWafers.Length; i++)
- // {
- // if (CheckWaferNeedProcess(tmWafers[i])
- // && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- // continue;
- // }
- // for (int i = 0; i < wafers.Length; i++)
- // {
- // if (!wafers[i].IsEmpty
- // && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- // && CheckWaferNeedProcess(ll.Module, i, pm.Module)
- // && wafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name
- // && !result.Exists(x => x.Item1 == ll && x.Item2 == i))
- // result.Add(new Tuple<SchedulerLoadLock, int>(ll, i));
- // }
- // }
- // }
- // }
- // return result;
- //}
- public List<Tuple<SchedulerLoadLock, int>> FindAllLoadLockSlotForTMRobotPick()
- {
- List<Tuple<SchedulerLoadLock, int>> result = new List<Tuple<SchedulerLoadLock, int>>();
- foreach (var ll in _lstLls)
- {
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- foreach (var pm in _lstPms)
- {
- var pmWafer0 = WaferManager.Instance.GetWafer(pm.Module, 0);
- var pmWafer1 = WaferManager.Instance.GetWafer(pm.Module, 1);
- if(pm.IsError) continue;
- //如果腔体中两片都满了,则跳过
- if (!pmWafer0.IsEmpty && !pmWafer1.IsEmpty && !SC.IsDoubleFork)
- continue;
- bool blade1EmptyAndEnable = _tmRobot.Blade1Enable && Converter.MapBladeToSlots(Hand.Blade1).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- bool blade2EmptyAndEnable = _tmRobot.Blade2Enable && Converter.MapBladeToSlots(Hand.Blade2).All(p => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, p));
- //如果腔体中两片都为空
- if ((pmWafer0.IsEmpty && pmWafer1.IsEmpty) ||
- (SC.IsDoubleFork && blade1EmptyAndEnable && blade2EmptyAndEnable))
- {
- if (SC.IsDoubleFork && pm.Module == ModuleName.PMA && (_PMA1Disabled || _PMA2Disabled)) continue;
- if (SC.IsDoubleFork && pm.Module == ModuleName.PMB && (_PMB1Disabled || _PMB2Disabled)) continue;
- for (int i = 0; i < wafers.Length; i++)
- {
- if (!wafers[i].IsEmpty
- && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- && (CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 0) || CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 1))
- && !result.Exists(x => x.Item1 == ll && x.Item2 == i))
- result.Add(new Tuple<SchedulerLoadLock, int>(ll, i));
- }
- }
- if (SC.IsDoubleFork) continue;
- if (pm.Module == ModuleName.PMA && !pmWafer0.IsEmpty && _PMA2Disabled)
- {
- continue;
- }
- if (pm.Module == ModuleName.PMA && !pmWafer1.IsEmpty && _PMA1Disabled)
- {
- continue;
- }
- if (pm.Module == ModuleName.PMB && !pmWafer0.IsEmpty && _PMB2Disabled)
- {
- continue;
- }
- if (pm.Module == ModuleName.PMB && !pmWafer1.IsEmpty && _PMB1Disabled)
- {
- continue;
- }
- //如果腔体中一片为空,则取一片相同recipeName的放入
- if (!pmWafer0.IsEmpty)
- {
- var wafer = !pmWafer0.IsEmpty ? pmWafer0 : pmWafer1;
- if (!CheckWaferNeedProcessBySlot(wafer, pm.Module, 1))
- continue;
- var tmWafers = WaferManager.Instance.GetWafers(ModuleName.TMRobot);
- //判断TMRobot是否已经存在相同recipeName的wafer
- for (int i = 0; i < tmWafers.Length; i++)
- {
- if (CheckWaferNeedProcessBySlot(tmWafers[i], pm.Module, 1)
- && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- continue;
- }
- for (int i = 0; i < wafers.Length; i++)
- {
- if (!wafers[i].IsEmpty
- && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- && CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 1)
- && wafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name
- && !result.Exists(x => x.Item1 == ll && x.Item2 == i))
- result.Add(new Tuple<SchedulerLoadLock, int>(ll, i));
- }
- }
- if (!pmWafer1.IsEmpty)
- {
- var wafer = !pmWafer0.IsEmpty ? pmWafer0 : pmWafer1;
- if (!CheckWaferNeedProcessBySlot(wafer, pm.Module, 0))
- continue;
- var tmWafers = WaferManager.Instance.GetWafers(ModuleName.TMRobot);
- //判断TMRobot是否已经存在相同recipeName的wafer
- for (int i = 0; i < tmWafers.Length; i++)
- {
- if (CheckWaferNeedProcessBySlot(tmWafers[i], pm.Module, 0)
- && tmWafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name)
- continue;
- }
- for (int i = 0; i < wafers.Length; i++)
- {
- if (!wafers[i].IsEmpty
- && ll.IsReadyForPick(ModuleName.TMRobot, Hand.Blade1, i)
- && CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 0)
- && wafers[i].ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name
- && !result.Exists(x => x.Item1 == ll && x.Item2 == i))
- result.Add(new Tuple<SchedulerLoadLock, int>(ll, i));
- }
- }
- }
- }
- return result;
- }
- public int GetWaferCountLoadLockToPM(ModuleName pmModule)
- {
- int result = 0;
- foreach (var ll in _lstLls)
- {
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- foreach (var pm in _lstPms)
- {
- if (pm.Module != pmModule)
- continue;
- for (int i = 0; i < wafers.Length; i++)
- {
- if (!wafers[i].IsEmpty
- && (CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 0)
- || CheckWaferNeedProcessBySlot(ll.Module, i, pm.Module, 1)))
- result++;
- }
- }
- }
- return result;
- }
- public bool CheckRecipeUsedInJob(string pathName)
- {
- foreach (var pj in _lstProcessJobs)
- {
- var seq = pj.Sequence;
- for (int i = 0; i < seq.Steps.Count; i++)
- {
- SequenceStepInfo stepInfo = seq.Steps[i];
- foreach (var module in stepInfo.StepModules)
- {
- if (ModuleHelper.IsPm(module))
- {
- string attr = module == ModuleName.PMA ? "PMARecipe" : "PMBRecipe";
- if (stepInfo.StepParameter.ContainsKey(attr)
- && !string.IsNullOrEmpty((string)stepInfo.StepParameter[attr]))
- {
- var recipeName = (string)stepInfo.StepParameter[attr];
- if (!string.IsNullOrEmpty(recipeName))
- {
- if (pathName.EndsWith(recipeName + ".rcp"))
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
- public bool CheckSequenceUsedInJob(string pathName)
- {
- foreach (var pj in _lstProcessJobs)
- {
- if (pathName.EndsWith(pj.Sequence.Name + ".seq"))
- return true;
- }
- return false;
- }
- private bool CheckHasWaferAndNextStepIsLoadLock(Hand hand)
- {
- var forkSlots = new int[] { (int)hand, ((int)hand) + 2 };
- var sourceSlots = new List<int>();
- foreach (var forkSlot in forkSlots)
- {
- var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, forkSlot);
- if (wafer != null && !wafer.IsEmpty) sourceSlots.Add(forkSlot);
- }
- return sourceSlots.Count() > 0 && sourceSlots.All(p => CheckWaferNextStepIsLoadLock(ModuleName.TMRobot, p));
- }
- private List<int> TryGetPairSlot(int sourceSlot)
- {
- if (SC.IsDoubleFork)
- {
- var targetSlots = new List<int>() { sourceSlot, (sourceSlot % 2 > 0) ? sourceSlot - 1 : sourceSlot + 1 };
- targetSlots.Sort();
- return targetSlots;
- }
- return new List<int>() { sourceSlot };
- }
- private int GetNoNeedProcessInLoadLock(SchedulerLoadLock ll)
- {
- int count = 0;
- if (!ll.IsOnline)
- return count;
- var wafers = WaferManager.Instance.GetWafers(ll.Module);
- for (int i = 0; i < wafers.Length; i++)
- {
- if (wafers[i] != null && !wafers[i].IsEmpty && !CheckWaferNeedProcess(ll.Module, i)) count++;
- }
- return count;
- }
- private SchedulerPM GetExistSwapPM()
- {
- SchedulerPM swapPm = null;
- if (!SC.IsDoubleFork) return swapPm;
- foreach(var pm in _lstPms)
- {
- if(IsExistSwap(pm.Module,0) &&
- (swapPm == null || (swapPm != null && (pm.WaferArriveTicks[0] < swapPm.WaferArriveTicks[0]))))
- {
- swapPm = pm;
- }
- }
- return swapPm;
- }
- private bool CheckLLSlotForSwap(ModuleName llModule, params int[] llSlots)
- {
- var swapPm = GetExistSwapPM();
- if (swapPm == null) return true;
- return llSlots.Any(p => _pmSlots.Any(s => CheckWaferNeedProcessBySlot(llModule, p, swapPm.Module, s)));
- }
- private bool IsExistSwap(ModuleName pm, int pmSlot)
- {
- if (!_pmSwapWaitTimeOut[pm].Item2.IsTimeout() && SC.IsDoubleFork &&
- _tmRobot.Blade1Enable && _tmRobot.Blade2Enable &&
- _lstPms.Sum(p => WaferManager.Instance.GetWafers(p.Module).Where(m => !m.IsEmpty).Count()) > 3 &&
- CheckCanPickWaferFromPM(pm, pmSlot))
- {
- _pmSwapWaitTimeOut[pm].Item1.CLK = _lstLls.Any(ll => _llSlots.Any(s => WaferManager.Instance.CheckHasWafer(ll.Module, s) &&
- CheckWaferNeedProcessBySlot(ll.Module, s, pm, pmSlot)));
- if (_pmSwapWaitTimeOut[pm].Item1.Q) _pmSwapWaitTimeOut[pm].Item2.Start(2000);
- return _pmSwapWaitTimeOut[pm].Item1.CLK;
- }
- return false;
- }
- private void ResetPmSwapWaitTimeOut(ModuleName pm)
- {
- _pmSwapWaitTimeOut[pm].Item1.RST = true;
- _pmSwapWaitTimeOut[pm].Item2.Stop();
- }
- private Tuple<SchedulerLoadLock, List<int>> FindPairSlotInLL(List<Tuple<SchedulerLoadLock, int>> llSlots)
- {
- var newLLSlot = new List<Tuple<SchedulerLoadLock, int>>();
- newLLSlot.AddRange(llSlots);
- newLLSlot.Sort(LoadLockComparison);
- for (var i = 0; i < llSlots.Count; i++)
- {
- var selectSlot = GetWaferOrderInJobQueue(newLLSlot);
- if (selectSlot != null && selectSlot.Item1.IsAvailable)
- {
- int pickSlot = selectSlot.Item2;
- var pairSlot = TryGetPairSlot(pickSlot);
- if (pairSlot.Count > 1 &&
- pairSlot.All(slot => llSlots.FirstOrDefault(p => p.Item1.Module == selectSlot.Item1.Module && p.Item2 == slot) != null) &&
- CheckLLSlotForSwap(selectSlot.Item1.Module, pairSlot.ToArray()))
- {
- return new Tuple<SchedulerLoadLock, List<int>>(selectSlot.Item1, pairSlot);
- }
- else
- {
- if (CheckLLSlotForSwap(selectSlot.Item1.Module, selectSlot.Item2) &&
- (!SC.IsDoubleFork || !CheckSequenceNameAndNeedProcess(WaferManager.Instance.GetWafer(selectSlot.Item1.Module, selectSlot.Item2).ProcessJob.Sequence.Name)))
- {
- return new Tuple<SchedulerLoadLock, List<int>>(selectSlot.Item1, new List<int>() { selectSlot.Item2 });
- }
- }
- newLLSlot.Remove(selectSlot);
- }
- }
- return null;
- }
- private int LoadLockComparison(Tuple<SchedulerLoadLock, int> x, Tuple<SchedulerLoadLock, int> y)
- {
- return (int)(x.Item1.WaferArriveTicks[x.Item2] - y.Item1.WaferArriveTicks[y.Item2]);
- }
- private Tuple<SchedulerLoadLock, List<int>> FindSingleSlotInLL(List<Tuple<SchedulerLoadLock, int>> llSlots)
- {
- var newLLSlot = new List<Tuple<SchedulerLoadLock, int>>();
- newLLSlot.AddRange(llSlots);
- for (var i = 0; i < llSlots.Count; i++)
- {
- Tuple<SchedulerLoadLock, int> selectSlot = GetWaferOrderInJobQueue(newLLSlot);
- if (selectSlot != null)
- {
- SchedulerLoadLock ll = selectSlot.Item1;
- if (!ll.IsAvailable)
- return null;
- if(CheckLLSlotForSwap(selectSlot.Item1.Module, selectSlot.Item2) &&
- !CheckSequenceNameAndNeedProcess(WaferManager.Instance.GetWafer(ll.Module,selectSlot.Item2).ProcessJob.Sequence.Name))
- {
- return new Tuple<SchedulerLoadLock, List<int>>(ll, new List<int>() { selectSlot.Item2 });
- }
- newLLSlot.Remove(selectSlot);
- }
- }
- return null;
- }
- private Tuple<SchedulerLoadLock, List<int>> TryFindLLAndPairSlot(List<Tuple<SchedulerLoadLock, int>> llSlots)//(List<Tuple<SchedulerLoadLock, int>> lists, Tuple<SchedulerLoadLock, int> firstSlot, out int secondSlot)
- {
- if (SC.IsDoubleFork && GetExistSwapPM() == null &&
- _lstPms.Sum(p => WaferManager.Instance.GetWafers(p.Module).Where(m => !m.IsEmpty).Count()) > 3)
- {
- var allSequenceName = _lstPms.SelectMany(p => WaferManager.Instance.GetWafers(p.Module).Where(m => !m.IsEmpty)).Select(w => w.ProcessJob.Sequence.Name);
- if (allSequenceName.GroupBy(p => p).Count() > 1) return null;
- }
- return FindPairSlotInLL(llSlots);
- }
- private bool ExistPairWafer(List<Tuple<SchedulerLoadLock, int>> targetWafers)
- {
- if (targetWafers.Count > 0)
- {
- var targetLLSlots = targetWafers.GroupBy(p => p.Item1);
- var pairSlots = new string[] { "01", "23", "45", "67" };
- foreach (var item in targetLLSlots)
- {
- var slots = string.Join("", item.Select(p => p.Item2).ToArray().OrderBy(p => p));
- if (pairSlots.Any(p => slots.Contains(p)))
- {
- return true;
- }
- }
- }
- return false;
- }
- private bool CheckHasWaferAndNeedProcess(Hand hand)
- {
- var forkSlots = new int[] { (int)hand, ((int)hand) + 2 };
- var sourceSlots = new List<int>();
- foreach (var forkSlot in forkSlots)
- {
- var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, forkSlot);
- if (wafer != null && !wafer.IsEmpty) sourceSlots.Add(forkSlot);
- }
- return sourceSlots.Count > 0 && sourceSlots.All(p => CheckWaferNeedProcess(ModuleName.TMRobot, p));
- }
- private int[] GetHasWaferSlotByHand(Hand hand)
- {
- var forkSlots = new int[] { (int)hand, ((int)hand) + 2 };
- var sourceSlots = new List<int>();
- foreach (var forkSlot in forkSlots)
- {
- var wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, forkSlot);
- if (wafer != null && !wafer.IsEmpty) sourceSlots.Add(forkSlot);
- }
- return sourceSlots.ToArray();
- }
- private WaferInfo[] GetHandWafers(Hand hand)
- {
- return GetHasWaferSlotByHand(hand).Select(p => WaferManager.Instance.GetWafer(ModuleName.TMRobot, p)).ToArray();
- }
- private List<Hand> CheckCanPlaceWaferToPM(Hand[] sourceHand, ModuleName pm)
- {
- List<Hand> hands = new List<Hand>();
- for (int i = 0; i < sourceHand.Length; i++)
- {
- var wafers = GetHandWafers(sourceHand[i]);
- var pmSlot = wafers.Length > 1 ? new int[] { 0, 1 } : new int[] { 0 };
- if (pmSlot.All(p => CheckCanPlaceWaferToPM(pm, p, wafers[p]))) hands.Add(sourceHand[i]);
- }
- return hands;
- }
- private bool TryFindNeedPairLoadLock(ModuleName root, Hand hand, SchedulerLoadLock curLL)
- {
- var sourceWafer = WaferManager.Instance.GetWafer(root, (int)hand);
- if (sourceWafer == null || sourceWafer.IsEmpty ||
- sourceWafer.ProcessJob == null || sourceWafer.ProcessJob.Sequence == null) return false;
- var targetLL = curLL;
- foreach (var ll in _lstLls)
- {
- if (!_efem.IsAvailable)
- return false;
- if (ll == curLL) continue;
- if (!CheckWaferNextStepIsLoadLock(ModuleName.EfemRobot, (int)hand, ll.Module))
- continue;
- for (int i = 0; i < 6; i++)
- {
- var wafer = WaferManager.Instance.GetWafer(ll.Module, i);
- if (wafer != null && !wafer.IsEmpty &&
- wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null &&
- wafer.ProcessState == EnumWaferProcessStatus.Idle &&
- sourceWafer.ProcessJob.Sequence.Name == wafer.ProcessJob.Sequence.Name
- )
- {
- var nextSlot = (i % 2 > 0) ? i - 1 : i + 1;
- var nextWafer = WaferManager.Instance.GetWafer(ll.Module, nextSlot);
- if (nextWafer != null && !nextWafer.IsEmpty) continue;
- targetLL = ll;
- break;
- }
- }
- }
- return targetLL.Module == curLL.Module;
- }
- private bool CheckSequenceNameAndNeedProcess(string sequenceName)
- {
- foreach (ProcessJobInfo pj in _lstProcessJobs)
- {
- if (pj.State == EnumProcessJobState.Processing || pj.State == EnumProcessJobState.Paused)
- {
- for (int i = 0; i < pj.SlotWafers.Count; ++i)
- {
- WaferInfo wafer = WaferManager.Instance.GetWafer(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2);
- if (wafer.IsEmpty)
- continue;
- if (CheckWaferNeedProcess(pj.SlotWafers[i].Item1, pj.SlotWafers[i].Item2) && wafer.ProcessJob.Sequence.Name == sequenceName)
- return true;
- }
- }
- }
- var moduleList = new List<ModuleName>();
- moduleList.Add(ModuleName.EfemRobot);
- moduleList.AddRange(_lstAligners.Select(p => p.Module));
- return moduleList.Any(p => WaferManager.Instance.GetWafers(p).Where(w => !w.IsEmpty).Any(w => CheckWaferNeedProcess(w) && w.ProcessJob.Sequence.Name == sequenceName));
- }
- private bool CheckSequenceNameAndNeedProcess(List<Tuple<SchedulerLoadLock, int>> targetWafers)
- {
- return targetWafers.Count <= 0 || targetWafers.All(p => CheckSequenceNameAndNeedProcess(WaferManager.Instance.GetWafer(p.Item1.Module, p.Item2).ProcessJob.Sequence.Name));
- }
- #endregion
- }
- }
|