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