1 /*
2 * Copyright (C) 1989-1991 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: configpads.c
42 DESCRIPTION:Configure pads
43 CONTENTS:
44 DATE: Jan 29, 1989 - added heading.
45 REVISIONS: Jan 29, 1989 - removed message about pad limited designs.
46 Mar 30, 1989 - changed tile datastructure.
47 Apr 30, 1989 - fixed problem with padgroups. Rewrote major
48 sections of the algorithm.
49 Thu Feb 14 02:41:45 EST 1991 - new algorithm for placing
50 pads. Still need to do VARIABLE_PADS.
51 Fri Feb 15 15:13:49 EST 1991 - added VARIABLE PAD code.
52 Sun Feb 17 21:10:35 EST 1991 - added min_pad_spacing.
53 Thu Mar 7 01:52:16 EST 1991 - now perform pad rotations
54 correctly.
55 Tue Mar 19 16:01:40 CST 1991 - added core expansion code.
56 Thu Apr 18 01:45:56 EDT 1991 - fixed problem with align_pads
57 Thu Aug 29 15:44:00 CDT 1991 - added overflow processing
58 code.
59 ----------------------------------------------------------------- */
60
61 #include <standard.h>
62 #include <pads.h>
63 #include <parser.h>
64 #include <yalecad/relpos.h>
65 #include <yalecad/message.h>
66
67 /* ***************** STATIC FUNCTION DEFINITIONS ******************* */
68 static BOOL check_overflow( P1(BOOL retain_pad_groups) ) ;
69 static void move_clockwise( P4(INT pad, INT side, INT cw_side, INT moveable_cw) ) ;
70 static void move_counterclockwise( P4(INT pad,INT side,INT ccw_side,INT m_ccw ) ) ;
71 static void update_pad_position( P3(PADBOXPTR pad,INT current_side, INT move_side) );
72 static void expand_core( P1(INT side) ) ;
73 static INT compare_overflow( P2(INT *side1, INT *side2) ) ;
74 static void update_pad_groups( P1(void) ) ;
75 static void resort_place_array( P1(void) ) ;
76 static void child_constraints(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL s));
77 static void place_variable( P3(INT first,INT numpads,INT side) ) ;
78
79 void calc_constraints( PADBOXPTR pad, INT side, DOUBLE *lb, DOUBLE *ub, BOOL *spacing_restricted, INT *lowpos, INT *uppos );
80
81 /* ***************** STATIC VARIABLE DEFINITIONS ******************* */
82 static INT overflowS[5] ; /* amount of overflow on each side */
83 static INT side_lengthS[5] ; /* sum of pad lengths on a side */
84 static INT first_pad_on_sideS[5] ; /* index of first pad on side */
85 static INT last_pad_on_sideS[5] ; /* index of last pad on side */
86 static INT pad_extraS ; /* insure that sort works correctly */
87
align_pads()88 void align_pads()
89 {
90 INT pad ; /* counter */
91 INT side ; /* current pad side */
92 INT last ; /* index of last pad on side */
93 INT first ; /* index of first pad on side */
94 INT count ; /* count number of overflow iterations */
95 INT length ; /* length of current pad */
96 INT needed ; /* extra space needed on each side */
97 INT numpads ; /* number of pads on this side */
98 INT cum_space ; /* cum_space on this side */
99 INT padspacing ; /* padspacing method for current side*/
100 INT extra_space ; /* slack on a side */
101 BOOL overflow_exists ; /* if set, overflow still exists */
102 BOOL retain_pad_groups ; /* if set, padgroups will not be moved from side */
103 PADBOXPTR padptr ; /* current pad info */
104 DOUBLE left_edge ; /* left edge of the placed pad */
105 DOUBLE extra_space_per_pad ; /* how much left over per pad */
106
107 count = 0 ;
108 retain_pad_groups = TRUE ;
109 pad_extraS = 100000 ;
110 do {
111 overflow_exists = check_overflow( retain_pad_groups ) ;
112 if( overflow_exists ){
113 resort_place_array() ;
114 }
115 if( ++count >= 3 ){
116 retain_pad_groups = FALSE ;
117 }
118 } while( overflow_exists ) ;
119
120 update_pad_groups() ;
121
122 for( side = 1 ; side <= 4 ; side++ ) {
123 if(!(first_pad_on_sideS[side])){
124 /* there are no pads on this side */
125 continue ;
126 }
127 extra_space = perdimG[ side%2 ] - side_lengthS[side] ;
128 /* check to see if we have overflow */
129 if( extra_space <= 0 ){
130 /* we must perform abut padspacing on this side */
131 padspacing = ABUT_PADS ;
132 } else {
133 /* do what the user requested */
134 padspacing = padspacingG ;
135 }
136
137 first = first_pad_on_sideS[side] ;
138 last = last_pad_on_sideS[side] ;
139 numpads = last - first + 1 ;
140
141 switch( padspacing ){
142 case UNIFORM_PADS:
143 extra_space_per_pad = (DOUBLE) extra_space /
144 (DOUBLE) (numpads+1) ;
145 left_edge = (DOUBLE) coreG[side%2][MINI] ;
146 for( pad = 1; pad <= numpads; pad++ ){
147 padptr = placearrayG[first + pad - 1] ;
148 /* calculate the placement of the left edge of the pad */
149 left_edge += extra_space_per_pad ;
150 /* now find the center of the current pad */
151 padptr->position = ((INT) left_edge ) +
152 padptr->length / 2 ;
153 /* now set left edge for next pad */
154 left_edge += (DOUBLE)
155 (padptr->length + min_pad_spacingG) ;
156 }
157 break ;
158 case ABUT_PADS:
159 extra_space_per_pad = (DOUBLE) extra_space / 2.0 ;
160 left_edge = (DOUBLE) coreG[side%2][MINI] + extra_space_per_pad ;
161
162 for( pad = 1; pad <= numpads; pad++ ){
163 padptr = placearrayG[first + pad - 1] ;
164 /* now find the center of the current pad */
165 padptr->position = ((INT) left_edge ) +
166 padptr->length / 2 ;
167 /* now set left edge for next pad */
168 left_edge += (DOUBLE)
169 (padptr->length + min_pad_spacingG) ;
170 }
171 break ;
172 case VARIABLE_PADS:
173 /* we now we can fit it on this side */
174 place_variable( first, numpads, side ) ;
175 break ;
176 case EXACT_PADS:
177 break ;
178
179 } /* end switch */
180
181 } /* end loop on sides */
182
183 } /* end align_pads */
184 /* ***************************************************************** */
185
check_overflow(retain_pad_groups)186 static BOOL check_overflow( retain_pad_groups )
187 BOOL retain_pad_groups ;
188 {
189 INT i ; /* counter */
190 INT pad ; /* counter */
191 INT side ; /* current pad side */
192 INT cw_pad ; /* pad to move in clockwise direction */
193 INT ccw_pad ; /* pad to move in ccw direction */
194 INT length ; /* length of current pad */
195 INT clockwise ; /* the side in the clockwise direction */
196 INT counterclockwise ; /* the side in the ccw direction */
197 INT overflow_cw ; /* amount of overflow when pad is moved cw */
198 INT overflow_ccw ; /* amount of overflow when pad is moved ccw */
199 INT moveable_cw ; /* size of pad to be moved cw */
200 INT moveable_ccw ; /* size of pad to be moved ccw */
201 INT side_open[5] ; /* whether side has been processed */
202 INT sort_overflow[5] ; /* index for sorted overflow */
203 INT compare_overflow() ; /* sort the sides for overflow */
204 PADBOXPTR padptr ; /* current pad info */
205
206 /* first accummulate the sum of all the pads on a given side */
207 /* also find the first and last pad on a given side */
208 for( side = 1 ; side <= 4 ; side++ ) {
209 overflowS[side] = 0 ;
210 side_lengthS[side] = 0 ;
211 first_pad_on_sideS[side] = 0 ;
212 last_pad_on_sideS[side] = -1 ;
213 }
214 for( pad = 1 ; pad <= numpadsG ; pad++ ) {
215 padptr = placearrayG[pad] ;
216 side = padptr->padside ;
217 length = padptr->length ;
218 /* this will add one too many min_pad_spacing */
219 /* subtract it below */
220 side_lengthS[side] += length + min_pad_spacingG ;
221 if(!(first_pad_on_sideS[side])){
222 first_pad_on_sideS[side] = pad ;
223 }
224 last_pad_on_sideS[side] = pad ;
225 }
226
227 /* check for overflow on the sides */
228 for( side = 1 ; side <= 4 ; side++ ) {
229 /* adjust extra min_pad_spacing */
230 if(first_pad_on_sideS[side]){
231 /* there are pads on this side */
232 side_lengthS[side] -= min_pad_spacingG ;
233 }
234 overflowS[side] = side_lengthS[side] - perdimG[ side%2 ] ;
235 }
236 /* check to see if we have overflow */
237 if( overflowS[L] <= 0 && overflowS[R] <= 0 &&
238 overflowS[B] <= 0 && overflowS[T] <= 0 ){
239 /* there is no overflow */
240 return( FALSE ) ;
241 }
242
243 /* overflow exists so resolve the conflict. */
244 /* first sort the overflow */
245 for( i = 1 ; i <= 4; i++ ){
246 /* initialize sort_overflow array */
247 sort_overflow[i] = i ;
248 side_open[i] = TRUE ;
249 }
250 Yquicksort( &(sort_overflow[1]), 4, sizeof(INT), compare_overflow );
251 for( i = 1; i <= 4; i++ ){
252 side = sort_overflow[i] ;
253 side_open[side] = FALSE ;
254 if( overflowS[side] <= 0 ){
255 continue ;
256 }
257 /* find clockwise side */
258 clockwise = side + 1 ;
259 if( clockwise > 4 ) clockwise = 1 ; /* wrap around */
260 /* find counter clockwise side */
261 counterclockwise = side - 1 ;
262 if( counterclockwise < 1 ) counterclockwise = 4 ; /* wrap around */
263
264 do {
265 /* look for the last valid pad on side to move clockwise */
266 /* make sure side is still open */
267 cw_pad = 0 ;
268 if( side_open[clockwise] ){
269 for( pad = last_pad_on_sideS[side];pad >= first_pad_on_sideS[side];
270 pad-- ){
271 padptr = placearrayG[pad] ;
272 if( padptr->padside != side ){
273 /* this means we already moved this pad from this side */
274 continue ;
275 }
276 if( retain_pad_groups && padptr->hierarchy != NONE ){
277 /* if the retain_pad_group switch is on, we ignore any */
278 /* pad in a padgroup */
279 continue ;
280 }
281 if( padptr->valid_side[ALL] || padptr->valid_side[clockwise] ){
282 cw_pad = pad ;
283 moveable_cw = padptr->length + min_pad_spacingG ;
284 break ;
285 }
286 } /* end pad = last_pad_on_side... */
287 } /* end side_open[clockwise... */
288
289 /* look for the first valid pad on side to move counterclockwise */
290 /* make sure side is still open */
291 ccw_pad = 0 ;
292 if( side_open[counterclockwise] ){
293 for( pad = first_pad_on_sideS[side]; pad <= last_pad_on_sideS[side];
294 pad++ ){
295 padptr = placearrayG[pad] ;
296 if( padptr->padside != side ){
297 /* this means we already moved this pad from this side */
298 continue ;
299 }
300 if( retain_pad_groups && padptr->hierarchy != NONE ){
301 /* if the retain_pad_group switch is on, we ignore any */
302 /* pad in a padgroup */
303 continue ;
304 }
305 if( padptr->valid_side[ALL] || padptr->valid_side[counterclockwise] ){
306 ccw_pad = pad ;
307 moveable_ccw = padptr->length + min_pad_spacingG ;
308 break ;
309 }
310 } /* end pad = first_pad_on_side... */
311 } /* end side_open[counterclockwise... */
312
313 if( cw_pad && ccw_pad ){
314 /* this is the case where there are two valid pads which can be moved */
315 /* pick the pad && side which has smaller overflow */
316 overflow_cw = overflowS[clockwise] + moveable_cw ; ;
317 overflow_ccw = overflowS[counterclockwise] + moveable_ccw ; ;
318 if( overflow_cw <= overflow_ccw ){
319 move_clockwise( cw_pad, side, clockwise, moveable_cw ) ;
320 } else {
321 move_counterclockwise( ccw_pad, side, counterclockwise, moveable_ccw ) ;
322 }
323 } else if( cw_pad ){
324 move_clockwise( cw_pad, side, clockwise, moveable_cw ) ;
325 } else if( ccw_pad ){
326 move_counterclockwise( ccw_pad, side, counterclockwise,
327 moveable_ccw ) ;
328 } else {
329 /* no more pads to move, we need to expand core */
330 expand_core( side ) ;
331 return( TRUE ) ;
332 }
333 } while( overflowS[side] > 0 ) ;
334
335 } /* end for( i = 1; i <= 4; i++ ) ... */
336
337 /* if we get here, we had some overflow */
338 return( TRUE ) ;
339
340 } /* end check_overflow */
341
move_clockwise(pad,side,clockwise_side,moveable_cw)342 static void move_clockwise( pad, side, clockwise_side, moveable_cw )
343 INT pad, side, clockwise_side, moveable_cw ;
344 {
345 PADBOXPTR padptr ; /* current pad info */
346
347 /* move pad */
348 padptr = placearrayG[pad] ;
349 padptr->padside = clockwise_side ;
350 /* determine position */
351 update_pad_position( padptr, side, clockwise_side ) ;
352 /* reset the overflows */
353 overflowS[side] -= moveable_cw ;
354 overflowS[clockwise_side] += moveable_cw ;
355
356 } /* end move_clockwise */
357
358
move_counterclockwise(pad,side,counterclockwise,moveable_ccw)359 static void move_counterclockwise( pad, side, counterclockwise, moveable_ccw )
360 INT pad, side, counterclockwise, moveable_ccw ;
361 {
362 PADBOXPTR padptr ; /* current pad info */
363
364 /* move pad */
365 padptr = placearrayG[pad] ;
366 padptr->padside = counterclockwise ;
367 update_pad_position( padptr, side, counterclockwise ) ;
368 /* determine position */
369 /* reset the overflows */
370 overflowS[side] -= moveable_ccw ;
371 overflowS[counterclockwise] += moveable_ccw ;
372
373 } /* end move_counterclockwise */
374
update_pad_position(padptr,current_side,move_side)375 static void update_pad_position( padptr, current_side, move_side )
376 PADBOXPTR padptr ; /* current pad info */
377 INT current_side ;
378 INT move_side ;
379 {
380 INT dimension ; /* the X or Y dimension */
381
382 dimension = move_side % 2 ;
383 switch( current_side ){
384 case L:
385 padptr->position = coreG[dimension][MINI] - ++pad_extraS;
386 break ;
387 case T:
388 padptr->position = coreG[dimension][MAXI] + ++pad_extraS ;
389 break ;
390 case R:
391 padptr->position = coreG[dimension][MAXI] + ++pad_extraS ;
392 break ;
393 case B:
394 padptr->position = coreG[dimension][MINI] - ++pad_extraS;
395 break ;
396 } /* end switch side ... */
397 } /* end update_pad_position */
398
expand_core(side)399 static void expand_core( side )
400 INT side ;
401 {
402 INT i ; /* counter */
403 INT pad ; /* counter */
404 INT overflow_amount ; /* amount to expand */
405 INT amount ; /* amount to add to each pad half of a side */
406 INT expansion ; /* amount to expand a dimension */
407 PADBOXPTR padptr ; /* current pad info */
408
409 overflow_amount = 0 ;
410 /* determine how much to expand by */
411 /* normally we assume that all sides can help reduce overflow */
412 /* if we find that the overflow_amount < 0 or overflow_amount is only */
413 /* 25% of the overflow on a side, it means that some sides */
414 /* have non moveable pads. We need to make the overflow amount the given side */
415 for( i = 1; i <= 4 ; i++ ){
416 overflow_amount += overflowS[i] ;
417 }
418 if( overflow_amount < 0 || overflow_amount < 0.25 * overflowS[side] ){
419 overflow_amount = overflowS[side] ;
420 }
421
422 /* now divide the amount equally in both dimensions */
423 expansion = overflow_amount / 2 ;
424 if( expansion <= 0 ) expansion = 1 ;
425 amount = expansion / 2 ;
426 coreG[X][MINI] -= amount ;
427 coreG[X][MAXI] += (expansion - amount ) ;
428 coreG[Y][MINI] -= amount ;
429 coreG[Y][MAXI] += (expansion - amount ) ;
430 /* expand in X and Y directions */
431 /* we to search all the pads since they may not be in order */
432 for( pad = 1 ; pad <= numpadsG ; pad++ ) {
433 padptr = placearrayG[pad] ;
434 side = padptr->padside ;
435 padptr->position += amount ;
436 }
437 /* now reset the perimeters */
438 perdimG[X] = coreG[X][MAXI] - coreG[X][MINI] ;
439 perdimG[Y] = coreG[Y][MAXI] - coreG[Y][MINI] ;
440 } /* end expand_core */
441
compare_overflow(side1,side2)442 static INT compare_overflow( side1, side2 )
443 INT *side1, *side2 ;
444 {
445 /* sort largest to smallest */
446 return( overflowS[*side2] - overflowS[*side1] ) ;
447 } /* end compare_overflow */
448
compare_placearray(padptr1,padptr2)449 static INT compare_placearray( padptr1, padptr2 )
450 PADBOXPTR *padptr1, *padptr2 ;
451 {
452 PADBOXPTR pad1, pad2;
453
454 pad1 = *padptr1 ;
455 pad2 = *padptr2 ;
456
457 if( pad1->padside != pad2->padside) {
458 return( pad1->padside - pad2->padside ) ;
459 }
460 if( pad1->position < pad2->position ){
461 return( -1 ) ;
462 } else if( pad1->position > pad2->position ){
463 return( 1 ) ;
464 } else {
465 return( 0 ) ;
466 }
467 } /* end compare_placearray */
468
resort_place_array()469 static void resort_place_array()
470 {
471 Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), compare_placearray );
472 } /* end resort_place_array */
473 /* ***************************************************************** */
474
475 /* set the lo_pos and hi_pos fields for the pads */
update_pad_groups()476 static void update_pad_groups()
477 {
478
479 INT i ; /* pad counter */
480 DOUBLE lobound ; /* lower bound on position */
481 DOUBLE hibound ; /* upper bound on position */
482 BOOL spacing_restricted ; /* whether spacing is restricted */
483 PADBOXPTR pad ; /* current pad */
484
485 if( padspacingG != VARIABLE_PADS ){
486 return ;
487 }
488
489 /* now update the lo_pos and hi_pos fields of the pad */
490 for( i = 1 ; i <= totalpadsG; i++ ) {
491 pad = padarrayG[i];
492 /* make copy of these we don't want to change roots copy */
493 lobound = pad->lowerbound ;
494 hibound = pad->upperbound ;
495 spacing_restricted = pad->fixed ;
496 if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){
497 child_constraints( pad, pad->padside, lobound, hibound,
498 spacing_restricted ) ;
499
500 } else if( pad->padtype == PADTYPE && pad->hierarchy == NONE ) {
501 /* the case of a pad that is not in a padgroup */
502 calc_constraints( pad, pad->padside, &lobound, &hibound,
503 &spacing_restricted, &(pad->lo_pos), &(pad->hi_pos) ) ;
504 }
505 }
506
507 } /* end update_pad_groups */
508
509 /* this will set the constaints for pad groups and children of them */
child_constraints(pad,side,lb,ub,spacing_restricted)510 static void child_constraints( pad, side, lb, ub, spacing_restricted )
511 PADBOXPTR pad ;
512 INT side ;
513 DOUBLE lb, ub ;
514 BOOL spacing_restricted ;
515 {
516 INT i ; /* pad counter */
517 INT howmany ; /* number of children */
518 PADBOXPTR child ; /* current child */
519
520 calc_constraints( pad, side, &lb, &ub, &spacing_restricted,
521 &(pad->lo_pos), &(pad->hi_pos) );
522
523 if( pad->padtype != PADTYPE ){
524 howmany = pad->children[HOWMANY] ;
525 for( i = 1 ;i <= howmany ; i++ ){
526 child = padarrayG[ pad->children[i] ] ;
527 child_constraints( child, side, lb, ub,spacing_restricted ) ;
528 }
529 }
530 } /* end child_constraints */
531 /* ***************************************************************** */
532
calc_constraints(PADBOXPTR pad,INT side,DOUBLE * lb,DOUBLE * ub,BOOL * spacing_restricted,INT * lowpos,INT * uppos)533 void calc_constraints( PADBOXPTR pad, INT side, DOUBLE *lb, DOUBLE *ub, BOOL *spacing_restricted, INT *lowpos, INT *uppos )
534 {
535 DOUBLE lowbound, hibound ;
536
537 /* determine spacing restrictions */
538 if( *spacing_restricted ){
539 /* this is the case that the spacing has been restricted */
540 if( pad->fixed ){
541 /* if the padgroup bounds have been fixed, */
542 /* force position to be within bound */
543 /* assume we are ok and then correct it */
544 lowbound = pad->lowerbound ;
545 if( lowbound < *lb ){
546 lowbound = *lb ;
547 }
548 if( lowbound > *ub ){
549 lowbound = *ub ;
550 }
551 hibound = pad->upperbound ;
552 if( hibound < *lb ){
553 hibound = *lb ;
554 }
555 if( hibound > *ub ){
556 hibound = *ub ;
557 }
558 } else {
559 /* this pad is not fixed use the given ub and lb */
560 lowbound = *lb ; hibound = *ub ;
561 }
562 } else {
563 if( pad->fixed ){
564 /* the padgroup bounds have not been fixed */
565 /* just take the pad's restricted position */
566 lowbound = pad->lowerbound;
567 hibound = pad->upperbound;
568 *spacing_restricted = TRUE ;
569 }
570 }
571 if( *spacing_restricted ){
572 *lowpos = (INT) ( lowbound * (DOUBLE)perdimG[side%2] ) ;
573 *lowpos += coreG[side%2][MINI] ;
574 *uppos = (INT) ( hibound * (DOUBLE)perdimG[side%2] ) ;
575 *uppos += coreG[side%2][MINI] ;
576 } else {
577 *lowpos = -1 ;
578 *uppos = PINFINITY ;
579 }
580 /* **** END spacing restriction calculations *** */
581 /* return low bound */
582 *lb = lowbound ;
583 *ub = hibound ;
584
585 } /* end calc_constraints */
586 /* ***************************************************************** */
587
place_variable(first,numpads,side)588 static void place_variable( first, numpads, side )
589 INT first, numpads, side ;
590 {
591 INT pad ; /* counter */
592 INT left_edge ; /* current left edge of pad */
593 INT right_edge ; /* current right edge of pad */
594 INT half_length ; /* half the span of a pad */
595 INT valid_left_edge ;/* this position is open for the pad leftedge*/
596 INT valid_right_edge;/* this position is open for the pad rightedge*/
597 PADBOXPTR padptr ; /* current pad info */
598
599 valid_left_edge = 0 ;
600 for( pad = 0; pad < numpads; pad++ ){
601 padptr = placearrayG[first + pad ] ;
602 /* now find the left edge of the current pad */
603 half_length = padptr->length / 2 ;
604 left_edge = padptr->position - half_length ;
605 valid_left_edge = MAX( valid_left_edge, padptr->lo_pos ) ;
606 if( left_edge < valid_left_edge ){
607 /* need to remove overlap */
608 /* so left edge of pad becomes valid_left_edge */
609 left_edge = valid_left_edge ;
610 /* calculate new padptr position */
611 padptr->position = valid_left_edge + half_length ;
612 }
613 /* now calculate the new valid left edge */
614 valid_left_edge = left_edge + padptr->length + min_pad_spacingG ;
615 }
616
617 valid_right_edge = coreG[side%2][MAXI] ;
618 /* now condense pads if they exceed the length of the side */
619 for( pad = numpads-1; pad >= 0; pad-- ){
620 padptr = placearrayG[first + pad] ;
621 /* now find the left edge of the current pad */
622 half_length = padptr->length / 2 ;
623 half_length = padptr->length - half_length ;
624 right_edge = padptr->position + half_length ;
625 valid_right_edge = MIN( valid_right_edge, padptr->hi_pos ) ;
626 if( right_edge > valid_right_edge ){
627 /* need to remove overlap */
628 /* so left edge of pad becomes valid_left_edge */
629 right_edge = valid_right_edge ;
630 /* calculate new padptr position */
631 padptr->position = valid_right_edge - half_length ;
632 } else {
633 break ;
634 }
635 /* now calculate the new valid right edge */
636 valid_right_edge = right_edge - padptr->length - min_pad_spacingG ;
637 }
638
639 } /* end place_variable */
640 /* ***************************************************************** */
641
dimension_pads()642 void dimension_pads()
643 {
644 INT i ; /* pad counter */
645 PADBOXPTR pad ; /* current pad */
646 PINBOXPTR pin ; /* current pin */
647 CBOXPTR cptr ; /* current cell */
648
649 for( i = 1 ; i <= numpadsG; i++ ) {
650 pad = padarrayG[i];
651 cptr = carrayG[ pad->cellnum ] ;
652 switch( pad->padside) {
653 case L:
654 cptr->cxcenter = coreG[X][MINI] - pad->height / 2 ;
655 cptr->cycenter = pad->position ;
656 break;
657 case T:
658 cptr->cxcenter = pad->position ;
659 cptr->cycenter = coreG[Y][MAXI] + pad->height / 2 ;
660 break;
661 case R:
662 cptr->cxcenter = coreG[X][MAXI] + pad->height / 2 ;
663 cptr->cycenter = pad->position ;
664 break;
665 case B:
666 cptr->cxcenter = pad->position ;
667 cptr->cycenter = coreG[Y][MINI] - pad->height / 2 ;
668 break;
669 } /* end switch on side */
670
671 /* now update the pins */
672 for( pin = cptr->pins; pin ; pin = pin->nextpin ){
673 REL_POST( cptr->corient,
674 pin->txpos[1], pin->typos[1], /* result */
675 pin->txpos[0],
676 pin->typos[0], /* cell relative */
677 0, 0 ) ; /* cell relative */
678 /* global positions */
679 pin->xpos = pin->txpos[1] + cptr->cxcenter ;
680 pin->ypos = pin->typos[1] + cptr->cycenter ;
681 }
682 }
683
684 } /* dimension_pads */
685 /* ***************************************************************** */
686
687
orient_pads()688 void orient_pads()
689 {
690 INT i ; /* counter */
691 PADBOXPTR pad ; /* current pad info */
692 CBOXPTR cptr ; /* current cell */
693
694 for( i = 1; i <= numpadsG; i++ ){
695 pad = placearrayG[i];
696 cptr = carrayG[ pad->cellnum ] ;
697 switch( pad->padside) {
698 case L:
699 /* rotate 270 | -90 */
700 cptr->corient = (SHORT) 7 ;
701 cptr->cycenter = cptr->cxcenter;
702 break;
703 case T:
704 /* rotate180 */
705 cptr->corient = (SHORT) 3 ;
706 break;
707 case R:
708 /* rotate90 */
709 cptr->corient = (SHORT) 6 ;
710 cptr->cycenter = cptr->cxcenter;
711 break;
712 case B:
713 cptr->corient = (SHORT) 0 ;
714 break;
715 default:
716 OUT1("\nNON-PADS or PAD w/o side not rotated ");
717 break;
718 }
719 }
720 } /* end orient_pads */
721 /* ***************************************************************** */
722