· 7 years ago · Oct 08, 2018, 02:04 PM
1/*---HEADER--------------------------------------------------------------------
2* Component..: pt_calcul.pc
3* Version....: 1.0
4* Creation...: 14/01/2004
5* Author.....: L. SPEYSER Euriware
6* Description: Measurement cells computation
7*
8*-----------------------------------------------------------------------------
9* Modified...: 21/04/2004
10* By.........: L. SPEYSER Euriware
11* Version....: 2.0
12* Description: See the following procedures
13* - PT_ComputeCell()
14* - PT_ComputeCells()
15* FAE 04-582
16*
17*-----------------------------------------------------------------------------
18* Modified...: 24/05/2004
19* By.........: L. SPEYSER Euriware
20* Version....: 3.0
21* Description: Algorithm improvements
22* FAE 04-624
23*
24*-----------------------------------------------------------------------------
25* Modified...: 28/05/2004
26* By.........: L. SPEYSER Euriware
27* Version....: 4.0
28* Description: Crolles 2 Parametric test
29* Global rework of the component pt_calcul.pc
30* Procedures changes
31* New: PT_ComputeCellContainingPoint()
32* Updated:PT_GetCellLimits(), arguments changes
33* PT_IsCellInUsefulArea(), arguments changes
34* PT_NumOfCornerInUsefulArea(), arguments changes
35* PT_OrderCells(), arguments changes
36* PT_IsCellUsed(), arguments changes
37* PT_ComputeCell(), implementation changes
38* PT_ComputeCells(), implementation changes
39* PT_ComputeMeasurementCells(), implementation changes
40* Removed:PT_ComputeCellCoord(), replaced by PT_ComputeCellContainingPoint()
41*
42*-----------------------------------------------------------------------------
43* Modified...: 20/09/2004
44* By.........: SL23 Euriware
45* Version....: 4.1
46* Description: FAE 04-711
47*
48*-----------------------------------------------------------------------------
49* Modified...: 21/09/2004
50* By.........: SL23 Euriware
51* Version....: 4.2
52* Description: FAE 04-680
53*
54*-----------------------------------------------------------------------------
55* Modified...: 14/12/2004
56* By.........: SL23 Euriware
57* Version....: 4.3
58* Description: FAE 04-758
59*
60*-----------------------------------------------------------------------------
61* Modified...: 07/02/2005
62* By.........: SL23 Euriware
63* Version....: 4.4
64* Description: FAE 04-764
65* Parametric test
66* Checkboard mapping
67*
68*-----------------------------------------------------------------------------
69* Modified...: 09/02/2005
70* By.........: SL23 Euriware
71* Version....: 5.0
72* Description: FAE 05-522
73* Memory space management improvement
74*
75*-----------------------------------------------------------------------------
76* Modified...: 11/02/2005
77* By.........: SL23 Euriware
78* Version....: 5.1
79* Description: FAE 05-523
80* Information display improvement
81*
82*-----------------------------------------------------------------------------
83* Modified...: 31/01/2005
84* By.........: SL23 Euriware
85* Version....: 5.2
86* Description: FAE 06-001
87* Metro Viper recipe changes
88* Use now C_GDW_300MM_WAFER_RADIUS (stc_cst.h) instead of C_C2_WAFER_RADIUS
89*
90*-----------------------------------------------------------------------------
91* Modified...: 29/03/2006
92* By.........: SL23 Euriware
93* Version....: 5.3
94* Description: FAE 06-509
95* MetroLitho recipe
96*
97*-----------------------------------------------------------------------------
98* Modified...: 17/10/2006
99* By.........: SL23 Euriware
100* Version....: 5.4
101* Description: FAE 06-544
102* Log the metro recipe creation in the stc_ptmes_recipe table
103*
104*-----------------------------------------------------------------------------
105* Modified...: 18/12/2006
106* By.........: SL23 Euriware
107* Version....: 5.5
108* Description: FAE 06-583
109* Remove the rule : "Check that none of the 4 cells, adjacents by side to
110* the current cell, is already used as measurement site"
111*
112*-----------------------------------------------------------------------------
113* Modified...: 05/06/2008
114* By.........: sl23
115* Version....: 5.6
116* Description: FAE 08-049 Manage impact of project : 'Photo Target Dice'
117*------------------------------------------------------------------------------
118* Modified...: 02/07/2008
119* By.........: sl23
120* Version....: 5.7
121* Description: FAE 08-049 Bug fix
122*------------------------------------------------------------------------------
123* Modified...: 03/11/2008
124* By.........: sl23
125* Version....: 5.8
126* Description: ECR CR00009884
127* Ability to compute measurement cells for one test type
128* Ability to compute measurement cells even if some recipe have been sent
129*------------------------------------------------------------------------------
130* Modified...: 17/06/2009
131* By.........: sl23
132* Version....: 5.9
133* Description: ECR CR00009640
134* Metro C2 map optimization
135*------------------------------------------------------------------------------
136* Modified...: 05/10/2009
137* By.........: sl23
138* Version....: 5.10
139* Description: SIR CR00011604
140* Metro C2 map optimization WARRANTY
141*------------------------------------------------------------------------------
142* Modified...: 26/01/2010
143* By.........: bf79 STERIA
144* Version....: 5.11
145* Description: SR4-006 Intrafield points management
146* Procedures changes
147* New:
148* PT_ComputePointsDistance()
149* PT_ComputeIfMeasurePoint()
150* PT_ComputeIfMeasurePoints()
151* PT_CheckAndComputeIfMeasurePoints()
152* Updated:
153* PT_ComputeMeasurementCells()
154*
155*-----------------------------------------------------------------------------
156* Modified...: 15/06/2010
157* By.........: STERIA
158* Version....: 5.12
159* Description: Send mail in case of error during intrafield measurement point calculation (SIR 13149, 13150)
160* Procedures changes
161* New:
162* PT_SendErrorMailIfMeasurementPoint()
163* Updated:
164* PT_CheckAndComputeIfMeasurePoints()
165*-----------------------------------------------------------------------------
166* Modified...: 08/07/2010
167* By.........: Steria
168* Version....: 5.13
169* Description: Take into account code review CO-033
170*
171*-----------------------------------------------------------------------------
172* Modified...: 15/07/2010
173* By.........: Steria
174* Version....: 5.14
175* Description: Fix Integration SIR
176*
177*-----------------------------------------------------------------------------
178* Modified...: 10/08/2010
179* By.........: Steria
180* Version....: 5.15
181* Description: Fixed PCSA 8.20 SIR in prod
182*------------------------------------------------------------------------------
183* Modified...: 27/10/2010
184* By.........: sl23
185* Version....: 5.15
186* Description: SIR CR00013012
187*-------------------------------------------------------------------------------
188* Modified...: 24/01/2013
189* By.........: ERI ERW
190* Version....: 5.16
191* Description: ECR14848: ne plus utiliser la machine relay pour la gestion des email C2
192* Retour recette (Suprression d'un saut de ligne (existant) problématique suite à la supression du relaypcsa)
193*------------------------------------------------------------------------------
194* Modified...: 16/04/2013
195* By.........: Sopra Group
196* Version....: 10.0
197* Description: Migration de la base de donnees INGRES vers ORACLE
198*------------------------------------------------------------------------------
199* Modified...: 31/07/2014
200* By.........: F. Thollard (Sopra)
201* Version....: 10.1
202* Description: Adding PT_GetMeasurementPoint and PT_ComputeIdealPoints
203*------------------------------------------------------------------------------
204* Modified...: 21/08/2015
205* By.........: E. Talavet
206* Version....: 10.2
207* Description: Adding Yieldstar OV
208*------------------------------------------------------------------------------
209* Modified...: 25/01/2017
210* By.........: E. Talavet
211* Version....: 10.3
212* Description: SIR18404 choisir 2 fois le meme champ en dernier lieu
213*------------------------------------------------------------------------------
214* Modified...: 17/05/2017
215* By.........: F. Gaillard
216* Version....: 10.4
217* Description: ECR18308 - Completion multiple - Adaptation requete pour STC_PROD_CREATION
218*------------------------------------------------------------------------------
219* Modified...: 28/06/2017
220* By.........: te24
221* Version....: 10.5
222* Description: rattrapage trace SQL
223*------------------------------------------------------------------------------
224* Modified...: 17/07/2017
225* By.........: kocha
226* Version....: 10.6
227* Description: Migration Linux
228* - Ajout de .h manquants
229* - Déplacement de méthodes pour suppression warnings "implicit declaration"
230* - Cast PM_Recipe en Char* pour PT_GetRecipeAndConfig
231*-------------------------------------------------------------------------------
232* Modified...: 13/09/2017
233* By.........: GF102
234* Version....: 10.7
235* Description: Migration Linux
236* - Correction crash : Initialisation pointeur + Suppression double free.
237* - Correction Warning Out Of bound
238* - Initialisation VL_MetroID
239*-------------------------------------------------------------------------------
240* Modified...: 24/01/2018
241* By.........: GF102
242* Version....: 10.8
243* Description: SIR19378 - Pour les mappings IF de type frame, faire la recherche des sites de mesure par nom de label strict (et non avec un like)
244*-------------------------------------------------------------------------------
245* Modified...: 02/07/2018
246* By.........: pt72 - ST
247* Version....: 10.9
248* Description: ECR14721 - Nouveaux templates engineering RING
249* - PT_GetRecipeFields : Récupère maintenant tous les sites et pas uniquement ceux dans le useful radius
250*-------------------------------------------------------------------------------
251* Modified...: 27/04/2018
252* By.........: pt72 - ST
253* Version....: 11.0
254* Description: ECR19431 - Program Metro Quality Booster
255* Début fusion de la métrologie C1,R8 et C2. Modification de pt_compute_intrawafer pour prendre en compte plusieurs algorithmes
256*-------------------------------------------------------------------------------
257* Modified...: 03/07/2018
258* By.........: pt72 - ST
259* Version....: 11.1
260* Description: ECR19486 - Heritage Etendu
261* Modification de l'heritage des templates pour permettre l'ajout de points supplémentaires à un sous-template
262*-------------------------------------------------------------------------------
263* Modified...: 14/09/2018
264* By.........: pt72 - ST
265* Version....: 11.2
266* Description: SIR19511 - Correction d'une erreur qui envoyait un mail d'erreur lors d'un resend avec mapping champ bleu et des jobs existants,
267* Même s'il n'y avait pas de nouveaux champs bleus à placer
268*-------------------------------------------------------------------------------
269* Modified...: 14/09/2018
270* By.........: pt72 - ST
271* Version....: 11.3
272* Description: ECR19486 - Heritage Etendu
273* Correction d'une erreur sur le type d'algorithme des sous-templates étendus
274*-------------------------------------------------------------------------------
275*/
276
277/***************************** INCLUDE *************************************/
278#define DEBUG_PT_CALCUL 0
279
280
281#include <stdio.h>
282#include <stdlib.h>
283#include <string.h>
284#include <ctype.h>
285#include <math.h>
286#include <time.h>
287
288#include <c_commun.h>
289#include <c_tracedb.h>
290#include <c_err.h>
291#include <c_divdb.h>
292#include <stc_err.h>
293#include <stc_cst.h>
294
295#include "pt_cst.h"
296#include "pt_metro_algo.h"
297#include "pt_var.h"
298#include "mem.h"
299#include "info.h"
300
301EXEC SQL INCLUDE stc_tydb.h;
302EXEC SQL INCLUDE c_vardb.h;
303EXEC SQL INCLUDE pt_tydb.h;
304EXEC SQL INCLUDE SQLCA;
305EXEC SQL INCLUDE pt_metro_var.h;
306
307#include "selectIFVoronoi.h"
308#include "pt_type.h"
309#include "pt_util.h"
310#include "pt_write_err.h"
311#include "pt_template_engineering.h"
312#include "c_outil.h"
313
314
315/************************** Procedures **********************************/
316
317/*-------------------------------------------------------------------------------
318* PROGRAM VERSION
319*-------------------------------------------------------------------------------
320*/
321void _version_pt_calcul() {
322 printf("\n##CScodeVer270368 Executable PCSA, version 11.3 du 20/09/2018 [pt_calcul.pc]\n" );
323}
324
325/*---Procedure----------------------------------------------------------------
326* Component..: PT_IsPointOnWafer
327* Version....: 1.0
328* Creation...: 01/2004
329* Author.....: L. SPEYSER Euriware
330* Description: Indicate if a point is located on the wafer area
331*
332*-----------------------------------------------------------------------------
333* Modified...: 31/01/2005
334* By.........: SL23 Euriware
335* Version....: 1.1
336* Description: FAE 06-001
337* Metro Viper recipe changes
338* Use now C_GDW_300MM_WAFER_RADIUS (stc_cst.h) instead of C_C2_WAFER_RADIUS
339*---------------------------------------------------------------------------*/
340
341bool PT_IsPointOnWafer (PM_Trace, PM_X, PM_Y)
342U_Trace PM_Trace; /* In : trace mode */
343float PM_X; /* In : X coordinate of the point in the (absolute) axis system of the wafer */
344float PM_Y; /* In : Y coordinate of the point in the (absolute) axis system of the wafer */
345{
346 /*--------------------------------------------------------------------------
347 * Initialisation
348 *--------------------------------------------------------------------------
349 */
350 EP_Strcpy(PM_Trace.FunctionName, "PT_IsPointOnWafer");
351
352#if DEBUG_PT_CALCUL
353 _StartInfo(PM_Trace.FunctionName, "%f, %f", PM_X, PM_Y);
354#endif
355
356 /*--------------------------------------------------------------------------
357 * Instructions
358 *--------------------------------------------------------------------------
359 */
360 /* Valuate the output parameter */
361 /* Bolean expression = distance(wafer center, point) < wafer radius */
362 bool VL_OnWafer = sqrt (pow (PM_X, 2) + pow (PM_Y, 2)) < C_GDW_300MM_WAFER_RADIUS;
363
364#if DEBUG_PT_CALCUL
365 _EndInfo(PM_Trace.FunctionName, "%d", VL_OnWafer);
366#endif
367
368 return (VL_OnWafer);
369}
370
371
372/*---Procedure----------------------------------------------------------------
373* Component..: PT_IsMaskOptimized
374* Version....: 1.0
375* Creation...: 01/2004
376* Author.....: L. SPEYSER Euriware
377* Description: Indicate if a mask set is optimized
378*
379*-----------------------------------------------------------------------------
380* Modified...:
381* By.........:
382* Version....:
383* Description:
384*
385*---------------------------------------------------------------------------*/
386
387int PT_IsMaskOptimized (PM_Trace, PM_MaskName, PM_Optimized)
388U_Trace PM_Trace; /* in: trace */
389bool *PM_Optimized; /* out : optimization information */
390EXEC SQL BEGIN DECLARE SECTION ;
391char *PM_MaskName; /* in : name of the mask set */
392EXEC SQL END DECLARE SECTION ;
393{
394 int VL_Error;
395 U_InqSQL VL_SqlStatus;
396 char VL_ErrorMsg[256];
397 EXEC SQL BEGIN DECLARE SECTION ;
398 int VL_Optimized;
399 EXEC SQL END DECLARE SECTION ;
400
401 EP_Strcpy(PM_Trace.FunctionName, "PT_IsMaskOptimized");
402
403#if DEBUG_PT_CALCUL
404 _StartInfo(PM_Trace.FunctionName, "%s", PM_MaskName);
405#endif
406
407 /* Init */
408 VL_Error = C_OK;
409 (*PM_Optimized) = 0; /* Default value */
410
411 /* Read in DB the optimization inforamtion */
412 EXEC SQL SELECT MA_OPTI_CREATED
413 INTO :VL_Optimized
414 FROM STC_MASK MA
415 WHERE MA.MA_NAME = :PM_MaskName;
416 Trace_DB("pt_calcul.pc", "ptmeas", "req_1");
417
418 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
419 if (C_OK != VL_Error) {
420 sprintf(VL_ErrorMsg, "Select in DB failed\n");
421 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
422 return (VL_Error);
423 }
424
425 /* Valuate the ouput parameter */
426 (*PM_Optimized) = VL_Optimized;
427
428#if DEBUG_PT_CALCUL
429 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_Optimized));
430#endif
431
432 return (VL_Error);
433}
434
435
436/*---Procedure----------------------------------------------------------------
437* Component..: PT_DoesJobScannerExist
438* Version....: 1.0
439* Creation...: 30/06/2006
440* Author.....: sl23
441* Description: ECR CR00009640
442* Indicates if a job scanner exists for a given mask set
443*
444*-----------------------------------------------------------------------------
445* Modified...:
446* By.........:
447* Version....:
448* Description:
449*
450*---------------------------------------------------------------------------*/
451
452int PT_DoesJobScannerExist (PM_Trace, PM_MaskName, PM_Exists)
453U_Trace PM_Trace; /* In: trace mode */
454bool *PM_Exists; /* Out */
455EXEC SQL BEGIN DECLARE SECTION ;
456char *PM_MaskName; /* In : maskset name */
457EXEC SQL END DECLARE SECTION ;
458{
459 /*--------------------------------------------------------------------------
460 * Declaration
461 *--------------------------------------------------------------------------
462 */
463 int VL_Error;
464 U_InqSQL VL_SqlStatus;
465 char VL_ErrorMsg[256];
466 EXEC SQL BEGIN DECLARE SECTION ;
467 int VL_Count;
468 EXEC SQL END DECLARE SECTION ;
469
470 /*--------------------------------------------------------------------------
471 * Initialisation
472 *--------------------------------------------------------------------------
473 */
474 EP_Strcpy(PM_Trace.FunctionName, "PT_DoesJobScannerExist");
475
476#if DEBUG_PT_CALCUL
477 _StartInfo(PM_Trace.FunctionName, "%s", PM_MaskName);
478#endif
479
480 VL_Error = C_OK;
481 (*PM_Exists) = 0; /* Default value */
482
483 /*--------------------------------------------------------------------------
484 * Instructions
485 *--------------------------------------------------------------------------
486 */
487 /* Count in DB */
488 EXEC SQL SELECT COUNT(*)
489 INTO :VL_Count
490 FROM STC_REQUEST R, STC_PROD_CREATION PCR, STC_PRODUCT P
491 WHERE UPPER(R.MA_NAME) = UPPER(:PM_MaskName)
492 AND PCR.LR_ID = R.LR_ID
493 AND P.PR_NAME || '-' || P.PR_VERSION = PCR.PR_NAME || '-' || PCR.PR_VERSION
494 AND (P.PR_JS_CREATING != 0 OR P.PR_JS_CREATION_OK != 0);
495 Trace_DB("pt_calcul.pc", "ptmeas", "req_2");
496
497 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
498 if (C_OK != VL_Error) {
499 sprintf(VL_ErrorMsg, "Select in DB failed\n");
500 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
501 snprintf(VG_Msg_Dat_Err, 2047, "Database error\n");
502 return (VL_Error);
503 }
504
505 /* Valuate the ouput parameter */
506 if (VL_Count > 0) (*PM_Exists) = 1;
507
508#if DEBUG_PT_CALCUL
509 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_Exists));
510#endif
511
512 return (VL_Error);
513}
514
515
516/*---Procedure----------------------------------------------------------------
517* Component..: PT_DoesCellExist
518* Version....: 1.0
519* Creation...: 01/2004
520* Author.....: L. SPEYSER Euriware
521* Description: Indicate if a cell exists for a given mask set
522*
523*-----------------------------------------------------------------------------
524* Modified...: 21/09/2004
525* By.........: SL23 Euriware
526* Version....: 2.0
527* Description: FAE 04-680
528* Use a U_Mask structure as input parameter instead of a mask set name
529* Take in account the SO_Rank value to get the right cell
530*
531*-----------------------------------------------------------------------------
532* Modified...:
533* By.........:
534* Version....:
535* Description:
536*
537*---------------------------------------------------------------------------*/
538
539int PT_DoesCellExist (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_Exist)
540U_Trace PM_Trace; /* In/Out : trace mode */
541bool *PM_Exist; /* Out : existence information of the cell */
542EXEC SQL BEGIN DECLARE SECTION ;
543U_Mask PM_Mask; /* In : mask set */
544int PM_XCell; /* In : X coordinate of the cell */
545int PM_YCell; /* In : Y coordinate of the cell */
546EXEC SQL END DECLARE SECTION ;
547{
548 /*--------------------------------------------------------------------------
549 * Declaration
550 *--------------------------------------------------------------------------
551 */
552 int VL_Error;
553 U_InqSQL VL_SqlStatus ;
554 char VL_ErrorMsg[256];
555 EXEC SQL BEGIN DECLARE SECTION ;
556 int VL_Count;
557 int VL_FiledFull_Id = C_CELL_FIELDFULL;
558 EXEC SQL END DECLARE SECTION ;
559
560 /*--------------------------------------------------------------------------
561 * Initialisation
562 *--------------------------------------------------------------------------
563 */
564 EP_Strcpy(PM_Trace.FunctionName, "PT_DoesCellExist");
565
566#if DEBUG_PT_CALCUL
567 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d", PM_Mask.MA_Name, PM_XCell, PM_YCell);
568#endif
569
570 VL_Error = C_OK;
571 (*PM_Exist) = 0; /* Default value */
572
573 /*--------------------------------------------------------------------------
574 * Instructions
575 *--------------------------------------------------------------------------
576 */
577 /* Count the number of cell located at the given coordinates */
578 EXEC SQL SELECT COUNT(*)
579 INTO :VL_Count
580 FROM STC_CELL_LIST CL
581 WHERE CL.MA_NAME = :PM_Mask.MA_Name
582 AND CL.CL_CELL_TYPE = :VL_FiledFull_Id /* filter on the cell type = FIELDFULL */
583 AND CL.SO_RANK = :PM_Mask.SO_Rank
584 AND CL.CL_X = :PM_XCell
585 AND CL.CL_Y = :PM_YCell;
586 Trace_DB("pt_calcul.pc", "ptmeas", "req_3");
587
588 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
589 if (C_OK != VL_Error) {
590 sprintf(VL_ErrorMsg, "Select in DB failed\n");
591 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
592 return (VL_Error);
593 }
594
595 /* Valuate the ouput parameter */
596 if (1 != VL_Count)
597 (*PM_Exist) = 0;
598 else
599 (*PM_Exist) = 1;
600
601#if DEBUG_PT_CALCUL
602 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_Exist));
603#endif
604
605 return (VL_Error);
606}
607
608
609/*---Procedure----------------------------------------------------------------
610* Component..: PT_IsCellExposed
611* Version....: 1.0
612* Creation...: 21/09/2004
613* Author.....: SL23 Euriware
614* Description: FAE 04-680
615* Indicate if a cell is exposed
616*
617*-----------------------------------------------------------------------------
618* Modified...: 05/06/2008
619* By.........: sl23
620* Version....: 1.1
621* Description: FAE 08-049 Manage impact of project : 'Photo Target Dice'
622* Disable selection of field used as corner (C_CELL_NOFIELDCORNER)
623* by Photo (corner means 'not exposed')
624*------------------------------------------------------------------------------
625* Modified...:
626* By.........:
627* Version....:
628* Description:
629*
630*---------------------------------------------------------------------------*/
631int PT_IsCellExposed (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_Exposed)
632U_Trace PM_Trace; /* In/Out : trace mode */
633EXEC SQL BEGIN DECLARE SECTION ;
634int *PM_Exposed; /* Out : exposition information of the cell */
635U_Mask PM_Mask; /* In : mask set */
636int PM_XCell; /* In : X coordinate of the cell */
637int PM_YCell; /* In : Y coordinate of the cell */
638EXEC SQL END DECLARE SECTION ;
639{
640 /*--------------------------------------------------------------------------
641 * Declaration
642 *--------------------------------------------------------------------------
643 */
644 int VL_Error;
645 U_InqSQL VL_SqlStatus ;
646 char VL_ErrorMsg[256];
647 EXEC SQL BEGIN DECLARE SECTION ;
648 int VL_Count;
649 int VL_Field_Id = C_CELL_FIELD;
650 int VL_NoFieldEdge_Id = C_CELL_NOFIELDEDGE;
651 int VL_NoFieldCorner_Id = C_CELL_NOFIELDCORNER;
652 int VL_NoFieldLaserMark_Id = C_CELL_NOFIELDLASERMARK;
653 int VL_NoFieldMetro_Id = C_CELL_NOFIELDMETRO;
654 EXEC SQL END DECLARE SECTION ;
655
656 /*--------------------------------------------------------------------------
657 * Initialisation
658 *--------------------------------------------------------------------------
659 */
660 EP_Strcpy(PM_Trace.FunctionName, "PT_IsCellExposed");
661
662#if DEBUG_PT_CALCUL
663 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d", PM_Mask.MA_Name, PM_XCell, PM_YCell);
664#endif
665
666 VL_Error = C_OK;
667 (*PM_Exposed) = 0; /* Default value */
668
669 /* Get the number of exposed field at this location */
670 /* Disable selection of field used as corner (C_CELL_NOFIELDCORNER) by Photo (corner means 'not exposed') */
671 VL_Count = 0;
672
673 /*--------------------------------------------------------------------------
674 * Instructions
675 *--------------------------------------------------------------------------
676 */
677 EXEC SQL
678 SELECT COUNT(*)
679 INTO :VL_Count
680 FROM STC_CELL_LIST CL
681 WHERE CL.MA_NAME = :PM_Mask.MA_Name
682 AND CL.SO_RANK = :PM_Mask.SO_Rank
683 AND CL.CL_CELL_TYPE IN (:VL_Field_Id, :VL_NoFieldMetro_Id) /* filter on the cell type = FIELD or NOFIELDMETRO */
684 AND CL.CL_X = :PM_XCell
685 AND CL.CL_Y = :PM_YCell
686 AND NOT EXISTS (SELECT 1
687 FROM STC_CELL_LIST CL2
688 WHERE CL2.MA_NAME = :PM_Mask.MA_Name
689 AND CL2.SO_RANK = :PM_Mask.SO_Rank
690 AND CL2.CL_CELL_TYPE in (:VL_NoFieldCorner_Id, :VL_NoFieldLaserMark_Id, :VL_NoFieldEdge_Id) /* filter on the cell type = NOFIELD* */
691 AND CL2.CL_X = :PM_XCell
692 AND CL2.CL_Y = :PM_YCell);
693 Trace_DB("pt_calcul.pc", "ptmeas", "req_4");
694
695 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
696 if (C_OK != VL_Error) {
697 sprintf(VL_ErrorMsg, "Select in DB failed\n");
698 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
699 return (VL_Error);
700 }
701
702 /* Valuate the ouput parameter */
703 if (VL_Count > 0)
704 (*PM_Exposed) = 1;
705 else
706 (*PM_Exposed) = 0;
707
708#if DEBUG_PT_CALCUL
709 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_Exposed));
710#endif
711
712 return (VL_Error);
713}
714
715
716/*---Procedure----------------------------------------------------------------
717* Component..: PT_IsCellAvailableForExpo
718* Version....: 1.0
719* Creation...: 18/06/2009
720* Author.....: sl23
721* Description: ECR CR00009640
722* Metro C2 map optimization
723*---------------------------------------------------------------------------*/
724
725int PT_IsCellAvailableForExpo (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_AvailableForExpo)
726U_Trace PM_Trace; /* In/Out : trace mode */
727EXEC SQL BEGIN DECLARE SECTION ;
728U_Mask PM_Mask; /* In : mask set */
729int PM_XCell; /* In : X coordinate of the cell */
730int PM_YCell; /* In : Y coordinate of the cell */
731int *PM_AvailableForExpo; /* Out : can the cell be exposed? */
732EXEC SQL END DECLARE SECTION ;
733{
734 /*--------------------------------------------------------------------------
735 * Declaration
736 *--------------------------------------------------------------------------
737 */
738 int VL_Error;
739 U_InqSQL VL_SqlStatus ;
740 char VL_ErrorMsg[256];
741 EXEC SQL BEGIN DECLARE SECTION ;
742 int VL_Count;
743 int VL_NoFieldEdge_Id = C_CELL_NOFIELDEDGE;
744 int VL_NoFieldCorner_Id = C_CELL_NOFIELDCORNER;
745 int VL_NoFieldLaserMark_Id = C_CELL_NOFIELDLASERMARK;
746 EXEC SQL END DECLARE SECTION ;
747
748 /*--------------------------------------------------------------------------
749 * Initialisation
750 *--------------------------------------------------------------------------
751 */
752 EP_Strcpy(PM_Trace.FunctionName, "PT_IsCellAvailableForExpo");
753
754#if DEBUG_PT_CALCUL
755 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d", PM_Mask.MA_Name, PM_XCell, PM_YCell);
756#endif
757
758 VL_Error = C_OK;
759 (*PM_AvailableForExpo) = 0; /* Default value */
760
761 /*--------------------------------------------------------------------------
762 * Instructions
763 *--------------------------------------------------------------------------
764 */
765 /* Get the number of exposed field at this location */
766 /* Disable selection of field used as corner (C_CELL_NOFIELDCORNER) by Photo (corner means 'not exposed') */
767 VL_Count = 0;
768
769 EXEC SQL SELECT COUNT(*)
770 INTO :VL_Count
771 FROM STC_CELL_LIST CL
772 WHERE CL.MA_NAME = :PM_Mask.MA_Name
773 AND CL.SO_RANK = :PM_Mask.SO_Rank
774 AND CL.CL_CELL_TYPE = :VL_NoFieldEdge_Id /* filter on the cell type = NOFIELDEDGE */
775 AND CL.CL_X = :PM_XCell
776 AND CL.CL_Y = :PM_YCell
777 AND NOT EXISTS (SELECT 1
778 FROM STC_CELL_LIST CL2
779 WHERE CL2.MA_NAME = :PM_Mask.MA_Name
780 AND CL2.SO_RANK = :PM_Mask.SO_Rank
781 AND CL2.CL_CELL_TYPE in (:VL_NoFieldCorner_Id, :VL_NoFieldLaserMark_Id) /* filter on the cell type = NOFIELDCORNER, NOFIELDLASERMARK */
782 AND CL2.CL_X = :PM_XCell
783 AND CL2.CL_Y = :PM_YCell);
784 Trace_DB("pt_calcul.pc", "ptmeas", "req_5");
785
786 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
787 if (C_OK != VL_Error) {
788 sprintf(VL_ErrorMsg, "Select in DB failed\n");
789 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
790 return (VL_Error);
791 }
792
793 /* Valuate the ouput parameter */
794 if (0 < VL_Count)
795 (*PM_AvailableForExpo) = 1;
796 else
797 (*PM_AvailableForExpo) = 0;
798
799#if DEBUG_PT_CALCUL
800 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_AvailableForExpo));
801#endif
802
803 return (VL_Error);
804}
805
806
807/*---Procedure----------------------------------------------------------------
808* Component..: PT_RevertPhotoMap
809* Version....: 1.0
810* Creation...: 01/07/2009
811* Author.....: sl23
812* Description: ECR CR00009640
813* Metro C2 map optimization
814*---------------------------------------------------------------------------*/
815int PT_RevertPhotoMap (PM_Trace, PM_MaskName, PM_OldImageId, PM_OldImageName, PM_NewImageId, PM_NewImageName)
816U_Trace PM_Trace; /* In/Out : trace mode */
817EXEC SQL BEGIN DECLARE SECTION ;
818char *PM_MaskName; /* In : maskset name */
819int PM_OldImageId; /* In : id of the image to change */
820int PM_NewImageId; /* In : id of the new image to set */
821char *PM_OldImageName; /* In : name of the image to change */
822char *PM_NewImageName; /* In : name of the image to set */
823EXEC SQL END DECLARE SECTION ;
824{
825 /*--------------------------------------------------------------------------
826 * Declaration
827 *--------------------------------------------------------------------------
828 */
829 int VL_Error;
830 U_InqSQL VL_SqlStatus ;
831 char VL_ErrorMsg[256];
832 int VL_RowCount;
833 EXEC SQL BEGIN DECLARE SECTION ;
834 char VL_ActionMsg[256];
835 EXEC SQL END DECLARE SECTION ;
836
837 /*--------------------------------------------------------------------------
838 * Initialisation
839 *--------------------------------------------------------------------------
840 */
841 EP_Strcpy(PM_Trace.FunctionName, "PT_RevertPhotoMap");
842
843#if DEBUG_PT_CALCUL
844 _StartInfo(PM_Trace.FunctionName, "%s, %d, %s, %d, %s", PM_MaskName, PM_OldImageId, PM_OldImageName, PM_NewImageId, PM_NewImageName);
845#endif
846
847 VL_Error = C_OK;
848
849 /*--------------------------------------------------------------------------
850 * Instructions
851 *--------------------------------------------------------------------------
852 */
853 /* Insert info in stc_mask_log table */
854 EXEC SQL
855 INSERT INTO STC_MASK_LOG(
856 MA_NAME,
857 MA_ACTION,
858 US_ID,
859 MA_ACTION_DATE,
860 MA_ACTION_RESULT)
861 SELECT CL.MA_NAME,
862 'Reset Metro required expo => Cell(' || TO_CHAR(CL.CL_X) || ', ' || TO_CHAR(CL.CL_Y) || ') : revert image ' || :PM_OldImageName || ' back to ' || :PM_NewImageName,
863 604,
864 SYSDATE,
865 'OK'
866 FROM STC_CELL_LIST CL
867 WHERE CL.MA_NAME = :PM_MaskName
868 AND CL.CL_CELL_TYPE = :PM_OldImageId;
869 Trace_DB("pt_calcul.pc", "ptmeas", "req_6");
870
871 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
872 if (C_OK != VL_Error) {
873 sprintf(VL_ErrorMsg, "Insert in DB failed\n");
874 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
875 return (VL_Error);
876 }
877
878 /* Update the stc_cell_list table */
879 EXEC SQL
880 UPDATE STC_CELL_LIST
881 SET CL_CELL_TYPE = :PM_NewImageId
882 WHERE MA_NAME = :PM_MaskName
883 AND CL_CELL_TYPE = :PM_OldImageId;
884 Trace_DB("pt_calcul.pc", "ptmeas", "req_7");
885
886 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
887 if (C_OK != VL_Error) {
888 sprintf(VL_ErrorMsg, "Update in DB failed\n");
889 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
890 return (VL_Error);
891 }
892
893 VL_RowCount = VL_SqlStatus.RowCount;
894
895#if DEBUG_PT_CALCUL
896 _EndInfo(PM_Trace.FunctionName, "%d", VL_RowCount);
897#endif
898
899 return (VL_Error);
900}
901
902
903/*---Procedure----------------------------------------------------------------
904* Component..: PT_UpdatePhotoMap
905* Version....: 1.0
906* Creation...: 18/06/2009
907* Author.....: sl23
908* Description: ECR CR00009640
909* Metro C2 map optimization
910*------------------------------------------------------------------------------
911* Modified...: 27/10/2010
912* By.........: sl23
913* Version....: 1.1
914* Description: SIR CR00013012
915*------------------------------------------------------------------------------
916* Modified...: 25/08/2014
917* By.........: Sopra
918* Version....: 1.2
919* Description: Log the action into STC_MASK_LOG.
920* Action : Update the current cell type to a metro field, for a given
921* maskset name, when the cell above requires exposition
922* below and that the current field is not flag as a
923* corner or a laser mark.
924*------------------------------------------------------------------------------
925*/
926int PT_UpdatePhotoMap (PM_Trace, PM_MaskName, PM_OldImageId, PM_OldImageName, PM_NewImageId, PM_NewImageName)
927U_Trace PM_Trace; /* In/Out : trace mode */
928EXEC SQL BEGIN DECLARE SECTION ;
929char *PM_MaskName; /* In : mask set */
930int PM_OldImageId; /* In : id of the image to change */
931int PM_NewImageId; /* In : id of the new image to set */
932EXEC SQL END DECLARE SECTION ;
933char *PM_OldImageName; /* In : mask set */
934char *PM_NewImageName; /* In : mask set */
935{
936 /*--------------------------------------------------------------------------
937 * Declaration
938 *--------------------------------------------------------------------------
939 */
940 int VL_Error; // error flag
941 U_InqSQL VL_SqlStatus ; // sql status returned after a sql query
942 char VL_ErrorMsg[256]; // error message
943 int VL_RowCount; // number of row retrieved from the database
944 EXEC SQL BEGIN DECLARE SECTION ;
945 int VL_NoFieldCorner_Id = C_CELL_NOFIELDCORNER; // position of the cell in the wafer
946 int VL_NoFieldLaserMark_Id = C_CELL_NOFIELDLASERMARK; // position of the cell in the wafer
947 int VL_NoFieldMetro_Id = C_CELL_NOFIELDMETRO ; // position of the cell in the wafer
948 EXEC SQL END DECLARE SECTION ;
949
950 EP_Strcpy(PM_Trace.FunctionName, "PT_UpdatePhotoMap");
951
952 /*--------------------------------------------------------------------------
953 * Initialisation
954 *--------------------------------------------------------------------------
955 */
956#if DEBUG_PT_CALCUL
957 _StartInfo(PM_Trace.FunctionName, "%s, %d, %s, %d, %s", PM_MaskName, PM_OldImageId, PM_OldImageName, PM_NewImageId, PM_NewImageName);
958#endif
959
960 VL_Error = C_OK;
961
962 /*--------------------------------------------------------------------------
963 * Instructions
964 *--------------------------------------------------------------------------
965 */
966 /* Update the stc_cell_list table */
967 /* Convert NOFIELDEDGE image into NOFIELDMETRO image when missing */
968 /* for a template requiring additional exposition cells. */
969 EXEC SQL
970 UPDATE STC_CELL_LIST CL
971 SET CL_CELL_TYPE = :VL_NoFieldMetro_Id
972 WHERE UPPER(CL.MA_NAME) = UPPER(:PM_MaskName)
973 AND EXISTS ( SELECT 1
974 FROM STC_PTMES_MAPPING_IW PMIW, STC_PTMES_MAPPING_CELL PMC, STC_PTMES_TEMPLATE_IW PTIW
975 WHERE UPPER(PMIW.MA_NAME) = UPPER(CL.MA_NAME)
976 AND PMC.MIW_ID = PMIW.MIW_ID
977 AND PMIW.MIW_STATE = 1
978 AND PMC.MC_X = CL.CL_X
979 AND (PMC.MC_Y - 1) = CL.CL_Y
980 AND PTIW.TIW_NAME = PMIW.TIW_NAME
981 AND PTIW.TIW_EXPO_BELOW_REQUIRED = '1'
982 )
983 AND CL.CL_CELL_TYPE = :PM_OldImageId
984 /* CELL BELOW DOES NOT HAVE NOFIELDCORNER OR NOFIELDLASERMARK IMAGE */
985 AND NOT EXISTS (SELECT 1
986 FROM STC_CELL_LIST CL2
987 WHERE UPPER(CL2.MA_NAME) = UPPER(CL.MA_NAME)
988 AND CL2.CL_X = CL.CL_X
989 AND CL2.CL_Y = CL.CL_Y
990 AND CL2.CL_CELL_TYPE IN (:VL_NoFieldCorner_Id, :VL_NoFieldLaserMark_Id)
991 );
992 Trace_DB("pt_calcul.pc", "ptmeas", "req_8");
993
994 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
995 if (C_OK != VL_Error) {
996 sprintf(VL_ErrorMsg, "Update in DB failed\n");
997 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
998 return (VL_Error);
999 }
1000
1001 VL_RowCount = VL_SqlStatus.RowCount;
1002
1003 /* Insert info in stc_mask_log table */
1004 EXEC SQL
1005 INSERT INTO STC_MASK_LOG(
1006 MA_NAME,
1007 MA_ACTION,
1008 US_ID,
1009 MA_ACTION_DATE,
1010 MA_ACTION_RESULT)
1011 SELECT CL.MA_NAME, 'Add Metro required expo => Cell(' || TO_CHAR(CL.CL_X) || ', ' || TO_CHAR(CL.CL_Y) || ') : convert image ' || :PM_OldImageName || ' into ' || :PM_NewImageName, 604, SYSDATE, 'OK'
1012 FROM STC_CELL_LIST CL
1013 WHERE CL.MA_NAME = :PM_MaskName
1014 AND CL.CL_CELL_TYPE = :PM_NewImageId;
1015 Trace_DB("pt_calcul.pc", "ptmeas", "req_9");
1016
1017 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
1018 if (C_OK != VL_Error) {
1019 sprintf(VL_ErrorMsg, "Insert in DB failed\n");
1020 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1021 return (VL_Error);
1022 }
1023
1024#if DEBUG_PT_CALCUL
1025 _EndInfo(PM_Trace.FunctionName, "%d", VL_RowCount);
1026#endif
1027
1028 return (VL_Error);
1029}
1030
1031
1032/*---Procedure----------------------------------------------------------------
1033* Component..: PT_ComputeCellContainingPoint
1034* Version....: 1.0
1035* Creation...: 26/05/2004
1036* Author.....: L. SPEYSER Euriware
1037* Description: Compute the coordinates of the cell containing a given point
1038* for a given mask set
1039*
1040*-----------------------------------------------------------------------------
1041* Modified...:
1042* By.........:
1043* Version....:
1044* Description:
1045*
1046*---------------------------------------------------------------------------*/
1047int PT_ComputeCellContainingPoint (PM_Trace, PM_Mask, PM_Point, PM_XCell, PM_YCell)
1048U_Trace PM_Trace; /* In : trace mode */
1049U_Mask PM_Mask; /* In : mask set */
1050U_PtmesTemplatePoint PM_Point; /* In : ideal measurement point */
1051int *PM_XCell; /* Out : X coordinate of the cell */
1052int *PM_YCell; /* Out : Y coordinate of the cell */
1053{
1054 /*--------------------------------------------------------------------------
1055 * Declaration
1056 *--------------------------------------------------------------------------
1057 */
1058 int VL_Error;
1059 U_InqSQL VL_SqlStatus;
1060 char VL_ErrorMsg[256];
1061 float VL_X;
1062 float VL_Y;
1063
1064 /*--------------------------------------------------------------------------
1065 * Initialisation
1066 *--------------------------------------------------------------------------
1067 */
1068 EP_Strcpy(PM_Trace.FunctionName, "PT_ComputeCellContainingPoint");
1069
1070#if DEBUG_PT_CALCUL
1071 _StartInfo(PM_Trace.FunctionName, "%s, %f, %f", PM_Mask.MA_Name, PM_Point.Tpw_X, PM_Point.Tpw_Y);
1072#endif
1073
1074 /*--------------------------------------------------------------------------
1075 * Instructions
1076 *--------------------------------------------------------------------------
1077 */
1078 /* Check the validity of the point */
1079 if (0 == PT_IsPointOnWafer(PM_Trace, PM_Point.Tpw_X, PM_Point.Tpw_Y)) {
1080 sprintf(VL_ErrorMsg, "The point (%f, %f) is not located on the surface of the wafer\n", PM_Point.Tpw_X, PM_Point.Tpw_Y);
1081 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1082 VL_Error = C_NOT_OK;
1083 return (VL_Error);
1084 }
1085
1086 /* Compute the X coordinate of the cell containing the point */
1087 VL_X = (PM_Point.Tpw_X - PM_Mask.MA_ShiftX) / PM_Mask.MA_XOverlap;
1088
1089 /* Adjust the X coordinate value using a round (dynamic int cast) */
1090 if (VL_X < 0)
1091 (*PM_XCell) = VL_X - 0.5;
1092 else
1093 (*PM_XCell) = VL_X + 0.5;
1094
1095
1096 /* Compute the Y coordinate of the cell containing the point */
1097 VL_Y = (PM_Point.Tpw_Y - PM_Mask.MA_ShiftY) / PM_Mask.MA_YOverlap;
1098
1099 /* Adjust the Y coordinate value using a round (dynamic int cast) */
1100 if (VL_Y < 0)
1101 (*PM_YCell) = VL_Y - 0.5;
1102 else
1103 (*PM_YCell) = VL_Y + 0.5;
1104
1105 /* Check the existence of the cell on the mask set mapping */
1106 bool VL_Exist = 0;
1107 VL_Error = PT_DoesCellExist(PM_Trace, PM_Mask, (*PM_XCell), (*PM_YCell), &VL_Exist);
1108
1109 if (C_OK != VL_Error || 0 == VL_Exist) {
1110 sprintf(VL_ErrorMsg, "The cell (%d, %d) does not exist\n", (*PM_XCell), (*PM_YCell));
1111 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1112 VL_Error = C_NOT_OK;
1113 return (VL_Error);
1114 }
1115
1116#if DEBUG_PT_CALCUL
1117 _EndInfo(PM_Trace.FunctionName, "%d, %d", (*PM_XCell), (*PM_YCell));
1118#endif
1119
1120 return (VL_Error);
1121}
1122
1123
1124/*---Procedure----------------------------------------------------------------
1125* Component..: PT_GetCellLimits
1126* Version....: 1.0
1127* Creation...: 01/2004
1128* Author.....: L. SPEYSER Euriware
1129* Description: Compute the X (left, right) and Y (bottom, top) coordinates of
1130* the boundary of a cell in the absolute system axis of the wafer
1131* for a given mask set
1132*
1133*-----------------------------------------------------------------------------
1134* Modified...: 28/05/2004
1135* By.........: L. SPEYSER Euriware
1136* Version....: 2.0
1137* Description: Crolles 2 Parametric test
1138* Rework
1139*
1140*---------------------------------------------------------------------------*/
1141
1142int PT_GetCellLimits (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_XLeft, PM_XRight, PM_YBottom, PM_YTop)
1143U_Trace PM_Trace; /* In : trace mode */
1144U_Mask PM_Mask; /* In : mask set */
1145int PM_XCell; /* In : X coordinate of the cell */
1146int PM_YCell; /* In : Y coordinate of the cell */
1147double *PM_XLeft; /* Out : left X limit of the cell in the (absolute) axis system of the wafer */
1148double *PM_XRight; /* Out : right X limit of the cell in the (absolute) axis system of the wafer */
1149double *PM_YBottom; /* Out : bottom Y limit of the cell in the (absolute) axis system of the wafer */
1150double *PM_YTop; /* Out : top Y limit of the cell in the (absolute) axis system of the wafer */
1151{
1152 /*--------------------------------------------------------------------------
1153 * Declaration
1154 *--------------------------------------------------------------------------
1155 */
1156 int VL_Error;
1157 U_InqSQL VL_SqlStatus;
1158 char VL_ErrorMsg[256];
1159
1160 /*--------------------------------------------------------------------------
1161 * Initialisation
1162 *--------------------------------------------------------------------------
1163 */
1164 EP_Strcpy(PM_Trace.FunctionName, "PT_GetCellLimits");
1165
1166#if DEBUG_PT_CALCUL
1167 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d", PM_Mask.MA_Name, PM_XCell, PM_YCell);
1168#endif
1169
1170 /*--------------------------------------------------------------------------
1171 * Instructions
1172 *--------------------------------------------------------------------------
1173 */
1174 /* Check the existence of the cell on the mask set mapping */
1175 bool PM_Exist = 0;
1176 VL_Error = PT_DoesCellExist(PM_Trace, PM_Mask, PM_XCell, PM_YCell, &PM_Exist);
1177
1178 if (C_OK != VL_Error || 0 == PM_Exist) {
1179 sprintf(VL_ErrorMsg, "The cell (%d, %d) does not exist\n", PM_XCell, PM_YCell);
1180 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1181 VL_Error = C_NOT_OK;
1182 return (VL_Error);
1183 }
1184
1185 /* Compute the X (left, right) and Y (bottom, top) limits of the cell */
1186 (*PM_XLeft) = PM_Mask.MA_ShiftX + (PM_XCell - 0.5) * PM_Mask.MA_XOverlap;
1187 (*PM_YBottom) = PM_Mask.MA_ShiftY + (PM_YCell - 0.5) * PM_Mask.MA_YOverlap;
1188 (*PM_XRight) = (*PM_XLeft) + PM_Mask.MA_XOverlap;
1189 (*PM_YTop) = (*PM_YBottom) + PM_Mask.MA_YOverlap;
1190
1191#if DEBUG_PT_CALCUL
1192 _EndInfo(PM_Trace.FunctionName, "%f, %f, %f, %f", (*PM_XLeft), (*PM_XRight), (*PM_YBottom), (*PM_YTop));
1193#endif
1194
1195 return (VL_Error);
1196}
1197
1198
1199/*---Procedure----------------------------------------------------------------
1200* Component..: PT_IsCellInUsefulArea
1201* Version....: 1.0
1202* Creation...: 01/2004
1203* Author.....: L. SPEYSER Euriware
1204* Description: Indicate if a cell is included in the useful area of a given
1205* mask set
1206*-----------------------------------------------------------------------------
1207* Modified...: 28/05/2004
1208* By.........: L. SPEYSER Euriware
1209* Version....: 2.0
1210* Description: Crolles 2 Parametric test
1211* Rework
1212*---------------------------------------------------------------------------*/
1213int PT_IsCellInUsefulArea (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_UsefulRadius, PM_In)
1214U_Trace PM_Trace; /* In : trace mode */
1215U_Mask PM_Mask; /* In : mask set */
1216int PM_XCell; /* In : X coordinate of the cell */
1217int PM_YCell; /* In : Y coordinate of the cell */
1218double PM_UsefulRadius; /* In : value of the useful radius */
1219bool *PM_In; /* Out : cell included in the useful area */
1220{
1221 /*--------------------------------------------------------------------------
1222 * Declaration
1223 *--------------------------------------------------------------------------
1224 */
1225 int VL_Error;
1226 char VL_ErrorMsg[256];
1227
1228 /*--------------------------------------------------------------------------
1229 * Initialisation
1230 *--------------------------------------------------------------------------
1231 */
1232 EP_Strcpy(PM_Trace.FunctionName, "PT_IsCellInUsefulArea");
1233
1234#if DEBUG_PT_CALCUL
1235 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d, %f", PM_Mask.MA_Name, PM_XCell, PM_YCell, PM_UsefulRadius);
1236#endif
1237
1238 /* Default value for the ouput parameter */
1239 (*PM_In) = 0;
1240
1241 /*--------------------------------------------------------------------------
1242 * Instructions
1243 *--------------------------------------------------------------------------
1244 */
1245 /* Check the existence of the cell on the mask set mapping */
1246 bool VL_Exist = 0;
1247 VL_Error = PT_DoesCellExist(PM_Trace, PM_Mask, PM_XCell, PM_YCell, &VL_Exist);
1248
1249 if (C_OK != VL_Error) {
1250 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) does not exist\n", PM_XCell, PM_YCell);
1251 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1252 return (VL_Error);
1253 }
1254
1255 /* Valuate the ouput parameter */
1256 if (0 == VL_Exist)
1257 (*PM_In) = 0;
1258 else {
1259 /* Compute the X (left, right) and Y (bottom, top) limits of the cell */
1260 double VL_XLeft, VL_XRight, VL_YBottom, VL_YTop;
1261 VL_Error = PT_GetCellLimits(PM_Trace, PM_Mask, PM_XCell, PM_YCell, &VL_XLeft, &VL_XRight, &VL_YBottom, &VL_YTop);
1262
1263 if (C_OK != VL_Error) {
1264 sprintf(VL_ErrorMsg, "Unable to compute the X (left, right) and Y (bottom, top) limits of the cell (%d, %d)\n", PM_XCell, PM_YCell);
1265 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1266 return (VL_Error);
1267 }
1268
1269 /* Valuate the ouput parameter */
1270 /* Boolean expression = distance(wafer center, most distant corner of the cell) < useful radius */
1271 (*PM_In) = sqrt (pow (max (fabs (VL_XLeft), fabs (VL_XRight)), 2)
1272 + pow (max (fabs (VL_YBottom), fabs (VL_YTop)), 2)) <= PM_UsefulRadius;
1273 }
1274
1275#if DEBUG_PT_CALCUL
1276 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_In));
1277#endif
1278
1279 return (VL_Error);
1280}
1281
1282
1283/*---Procedure----------------------------------------------------------------
1284* Component..: PT_AreCellsInUsefulArea
1285* Version....: 1.0
1286* Creation...: 14/12/2004
1287* Author.....: SL23 Euriware
1288* Description: FAE 04-758
1289* Indicate if cells are included in the useful area of a given
1290* mask set
1291*
1292*-----------------------------------------------------------------------------
1293* Modified...: 07/02/2005
1294* By.........: SL23 Euriware
1295* Version....: 1.1
1296* Description: FAE 04-764
1297* Parametric test
1298* Checkboard mapping
1299* Return also the number of cell included in the useful area
1300*---------------------------------------------------------------------------*/
1301
1302int PT_AreCellsInUsefulArea (PM_Trace, PM_Mask, PM_Cells, PM_NumOfCell, PM_UsefulRadius, PM_In, PM_NumOfIn)
1303U_Trace PM_Trace; /* in : trace */
1304U_Mask PM_Mask; /* in : mask set */
1305U_CellList *PM_Cells; /* in : X coordinate of the cell */
1306int PM_NumOfCell; /* in : X coordinate of the cell */
1307double PM_UsefulRadius; /* in : value of the useful radius */
1308int **PM_In; /* out : cell included in the useful area */
1309int *PM_NumOfIn; /* out : number of cell included in the useful area */
1310{
1311 int VL_Error;
1312 char VL_ErrorMsg[256];
1313 int VL_i;
1314
1315 EP_Strcpy(PM_Trace.FunctionName, "PT_AreCellsInUsefulArea");
1316
1317#if DEBUG_PT_CALCUL
1318 _StartInfo(PM_Trace.FunctionName, "%s, %d, %f", PM_Mask.MA_Name, PM_NumOfCell, PM_UsefulRadius);
1319#endif
1320
1321 /* Init */
1322 VL_Error = C_OK;
1323 (*PM_In) = NULL;
1324 (*PM_NumOfIn) = 0;
1325
1326 /* Check that the input array is not empty */
1327 if (0 == PM_NumOfCell || NULL == PM_Cells)
1328 return (VL_Error);
1329
1330 /* Allocate memory space */
1331 (*PM_In) = (int *) _Calloc(PM_Trace.FunctionName, PM_NumOfCell, sizeof(int));
1332 if (NULL == (*PM_In)) {
1333 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
1334 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1335 VL_Error = C_NOT_OK;
1336 return (VL_Error);
1337 }
1338
1339 /* Loop on the input cells list */
1340 for (VL_i = 0; VL_i < PM_NumOfCell; VL_i++) {
1341 VL_Error = PT_IsCellInUsefulArea(PM_Trace, PM_Mask, PM_Cells[VL_i].CL_X, PM_Cells[VL_i].CL_Y, PM_UsefulRadius, &((*PM_In)[VL_i]));
1342 if (C_OK != VL_Error) {
1343 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) does not exist\n", PM_Cells[VL_i].CL_X, PM_Cells[VL_i].CL_Y);
1344 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1345 /* Free memory space */
1346 _Free(PM_Trace.FunctionName, *PM_In);
1347 return (VL_Error);
1348 }
1349 if (0 != (*PM_In)[VL_i])
1350 (*PM_NumOfIn)++;
1351 }
1352
1353#if DEBUG_PT_CALCUL
1354 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_NumOfIn));
1355#endif
1356
1357 return (VL_Error);
1358}
1359
1360
1361/*---Procedure----------------------------------------------------------------
1362* Component..: PT_NumOfCornerInUsefulArea
1363* Version....: 1.0
1364* Creation...: 01/2004
1365* Author.....: L. SPEYSER Euriware
1366* Description: Compute the number of corner of a cell included in the useful
1367* area of a given mask set
1368*
1369*-----------------------------------------------------------------------------
1370* Modified...: 28/05/2004
1371* By.........: L. SPEYSER Euriware
1372* Version....: 2.0
1373* Description: Crolles 2 Parametric test
1374* Rework
1375*---------------------------------------------------------------------------*/
1376
1377int PT_NumOfCornerInUsefulArea (PM_Trace, PM_Mask, PM_XCell, PM_YCell, PM_UsefulRadius, PM_NumCornerIn)
1378U_Trace PM_Trace; /* in : trace */
1379U_Mask PM_Mask; /* in : mask set */
1380int PM_XCell; /* in : X coordinate of a cell */
1381int PM_YCell; /* in : Y coordinate of a cell */
1382float PM_UsefulRadius; /* in : useful radius value */
1383int *PM_NumCornerIn; /* out : number of corner [0..4] included in the useful area of the wafer */
1384{
1385 int VL_Error;
1386 char VL_ErrorMsg[256];
1387
1388 EP_Strcpy(PM_Trace.FunctionName, "PT_NumOfCornerInUsefulArea");
1389
1390#if DEBUG_PT_CALCUL
1391 _StartInfo(PM_Trace.FunctionName, "%s, %d, %d, %f", PM_Mask.MA_Name, PM_XCell, PM_YCell, PM_UsefulRadius);
1392#endif
1393
1394 /* Valuate by default the ouput parameter */
1395 (*PM_NumCornerIn) = 0;
1396
1397 /* Check the existence of the cell on the mask set mapping */
1398 bool VL_Exist = 0;
1399 VL_Error = PT_DoesCellExist(PM_Trace, PM_Mask, PM_XCell, PM_YCell, &VL_Exist);
1400 if (C_OK != VL_Error) {
1401 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) does not exist\n", PM_XCell, PM_YCell);
1402 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1403 return (VL_Error);
1404 }
1405
1406 /* Valuate the ouput parameter */
1407 if (0 != VL_Exist) {
1408 /* Compute the X (left, right) and Y (bottom, top) limits of the cell */
1409 double VL_XLeft, VL_XRight, VL_YBottom, VL_YTop;
1410 VL_Error = PT_GetCellLimits(PM_Trace, PM_Mask, PM_XCell, PM_YCell, &VL_XLeft, &VL_XRight, &VL_YBottom, &VL_YTop);
1411 if (C_OK != VL_Error) {
1412 sprintf(VL_ErrorMsg, "Unable to compute the X (left, right) and Y (bottom, top) limits of the cell (%d, %d)\n", PM_XCell, PM_YCell);
1413 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1414 return (VL_Error);
1415 }
1416
1417 /* Valuate the ouput parameters */
1418 /* Boolean expression = distance(wafer center, corner(i) of the cell) < useful radius */
1419 /* Bottom left corner */
1420 if (sqrt (pow (VL_XLeft, 2) + pow (VL_YBottom, 2)) <= PM_UsefulRadius)
1421 (*PM_NumCornerIn)++;
1422 /* Bottom right corner */
1423 if (sqrt (pow (VL_XRight, 2) + pow (VL_YBottom, 2)) <= PM_UsefulRadius)
1424 (*PM_NumCornerIn)++;
1425 /* Top right corner */
1426 if (sqrt (pow (VL_XRight, 2) + pow (VL_YTop, 2)) <= PM_UsefulRadius)
1427 (*PM_NumCornerIn)++;
1428 /* Top left corner */
1429 if (sqrt (pow (VL_XLeft, 2) + pow (VL_YTop, 2)) <= PM_UsefulRadius)
1430 (*PM_NumCornerIn)++;
1431 }
1432
1433#if DEBUG_PT_CALCUL
1434 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_NumCornerIn));
1435#endif
1436
1437 return (VL_Error);
1438}
1439
1440
1441/*---Procedure----------------------------------------------------------------
1442* Component..: PT_OrderCells
1443* Version....: 1.0
1444* Creation...: 01/2004
1445* Author.....: L. SPEYSER Euriware
1446* Description: Order cells being potentials measurement sites for a given
1447* point of a given mask set
1448*
1449*-----------------------------------------------------------------------------
1450* Modified...: 28/05/2004
1451* By.........: L. SPEYSER Euriware
1452* Version....: 2.0
1453* Description: Crolles 2 Parametric test
1454* Rework
1455*
1456*-----------------------------------------------------------------------------
1457* Modified...: 17/06/2009
1458* By.........: sl23
1459* Version....: 2.1
1460* Description: ECR CR00009640
1461* Metro C2 map optimization
1462*---------------------------------------------------------------------------*/
1463int PT_OrderCells (PM_Trace, PM_Mask, PM_Point, PM_XLeft, PM_XRight, PM_YBottom, PM_YTop, PM_XCellij, PM_YCellij)
1464U_Trace PM_Trace; /* In : trace mode */
1465U_Mask PM_Mask; /* In : mask set */
1466U_PtmesTemplatePoint PM_Point; /* In : ideal measurement point */
1467float PM_XLeft; /* In : X coordinate of the bottom left corner of a cell */
1468float PM_XRight; /* In : X coordinate of the bottom left corner of a cell */
1469float PM_YBottom; /* In : Y coordinate of the bottom left corner of a cell */
1470float PM_YTop; /* In : Y coordinate of the bottom left corner of a cell */
1471int PM_XCellij[C_CELLS_SQR_SIZE *C_CELLS_SQR_SIZE]; /* Out : relative X coordinates of the cells */
1472int PM_YCellij[C_CELLS_SQR_SIZE *C_CELLS_SQR_SIZE]; /* Out : relative Y coordinates of the cells */
1473{
1474 /*--------------------------------------------------------------------------
1475 * Declaration
1476 *--------------------------------------------------------------------------
1477 */
1478 int VL_XCellij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE]; /* array of relative X cell coordinates / the (0, 0) cell containing the given point */
1479 int VL_YCellij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE]; /* array of relative Y cell coordinates / the (0, 0) cell containing the given point */
1480 float VL_Distij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE];
1481 int VL_Orderij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE];
1482
1483 /*--------------------------------------------------------------------------
1484 * Initialisation
1485 *--------------------------------------------------------------------------
1486 */
1487 EP_Strcpy(PM_Trace.FunctionName, "PT_OrderCells");
1488
1489#if DEBUG_PT_CALCUL
1490 _StartInfo(PM_Trace.FunctionName, "%s, %f, %f, %f, %f", PM_Mask.MA_Name, PM_Point.Tpw_X, PM_Point.Tpw_Y, PM_XLeft, PM_YBottom);
1491#endif
1492
1493 /*--------------------------------------------------------------------------
1494 * Instructions
1495 *--------------------------------------------------------------------------
1496 */
1497 /* Initialize the VL_XCellij & VL_YCellij arrays with default relative cell coordinates / cell (0, 0) containing the given point
1498 * Example :
1499 * if C_CELLS_SQR_SIZE = 3:
1500 * VL_XCellij[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1},
1501 * VL_YCellij[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1}
1502 * | | | |
1503 * -+---+---+---+-
1504 * | 4 | 3 | 2 |
1505 * --+---+---+---+--
1506 * | 5 | 0 | 1 |
1507 * --+---+---+---+--
1508 * | 6 | 7 | 8 |
1509 * -+---+---+---+-
1510 * | | | |
1511 */
1512 int VL_i, VL_j, VL_c;
1513 int VL_Coord, VL_StartCoord = (int)(C_CELLS_SQR_SIZE * 0.5) - C_CELLS_SQR_SIZE + 1;
1514
1515 /* Initialize the VL_XCellij array of relative cell X coordinates */
1516 VL_j = 0;
1517
1518 for (VL_c = 0; VL_c < C_CELLS_SQR_SIZE; VL_c++) {
1519 VL_Coord = VL_StartCoord;
1520
1521 for (VL_i = VL_j; VL_i < (VL_j + C_CELLS_SQR_SIZE); VL_i++)
1522 VL_XCellij[VL_i] = VL_Coord++;
1523
1524 VL_j += C_CELLS_SQR_SIZE;
1525 }
1526
1527 /* Initialize the VL_YCellij array of relative cell Y coordinates */
1528 VL_Coord = VL_StartCoord;
1529 VL_i = 0;
1530
1531 for (VL_c = 0; VL_c < C_CELLS_SQR_SIZE; VL_c++) {
1532 for (VL_j = 0; VL_j < C_CELLS_SQR_SIZE; VL_j++)
1533 VL_YCellij[VL_i++] = VL_Coord;
1534 VL_Coord++;
1535 }
1536
1537
1538 /* Compute the distance between the given point and each of the C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE center of field */
1539 for (VL_i = 0; VL_i < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_i++) {
1540 VL_Distij[VL_i] = sqrt (pow ((PM_XLeft + PM_XRight) / 2 + (VL_XCellij[VL_i] * PM_Mask.MA_XOverlap) - PM_Point.Tpw_X, 2)
1541 + pow ((PM_YBottom + PM_YTop) / 2 + (VL_YCellij[VL_i] * PM_Mask.MA_YOverlap) - PM_Point.Tpw_Y, 2));
1542 }
1543
1544 /* Initialize the order array with bad values */
1545 for (VL_j = 0; VL_j < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_j++) {
1546 VL_Orderij[VL_j] = -1;
1547 }
1548
1549 /* Order the cells according to the distance of the back left corner to the given point - increasing distance */
1550 int VL_Index;
1551
1552 for (VL_i = 0; VL_i < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_i++) {
1553#if DEBUG_PT_CALCUL
1554 _Tab(0);
1555 printf("dist (%2d, %2d) \t= %f \t", VL_XCellij[VL_i], VL_YCellij[VL_i], VL_Distij[VL_i]);
1556#endif
1557
1558 VL_Index = 0;
1559
1560 for (VL_j = 0; VL_j < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_j++) {
1561 if (VL_Distij[VL_i] > VL_Distij[VL_j])
1562 VL_Index++;
1563 }
1564
1565 /* Equal distance case */
1566 for (VL_j = 0; VL_j < VL_i; VL_j++) {
1567 if (VL_Orderij[VL_j] == VL_Index) // equal distance
1568 VL_Index++;
1569 }
1570
1571 /* Store the order index */
1572 VL_Orderij[VL_i] = VL_Index;
1573#if DEBUG_PT_CALCUL
1574 printf("=> %d\n", VL_Index + 1);
1575#endif
1576 }
1577
1578 /* Order the cells acording to the order of the (bottom left) corners */
1579 for (VL_i = 0; VL_i < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_i++) {
1580 PM_XCellij[VL_Orderij[VL_i]] = VL_XCellij[VL_i];
1581 PM_YCellij[VL_Orderij[VL_i]] = VL_YCellij[VL_i];
1582 }
1583
1584
1585#if DEBUG_PT_CALCUL
1586 _EndInfo(PM_Trace.FunctionName);
1587#endif
1588
1589 return (C_OK);
1590}
1591
1592
1593/*---Procedure----------------------------------------------------------------
1594* Component..: PT_IsCellUsed
1595* Version....: 1.0
1596* Creation...: 01/2004
1597* Author.....: L. SPEYSER Euriware
1598* Description: Indicate if a cell is already used as measurement site
1599*
1600*-----------------------------------------------------------------------------
1601* Modified...: 24/05/2004
1602* By.........: L. SPEYSER Euriware
1603* Version....: 2.0
1604* Description: Algorithm improvements
1605* FAE 04-624
1606*
1607*-----------------------------------------------------------------------------
1608* Modified...: 28/05/2004
1609* By.........: L. SPEYSER Euriware
1610* Version....: 3.0
1611* Description: Crolles 2 Parametric test
1612* Rework
1613*
1614*-----------------------------------------------------------------------------
1615* Modified...: 20/09/2004
1616* By.........: SL23 Euriware
1617* Version....: 4.0
1618* Description: FAE 04-711
1619*---------------------------------------------------------------------------*/
1620int PT_IsCellUsed (PM_Trace, PM_XCell, PM_YCell, PM_ResultsCell, PM_ResultRefIndex, PM_ResultCurrentIndex, PM_Used)
1621U_Trace PM_Trace; /* In : trace mode */
1622int PM_XCell; /* In : X coordinate of a cell */
1623int PM_YCell; /* In : Y coordinate of a cell */
1624U_PtmesResultCell *PM_ResultsCell; /* In : current ideal measurement site computation result list */
1625int PM_ResultRefIndex; /* In : start index in the current result list*/
1626int PM_ResultCurrentIndex; /* In : current index in the current result list */
1627bool *PM_Used; /* Out : cell already used as measurement site */
1628{
1629 /*--------------------------------------------------------------------------
1630 * Initialisation
1631 *--------------------------------------------------------------------------
1632 */
1633 EP_Strcpy(PM_Trace.FunctionName, "PT_IsCellUsed");
1634
1635#if DEBUG_PT_CALCUL
1636 _StartInfo(PM_Trace.FunctionName, "%d, %d, %d, %d", PM_XCell, PM_YCell, PM_ResultRefIndex, PM_ResultCurrentIndex);
1637#endif
1638
1639 /* Valuate by default the ouput parameter */
1640 (*PM_Used) = 0;
1641
1642 /*--------------------------------------------------------------------------
1643 * Instructions
1644 *--------------------------------------------------------------------------
1645 */
1646 /* Order the search limits */
1647 int VL_LimInf, VL_LimSup;
1648
1649 if (PM_ResultRefIndex > PM_ResultCurrentIndex) {
1650 VL_LimInf = PM_ResultCurrentIndex + 1;
1651 VL_LimSup = PM_ResultRefIndex;
1652 } else {
1653 VL_LimInf = PM_ResultRefIndex;
1654 VL_LimSup = PM_ResultCurrentIndex - 1;
1655 }
1656
1657
1658 /* Go through the array of selected cells */
1659 int VL_i = VL_LimInf;
1660
1661 while (VL_i <= VL_LimSup && 0 == (*PM_Used)) {
1662 /* Test the equality between cells coordinates */
1663 if (PM_ResultsCell[VL_i].X_Cell == PM_XCell && PM_ResultsCell[VL_i].Y_Cell == PM_YCell) {
1664 /* Valuate the ouput parameter */
1665 (*PM_Used) = 1;
1666 /* Exit loop */
1667 break;
1668 }
1669 VL_i++;
1670 }
1671
1672#if DEBUG_PT_CALCUL
1673 _EndInfo(PM_Trace.FunctionName, "%d", (*PM_Used));
1674#endif
1675
1676 return (C_OK);
1677}
1678
1679
1680/*---Procedure----------------------------------------------------------------
1681* Component..: PT_ComputeCell
1682* Version....: 1.0
1683* Creation...: 01/2004
1684* Author.....: L. SPEYSER Euriware
1685* Description: Compute the cell to use as measurement site for a given point and
1686* a given mask set
1687* Principle:
1688* - compute the coordinates of the cell containing the input point
1689* - get the 8 adjascent cells (the cell #0 contains the input point)
1690* example:
1691* | | | |
1692* -+---+---+---+-
1693* | 4 | 3 | 2 |
1694* --+---+---+---+--
1695* | 5 | 0 | 1 |
1696* --+---+---+---+--
1697* | 6 | 7 | 8 |
1698* -+---+---+---+-
1699* | | | |
1700* - compute the distance between the input point and the
1701* bottom-left corner of the 9 cells
1702* - order the cells according the increasing computed distance.
1703* example:
1704* | | | |
1705* -+---+---+---+-
1706* | 8 | 2 | 1 |
1707* --+---+---+---+--
1708* | 6 | 3 | 0 |
1709* --+---+---+---+--
1710* | 7 | 5 | 4 |
1711* -+---+---+---+-
1712* | | | |
1713* - check the rules on the closest cell (cell#0)
1714* if all rules are checked, take the cell as the measurement site
1715* else, do the same for the next closest cell, ...
1716* - if at the end no available cell is found -> error!
1717*
1718* Algorithm variable : C_CELLS_SQR_SIZE, defines the size of the research zone
1719* example:
1720* C_CELLS_SQR_SIZE = 1 => research zone = 1 cell
1721* -+---+- (the cell containing the point)
1722* | 0 |
1723* -+---+-
1724* C_CELLS_SQR_SIZE = 2 => research zone = 4 cells
1725* -+---+---+-
1726* | 3 | 2 |
1727* --+---+---+--
1728* | 0 | 1 |
1729* -+---+---+-
1730* C_CELLS_SQR_SIZE = 3 => research zone = 9 cells
1731* | | | |
1732* -+---+---+---+-
1733* | 4 | 3 | 2 |
1734* --+---+---+---+--
1735* | 5 | 0 | 1 |
1736* --+---+---+---+--
1737* | 6 | 7 | 8 |
1738* -+---+---+---+-
1739* | | | |
1740*
1741*-----------------------------------------------------------------------------
1742* Modified...: 21/04/2004
1743* By.........: L. SPEYSER Euriware
1744* Version....: 2.0
1745* Description: Do not accept anymore a measurement cell if it is already used
1746* as measurement site, excepted if it is the only solution.
1747* Sends an information message in this case.
1748* FAE 04-582
1749*
1750*-----------------------------------------------------------------------------
1751* Modified...: 24/05/2004
1752* By.........: L. SPEYSER Euriware
1753* Version....: 3.0
1754* Description: Algorithm improvements
1755* FAE 04-624
1756*
1757*-----------------------------------------------------------------------------
1758* Modified...: 28/05/2004
1759* By.........: L. SPEYSER Euriware
1760* Version....: 4.0
1761* Description: Crolles 2 Parametric test
1762* Rework
1763*
1764*-----------------------------------------------------------------------------
1765* Modified...: 21/09/2004
1766* By.........: SL23 Euriware
1767* Version....: 5.0
1768* Description: FAE 04-680
1769* Call PT_IsCellExposed()
1770*
1771*-----------------------------------------------------------------------------
1772* Modified...: 18/12/2006
1773* By.........: SL23 Euriware
1774* Version....: 5.1
1775* Description: FAE 06-583
1776* Remove the rule : "Check that none of the 4 cells, adjacents by side to
1777* the current cell, is already used as measurement site"
1778*
1779*-----------------------------------------------------------------------------
1780* Modified...: 17/06/2009
1781* By.........: sl23
1782* Version....: 5.2
1783* Description: ECR CR00009640
1784* Metro C2 map optimization
1785*---------------------------------------------------------------------------*/
1786int PT_ComputeCell (PM_Trace, PM_Mask, PM_Template, PM_Point, PM_ExpoBelowRequired, PM_ResultsCell, PM_ResultRefIndex, PM_ResultCurrentIndex, PM_XCell, PM_YCell)
1787U_Trace PM_Trace; /* In : trace mode */
1788U_Mask PM_Mask; /* In : mask set */
1789U_PtmesTemplateIW PM_Template; /* In : ideal measurement points template */
1790U_PtmesTemplatePoint PM_Point; /* In : ideal measurement point */
1791int PM_ExpoBelowRequired; /* In : requires to expose the cell located below the measurement site */
1792U_PtmesResultCell *PM_ResultsCell; /* In : current ideal measurement site computation result list */
1793int PM_ResultRefIndex; /* In : start index in the result list for search operations */
1794int PM_ResultCurrentIndex; /* In : current index in the result list for search operations */
1795int *PM_XCell; /* Out : computed measurement cell x coordinate */
1796int *PM_YCell; /* Out : computed measurement cell y coordinate */
1797{
1798
1799 /*--------------------------------------------------------------------------
1800 * Declaration
1801 *--------------------------------------------------------------------------
1802 */
1803 int VL_Error;
1804 U_InqSQL VL_SqlStatus;
1805 char VL_ErrorMsg[256];
1806 float VL_X;
1807 float VL_Y;
1808
1809 /*--------------------------------------------------------------------------
1810 * Initialisation
1811 *--------------------------------------------------------------------------
1812 */
1813 EP_Strcpy(PM_Trace.FunctionName, "PT_ComputeCell");
1814
1815 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "");
1816
1817
1818 /*--------------------------------------------------------------------------
1819 * Instructions
1820 *--------------------------------------------------------------------------
1821 */
1822 /* Compute the coordinates of the cell containing the point */
1823 int VL_XCell00, VL_YCell00;
1824 VL_Error = PT_ComputeCellContainingPoint(PM_Trace, PM_Mask, PM_Point, &VL_XCell00, &VL_YCell00);
1825
1826 if (C_OK != VL_Error) {
1827 sprintf(VL_ErrorMsg, "Unable to compute the coordinates of the cell containig the point (%f, %f)\n", PM_Point.Tpw_X, PM_Point.Tpw_Y);
1828 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1829 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1830 return (VL_Error);
1831 }
1832
1833
1834 /* Compute the X (left, right) and Y (bottom, top) limits of the cell containg the point */
1835 double VL_XLeft, VL_XRight, VL_YBottom, VL_YTop;
1836 VL_Error = PT_GetCellLimits(PM_Trace, PM_Mask, VL_XCell00, VL_YCell00, &VL_XLeft, &VL_XRight, &VL_YBottom, &VL_YTop);
1837
1838 if (C_OK != VL_Error) {
1839 sprintf(VL_ErrorMsg, "Unable to compute the X (left, right) and Y (bottom, top) limits of the cell (%d, %d)\n", VL_XCell00, VL_YCell00);
1840 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1841 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1842 return (VL_Error);
1843 }
1844
1845
1846 /* Order the cells to test */
1847 int VL_XCellij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE];
1848 int VL_YCellij[C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE];
1849 VL_Error = PT_OrderCells(PM_Trace, PM_Mask, PM_Point, VL_XLeft, VL_XRight, VL_YBottom, VL_YTop, VL_XCellij, VL_YCellij);
1850
1851
1852 if (C_OK != VL_Error) {
1853 sprintf(VL_ErrorMsg, "Unable to order the potential measurement cells\n");
1854 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1855 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1856 return (VL_Error);
1857 }
1858
1859 /* Search the right cell among C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE */
1860 int VL_XCurrentCell, VL_YCurrentCell;
1861 int VL_XUsedCell = 9999;
1862 int VL_YUsedCell = 9999;
1863 bool VL_In, VL_Used, VL_FirstUsed = 0;
1864 int VL_Exposed = 0;
1865 int VL_AvailableForExpo = 0;
1866 int VL_i, VL_NumCornerIn;
1867
1868 for (VL_i = 0; VL_i < C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE; VL_i++) {
1869 /* Compute the coordinates of the current cell */
1870 VL_XCurrentCell = VL_XCell00 + VL_XCellij[VL_i];
1871 VL_YCurrentCell = VL_YCell00 + VL_YCellij[VL_i];
1872
1873#if DEBUG_PT_CALCUL
1874 _Tab(0);
1875 printf("Current cell = (%d, %d)\n", VL_XCurrentCell, VL_YCurrentCell);
1876#endif
1877
1878 /* Apply the algorithm rules */
1879
1880 /* Cell included in the useful area of the wafer */
1881 VL_Error = PT_IsCellInUsefulArea(PM_Trace, PM_Mask, VL_XCurrentCell, VL_YCurrentCell, PM_Template.Tiw_Useful_Radius, &VL_In);
1882
1883 if (C_OK != VL_Error) {
1884 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) is included in the useful area of the wafer\n", VL_XCurrentCell, VL_YCurrentCell);
1885 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1886 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1887 return (VL_Error);
1888 }
1889
1890 if (0 == VL_In) {
1891#if DEBUG_PT_CALCUL
1892 _Tab(0);
1893 printf("Current cell not included in the useful area of the wafer... abandonment\n");
1894#endif
1895
1896 continue;
1897 }
1898
1899
1900 /* The current cell is exposed */
1901 /* Check if the current cell is an exposed FIELD that contains no NOFIELDCORNER image */
1902 VL_Error = PT_IsCellExposed(PM_Trace, PM_Mask, VL_XCurrentCell, VL_YCurrentCell, &VL_Exposed);
1903
1904 if (C_OK != VL_Error) {
1905 sprintf(VL_ErrorMsg, "Unable to determinate if the current cell (%d, %d) is exposed\n", VL_XCurrentCell, VL_YCurrentCell);
1906 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1907 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1908 return (VL_Error);
1909 }
1910
1911 if (0 == VL_Exposed) {
1912#if DEBUG_PT_CALCUL
1913 _Tab(0);
1914 printf("Current cell is not exposed... abandonment\n");
1915#endif
1916
1917 continue;
1918 }
1919
1920 /* The cell below needs to be exposed */
1921 if (PM_ExpoBelowRequired) {
1922 /* Check if the cell below is an exposed FIELD that contains no NOFIELD* image */
1923 VL_Error = PT_IsCellExposed(PM_Trace, PM_Mask, VL_XCurrentCell, VL_YCurrentCell - 1, &VL_Exposed);
1924
1925 if (C_OK != VL_Error) {
1926 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) is exposed\n", VL_XCurrentCell, VL_YCurrentCell - 1);
1927 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1928 return (VL_Error);
1929 }
1930
1931 if (!VL_Exposed) {
1932 /* Check if the cell below can be exposed (should contain a NOFIELDEGE image but no other NOFIELD* image) */
1933 VL_Error = PT_IsCellAvailableForExpo(PM_Trace, PM_Mask, VL_XCurrentCell, VL_YCurrentCell - 1, &VL_AvailableForExpo);
1934
1935 if (C_OK != VL_Error) {
1936 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) can be exposed\n", VL_XCurrentCell, VL_YCurrentCell - 1);
1937 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1938 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1939 return (VL_Error);
1940 }
1941
1942 if (!VL_AvailableForExpo) {
1943#if DEBUG_PT_CALCUL
1944 _Tab(0);
1945 printf("Cell located below can not be exposed... abandonment\n");
1946#endif
1947
1948 continue;
1949 }
1950 }
1951 }
1952
1953 /* Check if the current cell is already used as measurement site */
1954 VL_Error = PT_IsCellUsed(PM_Trace, VL_XCurrentCell, VL_YCurrentCell, PM_ResultsCell, PM_ResultRefIndex, PM_ResultCurrentIndex, &VL_Used);
1955
1956 if (C_OK != VL_Error) {
1957 sprintf(VL_ErrorMsg, "Unable to determinate if the cell (%d, %d) is already used\n", VL_XCurrentCell, VL_YCurrentCell);
1958 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1959 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1960 return (VL_Error);
1961 }
1962
1963 /* Keep this solution whatever the case, but send a warning message in the log file */
1964 if (1 == VL_Used) {
1965 if (0 == VL_FirstUsed) {
1966 VL_FirstUsed = 1;
1967 /* Valuate the ouput parameters */
1968 VL_XUsedCell = VL_XCurrentCell;
1969 VL_YUsedCell = VL_YCurrentCell;
1970 (*PM_XCell) = VL_XCurrentCell;
1971 (*PM_YCell) = VL_YCurrentCell;
1972 }
1973
1974 continue; // Skip to the next cell
1975 }
1976
1977 /* The current cell is also valid */
1978 /* Valuate the ouput parmeters */
1979 (*PM_XCell) = VL_XCurrentCell;
1980 (*PM_YCell) = VL_YCurrentCell;
1981
1982 /* Exit loop */
1983 break;
1984 }
1985
1986 /* Only an already used cell has been found */
1987 if (VL_XUsedCell == (*PM_XCell) && VL_YUsedCell == (*PM_YCell)) {
1988 /* Display a message */
1989 sprintf(VL_ErrorMsg, "BE CAREFUL, the cell (%d, %d) is used at least twice as measurement site!\n", (*PM_XCell), (*PM_YCell));
1990 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1991 } else {
1992 /* No solution found */
1993 if (VL_i >= C_CELLS_SQR_SIZE * C_CELLS_SQR_SIZE) {
1994 sprintf(VL_ErrorMsg, "No available measurement cell found for the point (%f, %f)\n", PM_Point.Tpw_X, PM_Point.Tpw_Y);
1995 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
1996 EP_Strcpy( VG_Msg_Dat_Err, VL_ErrorMsg);
1997 VL_Error = C_NOT_OK;
1998 return (VL_Error);
1999 }
2000 }
2001
2002 TraceLeaveFunction(&PM_Trace);
2003
2004 return (VL_Error);
2005}
2006
2007
2008
2009
2010
2011int PT_IsStdAlgo( U_PtmesTemplateIW PM_Template )
2012{
2013 if ( strcmp(PM_Template.Tiw_Algo,"STD") == 0 ) return(1);
2014 else return(0);
2015}
2016
2017int PT_IsTboxAlgo( U_PtmesTemplateIW PM_Template )
2018{
2019 if ( strcmp(PM_Template.Tiw_Algo,"TBOX") == 0 ) return(1);
2020 else return(0);
2021}
2022
2023int PT_IsSymAlgo( U_PtmesTemplateIW PM_Template )
2024{
2025 if ( strcmp(PM_Template.Tiw_Algo,"Symetries") == 0 ) return(1);
2026 else return(0);
2027}
2028
2029int PT_IsCenterAlgo( U_PtmesTemplateIW PM_Template )
2030{
2031 if ( strcmp(PM_Template.Tiw_Algo,"Centre") == 0 ) return(1);
2032 else return(0);
2033}
2034
2035
2036
2037
2038
2039/*---Procedure----------------------------------------------------------------
2040* Component..: PT_ComputeCells
2041* Version....: 1.0
2042* Creation...: 01/2004
2043* Author.....: L. SPEYSER Euriware
2044* Description: Compute the measurement cells corresponding to the ideal points
2045* model of a given mask set
2046*
2047*-----------------------------------------------------------------------------
2048* Modified...: 21/04/2004
2049* By.........: L. SPEYSER Euriware
2050* Version....: 2.0
2051* Description: Invert the way to go through the list of ideal measurement
2052* points of the templates to optimize the position of the
2053* measurement cells the most constrainted by the boundary of the
2054* useful area of the wafer
2055* FAE 04-582
2056*
2057*-----------------------------------------------------------------------------
2058* Modified...: 24/05/2004
2059* By.........: L. SPEYSER Euriware
2060* Version....: 3.0
2061* Description: Algorithm improvements
2062* FAE 04-624
2063*
2064*-----------------------------------------------------------------------------
2065* Modified...: 28/05/2004
2066* By.........: L. SPEYSER Euriware
2067* Version....: 4.0
2068* Description: Crolles 2 Parametric test
2069* Rework
2070*
2071*-----------------------------------------------------------------------------
2072* Modified...: 20/09/2004
2073* By.........: SL23 Euriware
2074* Version....: 5.0
2075* Description: FAE 04-711
2076*
2077*-----------------------------------------------------------------------------
2078* Modified...: 29/03/2006
2079* By.........: SL23 Euriware
2080* Version....: 5.1
2081* Description: FAE 06-509
2082* MetroLitho recipe
2083*
2084*-----------------------------------------------------------------------------
2085* Modified...: 06/09/2010
2086* By.........: OC5 (Steria)
2087* Version....: 1.0
2088* Description: Add Layer ID on function parameter
2089*
2090*-----------------------------------------------------------------------------
2091* Modified...: 25/08/2014
2092* By.........: Sopra
2093* Version....: 6.0
2094* Description: Compute the mapping Intra-Wafer and the measurements cells by
2095* mapping Intra-Wafer.
2096*-----------------------------------------------------------------------------
2097* Modified...: 03/07/2018
2098* By.........: pt72 - ST
2099* Version....: 6.1
2100* Description: Rajout de l'heritage etendu des templates = possibilite de rajouter des
2101* points supplémentaires à calculer à un sous-template
2102*---------------------------------------------------------------------------*/
2103int PT_ComputeCells (U_Trace PM_Trace, U_Mask PM_Mask, char *PM_CustomTemplateName, char *PM_CustomMappingName,
2104char *PM_RecipeName, char *PM_MetroType, U_PtmesResultCell **PM_ResultsCell,
2105U_PtmesResultTemplate **PM_ResultsTemplate, int *PM_NumOfResultCell, int *PM_NumOfResultTemplate,
2106U_MetroError *PM_Err)
2107{
2108 /*------- Parameters descriptions -------*/
2109 /* U_Trace PM_Trace; /* In : trace mode */
2110 /* U_Mask PM_Mask; /* In : mask set */
2111 /* char *PM_CustomTemplateName; /* In : template name customized */
2112 /* char *PM_CustomMappingName; /* In : template name customized */
2113 /* char *PM_RecipeName; /* In : recipe name */
2114 /* char *PM_MetroType; /* In : metro type */
2115 /* U_PtmesResultCell **PM_ResultsCell; /* Out : array of measurement (mapping) cell */
2116 /* U_PtmesResultTemplate **PM_ResultsTemplate; /* Out : array of measurement (mapping) template */
2117 /* int *PM_NumOfResultCell; /* Out : number of measurement (mapping) cell */
2118 /* int *PM_NumOfResultTemplate; /* Out : number of measurement (mapping) template */
2119
2120 /*--------------------------------------------------------------------------
2121 * Declaration
2122 *--------------------------------------------------------------------------
2123 */
2124 int VL_Error;
2125 U_InqSQL VL_SqlStatus ;
2126 char VL_ErrorMsg[256];
2127 int VL_i, VL_j; // Loop level : VL_i (level 1), VL_j (level 2)
2128 int VL_XCell;
2129 int VL_YCell;
2130 TypeErreur VL_Err; // To catch errors for global variables (from C1, R8 algorithms initially)
2131 int VL_Cr; // Is there an error while getting global variables
2132
2133 /* General */
2134 int VL_Size = 0; // Temporary number of cells for a template.
2135 int VL_ResultRefIndex = 0; // Index of reference for the template being processed. Hold the last index cell in the whole cell list.
2136 int VL_ResultCurrentIndex = 0; // Index of the current cell being processed in the whole cell list.
2137 int VL_BeginningTemplateIndex = 0;
2138 int VL_ExpoBelowRequired = 0;
2139 bool VL_Aborted = 0;
2140 int VL_Index = 0;
2141 char VL_MappingType[C_SIZE_MAPPING_TYPE];
2142 int VL_NbOfNonHeritedPoints = 0; // In the case of extended subtemplates, used to count the number of non-inherited points
2143
2144 /* Output */
2145 U_PtmesResultCell *VL_ResultsCell; // List of cells used for the mapping
2146 U_PtmesResultTemplate *VL_ResultsTemplate; // List of template used for the mapping
2147 U_PtmesResultTemplate *VL_SubResultsTemplate;
2148 U_PtmesResultCell *VL_SubResultsCell;
2149
2150 /* Ideal measurement points */
2151 U_PtmesTemplatePoint *VL_TemplatePoints = NULL; // List of the ideal measurement points for template and subtemplate
2152 int VL_NumOfPoint = 0; // Number of ideal measurement point
2153 StructMesures VL_Mesure; // Used in C200 algorithms (TboxAlgo, ...)
2154 int VL_nb_cells_mapping = 0 ; // Nombre de champs existants en bdd pour un mapping
2155
2156 /* Template Standard */
2157 U_PtmesTemplateIW *VL_UsedTemplates = NULL; // Template used
2158 int *VL_UsedTemplatesSizes; // For each template return the number of cell include.
2159 int VL_UsedTemplatesTotalSize = 0; // Total number of cells used for all the template used.
2160 int VL_NumOfTemplate = 0; // Number of template used.
2161
2162 /* Subtemplate */
2163 U_PtmesTemplateIW *VL_UsedSubTemplates = NULL; // Subtemplate used
2164 int *VL_UsedSubTemplatesSizes; // For each subtemplate return the number of cell include.
2165 int VL_UsedSubTemplatesTotalSize = 0; // Total number of cells used for all the template used.
2166 U_PtmesTemplatePoint *VL_SubTemplatePoints = NULL;
2167 int VL_NumOfSubTemplate = 0;
2168
2169 /* Template Engineering */
2170 U_CellList *VL_ListSelectedCell = NULL;
2171 int VL_NbSelectedCell = 0;
2172
2173
2174 /*--------------------------------------------------------------------------
2175 * Initialisation
2176 *--------------------------------------------------------------------------
2177 */
2178 EP_Strcpy(PM_Trace.FunctionName, "PT_ComputeCells");
2179
2180 if ( (EP_Strcmp(PM_CustomMappingName, "\0") != 0) && (PM_CustomMappingName != NULL) ){
2181 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "Maskset: %s, Custom Mapping: %s, Template: %s", PM_Mask.MA_Name, PM_CustomMappingName, PM_CustomTemplateName);
2182 }
2183 else if ( (EP_Strcmp(PM_CustomTemplateName, "\0") != 0) && (PM_CustomTemplateName != NULL) ) {
2184 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "Maskname: %s, Template: %s", PM_Mask.MA_Name, PM_CustomTemplateName);
2185 }
2186 else {
2187 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "%s", PM_Mask.MA_Name);
2188 }
2189
2190
2191 /*--------------------------------------------------------------------------------
2192 * Getting global variables that are used for Tbox, Sym and Center algorithms
2193 *---------------------------------------------------------------------------------*/
2194 VL_Cr = C_OK1;
2195
2196 VG_Proto_Site = getenv( C_VAR_PROTO_SITE ) ;
2197 VGE_Mask = PM_Mask;
2198 VL_Cr = EP_LitWaferTechno(); // ==> VGE_Techno , VGE_Wafer
2199 if ( VL_Cr == C_OK1 ) VL_Cr = P_LitNbSolOpti ( &VL_Err ); // ==> VG_NbSolutions , VGE_SoRank
2200 if ( VL_Cr == C_OK1 ) VL_Cr = EP_LitMask ( 0 ); // ==> VGE_Mask , VGE_OptiSolution
2201 if ( VL_Cr == C_OK1 ) VL_Cr = EP_LitStcTboxShift ( &VL_Err ); // ==> VG_ShiftSiteX , VG_ShiftSiteY
2202 if ( VL_Cr == C_OK1 ) VL_Cr = EP_LitCellList ( 0 ); // ==> VGE_CellList , VG_TabCellList , VG_NbCellList
2203 if ( VL_Cr == C_OK1 ) VL_Cr = EP_LitHFList ( 0 ); // ==> VGE_HFList , VG_TabHFList , VG_NbHFList
2204
2205 if (VL_Cr != C_OK1 ){
2206 sprintf(VL_ErrorMsg, "Error while getting global variables\n");
2207 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2208 return( C_NOT_OK );
2209 }
2210
2211
2212 /*--------------------------------------------------------------------------------*/
2213
2214 /* Error handling */
2215 VL_Error = C_OK;
2216 EP_Strcpy(VG_Msg_Dat_Err, "\0");
2217
2218 /* Valuate by default the output parameters */
2219 (*PM_ResultsCell) = NULL;
2220 (*PM_ResultsTemplate) = NULL;
2221 (*PM_NumOfResultCell) = 0;
2222 (*PM_NumOfResultTemplate) = 0;
2223
2224 /*--------------------------------------------------------------------------
2225 * Instructions
2226 *--------------------------------------------------------------------------*/
2227 /*---Compute parent template and engineering template----------
2228 ---------------------------------------------------------------
2229 /* First, compute the result relative to the 'main' templates use
2230 Get the list of templates used by the metrology
2231 Check as well if it is a custom mapping */
2232 if ( EP_Strcmp(PM_CustomTemplateName, "\0") == 0 || (PM_CustomTemplateName == NULL) ) {
2233 VL_Error = PT_GetUsedTemplates(PM_Trace, &VL_UsedTemplates, &VL_NumOfTemplate, PM_Mask.MA_Name, PM_RecipeName, PM_MetroType);
2234
2235 if ( VL_Error != C_OK ){
2236 Err_AddError( PM_Err, computeIW, VG_Msg_Dat_Err );
2237 return (C_NOT_OK);
2238 }
2239 snprintf(VL_MappingType, C_SIZE_MAPPING_TYPE, C_AUTOMATIC_TEMPLATE);
2240 } else {
2241 VL_NumOfTemplate = 1;
2242 snprintf(VL_MappingType, C_SIZE_MAPPING_TYPE, C_CUSTOM_TEMPLATE);
2243
2244 /* Allocate memory space */
2245 VL_UsedTemplates = (U_PtmesTemplateIW *) _Calloc(PM_Trace.FunctionName, VL_NumOfTemplate, sizeof(U_PtmesTemplateIW));
2246
2247 if (NULL == VL_UsedTemplates) {
2248 // Error handling
2249 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
2250 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2251 VL_Error = C_NOT_OK;
2252 return (VL_Error);
2253 }
2254
2255
2256 /* Get template data */
2257 VL_Error = PT_GetTemplate(PM_Trace, PM_CustomTemplateName, PM_CustomMappingName, VL_UsedTemplates, PM_Mask.MA_Name, C_TEMPLATE_STANDARD);
2258 if ( VL_Error != C_OK ){
2259 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
2260 return (C_NOT_OK);
2261 }
2262
2263 }
2264
2265 if (C_OK != VL_Error) {
2266 // Error handling
2267 sprintf(VL_ErrorMsg, "Unable to get the list of IW templates used by the metrology for the maskset name %s\n", PM_Mask.MA_Name);
2268 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2269 // Free memory space
2270 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2271 VL_UsedTemplates = NULL;
2272 return (VL_Error);
2273 }
2274
2275 if (VL_NumOfTemplate == 0) {
2276 // Error handling
2277 sprintf(VL_ErrorMsg, "All IntraWafer elements in recipe configs for maskset %s are either already active Mappings or customized ones\n", PM_Mask.MA_Name);
2278 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2279 // Free memory space
2280 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2281 VL_UsedTemplates = NULL;
2282 VL_Error = C_NOT_OK;
2283 return (VL_Error);
2284 }
2285
2286 /* Allocate memory space */
2287 VL_ResultsTemplate = (U_PtmesResultTemplate *) _Calloc(PM_Trace.FunctionName, VL_NumOfTemplate, sizeof(U_PtmesResultTemplate));
2288 VL_UsedTemplatesSizes = (int *) _Calloc(PM_Trace.FunctionName, VL_NumOfTemplate, sizeof(int));
2289
2290 if ( (VL_ResultsTemplate == NULL) && (VL_UsedTemplatesSizes == NULL) ) {
2291 // Error handling
2292 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
2293 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2294 // Free memory space
2295 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2296 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2297 VL_UsedTemplates = NULL;
2298 VL_ResultsTemplate = NULL;
2299 VL_Error = C_NOT_OK;
2300 return (VL_Error);
2301 }
2302
2303
2304 /* Loop on the list of result template */
2305 for (VL_i = 0; VL_i < VL_NumOfTemplate; VL_i++) {
2306
2307 // Check if it is a custom template
2308 if ( (EP_Strcmp(PM_CustomMappingName, "\0") == 0) || (PM_CustomMappingName == NULL) ){
2309 EP_Strcpy(VL_ResultsTemplate[VL_i].MappingName, VL_UsedTemplates[VL_i].Tiw_Name);
2310 }
2311 else {
2312 EP_Strcpy(VL_ResultsTemplate[VL_i].MappingName, PM_CustomMappingName);
2313 }
2314
2315 VL_ResultsTemplate[VL_i].Miw_ID = VL_UsedTemplates[VL_i].Miw_ID;
2316 VL_ResultsTemplate[VL_i].Miw_State = VL_UsedTemplates[VL_i].Miw_State;
2317 EP_Strcpy(VL_ResultsTemplate[VL_i].TemplateName , VL_UsedTemplates[VL_i].Tiw_Name);
2318 EP_Strcpy(VL_ResultsTemplate[VL_i].Miw_Type, VL_MappingType);
2319 VL_ResultsTemplate[VL_i].Miw_Useful_Radius = VL_UsedTemplates[VL_i].Tiw_Useful_Radius;
2320 EP_Strcpy(VL_ResultsTemplate[VL_i].Miw_Comment, VL_UsedTemplates[VL_i].Tiw_Comment);
2321 EP_Strcpy(VL_ResultsTemplate[VL_i].Inherits, "\0");
2322 VL_ResultsTemplate[VL_i].Cell_Found = 0;
2323 }
2324
2325 /* Loop on the list of template */
2326 for (VL_i = 0; VL_i < VL_NumOfTemplate; VL_i++) {
2327
2328 /* Get the size of the current template */
2329 VL_Error = PT_GetTemplateSize(PM_Trace, PM_Mask, VL_UsedTemplates[VL_i].Tiw_Name, &VL_Size, PM_CustomMappingName);
2330
2331 if (VL_Error != C_OK ) {
2332 // Error handling
2333 sprintf(VL_ErrorMsg, "Unable to get the number of ideal measurement point of the template %s\n", VL_UsedTemplates[VL_i].Tiw_Name);
2334 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2335 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2336 // Free memory space
2337 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2338 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2339 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2340 VL_UsedTemplates = NULL;
2341 VL_UsedTemplatesSizes = NULL;
2342 VL_ResultsTemplate = NULL;
2343 return (VL_Error);
2344 }
2345
2346 /* Store the size of the current template */
2347 VL_UsedTemplatesSizes[VL_i] = VL_Size;
2348
2349 /* Increment the global counter */
2350 VL_UsedTemplatesTotalSize += VL_Size;
2351 }
2352
2353 /* Allocate memory space */
2354 VL_ResultsCell = (U_PtmesResultCell *) _Calloc(PM_Trace.FunctionName, VL_UsedTemplatesTotalSize, sizeof(U_PtmesResultCell));
2355
2356 if ( VL_ResultsCell == NULL ) {
2357 // Error handling
2358 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
2359 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2360 // Free memory space
2361 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2362 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2363 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2364 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2365 VL_UsedTemplates = NULL;
2366 VL_UsedTemplatesSizes = NULL;
2367 VL_ResultsTemplate = NULL;
2368 VL_ResultsCell = NULL;
2369 VL_Error = C_NOT_OK;
2370 return (VL_Error);
2371 }
2372
2373 /* Loop on the list of template */
2374 for (VL_i = 0; VL_i < VL_NumOfTemplate; VL_i++) {
2375
2376 ////////////////////////////////////////////////////////////////////////////////
2377 // Ici, possibilité de rajouter la computation pour les templates engineering //
2378 // Avec une condition : si je suis dans le cas dun template engineering, je //
2379 // ne fais pas le reste //
2380 ////////////////////////////////////////////////////////////////////////////////
2381 if (PT_IsTemplateEngineering(VL_UsedTemplates[VL_i])) {
2382 TracePrint(&PM_Trace, "Compute Engineering Template\n");
2383 VL_ListSelectedCell = NULL;
2384
2385 VL_Error = PT_ComputeTemplateEngineering(PM_Trace, PM_Mask, VL_UsedTemplates[VL_i], &VL_ListSelectedCell, &VL_NbSelectedCell);
2386
2387 // an error occured during the computation of the template engineering
2388 if (VL_Error != C_OK) {
2389 // Error handling
2390 sprintf(VL_ErrorMsg, "Error during computation of the following engineering template %s\n", VL_UsedTemplates[VL_i].Tiw_Name);
2391 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2392 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2393 // Free memory space
2394 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2395 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2396 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2397 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2398 VL_UsedTemplates = NULL;
2399 VL_UsedTemplatesSizes = NULL;
2400 VL_ResultsTemplate = NULL;
2401 VL_ResultsCell = NULL;
2402 return (VL_Error);
2403 }
2404
2405
2406 /* Loop on the list of ideal measurement point */
2407 VL_Aborted = 0;
2408
2409 // Loop on the list of result cells
2410 for ( VL_j = 0; VL_j < VL_NbSelectedCell; VL_j++ ) {
2411
2412 /* Increment index */
2413 VL_ResultCurrentIndex = VL_ResultRefIndex + VL_j;
2414
2415 /* Valuate the current result measurement cell item */
2416 EP_Strcpy(VL_ResultsCell[VL_ResultCurrentIndex].TemplateName, VL_UsedTemplates[VL_i].Tiw_Name);
2417 VL_ResultsCell[VL_ResultCurrentIndex].Index = VL_j + 1;
2418 VL_ResultsCell[VL_ResultCurrentIndex].Linked_Index = 0;
2419 VL_ResultsCell[VL_ResultCurrentIndex].X_Point = 0;
2420 VL_ResultsCell[VL_ResultCurrentIndex].Y_Point = 0;
2421 VL_ResultsCell[VL_ResultCurrentIndex].Expo_Below_Required = 0;
2422
2423 if (C_OK != VL_Error || VL_Aborted) {
2424 VL_Aborted = 1;
2425 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2426 sprintf(VL_ErrorMsg, "Unable to compute the measurement cell #%d\n", VL_j);
2427 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2428 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2429
2430 continue;
2431 // Ou faire "continue;" si on souhaite calculer le maximum de sites de mesures...
2432 }
2433
2434 VL_ResultsCell[VL_ResultCurrentIndex].X_Cell = VL_ListSelectedCell[VL_j].CL_X;
2435 VL_ResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_ListSelectedCell[VL_j].CL_Y;
2436 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 1;
2437 }
2438
2439 // Free memory space
2440 if ( VL_ListSelectedCell != NULL) {
2441 _Free(PM_Trace.FunctionName, VL_ListSelectedCell);
2442 VL_ListSelectedCell = NULL;
2443 }
2444
2445 } else {
2446
2447 TracePrint(&PM_Trace, "Compute Ideal Point Template\n");
2448 /* Check if at least one template requires to expose the cell located below a measurement site for the current template */
2449 VL_Error = PT_IsExpoBelowRequired(PM_Trace, PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name, &VL_ExpoBelowRequired);
2450
2451 if (C_OK != VL_Error) {
2452 // Error handling
2453 sprintf(VL_ErrorMsg, "Unable to check if the cell below needs to be exposed for the maskset name %s and the template %s\n", PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name);
2454 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2455 // Free memory space
2456 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2457 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2458 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2459 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2460 VL_UsedTemplates = NULL;
2461 VL_UsedTemplatesSizes = NULL;
2462 VL_ResultsTemplate = NULL;
2463 VL_ResultsCell = NULL;
2464 return (VL_Error);
2465 }
2466
2467
2468 /* Si le mapping existe déjà , est actif, et possède autant de points que dans le template,
2469 on ne le recalcule pas, on charge les champs sélectionnés depuis la base de données */
2470 VL_Error = PT_GetNbCellsMappingInDB ( PM_Trace, PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name, &VL_nb_cells_mapping ) ; // Nombre de champs existants en bdd pour le mapping actif (0 si pas de mapping actif)
2471
2472 if ( VL_Error != C_OK ) {
2473 // Error handling
2474 sprintf(VL_ErrorMsg, "Unable to get the number of cells in the DB for the maskset %s and the mapping %s\n", PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name);
2475 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2476 // Free memory space
2477 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2478 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2479 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2480 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2481 VL_UsedTemplates = NULL;
2482 VL_UsedTemplatesSizes = NULL;
2483 VL_ResultsTemplate = NULL;
2484 VL_ResultsCell = NULL;
2485 return (VL_Error);
2486 }
2487
2488
2489 /* Si le mapping existe déjà en BDD (est actif, et possède autant de points que dans le template)
2490 et si c'est une génération auto ou si c'est une génération custo mais avec un sous template demandé
2491 ==> alors on charge le mapping existant en BDD
2492 sinon
2493 ==> On calcule le mapping */
2494 if ( VL_UsedTemplatesSizes[VL_i]==VL_nb_cells_mapping &&
2495 ( EP_Strcmp(VL_MappingType,C_AUTOMATIC_TEMPLATE)==0 || ( EP_Strcmp(VL_MappingType,C_CUSTOM_TEMPLATE)==0 && EP_Strcmp(VL_UsedTemplates[VL_i].Tiw_Name,PM_CustomTemplateName)!=0 ) ) ){
2496
2497 // Récupération des champs sélectionnés en base de données
2498 VL_Error = PT_GetCellsMappingInDB ( PM_Trace, PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name, VL_nb_cells_mapping, VL_ExpoBelowRequired, VL_ResultRefIndex, &VL_ResultsCell );
2499
2500 if ( VL_Error != C_OK ) {
2501 // Error handling
2502 sprintf(VL_ErrorMsg, "Unable to get the cells in DB for the maskset %s and the mapping %s\n", PM_Mask.MA_Name, VL_UsedTemplates[VL_i].Tiw_Name);
2503 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2504 // Free memory space
2505 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2506 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2507 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2508 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2509 VL_UsedTemplates = NULL;
2510 VL_UsedTemplatesSizes = NULL;
2511 VL_ResultsTemplate = NULL;
2512 VL_ResultsCell = NULL;
2513 return (VL_Error);
2514 }
2515
2516 continue; // On passe au template suivant
2517 }
2518
2519
2520 /* Get the list of ideal measurement point of the current used template */
2521 VL_Error = PT_GetIdealMeasurementPoints(PM_Trace, VL_UsedTemplates[VL_i].Tiw_Name, &VL_TemplatePoints, &VL_NumOfPoint);
2522
2523 if (C_OK != VL_Error) {
2524 // Error handling
2525 sprintf(VL_ErrorMsg, "Unable to get the list of ideal measurement point of the template %s\n", VL_UsedTemplates[VL_i].Tiw_Name);
2526 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2527 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2528 // Free memory space
2529 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2530 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2531 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2532 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2533 _Free(PM_Trace.FunctionName, VL_TemplatePoints);
2534 VL_UsedTemplates = NULL;
2535 VL_UsedTemplatesSizes = NULL;
2536 VL_ResultsTemplate = NULL;
2537 VL_ResultsCell = NULL;
2538 VL_TemplatePoints = NULL;
2539 return (VL_Error);
2540 }
2541
2542 /* Check that the number of ideal measurement point found matches with the template size found above to avoid memory space problems */
2543 if (VL_NumOfPoint != VL_UsedTemplatesSizes[VL_i]) {
2544 // Error handling
2545 sprintf(VL_ErrorMsg, "The number of ideal measurement point found (%d) does not match with the %s template size (%d)\n", VL_NumOfPoint, VL_UsedTemplates[VL_i].Tiw_Name, VL_UsedTemplatesSizes[VL_i]);
2546 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2547 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2548 // Free memory space
2549 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2550 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2551 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2552 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2553 _Free(PM_Trace.FunctionName, VL_TemplatePoints);
2554 VL_UsedTemplates = NULL;
2555 VL_UsedTemplatesSizes = NULL;
2556 VL_ResultsTemplate = NULL;
2557 VL_ResultsCell = NULL;
2558 VL_TemplatePoints = NULL;
2559 return (VL_Error);
2560 }
2561
2562 //////////////////////////////////////////////////////////////////////////////////
2563 // Looping on the list of ideal points depends on the type of algorithm used //
2564 //////////////////////////////////////////////////////////////////////////////////
2565
2566 // The standard C300 algorithm common for all metrologies
2567 if ( PT_IsStdAlgo( VL_UsedTemplates[VL_i] ) ) {
2568
2569 /* Loop on the list of ideal measurement point */
2570 VL_Aborted = 0;
2571
2572 for (VL_j = VL_NumOfPoint - 1; VL_j >= 0; VL_j--) {
2573 /* Increment index */
2574 VL_ResultCurrentIndex = VL_ResultRefIndex + VL_j;
2575
2576 if (!VL_Aborted) {
2577 /* Compute the coordinates of the measurement cell corresponding to the current ideal measurement point of the current template */
2578 VL_Error = PT_ComputeCell(PM_Trace, PM_Mask, VL_UsedTemplates[VL_i], VL_TemplatePoints[VL_j], VL_ExpoBelowRequired, VL_ResultsCell, VL_ResultRefIndex + VL_NumOfPoint - 1, VL_ResultCurrentIndex, &VL_XCell, &VL_YCell);
2579 if ( VL_Error != C_OK ){
2580 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
2581 }
2582 }
2583
2584 /* Valuate the current result measurement cell item */
2585 EP_Strcpy(VL_ResultsCell[VL_ResultCurrentIndex].TemplateName, VL_UsedTemplates[VL_i].Tiw_Name);
2586 VL_ResultsCell[VL_ResultCurrentIndex].Index = VL_TemplatePoints[VL_j].Tpw_Index;
2587 VL_ResultsCell[VL_ResultCurrentIndex].Linked_Index = VL_TemplatePoints[VL_j].Tpw_Index;
2588 VL_ResultsCell[VL_ResultCurrentIndex].X_Point = VL_TemplatePoints[VL_j].Tpw_X;
2589 VL_ResultsCell[VL_ResultCurrentIndex].Y_Point = VL_TemplatePoints[VL_j].Tpw_Y;
2590 VL_ResultsCell[VL_ResultCurrentIndex].Expo_Below_Required = VL_ExpoBelowRequired;
2591
2592 if (C_OK != VL_Error || VL_Aborted) {
2593 VL_Aborted = 1;
2594 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2595 sprintf(VL_ErrorMsg, "Unable to compute the measurement cell #%d\n", VL_j);
2596 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2597 continue;
2598 // Ou faire "continue;" si on souhaite calculer le maximum de sites de mesures...
2599 }
2600
2601 VL_ResultsCell[VL_ResultCurrentIndex].X_Cell = VL_XCell;
2602 VL_ResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_YCell;
2603 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 1;
2604 }
2605
2606 /* Free memory space */
2607 _Free(PM_Trace.FunctionName, VL_TemplatePoints);
2608 VL_TemplatePoints = NULL;
2609
2610
2611 } else if ( PT_IsTboxAlgo(VL_UsedTemplates[VL_i]) || PT_IsCenterAlgo(VL_UsedTemplates[VL_i]) || PT_IsSymAlgo(VL_UsedTemplates[VL_i]) ) {
2612 // Algorithms used on C200
2613
2614 // Transmission of the data points of the current template from VL_TemplatePoints to the StructMesures VL_Mesure
2615 VL_Mesure.NbPointsMesure = VL_NumOfPoint;
2616 for ( VL_j = 0 ; VL_j < VL_NumOfPoint ; VL_j++ ) {
2617 VL_Mesure.TabPtIdeal[VL_j].X = VL_TemplatePoints[VL_j].Tpw_X;
2618 VL_Mesure.TabPtIdeal[VL_j].Y = VL_TemplatePoints[VL_j].Tpw_Y;
2619 VL_Mesure.TabCell[VL_j].X = 0; // Initialization
2620 VL_Mesure.TabCell[VL_j].Y = 0; // Initialization
2621 }
2622
2623 // Getting Cells that are selected using either Tbox, Center or Symetries algorithms (from C200)
2624 // Those algorithms correspond initially to Thickness, PT and Overlay metrologies
2625 if ( PT_IsTboxAlgo(VL_UsedTemplates[VL_i]) ) {
2626 VL_Error = C_OK; // Pas de gestion des erreurs pour P_CalculerPointsMesure
2627 P_CalculerPointsMesure( C_SERVICE_METRO_OPTI , &VL_Mesure , VL_ResultsTemplate[VL_i].Miw_Useful_Radius , C_POSITION_TBOX );
2628 }
2629 else if ( PT_IsCenterAlgo(VL_UsedTemplates[VL_i]) ) {
2630 VL_Error = C_OK; // Pas de gestion des erreurs pour P_CalculerPointsMesure
2631 P_CalculerPointsMesure( C_SERVICE_METRO_TEST , &VL_Mesure , VL_ResultsTemplate[VL_i].Miw_Useful_Radius , C_POSITION_CENTRE );
2632 }
2633 else if ( PT_IsSymAlgo(VL_UsedTemplates[VL_i]) ) {
2634 VL_Error = P_CalculerPointsAlarm ( C_SERVICE_METRO_ALARM, &VL_Mesure , &(VL_ResultsTemplate[VL_i].Miw_Useful_Radius) );
2635 }
2636
2637 // Loop on the cell to store the results
2638 for (VL_j = 0; VL_j < VL_NumOfPoint; VL_j++) {
2639
2640 /* Increment index */
2641 VL_ResultCurrentIndex = VL_ResultRefIndex + VL_j;
2642
2643 /* Valuate the current result measurement cell item */
2644 EP_Strcpy(VL_ResultsCell[VL_ResultCurrentIndex].TemplateName, VL_UsedTemplates[VL_i].Tiw_Name);
2645 VL_ResultsCell[VL_ResultCurrentIndex].Index = VL_TemplatePoints[VL_j].Tpw_Index;
2646 VL_ResultsCell[VL_ResultCurrentIndex].Linked_Index = VL_TemplatePoints[VL_j].Tpw_Index;
2647 VL_ResultsCell[VL_ResultCurrentIndex].X_Point = VL_Mesure.TabPtIdeal[VL_j].X;
2648 VL_ResultsCell[VL_ResultCurrentIndex].Y_Point = VL_Mesure.TabPtIdeal[VL_j].Y;
2649 VL_ResultsCell[VL_ResultCurrentIndex].Expo_Below_Required = VL_ExpoBelowRequired;
2650
2651 if ( VL_Error == C_OK ) {
2652 VL_ResultsCell[VL_ResultCurrentIndex].X_Cell = VL_Mesure.TabCell[VL_j].X;
2653 VL_ResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_Mesure.TabCell[VL_j].Y;
2654 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 1;
2655 } else {
2656 VL_ResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2657 sprintf(VL_ErrorMsg, "Unable to compute the measurement cell #%d\n", VL_j);
2658 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2659 continue;
2660 }
2661 }
2662
2663 } else { // No other algorithm exists yet
2664 sprintf(VL_ErrorMsg, "The algorithm '%s' for the %s template is not implemented\n",VL_UsedTemplates[VL_i].Tiw_Algo,VL_UsedTemplates[VL_i].Tiw_Name);
2665 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2666 continue;
2667 }
2668
2669 /* Free memory space */
2670 _Free(PM_Trace.FunctionName, VL_TemplatePoints);
2671 VL_TemplatePoints = NULL;
2672
2673 } // fin des templates de points idéaux
2674
2675 /* Increment index */
2676 VL_ResultRefIndex += VL_UsedTemplatesSizes[VL_i];
2677 }
2678
2679 /*---Compute subtemplate---------------------------------------*/
2680 /*-------------------------------------------------------------*/
2681 TracePrint(&PM_Trace, "Compute Sub-Template\n");
2682 /* Once the main templates use result is computed, build the result of the used sub-templates */
2683
2684 /* Get the list of used sub-templates */
2685 if ( (EP_Strcmp(PM_CustomMappingName, "\0") == 0) || (PM_CustomMappingName == NULL) ){
2686 VL_Error = PT_GetUsedSubTemplates(PM_Trace, PM_Mask.MA_Name, PM_CustomMappingName, &VL_UsedSubTemplates, &VL_NumOfSubTemplate, PM_RecipeName, PM_MetroType);
2687
2688 if (C_OK != VL_Error) {
2689 // Error handling
2690 sprintf(VL_ErrorMsg, "Unable to get the list of sub-templates used by the metrology for the maskset name %s\n", PM_Mask.MA_Name);
2691 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2692 // Free memory space
2693 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2694 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2695 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2696 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2697 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2698 VL_UsedTemplates = NULL;
2699 VL_UsedTemplatesSizes = NULL;
2700 VL_ResultsTemplate = NULL;
2701 VL_ResultsCell = NULL;
2702 VL_UsedSubTemplates = NULL;
2703 return (VL_Error);
2704 }
2705
2706 }
2707 else {
2708 VL_NumOfSubTemplate = 1;
2709 VL_UsedSubTemplates = (U_PtmesTemplateIW *) _Calloc(PM_Trace.FunctionName, (VL_NumOfSubTemplate), sizeof(U_PtmesTemplateIW));
2710
2711 /* Get subtemplate and extended subtemplate data */
2712 VL_Error = PT_GetTemplate(PM_Trace, PM_CustomTemplateName, PM_CustomMappingName, VL_UsedSubTemplates, PM_Mask.MA_Name, C_TEMPLATE_SUBTEMPLATE);
2713
2714 if ( (EP_Strcmp(VL_UsedSubTemplates[0].Tiw_Name, "\0") == 0) ||(VL_UsedSubTemplates[0].Tiw_Name == NULL)){
2715 VL_NumOfSubTemplate = 0;
2716
2717 // Free memory
2718 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2719 VL_UsedSubTemplates = NULL;
2720 }
2721 }
2722
2723 /* Allocate memory space */
2724 VL_UsedSubTemplatesSizes = (int *) _Calloc(PM_Trace.FunctionName, VL_NumOfSubTemplate, sizeof(int));
2725
2726 if ( VL_UsedSubTemplatesSizes == NULL ) {
2727 // Error handling
2728 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
2729 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2730 // Free memory space
2731 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2732 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2733 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2734 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2735 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2736 VL_UsedTemplates = NULL;
2737 VL_UsedTemplatesSizes = NULL;
2738 VL_ResultsTemplate = NULL;
2739 VL_ResultsCell = NULL;
2740 VL_UsedSubTemplates = NULL;
2741 VL_Error = C_NOT_OK;
2742 return (VL_Error);
2743 }
2744
2745 /* Loop on the list of sub-template */
2746 for (VL_i = 0; VL_i < VL_NumOfSubTemplate; VL_i++) {
2747 /* Get the size of the current sub-template */
2748 VL_Error = PT_GetSubTemplateSize(PM_Trace, VL_UsedSubTemplates[VL_i].Tiw_Name, &VL_Size);
2749
2750 if (C_OK != VL_Error) {
2751 // Error handling
2752 sprintf(VL_ErrorMsg, "Unable to get the number of ideal measurement point of the sub-template %s\n", VL_UsedSubTemplates[VL_i].Tiw_Name);
2753 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2754 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2755 // Free memory space
2756 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2757 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2758 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2759 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2760 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2761 _Free(PM_Trace.FunctionName, VL_UsedSubTemplatesSizes);
2762 VL_UsedTemplates = NULL;
2763 VL_UsedTemplatesSizes = NULL;
2764 VL_ResultsTemplate = NULL;
2765 VL_ResultsCell = NULL;
2766 VL_UsedSubTemplates = NULL;
2767 VL_UsedSubTemplatesSizes = NULL;
2768 return (VL_Error);
2769 }
2770
2771 /* Store the size of the current template */
2772 VL_UsedSubTemplatesSizes[VL_i] = VL_Size;
2773
2774 /* Increment the global counter */
2775 VL_UsedSubTemplatesTotalSize += VL_Size;
2776
2777 }
2778
2779 /* Allocate memory space */
2780 VL_SubResultsTemplate = (U_PtmesResultTemplate *) _Calloc(PM_Trace.FunctionName, VL_NumOfSubTemplate, sizeof(U_PtmesResultTemplate));
2781 VL_SubResultsCell = (U_PtmesResultCell *) _Calloc(PM_Trace.FunctionName, VL_UsedSubTemplatesTotalSize, sizeof(U_PtmesResultCell));
2782
2783 if ( (VL_SubResultsTemplate == NULL) && (VL_SubResultsCell == NULL) ) {
2784 // Error handling
2785 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
2786 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2787 // Free memory space
2788 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2789 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2790 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2791 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2792 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2793 _Free(PM_Trace.FunctionName, VL_UsedSubTemplatesSizes);
2794 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
2795 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
2796 VL_UsedTemplates = NULL;
2797 VL_UsedTemplatesSizes = NULL;
2798 VL_ResultsTemplate = NULL;
2799 VL_ResultsCell = NULL;
2800 VL_UsedSubTemplates = NULL;
2801 VL_UsedSubTemplatesSizes = NULL;
2802 VL_SubResultsTemplate = NULL;
2803 VL_SubResultsCell = NULL;
2804 VL_Error = C_NOT_OK;
2805 return (VL_Error);
2806 }
2807
2808 /* Loop on the list of used sub-template */
2809 VL_ResultCurrentIndex = 0;
2810
2811 for (VL_i = 0; VL_i < VL_NumOfSubTemplate; VL_i++) {
2812
2813 VL_BeginningTemplateIndex = VL_ResultCurrentIndex;
2814
2815 /* Search the inherited template result into the current result list (names comparison) */
2816 for (VL_j = 0; VL_j < VL_NumOfTemplate; VL_j++) {
2817 if (0 == EP_Strcmp(VL_UsedSubTemplates[VL_i].Tiw_Parent_Name, VL_ResultsTemplate[VL_j].TemplateName))
2818 break; /* Inherited template found */
2819 }
2820
2821 /* The inherited template does not match any template used */
2822 if (VL_j >= VL_NumOfTemplate) {
2823 // Pour info?
2824 sprintf(VL_ErrorMsg, "Unable to get the result of the inherited template %s use for the sub-template %s\n", VL_UsedSubTemplates[VL_i].Tiw_Parent_Name, VL_UsedSubTemplates[VL_i].Tiw_Name);
2825 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2826 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2827 }
2828
2829 /* Get the definition of the current used sub-template */
2830 VL_NumOfPoint = 0;
2831 VL_Error = PT_GetSubTemplates(PM_Trace, VL_UsedSubTemplates[VL_i].Tiw_Name, &VL_SubTemplatePoints, &VL_NumOfPoint);
2832
2833 if (C_OK != VL_Error) {
2834 // Error handling
2835 sprintf(VL_ErrorMsg, "Unable to get the list of ideal measurement point of the template %s\n", VL_UsedTemplates[VL_i].Tiw_Name);
2836 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2837 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2838 // Free memory space
2839 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
2840 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
2841 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
2842 _Free(PM_Trace.FunctionName, VL_ResultsCell);
2843 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
2844 _Free(PM_Trace.FunctionName, VL_UsedSubTemplatesSizes);
2845 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
2846 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
2847 VL_UsedTemplates = NULL;
2848 VL_UsedTemplatesSizes = NULL;
2849 VL_ResultsTemplate = NULL;
2850 VL_ResultsCell = NULL;
2851 VL_UsedSubTemplates = NULL;
2852 VL_UsedSubTemplatesSizes = NULL;
2853 VL_SubResultsTemplate = NULL;
2854 VL_SubResultsCell = NULL;
2855 return (VL_Error);
2856 }
2857
2858 /* Check that the number of ideal measurement point found matches with the sub-template size found above to avoid memory space problems */
2859 if (VL_NumOfPoint != VL_UsedSubTemplatesSizes[VL_i]) {
2860 sprintf(VL_ErrorMsg, "The number of ideal measurement point found (%d) does not match with the %s sub-template size (%d)\n", VL_NumOfPoint, VL_UsedSubTemplates[VL_i].Tiw_Name, VL_UsedTemplatesSizes[VL_i]);
2861 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2862 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2863 continue;
2864 }
2865
2866 // Check if it is a custom template
2867 if ( (EP_Strcmp(PM_CustomMappingName, "\0") == 0) || (PM_CustomMappingName == NULL) ) {
2868 EP_Strcpy(VL_SubResultsTemplate[VL_i].MappingName, VL_UsedSubTemplates[VL_i].Tiw_Name);
2869 } else {
2870 EP_Strcpy(VL_SubResultsTemplate[VL_i].MappingName, PM_CustomMappingName);
2871 }
2872
2873
2874 VL_SubResultsTemplate[VL_i].Miw_ID = VL_UsedSubTemplates[VL_i].Miw_ID;
2875 VL_SubResultsTemplate[VL_i].Miw_State = VL_UsedSubTemplates[VL_i].Miw_State;
2876 EP_Strcpy(VL_SubResultsTemplate[VL_i].TemplateName, VL_UsedSubTemplates[VL_i].Tiw_Name);
2877 EP_Strcpy(VL_SubResultsTemplate[VL_i].Miw_Type, VL_MappingType);
2878 VL_SubResultsTemplate[VL_i].Miw_Useful_Radius = VL_UsedSubTemplates[VL_i].Tiw_Useful_Radius;
2879 EP_Strcpy(VL_SubResultsTemplate[VL_i].Miw_Comment, VL_UsedSubTemplates[VL_i].Tiw_Comment);
2880 EP_Strcpy(VL_SubResultsTemplate[VL_i].Inherits, VL_UsedSubTemplates[VL_i].Tiw_Parent_Name);
2881 VL_SubResultsTemplate[VL_i].Cell_Found = 0;
2882
2883
2884 VL_NbOfNonHeritedPoints = 0; // Count the number of non herited points (new points to calculate for extended subtemplates)
2885
2886 // 1st Loop on the list of point of the current sub-template
2887 // First only non herited points are placed
2888 for (VL_j = 0; VL_j < VL_NumOfPoint; VL_j++) {
2889
2890 if ( VL_SubTemplatePoints[VL_j].Tpw_Parent_Index != 0 ) { // It is an inherited point
2891
2892 /* Get the corresponding index of the computation result of the inherited template used in the result array */
2893 VL_Index = 0;
2894 VL_Error = PT_GetResultIndex(PM_Trace, VL_UsedSubTemplates[VL_i].Tiw_Parent_Name, VL_SubTemplatePoints[VL_j].Tpw_Parent_Index, VL_ResultsCell, VL_UsedTemplatesTotalSize, &VL_Index);
2895
2896 if (C_OK != VL_Error) {
2897 sprintf(VL_ErrorMsg, "Unable to get the list of ideal measurement point of the template %s\n", VL_UsedSubTemplates[VL_i].Tiw_Parent_Name);
2898 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2899 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
2900 continue;
2901 }
2902
2903 if (VL_ResultsCell[VL_Index].Cell_Found == 0) {
2904 /* Warning message */
2905 sprintf(VL_ErrorMsg, "Cell#%d was not found using the inherited template %s\n", VL_SubTemplatePoints[VL_j].Tpw_Parent_Index, VL_UsedSubTemplates[VL_i].Tiw_Parent_Name);
2906 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2907 }
2908
2909 /* Valuate the current result measurement cell item of the current sub-template*/
2910 EP_Strcpy(VL_SubResultsCell[VL_ResultCurrentIndex].TemplateName, VL_UsedSubTemplates[VL_i].Tiw_Name);
2911 VL_SubResultsCell[VL_ResultCurrentIndex].Index = VL_SubTemplatePoints[VL_j].Tpw_Index;
2912 VL_SubResultsCell[VL_ResultCurrentIndex].Linked_Index = VL_SubTemplatePoints[VL_j].Tpw_Parent_Index;
2913 VL_SubResultsCell[VL_ResultCurrentIndex].X_Point = VL_ResultsCell[VL_Index].X_Point;
2914 VL_SubResultsCell[VL_ResultCurrentIndex].Y_Point = VL_ResultsCell[VL_Index].Y_Point;
2915 VL_SubResultsCell[VL_ResultCurrentIndex].Expo_Below_Required = 0; /* Managed at the level of the template */
2916
2917 VL_SubResultsCell[VL_ResultCurrentIndex].X_Cell = VL_ResultsCell[VL_Index].X_Cell + VL_SubTemplatePoints[VL_j].Tpw_Shift_X;
2918 VL_SubResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_ResultsCell[VL_Index].Y_Cell + VL_SubTemplatePoints[VL_j].Tpw_Shift_Y;
2919 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = VL_ResultsCell[VL_Index].Cell_Found;
2920
2921 } else { // New points are calculated after all inherited points !!!
2922
2923 VL_NbOfNonHeritedPoints++;
2924
2925 }
2926
2927 /* Increment index */
2928 VL_ResultCurrentIndex++;
2929 }
2930
2931
2932 // 2nd loop on the list of points of the current sub-template if there are non herited points
2933 if ( VL_NbOfNonHeritedPoints > 0 ){
2934
2935 VL_ResultCurrentIndex = VL_BeginningTemplateIndex;
2936
2937 for ( VL_j = 0; VL_j < VL_NumOfPoint; VL_j++ ){
2938
2939 if ( VL_SubTemplatePoints[VL_j].Tpw_Parent_Index == 0 ) { // It is a non-herited point (a new point to calculate)
2940
2941 if ( PT_IsStdAlgo( VL_UsedSubTemplates[VL_i] ) ) {
2942
2943 if (!VL_Aborted) {
2944 /* Compute the coordinates of the measurement cell corresponding to the current ideal measurement point of the current template */
2945 VL_Error = PT_ComputeCell(PM_Trace, PM_Mask, VL_UsedSubTemplates[VL_i], VL_SubTemplatePoints[VL_j], VL_ExpoBelowRequired, VL_SubResultsCell, VL_BeginningTemplateIndex, VL_BeginningTemplateIndex + VL_j, &VL_XCell, &VL_YCell);
2946 if ( VL_Error != C_OK ){
2947 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
2948 }
2949 }
2950
2951 if (C_OK != VL_Error || VL_Aborted) {
2952 VL_Aborted = 1;
2953 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2954 sprintf(VL_ErrorMsg, "Unable to compute the measurement cell #%d\n", VL_j);
2955 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2956 continue;
2957 // Ou faire "continue;" si on souhaite calculer le maximum de sites de mesures...
2958 }
2959
2960 VL_SubResultsCell[VL_ResultCurrentIndex].X_Cell = VL_XCell;
2961 VL_SubResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_YCell;
2962 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = 1;
2963
2964 } else if ( PT_IsTboxAlgo(VL_UsedSubTemplates[VL_i]) || PT_IsCenterAlgo(VL_UsedSubTemplates[VL_i]) ) {
2965
2966 // Le calcul peut se faire sur un seul point a la fois pour les algorithmes TBOX et Center.
2967 // La selection des champs ne depend pas des champs deja selectionnes
2968 VL_Mesure.NbPointsMesure = 1;
2969
2970 VL_Mesure.TabPtIdeal[0].X = VL_SubTemplatePoints[VL_j].Tpw_X;
2971 VL_Mesure.TabPtIdeal[0].Y = VL_SubTemplatePoints[VL_j].Tpw_Y;
2972 VL_Mesure.TabCell[0].X = 0; // Initialization
2973 VL_Mesure.TabCell[0].Y = 0; // Initialization
2974
2975 if ( PT_IsTboxAlgo(VL_UsedSubTemplates[VL_i]) ) {
2976 P_CalculerPointsMesure( C_SERVICE_METRO_OPTI , &VL_Mesure , VL_UsedSubTemplates[VL_i].Tiw_Useful_Radius , C_POSITION_TBOX );
2977 }
2978 else if ( PT_IsCenterAlgo(VL_UsedSubTemplates[VL_i]) ) {
2979 P_CalculerPointsMesure( C_SERVICE_METRO_TEST , &VL_Mesure , VL_UsedSubTemplates[VL_i].Tiw_Useful_Radius , C_POSITION_CENTRE );
2980 }
2981
2982 VL_SubResultsCell[VL_ResultCurrentIndex].X_Cell = VL_Mesure.TabCell[0].X;
2983 VL_SubResultsCell[VL_ResultCurrentIndex].Y_Cell = VL_Mesure.TabCell[0].Y;
2984 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = 1;
2985
2986
2987 } else if ( PT_IsSymAlgo(VL_UsedSubTemplates[VL_i]) ) { // This algorithm should not exist for extended subtemplates
2988 VL_Aborted = 1;
2989 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2990 sprintf(VL_ErrorMsg, "Symetries algorithm should not be used for extended subtemplates\n");
2991 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2992 continue;
2993
2994 } else { // No other algorithm exists yet
2995 VL_SubResultsCell[VL_ResultCurrentIndex].Cell_Found = 0;
2996 sprintf(VL_ErrorMsg, "The algorithm '%s' for the %s template is not implemented\n",VL_UsedSubTemplates[VL_i].Tiw_Algo,VL_UsedSubTemplates[VL_i].Tiw_Name);
2997 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
2998 continue;
2999 }
3000
3001 /* Evaluate the current result measurement cell item */
3002 EP_Strcpy(VL_SubResultsCell[VL_ResultCurrentIndex].TemplateName, VL_UsedSubTemplates[VL_i].Tiw_Name);
3003 VL_SubResultsCell[VL_ResultCurrentIndex].Index = VL_SubTemplatePoints[VL_j].Tpw_Index;
3004 VL_SubResultsCell[VL_ResultCurrentIndex].Linked_Index = VL_SubTemplatePoints[VL_j].Tpw_Parent_Index;
3005 VL_SubResultsCell[VL_ResultCurrentIndex].X_Point = VL_SubTemplatePoints[VL_j].Tpw_X;
3006 VL_SubResultsCell[VL_ResultCurrentIndex].Y_Point = VL_SubTemplatePoints[VL_j].Tpw_Y;
3007 VL_SubResultsCell[VL_ResultCurrentIndex].Expo_Below_Required = VL_ExpoBelowRequired;
3008
3009 }
3010
3011 VL_ResultCurrentIndex++;
3012
3013 }
3014
3015 }
3016
3017
3018
3019 /* Free memory space */
3020 _Free(PM_Trace.FunctionName, VL_SubTemplatePoints);
3021 VL_SubTemplatePoints = NULL;
3022 }
3023
3024
3025 /* Free memory space */
3026 _Free(PM_Trace.FunctionName, VL_UsedTemplates);
3027 _Free(PM_Trace.FunctionName, VL_UsedTemplatesSizes);
3028 _Free(PM_Trace.FunctionName, VL_UsedSubTemplates);
3029 _Free(PM_Trace.FunctionName, VL_UsedSubTemplatesSizes);
3030 VL_UsedTemplates = NULL;
3031 VL_UsedTemplatesSizes = NULL;
3032 VL_UsedSubTemplates = NULL;
3033 VL_UsedSubTemplatesSizes = NULL;
3034
3035 /* Append the 2 result lists */
3036
3037 /* Get the total number of used template */
3038 (*PM_NumOfResultTemplate) = VL_NumOfTemplate + VL_NumOfSubTemplate;
3039 (*PM_NumOfResultCell) = VL_UsedTemplatesTotalSize + VL_UsedSubTemplatesTotalSize;
3040
3041 if ( ((*PM_NumOfResultCell) == 0) || ((*PM_NumOfResultTemplate) == 0) ) {
3042 // Error handling
3043 sprintf(VL_ErrorMsg, "Result is empty. There is no data.\n");
3044 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3045 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
3046 // Free memory space
3047 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
3048 _Free(PM_Trace.FunctionName, VL_ResultsCell);
3049 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
3050 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3051 VL_ResultsTemplate = NULL;
3052 VL_ResultsCell = NULL;
3053 VL_SubResultsTemplate = NULL;
3054 VL_SubResultsCell = NULL;
3055 (*PM_NumOfResultTemplate) = 0;
3056 (*PM_NumOfResultCell) = 0;
3057 return (VL_Error);
3058 }
3059
3060 /* Allocate memory space */
3061 (*PM_ResultsTemplate) = (U_PtmesResultTemplate *) _Calloc(PM_Trace.FunctionName, (*PM_NumOfResultTemplate), sizeof(U_PtmesResultTemplate));
3062 (*PM_ResultsCell) = (U_PtmesResultCell *) _Calloc(PM_Trace.FunctionName, (*PM_NumOfResultCell), sizeof(U_PtmesResultCell));
3063
3064 if ( ((*PM_ResultsTemplate) == NULL) && ((*PM_ResultsCell) == NULL) ) {
3065 // Error handling
3066 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
3067 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3068 // Free memory space
3069 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
3070 _Free(PM_Trace.FunctionName, VL_ResultsCell);
3071 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
3072 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3073 VL_ResultsTemplate = NULL;
3074 VL_ResultsCell = NULL;
3075 VL_SubResultsTemplate = NULL;
3076 VL_SubResultsCell = NULL;
3077 (*PM_NumOfResultTemplate) = 0;
3078 (*PM_NumOfResultCell) = 0;
3079 VL_Error = C_NOT_OK;
3080 return (VL_Error);
3081 }
3082
3083 /*----------------------------------------------------------------------------*/
3084 /* Copy the contents of the list of used template in the result template list */
3085 /*----------------------------------------------------------------------------*/
3086 if ( (0 < VL_NumOfTemplate) && (NULL != VL_ResultsTemplate) ) {
3087 /* Memory copy */
3088 memcpy((U_PtmesResultTemplate *) & ((*PM_ResultsTemplate)[0]), (U_PtmesResultTemplate *) & (VL_ResultsTemplate[0]), VL_NumOfTemplate * sizeof(U_PtmesResultTemplate));
3089
3090 if ( (*PM_ResultsTemplate) == NULL ) {
3091 // Error handling
3092 sprintf(VL_ErrorMsg, "Error during memory space copy\n");
3093 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3094 // Free memory space
3095 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
3096 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
3097 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3098 VL_ResultsTemplate = NULL;
3099 VL_SubResultsTemplate = NULL;
3100 VL_SubResultsCell = NULL;
3101 (*PM_NumOfResultTemplate) = 0;
3102 (*PM_NumOfResultCell) = 0;
3103 VL_Error = C_NOT_OK;
3104 return (VL_Error);
3105 }
3106 }
3107
3108 /* Free no more used memory space */
3109 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
3110 VL_ResultsTemplate = NULL;
3111
3112 /* Copy the contents of the list of inherited template in the result list */
3113 if ( (0 < VL_NumOfSubTemplate) && (NULL != VL_SubResultsTemplate) ) {
3114 /* Memory copy */
3115 memcpy((U_PtmesResultTemplate *) & ((*PM_ResultsTemplate)[VL_NumOfTemplate]), (U_PtmesResultTemplate *) & (VL_SubResultsTemplate[0]), VL_NumOfSubTemplate * sizeof(U_PtmesResultTemplate));
3116
3117 if ( (*PM_ResultsTemplate) == NULL ) {
3118 // Error handling
3119 sprintf(VL_ErrorMsg, "Error during memory space copy\n");
3120 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3121 // Free memory space
3122 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
3123 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3124 VL_SubResultsTemplate = NULL;
3125 VL_SubResultsCell = NULL;
3126 (*PM_NumOfResultTemplate) = 0;
3127 (*PM_NumOfResultCell) = 0;
3128 VL_Error = C_NOT_OK;
3129 return (VL_Error);
3130 }
3131 }
3132
3133 /* Free no more used memory space */
3134 _Free(PM_Trace.FunctionName, VL_SubResultsTemplate);
3135 VL_SubResultsTemplate = NULL;
3136
3137 /*-----------------------------------------------------------------------------*/
3138 /* Copy the contents of the cell list of used template in the result cell list */
3139 /*-----------------------------------------------------------------------------*/
3140 if (0 < VL_UsedTemplatesTotalSize && NULL != VL_ResultsCell) {
3141 /* Memory copy */
3142 memcpy((U_PtmesResultCell *) & ((*PM_ResultsCell)[0]), (U_PtmesResultCell *) & (VL_ResultsCell[0]), VL_UsedTemplatesTotalSize * sizeof(U_PtmesResultCell));
3143
3144 if ( (*PM_ResultsCell) == NULL ) {
3145 // Error handling
3146 sprintf(VL_ErrorMsg, "Error during memory space copy\n");
3147 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3148 // Free memory space
3149 _Free(PM_Trace.FunctionName, VL_ResultsCell);
3150 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3151 VL_ResultsCell = NULL;
3152 VL_SubResultsCell = NULL;
3153 (*PM_NumOfResultTemplate) = 0;
3154 (*PM_NumOfResultCell) = 0;
3155 VL_Error = C_NOT_OK;
3156 return (VL_Error);
3157 }
3158 }
3159
3160 /* Free no more used memory space */
3161 _Free(PM_Trace.FunctionName, VL_ResultsCell);
3162 VL_ResultsCell = NULL;
3163
3164 /* Copy the contents of the list of inherited template in the result list */
3165 if (0 < VL_UsedSubTemplatesTotalSize && NULL != VL_SubResultsCell) {
3166 /* Memory copy */
3167 memcpy((U_PtmesResultCell *) & ((*PM_ResultsCell)[VL_UsedTemplatesTotalSize]), (U_PtmesResultCell *) & (VL_SubResultsCell[0]), VL_UsedSubTemplatesTotalSize * sizeof(U_PtmesResultCell));
3168
3169 if (NULL == (*PM_ResultsCell)) {
3170 // Error handling
3171 sprintf(VL_ErrorMsg, "Error during memory space copy\n");
3172 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3173 // Free memory space
3174 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3175 VL_SubResultsCell = NULL;
3176 (*PM_NumOfResultTemplate) = 0;
3177 (*PM_NumOfResultCell) = 0;
3178 VL_Error = C_NOT_OK;
3179 return (VL_Error);
3180 }
3181 }
3182
3183 /* Free no more used memory space */
3184 _Free(PM_Trace.FunctionName, VL_SubResultsCell);
3185 VL_SubResultsCell = NULL;
3186
3187 TraceLeaveFunction(&PM_Trace);
3188 return (VL_Error);
3189}
3190
3191/**
3192* @brief Constructor of a U_RecipeInfo structure
3193*
3194* @param PM_Cfg_Type
3195* @param PM_MA_Name
3196* @param PM_Rcp_Name
3197* @param PM_ID
3198* @param PM_CreationOK
3199* @param PM_CreationDetail
3200* @param PM_AlignmentPath
3201* @param PM_EdgeExclusionZone
3202* @param PM_WaferSize
3203* @param PM_GridSizeX
3204* @param PM_GridSizeY
3205* @param PM_WaferMapVectorX
3206* @param PM_WaferMapVectorY
3207* @param PM_ChipserFieldX
3208* @param PM_ChipserFieldY
3209* @param PM_FiedlSizeX
3210* @param PM_FiedlSizeY
3211* @param PM_Recipe
3212*/
3213void PT_InitRecipeInfo( const char *PM_Cfg_Type, const char *PM_MA_Name, const char *PM_Rcp_Name,
3214int PM_ID, char PM_CreationOK, const char *PM_CreationDetail, const char *PM_AlignmentPath,
3215float PM_EdgeExclusionZone, float PM_WaferSize, float PM_GridSizeX, float PM_GridSizeY,
3216float PM_WaferMapVectorX, float PM_WaferMapVectorY, float PM_ChipserFieldX, float PM_ChipserFieldY,
3217float PM_FiedlSizeX, float PM_FiedlSizeY, U_RecipeInfo *PM_Recipe ){
3218 EP_Strcpy(PM_Recipe->Cfg_Type, PM_Cfg_Type);
3219 EP_Strcpy(PM_Recipe->MA_Name, PM_MA_Name);
3220 EP_Strcpy(PM_Recipe->Rcp_Name, PM_Rcp_Name);
3221 PM_Recipe->CreationOK = PM_CreationOK;
3222 PM_Recipe->ID = PM_ID;
3223 EP_Strcpy(PM_Recipe->CreationDetail, PM_CreationDetail);
3224 EP_Strcpy(PM_Recipe->AlignmentPath, PM_AlignmentPath);
3225 PM_Recipe->EdgeExclusionZone = PM_EdgeExclusionZone;
3226 PM_Recipe->WaferSize = PM_WaferSize;
3227 PM_Recipe->GridSizeX = PM_GridSizeX;
3228 PM_Recipe->GridSizeY = PM_GridSizeY;
3229 PM_Recipe->WaferMapVectorX = PM_WaferMapVectorX;
3230 PM_Recipe->WaferMapVectorY = PM_WaferMapVectorY;
3231 PM_Recipe->ChipserFieldX = PM_ChipserFieldX;
3232 PM_Recipe->ChipserFieldY = PM_ChipserFieldY;
3233 PM_Recipe->FiedlSizeX = PM_FiedlSizeX;
3234 PM_Recipe->FiedlSizeY = PM_FiedlSizeY;
3235
3236}
3237
3238/**
3239* @brief Print main info of a RecipeInfo structure
3240*
3241* @param PM_Recipe
3242*/
3243void PT_PrintRecipeInfo( const U_RecipeInfo *PM_Recipe){
3244 printf("Recipe: (%s, %s, %s, %c, %s, %d, %f, %f)\n", PM_Recipe->Cfg_Type, PM_Recipe->MA_Name, PM_Recipe->Rcp_Name,
3245 PM_Recipe->CreationOK, PM_Recipe->CreationDetail, PM_Recipe->ID, PM_Recipe->FiedlSizeX, PM_Recipe->FiedlSizeY);
3246}
3247
3248/* === FUNCTION ======================================================================
3249* Name: PT_OrderMetroType
3250* ===================================================================================== */
3251int PT_OrderMetroType(const void *PM_p1, const void *PM_p2) {
3252 /*--------------------------------------------------------------------------
3253 * Declaration
3254 *--------------------------------------------------------------------------
3255 */
3256 const U_RecipeInfo *VL_p1 = (U_RecipeInfo *) PM_p1;
3257 const U_RecipeInfo *VL_p2 = (U_RecipeInfo *) PM_p2;
3258
3259 if ( (EP_Strcmp(VL_p1->Cfg_Type, VL_p2->Cfg_Type) == 0) ){
3260 return EP_Strcmp(&VL_p2->CreationOK, &VL_p1->CreationOK);
3261 }
3262
3263 return (EP_Strcmp(VL_p1->Cfg_Type, VL_p2->Cfg_Type)) ;
3264}
3265
3266
3267/* === FUNCTION ======================================================================
3268* Name: PT_GetIFMappings
3269* ===================================================================================== */
3270int PT_GetIFMappings(U_Trace PM_Trace, char *PM_MaskName, char *PM_RecipeName, char *PM_Metro, U_MappingSpecIF **PM_MappingSpecs, int *PM_MappingSpecsCount) {
3271 EXEC SQL BEGIN DECLARE SECTION;
3272 char *VL_SqlRequest = NULL;
3273 U_InqSQL VL_SqlStatus ;
3274 char VL_TifName[16]; /* Template name(1pt_BKL,...) */
3275 char VL_Label[41]; /* Label */
3276 char VL_LayerID[3]; /* Layer ID */
3277 char VL_RefLayerID[3]; /* RefLayer ID (should be "" for some technos) */
3278 char VL_Type[16]; /* type (frame vs not frame) */
3279 char VL_MaName[8];
3280 char VL_ConfigType[51]; // config type (e.g. Caliper/Scattero/ ...
3281 EXEC SQL END DECLARE SECTION;
3282 U_MappingSpecIF *VL_MappingSpecs = NULL;
3283 int VL_NbSpecs;
3284 int VL_Error = C_OK;
3285 int VL_i;
3286 const int VL_RecipeListSize = EP_Strlen(PM_RecipeName);
3287 char VL_RecipeQuery[VL_RecipeListSize * 2 + 256];
3288 const int VL_QuerySize = sizeof(VL_RecipeQuery) + 3042;
3289 TraceEnterFunction(&PM_Trace, "PT_GetIFMappings", "maskname=%s", PM_MaskName);
3290
3291 // managing reciepe stuff
3292 if ((PM_RecipeName != NULL) && (EP_Strcmp(PM_RecipeName,"\0") != 0)){
3293 sprintf(VL_RecipeQuery, " AND (vi.RCP_NAME IN (%s) \
3294 OR 'ALL' = ALL (%s)) \
3295 AND pat.CFG_TYPE = '%s'", PM_RecipeName, PM_RecipeName, PM_Metro);
3296 }else{
3297 *VL_RecipeQuery='\0';
3298 }
3299
3300 // Allocate Memory for query
3301 VL_SqlRequest = (char *) _Calloc(PM_Trace.FunctionName, VL_QuerySize, sizeof(char));
3302
3303 if ( VL_SqlRequest == NULL){
3304 PT_Error(C_ER_CALLOC, PM_Trace, NULL, NULL);
3305 snprintf(VG_Msg_Dat_Err, 2047, "GetIFMappings: alloc error for %d bytes)", VL_QuerySize);
3306 return (C_NOT_OK);
3307 }
3308 // allocating space for result
3309 TracePrint(&PM_Trace, "allocating space for result (guess < 100)\n");
3310 VL_NbSpecs = 100;
3311 VL_MappingSpecs = (U_MappingSpecIF*) malloc ( sizeof(U_MappingSpecIF) * VL_NbSpecs);
3312 if ( VL_MappingSpecs==NULL ) {
3313 sprintf(VG_Msg_Dat_Err, "error while allocating %d MappingSpecs (ie %d bytes)",VL_NbSpecs, VL_NbSpecs * sizeof(U_MappingSpecIF));
3314 // Free memory space
3315 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3316 VL_SqlRequest = NULL;
3317 return PT_Error(C_ER_MSG, PM_Trace, VG_Msg_Dat_Err, "" );
3318 }
3319 TracePrint(&PM_Trace, "Allocation DONE\n");
3320 sprintf(VL_SqlRequest, "SELECT DISTINCT tif.TIF_NAME, vi.MA_NAME, pat.FD_MARKER_LABEL, pat.MP_LAYER_ID, \n\
3321 pat.fd_ref_layer_id , tif.TIF_TYPE\n\
3322FROM VW_EXE_PTMES_RCP_CURRENT vi, stc_ptmes_template_if tif, \n\
3323 (SELECT 'Scattero' AS CFG_TYPE, RCP_NAME, MA_NAME, TC_TECHNO, RCP_IF, FD_MARKER_LABEL, MP_LAYER_ID,'' as fd_ref_layer_id FROM stc_ptmes_cfg_sc_pattern \n\
3324 UNION ALL \n \
3325 SELECT 'Semcd' AS CFG_TYPE, RCP_NAME, MA_NAME, TC_TECHNO, RCP_IF, FD_MARKER_LABEL, MP_LAYER_ID,'' as fd_ref_layer_id FROM stc_ptmes_cfg_cd_pattern \n\
3326 UNION ALL \n\
3327 SELECT 'Archer' AS CFG_TYPE, RCP_NAME, MA_NAME, TC_TECHNO, RCP_IF, FD_MARKER_LABEL, MP_LAYER_ID, fd_ref_layer_id FROM STC_PTMES_CFG_OVARC_PATTERN \n\
3328 UNION ALL \n\
3329 SELECT 'Caliper' AS CFG_TYPE, WO_OPE_NAME || '-' || RCP_REF_OPE_NAME || '-' || RCP_VERSION AS RCP_NAME, MA_NAME, TC_TECHNO, \n\
3330 RCP_IF, FD_MARKER_LABEL, MP_LAYER_ID, fd_ref_layer_id FROM STC_PTMES_CFG_OVCAL \n\
3331 UNION ALL \n\
3332 SELECT 'YieldstarOv' AS CFG_TYPE, cop.RCP_NAME, cop.MA_NAME, cop.TC_TECHNO, \n\
3333 cosa.RCP_IF, cop.FD_MARKER_LABEL, cop.MP_LAYER_ID, cop.fd_ref_layer_id FROM STC_PTMES_CFG_OVYIELD_PATTERN cop \n\
3334 join STC_PTMES_CFG_OVYIELD_SAMPLE cosa on (cop.RCP_NAME = cosa.RCP_NAME and cop.MA_NAME = cosa.MA_NAME and cop.TC_TECHNO = cosa.TC_TECHNO and cop.RCP_PATTERN = cosa.RCP_PATTERN ) \n\
3335 ) pat \n \
3336WHERE vi.RCP_NAME = pat.RCP_NAME \n \
3337AND vi.CFG_MA_NAME = pat.MA_NAME \n \
3338AND vi.TC_TECHNO = pat.TC_TECHNO \n \
3339AND tif.TIF_NAME = pat.RCP_IF \n \
3340AND vi.MA_NAME = '%s' \n \
3341AND vi.CFG_TYPE = pat.CFG_TYPE \n \
3342AND NOT EXISTS (SELECT * \n \
3343 FROM stc_ptmes_mapping_if mif \n \
3344 WHERE tif.TIF_NAME = mif.TIF_NAME \n \
3345 AND pat.FD_MARKER_LABEL = mif.FD_MARKER_LABEL \n \
3346 AND pat.MP_LAYER_ID = mif.MP_LAYER_ID \n \
3347 AND NVL(pat.fd_ref_layer_id,'NULL') = NVL(mif.fd_ref_layer_id, 'NULL') \n \
3348 AND tif.TIF_NAME = mif.MIF_NAME \n \
3349 AND mif.MIF_TYPE = 'Automatic' \n \
3350 AND mif.MIF_STATE = 1 \n \
3351 AND mif.MA_NAME = vi.MA_NAME \n \
3352 ) %s", PM_MaskName, VL_RecipeQuery);
3353
3354 TracePrint(&PM_Trace, "Query = >%s<\n", VL_SqlRequest);
3355
3356 EXEC SQL DECLARE CURSOR_MAPPING_IF STATEMENT;
3357 EXEC SQL PREPARE CURSOR_MAPPING_IF FROM :VL_SqlRequest;
3358 EXEC SQL DECLARE MappingCursor CURSOR FOR CURSOR_MAPPING_IF;
3359 Trace_DB("pt_calcul.pc", "ptmeas", "req_10");
3360 EXEC SQL OPEN MappingCursor;
3361
3362 TracePrint(&PM_Trace, "Opening the cursor\n");
3363 // Open the cursor
3364 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
3365 if (C_OK != VL_Error ) {
3366 char VL_ErrorMsg[1024];
3367 snprintf(VL_ErrorMsg, 1023, "File %s: error while opening cursor \n", __FILE__);
3368 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText);
3369 snprintf(VG_Msg_Dat_Err, 2047, "data base error while getting mappings to compute");
3370
3371 // Free memory space
3372 free(VL_MappingSpecs);
3373 VL_MappingSpecs = NULL;
3374 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3375 VL_SqlRequest = NULL;
3376 return (C_ER_SQL);
3377 }
3378 TracePrint(&PM_Trace, "Cursor Opened \n");
3379 VL_SqlStatus.RowCount = -1; // to map Ingres behavior
3380 VL_i = 0;
3381 while (1){ /* two ways of going out: i) Error -> print and return ii) VL_SqlStatus.RowCount = 0 -> exit normally */
3382 EXEC SQL FETCH MappingCursor
3383 INTO
3384 :VL_TifName,
3385 :VL_MaName,
3386 :VL_Label,
3387 :VL_LayerID,
3388 :VL_RefLayerID,
3389 :VL_Type;
3390 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3391 char VL_ErrorMsg[1024];
3392 snprintf(VL_ErrorMsg,1023, "File %s, function %s: error while fetching cursor \"CURSOR_MAPPING_FRAME\"", __FILE__, PM_Trace.FunctionName);
3393 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText );
3394 snprintf(VG_Msg_Dat_Err, 2047, "data base error while getting mappings to compute)");
3395 // Free memory space
3396 free(VL_MappingSpecs);
3397 VL_MappingSpecs = NULL;
3398 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3399 VL_SqlRequest = NULL;
3400 return (VL_Error);
3401 }
3402 if (VL_SqlStatus.RowCount == 0) break;
3403 TracePrint(&PM_Trace, "Adding %dth mapping: (%s, %s, %s, %s, %s)\n", VL_i, VL_TifName, VL_Label, VL_LayerID, VL_RefLayerID, VL_Type);
3404
3405 // check if we have room for putting the result, else adding a chunk of size 100
3406 if (VL_i >= VL_NbSpecs){
3407 VL_NbSpecs+=100;
3408 VL_MappingSpecs = (U_MappingSpecIF*) realloc (VL_MappingSpecs, VL_NbSpecs * sizeof(U_MappingSpecIF));
3409 if ( VL_MappingSpecs==NULL ) {
3410 char VL_ErrorMsg[1024];
3411 sprintf(VL_ErrorMsg, "Error while allocating %d MappingSpecs (ie %d bytes)", VL_NbSpecs, VL_NbSpecs * sizeof(U_MappingSpecIF));
3412 snprintf(VG_Msg_Dat_Err, 2047, "fail to allocate space for mappings (%d bytes))", VL_NbSpecs * sizeof(U_MappingSpecIF) );
3413 // Free memory space
3414 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3415 VL_SqlRequest = NULL;
3416 return PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "" );
3417 }
3418 }
3419 EP_Strcpy(VL_MappingSpecs[VL_i].TifName, VL_TifName);
3420 EP_Strcpy(VL_MappingSpecs[VL_i].Label, VL_Label);
3421 EP_Strcpy(VL_MappingSpecs[VL_i].LayerID, VL_LayerID);
3422 EP_Strcpy(VL_MappingSpecs[VL_i].RefLayerID, VL_RefLayerID);
3423 EP_Strcpy(VL_MappingSpecs[VL_i].Type, VL_Type);
3424 EP_Strcpy(VL_MappingSpecs[VL_i].MifName, "");
3425 VL_i++;
3426 }
3427
3428 // Fitting VL_MappingSpecs to its real size (i.e. the number of TIF, which is VL_i)
3429 if (VL_i > 0){ //if there are no new IntraField template, VL_MappingSpecs is NOT to be reallocated
3430
3431 VL_MappingSpecs = (U_MappingSpecIF*) realloc(VL_MappingSpecs, VL_i*sizeof(U_MappingSpecIF));
3432
3433 if ( VL_MappingSpecs==NULL ) {
3434 char VL_ErrorMsg[1024];
3435 sprintf(VL_ErrorMsg, "Error while allocating %d MappingSpecs (ie %d bytes)", VL_i, VL_i * sizeof(U_MappingSpecIF));
3436 snprintf(VG_Msg_Dat_Err, 2047, "fail to allocate space for mappings (%d bytes))", VL_i * sizeof(U_MappingSpecIF) );
3437 // Free memory space
3438 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3439 VL_SqlRequest = NULL;
3440 return PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "" );
3441 }
3442 }
3443
3444 // Close the cursor
3445 EXEC SQL CLOSE MappingCursor;
3446 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3447 char VL_ErrorMsg[1024];
3448 sprintf(VL_ErrorMsg, "\nFile %s, function %s: error while closing cursor \"CURSOR_MAPPING_IF\"", __FILE__, PM_Trace.FunctionName);
3449 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText);
3450 snprintf(VG_Msg_Dat_Err, 2047, "data base error while getting mappings to compute)");
3451 // Free memory space
3452 free(VL_MappingSpecs);
3453 VL_MappingSpecs = NULL;
3454 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3455 VL_SqlRequest = NULL;
3456 return (VL_Error);
3457 }
3458
3459 // Copying data to the out parameter
3460 *PM_MappingSpecs = VL_MappingSpecs;
3461 *PM_MappingSpecsCount = VL_i;
3462 // Free memory space
3463 _Free(PM_Trace.FunctionName, VL_SqlRequest);
3464 VL_SqlRequest = NULL;
3465
3466 TraceLeaveFunction(&PM_Trace);
3467 return C_OK;
3468}
3469
3470
3471/* === FUNCTION ======================================================================
3472* Name: PT_ComputeMappingIFFrame
3473* ===================================================================================== */
3474int PT_ComputeMappingIFFrame(U_Trace PM_Trace, char *PM_MaskName, char *PM_LayerID, char *PM_RefLayerID, char *PM_Label, char *PM_Corner, U_PtmesTemplPoint *PM_Points, unsigned *PM_PointsCount) {
3475 // code to know what we got
3476 unsigned char VL_CornerCode=0; /* 0 BKL, 1 BKR, 2 FTL, 3 FTR, 4 ALL, 5 nothing good */
3477 char VL_ErrorMsg[1024];
3478 int VL_Error;
3479 char *VL_CornerNames[] = {"1pt_FTL", "1pt_BKL", "1pt_BKR", "1pt_FTR", "1pt_ALL" };
3480 EXEC SQL BEGIN DECLARE SECTION;
3481 char VL_SqlRequest[1024];
3482 U_InqSQL VL_SqlStatus ;
3483 double VL_X, VL_Y;
3484 EXEC SQL END DECLARE SECTION;
3485
3486
3487 TraceEnterFunction(&PM_Trace, "PT_ComputeMappingIFFrame", "Maskname=%s, LayerID=%s, RefLayerID=%s, Label=%s, template=%s",
3488 PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label, PM_Corner);
3489
3490 *PM_PointsCount = 0;
3491 VL_Error = C_OK;
3492 for ( VL_CornerCode = 0; VL_CornerCode < 5; ++VL_CornerCode ) {
3493 if ( EP_Strcmp(PM_Corner, VL_CornerNames[VL_CornerCode]) == 0) {
3494 break;
3495 }
3496 }
3497 if (VL_CornerCode == 5) { /* PM_Corner does not match any of the possible value */
3498 snprintf(VG_Msg_Dat_Err, 2047, "File %s: Corner identifier (%s) does not match any of the possible values \n", __FILE__, PM_Corner);
3499 PT_Error(C_ER_MSG, PM_Trace, VG_Msg_Dat_Err, "");
3500 return C_NOK;
3501 }
3502 if (VL_CornerCode == 4) { /*dealing with the 1pt_All patterns by a recursive call on each corner */
3503 TracePrint(&PM_Trace,"%s template: recursive call with each sub template \n", PM_Corner );
3504 for ( int VL_i = 0; VL_i < 4; ++VL_i ) {
3505 TracePrint(&PM_Trace, "template 1pt_ALL : recursive call with %s\n", VL_CornerNames[VL_i]);
3506 unsigned VL_tempCount;
3507 int VL_LocalError = PT_ComputeMappingIFFrame(PM_Trace, PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label, VL_CornerNames[VL_i], PM_Points, &VL_tempCount);
3508 if (C_OK != VL_LocalError) {
3509 sprintf(VL_ErrorMsg, "Error while getting point in corner %s", VL_CornerNames[VL_i]);
3510 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3511 }else{
3512 if (VL_tempCount == 1) {
3513 (*PM_PointsCount)++;
3514 PM_Points++;
3515 }
3516
3517 }
3518 }
3519 // case where 0 points found is not necessarily an error. It should be properly handled by caller
3520 return C_OK;
3521 }
3522
3523 // dealing with a unique point
3524 sprintf(VL_SqlRequest, "SELECT FD_X,FD_Y FROM STC_FIELD WHERE \n\
3525 ROWNUM <=1 AND MA_NAME = '%s' \n\
3526 AND MP_LAYER_ID = '%s' \n\
3527 AND NVL(FD_REF_LAYER_ID, 'NULL') = NVL('%s', 'NULL') \n\
3528 AND FD_MARKER_LABEL = '%s' \n\
3529 AND FD_POSITION = '%s' \n\
3530 ORDER BY ABS(FD_Y) DESC, ABS(FD_X) DESC ",
3531 PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label, PM_Corner + 4);
3532 TracePrint(&PM_Trace, "Query: >%s< \n", VL_SqlRequest);
3533
3534 EXEC SQL DECLARE CURSOR_IF_FRAME_curs1 STATEMENT;
3535 EXEC SQL PREPARE CURSOR_IF_FRAME_curs1 FROM :VL_SqlRequest;
3536 EXEC SQL DECLARE PointsCursor CURSOR FOR CURSOR_IF_FRAME_curs1;
3537 Trace_DB("pt_calcul.pc", "ptmeas", "req_11");
3538 EXEC SQL OPEN PointsCursor;
3539 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
3540 if (C_OK != VL_Error ) {
3541 sprintf(VL_ErrorMsg, "File %s: error while opening cursor", __FILE__);
3542 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText);
3543 snprintf(VG_Msg_Dat_Err, 2047, "Mapping IF Frame: Data base error while getting mappings to compute");
3544 return (VL_Error);
3545 }
3546 // Get the point if any
3547 *PM_PointsCount = 0;
3548 EXEC SQL FETCH PointsCursor INTO :VL_X, :VL_Y;
3549 VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
3550 if (C_OK != VL_Error ) {
3551 sprintf(VL_ErrorMsg, "File %s: error while fetching cursor", __FILE__);
3552 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText);
3553 snprintf(VG_Msg_Dat_Err, 2047, "Mapping IF Frame: Data base error while getting mappings to compute");
3554 }
3555 TracePrint(&PM_Trace, "VL_SqlStatus.RowCount %d\n", VL_SqlStatus.RowCount);
3556
3557 if ((VL_Error == C_OK) && (VL_SqlStatus.RowCount > 0)){
3558 PM_Points->Pt_Pos_X = VL_X;
3559 PM_Points->Pt_Pos_Y = VL_Y;
3560 PM_Points->Pt_Indice = 0;
3561 *PM_PointsCount = 1;
3562 }
3563 // case where 0 points found is not necessarily an error. It should be properly handled by caller
3564
3565 // Close the cursor
3566 EXEC SQL CLOSE PointsCursor;
3567 if (C_OK != PT_InquireSQL(PM_Trace, &VL_SqlStatus) ) {
3568 snprintf(VG_Msg_Dat_Err, 2047, "Mapping IF Frame: Data base error while getting mappings to compute");
3569 sprintf(VL_ErrorMsg, "File %s: error while closing cursor", __FILE__);
3570 PT_Error(C_ER_SQL, PM_Trace , VL_ErrorMsg, VL_SqlStatus.ErrorText);
3571 VL_Error = C_ER_SQL;
3572 }
3573 TraceLeaveFunction(&PM_Trace);
3574 return VL_Error;
3575}
3576
3577/* === FUNCTION ======================================================================
3578* Name: PT_Comp_PtmesTemplPointYdescXasc
3579* ===================================================================================== */
3580int PT_Comp_PtmesTemplPointYdescXasc(const void *PM_p1, const void *PM_p2) {
3581 const U_PtmesTemplPoint *VL_p1 = (U_PtmesTemplPoint *) PM_p1;
3582 const U_PtmesTemplPoint *VL_p2 = (U_PtmesTemplPoint *) PM_p2;
3583 if (VL_p1->Pt_Comp_Value > VL_p2->Pt_Comp_Value) { return -1;}
3584 if (VL_p1->Pt_Comp_Value < VL_p2->Pt_Comp_Value) { return 1;}
3585 // we come here if PM_p1->Pt_Pos_Y == PM_p2->Pt_Pos_Y)
3586 if (VL_p1->Pt_Pos_X < VL_p2->Pt_Pos_X) { return -1;}
3587 if (VL_p1->Pt_Pos_X > VL_p2->Pt_Pos_X) { return 1;}
3588 return 0;
3589}
3590
3591
3592
3593/* === FUNCTION ======================================================================
3594* Name: PT_CompMeasurementPoints
3595* ===================================================================================== */
3596int PT_GetMeasurementPoints(PM_Trace, PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label, PM_MeasurementPoints, PM_MeasurementPointsCount)
3597U_Trace PM_Trace;
3598EXEC SQL BEGIN DECLARE SECTION;
3599char *PM_MaskName; /* in: name of the mask set */
3600char *PM_LayerID; /* in: the layer ID */
3601char *PM_RefLayerID; /* in: ref layer ID needed for some metrologies */
3602char *PM_Label; /* in: label */
3603EXEC SQL END DECLARE SECTION;
3604U_PtmesTemplPoint **PM_MeasurementPoints;
3605unsigned *PM_MeasurementPointsCount;
3606{
3607
3608 EXEC SQL BEGIN DECLARE SECTION;
3609 char VL_SqlStatement[1024];
3610 U_InqSQL VL_SqlStatus ;
3611 int VL_Count = 0;
3612 U_PtmesTemplPoint VL_MeasurementPoint;
3613 EXEC SQL END DECLARE SECTION;
3614 char VL_ErrorMsg[1024];
3615 int VL_Error = C_OK;
3616 int VL_i = 0;
3617
3618 TraceEnterFunction(&PM_Trace, "PT_GetMeasurementPoints", "maskname=%s layerID=%s, refLayerID=%s, label=%s", PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label);
3619 sprintf(VL_SqlStatement, "SELECT COUNT(*) INTO :VL_Count FROM STC_FIELD WHERE MA_NAME = %s AND MP_LAYER_ID = %s AND NVL(FD_REF_LAYER_ID, 'NULL') = NVL('%s', 'NULL') AND FD_MARKER_LABEL = %s", PM_MaskName, PM_LayerID ,PM_RefLayerID, PM_Label);
3620 TracePrint(&PM_Trace, "PT_GetMeasurementPoints: query %s\n", VL_SqlStatement);
3621 EXEC SQL SELECT COUNT(*) INTO :VL_Count FROM STC_FIELD WHERE MA_NAME = :PM_MaskName AND MP_LAYER_ID = :PM_LayerID AND NVL(FD_REF_LAYER_ID, 'NULL') = NVL(:PM_RefLayerID, 'NULL') AND FD_MARKER_LABEL = :PM_Label;
3622 Trace_DB("pt_calcul.pc", "ptmeas", "req_14");
3623 if ( C_OK != (VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus)) ) {
3624 PT_Error(C_ER_SQL, PM_Trace , "Error while counting the number of Measurement points", VL_SqlStatus.ErrorText);
3625 return (VL_Error);
3626 }
3627 *PM_MeasurementPointsCount = VL_Count;
3628 if (VL_Count ==0 ){ return (C_OK);} // this case is not necessarily an error. It should be properly handled by caller
3629 *PM_MeasurementPointsCount = VL_Count;
3630 // allocating space for result
3631 *PM_MeasurementPoints = (U_PtmesTemplPoint *) _Calloc(PM_Trace.FunctionName, VL_Count, sizeof(U_PtmesTemplPoint));
3632 if (NULL == *PM_MeasurementPoints) {
3633 sprintf(VL_ErrorMsg, "Error during memory space allocation:\nTryed to allocate %ld bytes", VL_Count * sizeof(U_PtmesTemplPoint));
3634 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3635 snprintf(VG_Msg_Dat_Err, 2047, "Select IF: Internal allocation error");
3636 return (C_ER_CALLOC);
3637 }
3638 // build the query
3639 sprintf(VL_SqlStatement, "SELECT FD_X,FD_Y FROM STC_FIELD \n \
3640 WHERE MA_NAME = '%s' \n\
3641 AND MP_LAYER_ID = '%s' \n\
3642 AND NVL(FD_REF_LAYER_ID, 'NULL') = NVL('%s', 'NULL') \n\
3643 AND FD_MARKER_LABEL = '%s' ",
3644 PM_MaskName, PM_LayerID, PM_RefLayerID, PM_Label);
3645 TracePrint(&PM_Trace, "Query for getting measurment points: %s\n", VL_SqlStatement);
3646 // Declare a dynamic cursor
3647 EXEC SQL DECLARE SQL_measurementCursor STATEMENT;
3648 EXEC SQL PREPARE SQL_measurementCursor FROM :VL_SqlStatement;
3649 EXEC SQL DECLARE IfPointsCursor CURSOR FOR SQL_measurementCursor;
3650 Trace_DB("pt_calcul.pc", "ptmeas", "req_15");
3651 // Open the cursor
3652 EXEC SQL OPEN IfPointsCursor;
3653 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
3654 if (C_OK != VL_Error ) {
3655 PT_Error(C_ER_SQL, PM_Trace , "PT_GetMeasurmentPoint: error while opening cursor \"STC_INTRA_Cursor\"", VL_SqlStatus.ErrorText);
3656 snprintf(VG_Msg_Dat_Err, 2047, "Select IF: Database error");
3657 return (VL_Error);
3658 }
3659 VL_i = 0;
3660 VL_SqlStatus.RowCount = -1; // to map Ingres behavior
3661 while (C_OK == VL_Error && 0 != VL_SqlStatus.RowCount && VL_i < VL_Count) {
3662 // Get and store the next record data
3663 EXEC SQL FETCH IfPointsCursor
3664 INTO
3665 :VL_MeasurementPoint.Pt_Pos_X,
3666 :VL_MeasurementPoint.Pt_Pos_Y;
3667 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3668 PT_Error(C_ER_SQL, PM_Trace , "PT_GetMeasurmentPoint: error while fetching cursor \"STC_INTRA_Cursor\"", VL_SqlStatus.ErrorText);
3669 snprintf(VG_Msg_Dat_Err, 2047, "Select IF: Database error");
3670 return (VL_Error);
3671 }
3672 (*PM_MeasurementPoints)[VL_i].Pt_Pos_X = VL_MeasurementPoint.Pt_Pos_X;
3673 (*PM_MeasurementPoints)[VL_i].Pt_Pos_Y = VL_MeasurementPoint.Pt_Pos_Y;
3674 VL_i++;
3675 }
3676 // Close the cursor
3677 EXEC SQL CLOSE IfPointsCursor;
3678 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3679 PT_Error(C_ER_SQL, PM_Trace , "PT_GetMeasurmentPoint: error while closing cursor \"STC_INTRA_Cursor\"", VL_SqlStatus.ErrorText);
3680 snprintf(VG_Msg_Dat_Err, 2047, "Select IF: Database error");
3681 return (VL_Error);
3682 }
3683 if (VG_Verbose > 1) {
3684 TracePrint(&PM_Trace, "Measurement points coordinates: %d\n", VL_Count);
3685 for (VL_i = 0; VL_i < VL_Count ; ++VL_i ) {
3686 TracePrint(&PM_Trace,"pt num %d -> (%lf, %lf)\n", VL_i, (*PM_MeasurementPoints)[VL_i].Pt_Pos_X, (*PM_MeasurementPoints)[VL_i].Pt_Pos_Y);
3687 }
3688 }
3689 TraceLeaveFunction(&PM_Trace);
3690 return VL_Error;
3691}
3692
3693/* === FUNCTION ======================================================================
3694* Name: PT_ComputeIdealPoints
3695* ===================================================================================== */
3696int PT_ComputeIdealPoints( U_Trace PM_Trace, char *PM_Template, double PM_MaskCellSizeX, double PM_MaskCellSizeY, U_PtmesTemplPoint ** PM_IdealPoints, unsigned *PM_IdealPointsCount ) {
3697 int VL_Error = C_OK;
3698 char VL_ErrorMsg[1024];
3699
3700 int VL_i;
3701 int VL_Return = 0;
3702 EXEC SQL BEGIN DECLARE SECTION;
3703 char VL_SqlStatement[1024];
3704 U_InqSQL VL_SqlStatus ;
3705 int VL_Count;
3706 U_PtmesTemplPoint VL_PourcentIdealPoint;
3707 char * VL_Template;
3708 EXEC SQL END DECLARE SECTION;
3709 VL_Template = PM_Template;
3710 TraceEnterFunction(&PM_Trace, "PT_ComputeIdealPoints", "template: %s", VL_Template) ;
3711 TracePrint(&PM_Trace, "PT_ComputeIdealPoints: get the number of ideal points: SELECT COUNT(*) INTO :VL_Count FROM STC_PTMES_IDEAL_POINT_IF WHERE TIF_NAME=%s\n", VL_Template);
3712 EXEC SQL SELECT COUNT(*) INTO :VL_Count FROM STC_PTMES_IDEAL_POINT_IF WHERE TIF_NAME=:VL_Template;
3713 Trace_DB("pt_calcul.pc", "ptmeas", "req_16");
3714 // get the number of ideal points
3715 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
3716 if ( C_OK != VL_Error) {
3717 sprintf(VL_ErrorMsg, "File %s: Error while counting the number of STC_PTMES_IDEAL_POINT_IF for template %s", __FILE__, VL_Template);
3718 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:ComputeIdealPoints : DB error while counting number of ideal points");
3719 PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
3720 return (VL_Error);
3721 }
3722 TracePrint(&PM_Trace,"nb pts found: %d\n", VL_Count);
3723
3724 // allocate space for the points
3725 // get the ideal points purcentages
3726 *PM_IdealPointsCount = VL_Count;
3727 *PM_IdealPoints = (U_PtmesTemplPoint *) _Calloc(PM_Trace.FunctionName, VL_Count, sizeof(U_PtmesTemplPoint));
3728 if (NULL == *PM_IdealPoints) {
3729 sprintf(VL_ErrorMsg, "Error during memory space allocation:\nFILE %s:%d: trying to allocate %ld bytes", __FILE__, __LINE__, VL_Count * sizeof(U_PtmesTemplPoint));
3730 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3731 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:ComputeIdealPoints: allocation error");
3732 return (C_ER_CALLOC);
3733 }
3734 // build the query
3735 sprintf(VL_SqlStatement, "SELECT TPF_X,TPF_Y,TPF_INDEX FROM STC_PTMES_IDEAL_POINT_IF WHERE TIF_NAME = '%s'", VL_Template);
3736 TracePrint(&PM_Trace, "ComputeIdealPoint: getting Ideal points query: %s;\n", VL_SqlStatement);
3737 // Declare a dynamic cursor
3738 EXEC SQL DECLARE SQL_IdealPtsCursor STATEMENT;
3739 EXEC SQL PREPARE SQL_IdealPtsCursor FROM :VL_SqlStatement;
3740 EXEC SQL DECLARE IfIdealPointsCursor CURSOR FOR SQL_IdealPtsCursor;
3741 Trace_DB("pt_calcul.pc","ptmeas","req_17");
3742 // Open the cursor
3743 EXEC SQL OPEN IfIdealPointsCursor;
3744
3745 if (C_OK != (VL_Return = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3746 PT_Error(C_ER_MSG, PM_Trace, "Cursor opening failed\n", "");
3747 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:ComputeIdealPoints: DB Error (opening cursor)");
3748 return (VL_Return);
3749 }
3750 VL_i = 0;
3751 VL_SqlStatus.RowCount = -1; // to map Ingres behavior
3752 while (C_OK == VL_Return && 0 != VL_SqlStatus.RowCount && VL_i < VL_Count) {
3753 // Get and store the next record data
3754 EXEC SQL FETCH IfIdealPointsCursor
3755 INTO
3756 :VL_PourcentIdealPoint.Pt_Pos_X,
3757 :VL_PourcentIdealPoint.Pt_Pos_Y,
3758 :VL_PourcentIdealPoint.Pt_Indice;
3759
3760 VL_Return = PT_InquireSQL(PM_Trace, &VL_SqlStatus);
3761 if (C_OK != VL_Return) {
3762 PT_Error(C_ER_MSG, PM_Trace, "Cursor fetching failed\n", "");
3763 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:ComputeIdealPoints: DB Error (fetching data from cursor)");
3764 return (VL_Return);
3765 }
3766 (*PM_IdealPoints)[VL_i].Pt_Pos_X = VL_PourcentIdealPoint.Pt_Pos_X * PM_MaskCellSizeX * 10; /* *1000 as the unit is the milimter in mask and in micro in intrafield */
3767 (*PM_IdealPoints)[VL_i].Pt_Pos_Y = VL_PourcentIdealPoint.Pt_Pos_Y * PM_MaskCellSizeY * 10;
3768 (*PM_IdealPoints)[VL_i].Pt_Indice = VL_PourcentIdealPoint.Pt_Indice;
3769 VL_i++;
3770 }
3771 // Close the cursor
3772 EXEC SQL CLOSE IfIdealPointsCursor;
3773 if (C_OK != (VL_Return = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
3774 PT_Error(C_ER_MSG, PM_Trace, "Cursor closing failed\n", "");
3775 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:ComputeIdealPoints: DB Error (closing cursor)");
3776 return (VL_Return);
3777 }
3778 if (VG_Verbose >1){
3779 TracePrint(&PM_Trace,"Ideal points coordinates: %d\n", VL_Count);
3780 for (VL_i = 0; VL_i < VL_Count ; ++VL_i ) {
3781 TracePrint(&PM_Trace,"pt num %d -> (%lf, %lf)\n", VL_i, (*PM_IdealPoints)[VL_i].Pt_Pos_X, (*PM_IdealPoints)[VL_i].Pt_Pos_Y);
3782 }
3783 }
3784 TraceLeaveFunction(&PM_Trace);
3785 return VL_Error;
3786}
3787
3788/* === FUNCTION ======================================================================
3789* Name: PT_SelectIFVoronoi
3790* ===================================================================================== */
3791int PT_SelectIFVoronoi(U_Trace PM_Trace, char *PM_MaskName, char *PM_LayerID, char *PM_RefLayerID, char *PM_Label, char *PM_Template,
3792U_PtmesTemplPoint **PM_VoronoiMeasurementPoints, unsigned *PM_VoronoiMeasurementPointsCount) {
3793 EXEC SQL BEGIN DECLARE SECTION;
3794 char *VL_MaskName; /* in: name of the mask set */
3795 U_InqSQL VL_SqlStatus ;
3796 float VL_MaskCellSizeX;
3797 float VL_MaskCellSizeY;
3798 EXEC SQL END DECLARE SECTION;
3799
3800 VL_MaskName = PM_MaskName;
3801 U_PtmesTemplPoint* VL_MeasurementPoints; /* will contain the measurement point before selection */
3802 unsigned VL_MeasurementPointsCount; /* will contain the size of the above set */
3803 U_PtmesTemplPoint* VL_IdealPoints; /* will contain the ideal points */
3804 unsigned VL_IdealPointsCount; /* will contain the size of the above set */
3805 int* VL_IndexVoronoiPoints; /* index of the voronoi points in VL_MeasurePoints */
3806 char VL_ErrorMsg[256];
3807 int VL_Error = C_OK;
3808 int VL_i;
3809
3810 TraceEnterFunction(&PM_Trace, "PT_SelectIFVoronoi", "maskname=%s layerID=%s, refLayerID=%s, label=%s templat=%s", VL_MaskName, PM_LayerID, PM_RefLayerID , PM_Label, PM_Template);
3811 TracePrint(&PM_Trace, "getting the measurement points\n");
3812 VL_Error = PT_GetMeasurementPoints(PM_Trace,VL_MaskName,PM_LayerID, PM_RefLayerID, PM_Label, &VL_MeasurementPoints, &VL_MeasurementPointsCount);
3813 TracePrint(&PM_Trace, "%s: number of initial measurement pts found: %d\n", PM_Trace.FunctionName, VL_MeasurementPointsCount);
3814
3815 if (C_OK != VL_Error) {
3816 PT_Error(VL_Error, PM_Trace , "Error while querying for measurement points", "");
3817 return (VL_Error);
3818 }
3819 if (VL_MeasurementPointsCount == 0){
3820 *PM_VoronoiMeasurementPointsCount = 0;
3821 return (C_OK); // this case is not necessarily an error. It should be properly handled by caller
3822 }
3823 TracePrint(&PM_Trace, "getting the mask cell size \n");
3824
3825 // getting the cell size for the mask
3826 EXEC SQL SELECT MA_X_OVERLAP INTO :VL_MaskCellSizeX FROM STC_MASK WHERE MA_NAME = :VL_MaskName;
3827 Trace_DB("pt_calcul.pc", "ptmeas", "req_12");
3828 if ( C_OK != (VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus)) ) {
3829 PT_Error(C_ER_SQL, PM_Trace , "Error while querying the DB for reading mask cell size X", VL_SqlStatus.ErrorText);
3830 snprintf(VG_Msg_Dat_Err, 2047, "Select IF Voronoi: unable to fetch mask cell size X from DB");
3831 return (VL_Error);
3832 }
3833 EXEC SQL SELECT MA_Y_OVERLAP INTO :VL_MaskCellSizeY FROM STC_MASK WHERE MA_NAME = :VL_MaskName;
3834 Trace_DB("pt_calcul.pc", "ptmeas", "req_13");
3835 if ( C_OK != (VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus)) ) {
3836 PT_Error(C_ER_SQL, PM_Trace , "Error while querying the DB for reading mask cell size Y", VL_SqlStatus.ErrorText);
3837 snprintf(VG_Msg_Dat_Err, 2047, "Select IF Voronoi: unable to fetch mask cell size Y from DB");
3838 return (VL_Error);
3839 }
3840 TracePrint(&PM_Trace, "Done\n");
3841 TracePrint(&PM_Trace, "Getting the ideal points\n");
3842
3843 // getting the ideal points
3844 VL_Error = PT_ComputeIdealPoints(PM_Trace, PM_Template, VL_MaskCellSizeX, VL_MaskCellSizeY, &VL_IdealPoints, &VL_IdealPointsCount);
3845 if (C_OK != VL_Error) {
3846 PT_Error(VL_Error, PM_Trace , "Error while getting ideal points", VL_SqlStatus.ErrorText);
3847 return (VL_Error);
3848 }
3849
3850 TracePrint(&PM_Trace, "Got %d Ideal points\n", VL_IdealPointsCount);
3851 TracePrint(&PM_Trace, "Selecting the ideal points (using Voronoi property)\n");
3852
3853 // selecting the voronoi measurement points
3854 VL_IndexVoronoiPoints = (int *) malloc(VL_IdealPointsCount * sizeof(int));
3855 if (! VL_IndexVoronoiPoints) {
3856 sprintf(VL_ErrorMsg, "Error while allocating %d int (ie %d bytes)\n", VL_IdealPointsCount, VL_IdealPointsCount * sizeof(int));
3857 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "" );
3858 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:SelectIFVoronoi: Allocation error\n");
3859 return C_ER_CALLOC;
3860 }
3861 VL_Error = selectIF(VL_MeasurementPoints, VL_MeasurementPointsCount, VL_IdealPoints, VL_IdealPointsCount, VL_IndexVoronoiPoints );
3862 if (C_OK != VL_Error) {
3863 PT_Error(VL_Error, PM_Trace, "Error while selecting voronoi Points", "" );
3864 return VL_Error;
3865 }
3866 TracePrint(&PM_Trace, "Ideal point selected\n");
3867 // VL_IndexVoronoiPoints[i] = index of the measurement point the closest from region i
3868 if (VG_Verbose > 1) {
3869 for ( int VL_j = 0; VL_j < VL_IdealPointsCount; VL_j += 1 ) {
3870 TracePrint(&PM_Trace, "VL_IndexVoronoiPoints[%d]=%d\n", VL_j, VL_IndexVoronoiPoints[VL_j]);
3871 if (VL_IndexVoronoiPoints[VL_j] <0){
3872 TracePrint(&PM_Trace, "Empty cell for Measurement Point (%f,%f) \n", VL_MeasurementPoints[VL_j].Pt_Pos_X, VL_MeasurementPoints[VL_j].Pt_Pos_Y);
3873 }else{
3874 TracePrint(&PM_Trace, "Measurement Point (%f,%f) -> Ideal Point %d (%f,%f)\n",
3875 VL_MeasurementPoints[VL_IndexVoronoiPoints[VL_j]].Pt_Pos_X, VL_MeasurementPoints[VL_IndexVoronoiPoints[VL_j]].Pt_Pos_Y,
3876 VL_IndexVoronoiPoints[VL_j],
3877 VL_MeasurementPoints[VL_IndexVoronoiPoints[VL_j]].Pt_Pos_X, VL_MeasurementPoints[VL_IndexVoronoiPoints[VL_j]].Pt_Pos_Y);
3878 }
3879 }
3880 }
3881 TracePrint(&PM_Trace, "Building the final set\n");
3882
3883 // building the final set
3884 *PM_VoronoiMeasurementPoints = (U_PtmesTemplPoint *) malloc (VL_IdealPointsCount * sizeof(U_PtmesTemplPoint));
3885 if (! PM_VoronoiMeasurementPoints) {
3886 sprintf(VL_ErrorMsg, "Error while allocating %d int (ie %d bytes)", VL_IdealPointsCount, VL_IdealPointsCount * sizeof(U_PtmesTemplPoint));
3887 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "" );
3888 snprintf(VG_Msg_Dat_Err, 2047, "SelectIF:SelectIFVoronoi: Allocation error (2)\n");
3889 return C_ER_CALLOC;
3890 }
3891 // copying to the final structure: the ith final point is located in measurementPoint at index given by indexVoronoiPoint[i]
3892 *PM_VoronoiMeasurementPointsCount = 0;
3893 for ( VL_i = 0; VL_i < VL_IdealPointsCount; ++VL_i ) {
3894 if ( VL_IndexVoronoiPoints[VL_i] >= 0){
3895 memcpy((*PM_VoronoiMeasurementPoints) + (*PM_VoronoiMeasurementPointsCount), VL_MeasurementPoints + VL_IndexVoronoiPoints[VL_i], sizeof(U_PtmesTemplPoint));
3896 (*PM_VoronoiMeasurementPointsCount)++;
3897 }
3898 }
3899 *PM_VoronoiMeasurementPoints = realloc(*PM_VoronoiMeasurementPoints, (*PM_VoronoiMeasurementPointsCount) * sizeof(U_PtmesTemplPoint) );
3900 /*// sorting
3901 if (VG_Verbose > 0) {
3902 TracePrint(&PM_Trace, "Final set built\n");
3903 TracePrint(&PM_Trace, "Sorting\n");
3904 }
3905 qsort(*PM_VoronoiMeasurementPoints, *PM_VoronoiMeasurementPointsCount, sizeof(U_PtmesTemplPoint), PT_Comp_PtmesTemplPointYdescXasc);
3906 if (VG_Verbose > 0) {
3907 TracePrint(&PM_Trace, "Sorted\n");
3908 TracePrint(&PM_Trace, "Cleaning temp arrays\n");
3909 }*/
3910 // cleaning temporary arrays
3911 free(VL_IndexVoronoiPoints);
3912 free(VL_MeasurementPoints);
3913 free(VL_IdealPoints);
3914
3915 TraceLeaveFunction(&PM_Trace);
3916 return VL_Error; /* should be ok if we end up here */
3917}
3918
3919
3920/* === FUNCTION ======================================================================
3921* Name: PT_SetMappingSites
3922* ===================================================================================== */
3923int PT_SetMappingSites(U_Trace PM_Trace, int PM_MappingID, U_PtmesTemplPoint *PM_MeasurementSites, unsigned PM_MeasurementSitesCount) {
3924 EXEC SQL BEGIN DECLARE SECTION;
3925 U_InqSQL VL_SqlStatus ;
3926 int VL_MappingID;
3927 int VL_Rank;
3928 double VL_PosX;
3929 double VL_PosY;
3930 int VL_IdxIdealPoint;
3931 EXEC SQL END DECLARE SECTION;
3932 int VL_Error = C_OK;
3933
3934 TraceEnterFunction(&PM_Trace, "PT_SetMappingSites", "%s mappingID=%d", PM_Trace.FunctionName, PM_MappingID);
3935
3936 // if no measurement site -> exit directly.
3937 if (PM_MeasurementSitesCount == 0){
3938 TraceLeaveFunction(&PM_Trace);
3939 return VL_Error;
3940 }
3941
3942 VL_MappingID = PM_MappingID;
3943 for ( int VL_i = 0; VL_i < PM_MeasurementSitesCount; VL_i += 1 ) {
3944 VL_Rank = VL_i+1;
3945 VL_PosX =PM_MeasurementSites[VL_i].Pt_Pos_X ;
3946 VL_PosY =PM_MeasurementSites[VL_i].Pt_Pos_Y ;
3947 VL_IdxIdealPoint = PM_MeasurementSites[VL_i].Pt_Indice+1;
3948 TracePrint(&PM_Trace, "Query for inserting site : EXEC SQL INSERT INTO STC_PTMES_MAPPING_SITE(MIF_ID, MS_INDEX, MS_X, MS_Y, MS_TEMPL_INDEX) values(%d, %d, %f, %f, %d)\n", VL_MappingID, VL_Rank, VL_PosX, VL_PosY, VL_IdxIdealPoint);
3949 EXEC SQL INSERT INTO STC_PTMES_MAPPING_SITE(MIF_ID, MS_INDEX, MS_X, MS_Y, MS_TEMPL_INDEX)
3950 values(:VL_MappingID, :VL_Rank, :VL_PosX, :VL_PosY, :VL_IdxIdealPoint);
3951 Trace_DB("pt_calcul.pc", "ptmeas", "req_18");
3952 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
3953 if ( C_OK != VL_Error) {
3954 char VL_ErrorMsg[2048];
3955 sprintf(VL_ErrorMsg, "File %s, function %s: Error while inserting into DB (table STC_PTMES_MAPPING_SITE", __FILE__, PM_Trace.FunctionName);
3956 return PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
3957 }
3958 snprintf(VG_Msg_Dat_Err, 2047, "Select IF:SetMappingSites: Error while inserting Mappings in DB");
3959 }
3960 TraceLeaveFunction(&PM_Trace);
3961 return VL_Error;
3962}
3963
3964
3965/* === FUNCTION ======================================================================
3966* Name: PT_SortMappingSites
3967* ===================================================================================== */
3968int PT_SortMappingSites(U_Trace PM_Trace, U_Mask *PM_Mask, U_PtmesTemplPoint *PM_MeasurementSites, unsigned PM_MeasurementSitesCount){
3969 int VL_Error = C_OK;
3970 char VL_ErrorMsg[2048];
3971 int VL_SliceCount = 0;
3972 double VL_SliceHeigth = 0;
3973
3974
3975 // we need sqrt(nb_pt) slices rounded to upper value
3976 VL_SliceCount = round(0.5+sqrt(PM_MeasurementSitesCount));
3977 if (VL_SliceCount < 1) {
3978 VL_Error = C_KO;
3979 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF : Error while sorting sites \n");
3980 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3981 return VL_Error;
3982 }
3983 // Coupute slice heigth
3984 VL_SliceHeigth = PM_Mask->MA_YOverlap * 1000 / VL_SliceCount;
3985
3986 if (VL_SliceHeigth <= 0) {
3987 VL_Error = C_KO;
3988 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF : Error while sorting sites \n");
3989 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
3990 return VL_Error;
3991 }
3992
3993 // Compute slice for sorting
3994 for ( int VL_i = 0; VL_i < PM_MeasurementSitesCount; VL_i += 1 ) {
3995 PM_MeasurementSites[VL_i].Pt_Comp_Value = round(PM_MeasurementSites[VL_i].Pt_Pos_Y/VL_SliceHeigth-0.499999999); // not -0.5 so that a site at Y=0 will be in slice 0
3996 }
3997 // QSORT
3998 qsort(PM_MeasurementSites, PM_MeasurementSitesCount, sizeof(U_PtmesTemplPoint), PT_Comp_PtmesTemplPointYdescXasc);
3999 return VL_Error; // should be ok if we end up here
4000}
4001
4002/* === FUNCTION ======================================================================
4003* Name: PT_SetMappingIF
4004* ===================================================================================== */
4005int PT_SetMappingIF(U_Trace PM_Trace, char *PM_MaName, char *PM_LayerID, char *PM_RefLayerID, char *PM_Label, char *PM_TifName, char *PM_MifName, char *PM_Comment, int *PM_MappingID) {
4006 EXEC SQL BEGIN DECLARE SECTION;
4007 char VL_Query[2048];
4008 U_InqSQL VL_SqlStatus ;
4009 int VL_MappingID;
4010 EXEC SQL END DECLARE SECTION;
4011 char *VL_MifTypeAuto = C_AUTOMATIC_TEMPLATE;
4012 char *VL_MifTypeCustom = C_CUSTOM_TEMPLATE;
4013 char *VL_MifType = VL_MifTypeAuto; /* by default, consider it automatic */
4014
4015 int VL_Error = C_OK;
4016 char VL_ErrorMsg[2048];
4017 TraceEnterFunction(&PM_Trace, "PT_SetMappingIF", "maskname=%s layerID=%s", PM_MaName, PM_LayerID);
4018
4019 // preparing the data for the query
4020 // automatic vs custom mode
4021 if (*PM_MifName == '\0'){ /* automatic mode */
4022 PM_MifName = PM_TifName;
4023 VL_MifType = VL_MifTypeAuto;
4024 }else{ /* custom mode */
4025 VL_MifType = VL_MifTypeCustom;
4026 }
4027 EXEC SQL SELECT SEQ_MAPPING_IF.nextval INTO :VL_MappingID FROM DUAL;
4028 Trace_DB("pt_calcul.pc","ptmeas","req_19");
4029 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
4030 if ( C_OK != VL_Error) {
4031 char VL_ErrorMsg[2048];
4032 snprintf(VL_ErrorMsg, 2048, "File %s: Error while getting an index from DB (sequence SEQ_MAPPING_IF)", __FILE__);
4033 return PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
4034 }
4035 TracePrint(&PM_Trace, "mapping id=%d\n", VL_MappingID);
4036 // Building the query
4037 if (PM_Comment == NULL ){
4038 sprintf(VL_Query, "INSERT INTO STC_PTMES_MAPPING_IF ( \n\
4039 MIF_ID, MA_NAME, MIF_NAME, MIF_DATE, US_ID, \n\
4040 FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID, \n\
4041 TIF_NAME, MIF_TYPE, MIF_STATE, MIF_COMMENT) VALUES \n\
4042 ( %d, '%s', '%s', SYSDATE, '%d', '%s', '%s', '%s', '%s', '%s', 1, NULL)"
4043 , VL_MappingID,PM_MaName, PM_MifName, VG_UserID, PM_Label, PM_LayerID, PM_RefLayerID,PM_TifName, VL_MifType);
4044 }
4045 else{
4046 sprintf(VL_Query, "INSERT INTO STC_PTMES_MAPPING_IF ( \n\
4047 MIF_ID, MA_NAME, MIF_NAME, MIF_DATE, US_ID, \n\
4048 FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID, \n\
4049 TIF_NAME, MIF_TYPE, MIF_STATE, MIF_COMMENT) VALUES \n\
4050 ( %d, '%s', '%s', SYSDATE, '%d', '%s', '%s', '%s', '%s', '%s', 1, '%s')"
4051 , VL_MappingID,PM_MaName, PM_MifName, VG_UserID, PM_Label, PM_LayerID, PM_RefLayerID,PM_TifName, VL_MifType,PM_Comment);
4052 }
4053 EXEC SQL EXECUTE IMMEDIATE :VL_Query;
4054 Trace_DB("pt_calcul.pc", "ptmeas", "req_20");
4055 TracePrint(&PM_Trace, "Query for inserting mapping: %s\n", VL_Query);
4056 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
4057 if ( C_OK != VL_Error) {
4058 snprintf(VL_ErrorMsg, 2047, "File %s, Error while inserting into DB (table STC_PTMES_MAPPING_IF", __FILE__) ;
4059 return PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
4060 }
4061 *PM_MappingID = VL_MappingID;
4062 EP_Commit();
4063 TraceLeaveFunction(&PM_Trace);
4064 return VL_Error;
4065}
4066
4067/* === FUNCTION ======================================================================
4068* Name: PT_ComputeDumpMappingIF
4069* ===================================================================================== */
4070int PT_ComputeDumpMappingIF(U_Trace PM_Trace, U_Mask *PM_Mask, char *PM_RecipeName, U_MappingSpecIF *PM_MaSpec, U_MetroError *PM_Err, int *PM_MappingID, char *PM_Comment){
4071 U_PtmesTemplPoint *VL_Points = NULL; // required to be null as it is realloced in selectIFVoronoi
4072 unsigned VL_PointsCount=0;
4073 char VL_RefLayerIDLabel[50];
4074 int VL_Error= C_OK;
4075 char VL_ErrorMsg[2048];
4076 int VL_MappingID;
4077
4078 if (*PM_MaSpec->RefLayerID == '\0') {
4079 sprintf(VL_RefLayerIDLabel, "");
4080 } else {
4081 sprintf(VL_RefLayerIDLabel, ",%s", PM_MaSpec->RefLayerID);
4082 }
4083 TraceEnterFunction(&PM_Trace, "PT_ComputeDumpMappingIF", "maskname=%s, mapping (LayerID=%s, RefLayerID=\"%s\", Label=\"%s\", Template=\"%s\")",
4084 PM_Mask->MA_Name, PM_MaSpec->LayerID, VL_RefLayerIDLabel, PM_MaSpec->Label, PM_MaSpec->TifName );
4085 VL_Points = NULL; // required to be null as it is realloced in selectIFVoronoi
4086 if ( 0 == EP_Strcmp(PM_MaSpec->Type, "Frame")) {
4087 TracePrint(&PM_Trace,"Frame mapping \n");
4088 // Frame mapping
4089 VL_Points = realloc(VL_Points, 4 * sizeof(U_PtmesTemplPoint) );
4090 VL_Error = PT_ComputeMappingIFFrame(PM_Trace, PM_Mask->MA_Name,
4091 PM_MaSpec->LayerID, PM_MaSpec->RefLayerID,
4092 PM_MaSpec->Label, PM_MaSpec->TifName,
4093 VL_Points, &VL_PointsCount);
4094 if (C_OK != VL_Error) {
4095 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): error while selecting sites. \n",
4096 PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4097 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4098 Err_AddError(PM_Err, computeIF, VL_ErrorMsg );
4099 return VL_Error;
4100 }
4101 } else {
4102 // Standard IF mapping, we select according to the Voronoi property
4103 VL_Error = PT_SelectIFVoronoi(PM_Trace, PM_Mask->MA_Name,
4104 PM_MaSpec->LayerID, PM_MaSpec->RefLayerID, PM_MaSpec->Label, PM_MaSpec->TifName,
4105 &VL_Points, &VL_PointsCount);
4106 if (C_OK != VL_Error) {
4107 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): error while selecting sites. \n",
4108 PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4109 PT_Error(C_ER_MSG, PM_Trace,VL_ErrorMsg, "");
4110 Err_AddError(PM_Err, computeIF, VL_ErrorMsg );
4111 return VL_Error;
4112 }
4113 VL_Error = PT_SortMappingSites(PM_Trace, PM_Mask, VL_Points, VL_PointsCount);
4114 if (C_OK != VL_Error) {
4115 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): Error while soting mapping sites. \n",
4116 PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4117 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4118 Err_AddError(PM_Err, computeIF, VL_ErrorMsg );
4119 return VL_Error;
4120 }
4121 }
4122 if (VL_PointsCount == 0){
4123 snprintf(VL_ErrorMsg, 2047, "Warning: Mapping IF %s (%s,%s%s): no measurement site found. \n",PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4124 PT_Error(C_ER_MSG, PM_Trace,VL_ErrorMsg, "");
4125 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): no measurement site found. \n",PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4126 Err_AddError(PM_Err, computeIF, VL_ErrorMsg);
4127 VL_MappingID = -1;
4128 }
4129 else if (VL_PointsCount >0){
4130 // saving mapping to db and update mappingID
4131 TracePrint(&PM_Trace,"inserting Mapping ID in DB\n");
4132 if (VG_Verbose > 1) {
4133 for ( int VL_j = 0; VL_j < VL_PointsCount; VL_j += 1 ) {
4134 TracePrint(&PM_Trace, "Mapping site[%d]\n", VL_j, VL_Points[VL_j]);
4135 TracePrint(&PM_Trace, "Measurement Point (%f,%f) Index : %d\n",
4136 VL_Points[VL_j].Pt_Pos_X, VL_Points[VL_j].Pt_Pos_Y, VL_Points[VL_j].Pt_Indice+1);
4137 }
4138 }
4139 VL_Error = PT_SetMappingIF(PM_Trace, PM_Mask->MA_Name, PM_MaSpec->LayerID, PM_MaSpec->RefLayerID, PM_MaSpec->Label, PM_MaSpec->TifName, PM_MaSpec->MifName, PM_Comment, &VL_MappingID);
4140 if (C_OK != VL_Error) {
4141 PT_Error(C_ER_MSG, PM_Trace, "Unable to save mappping IF to db\n", "");
4142 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): Error while saving mapping in database. error : \n",
4143 PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4144 Err_AddError(PM_Err, computeIF, VL_ErrorMsg );
4145 return VL_Error;
4146 }
4147 TracePrint(&PM_Trace,"insertion OK (Mapping ID=%d)\n", VL_MappingID);
4148
4149 // insert mapping sites in DB
4150 TracePrint(&PM_Trace," inserting Mapping Sites in DB (%d elem) \n", VL_PointsCount);
4151 VL_Error = PT_SetMappingSites(PM_Trace, VL_MappingID, VL_Points, VL_PointsCount);
4152 if (C_OK != VL_Error) {
4153 snprintf(VL_ErrorMsg, 2047, "\t\tMapping IF %s (%s,%s%s): Error while saving mapping sites in database. \n",
4154 PM_MaSpec->TifName, PM_MaSpec->Label, PM_MaSpec->LayerID, VL_RefLayerIDLabel);
4155 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4156 Err_AddError(PM_Err, computeIF, VL_ErrorMsg );
4157 return VL_Error;
4158 }
4159 TracePrint(&PM_Trace,"Site insertion OK \n");
4160 }
4161 *PM_MappingID = VL_MappingID;
4162 free(VL_Points);
4163 TraceLeaveFunction(&PM_Trace);
4164 return VL_Error; // should be ok if we end up here
4165}
4166
4167
4168/* === FUNCTION ======================================================================
4169* Name: PT_ComputeIntraField
4170* ===================================================================================== */
4171int PT_ComputeIntraField(U_Trace PM_Trace, U_Mask *PM_Mask, char *PM_RecipeName, char *PM_Metro, U_MappingSpecIF *PM_MaSpec, U_MetroError *PM_Err, int *PM_MappingID, char *PM_Comment ){
4172
4173 /*--------------------------------------------------------------------------
4174 * Declaration
4175*--------------------------------------------------------------------------
4176 */
4177 U_MappingSpecIF *VL_MappingSpecs = NULL; // set of mappings that we need to compute
4178 int VL_MappingSpecsCount; // number of mapping to compute
4179
4180 int VL_Error= C_OK;
4181 char VL_ErrorMsg[2048];
4182
4183 /*--------------------------------------------------------------------------
4184 * Initialisation
4185*--------------------------------------------------------------------------
4186 */
4187 /* Custom Computation */
4188 if ( PM_MaSpec != NULL ){
4189 TraceEnterFunction(&PM_Trace, "PT_ComputeIntraField", "maskname=%s, mapping (LayerID=%s, RefLayerID=\"%s\", Label=\"%s\", Template=\"%s\")",
4190 PM_Mask->MA_Name, PM_MaSpec->LayerID, PM_MaSpec->RefLayerID, PM_MaSpec->Label, PM_MaSpec->TifName );
4191 }
4192 /* Automatic Computation */
4193 else {
4194 TraceEnterFunction(&PM_Trace, "PT_ComputeIntraField", "maskname=%s", PM_Mask->MA_Name);
4195 }
4196
4197 /*--------------------------------------------------------------------------
4198 * Instructions
4199*--------------------------------------------------------------------------
4200 */
4201 /* Automatic Computation */
4202 if ( PM_MaSpec == NULL ){
4203 // Getting IF Mappings to compute
4204 TracePrint(&PM_Trace, "Getting IF Mappings to compute \n");
4205 VL_Error = PT_GetIFMappings(PM_Trace, PM_Mask->MA_Name, PM_RecipeName, PM_Metro, &VL_MappingSpecs, &VL_MappingSpecsCount);
4206 if (C_OK != VL_Error) {
4207 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, VG_Msg_Dat_Err);
4208 Err_AddError(PM_Err, computeIF, VG_Msg_Dat_Err );
4209 return VL_Error;
4210 }
4211 TracePrint(&PM_Trace, "Got %d IF Mappings to compute \n", VL_MappingSpecsCount);
4212 // Compute each mapping
4213 for ( int VL_i = 0; VL_i < VL_MappingSpecsCount; VL_i += 1 ) {
4214 // Error is managed in sub function ... do not overload logs.
4215
4216 PT_ComputeDumpMappingIF(PM_Trace, PM_Mask, PM_RecipeName, VL_MappingSpecs+VL_i, PM_Err, PM_MappingID, NULL);
4217 }
4218 }
4219 /* Custom Computation */
4220 else {
4221 VL_Error = PT_ComputeDumpMappingIF(PM_Trace, PM_Mask, NULL, PM_MaSpec, PM_Err, PM_MappingID, PM_Comment);
4222 }
4223
4224 TracePrint(&PM_Trace, "Computation/dump done\n");
4225
4226 if ( VL_MappingSpecs != NULL) {
4227 free(VL_MappingSpecs);
4228 }
4229 TraceLeaveFunction(&PM_Trace);
4230 return VL_Error; // should be ok if we end up here
4231}
4232
4233/*
4234* === FUNCTION ======================================================================
4235* Name: PT_SendReportMail
4236* =====================================================================================
4237*/
4238int PT_SendReportMail(U_Trace PM_Trace, const int PM_WriteMode, U_Mask PM_Mask, const char *PM_Metro, const char *PM_RecipeName, const char *PM_Subject, const char *PM_Address,
4239char **PM_MappingErrors, const int PM_MappingErrorsCount, U_MetroError *PM_Error) {
4240
4241 /*--------------------------------------------------------------------------
4242 * Declaration
4243 *--------------------------------------------------------------------------
4244 */
4245 char *VL_MailFileName = NULL;
4246 int VL_Error = C_OK;
4247 FILE *VL_MailHandle = NULL;
4248 int VL_NbFailure = 0;
4249 int VL_NbSuccess = 0;
4250 char VL_MailCMD[1024];
4251 char VL_ErrorMsg[1024];
4252 int VL_i, VL_j;
4253 char VL_MetroType[16] = {'\0'};
4254 char VL_Equipment[51] = {'\0'};
4255 int VL_SuccessFlag = 0 ;
4256 int VL_ErrorFlag = 0 ;
4257
4258 U_Recipe *VL_Recipe = NULL;
4259 int VL_NumberOfRecipe = 0;
4260 char *VL_GeneralError = NULL;
4261 U_MetroErrorID VL_MetroID;
4262
4263 /*--------------------------------------------------------------------------
4264 * Initialisation
4265 *--------------------------------------------------------------------------
4266 */
4267 TraceEnterFunction(&PM_Trace, "PT_SendReportMail", "");
4268 TracePrint(&PM_Trace, "Creating file for storing email\n");
4269 VL_MetroID = generalID;
4270
4271
4272 /*--------------------------------------------------------------------------
4273 * Instructions
4274*--------------------------------------------------------------------------
4275 */
4276 // Create the temp file for the final email /tmp/pid_ppid_date
4277 errno=0;
4278 VL_MailHandle = mkTempFileName(&VL_MailFileName);
4279 if (! VL_MailHandle){
4280 sprintf(VL_ErrorMsg, "Unable to create tempFile (%s)\n", strerror(errno));
4281 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4282 return (C_NOK);
4283 }
4284
4285 /* Get recipe and equipment */
4286 VL_Error = PT_GetRecipeAndConfig(PM_Trace, 0, PM_Mask.MA_Name, (char *) PM_Metro, (char *) PM_RecipeName, &VL_Recipe, &VL_NumberOfRecipe, NULL);
4287
4288 if ( VL_Error != C_OK){
4289 sprintf(VL_ErrorMsg, "Database issue.\n");
4290 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4291 if ( VL_Recipe != NULL ){
4292 _Free(PM_Trace.FunctionName, VL_Recipe);
4293 VL_Recipe = NULL;
4294 }
4295 Err_AddError(PM_Error, generalID, "Database issue.\n");
4296 }
4297 else if (VL_NumberOfRecipe == 0) {
4298 sprintf(VL_ErrorMsg, "No recipe found.\n");
4299 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4300 if ( VL_Recipe != NULL ){
4301 _Free(PM_Trace.FunctionName, VL_Recipe);
4302 VL_Recipe = NULL;
4303 }
4304 Err_AddError(PM_Error, generalID, VL_ErrorMsg);
4305 }
4306
4307 // General failure handling
4308 VL_GeneralError = Err_GetError(PM_Error, generalID);
4309 if ( ((PM_MappingErrorsCount == 0) && (VL_NumberOfRecipe == 0))
4310 && (VL_GeneralError != NULL) && (*VL_GeneralError != '\0') ) {
4311 fprintf(VL_MailHandle, "\tGeneral failure:\n\t\t%s\n", VL_GeneralError);
4312
4313 }
4314 // Mapping and recipe processing report
4315 else {
4316 /*=== Mapping Generation report ==========================================*/
4317 /*------------------------------------------------------------------------*/
4318 if ( PM_WriteMode == C_FALSE ){
4319
4320 // Preparing report email
4321 TracePrint(&PM_Trace, "reporting mappings errors (%d)\n", PM_MappingErrorsCount);
4322 // Mappings
4323 fprintf(VL_MailHandle, "Mapping(s):\n");
4324 if ( Err_HasError(PM_Error, computeIW) || Err_HasError(PM_Error, computeIF) ){
4325
4326 fprintf(VL_MailHandle, "\tFail to create the following mapping(s): %s\n%s", Err_GetError(PM_Error, computeIW), Err_GetError(PM_Error, computeIF));
4327 }else{
4328 fprintf(VL_MailHandle, "\tAll mappings successfully created\n");
4329 }
4330 }
4331
4332 /*=== Recipe Generation report ==========================================*/
4333 /*------------------------------------------------------------------------*/
4334 /* Recipes handling */
4335 TracePrint(&PM_Trace, "reporting recipes status: %d recipes \n", VL_NumberOfRecipe );
4336 fprintf(VL_MailHandle, "\n Recipe(s):\n");
4337
4338 if ( VL_NumberOfRecipe == 0 ){
4339 fprintf(VL_MailHandle,"\t\tNo recipe found: %s\n", VL_GeneralError);
4340 }
4341 else {
4342
4343 for ( VL_i = 0 ; VL_i < VL_NumberOfRecipe ; VL_i++ ){
4344
4345 if ( (EP_Strcmp(VL_MetroType, VL_Recipe[VL_i].Cfg_Type) != 0) || (EP_Strcmp(VL_Equipment, VL_Recipe[VL_i].Eqt_Name) != 0) ){
4346 // Initialisation of the metro being processed
4347 VL_SuccessFlag = 0;
4348 VL_ErrorFlag = 0;
4349 VL_NbFailure = 0;
4350 VL_NbSuccess = 0;
4351 EP_Strcpy(VL_MetroType, VL_Recipe[VL_i].Cfg_Type);
4352 EP_Strcpy(VL_Equipment, VL_Recipe[VL_i].Eqt_Name);
4353 VL_MetroID = Err_GetMetroID(PM_Error,VL_MetroType);
4354
4355 // Recipe name
4356 if ( (VL_Equipment != NULL) && (*VL_Equipment != '\0') ){
4357 fprintf(VL_MailHandle, "\t%s-%s:\n", VL_MetroType, VL_Equipment);
4358 }
4359 else {
4360 fprintf(VL_MailHandle, "\t%s:\n", VL_MetroType);
4361 }
4362
4363 // General failure
4364 VL_GeneralError = Err_GetError(PM_Error, VL_MetroID);
4365 // particular case for MJT : only one recipe with name FILES -> we do not print FILES
4366 if (VL_GeneralError && (*VL_GeneralError) != '\0'){
4367 if (VL_MetroID == mjtID || VL_MetroID == ptID ){
4368 fprintf(VL_MailHandle,"\t\tGeneration failure: %s\n\t\t\t%s\n", VL_GeneralError,VL_Recipe[VL_i].CreationDetail);
4369 }else{
4370 fprintf(VL_MailHandle,"\t\tGeneration failure: %s\n", VL_GeneralError);
4371 }
4372 }else{
4373 for ( VL_j = 0; VL_j < VL_NumberOfRecipe; VL_j++ ) {
4374 if ( ('1' != VL_Recipe[VL_j].CreationOK) && (EP_Strcmp(VL_MetroType,VL_Recipe[VL_j].Cfg_Type) == 0 ) ){
4375 VL_NbFailure++;
4376 }
4377 else if (EP_Strcmp(VL_MetroType,VL_Recipe[VL_j].Cfg_Type) == 0 ){
4378 VL_NbSuccess++;
4379 }
4380 }
4381 }
4382 }
4383 // Managing Generation Success
4384
4385 if ( (VL_NbSuccess > 0) && ('1' == VL_Recipe[VL_i].CreationOK) ){
4386 if ( VL_MetroID == mjtID ||VL_MetroID == ptID ){
4387 fprintf(VL_MailHandle, "\t\tGeneration success\n");
4388 }
4389 else {
4390 if ( VL_SuccessFlag == 0 ){
4391 fprintf(VL_MailHandle, "\t\tGeneration success%s: \n", (VL_NbSuccess > 1) ? "es": "");
4392 VL_SuccessFlag = 1;
4393 }
4394 fprintf(VL_MailHandle, "\t\t\t%s\n", VL_Recipe[VL_i].Rcp_Name);
4395 }
4396 }
4397
4398 // Managing Generation Failure
4399 if ( (VL_NbFailure > 0) && ('1' != VL_Recipe[VL_i].CreationOK) ){
4400 if ( VL_MetroID == mjtID ||VL_MetroID == ptID){
4401 if ('2' == VL_Recipe[VL_i].CreationOK) {
4402 fprintf(VL_MailHandle, "\t\tPartial generation failure\n");
4403 fprintf(VL_MailHandle, "\t\t\t%s\n", VL_Recipe[VL_i].CreationDetail);
4404 }
4405 else {
4406 fprintf(VL_MailHandle, "\t\tGeneration failure\n");
4407 fprintf(VL_MailHandle, "\t\t\t%s\n", VL_Recipe[VL_i].CreationDetail);
4408 }
4409 }
4410 else {
4411 if ( VL_ErrorFlag == 0 ){
4412 fprintf(VL_MailHandle, "\t\tGeneration failure%s:\n", (VL_NbFailure > 1 ) ? "s" : "" );
4413 VL_ErrorFlag = 1;
4414 }
4415 fprintf(VL_MailHandle, "\t\t\t%s%s %s \n", VL_Recipe[VL_i].Rcp_Name, (VL_Recipe[VL_i].CreationDetail != NULL) ? ":" : "", VL_Recipe[VL_i].CreationDetail);
4416 }
4417 }
4418 }
4419 }
4420 }
4421 fclose(VL_MailHandle);
4422
4423 // send mail
4424 sprintf(VL_MailCMD, "mailx -r $PROTO_MAIL_SENDER -s \"%s\" %s < %s", PM_Subject, PM_Address, VL_MailFileName);
4425 VL_Error = system(VL_MailCMD);
4426 if (VL_Error != 0){
4427 sprintf(VL_ErrorMsg, "System call for sending mail returns a non 0 value (cmd = >%s<)\n", VL_MailCMD);
4428 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4429 VL_Error = C_NOK;
4430 }
4431
4432 // cleansing
4433 remove(VL_MailFileName);
4434 free(VL_MailFileName);
4435 _Free(PM_Trace.FunctionName, VL_Recipe);
4436 VL_Recipe = NULL;
4437
4438 TraceLeaveFunction(&PM_Trace);
4439 return VL_Error;
4440}
4441
4442
4443
4444/* === FUNCTION ======================================================================
4445* Name: PT_SetRecipeInDB
4446* ===================================================================================== */
4447int PT_SetRecipeInDB(U_Trace PM_Trace, int PM_UserID, char *PM_MaskName, char *PM_Metro, char *PM_RecipeName) {
4448 int VL_UserID;
4449 char *VL_Metro = NULL;
4450 char *VL_MaskName = NULL;
4451 EXEC SQL BEGIN DECLARE SECTION;
4452 U_InqSQL VL_SqlStatus ;
4453 char *VL_Query = NULL;
4454 int VL_RecipeID;
4455 EXEC SQL END DECLARE SECTION;
4456
4457 const int VL_RecipeListSize = EP_Strlen(PM_RecipeName);
4458 char VL_QueryAddOn[VL_RecipeListSize * 2 + 2048];
4459 const int VL_QuerySize = sizeof(VL_QueryAddOn) + 5020;
4460
4461 TraceEnterFunction(&PM_Trace, "PT_SetRecipeInDB", "MaskName=%s, UserID=%d", PM_MaskName, PM_UserID);
4462 VL_UserID=PM_UserID;
4463 VL_MaskName = PM_MaskName;
4464 VL_Metro = PM_Metro;
4465 int VL_Error = C_OK;
4466
4467 char VL_ErrorMsg[4000];
4468
4469 // Allocate Memory
4470 VL_Query = (char *) _Calloc(PM_Trace.FunctionName, VL_QuerySize, sizeof(char));
4471
4472 if ( VL_Query == NULL){
4473 PT_Error(C_ER_CALLOC, PM_Trace, NULL, NULL);
4474 return (C_NOT_OK);
4475 }
4476
4477 sprintf(VL_Query, "INSERT INTO stc_ptmes_rcp \n\
4478 (RCP_ID, CFG_NAME, MA_NAME, RCP_NAME, RCP_CREATION_OK, RCP_SENT_OK, RCP_CREATION_DETAIL, RCP_DATE, US_ID) \n\
4479 WITH rcp AS (\n\
4480 SELECT DISTINCT \n\
4481 cfg_name, ma_name, rcp_name, rcp_creation_ok, CASE rcp_creation_ok WHEN '0' THEN '0' ELSE NULL END as rcp_sent_ok, \n\
4482 NVL2(rcp_creation_detail, 'Missing: ' ||rcp_creation_detail || NVL2(rcp_creation_detail2, ', Invalid: ' ||rcp_creation_detail2 , ''), \n\
4483 NVL2(rcp_creation_detail2, 'Invalid: ' ||rcp_creation_detail2 , '')) as rcp_creation_detail \n\
4484 FROM ( \n\
4485 SELECT cfg_name, ma_name, rcp_name, \n\
4486 CASE \n\
4487 WHEN (cfg_name != ALL ('MJT', 'PT', 'Viper') AND ( COUNT(*) > COUNT(miw) OR COUNT( *) > COUNT(mif) + DECODE(cfg_name,'YieldstarOv',2,0) OR COUNT( *) > SUM(IF_OK))) THEN '0' \n\
4488 WHEN (cfg_name = ANY ('MJT', 'PT') AND COUNT(miw) = 0) THEN '0' \n\
4489 WHEN ((cfg_name = ANY ('MJT', 'PT')) AND (( COUNT(*) > COUNT(miw))) AND (COUNT(miw) != 0)) THEN '2' \n\
4490 ELSE '1' \n\
4491 END AS rcp_creation_ok, \n\
4492 (LISTAGG(rcp_creation_detail ,', ' ) WITHIN GROUP (ORDER BY rcp_creation_detail)) rcp_creation_detail, \n\
4493 (LISTAGG(rcp_creation_detail2 ,', ' ) WITHIN GROUP (ORDER BY rcp_creation_detail2)) rcp_creation_detail2 \n\
4494 FROM ( \n\
4495 SELECT cfg_type cfg_name, ma_name, rcp_name, miw, mif, rcp_iw, rcp_if, rcp_pattern, FD_MARKER_LABEL, FD_REF_LAYER_ID, \n\
4496 CASE \n\
4497 WHEN if_site < RCP_MIN_IF THEN 0 \n\
4498 ELSE 1 \n\
4499 END IF_OK, \n\
4500 CASE \n\
4501 WHEN (cfg_type != 'Viper' AND MIW IS NULL ) THEN NVL2(RCP_PATTERN,'['|| RCP_PATTERN||'] ', '')||'Mapping IW ' ||rcp_iw \n\
4502 ELSE '' \n\
4503 END || CASE \n\
4504 WHEN ((cfg_type != ALL ('MJT', 'PT','Viper', 'YieldstarOv') AND MIF IS NULL) OR (MIF IS NULL AND cfg_type = 'YieldstarOv' AND RCP_PATTERN != ALL ('EP-COARSE', 'EP-FINE') )) THEN ( \n\
4505 CASE WHEN (MIW IS NULL) THEN ' and ' ELSE NVL2(RCP_PATTERN,'['|| RCP_PATTERN||'] ', '') END \n\
4506 ||'Mapping IF ' ||rcp_if || ' (' ||fd_marker_label ||',' || mp_layer_id ||NVL2(FD_REF_LAYER_ID, ','||FD_REF_LAYER_ID, '') ||')') \n\
4507 ELSE '' \n\
4508 END rcp_creation_detail, \n\
4509 CASE \n\
4510 WHEN (if_site < RCP_MIN_IF AND MIF IS NOT NULL) THEN (\n\
4511 CASE WHEN (MIW IS NULL) THEN ' and ' ELSE NVL2(RCP_PATTERN,'['|| RCP_PATTERN||'] ', '') END \n\
4512 ||'Mapping IF '||rcp_if||' (not enough sites '||if_site||'/'||rcp_min_if||') ('||fd_marker_label||','|| mp_layer_id||NVL2(FD_REF_LAYER_ID, ','||FD_REF_LAYER_ID, '') ||')') \n\
4513 ELSE '' \n\
4514 END rcp_creation_detail2 \n\
4515 FROM ( \n\
4516 SELECT CFG_TYPE,TC_TECHNO,MA_NAME,CFG_MA_NAME,RCP_NAME, CFG_DATE, GEN_DATE, RCP_ID, RCP_IW, RCP_IF, \n\
4517 (SELECT COUNT(1) FROM STC_PTMES_MAPPING_SITE s WHERE s.mif_id=MIF ) AS if_site, \n\
4518 RCP_MIN_IF, RCP_PATTERN, FD_MARKER_LABEL, FD_REF_LAYER_ID, MP_LAYER_ID, MIW, MIF \n\
4519 FROM ( \n\
4520 SELECT pat.CFG_TYPE AS CFG_TYPE, vi.TC_TECHNO, vi.MA_NAME, vi.CFG_MA_NAME, vi.RCP_NAME, vi.CFG_DATE, vi.GEN_DATE, vi.RCP_ID, pat.RCP_IW, \n\
4521 pat.RCP_IF, pat.rcp_pattern, pat.FD_MARKER_LABEL, pat.FD_REF_LAYER_ID, pat.MP_LAYER_ID, RCP_MIN_IF,\n\
4522 (SELECT MAX(w.miw_id) FROM stc_ptmes_mapping_iw w WHERE w.ma_name = vi.ma_name AND w.miw_name =pat.rcp_iw AND w.miw_state = 1) AS miw, \n\
4523 (SELECT MAX(f.mif_id) FROM stc_ptmes_mapping_if f WHERE f.ma_name = vi.ma_name AND f.mif_name = pat.rcp_if AND f.fd_marker_label = pat.fd_marker_label \n\
4524 AND f.mp_layer_id = pat.mp_layer_id AND NVL(f.fd_ref_layer_id, 'NULL') = NVL(pat.FD_REF_LAYER_ID, 'NULL') AND f.mif_state = 1 ) AS mif\n\
4525 FROM vw_exe_ptmes_rcp_current vi, \n\
4526 (SELECT 'Scattero' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, RCP_IW, RCP_IF, RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, '' AS FD_REF_LAYER_ID,0 AS RCP_MIN_IF \n\
4527 FROM stc_ptmes_cfg_sc_pattern \n\
4528 UNION ALL \n\
4529 SELECT 'Semcd' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, RCP_IW, RCP_IF, RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, '' AS FD_REF_LAYER_ID,0 AS RCP_MIN_IF \n\
4530 FROM stc_ptmes_cfg_cd_pattern \n\
4531 UNION ALL \n\
4532 SELECT CFG_NAME AS CFG_TYPE, TC_TECHNO, MA_NAME, 'Files' AS RCP_NAME, RCP_IW, NULL AS RCP_IF, NULL AS RCP_PATTERN, \n\
4533 NULL AS FD_MARKER_LABEL, NULL AS MP_LAYER_ID, '' AS FD_REF_LAYER_ID,0 AS RCP_MIN_IF \n\
4534 FROM stc_ptmes_cfg_templ_use \n\
4535 UNION ALL \n\
4536 SELECT 'Archer' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, RCP_IW, RCP_IF, RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID, RCP_MIN_IF \n\
4537 FROM STC_PTMES_CFG_OVARC_PATTERN \n\
4538 UNION ALL \n\
4539 SELECT 'YieldstarOv' AS CFG_TYPE, cop.TC_TECHNO, cop.MA_NAME, cop.RCP_NAME, cosa.RCP_IW, cosa.RCP_IF, cop.RCP_PATTERN, cop.FD_MARKER_LABEL, cop.MP_LAYER_ID, cop.FD_REF_LAYER_ID, NULL \n\
4540 FROM STC_PTMES_CFG_OVYIELD_PATTERN cop join STC_PTMES_CFG_OVYIELD_SAMPLE cosa \n\
4541 on (cop.tc_techno = cosa.tc_techno and cop.ma_name = cosa.ma_name and cop.rcp_name = cosa.rcp_name and cop.rcp_pattern = cosa.rcp_pattern) \n\
4542 UNION ALL \n\
4543 SELECT 'YieldstarOv' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, RCP_FINE_ALIGN_IW as RCP_IW, null as RCP_IF, 'EP-FINE' as rcp_pattern, null as fd_marker_label, null as mp_layer_id, null as FD_REF_LAYER_ID, NULL \n\
4544 FROM STC_PTMES_CFG_OVYIELD \n\
4545 UNION ALL \n\
4546 SELECT 'YieldstarOv' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, RCP_COARSE_ALIGN_IW as RCP_IW, null as RCP_IF, 'EP-COARSE' as rcp_pattern, null as fd_marker_label, null as mp_layer_id, null as FD_REF_LAYER_ID, NULL \n\
4547 FROM STC_PTMES_CFG_OVYIELD \n\
4548 UNION ALL \n\
4549 SELECT 'Caliper' AS CFG_TYPE, TC_TECHNO, MA_NAME, WO_OPE_NAME || '-' || RCP_REF_OPE_NAME || '-' || RCP_VERSION AS RCP_NAME, RCP_IW, RCP_IF, \n\
4550 '1' AS RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID,4 AS RCP_MIN_IF FROM STC_PTMES_CFG_OVCAL \n\
4551 UNION ALL \n\
4552 SELECT 'Viper' AS CFG_TYPE, TC_TECHNO, MA_NAME, WO_OPE_NAME || '-PH-' || RCP_VERSION AS RCP_NAME, NULL AS RCP_IW, NULL AS RCP_IF, NULL AS RCP_PATTERN, \n\
4553 NULL AS FD_MARKER_LABEL, NULL AS MP_LAYER_ID, '' AS FD_REF_LAYER_ID,0 AS RCP_MIN_IF FROM STC_PTMES_CFG_VIPER \n\
4554 ) pat \n\
4555 WHERE (vi.TC_TECHNO = pat.TC_TECHNO OR (pat.TC_TECHNO = 'ALL' AND vi.CFG_TYPE = ANY ('MJT','PT'))) \n\
4556 AND (vi.CFG_MA_NAME = pat.MA_NAME OR (vi.CFG_TYPE = ANY('MJT','PT') AND pat.MA_NAME = 'ALL' )) \n\
4557 AND vi.RCP_NAME = pat.RCP_NAME AND vi.CFG_TYPE = pat.CFG_TYPE) \n\
4558 ) r1 \n\
4559 ) GROUP BY cfg_name, ma_name, rcp_name \n\
4560 ) \n\
4561 ) \n\
4562 SELECT SEQ_RCP_ID.NEXTVAL rcp_id, rcp.*, sysdate RCP_DATE, %d US_ID \n\
4563 FROM rcp \n\
4564 WHERE ma_name= '%s'", VG_UserID, VL_MaskName);
4565
4566 if ( (PM_RecipeName != NULL) && (*PM_RecipeName != '\0')
4567 && (EP_Strcmp(VL_Metro, C_ALL_KEY) != 0) ){
4568 sprintf(VL_QueryAddOn, " AND (rcp.rcp_name IN (%s) \n\
4569 OR 'ALL' = ALL (%s)) \n\
4570 AND rcp.cfg_name = '%s'", PM_RecipeName, PM_RecipeName, VL_Metro);
4571 EP_Strcat( VL_Query, VL_QueryAddOn);
4572 }
4573
4574 TracePrint(&PM_Trace, "Fisrt insertion: %s\n", VL_Query);
4575 EXEC SQL EXECUTE IMMEDIATE :VL_Query;
4576 Trace_DB("pt_calcul.pc","ptmeas","req_21");
4577 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
4578 if ( C_OK != VL_Error) {
4579 sprintf(VL_ErrorMsg, "File %s: Error while inserting Recipe %s in DB", __FILE__ , PM_RecipeName);
4580 // Free memory space
4581 _Free(PM_Trace.FunctionName, VL_Query);
4582 VL_Query = NULL;
4583 return PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
4584 }
4585
4586 TracePrint(&PM_Trace, "Insertion OK\n");
4587
4588 sprintf(VL_Query,"INSERT INTO stc_ptmes_rcp_detail ( RCP_ID, RCP_SAMPLE_NAME, RCP_SAMPLE_ORDER, RCP_SAMPLE_GROUP, RCP_PATTERN, MIW_ID, MIF_ID ) \n\
4589 SELECT DISTINCT RCP_ID, RCP_SAMPLE_NAME, RCP_SAMPLE_ORDER, RCP_SAMPLE_GROUP, RCP_PATTERN, MIW, MIF \n\
4590 FROM ( \n\
4591 SELECT RCP_ID, RCP_SAMPLE_NAME, RCP_SAMPLE_ORDER, RCP_SAMPLE_GROUP, RCP_PATTERN, MIW, MIF, CFG_TYPE, RCP_NAME \n\
4592 FROM ( \n\
4593 SELECT pat.CFG_TYPE AS CFG_TYPE, vi.TC_TECHNO, vi.MA_NAME, vi.CFG_MA_NAME, vi.RCP_NAME, vi.CFG_DATE, \n\
4594 vi.GEN_DATE, vi.RCP_ID, pat.RCP_IW, pat.RCP_IF, pat.rcp_sample_name, pat.rcp_sample_order, pat.rcp_sample_group, pat.rcp_pattern, pat.FD_MARKER_LABEL, pat.FD_REF_LAYER_ID, pat.MP_LAYER_ID, \n\
4595 (SELECT MAX(w.miw_id) FROM stc_ptmes_mapping_iw w WHERE w.ma_name = vi.ma_name AND w.miw_name = pat.rcp_iw AND w.miw_state = 1 ) AS miw, \n\
4596 (SELECT MAX(f.mif_id) FROM stc_ptmes_mapping_if f WHERE f.ma_name = vi.ma_name AND f.mif_name = pat.rcp_if AND f.fd_marker_label = pat.fd_marker_label \n\
4597 AND f.mp_layer_id = pat.mp_layer_id AND NVL(f.fd_ref_layer_id, 'NULL') = NVL(pat.FD_REF_LAYER_ID, 'NULL') AND f.mif_state = 1 ) AS mif \n\
4598 FROM vw_exe_ptmes_rcp_current vi, \n\
4599 (SELECT 'Scattero' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_IW, RCP_IF, RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, '' AS FD_REF_LAYER_ID \n\
4600 FROM stc_ptmes_cfg_sc_pattern \n\
4601 UNION ALL \n\
4602 SELECT 'Semcd' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_IW, RCP_IF, RCP_PATTERN, \n\
4603 FD_MARKER_LABEL, MP_LAYER_ID, '' AS FD_REF_LAYER_ID FROM stc_ptmes_cfg_cd_pattern \n\
4604 UNION ALL \n\
4605 SELECT CFG_NAME AS CFG_TYPE, TC_TECHNO, MA_NAME, 'Files' AS RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_IW, NULL AS RCP_IF, NULL AS RCP_PATTERN, \n\
4606 NULL AS FD_MARKER_LABEL, NULL AS MP_LAYER_ID, '' AS FD_REF_LAYER_ID FROM stc_ptmes_cfg_templ_use \n\
4607 UNION ALL \n\
4608 SELECT 'Archer' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_IW, RCP_IF, RCP_PATTERN, \n\
4609 FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID FROM STC_PTMES_CFG_OVARC_PATTERN \n\
4610 UNION ALL \n\
4611 SELECT 'YieldstarOv' AS CFG_TYPE, cop.TC_TECHNO, cop.MA_NAME, cop.RCP_NAME, cosa.RCP_SAMPLE_NAME, cosa.RCP_SAMPLE_ORDER, cosa.RCP_SAMPLE_GROUP, cosa.RCP_IW, cosa.RCP_IF, cop.RCP_PATTERN, \n\
4612 cop.FD_MARKER_LABEL, cop.MP_LAYER_ID, cop.FD_REF_LAYER_ID FROM STC_PTMES_CFG_OVYIELD_PATTERN cop \n\
4613 join STC_PTMES_CFG_OVYIELD_SAMPLE cosa \n\
4614 on (cop.tc_techno = cosa.tc_techno and cop.ma_name = cosa.ma_name and cop.rcp_name = cosa.rcp_name and cop.rcp_pattern = cosa.rcp_pattern) \n\
4615 UNION ALL \n\
4616 SELECT 'YieldstarOv' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_FINE_ALIGN_IW as RCP_IW, null as RCP_IF, 'EP-FINE', \n\
4617 NULL as FD_MARKER_LABEL, NULL as MP_LAYER_ID, NULL as FD_REF_LAYER_ID FROM STC_PTMES_CFG_OVYIELD cop \n\
4618 UNION ALL \n\
4619 SELECT 'YieldstarOv' AS CFG_TYPE, TC_TECHNO, MA_NAME, RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, RCP_COARSE_ALIGN_IW as RCP_IW, null as RCP_IF, 'EP-COARSE', \n\
4620 NULL as FD_MARKER_LABEL, NULL as MP_LAYER_ID, NULL as FD_REF_LAYER_ID FROM STC_PTMES_CFG_OVYIELD cop \n\
4621 UNION ALL \n\
4622 SELECT 'Caliper' AS CFG_TYPE, TC_TECHNO, MA_NAME, WO_OPE_NAME || '-' || RCP_REF_OPE_NAME || '-' || RCP_VERSION AS RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, \n\
4623 RCP_IW, RCP_IF, '1' AS RCP_PATTERN, FD_MARKER_LABEL, MP_LAYER_ID, FD_REF_LAYER_ID FROM STC_PTMES_CFG_OVCAL \n\
4624 UNION ALL \n\
4625 SELECT 'Viper' AS CFG_TYPE, TC_TECHNO, MA_NAME, WO_OPE_NAME || '-PH-' || RCP_VERSION AS RCP_NAME, NULL as RCP_SAMPLE_NAME, NULL as RCP_SAMPLE_ORDER, NULL as RCP_SAMPLE_GROUP, NULL AS RCP_IW, NULL AS RCP_IF, \n\
4626 NULL AS RCP_PATTERN, NULL AS FD_MARKER_LABEL, NULL AS MP_LAYER_ID, '' AS FD_REF_LAYER_ID FROM STC_PTMES_CFG_VIPER \n\
4627 ) pat \n\
4628 WHERE (vi.TC_TECHNO = pat.TC_TECHNO OR (pat.TC_TECHNO = 'ALL' AND vi.CFG_TYPE = ANY ('MJT','PT'))) \n\
4629 AND (vi.CFG_MA_NAME = pat.MA_NAME OR (vi.CFG_TYPE = ANY('MJT','PT') AND pat.MA_NAME = 'ALL' )) \n\
4630 AND vi.RCP_NAME = pat.RCP_NAME AND vi.CFG_TYPE = pat.CFG_TYPE \n\
4631 ) \n\
4632 WHERE MIW IS NOT NULL AND (MIF IS NOT NULL OR CFG_TYPE IN ('MJT', 'PT') OR (CFG_TYPE = 'YieldstarOv' and RCP_PATTERN in ('EP-COARSE', 'EP-FINE') ) ) AND MA_NAME = '%s'", VL_MaskName);
4633
4634 if ( (PM_RecipeName != NULL) && (*PM_RecipeName != '\0')
4635 && (EP_Strcmp(VL_Metro, C_ALL_KEY) != 0) ){
4636 sprintf(VL_QueryAddOn, " AND (RCP_NAME IN (%s) \
4637 OR 'ALL' = ALL (%s)) \
4638 AND CFG_TYPE = '%s')", PM_RecipeName, PM_RecipeName, VL_Metro);
4639 }
4640 else {
4641 sprintf(VL_QueryAddOn, ")");
4642 }
4643 EP_Strcat( VL_Query, VL_QueryAddOn);
4644
4645 TracePrint(&PM_Trace, "Second insertion: %s\n", VL_Query);
4646
4647 EXEC SQL EXECUTE IMMEDIATE :VL_Query;
4648 Trace_DB("pt_calcul.pc", "ptmeas", "req_22");
4649 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
4650 if ( C_OK != VL_Error) {
4651 sprintf(VL_ErrorMsg, "File %s: Error while inserting Recipe %s in DB", __FILE__, PM_RecipeName);
4652 // Free memory space
4653 _Free(PM_Trace.FunctionName, VL_Query);
4654 VL_Query = NULL;
4655 return PT_Error(C_ER_SQL, PM_Trace, VL_ErrorMsg, VL_SqlStatus.ErrorText);
4656 }
4657 // Free memory space
4658 _Free(PM_Trace.FunctionName, VL_Query);
4659 VL_Query = NULL;
4660
4661 TraceLeaveFunction(&PM_Trace);
4662 return VL_Error;
4663}
4664
4665/* === FUNCTION ======================================================================
4666* Name: PT_ComputeIntraWafer
4667* ===================================================================================== */
4668int PT_ComputeIntraWafer (U_Trace PM_Trace, U_Mask PM_Mask, char *PM_CustomTemplateName, char *PM_CustomMappingName,
4669char *PM_Comment, char *PM_RecipeName, char *PM_MetroType, U_MetroError *PM_Err, int *PM_NumberOfMappingIW, U_PtmesMappingIW **PM_MappingIW)
4670{
4671 /*--------------------------------------------------------------------------
4672 * Input Parameters
4673 *--------------------------------------------------------------------------
4674 */
4675 /* In/Out : U_Trace PM_Trace: trace mode */
4676 /* In : U_Mask PM_Mask: maskset definition */
4677 /* In : char *PM_CustomTemplateName: Custom template name */
4678 /* In : char *PM_CustomMappingName: Custom mapping name */
4679 /* In/Out : char ***PM_MappingErrors: errors encountered */
4680 /* In/Out : int *PM_MappingErrorCount: number of errors encountered */
4681
4682 /*--------------------------------------------------------------------------
4683 * Declaration
4684 *--------------------------------------------------------------------------
4685 */
4686 int VL_Error;
4687 int VL_i, VL_j; // Loop level : VL_i (level 1), VL_j (level 2)
4688 char VL_Command[1024];
4689 char VL_ErrorMsg[256];
4690 char VL_Msg[2048];
4691
4692 /* Computation */
4693 U_PtmesResultCell *VL_ResultsCell = NULL;
4694 U_PtmesResultTemplate *VL_ResultsTemplate = NULL;
4695 int VL_NumOfResultCell = 0; // Whole number of cells for all the types of template (Standard, Subtemplate, Template Engineering) coumpound
4696 int VL_NumOfResultTemplate = 0; // Whole number of template used for all the types of template (Standard, Subtemplate, Template Engineering) coumpound
4697
4698 /* Computation final results */
4699 U_PtmesMappingIW *VL_MappingIW; // List of the mapping Intra-Wafer
4700 U_PtmesMappingCell *VL_MappingCells; // List of the mapping cell for the Intra-Wafer
4701
4702 /* Others */
4703 int VL_Index = 0; // Mapping Cells Index
4704 int VL_Found = 0; // Template - Cell link found - Flag
4705 int VL_AllCellFound = 0; // All cell found flag
4706 bool VL_JobScannerExists = 0; // Job scanner flag.
4707 int VL_NumOfTemplateRequiringExpoBelow = 0; // Nulber of template requiring exposition below measurement sites.
4708 int VL_NumOfCellNotFound = 0; // Number of cells not found.
4709 int VL_NumOfCellBelowNotExposed = 0; // Number of cells requiring no exposition below.
4710 bool VL_Exposed; // Exposition cell flag
4711
4712
4713 /*--------------------------------------------------------------------------
4714 * Initialisation
4715 *--------------------------------------------------------------------------
4716 */
4717 EP_Strcpy( PM_Trace.FunctionName, "PT_ComputeIntraWafer");
4718
4719 if ( PM_NumberOfMappingIW != NULL ){
4720 (*PM_MappingIW) = NULL;
4721 (*PM_NumberOfMappingIW) = 0;
4722 }
4723
4724
4725 if ( (EP_Strcmp(PM_CustomMappingName, "\0") != 0) && (PM_CustomMappingName != NULL) ){
4726 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "Maskset: %s, Custom Mapping: %s, Template: %s", PM_Mask.MA_Name, PM_CustomMappingName, PM_CustomTemplateName );
4727 }
4728 else if ( (EP_Strcmp(PM_CustomTemplateName, "\0") != 0) && (PM_CustomTemplateName != NULL) ) {
4729 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "Maskname: %s, Template: %s", PM_Mask.MA_Name, PM_CustomTemplateName);
4730 }
4731 else {
4732 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "%s", PM_Mask.MA_Name);
4733 }
4734
4735 // Error handling
4736 VL_Error = C_OK;
4737 sprintf(VG_Msg_Dat_Err, "\0");
4738
4739 /*--------------------------------------------------------------------------
4740 * Instructions
4741 *--------------------------------------------------------------------------
4742 */
4743 /* Compute the coordinates of the measurement cells (sites) associated to the ideal measurement points of the used templates */
4744 /*VL_Error = PT_ComputeMappingIntraWafer(PM_Trace, PM_Mask, PM_CustomTemplateName, PM_CustomMappingName, PM_RecipeName,
4745 PM_MetroType, &VL_ResultsCell, &VL_ResultsTemplate, &VL_NumOfResultCell, &VL_NumOfResultTemplate);*/
4746
4747 VL_Error = PT_ComputeCells(PM_Trace, PM_Mask, PM_CustomTemplateName, PM_CustomMappingName, PM_RecipeName,
4748 PM_MetroType, &VL_ResultsCell, &VL_ResultsTemplate, &VL_NumOfResultCell, &VL_NumOfResultTemplate, PM_Err);
4749
4750
4751 if ( VL_Error != C_OK ) {
4752 // Free memory space
4753 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4754 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4755 VL_ResultsTemplate = NULL;
4756 VL_ResultsCell = NULL;
4757 // Error handling
4758 sprintf(VL_ErrorMsg, "Computation of new IW mappings cells failed or was not necessary\n");
4759 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4760
4761 if ( VL_NumOfResultTemplate > 0){
4762 if ( EP_Strcmp( VG_Msg_Dat_Err, "\0") != 0 ){
4763 snprintf(VL_Msg,sizeof(VL_Msg) - EP_Strlen(VG_Msg_Dat_Err),"\t%s",VG_Msg_Dat_Err);
4764 EP_Strcpy(VG_Msg_Dat_Err, "\t\t\t\tUnable to generate the following mapping name: ");
4765 EP_Strncat(VL_Msg,VG_Msg_Dat_Err,sizeof(VL_Msg) - EP_Strlen(VG_Msg_Dat_Err));
4766 }
4767 else {
4768 sprintf(VL_Msg, "\tUnable to generate the following mapping name: ");
4769 }
4770
4771 for(VL_i = 0; VL_i < VL_NumOfResultTemplate; VL_i++)
4772 {
4773 sprintf(VL_ErrorMsg, "%s, ", VL_ResultsTemplate[VL_i].MappingName);
4774
4775 if (VL_i == (VL_NumOfResultTemplate - 1))
4776 {
4777 sprintf(VL_ErrorMsg, "%s\n", VL_ResultsTemplate[VL_i].MappingName);
4778 }
4779
4780 EP_Strcat(VL_Msg, VL_ErrorMsg);
4781 }
4782
4783 EP_Strcpy(VG_Msg_Dat_Err, VL_Msg);
4784 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
4785 return (C_KO);
4786 }
4787
4788 return (C_NOT_OK);
4789 }
4790
4791 // Advanced debug mode
4792 if ( VG_Verbose == 2 ){
4793 PT_PrintResults(VL_ResultsCell, VL_NumOfResultCell);
4794 }
4795
4796 /* Check if all the cells have been computed, hence the template */
4797 for (VL_i = 0; VL_i < VL_NumOfResultTemplate; VL_i++) {
4798 VL_ResultsTemplate[VL_i].Cell_Found = 1;
4799
4800 for (VL_j = 0; VL_j < VL_NumOfResultCell; VL_j++) {
4801 if (EP_Strcmp(VL_ResultsCell[VL_j].TemplateName, VL_ResultsTemplate[VL_i].TemplateName) == 0 && VL_ResultsCell[VL_j].Cell_Found == 0) {
4802 VL_ResultsTemplate[VL_i].Cell_Found = 0;
4803 break;
4804 }
4805 }
4806
4807 if (VL_ResultsTemplate[VL_i].Cell_Found == 0) continue;
4808 }
4809
4810 // Allocate memory space
4811 VL_MappingIW = (U_PtmesMappingIW *) _Calloc(PM_Trace.FunctionName, VL_NumOfResultTemplate, sizeof(U_PtmesMappingIW));
4812 VL_MappingCells = (U_PtmesMappingCell *) _Calloc(PM_Trace.FunctionName, VL_NumOfResultCell, sizeof(U_PtmesMappingCell));
4813
4814 if ( (VL_MappingCells == NULL) || (VL_MappingIW == NULL) ){
4815 // Error handling
4816 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
4817 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4818 // Free memory space
4819 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4820 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4821 VL_ResultsCell = NULL;
4822 VL_ResultsTemplate = NULL;
4823 return (C_NOT_OK);
4824 }
4825
4826 /* Loop on the list of template use */
4827 for (VL_i = 0; VL_i < VL_NumOfResultTemplate; VL_i++) {
4828
4829 // Check if the template has been well computed
4830 VL_AllCellFound = 1;
4831
4832 for (VL_j = 0; VL_j < VL_NumOfResultTemplate; VL_j++) {
4833 if (VL_ResultsTemplate[VL_i].Cell_Found == 0) {
4834 VL_AllCellFound = 0;
4835 break;
4836 }
4837 }
4838
4839 // Definition of the mapping name
4840 EP_Strcpy(VL_MappingIW[VL_i].Miw_Name, VL_ResultsTemplate[VL_i].MappingName);
4841 VL_MappingIW[VL_i].Miw_Id = VL_ResultsTemplate[VL_i].Miw_ID;
4842 VL_MappingIW[VL_i].Miw_State = VL_ResultsTemplate[VL_i].Miw_State;
4843 VL_MappingIW[VL_i].Us_Id = VG_UserID;
4844 EP_Strcpy(VL_MappingIW[VL_i].Tiw_Name, VL_ResultsTemplate[VL_i].TemplateName);
4845 EP_Strcpy(VL_MappingIW[VL_i].Miw_Type, VL_ResultsTemplate[VL_i].Miw_Type);
4846 VL_MappingIW[VL_i].Miw_Useful_Radius = VL_ResultsTemplate[VL_i].Miw_Useful_Radius;
4847 VL_MappingIW[VL_i].Ma_Shift_X = PM_Mask.MA_ShiftX;
4848 VL_MappingIW[VL_i].Ma_Shift_Y = PM_Mask.MA_ShiftY;
4849
4850 /* Do not take in account the result if the template was not well computed */
4851 if (VL_AllCellFound == 0) continue;
4852
4853 VL_Found = 0;
4854
4855 if ( (EP_Strcmp(PM_Comment, "\0") == 0) || (PM_Comment == NULL) ) {
4856 EP_Strcpy(VL_MappingIW[VL_i].Miw_Comment, VL_ResultsTemplate[VL_i].Miw_Comment);
4857 }
4858 else {
4859 EP_Strcpy(VL_MappingIW[VL_i].Miw_Comment, PM_Comment);
4860 }
4861
4862 /* Search the used template in the result list */
4863 for (VL_j = 0; VL_j < VL_NumOfResultCell; VL_j++) {
4864 if (0 == EP_Strcmp(VL_ResultsTemplate[VL_i].TemplateName, VL_ResultsCell[VL_j].TemplateName)) {
4865 // Template found
4866 VL_Found = 1;
4867
4868 // Get the result contents
4869 EP_Strcpy(VL_MappingCells[VL_Index].Tiw_Name, VL_ResultsCell[VL_j].TemplateName);
4870 VL_MappingCells[VL_Index].Mc_Index = VL_ResultsCell[VL_j].Index;
4871 VL_MappingCells[VL_Index].Mc_X = VL_ResultsCell[VL_j].X_Cell;
4872 VL_MappingCells[VL_Index].Mc_Y = VL_ResultsCell[VL_j].Y_Cell;
4873
4874 // Increment index
4875 VL_Index++;
4876 }
4877
4878 if( ((0 != EP_Strcmp( VL_ResultsTemplate[VL_i].TemplateName, VL_ResultsCell[VL_j].TemplateName )) || (VL_j == ( VL_NumOfResultCell - 1 )))
4879 && ( 1 == VL_Found )
4880 )
4881 {
4882 break; // exit loop
4883 }
4884 }
4885
4886 /* Template not found */
4887 if (0 == VL_Found) {
4888 sprintf(VL_ErrorMsg, "Unable to find the result of the %s template use computation\n", VL_ResultsTemplate[VL_i].TemplateName);
4889 EP_Strncpy(VG_Msg_Dat_Err, VL_ErrorMsg, sizeof(VG_Msg_Dat_Err) - EP_Strlen(VG_Msg_Dat_Err));
4890 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4891 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
4892 continue;
4893 }
4894 }
4895
4896 // Advanced debug mode
4897 if ( VG_Verbose == 2 ){
4898 PT_PrintMeasurementCells(VL_ResultsCell, VL_NumOfResultCell, PM_Mask.MA_Name, VL_NumOfResultTemplate);
4899 }
4900
4901 /* Write in database the informations linked to the computed measurement cells for the given mask set */
4902 VL_Error = PT_InsertCells(PM_Trace, PM_Mask.MA_Name, VL_MappingIW, VL_MappingCells, VL_NumOfResultTemplate, VL_NumOfResultCell, PM_CustomTemplateName);
4903
4904 if (C_OK != VL_Error) {
4905 // Free memory space
4906 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4907 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4908 VL_ResultsTemplate = NULL;
4909 VL_ResultsCell = NULL;
4910
4911 // Error handling
4912 sprintf(VL_ErrorMsg, "Unable to insert in the database the computed informations about the measurement cells\n");
4913 EP_Strncat(VG_Msg_Dat_Err, VL_ErrorMsg, sizeof(VG_Msg_Dat_Err) - EP_Strlen(VG_Msg_Dat_Err));
4914 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4915 EP_Strcpy(VL_Msg, VL_ErrorMsg);
4916
4917 if ( VL_NumOfResultTemplate > 0 ){
4918 EP_Strcat(VL_Msg, "\t\t\t\tUnable to generate the following mapping name: ");
4919
4920 for(VL_i = 0; VL_i < VL_NumOfResultTemplate; VL_i++)
4921 {
4922 sprintf(VL_ErrorMsg, "%s, ", VL_MappingIW[VL_i].Miw_Name);
4923
4924 if (VL_i == (VL_NumOfResultTemplate - 1))
4925 {
4926 sprintf(VL_ErrorMsg, "%s", VL_MappingIW[VL_i].Miw_Name);
4927 }
4928
4929 EP_Strcat(VL_Msg, VL_ErrorMsg);
4930 }
4931 }
4932 sprintf(VG_Msg_Dat_Err, VL_Msg);
4933 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err );
4934 return (C_KO);
4935 }
4936 EP_Commit();
4937
4938 // Free memory space
4939 _Free(PM_Trace.FunctionName, VL_MappingCells);
4940 VL_MappingCells = NULL;
4941
4942 /* Job scanner exists for the maskset ? */
4943 VL_Error = PT_DoesJobScannerExist(PM_Trace, PM_Mask.MA_Name, &VL_JobScannerExists);
4944
4945 if ( VL_Error != C_OK ) {
4946 // Error handling
4947 sprintf(VL_ErrorMsg, "\tUnable to check if a job scanner exists for the maskset %s\n", PM_Mask.MA_Name);
4948 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4949 // Free memory space
4950 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4951 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4952 VL_ResultsTemplate = NULL;
4953 VL_ResultsCell = NULL;
4954 return (C_NOT_OK);
4955 }
4956
4957 /* Count number of template requiring exposition of cell below measurement cell */
4958 for ( VL_i = 0 ; (VL_i < VL_NumOfResultTemplate) ; VL_i++){
4959 VL_NumOfTemplateRequiringExpoBelow = 0;
4960 VL_Error = PT_CountTemplateRequiringExpoBelow(PM_Trace, PM_Mask.MA_Name, VL_MappingIW[VL_i].Tiw_Name, &VL_NumOfTemplateRequiringExpoBelow);
4961
4962 if ( VL_Error != C_OK ) {
4963 // Error handling
4964 sprintf(VL_ErrorMsg, "\tUnable to check if the following template requires exposition below: %s\n", VL_MappingIW[VL_i].Tiw_Name);
4965 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4966 // Free memory space
4967 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4968 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4969 VL_ResultsTemplate = NULL;
4970 VL_ResultsCell = NULL;
4971 return (C_NOT_OK);
4972 }
4973
4974
4975 /* Reset the Photolitho map only if compute has been made for all template */
4976 if ( VL_JobScannerExists == 0) {
4977 // Revert NOFIELDMETRO image into NOFIELDEDGE image and log the action
4978 VL_Error = PT_RevertPhotoMap(PM_Trace, PM_Mask.MA_Name, C_CELL_NOFIELDMETRO, C_NAME_NOFIELDMETRO, C_CELL_NOFIELDEDGE, C_NAME_NOFIELDEDGE);
4979
4980 if ( VL_Error != C_OK ) {
4981 // Error handling
4982 sprintf(VL_ErrorMsg, "\tUnable to revert the Photo map (%s -> %s)\n", C_NAME_NOFIELDMETRO, C_NAME_NOFIELDEDGE);
4983 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4984 // Free memory space
4985 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
4986 _Free(PM_Trace.FunctionName, VL_ResultsCell);
4987 VL_ResultsTemplate = NULL;
4988 VL_ResultsCell = NULL;
4989 return (C_NOT_OK);
4990 }
4991 EP_Commit();
4992 }
4993 else if (VL_JobScannerExists != 0 && VL_NumOfTemplateRequiringExpoBelow > 0) {
4994 sprintf(VL_ErrorMsg, "\tWARNING: Job scanner exists for maskset %s => do not revert the Photo map (%s -> %s).\n", PM_Mask.MA_Name, C_NAME_NOFIELDMETRO, C_NAME_NOFIELDEDGE);
4995 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
4996
4997 //for ( VL_i = 0 ; VL_i < VL_NumOfResultTemplate ; VL_i++){
4998 VL_Error = PT_DeleteMappingIWExpoNeeded(PM_Trace, PM_Mask.MA_Name, &VL_MappingIW[VL_i]);
4999
5000 if (VL_Error == C_NOT_OK){
5001 // Error handling
5002 sprintf(VL_ErrorMsg, "\n\t\tMapping IW %s: Unable to (re)generate (job scanner exists).", VL_MappingIW[VL_i].Miw_Name);
5003 printf ("%s\n", VL_ErrorMsg);
5004 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
5005 VL_Error = C_OK;
5006 }
5007 else if ( VL_Error == C_KO ) {
5008 sprintf(VL_ErrorMsg, "Delete in DB failed\n");
5009 Err_AddError(PM_Err, computeIW, VL_ErrorMsg );
5010 }
5011 // Else, no template requiring NEW blue field to delete (case C_WARNING)
5012 else
5013 {
5014 // Nothing to do
5015 //}
5016 }
5017 EP_Commit();
5018 }
5019 }
5020
5021 /* Disable Photolitho map update if a job scanner exists => error */
5022 for (VL_i = 0; VL_i < VL_NumOfResultCell; VL_i++) {
5023 // Check if the expo of the cell below the measurement site is required
5024 if (VL_ResultsCell[VL_i].Expo_Below_Required != 0 && VL_ResultsCell[VL_i].Cell_Found != 0 && VL_JobScannerExists != 0 )
5025 break;
5026 }
5027
5028 if (VL_i < VL_NumOfResultCell) {
5029 sprintf(VL_ErrorMsg, "\tWARNING: Job scanner exists for maskset %s => no changes made on Photo map (no %s image added)\n", PM_Mask.MA_Name, C_NAME_NOFIELDMETRO);
5030 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5031 }
5032
5033 /* Update the Photolitho map : expose fields on the edge of the wafer if required */
5034 /* => convert some NOFIELDEDGE image into NOFIELDMETRO and log the action */
5035 if (VL_JobScannerExists == 0) {
5036 VL_Error = PT_UpdatePhotoMap(PM_Trace, PM_Mask.MA_Name, C_CELL_NOFIELDEDGE, C_NAME_NOFIELDEDGE, C_CELL_NOFIELDMETRO, C_NAME_NOFIELDMETRO);
5037
5038 if ( VL_Error != C_OK ) {
5039 // Error handling
5040 sprintf(VL_ErrorMsg, "\tUnable to update the Photo map (%s -> %s)\n", C_NAME_NOFIELDEDGE, C_NAME_NOFIELDMETRO);
5041 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5042 // Free memory space
5043 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
5044 _Free(PM_Trace.FunctionName, VL_ResultsCell);
5045 VL_ResultsTemplate = NULL;
5046 VL_ResultsCell = NULL;
5047 return (C_NOT_OK);
5048 }
5049 EP_Commit();
5050 }
5051
5052 // Free memory space
5053 _Free(PM_Trace.FunctionName, VL_ResultsCell);
5054 _Free(PM_Trace.FunctionName, VL_ResultsTemplate);
5055 VL_ResultsCell = NULL;
5056 VL_ResultsTemplate = NULL;
5057
5058 if (PM_NumberOfMappingIW != NULL){
5059 /* Get the number of mapping */
5060 *PM_NumberOfMappingIW = VL_NumOfResultTemplate;
5061
5062 /* Allocate Memory Space */
5063 (*PM_MappingIW) = ( U_PtmesMappingIW *) _Calloc(PM_Trace.FunctionName, (*PM_NumberOfMappingIW), sizeof(U_PtmesMappingIW));
5064 if ((*PM_MappingIW) == NULL) {
5065 // Error handling
5066 sprintf(VL_ErrorMsg, "Error during memory space allocation\n");
5067 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5068 // Free memory space
5069 _Free(PM_Trace.FunctionName, VL_MappingIW);
5070 VL_MappingIW = NULL;
5071 (*PM_NumberOfMappingIW) = 0;
5072 return (C_NOT_OK);
5073 }
5074
5075 /* Memory copy */
5076 memcpy((U_PtmesMappingIW *) & ((*PM_MappingIW)[0]), (U_PtmesMappingIW *) & (VL_MappingIW[0]), (*PM_NumberOfMappingIW) * sizeof(U_PtmesMappingIW));
5077 if ( (*PM_MappingIW) == NULL ) {
5078 // Error handling
5079 sprintf(VL_ErrorMsg, "Error during memory space copy\n");
5080 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5081 // Free memory space
5082 _Free(PM_Trace.FunctionName, VL_MappingIW);
5083 VL_MappingIW = NULL;
5084 (*PM_NumberOfMappingIW) = 0;
5085 return (C_NOT_OK);
5086 }
5087 }
5088
5089 /* The mapping have been partially generated */
5090 if ( (VL_NumOfCellNotFound > 0) || (VL_NumOfCellBelowNotExposed > 0) ) {
5091
5092 // Advanced debug mode
5093 if ( VG_Verbose == 2 ){
5094 _ExitInfo("Exit 2");
5095 }
5096
5097 // Free memory space
5098 _Free(PM_Trace.FunctionName, VL_MappingIW);
5099 VL_MappingIW = NULL;
5100
5101 // Return a warning - A part of the measurement cells have been unable to compute
5102 return (C_WARNING);
5103 }
5104
5105 /* The mapping have been fully generated */
5106 // Free memory space
5107 _Free(PM_Trace.FunctionName, VL_MappingIW);
5108 VL_MappingIW = NULL;
5109
5110 TraceLeaveFunction(&PM_Trace);
5111
5112 return (VL_Error);
5113}
5114
5115/* === FUNCTION ======================================================================
5116* Name: PT_GetRecipeFields
5117* ===================================================================================== */
5118int PT_GetRecipeFields(U_Trace PM_Trace, int PM_RecipeID, U_RecipeFields **PM_OutArray, int *PM_OutArrayCount) {
5119 EXEC SQL BEGIN DECLARE SECTION;
5120 U_InqSQL VL_SqlStatus ;
5121 U_RecipeFields VL_Elem;
5122 char VL_Query[2048];
5123 EXEC SQL END DECLARE SECTION;
5124 int VL_OutArraySize;
5125 U_RecipeFields *VL_OutArray;
5126 int VL_OutArrayCount;
5127 int VL_i;
5128 char VL_ErrorMsg[256];
5129 int VL_Error = C_OK;
5130
5131 TraceEnterFunction(&PM_Trace, "PT_GetRecipeFields", "");
5132 sprintf(VL_Query, "SELECT \n \
5133 RCP_ID, MA_NAME, CFG_NAME, RCP_PATTERN, FD_MARKER_LABEL, \n\
5134 MP_LAYER_ID, FD_REF_LAYER_ID, TIW_NAME, TIF_NAME, \n \
5135 MC_INDEX, MC_X, MC_Y, MS_INDEX, MS_X, MS_Y, IN_RADIUS \n \
5136 FROM VW_EXE_PTMES_RCP_USEFUL_POINT \n\
5137 WHERE rcp_id='%d' \n\
5138 ORDER BY rcp_pattern, fd_marker_label,ms_index, mc_index",
5139 PM_RecipeID);
5140
5141 TracePrint(&PM_Trace, "Building the query\n");
5142 TracePrint(&PM_Trace, "%s\n", VL_Query);
5143 // Declare a dynamic cursor
5144 EXEC SQL DECLARE SQL_VL_RecipeCursorFields STATEMENT;
5145 EXEC SQL PREPARE SQL_VL_RecipeCursorFields FROM :VL_Query;
5146 EXEC SQL DECLARE VL_RecipeCursorFields CURSOR FOR SQL_VL_RecipeCursorFields;
5147
5148 Trace_DB("pt_calcul.pc","ptmeas","req_23");
5149
5150 // Open the cursor
5151 EXEC SQL OPEN VL_RecipeCursorFields;
5152 VL_Error = PT_InquireSQL (PM_Trace, &VL_SqlStatus);
5153 if (C_OK != VL_Error ) {
5154 PT_Error(C_ER_SQL, PM_Trace , "error while opening cursor", VL_SqlStatus.ErrorText);
5155 return (VL_Error);
5156 }
5157 // set to 0 and NULL to have realloc do the job
5158 VL_OutArraySize = 0;
5159 VL_OutArray = NULL;
5160 VL_i = 0;
5161 VL_SqlStatus.RowCount = -1; // to map Ingres behavior
5162 while (1){ // two ways of going out: i) Error -> print and return ii) VL_SqlStatus.RowCount = 0 -> exit normally
5163 // Get and store the next record data
5164 memset(&VL_Elem, 0, sizeof(U_RecipeFields)); // need to set to null to ensure data not created with VARCHAR will be NULL terminated.
5165 EXEC SQL FETCH VL_RecipeCursorFields
5166 INTO
5167 :VL_Elem;
5168 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
5169 PT_Error(C_ER_SQL, PM_Trace , "error while fetching cursor", VL_SqlStatus.ErrorText);
5170 return (VL_Error);
5171 }
5172 // should I stay or should I go ?
5173 if (VL_SqlStatus.RowCount == 0) break;
5174 // resize out array if needed
5175 if (VL_i >= VL_OutArraySize){
5176 VL_OutArraySize+=100;
5177 VL_OutArray = realloc (VL_OutArray, VL_OutArraySize * sizeof(U_RecipeFields));
5178 if ( VL_OutArray==NULL ){
5179 char VL_ErrorMsg[1024];
5180 sprintf(VL_ErrorMsg, "Error while allocating %d elements of size %d (ie %d bytes)", VL_OutArraySize, sizeof(U_RecipeFields), VL_OutArraySize * sizeof(U_RecipeFields));
5181 return PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "" );
5182 }
5183 }
5184 // copying data to the array
5185 TracePrint(&PM_Trace, "Rcp info: (%d, %d, %f, %f)\n", VL_Elem.MC_X, VL_Elem.MC_Y, VL_Elem.MS_X, VL_Elem.MS_Y);
5186 memcpy(VL_OutArray+(VL_i), &VL_Elem, sizeof(U_RecipeFields));
5187 VL_i++;
5188 }
5189 VL_OutArrayCount = VL_i;
5190 // Fitting the result to the real size if it is not null
5191 if (VL_i > 0) {
5192 VL_OutArray = realloc(VL_OutArray, VL_i*sizeof(U_RecipeFields));
5193 }
5194
5195 // Close the cursor
5196 EXEC SQL CLOSE VL_RecipeCursorFields;
5197 if (C_OK != (VL_Error = PT_InquireSQL(PM_Trace, &VL_SqlStatus)) ) {
5198 free(VL_OutArray);
5199 VL_OutArray = NULL;
5200 PT_Error(C_ER_SQL, PM_Trace , "error while closing cursor", VL_SqlStatus.ErrorText);
5201 return (VL_Error);
5202 }
5203 *PM_OutArray = VL_OutArray;
5204 *PM_OutArrayCount = VL_OutArrayCount;
5205 TraceLeaveFunction(&PM_Trace);
5206 return VL_Error;
5207}
5208
5209/* === FUNCTION ======================================================================
5210* Name: PT_Compute
5211* ===================================================================================== */
5212int PT_Compute (U_Trace PM_Trace, U_Mask *PM_Mask, char *PM_RecipeName, char *PM_MetroType, U_MetroError *PM_Err) {
5213 /*--------------------------------------------------------------------------
5214 * Declaration
5215 *--------------------------------------------------------------------------
5216 */
5217 int VL_Error = C_OK;
5218 char VL_ErrorMsg[256];
5219 int VL_MappingID = 0;
5220
5221 /*--------------------------------------------------------------------------
5222 * Initialisation
5223 *--------------------------------------------------------------------------
5224 */
5225 EP_Strcpy( PM_Trace.FunctionName, "PT_Compute");
5226 TraceEnterFunction(&PM_Trace, PM_Trace.FunctionName, "Maskset: %s, Metro: %s", PM_Mask->MA_Name, PM_MetroType);
5227
5228 /*--------------------------------------------------------------------------
5229 * Instructions
5230 *--------------------------------------------------------------------------
5231 */
5232 /*=== COMPUTATION / DB INSERTIONS OF THE IW MAPPINGS ====================================================*/
5233 if (VG_Verbose > 0) printf("PT_COMPUTE --- Generating IW Mapping (and dump into DB) \n ################\n");
5234
5235 VL_Error = PT_ComputeIntraWafer(PM_Trace, *PM_Mask, NULL, NULL, NULL, PM_RecipeName, PM_MetroType, PM_Err, NULL, NULL);
5236
5237 if ( VL_Error == C_WARNING) {
5238 // Log handling
5239 sprintf(VL_ErrorMsg, "\tWARNING : Unable to compute part of the measurement cells\n\t\t\t");
5240 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5241 // Report handling
5242 if ( (EP_Strcmp( VG_Msg_Dat_Err , "\0") != 0) && (VG_Msg_Dat_Err != NULL) ){
5243 snprintf(VL_ErrorMsg, sizeof(VL_ErrorMsg) - EP_Strlen(VL_ErrorMsg), VG_Msg_Dat_Err);
5244 Err_AddError(PM_Err, computeIW, "Unable to compute part of the measurement cells\n" );
5245 }
5246 }
5247 else if ( VL_Error != C_OK ){
5248 // Log handling
5249 sprintf(VL_ErrorMsg, "\tNo new IW mappings generation needed.\n");
5250 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5251 // Report handling
5252 if ( (EP_Strcmp( VG_Msg_Dat_Err , "\0") != 0) && (VG_Msg_Dat_Err != NULL) ){
5253 snprintf(VL_ErrorMsg, sizeof(VL_ErrorMsg) - EP_Strlen(VL_ErrorMsg), VG_Msg_Dat_Err);
5254 Err_AddError(PM_Err, computeIW, "No new IW mappings generation needed.\n" );
5255
5256 }
5257 }
5258 else if ( (EP_Strcmp(VG_Msg_Dat_Err, "\0") != 0) && (VG_Msg_Dat_Err != NULL) ) {
5259 // PT_AddMappingError(PM_Trace, PM_MappingErrors, PM_MappingErrorCount, NULL, VG_Msg_Dat_Err, 1);
5260 Err_AddError(PM_Err, computeIW, VG_Msg_Dat_Err);
5261 }
5262
5263 /*=== Computing IF Mappings (Frame and standard) ====================================================*/
5264 if (VG_Verbose > 0) printf("PT_COMPUTE --- Generating IF Mapping (and dump into DB) \n ################ \n");
5265
5266 VL_Error= PT_ComputeIntraField(PM_Trace, PM_Mask, PM_RecipeName, PM_MetroType, NULL, PM_Err, &VL_MappingID, NULL );
5267
5268 if ( VL_Error != C_OK ){
5269 sprintf(VL_ErrorMsg, "Error while Getting or computing or dumping the set of mappings IF.");
5270 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5271 return (C_NOT_OK);
5272 }
5273
5274 /*=== Generate Recipe ====================================================*/
5275 /* Dump recipes into DB */
5276 /*------------------------------------------------------------------------*/
5277 if (VG_Verbose > 0) printf("PT_COMPUTE --- inserting recipe in DB (and computing status)\n");
5278 VL_Error = PT_SetRecipeInDB(PM_Trace, VG_UserID, PM_Mask->MA_Name, PM_MetroType, PM_RecipeName);
5279
5280 if (C_OK != VL_Error) {
5281 sprintf(VL_ErrorMsg, "Error while inserting Recipe in DB. \n");
5282 PT_Error(C_ER_MSG, PM_Trace, VL_ErrorMsg, "");
5283 Err_AddError(PM_Err, generalID, VL_ErrorMsg);
5284 return (C_NOT_OK);
5285 }
5286
5287 if (VG_Verbose > 0) printf("PT_COMPUTE --- Insertion done \n");
5288 TraceLeaveFunction(&PM_Trace);
5289 return( C_OK );
5290
5291}
5292
5293
5294
5295/* EOF */