1 /*
2 * Copyright (C) 1990-1992 Yale University
3 *
4 * This work is distributed in the hope that it will be useful; you can
5 * redistribute it and/or modify it under the terms of the
6 * GNU General Public License as published by the Free Software Foundation;
7 * either version 2 of the License,
8 * or any later version, on the following conditions:
9 *
10 * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11 * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12 * SALE OR
13 * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14 * PATENT OR
15 * OTHER RIGHTS NOT VESTED IN YALE.
16 *
17 * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18 * WARRANTIES
19 * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20 * INCLUDING,
21 * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22 * PARTICULAR
23 * PURPOSE.
24 *
25 * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26 * WHATSOEVER TO
27 * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28 * ARTICLE
29 * (a) AND (b) above.
30 *
31 * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32 * EMPLOYEES AND
33 * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34 * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35 * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36 * POSSIBILITY OF THE FOREGOING.
37 *
38 */
39
40 /* -----------------------------------------------------------------
41 FILE: yreadpar.c
42 DESCRIPTION: Read a TimberWolf parameter file.
43 CONTENTS:
44 DATE: Oct 24, 1990
45 REVISION: Nov 23, 1990 - Fixed for tab spaces in USER file.
46 Dec 21, 1990 - Changed buffer to static so it
47 won't disappear upon return.
48 Sat Jan 26 16:33:03 PST 1991 - added genrows
49 to list of programs.
50 Wed Jan 30 18:35:01 EST 1991 - fixed problem
51 with numtokens access violation on empty lines.
52 Fri Feb 22 23:41:39 EST 1991 - added wildcard
53 boolean to Yreadpar_next and renamed for Tomus.
54 Wed Apr 17 23:32:00 EDT 1991 - Added design rule
55 information into the .par file.
56 Wed Jun 5 16:35:41 CDT 1991 - added overhang and
57 aspect limit to design rules. Also fixed
58 Yreadpar_next problems.
59 Mon Aug 12 16:02:33 CDT 1991 - modified for new
60 Yrbtree_init routine.
61 Sat Apr 18 11:29:50 EDT 1992 - added compactor
62 program entry - CMPT.
63 ----------------------------------------------------------------- */
64
65 #include <string.h>
66 #include <yalecad/file.h>
67 #include <yalecad/rbtree.h>
68 #include <yalecad/message.h>
69 #include <yalecad/string.h>
70 #include <yalecad/yreadpar.h>
71
72 #define COMMENT '#'
73 #define WILDCARD '*'
74 #define END(v) (v-1 + sizeof(v)/sizeof(v[0]) ) /* for table lookup */
75 #define CHARACTERISTIC (DOUBLE) 1000.0 ;
76 #define DEFAULT_LAYERS 3
77 #define DEFAULT_VIAS 2
78
79 /* the rule type definitions */
80 #define CAPACITANCE_T 'c'
81 #define RESISTANCE_T 'r'
82 #define DIRECTION_T 'd'
83 #define LAYER_T 'l'
84 #define WIDTH_T 'w'
85 #define VIA_T 'v'
86 #define SPACING_T 's'
87 #define OVERHANG_T 'o'
88 #define ASPECTLIM_T 'a'
89
90 #define ERROR_CHECK(type) \
91 if(!(layerArrayS )){ \
92 M(ERRMSG,"Yreadpar_errorcheck","No rules found in parameter file\n");\
93 return( (type) 0 ) ; \
94 }
95
96 typedef struct {
97 char *rule ;
98 union {
99 BOOL bvalue ;
100 INT ivalue ;
101 DOUBLE fvalue ;
102 char *svalue ;
103 } value ;
104 } RULEBOX, *RULEPTR ;
105
106 static YTREEPTR rule_treeS ;
107 static INT numlayS = 0 ;
108 static INT numviaS = 0 ;
109 static INT alloc_layS = DEFAULT_LAYERS ;
110 static INT alloc_viaS = DEFAULT_VIAS ;
111 static char **layerArrayS = NIL(char **) ;
112 static char **viaArrayS = NIL(char **) ;
113
114 /* reserved programs binary search */
115 /* -----------------------------------------------------------------
116 The following is table of the reserved words - Table must be in
117 alphabetical order for binary search to work properly.
118 ----------------------------------------------------------------- */
119 static struct ptable_rec { /* reserved program table */
120 char *program ; /* program name */
121 INT program_id ; /* program id */
122 char *suffix ; /* program suffix */
123 } pgmtableS[] = {
124 "CMPT", CMPT, "cpar",
125 "GENR", GENR, "genpar",
126 "MICK", MICK, "gpar",
127 "MINC", MINC, "mtpar",
128 "PART", PART, "ppar",
129 "SGGR", SGGR, "sgpar",
130 "TWAR", TWAR, "apar",
131 "TWMC", TWMC, "mpar",
132 "TWSC", TWSC, "spar",
133 "USER", USER, "par"
134 } ;
135
136 typedef struct {
137 char *parameter ; /* the parameter keyword */
138 char **tokens ; /* the values of the parameter */
139 INT numtokens ; /* number of tokens */
140 INT program ; /* name of program */
141 } PARAM, *PARAMPTR ;
142
143 static FILE *fpS = NIL(FILE *) ;
144 static char copy_bufferS[LRECL] ;
145 static char bufferS[LRECL] ;
146 static INT filter_idS = 0 ;
147 static INT prog_idS = 0 ;
148 static INT lineS = 0 ;
149 static char filterNameS[5] ;
150 static BOOL verboseS = TRUE ;
151
prog2id(program)152 static INT prog2id( program )
153 char *program ;
154 {
155 INT c ;
156 struct ptable_rec *low = pgmtableS, /* ptr to beginning */
157 *mid ,
158 *high = END(pgmtableS) ; /* ptr to end */
159
160 /* binary search to look thru table to find pattern match */
161 while( low <= high){
162 mid = low + (high-low) / 2 ;
163 if( (c = strcmp(mid->program, program) ) == STRINGEQ){
164 return( mid->program_id ) ; /* return token number */
165 } else if( c < 0 ){
166 low = mid + 1 ;
167 } else {
168 high = mid - 1 ;
169 }
170 }
171 /* at this point we haven't found a match so we have an error */
172 return( UNKN ) ;
173
174 } /* end prog2id function */
175
id2prog(id)176 static char *id2prog( id )
177 INT id ;
178 {
179 if( id > 0 && id <= MAXID ){
180 return( pgmtableS[id-1].program ) ;
181 } else {
182 return( NIL(char *) ) ;
183 }
184 } /* end id2prog */
185
id2suffix(id)186 static char *id2suffix( id )
187 INT id ;
188 {
189 if( id > 0 && id <= MAXID ){
190 return( pgmtableS[id-1].suffix ) ;
191 } else {
192 return( NIL(char *) ) ;
193 }
194 } /* end id2prog */
195
196 /* compare routine for design rule processing */
compare_rule(key1,key2)197 static INT compare_rule( key1, key2 )
198 RULEPTR key1, key2 ;
199 {
200 return( (INT)strcmp( key1->rule, key2->rule ) ) ;
201 } /* end compare */
202
check_layer(layer)203 static BOOL check_layer( layer )
204 char *layer ;
205 {
206 INT i ; /* counter */
207
208 verboseS = FALSE ;
209 if( Yreadpar_layer2id( layer ) ){
210 verboseS = TRUE ;
211 return( FALSE ) ;
212 } else {
213 for( i = 1; i <= numviaS; i++ ){
214 if( strcmp( Yreadpar_viaId2name( i ), layer ) == STRINGEQ ){
215 verboseS = TRUE ;
216 return( FALSE ) ;
217 }
218 }
219 }
220 sprintf( YmsgG,
221 "Layer or via:%s has not been defined. Rule ignored.\n", layer) ;
222 M( ERRMSG, "check_layer", YmsgG ) ;
223 verboseS = TRUE ;
224 return( TRUE ) ;
225 } /* end check_layer */
226
227
make_data(rule,value,type)228 static char *make_data( rule, value, type )
229 char *rule ;
230 char *value ;
231 char type ;
232 {
233 RULEPTR data ;
234 RULEBOX data_buffer ;
235 DOUBLE fvalue ;
236 INT data_value ;
237 char key[LRECL] ;
238
239 /* make the key */
240 sprintf( key, "%s:%c", rule, type ) ;
241 data_buffer.rule = key ;
242
243 /* see if key already exists */
244 if( Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
245 sprintf( YmsgG, "Rule on line:%d already exists. Ignored.\n", lineS ) ;
246 M( ERRMSG, "Yreadpar_init", YmsgG ) ;
247 return( NIL(char *) ) ;
248 }
249
250 data = YMALLOC( 1, RULEBOX ) ;
251 data->rule = Ystrclone( key ) ;
252
253 switch( type ){
254 case CAPACITANCE_T:
255 case RESISTANCE_T:
256 data->value.fvalue = atof( value ) ;
257 break ;
258 case DIRECTION_T:
259 /* use the HnotV convention */
260 if( strcmp( value, "vertical" ) == STRINGEQ ){
261 data->value.bvalue = FALSE ;
262 } else if( strcmp( value, "horizontal" ) == STRINGEQ ){
263 data->value.bvalue = TRUE ;
264 } else {
265 M( ERRMSG, "Yreadpar_init", "Unknown layer direction\n" ) ;
266 }
267 break ;
268 case LAYER_T:
269 data->value.ivalue = (INT) value ;
270 break ;
271 case WIDTH_T:
272 /* now calculate value */
273 fvalue = atof( value ) ;
274
275 /* This code converts the float to an integer
276 fvalue *= CHARACTERISTIC ;
277 data_value = ROUND( fvalue ) ;
278 data->value.ivalue = data_value ;
279 */
280
281 data->value.fvalue = fvalue ;
282
283 break ;
284 case ASPECTLIM_T:
285 data->value.fvalue = atof( value ) ;
286 break ;
287 } /* end switch on type */
288
289 return( (char *) data ) ;
290
291 } /* end make_data */
292
make_data2(object1,object2,value,type)293 static char *make_data2( object1, object2, value, type )
294 char *object1 ;
295 char *object2 ;
296 char *value ;
297 char type ;
298 {
299 RULEPTR data ;
300 RULEBOX data_buffer ;
301 DOUBLE fvalue ;
302 INT data_value ;
303 char key[LRECL] ;
304
305
306 /* make the key order the key alphabetically */
307 if( strcmp( object1, object2 ) <= STRINGEQ ){
308 sprintf( key, "%s/%s:%c", object1, object2, type ) ;
309 } else {
310 sprintf( key, "%s/%s:%c", object2, object1, type ) ;
311 }
312 data_buffer.rule = key ;
313
314 /* see if key already exists */
315 if( Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
316 sprintf( YmsgG, "Rule on line:%d already exists. Ignored.\n", lineS ) ;
317 M( ERRMSG, "Yreadpar_init", YmsgG ) ;
318 return( NIL(char *) ) ;
319 }
320
321 data = YMALLOC( 1, RULEBOX ) ;
322 data->rule = Ystrclone( key ) ;
323
324 switch( type ){
325 case VIA_T:
326 data->value.svalue = Ystrclone( value ) ;
327 break ;
328 case SPACING_T:
329 /* now calculate value */
330 fvalue = atof( value ) ;
331
332 /* This code converts the float to an integer
333 fvalue *= CHARACTERISTIC ;
334 data_value = ROUND( fvalue ) ;
335 data->value.ivalue = data_value ;
336 */
337
338 data->value.fvalue = fvalue ;
339
340 break ;
341 }
342 return( (char *) data ) ;
343 } /* end make_data_spacing */
344
345
Yreadpar_init(design_name,parfile,filter,abortFlag)346 VOID Yreadpar_init( design_name, parfile, filter, abortFlag )
347 char *design_name ;
348 INT parfile ;
349 INT filter ;
350 BOOL abortFlag ;
351 {
352 char *suffix ; /* parameter file suffix */
353 char *pname ; /* program name of filter */
354 char filename[LRECL] ; /* the file name */
355 char *bufferptr ;
356 char **tokens ;
357 INT i ; /* counter */
358 INT numtokens ; /* number of tokens on a line */
359 BOOL rule_section ; /* true if rule section exists */
360 char *data ; /* rule data to be stored */
361 static BOOL rules_unreadL=TRUE; /* false after the rules have been read */
362
363 if( suffix = id2suffix( parfile ) ){
364 prog_idS = parfile ;
365 sprintf( filename, "%s.%s", design_name, suffix ) ;
366 if( pname = id2prog( filter )){
367 filter_idS = filter ;
368 strcpy( filterNameS, pname ) ;
369 } else {
370 M( ERRMSG, "Yreadpar_init", "Unknown filter program\n" ) ;
371 }
372 } else {
373 M( ERRMSG, "Yreadpar_init", "Unknown parameter file\n" ) ;
374 return ;
375 } /* end switch on program */
376
377 /* now that we have the file name open the par file */
378 if(fpS){
379 M( ERRMSG, "Yreadpar_init",
380 "Only one par file may be read at the same time\n" ) ;
381 return ;
382 }
383 fpS = TWOPEN( filename, "r", abortFlag ) ;
384 if(!(fpS) ){
385 return ;
386 }
387 lineS = 0 ;
388 rule_section = FALSE ;
389
390
391 /* TRY to read the RULES SECTION of the parameter file */
392 while( bufferptr = fgets( bufferS, LRECL, fpS ) ){
393 lineS++ ;
394 /* remove leading blanks */
395 bufferptr = Yremove_lblanks( bufferptr ) ;
396 if( *bufferptr == '#' ){
397 /* skip over comments */
398 continue ;
399 }
400 tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ;
401 if( numtokens == 0 ){
402 continue ;
403 }
404 if( strcmp( tokens[0], "RULES" ) == STRINGEQ ){
405 rule_section = TRUE ;
406 /* initialize tree of rules */
407 rule_treeS = Yrbtree_init( compare_rule ) ;
408 /* initialize the number of layers */
409 layerArrayS = YVECTOR_CALLOC( 1,alloc_layS,char *) ;
410 viaArrayS = YVECTOR_CALLOC( 1,alloc_viaS,char *) ;
411 continue ;
412 } else if( strcmp( tokens[0], "ENDRULES" ) == STRINGEQ ){
413 rules_unreadL = FALSE ;
414 break ;
415 }
416 if( rule_section && rules_unreadL ){
417 if( strcmp( tokens[0], "width" ) == STRINGEQ &&
418 numtokens == 3 ){
419 if( check_layer( tokens[1] ) ){
420 continue ;
421 }
422 data = make_data( tokens[1], tokens[2], WIDTH_T ) ;
423 if( data ){
424 Yrbtree_insert( rule_treeS, data ) ;
425 }
426 } else if( strcmp( tokens[0], "spacing" ) == STRINGEQ &&
427 numtokens == 4 ){
428 if( check_layer( tokens[1] ) ){
429 continue ;
430 }
431 if( check_layer( tokens[2] ) ){
432 continue ;
433 }
434 data = make_data2( tokens[1], tokens[2], tokens[3], SPACING_T ) ;
435 if( data ){
436 Yrbtree_insert( rule_treeS, data ) ;
437 }
438 } else if( strcmp( tokens[0], "via" ) == STRINGEQ &&
439 (numtokens == 4 || numtokens == 5) ){
440 if( ++numviaS >= alloc_viaS ){
441 /* need to expand the number of vias allocated */
442 alloc_viaS = numviaS + 3 ;
443 viaArrayS = YVECTOR_REALLOC( viaArrayS,1,alloc_viaS,char * ) ;
444 for( i = numviaS; i <= alloc_viaS; i++ ){
445 viaArrayS[i] = NIL(char *) ;
446 }
447
448 }
449 /* at this point safe to use vianame */
450 /* we need two mechanisms : viaid to vianame - use array */
451 /* and vianame to viaid - use balanced tree */
452 viaArrayS[numviaS] = Ystrclone( tokens[1] ) ;
453 data = make_data2( tokens[2], tokens[3], tokens[1], VIA_T ) ;
454 if( data ){
455 Yrbtree_insert( rule_treeS, data ) ;
456 }
457 if( numtokens == 5 ){
458 data = make_data( tokens[1], tokens[4], ASPECTLIM_T ) ;
459 } else {
460 /* set the default to 1.0 for aspect ratio limit */
461 data = make_data( tokens[1], "1.0", ASPECTLIM_T ) ;
462 }
463 if( data ) Yrbtree_insert( rule_treeS, data ) ;
464
465 } else if( strncmp( tokens[0], "layer",5 ) == STRINGEQ &&
466 numtokens == 5 ){
467 if( ++numlayS >= alloc_layS ){
468 /* need to expand the number of layers allocated */
469 alloc_layS = numlayS + 3 ;
470 layerArrayS = YVECTOR_REALLOC(layerArrayS,1,alloc_layS,char*);
471 for( i = numlayS; i <= alloc_layS; i++ ){
472 layerArrayS[i] = NIL(char *) ;
473 }
474
475 }
476 /* at this point safe to use layer */
477 /* we need two mechanisms : layerid to layername - use array */
478 /* and layername to layerid - use balanced tree */
479 layerArrayS[numlayS] = Ystrclone( tokens[1] ) ;
480 data = make_data( tokens[1], (char *) numlayS, LAYER_T ) ;
481 if( data ) Yrbtree_insert( rule_treeS, data ) ;
482 /* store the values of res, cap, and routing preference */
483 data = make_data( tokens[1], tokens[2], RESISTANCE_T ) ;
484 if( data ) Yrbtree_insert( rule_treeS, data ) ;
485 data = make_data( tokens[1], tokens[3], CAPACITANCE_T ) ;
486 if( data ) Yrbtree_insert( rule_treeS, data ) ;
487 data = make_data( tokens[1], tokens[4], DIRECTION_T ) ;
488 if( data ) Yrbtree_insert( rule_treeS, data ) ;
489
490 } else if( strncmp( tokens[0], "overhang",8 ) == STRINGEQ &&
491 numtokens == 4 ){
492 data = make_data2( tokens[1], tokens[2], tokens[3], OVERHANG_T ) ;
493 if( data ) Yrbtree_insert( rule_treeS, data ) ;
494
495 } else {
496 sprintf( YmsgG, "Unknown rule at line:%d in filename:%s\n",
497 lineS, filename ) ;
498 M( ERRMSG, "Yreadpar_init", YmsgG ) ;
499 }
500
501 }/* end processing of rule section */
502
503 } /* end while */
504
505 if(!(rule_section)){
506 rewind(fpS) ;
507 lineS = 0 ;
508 }
509
510 } /* end Yreadpar_init */
511
Yreadpar_next(lineptr,line,numtokens,onNotOff,wildcard)512 char **Yreadpar_next( lineptr, line, numtokens, onNotOff, wildcard )
513 char **lineptr ;
514 INT *line ;
515 INT *numtokens ;
516 BOOL *onNotOff ;
517 BOOL *wildcard ;
518 {
519 PARAMPTR data ;
520 char *bufferptr ;
521 char **tokens ;
522 BOOL rule_section ;
523
524
525 if( filter_idS == UNKN || !(fpS) ){
526 /* don't read an unknown format */
527 return( NIL(char **) ) ;
528 }
529 /* assume that every option is on */
530 *onNotOff = TRUE ;
531 rule_section = FALSE ;
532 while( bufferptr = fgets( bufferS, LRECL, fpS )){
533 /* parse file */
534 lineS++ ;
535 *line = lineS ;
536 /* remove leading blanks */
537 bufferptr = Yremove_lblanks( bufferptr ) ;
538 /* skip comments */
539 if( *bufferptr == COMMENT ){
540 continue ;
541 }
542 if( strncmp( bufferptr, "RULES", 5 ) == STRINGEQ ){
543 rule_section = TRUE ;
544 /* skip over rules section */
545 continue ;
546 } else if( strncmp( bufferptr, "ENDRULES", 8 ) == STRINGEQ ){
547 rule_section = FALSE ;
548 /* skip over rules section */
549 continue ;
550 } else if( rule_section ){
551 continue ;
552 }
553 *wildcard = FALSE ;
554 strcpy( copy_bufferS, bufferptr ) ;
555 *lineptr = copy_bufferS ;
556 if( prog_idS == USER ){
557 bufferptr = Yremove_lblanks( bufferptr ) ;
558 if( *bufferptr != WILDCARD ){
559 tokens = Ystrparser( bufferptr, "*\n", numtokens ) ;
560 if( *numtokens == 2 ){
561 /* look for match for this program */
562 if( strcmp( tokens[0], filterNameS ) != STRINGEQ ){
563 /* go on to the next line */
564 if( prog_idS == USER ){
565 continue ;
566 }
567 }
568 bufferptr = tokens[1] ;
569 } else if( *numtokens == 0 ){
570 continue ;
571 } else {
572 sprintf( YmsgG,
573 "Trouble parsing line:%d :\n\t%s\n", lineS,
574 copy_bufferS ) ;
575 M( ERRMSG, "Yreadpar_next", YmsgG ) ;
576 continue ;
577 }
578 } else {
579 /* WILDCARD skip over it */
580 *wildcard = TRUE ;
581 bufferptr++ ;
582 }
583 }
584 tokens = Ystrparser( bufferptr, " :\t\n", numtokens ) ;
585 if( *numtokens > 1 ){
586 if( strcmp( tokens[*numtokens-1], "off" ) == STRINGEQ ){
587 /* we have turned this value off */
588 *onNotOff = FALSE ;
589 }
590 }
591 return( tokens ) ;
592 }
593 TWCLOSE( fpS ) ;
594 fpS = NIL( FILE * ) ;
595 return( NIL(char **) ) ;
596
597 } /* end Yreadpar_next */
598
compare_parameter(key1,key2)599 static INT compare_parameter( key1, key2 )
600 PARAMPTR key1, key2 ;
601 {
602 return( (INT)strcmp( key1->parameter, key2->parameter ) ) ;
603 } /* end compare */
604
Yreadpar_file()605 YPARPTR Yreadpar_file()
606 {
607 PARAMPTR data ;
608 YPARPTR store ; /* a tree with all the parameters */
609 char *lineptr ;
610 char **tokens ;
611 INT numtokens ;
612 INT line ;
613 INT i ; /* counter */
614 BOOL onNotOff ;
615 BOOL wildcard ;
616
617 store = (YPARPTR) NULL ;
618
619 if( prog_idS == UNKN || !(fpS) ){
620 /* don't read an unknown format */
621 return( store ) ;
622 }
623
624 /* initialize a tree which store the data found in the *par file*/
625 YRBTREE_INIT( store, compare_parameter );
626
627 /* assume that every option is on */
628 while( tokens = Yreadpar_next( &lineptr, &line, &numtokens,
629 &onNotOff, &wildcard )){
630 if( numtokens == 0 ){
631 continue ;
632 }
633 if( numtokens >= 2 ){
634 /* copy tokens for storing in a tree */
635 data = YMALLOC( 1, PARAM ) ;
636 data->parameter = Ystrclone( tokens[0] ) ;
637 data->program = filter_idS ;
638 data->tokens = YMALLOC( numtokens-1, char * ) ;
639 for( i = 1; i < numtokens ; i++ ){
640 data->tokens[i-1] = Ystrclone( tokens[i] ) ;
641 }
642 data->numtokens = numtokens - 1 ; /* save rest of line */
643 /* now write the tokens */
644 Yrbtree_insert( store, data ) ;
645 } else {
646 sprintf( YmsgG,
647 "Trouble parsing line:%d :\n\t%s\n", line,
648 lineptr ) ;
649 M( ERRMSG, "Yreadpar_file", YmsgG ) ;
650 continue ;
651 }
652 } /* end while loop */
653
654 TWCLOSE( fpS ) ;
655 fpS = NIL( FILE * ) ;
656 return( store ) ;
657
658 } /* end Yreadpar_file */
659
Yreadpar_lookup(par_object,param,program,numtokens)660 char **Yreadpar_lookup( par_object, param, program, numtokens )
661 YPARPTR par_object ; /* parameter tree */
662 char *param ; /* parameter */
663 INT program ; /* program id */
664 INT *numtokens ; /* returns the number of tokens for parameter */
665 {
666 PARAMPTR data ; /* store this in the tree */
667 PARAM key ;
668
669 *numtokens = 0 ;
670 key.parameter = param ;
671 data = (PARAMPTR) Yrbtree_interval(par_object,&key,&key,TRUE) ;
672 while( data ){
673 if( data->program == program ){
674 *numtokens = data->numtokens ;
675 return( data->tokens ) ;
676 }
677 data = (PARAMPTR) Yrbtree_interval(par_object,&key,&key,FALSE) ;
678 }
679 /* if we get to this point we didn't find a match */
680 return( NIL(char **) ) ;
681 } /* end Yreadpar_lookup */
682
Yreadpar_spacing(object1,object2)683 DOUBLE Yreadpar_spacing( object1, object2 )
684 char *object1, *object2 ;
685 {
686 char key[LRECL] ;
687 RULEPTR data ;
688 RULEBOX data_buffer ;
689
690 ERROR_CHECK(DOUBLE) ;
691 /* first build the key */
692 sprintf( key, "%s/%s:%c", object1, object2, SPACING_T ) ;
693 data_buffer.rule = key ;
694
695 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
696 return( data->value.fvalue ) ;
697 } else if( verboseS ){
698 sprintf( YmsgG,
699 "Spacing for %s to %s not defined in the given design rules.\n",
700 object1, object2 );
701 M( ERRMSG, "Yreadpar_spacing", YmsgG ) ;
702 M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ;
703 }
704 return( 0 ) ;
705
706 } /* end Yreadpar_spacing */
707
Yreadpar_width(object)708 DOUBLE Yreadpar_width( object )
709 char *object ;
710 {
711 char key[LRECL] ;
712 RULEPTR data ;
713 RULEBOX data_buffer ;
714
715 ERROR_CHECK(DOUBLE) ;
716 /* first build the key */
717 sprintf( key, "%s:%c", object, WIDTH_T ) ;
718 data_buffer.rule = key ;
719 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
720 return( data->value.fvalue ) ;
721 } else {
722 sprintf( YmsgG,
723 "Width for %s not defined in the given design rules.\n",
724 object );
725 M( ERRMSG, "Yreadpar_width", YmsgG ) ;
726 M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ;
727 return( 0 ) ;
728 }
729
730 } /* end Yreadpar_spacing */
731
Yreadpar_pitch(object)732 DOUBLE Yreadpar_pitch( object )
733 char *object ;
734 {
735 DOUBLE spacing ;
736 DOUBLE width ;
737
738 /* pitch for a given layer is spacing plus width */
739
740 ERROR_CHECK(DOUBLE) ;
741 spacing = Yreadpar_spacing( object, object ) ;
742 width = Yreadpar_width( object ) ;
743 return( spacing + width ) ;
744 } /* end Yreadpar_pitch */
745
Yreadpar_layer_res(object)746 DOUBLE Yreadpar_layer_res( object )
747 char *object ;
748 {
749 char key[LRECL] ;
750 RULEPTR data ;
751 RULEBOX data_buffer ;
752
753 ERROR_CHECK(DOUBLE) ;
754 /* first build the key */
755 sprintf( key, "%s:%c", object, RESISTANCE_T ) ;
756 data_buffer.rule = key ;
757 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
758 return( data->value.fvalue ) ;
759 } else if( verboseS ){
760 sprintf( YmsgG,
761 "Resistance for layer %s not defined in the given design rules.\n",
762 object );
763 M( ERRMSG, "Yreadpar_layer_res", YmsgG ) ;
764 M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ;
765 }
766 return( 0 ) ;
767
768 } /* end Yreadpar_layer_res */
769
Yreadpar_layer_cap(object)770 DOUBLE Yreadpar_layer_cap( object )
771 char *object ;
772 {
773 char key[LRECL] ;
774 RULEPTR data ;
775 RULEBOX data_buffer ;
776
777 ERROR_CHECK(DOUBLE) ;
778 /* first build the key */
779 sprintf( key, "%s:%c", object, CAPACITANCE_T ) ;
780 data_buffer.rule = key ;
781 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
782 return( data->value.fvalue ) ;
783 } else if( verboseS ){
784 sprintf( YmsgG,
785 "Capacitance for layer %s defined in the given design rules.\n",
786 object );
787 M( ERRMSG, "Yreadpar_layer_cap", YmsgG ) ;
788 M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ;
789 }
790 return( (DOUBLE) 0.0 ) ;
791
792 } /* end Yreadpar_layer_cap */
793
Yreadpar_layer_HnotV(object)794 BOOL Yreadpar_layer_HnotV( object )
795 char *object ;
796 {
797 char key[LRECL] ;
798 char *keyptr ;
799 RULEPTR data ;
800 RULEBOX data_buffer ;
801
802 ERROR_CHECK(BOOL) ;
803 /* first build the key */
804 sprintf( key, "%s:%c", object, DIRECTION_T ) ;
805 data_buffer.rule = key ;
806 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
807 return( data->value.bvalue ) ;
808 } else if( verboseS ){
809 sprintf( YmsgG,
810 "Routing direction for layer %s defined in the given design rules.\n",
811 object );
812 M( ERRMSG, "Yreadpar_layer_HnotV", YmsgG ) ;
813 M( ERRMSG, NULL, "\tDefaulting to horizontal.\n\n" ) ;
814 }
815 return( TRUE ) ;
816
817 } /* end Yreadpar_layer_HnotV */
818
Yreadpar_layer2id(object)819 INT Yreadpar_layer2id( object )
820 char *object ;
821 {
822 char key[LRECL] ;
823 RULEPTR data ;
824 RULEBOX data_buffer ;
825
826 ERROR_CHECK(INT) ;
827 /* first build the key */
828 sprintf( key, "%s:%c", object, LAYER_T ) ;
829 data_buffer.rule = key ;
830 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
831 return( data->value.ivalue ) ;
832 } else if( verboseS ){
833 sprintf( YmsgG,
834 "Routing layer %s not defined in the given design rules.\n",
835 object );
836 M( ERRMSG, "Yreadpar_layer2id", YmsgG ) ;
837 M( ERRMSG, NULL, "\tDefaulting to horizontal.\n\n" ) ;
838 }
839 return( TRUE ) ;
840
841 } /* end Yreadpar_layer2id */
842
Yreadpar_id2layer(layerid)843 char *Yreadpar_id2layer( layerid )
844 INT layerid ;
845 {
846 ERROR_CHECK(char*) ;
847 if( layerid > 0 && layerid <= numlayS ){
848 return( layerArrayS[layerid] ) ;
849 } else {
850 sprintf( YmsgG,
851 "Layer id:%d is out of bounds. Numlayers = %d\n",
852 layerid, numlayS ) ;
853 M( ERRMSG, "Yreadpar_id2layer", YmsgG ) ;
854 M( ERRMSG, NULL, "\tDefaulting to layer 1.\n\n" ) ;
855 return( layerArrayS[1] ) ;
856 }
857
858 } /* end Yreadpar_id2layer */
859
Yreadpar_numlayers()860 INT Yreadpar_numlayers()
861 {
862 return( numlayS ) ;
863 } /* end Yreadpar_numlayers */
864
Yreadpar_vianame(object1,object2)865 char *Yreadpar_vianame( object1, object2 )
866 char *object1, *object2 ;
867 {
868 char key[LRECL] ;
869 RULEPTR data ;
870 RULEBOX data_buffer ;
871
872 ERROR_CHECK(char*) ;
873 /* first build the key */
874 data_buffer.rule = key ;
875 /* make the key order the key alphabetically */
876 if( strcmp( object1, object2 ) <= STRINGEQ ){
877 sprintf( key, "%s/%s:%c", object1, object2, VIA_T ) ;
878 } else {
879 sprintf( key, "%s/%s:%c", object2, object1, VIA_T ) ;
880 }
881 if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){
882 return( data->value.svalue ) ;
883 } else if( verboseS ){
884 sprintf( YmsgG,
885 "Could not find a via between layers %s and %s.\n",
886 object1, object2 );
887 M( ERRMSG, "Yreadpar_vianame", YmsgG ) ;
888 }
889 return( NIL(char *) ) ;
890
891 } /* end Yreadpar_vianame */
892
Yreadpar_viaId2name(viaid)893 char *Yreadpar_viaId2name( viaid )
894 INT viaid ;
895 {
896 ERROR_CHECK(char*) ;
897 if( viaid > 0 && viaid <= numviaS ){
898 return( viaArrayS[viaid] ) ;
899 } else {
900 sprintf( YmsgG,
901 "Via id:%d is out of bounds. Numvias = %d\n",
902 viaid, numviaS ) ;
903 M( ERRMSG, "Yreadpar_viaId2name", YmsgG ) ;
904 M( ERRMSG, NULL, "\tDefaulting to via id 1.\n\n" ) ;
905 return( viaArrayS[1] ) ;
906 }
907
908 } /* end Yreadpar_viaId2name */
909