/************************************************ * Include Files * ************************************************/ #include #include #include /* #include */ #include /************************************************ * Constant Declarations * ************************************************/ #define FALSE 0 #define TRUE 1 #define SHL_NAMESIZE 9 /************************************************ * External Variable Declarations * ************************************************/ extern PROGRAM *prd; /***********************************************************************/ /* */ /* Description: */ /* This routine performs a planarization check of a metallized */ /* wafer. The routine loops until complete continuity is reached, */ /* then until complete discontinuity is reached, or reset is */ /* pressed. Three complete passes with 100% continuity are needed */ /* to be called full continuity. This avoids spurious results due */ /* to momentary continuity. This routine depends on the following: */ /* ALL_SIGS pingroup - contains all signal pins */ /* ALL_DPS pingroup - contains all DPSs */ /* sig_planarize_pins DCtest block - contains test for ALL_SIGS */ /* dps_planarize_pins DCtest block - contains test for ALL_DPS */ /* SHL_OPER_MSG global variable - flags printing of pin results */ /* SHL_PLANAR_RESULT global variable - contains planarization */ /* percentage (0.0 to 1.0) */ /* If any of the above are absent, this routine fails. */ /* If the loop does not terminate, it can be aborted by clicking the */ /* RESET button on Controltool. */ /* */ /***********************************************************************/ function shl_planarize() = { Generic_block *sig_pinset_ptr, *dps_pinset_ptr; Pingroup_block *sig_pingrp_ptr, *dps_pingrp_ptr; Dctest_block *sig_planarize, *dps_planarize; Global_block *switch4,*planar_result; short num_sig_pins, num_dps_pins; int status; char ans[SHL_NAMESIZE]; float prcnt; int indx,cnt,icnt,fcnt; int pincnt,d,dpscnt,pinnum,totcnt; int print_fail=FALSE; int print_pass=FALSE; int done,full,endloop; char bell; bell = '\007'; sig_pinset_ptr = NULL; sig_pinset_ptr=find_block(prd, "ALL_SIGS", PINGROUP); if (sig_pinset_ptr) { num_sig_pins = 0; get_pin_count(sig_pinset_ptr,&num_sig_pins); } else { printf("ERROR: Could not find pingroup ALL_SIGS\n"); return(0); } dps_pinset_ptr = NULL; dps_pinset_ptr=find_block(prd, "ALL_DPS", PINGROUP); if (dps_pinset_ptr) { num_dps_pins = 0; } else { printf("ERROR: Could not find pingroup ALL_DPS\n"); return(0); } sig_pingrp_ptr = (Pingroup_block *)sig_pinset_ptr; dps_pingrp_ptr = (Pingroup_block *)dps_pinset_ptr; sig_planarize = (Dctest_block *)find_block(prd, "sig_planarize_pins", DC); if (!sig_planarize) { printf("ERROR: Could not find DC test sig_planarize_pins\n"); return(0); } dps_planarize = (Dctest_block *)find_block(prd, "dps_planarize_pins", DC); if (!dps_planarize) { printf("ERROR: Could not find DC test dps_planarize_pins\n"); return(0); } switch4 = (Global_block *)find_block(prd, "SHL_OPER_MSG", GLOBAL_BLOCK); if (!switch4) { printf("ERROR: Could not find shell global SHL_OPER_MSG\n"); return(0); } if ((switch4->value.ival==1) || (switch4->value.ival==3)) print_fail=TRUE; if ((switch4->value.ival==2) || (switch4->value.ival==3)) print_pass=TRUE; planar_result = (Global_block *)find_block(prd, "SHL_PLANAR_RESULT", GLOBAL_BLOCK); if (!planar_result) { printf("ERROR: Could not find shell global SHL_PLANAR_RESULT\n"); return(0); } /* do { printf("\n WARNING !!!\n"); printf("\n\n\nBE SURE THAT THE VACUUM IS ON AT THE TEST HEAD BEFORE\n"); printf("\nPROCEEDING WITH PLANARIZATION AND CONTACT RESISTANCE\n\n"); printf("\nDo you want to run the planarization loop? (y/n)\n"); scanf("%s",ans); if ( (strcmp(ans,"n") == 0) || (strcmp(ans,"N") == 0) ) { done = TRUE; printf("Planarization loop finished\n"); } else { printf("Starting Planarization Loop\n"); done = FALSE; fcnt = 0; full = FALSE; endloop = FALSE; while (endloop == FALSE) { */ cnt = 0; icnt = 0; status=execute_test(prd,sig_planarize,NULL,NULL,NULL,NULL,NULL); if (num_sig_pins == 0) num_sig_pins = prd->result.num_items; if (num_sig_pins != prd->result.num_items) { printf( "\nERROR: ALL_SIGS pin count (%d) not equal to measured pins (%d)\n", num_sig_pins,prd->result.num_items); } if (print_fail) printf("\nFailing tester channels are:\n"); for (indx=0;indxresult.num_items;indx++) { pinnum=prd->result.data[indx].pin; if (prd->result.data[indx].measure > 100e-3) { cnt++; if (print_fail) { printf("%4d",pinnum); if ( (cnt % 18) == 0) printf("\n"); } } } if ((print_fail) && ( (cnt % 18) != 0)) printf("\n"); if (print_pass) { printf("\nPassing tester channels are:\n"); for (indx=0;indxresult.num_items;indx++) { pinnum=prd->result.data[indx].pin; if (prd->result.data[indx].measure <= 100e-3) { icnt++; printf("%4d",pinnum); if ( (icnt % 18) == 0) printf("\n"); } } if ( (icnt % 18) != 0) printf("\n"); } status=execute_test(prd,dps_planarize,NULL,NULL,NULL,NULL,NULL); if (num_dps_pins == 0) num_dps_pins = prd->result.num_items; if (num_dps_pins != prd->result.num_items) { printf( "\nERROR: ALL_DPS DPS count (%d) not equal to measured DPSs (%d)\n", num_dps_pins,prd->result.num_items); } if (print_fail) printf("\nFailing DPSs are:\n"); for (indx=0;indxresult.num_items;indx++) { pinnum=prd->result.data[indx].pin; if (prd->result.data[indx].measure > 100e-3) { cnt++; if (print_fail) printf("%4d",pinnum); } } if (print_fail) printf("\n"); if (print_pass) { printf("\nPassing DPSs are:\n"); for (indx=0;indxresult.num_items;indx++) { pinnum=prd->result.data[indx].pin; if (prd->result.data[indx].measure <= 100e-3) printf("%4d",pinnum); } printf("\n"); } totcnt = num_sig_pins + num_dps_pins; prcnt = ((totcnt-cnt)*1.0)/totcnt; printf("\n%d pads are contacting out of %d\n", totcnt-cnt,totcnt); printf("Contact percentage = %4.1f\n",prcnt*100.0); planar_result->value.fval = prcnt; /* if (cnt == 0) fcnt++; else fcnt = 0; if (fcnt > 2) full = TRUE; if ((full == TRUE) && (cnt == totcnt)) endloop = TRUE; } printf("\n*****************************\n"); printf("%c Full Continuity Reached%c\n",bell,bell); printf("*****************************\n"); } } while (!done); */ return(1); }; /***********************************************************************/ /* */ /* Description: */ /* This routine returns the number of pins in a pinset. */ /* It is passed a pointer to the pinset and a pointer to */ /* the variable which holds the pin count. It can be called */ /* recursively. It does not work properly on PWR pingroups. */ /* */ /***********************************************************************/ int get_pin_count(local_pinset_ptr,total_pins) Generic_block *local_pinset_ptr; short *total_pins; { Pindef_block *pindef_ptr; Pingroup_block *pingrp_ptr; Pinlist *pin_ptr; Generic_pin_block **pinset_ptr; int i; short number_of_pins, number_of_pinlists; short num_pinsets, pinset_type; pinset_type=local_pinset_ptr->type; switch (pinset_type) { case PINDEF: pindef_ptr = (Pindef_block *) local_pinset_ptr; *total_pins = *total_pins + pindef_ptr->num_pins; break; case PINGROUP : pingrp_ptr = (Pingroup_block *) local_pinset_ptr; number_of_pinlists=pingrp_ptr->num_pinsets; pinset_ptr=pingrp_ptr->pinset; for (i=0;i