/* * This file is part of the Alliance CAD System * Copyright (C) Laboratoire LIP6 - Département ASIM * Universite Pierre et Marie Curie * * Home page : http://www-asim.lip6.fr/alliance/ * E-mail : mailto:alliance-users@asim.lip6.fr * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * Alliance VLSI CAD System is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the GNU C Library; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /***************************************************************** * chaine de CAO & VLSI Alliance * * * * fichier : alc_pars_p.c * * auteur(s) : V. POUILLEY le : 01/01/92 * * modifie par : J.P CHAPUT * * modifie par : L. MAURIN\R. PREVOT le : 12/07/93 * * modifie par : F. PETROT * * numero de version actuelle : 4.00 * * $Log: alc_pars_p.c,v $ * Revision 1.4 2006/05/04 16:29:52 xtof * Allowing more than 64 chars filenames .... * * Revision 1.3 2004/09/04 09:11:52 ludo * - bug fix in AP parser (pb when scale_X is big) * * Revision 1.2 2002/09/30 16:20:53 czo * support/users * * Revision 1.1.1.1 2002/03/13 10:18:47 fred * Importing MBKAP sources into the new CVS tree * * *****************************************************************/ #include #include #include #include #ident "@(#)alliance physical view parser v4.00" #define TRUE 1 #define FALSE 0 #define MBKSZNAME 1024 #define MAXLBUFFER 256 #define MAXLBUFF 256 #define EVAL -2 #define EVER -3 #define EOPEN -4 #define ECLOSE -5 #define ESETUP -6 #define ELAYER -7 #define EOPGEO -8 #define ESYNTAX -9 #define EORIENT -10 #define EHEADER -11 #define EMISSEOF -12 #define ETYPESEG -13 #define ETYPEVIA -14 #define ENAMETRS -15 #define ENBFIELDS -16 #define EFILENAME -17 #define EFILETYPE -18 #define EBOUNDBOX -19 #define EABUTMBOX -20 #define EALLOCFIG -21 #define ECOMPONENT -22 #define ETRANSORIENT -23 #define mc_nexttoken(p_head,p_next,error_code) \ if ( (p_next=strchr(p_head,','))==NULL ) \ alc_printerror(error_code); \ *(p_next++) = '\0' #define mc_nexttoken3(p_head,p_next,error_code) \ if ( (p_next=strchr(p_head,'\n'))==NULL ) \ alc_printerror(error_code); \ *(p_next++) = '\0' #define mc_isthrough(layer) \ ( ((layer)==TPOLY) \ ||((layer)==TALU1) \ ||((layer)==TALU2) \ ||((layer)==TALU3) \ ||((layer)==TALU4) \ ||((layer)==TALU5) \ ||((layer)==TALU6) \ ||((layer)==TALU7) \ ||((layer)==TALU8) \ ||((layer)==TALU9) ) #define mc_isconseg(layer) \ ( ((layer)==CALU1) \ ||((layer)==CALU2) \ ||((layer)==CALU3) \ ||((layer)==CALU4) \ ||((layer)==CALU5) \ ||((layer)==CALU6) \ ||((layer)==CALU7) \ ||((layer)==CALU8) \ ||((layer)==CALU9) ) #define mc_isdigit(c) \ ( (((c)>='0')&&((c)<='9')) ? 1 : 0 ) static struct { FILE *file; char file_name[MAXLBUFF], buff_line[MAXLBUFF], mode; phfig_list *ptfig; long scale_x; long curr_line; } parser; /************************ DECLARATION DES FONCTIONS *****************/ static long alc_strtophtrs(); static void alc_createphtrs(); static char alc_strtoorient(); static char alc_StrToTransOrient(); static char alc_strtolayer(); static char alc_strtotransf(); static char alc_strtovia(); static void alc_printwarn(); static void alc_printerror(); static void alc_old_load(); static void alc_load(); #ifdef CLEANUP #define TYPE_LNWELL 10 #define TYPE_LNDIF 11 #define TYPE_LPDIF 12 #define TYPE_LCONT_DIF_N 13 #define TYPE_LCONT_DIF_P 14 static void alc_polar(); static long alc_innwell(); #endif # if 0 # define alc_scale_x( X ) (( (X) * SCALE_X ) / parser.scale_x) # else /* LUDO: 04/09/2004 */ static long alc_scale_x( long X ) { if ( SCALE_X != parser.scale_x ) { return ( (long)( (double)X * (double)SCALE_X / (double)parser.scale_x ) ); } else { return( X ); } } # endif /****************** alc_strtophtrs *******************/ static long alc_strtophtrs(s_name,p_layer,lp_l,lp_w) char *s_name, *p_layer; long *lp_l, *lp_w; { static char *p_l,*p_w, buffer[MBKSZNAME]; int i; #ifdef JP_DEBUG puts( "- Execution de \`alc_strtophtrs\` ."); #endif strcpy( buffer, s_name); if ( (buffer[0]!='T')||(buffer[2]!='_') ) return FALSE; switch( buffer[1] ) { case 'N' : *p_layer = NTRANS; break; case 'P' : *p_layer = PTRANS; break; default : return FALSE; } p_l = buffer+3; if ( (p_w=strchr(p_l,'_'))==NULL ) return FALSE; *(p_w++) = '\0'; for( i=0; p_l[i]!='\0'; i++) if ( !mc_isdigit(p_l[i]) ) return( FALSE); for( i=0; p_w[i]!='\0'; i++) if ( !mc_isdigit(p_w[i]) ) return( FALSE); *lp_l = atol( p_l); *lp_w = atol( p_w); return TRUE; } /******************* alc_createphtrs *****************/ static void alc_createphtrs(layer,l,w) char layer; long l,w; { #ifdef JP_DEBUG puts( "- Execution de \`alc_createphtrs\` ."); #endif if ( parser.mode!='C' ) { /* definition des connecteurs. */ /* source */ (void)addphcon( parser.ptfig, WEST, "Source", alc_scale_x( 1 ), alc_scale_x((l>>1)+1), layer, alc_scale_x(l-3) ); (void)addphcon( parser.ptfig, EAST, "Drain", alc_scale_x( w+3 ), alc_scale_x( (l>>1)+1 ), layer, alc_scale_x( l-3 ) ); (void)addphcon( parser.ptfig, NORTH, "Gate", alc_scale_x( (w>>1)+2 ), alc_scale_x(l+1), POLY, alc_scale_x( 1 ) ); (void)addphcon( parser.ptfig, SOUTH, "Gate", alc_scale_x( (w>>1)+2 ), alc_scale_x( 1 ), POLY, alc_scale_x( 1 ) ); } if ( parser.mode!='P' ) { /* segment */ (void)addphseg( parser.ptfig, layer, alc_scale_x( w ), alc_scale_x( (w>>1)+2 ), alc_scale_x(1), alc_scale_x( (w>>1)+2 ),alc_scale_x(l+1), "*"); defab( parser.ptfig, alc_scale_x( (w>>1)+2 ), alc_scale_x(1), alc_scale_x( (w>>1)+3 ), alc_scale_x(l+1) ); } return; } /********************* alc_strtoorient ***************/ static char alc_strtoorient(s_orient) char *s_orient; { #ifdef JP_DEBUG puts( "- Execution de \`alc_strtoorient\` ."); #endif switch( s_orient[0] ) { case 'N' : if ( strcmp(s_orient,"NORD")!=0 ) alc_printerror( EORIENT); return( NORTH); case 'S' : if ( strcmp(s_orient,"SUD")!=0 ) alc_printerror( EORIENT); return( SOUTH); case 'E' : if ( strcmp(s_orient,"EST")!=0 ) alc_printerror( EORIENT); return( EAST); case 'O' : if ( strcmp(s_orient,"OUEST")!=0 ) alc_printerror( EORIENT); return( WEST); default : alc_printwarn( EORIENT); } return SOUTH; } static char alc_StrToTransOrient(aStrTransOrient) char *aStrTransOrient; { if (!strcmp(aStrTransOrient,"RIGHT")) return(RIGHT); if (!strcmp(aStrTransOrient, "LEFT")) return( LEFT); if (!strcmp(aStrTransOrient, "UP")) return( UP); if (!strcmp(aStrTransOrient, "DOWN")) return( DOWN); alc_printerror( ETRANSORIENT); return( 0 ); } /********************* alc_strtoorient3 ***************/ static char alc_strtoorient3(s_orient) char *s_orient; { #ifdef JP_DEBUG puts( "- Execution de \`alc_strtoorient\` ."); #endif switch( s_orient[0] ) { case 'N' : if ( strcmp(s_orient,"NORTH")!=0 ) alc_printerror( EORIENT); return( NORTH); case 'S' : if ( strcmp(s_orient,"SOUTH")!=0 ) alc_printerror( EORIENT); return( SOUTH); case 'E' : if ( strcmp(s_orient,"EAST")!=0 ) alc_printerror( EORIENT); return( EAST); case 'W' : if ( strcmp(s_orient,"WEST")!=0 ) alc_printerror( EORIENT); return( WEST); default : alc_printwarn( EORIENT); } return SOUTH; } /******************** alc_strtolayer *****************/ static char alc_strtolayer(s_layer) char *s_layer; { int i; static char *TabNameLayer[] = { "CAISSON_N", "CAISSON_P", "NTIE", "PTIE" , "DIFN", "DIFP", "NTRANS", "PTRANS", "POLY", "TPOLY", "POLY2", "TPOLY2", "ALU1", "T_ALU1", "ALU2", "T_ALU2", "ALU3", "TALU3" }; #ifdef JP_DEBUG puts( "- Execution de \`alc_strtolayer\` ."); #endif for( i=0; i<18; i++) if ( strcmp(s_layer,TabNameLayer[i])==0 ) return( (char)i ); alc_printwarn( ELAYER); return( NWELL); } /******************** strtolayer *****************/ static char strtolayer(s_layer) char *s_layer; { int i; static char *TabNameLayer[] = { "NWELL", "PWELL", "NTIE", "PTIE", "NDIF", "PDIF", "NTRANS", "PTRANS", "NTRANS_FAST", "PTRANS_FAST", "NTRANS_HVIO", "PTRANS_HVIO", "POLY", "POLY2", "ALU1", "ALU2", "ALU3", "ALU4", "ALU5", "ALU6", "ALU7", "ALU8", "ALU9", "TPOLY", "TPOLY2", "TALU1", "TALU2", "TALU3", "TALU4", "TALU5", "TALU6", "TALU7", "TALU8", "TALU9", "CALU1", "CALU2", "CALU3", "CALU4", "CALU5", "CALU6", "CALU7", "CALU8", "CALU9" }; #ifdef JP_DEBUG puts( "- Execution de \`alc_strtolayer\` ."); #endif for( i=0; i=0 ) { if ( fscanf(parser.file,"%ld,%ld,%ld,%ld ", &xab, &yab, &dxab, &dyab )!=4 ) alc_printerror( EABUTMBOX); defab( parser.ptfig, alc_scale_x(xab), alc_scale_x(yab), alc_scale_x( xab+dxab), alc_scale_x(yab+dyab) ); } else defab( parser.ptfig, alc_scale_x(xbb), alc_scale_x(ybb), alc_scale_x(xbb+dxbb), alc_scale_x(ybb+dybb) ); /* Lecture ligne par ligne du reste du fichier */ for( parser.curr_line=3, exit_loop=FALSE; fgets( parser.buff_line,MAXLBUFFER-1, parser.file )!=NULL; parser.curr_line++ ) { if ( strncmp(parser.buff_line,"EOF",3)==0 ) { exit_loop = TRUE; break; } if ( parser.buff_line[1]!=' ' ) alc_printerror( ESYNTAX); switch( parser.buff_line[0] ) { /* Reconnaissance d'un connecteur. */ case 'C' : { p_index = parser.buff_line+2; mc_nexttoken( p_index , p_x , ENBFIELDS); mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_w , ENBFIELDS); mc_nexttoken( p_w , p_orient , ENBFIELDS); mc_nexttoken( p_orient , p_layer , ENBFIELDS); mc_nexttoken( p_layer , p_name , ENBFIELDS); mc_nexttoken( p_name , p_type_con , ENBFIELDS); mc_nexttoken( p_type_con , p_next_index, ENBFIELDS); mc_nexttoken( p_next_index, p_endequi , ENBFIELDS); if ( strcmp(p_name,"*")==0 ) p_name = (char*)NULL; x = atol( p_x); y = atol( p_y); w = atol( p_w); orient = alc_strtoorient( p_orient); layer = alc_strtolayer( p_layer); if ( (parser.mode=='C')||(!after_inst) ) continue; (void)addphcon( parser.ptfig, orient, p_name,alc_scale_x(x), alc_scale_x(y),layer,alc_scale_x(w) ); } break; /* Reconnaissance d'un segment. */ case 'S' : { after_inst = FALSE; p_index = parser.buff_line+2; mc_nexttoken( p_index , p_x , ENBFIELDS); mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_l , ENBFIELDS); mc_nexttoken( p_l , p_w , ENBFIELDS); mc_nexttoken( p_w , p_sens , ENBFIELDS); mc_nexttoken( p_sens , p_layer , ENBFIELDS); mc_nexttoken( p_layer , p_name , ENBFIELDS); mc_nexttoken( p_name , p_next_index, ENBFIELDS); mc_nexttoken( p_next_index, p_endequi , ENBFIELDS); if ( (*p_sens != 'H')&&(*p_sens != 'V') ) alc_printerror( ETYPESEG); if ( strcmp(p_name,"*")==0 ) p_name = NULL; x = atol( p_x); y = atol( p_y); l = atol( p_l); w = atol( p_w); layer = alc_strtolayer( p_layer); if ( (parser.mode=='P')&&(!mc_isthrough(layer))&&(!mc_isconseg(layer))) continue; if ( (parser.mode=='C')&&( mc_isthrough(layer)) ) continue; (void)addphseg( parser.ptfig, layer,alc_scale_x(w), alc_scale_x(x), alc_scale_x(y), (*p_sens=='H') ? alc_scale_x(x+l) : alc_scale_x(x), (*p_sens=='V') ? alc_scale_x(y+l) : alc_scale_x(y), p_name ); } break; /* Reconnaissance d'une instance. */ case 'I' : { after_inst = TRUE; p_index = parser.buff_line+2; mc_nexttoken( p_index , p_x , ENBFIELDS); mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_name , ENBFIELDS); mc_nexttoken( p_name , p_model , ENBFIELDS); mc_nexttoken( p_model , p_transf , ENBFIELDS); mc_nexttoken( p_transf , p_next_index, ENBFIELDS); mc_nexttoken( p_next_index, p_endequi , ENBFIELDS); x = atol( p_x); y = atol( p_y); transf = alc_strtotransf( p_transf); if ( parser.mode=='P' ) continue; (void)addphins( parser.ptfig, p_model, p_name, transf, alc_scale_x(x), alc_scale_x(y) ); } break; /* Reconnaissance des motifs ( VIA et references ). */ case 'M' : { after_inst = FALSE; p_index = parser.buff_line+2; mc_nexttoken( p_index , p_x , ENBFIELDS); mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_name , ENBFIELDS); mc_nexttoken( p_name , p_model , ENBFIELDS); mc_nexttoken( p_model , p_motif_index , ENBFIELDS); mc_nexttoken( p_motif_index , p_next_index , ENBFIELDS); mc_nexttoken( p_next_index , p_endequi , ENBFIELDS); x = atol( p_x); y = atol( p_y); if ( strncmp(p_model,"REF_",3)==0 ) { if ( parser.mode=='C' ) continue; if ( p_name[0] =='\0' ) p_name = NULL; if ( strcmp(p_name,"*")==0 ) p_name = NULL; (void)addphref( parser.ptfig, p_model, p_name, alc_scale_x(x), alc_scale_x(y) ); } else { if ( parser.mode=='P' ) continue; (void)addphvia( parser.ptfig, alc_strtovia(p_model), alc_scale_x(x), alc_scale_x(y), 0, 0, NULL ); } } break; /* Reconnaissance d'un transistor. */ case 'T' : { after_inst = FALSE; p_index = parser.buff_line+2; mc_nexttoken( p_index , p_x , ENBFIELDS); mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_name , ENBFIELDS); mc_nexttoken( p_name , p_model , ENBFIELDS); mc_nexttoken( p_model , p_transf , ENBFIELDS); mc_nexttoken( p_transf , p_next_index, ENBFIELDS); mc_nexttoken( p_next_index, p_endequi , ENBFIELDS); x = atol( p_x); y = atol( p_y); if ( parser.mode=='P' ) continue; if ( strcmp(p_name,"*")==0 ) p_name = NULL; transf = alc_strtotransf( p_transf); if ( !alc_strtophtrs(p_model,&layer,&l,&w) ) { alc_printwarn( ENAMETRS); (void)addphins( parser.ptfig, p_model, p_name, transf, alc_scale_x(x), alc_scale_x(y) ); continue; } switch( transf ) { case NOSYM : ; case SYM_X : ; case SYM_Y : ; case SYMXY : (void)addphseg( parser.ptfig, layer,alc_scale_x(w), alc_scale_x(x), alc_scale_x(y), alc_scale_x(x), alc_scale_x((y+l)), p_name ); break; case ROT_P : ; case ROT_M : ; case SY_RP : ; case SY_RM : (void)addphseg( parser.ptfig, layer,alc_scale_x(w), alc_scale_x(x), alc_scale_x(y), alc_scale_x((x+l)), alc_scale_x(y), p_name ); break; } } break; /* Composant inconnu. */ default : alc_printerror( ECOMPONENT); } } if ( !exit_loop ) alc_printerror( EMISSEOF); #ifdef CLEANUP alc_polar( parser.ptfig); #endif } /******************************************************************/ /************************ alc_loadvers3 ***************************/ /******************************************************************/ static void alc_load(ptfig,fig_name,mode,setup) phfig_list *ptfig; char *fig_name, mode; long setup; { char s_name[MBKSZNAME], s_date[MBKSZNAME], c_ftype, *p_x , *p_y , *p_x2 , *p_y2 , *p_w, *p_orient, *p_layer, *p_name , *p_model , *p_transf, *p_index , *p_type , *p_endequi, layer, orient; long xab, yab, dxab, dyab, x , y , x2 , y2 , w , transf, exit_loop, vl_tmp; parser.ptfig = ptfig; parser.mode = mode; if ( parser.ptfig==(phfig_list*)NULL ) alc_printerror( EALLOCFIG); /* Lecture de la ligne d'en tete ( prefixe 'H '). */ parser.curr_line++; /* ** --> MODIF LUDO */ if ( setup > 3 ) { if (fscanf(parser.file, "H %[^,],%c,%[^,],%ld\n", s_name, &c_ftype, s_date, &parser.scale_x)!=4) alc_printerror(EHEADER); } else { if (fscanf(parser.file, "H %[^,],%c,%[^\n]\n", s_name, &c_ftype, s_date)!=3) alc_printerror(EHEADER); } if ( strcmp(s_name,fig_name)!=0 ) alc_printerror( EFILENAME); if ( c_ftype!='P' ) alc_printerror( EFILETYPE); /* Lecture de l'abutment box. */ parser.curr_line++; if (fscanf(parser.file,"A %ld,%ld,%ld,%ld ", &xab, &yab, &dxab, &dyab) != 4) alc_printerror(EABUTMBOX); defab(parser.ptfig, alc_scale_x(xab), alc_scale_x(yab), alc_scale_x(dxab), alc_scale_x(dyab)); /* Lecture du reste du fichier ligne par ligne */ for( parser.curr_line++, exit_loop=FALSE; fgets( parser.buff_line,MAXLBUFFER-1, parser.file )!=NULL; parser.curr_line++ ) { if ( strncmp(parser.buff_line,"EOF",3)==0 ) { exit_loop = TRUE; break; } if ( parser.buff_line[1]!=' ' ) alc_printerror( ESYNTAX); switch( parser.buff_line[0] ) { /* Reconnaissance d'un connecteur. */ case 'C' :{ p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_w , ENBFIELDS); mc_nexttoken( p_w , p_name , ENBFIELDS); mc_nexttoken( p_name , p_index , ENBFIELDS); mc_nexttoken( p_index , p_orient , ENBFIELDS); mc_nexttoken( p_orient , p_layer , ENBFIELDS); mc_nexttoken3( p_layer , p_endequi , ENBFIELDS); if ( strcmp(p_name,"*")==0 ) p_name = (char*)NULL; x = atol( p_x); y = atol( p_y); w = atol( p_w); orient = alc_strtoorient3( p_orient); layer = strtolayer( p_layer); if (parser.mode=='C') continue; (void)addphcon( parser.ptfig, orient, p_name, alc_scale_x(x),alc_scale_x(y), layer , alc_scale_x(w) ); } break; /* Reconnaissance d'un segment. */ case 'S' : { p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_x2 , ENBFIELDS); mc_nexttoken( p_x2 , p_y2 , ENBFIELDS); mc_nexttoken( p_y2 , p_w , ENBFIELDS); mc_nexttoken( p_w , p_name , ENBFIELDS); mc_nexttoken( p_name , p_orient , ENBFIELDS); mc_nexttoken( p_orient , p_layer , ENBFIELDS); mc_nexttoken3( p_layer , p_endequi , ENBFIELDS); if ( strcmp(p_name,"*")==0 ) p_name = NULL; x = atol( p_x); y = atol( p_y); x2 = atol( p_x2); y2 = atol( p_y2); w = atol( p_w); layer = strtolayer( p_layer ); orient = alc_StrToTransOrient( p_orient); if ( (parser.mode=='P')&&(!mc_isthrough(layer)&&(! mc_isconseg(layer))) ) continue; /* MODIF LUDO 4/2/00 */ if ( (parser.mode=='C')&&( mc_isthrough(layer) || mc_isconseg(layer))) continue; if (orient == LEFT) { vl_tmp = x; x = x2; x2 = vl_tmp; } if (orient == DOWN) { vl_tmp = y; y = y2; y2 = vl_tmp; } (void)addphseg( parser.ptfig, layer, alc_scale_x(w),alc_scale_x(x),alc_scale_x(y), alc_scale_x(x2),alc_scale_x(y2),p_name ); } break; /* Reconnaissance d'une instance. */ case 'I' : { p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_model , ENBFIELDS); mc_nexttoken( p_model , p_name , ENBFIELDS); mc_nexttoken( p_name , p_transf , ENBFIELDS); mc_nexttoken3( p_transf , p_endequi , ENBFIELDS); x = atol( p_x); y = atol( p_y); transf = alc_strtotransf( p_transf); if ( parser.mode=='P' ) continue; (void)addphins( parser.ptfig, p_model, p_name, transf, alc_scale_x(x), alc_scale_x(y) ); } break; /* Reconnaissance des references . */ case 'R' : {p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_model , ENBFIELDS); mc_nexttoken( p_model , p_name , ENBFIELDS); mc_nexttoken3( p_name , p_endequi , ENBFIELDS); x = atol( p_x); y = atol( p_y); if ( parser.mode=='C' ) continue; if ( p_name[0] =='\0' ) p_name = NULL; if ( strcmp(p_name,"*")==0 ) p_name = NULL; (void)addphref( parser.ptfig, p_model, p_name, alc_scale_x(x), alc_scale_x(y) ); } break; /* Reconnaissance des VIA . */ case 'V' : {p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_type , ENBFIELDS); if ( setup > 5 ) { mc_nexttoken( p_type, p_name, ENBFIELDS ); mc_nexttoken3( p_name, p_endequi, ENBFIELDS ); if ( ( p_name[ 0 ] == '\0' ) || ( ! strcmp(p_name, "*" ) ) ) p_name = (char *)0; } else { p_name = (char *)0; mc_nexttoken3( p_type, p_endequi, ENBFIELDS); } x = atol( p_x); y = atol( p_y); if ( parser.mode=='P' ) continue; (void)addphvia(parser.ptfig, strtovia(p_type), alc_scale_x(x), alc_scale_x(y), 0, 0, p_name); } break; /* Reconnaissance des BIG-VIA . */ case 'B' : {p_x = parser.buff_line+2; mc_nexttoken( p_x , p_y , ENBFIELDS); mc_nexttoken( p_y , p_x2 , ENBFIELDS); mc_nexttoken( p_x2 , p_y2 , ENBFIELDS); mc_nexttoken( p_y2 , p_type , ENBFIELDS); if ( setup > 5 ) { mc_nexttoken( p_type, p_name, ENBFIELDS ); mc_nexttoken3( p_name, p_endequi, ENBFIELDS ); if ( ( p_name[ 0 ] == '\0' ) || ( ! strcmp(p_name, "*" ) ) ) p_name = (char *)0; } else { p_name = (char *)0; mc_nexttoken3( p_type, p_endequi, ENBFIELDS); } x = atol( p_x); y = atol( p_y); x2 = atol( p_x2 ); y2 = atol( p_y2 ); if ( parser.mode=='P' ) continue; (void)addphvia(parser.ptfig, strtovia(p_type), alc_scale_x(x), alc_scale_x(y), alc_scale_x(x2), alc_scale_x(y2), p_name); } break; /* Composant inconnu. */ default : alc_printerror( ECOMPONENT); } } if ( !exit_loop ) alc_printerror( EMISSEOF); } /************************** alc_printwarn **************************/ static void alc_printwarn(warn_code) long warn_code; { fprintf( stderr, "\n*** mbk warning *** alcloadphfig : "); switch( warn_code ) { case ELAYER : fprintf( stderr, "invalid layer"); break; case EOPGEO : fprintf( stderr, "invalid geometric operation"); break; case EORIENT : fprintf( stderr, "unknow orientation"); break; case ENAMETRS : fprintf( stderr, "invalid transistor"); break; case ETYPEVIA : fprintf( stderr, "invalid via"); break; default : fprintf( stderr, "unknow warning"); } fprintf( stderr, "\n( line %ld parsing %s )\n", parser.curr_line, parser.file_name ); } /**************************** alc_printerror *************************/ static void alc_printerror(error_code) long error_code; { fprintf( stderr, "\n*** mbk error *** alcloadphfig : "); switch( error_code ) { case EVER : fprintf( stderr, "invalid version of alc"); break; case EOPEN : fprintf( stderr, "unable to open file : %s .\n", parser.file_name);EXIT(1); case ECLOSE : fprintf( stderr, "can\'t close file : %s", parser.file_name);break; case ESETUP : fprintf( stderr, "invalid setup\'s number"); break; case ESYNTAX : fprintf( stderr, "syntax error"); break; case EMISSEOF : fprintf( stderr, "missing EOF"); break; case ETYPESEG : fprintf( stderr, "segment neither H nor V"); break; case ETRANSORIENT: fprintf( stderr, "Unknow transistor orientation"); break; case EHEADER : fprintf( stderr, "unexpected header"); break; case ENBFIELDS : fprintf( stderr, "missing or non-numeric field"); break; case EFILENAME : fprintf( stderr, "invalid file name"); break; case EFILETYPE : fprintf( stderr, "bad file type"); break; case EBOUNDBOX : fprintf( stderr, "can\'t read bounding box"); break; case EABUTMBOX : fprintf( stderr, "can\'t read abutment box"); break; case EALLOCFIG : fprintf( stderr, "ptfig not allocated"); break; case ECOMPONENT : fprintf( stderr, "invalid component"); break; default : fprintf( stderr, "unknow error"); } fprintf( stderr, "\n( line %ld parsing %s )\n",parser.curr_line, parser.file_name ); EXIT( 1); } #ifdef CLEANUP #define access_seg(seg_list) ( (phseg_list*)(seg_list->DATA) ) #define access_via(via_list) ( (phvia_list*)(via_list->DATA) ) /****************************** alc_polar ****************************/ static void alc_polar(ptfig) phfig_list *ptfig; { phvia_list *pvia; phseg_list *pseg; ptype_list *LP_NWELL, *LP_NDIF, *LP_PDIF, *LP_CONT_DIF_N, *LP_CONT_DIF_P, *lPPHSEG, *lPPHVIA; #ifdef JP_DEBUG puts( "- Execution de \'alc_polar\' ."); #endif LP_NWELL = LP_NDIF = LP_PDIF = LP_CONT_DIF_N = LP_CONT_DIF_P = (ptype_list*)NULL; /* Transformation des segments PTIE et NTIE en PDIF et NDIF. On memorise dans les listes LP_PDIF et LP_NDIF non seule- ment les TIE mais aussi les NDIF et PDIF. ( en cas d'erreur de conception ) On en profite pour lister les segments NWELL. */ for( pseg=ptfig->PHSEG; pseg!=(phseg_list*)NULL; pseg =pseg->NEXT ) switch( pseg->LAYER ) { case NWELL : LP_NWELL = addptype( LP_NWELL, TYPE_LNWELL, (void*)pseg ); break; case NTIE : pseg->LAYER = NDIF; case NDIF : LP_NDIF = addptype( LP_NDIF , TYPE_LNDIF , (void*)pseg ); break; case PTIE : pseg->LAYER = PDIF; case PDIF : LP_PDIF = addptype( LP_PDIF , TYPE_LPDIF , (void*)pseg ); break; } /* Transformation des contacts BODY_P et BODY_N en DIF_P et DIF_N. On memorise dans les listes LP_CONT_DIF_P et LP_CONT_DIF_N non seulement les BODY mais aussi les DIF_N et les DIF_P. ( en cas d'erreur de conception ) */ for( pvia=ptfig->PHVIA; pvia!=(phvia_list*)NULL; pvia =pvia->NEXT ) switch( pvia->TYPE ) { case CONT_BODY_N : pvia->TYPE = CONT_DIF_N; case CONT_DIF_N : LP_CONT_DIF_N = addptype( LP_CONT_DIF_N , TYPE_LCONT_DIF_N, (void*)pvia ); break; case CONT_BODY_P : pvia->TYPE = CONT_DIF_P; case CONT_DIF_P : LP_CONT_DIF_P = addptype( LP_CONT_DIF_P , TYPE_LCONT_DIF_P, (void*)pvia ); break; } /* Restauration des NTIE. Un segment de type NTIE est detecte lorsque un segment NDIF est inclus dans du NWELL. */ for( lPPHSEG=LP_NDIF; lPPHSEG!=(ptype_list*)NULL; lPPHSEG =lPPHSEG->NEXT ) if ( alc_innwell(access_seg(lPPHSEG)->X1, access_seg(lPPHSEG)->Y1, LP_NWELL )) access_seg(lPPHSEG)->LAYER = NTIE; /* Restauration des PTIE. Un segment de type PTIE est detecte lorsque un segment PDIF est hors de tout NWELL. ( substrat dope P ). */ for( lPPHSEG=LP_PDIF; lPPHSEG!=(ptype_list*)NULL; lPPHSEG =lPPHSEG->NEXT ) if ( !alc_innwell(access_seg(lPPHSEG)->X1, access_seg(lPPHSEG)->Y1, LP_NWELL )) access_seg(lPPHSEG)->LAYER = PTIE; /* Restauration des BODY_N. ( contact DIF_N inclus dans le NWELL ) */ for( lPPHVIA=LP_CONT_DIF_N; lPPHVIA!=(ptype_list*)NULL;lPPHVIA =lPPHVIA->NEXT) { #ifdef JP_DEBUG puts( "\tVIA N en cours d\'examen :"); viewphvia( access_via(lPPHVIA)); fgetc( stdin); #endif if ( alc_innwell(access_via(lPPHVIA)->XVIA, access_via(lPPHVIA)->YVIA,LP_NWELL)) { access_via(lPPHVIA)->TYPE = CONT_BODY_N; #ifdef JP_DEBUG viewphvia( access_via(lPPHVIA)); #endif } } /* Restauration des BODY_P. ( contact DIF_P hors du NWELL ) */ for( lPPHVIA=LP_CONT_DIF_P; lPPHVIA!=(ptype_list*)NULL;lPPHVIA =lPPHVIA->NEXT) { #ifdef JP_DEBUG puts( "\tVIA P en cours d\'examen :"); viewphvia( access_via(lPPHVIA)); fgetc( stdin); #endif if ( !alc_innwell(access_via(lPPHVIA)->XVIA, access_via(lPPHVIA)->YVIA,LP_NWELL )) { access_via(lPPHVIA)->TYPE = CONT_BODY_P; #ifdef JP_DEBUG viewphvia( access_via(lPPHVIA)); #endif } } } /********************* Fonction : 'alc_innwell' *******************/ static long alc_innwell(x,y,LP_NWELL) long x, y; ptype_list *LP_NWELL; { ptype_list *lPPHSEG; #ifdef JP_DEBUG puts( "- Execution de \'alc_innwell\' ."); #endif for( lPPHSEG=LP_NWELL; lPPHSEG!=(ptype_list*)NULL; lPPHSEG =lPPHSEG->NEXT ) { #ifdef JP_DEBUG puts( "\tExamen d\'un NWELL."); #endif if ( (access_seg(lPPHSEG)->TYPE==LEFT ) ||(access_seg(lPPHSEG)->TYPE==RIGHT) ) { if ( (x>=access_seg(lPPHSEG)->X1) &&(x<=access_seg(lPPHSEG)->X2) &&(y>=access_seg(lPPHSEG)->Y1 -access_seg(lPPHSEG)->WIDTH/2) &&(y<=access_seg(lPPHSEG)->Y1 +access_seg(lPPHSEG)->WIDTH/2) ) return TRUE; } else if ( (x>=access_seg(lPPHSEG)->X1 -access_seg(lPPHSEG)->WIDTH/2) &&(x<=access_seg(lPPHSEG)->X1 +access_seg(lPPHSEG)->WIDTH/2) &&(y>=access_seg(lPPHSEG)->Y1) &&(y<=access_seg(lPPHSEG)->Y2) ) return TRUE; } #ifdef JP_DEBUG puts( "\tHors de tout NWELL."); #endif return FALSE; } #endif /****************************************************************/ /***************** Fonction : alcloadphfig **********************/ /****************************************************************/ void alcloadphfig(ptfig, fig_name, mode) phfig_list *ptfig; char *fig_name, mode; { long setup; char buffer[BUFSIZ]; sprintf( parser.file_name, "%s.%s", fig_name, IN_PH); if ( !filepath(fig_name,IN_PH) || !(parser.file=mbkfopen(fig_name,IN_PH,READ_TEXT))) alc_printerror(EOPEN); parser.curr_line = 1; parser.scale_x = 1; if (!fgets(buffer, BUFSIZ, parser.file)) alc_printerror(ESYNTAX); /* printf( "%s\n", buffer); */ if (sscanf(buffer, "V ALLIANCE : %ld ", &setup) == 1) { if (setup >= 3) alc_load(ptfig, fig_name, mode,setup); else alc_printerror(ESETUP); } else if (sscanf(buffer, "V ALLIANCE 2.2 SETUP : %ld ", &setup) == 1) { if (setup == 2) alc_old_load(ptfig, fig_name, mode); else alc_printerror(ESETUP); } else alc_printerror(EVER); if (fclose(parser.file) != 0) alc_printerror(ECLOSE); }