1 /*
2 * Copyright (C) 1988-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: placepads.c
42 DESCRIPTION:This file contains the place pads routines.
43 CONTENTS:
44 placepads()
45 find_core()
46 setVirtualCore( flag )
47 BOOL flag ;
48 find_core_boundry( left, right, bottom, top )
49 INT *left, *right, *bottom, *top ;
50 get_global_pos( cell, l, b, r, t )
51 INT cell, *l, *r, *b, *t ;
52 DATE: Aug 12, 1988
53 REVISIONS: Oct 24, 1988 - added virtual core switch to control pad
54 placement.
55 Jan 17, 1988 - add find_core_boundary for channel graph
56 generation code - outgeo.c .
57 Jan 20, 1989 - fixed problem when pad has no pin connected
58 to it. Made sure softcells are using correct fields
59 and coordinates are translated.
60 Feb. 15, 1989 - added get_global_pos so that amount of
61 duplicated code is reduced.
62 Apr 30, 1989 - added bound to padcenter for non-virtual
63 core placement. Modified putChildren to place
64 padgroups with sidespace restriction.
65 Oct 20, 1989 - Now pads are output with global routing
66 density.
67 Feb 7, 1990 - Updated placepad core coordinates to
68 reflect new routing scheme.
69 Sun Jan 20 21:47:52 PST 1991 - ported to AIX.
70 Thu Feb 14 02:44:36 EST 1991 - new pad placement algorithm.
71 Fri Feb 15 15:19:38 EST 1991 - modified for VARIABLE_PADS
72 case.
73 Sun Feb 17 21:07:39 EST 1991 - renamed globals.
74 Wed Jun 5 16:39:11 CDT 1991 - added retain_side option
75 and now pad pins correctly.
76 Fri Sep 6 15:16:27 CDT 1991 - moved retain_side option
77 so it works when no pad groups exist.
78 Thu Sep 19 16:33:58 EDT 1991 - fixed problem with sidespace
79 options when only a fraction of the pins to pads have
80 connections to the core.
81 ----------------------------------------------------------------- */
82
83 #define PAD_VARS
84
85 #include <standard.h>
86 #include <pads.h>
87 #include <config.h>
88 #include <parser.h>
89 #include <yalecad/debug.h>
90
91 /* global references */
92 extern INT **pairArrayG ;
93
94 /* ***************** STATIC FUNCTION DEFINITIONS ******************* */
95 static void find_optimum_locations( P1(void) ) ;
96 static void place_pad( P2(PADBOXPTR pad,INT bestside ) ) ;
97 static void place_children( P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL sr) ) ;
98 static INT find_cost_for_a_side(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,
99 BOOL spacing_restricted ) ) ;
100 static void find_core( P1(void) ) ;
101
102 void get_global_pos(INT cell, INT *l, INT *b, INT *r, INT *t);
103
104 /* ***************** STATIC VARIABLE DEFINITIONS ******************* */
105 static BOOL virtualCoreS = FALSE ;
106 static INT sumposS ; /* sum of the modified opt. pin pos. of pad pins */
107 static INT sumtieS ; /* sum of all the opt. pin pos. of pad pins */
108 static INT pin_countS ; /* number of pins found with valid connections */
109 static BOOL retain_sideS = FALSE ; /* during global routing side is set */
110
111 /*-------------------------------------------------------------------
112 The placepads module tries to place the pads such that the distance
113 between the pads and their nearest connected pins in the is minimized.
114 It must also adhere to user-specified restrictions on side, position,
115 spacing and ordering.
116 ____________________________________________________________________*/
117
placepads()118 void placepads()
119 {
120 if( padspacingG == EXACT_PADS ){
121 return ;
122 }
123 find_core(); /* GET THE UPDATED CORE'S DIMENSION */
124
125 D( "placepads/initially",
126 print_pads( "pads initially\n", padarrayG, totalpadsG ) ;
127 ) ;
128
129 find_optimum_locations() ;
130 D( "placepads/after_find_opt",
131 print_pads( "pads after_cost\n", sortarrayG, totalpadsG ) ;
132 ) ;
133
134 sort_pads();
135 D( "placepads/after_sort",
136 print_pads( "pads after sort\n", placearrayG, numpadsG );
137 ) ;
138
139 align_pads();
140 D( "placepads/after_align",
141 print_pads( "pads after align\n", placearrayG, numpadsG ) ;
142 ) ;
143
144 orient_pads();
145 D( "placepads/after_orient",
146 print_pads( "pads after orient\n", placearrayG, numpadsG ) ;
147 ) ;
148
149 dimension_pads();
150 D( "placepads/after_dim",
151 print_pads( "pads after dimension\n", placearrayG, numpadsG ) ;
152 ) ;
153
154 } /* end placepads */
155 /* ***************************************************************** */
156
find_optimum_locations()157 static void find_optimum_locations()
158 {
159 INT i ; /* pad counter */
160 INT side ; /* loop thru valid sides */
161 INT cost ; /* current cost */
162 INT bestpos ; /* best modified position for pad */
163 INT besttie ; /* best position for pad for tiebreak */
164 INT bestcost ; /* best cost for pad or padgroup */
165 INT bestside ; /* best side to place pad or padgroup */
166 PADBOXPTR pad ; /* current pad */
167
168 /** FIND OPTIMUM PLACE FOR PADS ACCORDING TO THE RESTRICTIONS **/
169 for( i = 1; i <= totalpadsG; i++ ){
170
171 /**** LEAVES AND SUBROOTS NEED TO BE PLACED ON THE SAME
172 **** SIDE AS THEIR PARENT ROOT, HENCE WE PLACE THE ROOT
173 **** FIRST, AND THEN PLACE ALL ITS CHILDREN **/
174
175 pad = padarrayG[i] ;
176 if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){
177 /* the case of a padgroup root */
178 bestcost = INT_MAX ;
179 bestside = 1 ;
180 for (side = 1; side <= 4; side++ ) {
181 if( pad->valid_side[ALL] || pad->valid_side[side] ){
182 cost = find_cost_for_a_side( pad,side,
183 pad->lowerbound, pad->upperbound, pad->fixed ) ;
184 if( cost < bestcost) {
185 bestcost = cost;
186 bestside = side ;
187 }
188 }
189 }
190 place_children( pad, bestside, pad->lowerbound,
191 pad->upperbound, pad->fixed ) ;
192
193 } else if( pad->padtype == PADTYPE && pad->hierarchy == NONE ) {
194 /* the case of a pad that is not in a padgroup */
195 bestcost = INT_MAX ;
196 bestpos = 0 ; besttie = 0 ;
197 for (side = 1; side <= 4; side++ ) {
198 if( pad->valid_side[ALL] || pad->valid_side[side] ){
199 cost = find_cost_for_a_side( pad,side,
200 pad->lowerbound, pad->upperbound, pad->fixed ) ;
201 if( cost < bestcost) {
202 bestcost = cost;
203 bestside = side ;
204 bestpos = sumposS ;
205 besttie = sumtieS ;
206 }
207 }
208 }
209 /* now use the best positions for the position */
210 sumposS = bestpos ;
211 sumtieS = besttie ;
212 place_pad( pad, bestside ) ;
213
214 } /* end simple pad case */
215 }
216 } /* end find_optimum */
217
218 /* ***************************************************************** */
find_cost_for_a_side(pad,side,lb,ub,spacing_restricted)219 static INT find_cost_for_a_side(pad,side,lb,ub,spacing_restricted)
220 PADBOXPTR pad;
221 INT side ;
222 DOUBLE lb, ub ;
223 BOOL spacing_restricted ;
224 {
225 INT i ; /* children counter */
226 INT pos ; /* current pos. of current core pin constrained*/
227 INT dist ; /* current distance from core pin to pad */
228 INT cost ; /* sum of the opt pad pins to closest core pin */
229 INT dist2 ; /* under restrictions dist from core pin to pad */
230 INT lowpos ; /* convert lower bound to a position */
231 INT uppos ; /* convert upper bound to a position */
232 INT bestpos ; /* best constrained pos for pad to core for 1 net */
233 INT besttie ; /* best position for pad to core for 1 net */
234 INT bestdist ; /* best distance for pad to core for 1 net */
235 INT tiebreak ; /* best place to put pad pin unconstrained */
236 BOOL pinFound ; /* true if we find a match on current net */
237 PINBOXPTR pinptr; /* current pin */
238 PINBOXPTR netterm;/* loop thru pins of a net */
239 PADBOXPTR child; /* go thru the children of the padgroup */
240 CBOXPTR cptr ; /* current cell */
241 PADBOXPTR padptr; /* use to check if pad */
242
243
244 /**** FOR NORMAL PADS AND LEAVES, JUST CALCULATE THE COST */
245 /*** AND POSITION. THE LEAF CASE IS THE RETURN CONDITION OF */
246 /*** THE RECURSION ON THE ROOT PADS ***/
247
248 if( retain_sideS && side != pad->padside ){
249 /* during global routing must retain the side */
250 return( PINFINITY ) ;
251 }
252 if( pad->hierarchy == LEAF || pad->hierarchy == SUBROOT ){
253 if( !(pad->valid_side[ALL]) && !(pad->valid_side[side]) ){
254 /* this is not a valid side return a huge cost */
255 return( PINFINITY ) ;
256 }
257 }
258 /* At this point are guaranteed to have a valid side */
259 cost = 0 ;
260 sumposS = 0 ;
261 sumtieS = 0 ;
262
263 /* determine spacing restrictions */
264 calc_constraints( pad, side, &lb, &ub, &spacing_restricted,
265 &lowpos, &uppos ) ;
266
267 if( pad->hierarchy == LEAF || pad->hierarchy == NONE ){
268
269
270 /**** FOR ALL PINS BELONGING TO THE SAME NET AS PINS ON THE
271 PAD, FIND THE PIN CLOSEST TO THE SIDE IN padside. ****/
272
273 /**** ASSUME NO PIN WAS FOUND ***/
274 pin_countS = 0 ;
275
276 for ( pinptr=carrayG[pad->cellnum]->pins;pinptr;pinptr=pinptr->nextpin) {
277 bestdist = INT_MAX ;
278 /*** GO TO FIRST TERMS OF THE NET TO MAKE SURE ALL
279 TERMINALS ARE INCLUDED ***/
280 pinFound = FALSE ;
281 netterm = netarrayG[pinptr->net]->pins;
282 for( ;netterm ;netterm = netterm->next ) {
283
284 /**** CALCULATE THE DISTANCE FROM CORE.
285 **** pos IS THE POSITION OF THE PAD ON THIS SIDE
286 **** WHICH RESULTS IN THE SHORTEST DISTANCE TO THE PIN.
287 **** ONLY PINS ON CELLS ARE IN THIS CONTEST **/
288
289 cptr = carrayG[netterm->cell] ;
290 if( (padptr = cptr->padptr) && !(padptr->macroNotPad)){
291 /* skip over this pad */
292 continue ;
293 }
294 switch (side) {
295 case L:
296 pos = netterm->ypos;
297 dist = netterm->xpos - coreG[X][MINI];
298 break;
299 case T:
300 pos = netterm->xpos;
301 dist = coreG[Y][MAXI] - netterm->ypos;
302 break;
303 case R:
304 pos = netterm->ypos;
305 dist = coreG[X][MAXI] - netterm->xpos;
306 break;
307 case B:
308 pos = netterm->xpos;
309 dist = netterm->ypos - coreG[Y][MINI];
310 break;
311 default :
312 pos = INT_MAX ;
313 dist = INT_MAX ;
314 } /* end switch on side */
315
316 tiebreak = pos ; /* save original spot */
317 if( spacing_restricted ){
318 /* the pad placement on the side has been */
319 /* restricted in some way */
320 if( lowpos <= pos && pos <= uppos ){
321 /* everythings cool do no extra distance */
322 dist2 = 0 ;
323 } else if( lowpos > pos ){
324 dist2 = ABS( lowpos - pos ) ;
325 pos = lowpos ;
326 } else if( pos > uppos ){
327 dist2 = ABS( pos - uppos ) ;
328 pos = uppos ;
329 }
330 /* modify the distance by it Manhattan length */
331 /* to the pad in the orthogonal direction */
332 /* since this pad is fixed at a point */
333 /* could modify this to be more accurate since we want matching padpin*/
334 dist += dist2 ;
335 }
336 if (dist < bestdist) {
337 bestdist = dist; /*** UPDATE THE BEST DISTANCE */
338 bestpos = pos; /*** AND BEST POSITION */
339 besttie = tiebreak; /* save the original position */
340 pinFound = TRUE ; /* pin on this net was found */
341 }
342 } /* for(;netterm... end looking at this net */
343
344 if( pinFound ){
345 /*** SUM UP THE BEST POSITION OF ALL PINS */
346 sumposS += bestpos ;
347 sumtieS += besttie ;
348
349 /*** KEEP TRACK OF THE TOTAL COST FOR THIS SIDE */
350 cost += bestdist;
351 pin_countS++ ;
352 }
353 } /* end for loop on pins of the pad */
354
355 /*** IF NO PIN IS FOUND TO MATCH WITH PAD ARBITRARILY ***/
356 /*** SET best position to random number for THIS PAD ***/
357 if( pin_countS == 0 ){
358 if( spacing_restricted ){
359 /* average between constraints */
360 sumposS = (lowpos + uppos) / 2 ;
361 } else {
362 /*
363 Randomly pick a cost to break ties in the
364 case that this pad could go on any side. Small
365 value will not effect padgroups
366 */
367 cost = PICK_INT( 0, 3 ) ;
368 switch (side) {
369 case L:
370 sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ;
371 break;
372 case T:
373 sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ;
374 break;
375 case R:
376 sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ;
377 break;
378 case B:
379 sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ;
380 break;
381 default:
382 break;
383 }
384 }
385 sumtieS = sumposS ;
386 } /* end pin_countS == 0 */
387
388 return( cost ) ;
389
390 } else {
391
392 /***
393 IF THE PAD IS A SUPERPAD, THEN SEARCH THROUGH ALL ***
394 ITS CHILDREN AND SUM THE COST AND IDEAL POSITION ***
395 RECURSIVELY. Use the spacing restrictions derived above.
396 ***/
397
398
399 for( i = 1 ;i <= pad->children[HOWMANY]; i++ ){
400 child = padarrayG[pad->children[i]];
401 cost += find_cost_for_a_side( child, side,
402 lb, ub, spacing_restricted ) ;
403 }
404 return( cost );
405 }
406 } /* end find_cost_for_a_side */
407 /* ***************************************************************** */
408
409 /**** SET POSITION OF THE PAD. POS IS THE SUM OF THE OPTIMAL POSITION
410 **** FOR ALL TERMINALS OF THE PAD. WE DIVIDE BY THE NUMBER OF TERMINAL
411 **** TO GET THE AVERAGE. Place_pad must be performed immediately
412 **** after a find_cost_for_a_side since sumposS and sumtieS
413 **** are set in those routines. Otherwise set sumposS and sumtieS
414 **** to their proper values.
415 ***/
place_pad(pad,bestside)416 static void place_pad( pad, bestside )
417 PADBOXPTR pad ;
418 INT bestside ;
419 {
420
421 /* use the number of pins with valid connections */
422 /* pin_countS is set inf find_cost_for_a_side */
423 if( pin_countS == 0 ){
424 /*** SET PAD TO RANDOM POSITION DETERMINED IN find_cost_for_side*/
425 pad->position = sumposS ;
426 pad->tiebreak = sumtieS ;
427 } else {
428 pad->position = sumposS / pin_countS ;
429 pad->tiebreak = sumtieS / pin_countS ;
430 }
431 /* now bound pad center to current core boundary for normal case */
432 pad->padside = bestside ;
433 #ifdef LATER
434 switch( bestside ){
435 case L:
436 case R:
437 pad->position = MAX( pad->position, coreG[Y][MINI] ) ;
438 pad->position = MIN( pad->position, coreG[Y][MAXI] ) ;
439 break;
440 case T:
441 case B:
442 pad->position = MAX( pad->position, coreG[X][MINI] ) ;
443 pad->position = MIN( pad->position, coreG[X][MAXI] ) ;
444 } /* end bound of pad position */
445 #endif
446
447 } /* end place_pad */
448 /* ***************************************************************** */
449
450
451
452 /**** RECURSIVELY SET THE PADSIDE OF ALL CHILDREN OF THE ROOT PAD TO THE
453 **** PADSIDE OF THE PARENT. GIVEN THAT SIDE, SET THE OPTIMAL CXCENTER */
place_children(pad,side,lb,ub,spacing_restricted)454 static void place_children( pad, side, lb, ub, spacing_restricted )
455 PADBOXPTR pad ;
456 INT side ;
457 DOUBLE lb, ub ;
458 BOOL spacing_restricted ;
459 {
460 INT i ; /* pad counter */
461 INT pos ; /* position of last placed pad */
462 INT min_pos ; /* min position of the last padgroup */
463 INT max_pos ; /* max position of the last padgroup */
464 DOUBLE lowbound ; /* lower bound for pad or pad group */
465 DOUBLE hibound ; /* upper bound for pad or pad group */
466 PADBOXPTR child; /* go thru the children of the padgroup */
467
468 /* DETERMINE SPACING RESTRICTIONS */
469 lowbound = 0.0 ;
470 hibound = 1.0 ;
471 if( spacing_restricted ){
472 /* this is the case that the spacing has been restricted */
473 if( pad->fixed ){
474 /* if the padgroup bounds have been fixed, */
475 /* force position to be within bound */
476 /* assume we are ok and then correct it */
477 lowbound = pad->lowerbound ;
478 if( lowbound < lb ){
479 lowbound = lb ;
480 }
481 if( lowbound > ub ){
482 lowbound = ub ;
483 }
484 hibound = pad->upperbound ;
485 if( hibound < lb ){
486 hibound = lb ;
487 }
488 if( hibound > ub ){
489 hibound = ub ;
490 }
491 } else {
492 /* this pad is not fixed use the given ub and lb */
493 lowbound = lb ; hibound = ub ;
494 }
495 } else {
496 if( pad->fixed ){
497 /* the padgroup bounds have not been fixed */
498 /* just take the pad's restricted position */
499 lowbound = pad->lowerbound;
500 hibound = pad->upperbound;
501 spacing_restricted = TRUE ;
502 }
503 }
504 /* **** END spacing restriction calculations *** */
505
506 if( pad->hierarchy == LEAF ){
507 find_cost_for_a_side( pad, side,
508 lowbound, hibound, spacing_restricted ) ;
509 place_pad( pad, side ) ;
510 return ;
511 } else {
512 pos = 0 ;
513 min_pos = INT_MAX ;
514 max_pos = INT_MIN ;
515 for( i = 1; i <= pad->children[HOWMANY]; i++ ){
516 child = padarrayG[pad->children[i]];
517 place_children( child, side, lowbound, hibound, spacing_restricted ) ;
518 pos += child->position ;
519 min_pos = MIN( child->position, min_pos ) ;
520 max_pos = MAX( child->position, max_pos ) ;
521 }
522 if( pad->children[HOWMANY] ){
523 pad->position = pos /= pad->children[HOWMANY] ;
524 } else {
525 pad->position = pos ;
526 }
527 /* for tiebreak use the bounds of the padgroup and average them. */
528 /* set the side of the pad */
529 pad->padside = side ;
530 pad->tiebreak = (min_pos + max_pos ) / 2 ;
531 return ;
532 }
533 } /* end place_children */
534 /* ***************************************************************** */
535
536
537
538
539 /* ***************************************************************** */
540 #ifdef DEBUG
print_pads(message,array,howmany)541 void print_pads( message, array, howmany )
542 char *message ;
543 PADBOXPTR *array ;
544 INT howmany ;
545 {
546 INT i ;
547 PADBOXPTR ptr ;
548 CBOXPTR cptr ;
549
550 fprintf( stderr, "\n%s\n", message ) ;
551
552 /* now print them out */
553 for( i = 1 ; i <= howmany; i++ ){
554 ptr = array[i] ;
555 cptr = carrayG[ ptr->cellnum ] ;
556 fprintf( stderr,
557 "pad:%s x:%d y:%d type:%d side:%d pos:%d tie:%d orient:%d\n",
558 cptr->cname, cptr->cxcenter, cptr->cycenter, ptr->hierarchy,
559 ptr->padside, ptr->position, ptr->tiebreak, cptr->corient ) ;
560 }
561 fprintf( stderr, "\n" ) ;
562
563 dimension_pads() ;
564 G( process_graphics() ) ;
565
566 } /* end print_pads */
567
568 #endif /* DEBUG */
569 /* ***************************************************************** */
570
571
find_core()572 static void find_core()
573 {
574 INT minx, maxx ;
575 INT miny, maxy ;
576 INT l, r, b, t ;
577 INT i ;
578 INT num ;
579 INT cell ;
580 INT block ;
581 INT xc, yc ;
582 BBOXPTR bptr ;
583
584 /* initialize xmin, ymax, etc. */
585 minx = INT_MAX ;
586 miny = INT_MAX ;
587 maxx = INT_MIN ;
588 maxy = INT_MIN ;
589 if( virtualCoreS ){
590
591 for( block = 1 ; block <= numRowsG ; block++ ) {
592 num = pairArrayG[block][0] ;
593 if( num == 0 ) {
594 continue ;
595 }
596 cell = pairArrayG[block][ 1 ] ;
597 l = carrayG[cell]->cxcenter + carrayG[cell]->tileptr->left ;
598 cell = pairArrayG[block][ pairArrayG[block][0] ] ;
599 r = carrayG[cell]->cxcenter + carrayG[cell]->tileptr->right ;
600 minx = MIN( minx, l ) ;
601 maxx = MAX( maxx, r ) ;
602 }
603 cell = pairArrayG[1][ 1 ] ;
604 b = carrayG[cell]->cycenter + carrayG[cell]->tileptr->bottom ;
605 miny = MIN( miny, b ) ;
606 cell = pairArrayG[numRowsG][ 1 ] ;
607 t = carrayG[cell]->cycenter + carrayG[cell]->tileptr->top ;
608 maxy = MAX( maxy, t ) ;
609
610 } else {
611 for( block = 1 ; block <= numRowsG ; block++ ) {
612 bptr = barrayG[block] ;
613 xc = bptr->bxcenter ;
614 yc = bptr->bycenter ;
615 minx = MIN( minx, bptr->bleft + xc ) ;
616 maxx = MAX( maxx, bptr->bright + xc ) ;
617 miny = MIN( miny, bptr->bbottom + yc ) ;
618 maxy = MAX( maxy, bptr->btop + yc ) ;
619 }
620 }
621 /* now check macro cells if they exist */
622 for( i=numcellsG+1;i<=lastpadG;i++ ){
623 if( carrayG[i]->padptr->macroNotPad ){
624 /* only calculate position if it is a macro */
625 get_global_pos( i, &l, &b, &r, &t ) ;
626
627 minx = MIN( minx, l ) ;
628 maxx = MAX( maxx, r ) ;
629 miny = MIN( miny, b ) ;
630 maxy = MAX( maxy, t ) ;
631 }
632 }
633
634 /* now guarantee space between core and pads */
635 minx -= track_pitchG ;
636 miny -= track_pitchG ;
637 maxx += track_pitchG ;
638 maxy += track_pitchG ;
639
640 /* now save the dimensions */
641 coreG[Y][MINI] = miny ;
642 coreG[Y][MAXI] = maxy ;
643
644 coreG[X][MINI] = minx ;
645 coreG[X][MAXI] = maxx ;
646
647 perdimG[X] = maxx - minx ;
648 perdimG[Y] = maxy - miny ;
649
650 } /* end FindCore */
651
652 /* turn virtual core on and off */
setVirtualCore(flag)653 void setVirtualCore( flag )
654 BOOL flag ;
655 {
656 virtualCoreS = flag ;
657 } /* end set Virtual core */
658
659
660 /* given a cell it returns bounding box of cell in global coordinates */
get_global_pos(INT cell,INT * l,INT * b,INT * r,INT * t)661 void get_global_pos(INT cell, INT *l, INT *b, INT *r, INT *t )
662 {
663
664 CBOXPTR ptr ;
665
666 ptr = carrayG[cell] ;
667 *l = ptr->tileptr->left ;
668 *r = ptr->tileptr->right ;
669 *b = ptr->tileptr->bottom ;
670 *t = ptr->tileptr->top ;
671 YtranslateT( l, b, r, t, (INT) ptr->corient ) ;
672
673 /* now add xcenter ycenter to get global position */
674 *l += ptr->cxcenter ;
675 *r += ptr->cxcenter ;
676 *b += ptr->cycenter ;
677 *t += ptr->cycenter ;
678
679 } /* end get_global_pos */
680
placepads_retain_side(flag)681 void placepads_retain_side( flag )
682 BOOL flag;
683 {
684 retain_sideS = flag ;
685 } /* end placepads_retain_side */
686