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: placepin.c
42 DESCRIPTION:find initial placement of softpins
43 CONTENTS: placepin()
44 DATE: Mar 16, 1989 - added header and rewrote data structure.
45 REVISIONS: Apr 23, 1990 - working version of softpin placement for
46 instance changes.
47 Apr 28, 1990 - added control over overflow output.
48 May 2, 1990 - fixed problem with softcells with no
49 pins and fixed error in find_hardpin_side.
50 May 15, 1990 - fixed problems with standard cells.
51 Oct 14, 1990 - fixed problem with pins moving off cell.
52 Sun Jan 20 21:45:41 PST 1991 - ported to AIX.
53 Fri Jan 25 18:14:17 PST 1991 - added routines for wire
54 estimation.
55 Wed Jan 30 14:17:19 EST 1991 - updated for new trans
56 library routines.
57 Sat Feb 2 00:00:22 EST 1991 - renamed find_rtile_side to
58 file_tile_side a general routine.
59 Mon Feb 4 02:52:04 EST 1991 - added new placepin algorithm
60 which correctly handles pin groups and side space
61 restrictions.
62 Mon Feb 4 15:08:16 EST 1991 - each level of the recursion
63 in install_pin_groups needs a workspace.
64 Tue Mar 12 17:05:03 CST 1991 - fixed initialization problem
65 with permutation.
66 Sat Apr 27 01:11:41 EDT 1991 - now avoid crash during
67 stdcell designs with no pads.
68 Tue May 21 17:06:38 CDT 1991 - fixed argument problem,
69 FLOAT vs. DOUBLE.
70 Wed Jun 5 15:43:33 CDT 1991 - changed REL_POS to REL_POST
71 for accuracy.
72 ----------------------------------------------------------------- */
73
74 #include <custom.h>
75 #include <yalecad/debug.h>
76 #include <initialize.h>
77 #include <yalecad/relpos.h>
78
79 #undef NONE
80 #define NONE 0
81 #define LEAF 1
82 #define SUBROOT 2
83 #define ROOT 3
84
85 #ifdef INFINITY
86 #undef INFINITY
87 #endif
88 #define INFINITY INT_MAX >> 4
89 #define DIV_2 >> 1
90
91 #define UP 1
92 #define DOWN 2
93 #define LEFT 3
94 #define RIGHT 4
95
96 #define USESIDERESTRICTIONS 0
97 #define ONESIDE 1
98 #define SOMESIDES 2
99 #define ALLSIDES 3
100 #define HOWMANY 0 /* the 0th element of arrays store # elements */
101
102 #define UNCOMMITTED 0
103 #define LAYER1 1
104 #define LAYER2 2
105 #define LAYER3 3
106
107 #define VSMALL INT_MIN / 10
108 #define VLARGE INT_MAX / 10
109
110 typedef struct sidebox {
111 INT x ;
112 INT y ;
113 INT start ;
114 INT end ;
115 INT loc ;
116 INT length ; /* length of the side */
117 INT direction ; /* LEFT, RIGHT, TOP, BOTTOM */
118 } SIDEBOX, *SIDEBOXPTR ;
119
120 static SIDEBOXPTR *sideArrayS ; /* the sides of the cell */
121 static CELLBOXPTR ptrS ; /* the current cell pointer */
122 static INT aveTrackPitchS ; /* the average track pitch */
123 static INT numpinS ; /* number of pins (leaves only)for a cell */
124 static INT maxsideS = 0 ; /* the max numsides over all cells */
125 static INT bestposS ; /* the position to put pin */
126 static INT besttieS ; /* the best tie breaker */
127 static INT *greedy_posS ; /* array of pin positions for greedy method */
128 static PINBOXPTR *placearrayS;/* the leaves of a cell */
129 static BOOL tell_overflowS = FALSE ; /* turn on overflow message */
130 static BOOL softequivS ; /* true if soft equivs are present */
131 BOOL contiguous_pinsG = TRUE ;
132
133 /* ****** static FUNCTION definitions ******** */
134 static void find_optimal_locations( P1(BOOL newVertFlag ));
135 static INT find_cost_for_a_side( P5( PINBOXPTR pin, INT side, DOUBLE lb, DOUBLE ub, BOOL spacing_restricted )) ;
136 static void determine_bbox( P2( INT net, INT cell )) ;
137 static void place_pin( P4( PINBOXPTR pin, INT pos, INT tiebreak, INT side ) ) ;
138 static void place_children( P5( PINBOXPTR pin, INT side, DOUBLE lb, DOUBLE ub,
139 BOOL spacing_restricted ) ) ;
140 static void set_hardpin_pos( P2( PINBOXPTR pin, BOOL newVertFlag ) );
141 static void sort_softpins() ;
142 static INT compare_pins( P2( PINBOXPTR *pinptr1, PINBOXPTR *pinptr2 ) ) ;
143 static INT sort_by_pos( P2( PINBOXPTR *pinptr1, PINBOXPTR *pinptr2 ) ) ;
144 static void install_pin_groups( P1( PINBOXPTR pin ) ) ;
145 static void permute_pg( P1( PINBOXPTR pin ) ) ;
146 static void space_pins() ;
147 static void place_soft_equivs() ;
148 static void find_next_free_spotm( P3( SIDEBOXPTR sideptr, PINBOXPTR pin, INT *pos )) ;
149 static BOOL find_next_free_spotg(P3( SIDEBOXPTR sideptr, PINBOXPTR pin, INT *pos )) ;
150 static void init_side_array( P1( BOOL newVertFlag ) ) ;
151 static void side_to_global() ;
152 static void find_hardpin_side() ;
153
154 /* ****** global FUNCTION definitions ******** */
155 extern void init_wire_est() ;
156 extern void set_up_pinplace() ;
157 extern void set_pin_verbosity( P1(BOOL flag ) ) ;
158 extern void update_pins( P1( BOOL initialFlag ) ) ;
159 extern void print_pins( P3( char *message , PINBOXPTR *array , INT howmany ) ) ;
160 extern INT *find_pin_sides( P1( INT cell ) ) ;
161 extern INT find_tile_side( P3( INT center, INT loc, INT direction ) ) ;
162 /* ################################################################## */
163
164 /*-------------------------------------------------------------------
165 placepin() performs all the necessary step to place soft pins on
166 a soft cell. It first find the best spot for each pin using the
167 half perimeter bounding box metric. The best spot for pin groups
168 is the average of all its children. Placepin then spaces the
169 pins along the sides and returns all answers in the pin->t?pos_new
170 fields. No calculation to funccost or timing penalty is performed.
171 ____________________________________________________________________*/
placepin(cell,newVertFlag)172 void placepin( cell, newVertFlag )
173 INT cell ;
174 BOOL newVertFlag ; /* use the x_new field if true otherwise use x field */
175 {
176
177 INT i ; /* counter */
178 INT howmany ; /* number of soft pins including pg */
179 INT where ; /* where to put the pin on boundary */
180 INT side ; /* the side the pin is to be placed */
181 PINBOXPTR pin ;
182 SOFTBOXPTR spin ;
183 GLISTPTR pptr ; /* pointer to nets of a cell */
184
185 ptrS = cellarrayG[cell] ;
186
187 if( ptrS->numpins <= 0 ){
188 return ; /* no work to do */
189 }
190
191 init_side_array( newVertFlag ) ;
192 numpinS = 0 ;
193 softequivS = FALSE ;
194 howmany = (INT) ptrS->softpins[HOWMANY] ;
195
196 /** DETERMINE THE BOUNDING BOX OF NETS EXCLUDING THIS CELL **/
197 for( pptr = ptrS->nets; pptr ; pptr = pptr->next ) {
198 determine_bbox( pptr->p.net, cell ) ;
199 /* tell unet that this net has been modified. */
200 netarrayG[ pptr->p.net ]->nflag = TRUE ;
201 }
202
203 find_optimal_locations( newVertFlag ) ;
204 D( "placepins/after_find_opt",
205 print_pins( "pins after_cost\n", ptrS->softpins, howmany ) ;
206 ) ;
207
208 sort_softpins() ;
209 D( "placepins/after_sort",
210 print_pins( "pins after all sorting\n", placearrayS, numpinS );
211 ) ;
212
213 space_pins() ;
214 D( "placepins/after_spacing",
215 print_pins( "pins after spacing\n", placearrayS, numpinS );
216 ) ;
217 side_to_global() ;
218
219 } /* end placepins */
220 /* ***************************************************************** */
221
find_optimal_locations(newVertFlag)222 static void find_optimal_locations( newVertFlag )
223 BOOL newVertFlag ;
224 {
225 INT i, j ; /* pin counters */
226 INT side ; /* loop thru valid sides */
227 INT cost ; /* current cost */
228 INT bestpos ; /* best modified position for pins */
229 INT besttie ; /* best position for pins for tiebreak */
230 INT bestcost ; /* best cost for pin or pingroup */
231 INT bestside ; /* best side to place pin or pingroup */
232 INT howmany ; /* number of soft pins including pg */
233 INT num_restrict ; /* number of side restrictions for pin */
234 BOOL invalid ; /* whether side is invalid */
235 PINBOXPTR pin ;
236 SOFTBOXPTR spin ;
237
238
239 /** PLACE THE PINS ACCORDING TO THE RESTRICTIONS **/
240 howmany = (INT) ptrS->softpins[HOWMANY] ;
241 for( i = 1 ; i <= howmany; i++ ){
242
243 /**** LEAVES AND SUBROOTS NEED TO BE PLACED ON THE SAME
244 **** SIDE AS THEIR PARENT ROOT, HENCE WE PLACE THE ROOT
245 **** FIRST, AND THEN PLACE ALL ITS CHILDREN **/
246 pin = ptrS->softpins[i] ;
247 spin = pin->softinfo ;
248
249 if( pin->type == HARDPINTYPE ){
250 set_hardpin_pos( pin, newVertFlag ) ;
251 continue ;
252
253 } else if( pin->type == PINGROUPTYPE && spin->hierarchy == ROOT ){
254 /* the case of a pingroup root */
255 bestcost = INT_MAX ;
256 /* calculate number of restricted sides */
257 num_restrict = spin->restrict1[HOWMANY] ;
258 for( side = 1; side <= ptrS->numsides; side++ ) {
259 if( num_restrict != 0 ){
260 invalid = TRUE ;
261 /* make sure this side is a valid side */
262 for( j = 1; j <= num_restrict; j++ ){
263 if( spin->restrict1[j] == side ){
264 invalid = FALSE ;
265 break ;
266 }
267 }
268 if( invalid ){
269 /* this side is not valid go to next side */
270 continue ;
271 }
272 }
273 /* at this point we have a valid side */
274
275 cost = find_cost_for_a_side( pin, side,
276 spin->lowerbound, spin->upperbound, spin->fixed ) ;
277 if( cost < bestcost) {
278 bestcost = cost;
279 bestside = side ;
280 }
281 } /* loop on sides */
282 place_children( pin, bestside, spin->lowerbound,
283 spin->upperbound, spin->fixed ) ;
284
285 } else if( pin->type == SOFTPINTYPE && spin->hierarchy == NONE ) {
286 /* the case of a pin that is not in a pingroup */
287 bestcost = INT_MAX ;
288 /* calculate number of restricted sides */
289 num_restrict = spin->restrict1[HOWMANY] ;
290 for( side = 1; side <= ptrS->numsides; side++ ) {
291 if( num_restrict != 0 ){
292 invalid = TRUE ;
293 /* make sure this side is a valid side */
294 for( j = 1; j <= num_restrict; j++ ){
295 if( spin->restrict1[j] == side ){
296 invalid = FALSE ;
297 break ;
298 }
299 }
300 if( invalid ){
301 /* this side is not valid go to next side */
302 continue ;
303 }
304 }
305 /* at this point we have a valid side */
306
307 cost = find_cost_for_a_side( pin,side,
308 spin->lowerbound, spin->upperbound, spin->fixed ) ;
309 if( cost < bestcost) {
310 bestcost = cost;
311 bestside = side ;
312 bestpos = bestposS ;
313 besttie = besttieS ;
314 }
315 }
316 /* now use the best positions for the position */
317 place_pin( pin, bestpos, besttie, bestside ) ;
318
319 } /* end simple pin case */
320 } /* loop on number of pins */
321
322 } /* end find_optimal_locations */
323
324 /* ***************************************************************** */
find_cost_for_a_side(pin,side,lb,ub,spacing_restricted)325 static INT find_cost_for_a_side(pin,side,lb,ub,spacing_restricted)
326 PINBOXPTR pin;
327 INT side ;
328 DOUBLE lb, ub ;
329 BOOL spacing_restricted ;
330 {
331 INT i ; /* children counter */
332 INT pos ; /* current pos. of current core pin constrained*/
333 INT dist ; /* current distance from core pin to pin */
334 INT cost ; /* cost of the opt pin placement */
335 INT dista ; /* under restrictions dist from core pin to ideal */
336 INT dist1 ; /* under restrictions dist from core pin to ideal */
337 INT dist2 ; /* under restrictions dist from core pin to ideal */
338 INT xideal ; /* ideal place to put pin */
339 INT yideal ; /* ideal place to put pin */
340 INT pin_count ; /* number of pins found */
341 INT lowpos ; /* convert lower bound to a position */
342 INT uppos ; /* convert upper bound to a position */
343 INT bestpos ; /* best constrained pos for ideal to core for 1 net */
344 INT besttie ; /* best position for ideal to core for 1 net */
345 INT bestdist ; /* best distance for ideal to core for 1 net */
346 INT tiebreak ; /* best place to put pin unconstrained */
347 INT howmany ; /* number of soft pins including pg */
348 BOOL invalid ; /* whether side is invalid */
349 BOOL intersect ; /* whether pin intersects side */
350 INT num_restrict ;/* number of side restrictions for pin */
351 BOOL pinFound ; /* true if we find a match on current net */
352 FLOAT lowbound ; /* lower bound for pin or pin group */
353 FLOAT hibound ; /* upper bound for pin or pin group */
354 PINBOXPTR pinptr; /* current pin */
355 PINBOXPTR netterm;/* loop thru pins of a net */
356 PINBOXPTR child; /* child of the pin group */
357 SIDEBOXPTR sideptr;/* pointer to side information */
358 SOFTBOXPTR spin ; /* current soft information pointer */
359 NETBOXPTR netptr ;/* current net */
360
361
362 /**** FOR NORMAL PINS AND LEAVES, JUST CALCULATE THE COST */
363 /*** AND POSITION. THE LEAF CASE IS THE RETURN CONDITION OF */
364 /*** THE RECURSION ON THE ROOT PINS ***/
365
366 spin = pin->softinfo ;
367
368 if( spin->hierarchy == LEAF || spin->hierarchy == SUBROOT ){
369 /* check to make sure we have a valid side */
370 num_restrict = spin->restrict1[HOWMANY] ;
371 if( num_restrict != 0 ){
372 invalid = TRUE ;
373 /* make sure this side is a valid side */
374 for( i = 1; i <= num_restrict; i++ ){
375 if( spin->restrict1[i] == side ){
376 invalid = FALSE ;
377 break ;
378 }
379 }
380 if( invalid ){
381 /* this side is not valid go to next side */
382 /* set cost = INFINITY */
383 return( INFINITY ) ;
384 }
385 }
386 }
387
388 /* at this point we are processing a valid side */
389 cost = 0 ;
390 bestposS = 0 ;
391 besttieS = 0 ;
392 sideptr = sideArrayS[side] ;
393
394 /* determine spacing restrictions */
395 if( spacing_restricted ){
396 /* this is the case that the spacing has been restricted */
397 if( spin->fixed ){
398 /* if the pingroup bounds have been fixed, */
399 /* force position to be within bound */
400 /* assume we are ok and then correct it */
401 lowbound = spin->lowerbound ;
402 if( lowbound < lb ){
403 lowbound = lb ;
404 }
405 if( lowbound > ub ){
406 lowbound = ub ;
407 }
408 hibound = spin->upperbound ;
409 if( hibound < lb ){
410 hibound = lb ;
411 }
412 if( hibound > ub ){
413 hibound = ub ;
414 }
415 } else {
416 /* this pin is not fixed use the given ub and lb */
417 lowbound = lb ; hibound = ub ;
418 }
419 } else {
420 if( spin->fixed ){
421 /* the pingroup bounds have not been fixed */
422 /* just take the pin's restricted position */
423 spacing_restricted = TRUE ;
424 }
425 lowbound = spin->lowerbound;
426 hibound = spin->upperbound;
427 }
428 if( spacing_restricted ){
429 lowpos = (INT) ( lowbound * (DOUBLE) sideptr->length ) ;
430 lowpos += sideptr->start ;
431 uppos = (INT) ( hibound * (DOUBLE) sideptr->length ) ;
432 uppos += sideptr->start ;
433 /* lowpos and uppos are global coordinates here */
434 /* which relate to the given sidepointer start and end points */
435 }
436 /* **** END spacing restriction calculations *** */
437
438 if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){
439
440 netptr = netarrayG[pin->net] ;
441 /* the ideal position for the pin is center of bounding box */
442 xideal = (netptr->newxmin + netptr->newxmax ) DIV_2 ;
443 yideal = (netptr->newymin + netptr->newymax ) DIV_2 ;
444 bestdist = INT_MAX ;
445
446 intersect = FALSE ;
447 if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){
448 /* horizontal side */
449 if( sideptr->start <= xideal && xideal <= sideptr->end ){
450 /* side encompasses the point */
451 dist = ABS( yideal - sideptr->loc ) ;
452 pos = xideal ;
453 intersect = TRUE ;
454 } else {
455 /* check the 2 corner point using Manhattan dist */
456 /* the constant part */
457 dist1 = dist2 = ABS( sideptr->y - yideal ) ;
458 /* the part due to the corners */
459 dist1 += ABS( sideptr->x - xideal ) ;
460 dist2 += ABS( (sideptr->x + sideptr->length) - xideal ) ;
461 if( dist1 < dist2 ){
462 dist = dist1 ;
463 pos = sideptr->x ;
464 } else {
465 dist = dist2 ;
466 pos = sideptr->x + sideptr->length ;
467 }
468 }
469 } else {
470 /* else vertical side */
471 if( sideptr->start <= yideal && yideal <= sideptr->end ){
472 /* side is encompasses the point */
473 dist = ABS( xideal - sideptr->loc ) ;
474 pos = yideal ;
475 intersect = TRUE ;
476 } else {
477 /* check the 2 corner point using Manhattan dist */
478 /* the constant part */
479 dist1 = dist2 = ABS( sideptr->x - xideal ) ;
480 /* the part due to the corners */
481 dist1 += ABS( sideptr->y - yideal ) ;
482 dist2 += ABS( (sideptr->y + sideptr->length) - yideal ) ;
483 if( dist1 < dist2 ){
484 dist = dist1 ;
485 pos = sideptr->y ;
486 } else {
487 dist = dist2 ;
488 pos = sideptr->y + sideptr->length ;
489 }
490 }
491 }
492 /* NOW CHECK SPACING RESTRICTIONS */
493 tiebreak = pos ; /* save original spot */
494 if( spacing_restricted ){
495 /* the pin placement on the side has been */
496 /* restricted in some way */
497 if( lowpos <= pos && pos <= uppos ){
498 /* everythings cool do no extra distance */
499 dista = 0 ;
500 } else if( lowpos > pos ){
501 dista = ABS( lowpos - pos ) ;
502 pos = lowpos ;
503 } else if( pos > uppos ){
504 dista = ABS( pos - uppos ) ;
505 pos = uppos ;
506 }
507 /* modify the distance by it Manhattan length */
508 /* to the pin in the orthogonal direction */
509 /* since this pin is fixed at a point */
510 dist += dista ;
511 }
512
513 if( dist < bestdist || (dist == bestdist && intersect) ){
514 bestdist = dist; /*** UPDATE THE BEST DISTANCE */
515 bestposS = pos; /*** AND BEST POSITION */
516 besttieS = tiebreak; /* save the original position */
517 }
518 return( bestdist ) ;
519 /* end single pin code */
520
521 } else {
522
523 /***
524 IF THE PIN IS A SUPERPIN, THEN SEARCH THROUGH ALL ***
525 ITS CHILDREN AND SUM THE COST AND IDEAL POSITION ***
526 RECURSIVELY. Use the spacing restrictions derived above.
527 ***/
528
529 howmany = (INT) spin->children[HOWMANY] ;
530 for( i = 1 ; i <= howmany; i++ ){
531 child = spin->children[i] ;
532 cost += find_cost_for_a_side( child, side,
533 lowbound, hibound, spacing_restricted ) ;
534 }
535 return( cost );
536
537 }
538 } /* end find_cost_for_a_side */
539 /* ***************************************************************** */
540
541 /* find the bounding box of this net without this cell */
determine_bbox(net,cell)542 static void determine_bbox( net, cell )
543 INT net ; /* calculate this net */
544 INT cell ; /* exclude this cell */
545 {
546 NETBOXPTR netptr ; /* current net */
547 PINBOXPTR pinptr ; /* current pin */
548 BOOL noPinsFound ; /* see if pins are found for this net */
549 INT x, y ; /* current pinpos for speed */
550 /* ********* calculate net half perimeter bounding box *********** */
551 netptr = netarrayG[net] ;
552 noPinsFound = TRUE ;
553 if( netptr->skip != TRUE ) {
554
555 /* find first pin that we don't have skip field set */
556 /* initialize bounding box pin count to 1 */
557 for( pinptr = netptr->pins;pinptr; pinptr = pinptr->next ) {
558 if( pinptr->skip == 1 || pinptr->cell == cell ) {
559 continue ;
560 }
561 noPinsFound = FALSE ;
562 netptr->newxmin = netptr->newxmax = pinptr->xpos ;
563 netptr->newymin = netptr->newymax = pinptr->ypos ;
564 pinptr = pinptr->next ;
565 break ;
566 }
567 /* Now find whether this pin impacts the bounding box */
568 /* Note when we get more than one pin on the bounding box */
569 for( ; pinptr ; pinptr = pinptr->next ) {
570 if( pinptr->skip == 1 || pinptr->cell == cell ) {
571 continue ;
572 }
573 x = pinptr->xpos ;
574 y = pinptr->ypos ;
575
576 if( x <= netptr->newxmin ) {
577 netptr->newxmin = x ;
578 } else if( x >= netptr->newxmax ) {
579 netptr->newxmax = x ;
580 }
581 if( y <= netptr->newymin ) {
582 netptr->newymin = y ;
583 } else if( y >= netptr->newymax ) {
584 netptr->newymax = y ;
585 }
586 }
587 }
588 if( noPinsFound ){
589 /* this means we are free to put pin anywhere to minimize */
590 /* wirelength */
591 netptr->newxmin = VSMALL ;
592 netptr->newxmax = VLARGE ;
593 netptr->newymin = VSMALL ;
594 netptr->newymax = VLARGE ;
595 }
596 } /* end half perimeter bounding box calculation */
597 /* ***************************************************************** */
598
599 /**** SET XPOS OF THE PIN TO DESIRED POSITION. *****/
place_pin(pin,pos,tiebreak,side)600 static void place_pin( pin, pos, tiebreak, side )
601 PINBOXPTR pin;
602 INT pos;
603 INT tiebreak;
604 INT side;
605 {
606
607 pin->txpos_new = pos ;
608 pin->typos_new = tiebreak ;
609 pin->softinfo->side = side ;
610
611 } /* end place_pin */
612 /* ***************************************************************** */
613
614
615 /**** RECURSIVELY SET THE SIDE OF ALL CHILDREN OF THE ROOT PIN TO THE
616 **** PADSIDE OF THE PARENT. GIVEN THAT SIDE, SET THE OPTIMAL POSITION */
place_children(pin,side,lb,ub,spacing_restricted)617 static void place_children( pin, side, lb, ub, spacing_restricted )
618 PINBOXPTR pin ;
619 INT side ;
620 DOUBLE lb, ub ;
621 BOOL spacing_restricted ;
622 {
623 INT i ; /* pin counter */
624 INT pos ; /* position of last placed pin */
625 INT min_pos ; /* min position of the last pingroup */
626 INT max_pos ; /* max position of the last pingroup */
627 INT howmany ; /* number of soft pins including pg */
628 INT child_pos ; /* position of children */
629 FLOAT lowbound ; /* lower bound for pin or pingroup */
630 FLOAT hibound ; /* upper bound for pin or pingroup */
631 PINBOXPTR child; /* go thru the children of the pingroup */
632 SOFTBOXPTR spin ; /* current soft information pointer */
633
634
635 spin = pin->softinfo ;
636
637 /* DETERMINE SPACING RESTRICTIONS */
638 if( spacing_restricted ){
639 /* this is the case that the spacing has been restricted */
640 if( spin->fixed ){
641 /* if the pingroup bounds have been fixed, */
642 /* force position to be within bound */
643 /* assume we are ok and then correct it */
644 lowbound = spin->lowerbound ;
645 if( lowbound < lb ){
646 lowbound = lb ;
647 }
648 if( lowbound > ub ){
649 lowbound = ub ;
650 }
651 hibound = spin->upperbound ;
652 if( hibound < lb ){
653 hibound = lb ;
654 }
655 if( hibound > ub ){
656 hibound = ub ;
657 }
658 } else {
659 /* this pin is not fixed use the given ub and lb */
660 lowbound = lb ; hibound = ub ;
661 }
662 } else {
663 if( spin->fixed ){
664 /* the pingroup bounds have not been fixed */
665 /* just take the pin's restricted position */
666 lowbound = spin->lowerbound;
667 hibound = spin->upperbound;
668 spacing_restricted = TRUE ;
669 }
670 }
671 /* **** END spacing restriction calculations *** */
672
673 if( spin->hierarchy == LEAF ){
674 find_cost_for_a_side( pin, side,
675 lowbound, hibound, spacing_restricted ) ;
676 /* bestposS and besttieS are set in find_cost_for_a_side */
677 place_pin( pin, bestposS, besttieS, side ) ;
678 return ;
679 } else {
680 pos = 0 ;
681 min_pos = INT_MAX ;
682 max_pos = INT_MIN ;
683
684 /* txpos_new holds the best position on this side */
685 /* typos_new holds the tie breaker */
686 howmany = (INT) spin->children[HOWMANY] ;
687 /* find the position of the children */
688 for (i = 1; i <= howmany; i++) {
689 child = spin->children[i] ;
690 place_children( child, side, lowbound, hibound, spacing_restricted ) ;
691 child_pos = child->txpos_new ;
692 pos += child_pos ;
693 min_pos = MIN( child_pos, min_pos ) ;
694 max_pos = MAX( child_pos, max_pos ) ;
695 }
696 if( howmany ){
697 pin->txpos_new = pos /= howmany ;
698 } else {
699 pin->txpos_new = pos ;
700 }
701 /* for tiebreak use the bounds of the pingroup and average them. */
702 pin->typos_new = (min_pos + max_pos ) / 2 ;
703 /* mark the side */
704 spin->side = side ;
705 return ;
706 }
707 } /* end place_children */
708 /* ***************************************************************** */
709
710 /**** SET XPOS OF THE PIN TO DESIRED POSITION. *****/
set_hardpin_pos(pin,newVertFlag)711 static void set_hardpin_pos( pin, newVertFlag )
712 PINBOXPTR pin;
713 BOOL newVertFlag ;
714 {
715
716 INT x, y ; /* pin x, y location */
717 SOFTBOXPTR sptr ; /* pointer to soft information */
718 SIDEBOXPTR sideptr ; /* pointer to side information */
719
720 if( newVertFlag ){
721 REL_POS( ptrS->orient,
722 x, y, /* result */
723 pin->txpos_new, pin->typos_new, /* cell relative */
724 ptrS->xcenter, ptrS->ycenter ) ; /* cell center */
725 } else {
726 REL_POS( ptrS->orient,
727 x, y, /* result */
728 pin->txpos, pin->typos, /* cell relative */
729 ptrS->xcenter, ptrS->ycenter ) ; /* cell center */
730 }
731 sptr = pin->softinfo ;
732 /* we already know the side */
733 sideptr = sideArrayS[sptr->side] ;
734 switch( sideptr->direction ){
735 case UP:
736 case DOWN:
737 pin->txpos_new = y ;
738 break ;
739 case LEFT:
740 case RIGHT:
741 pin->txpos_new = x ;
742 break ;
743 }
744
745 } /* end set_hardpin_pos */
746 /**********************************************************************
747 PIN SORTING ROUTINES
748 ***********************************************************************/
749
sort_softpins()750 static void sort_softpins()
751 {
752 INT i ; /* pin counter */
753 INT pos ; /* position in place array */
754 INT howmany ; /* number of soft pins including pg */
755 SOFTBOXPTR spin ; /* pointer to soft information */
756 PINBOXPTR pin ; /* current pin */
757
758 /* first perform an initial sort to order the pins by side, hierarchy, */
759 /* and position on the side. */
760 howmany = (INT) ptrS->softpins[HOWMANY] ;
761 Yquicksort( &(ptrS->softpins[1]), howmany, sizeof(PINBOXPTR),
762 compare_pins ) ;
763
764 D( "sort_softpins/1st_sort",
765 print_pins( "pins after 1st sort\n", ptrS->softpins, howmany );
766 ) ;
767
768 /* Now make sure the pins are permuted correctly */
769 for( i = 1; i <= howmany; i++ ){
770 pin = ptrS->softpins[i] ;
771 spin = pin->softinfo ;
772 ASSERTNCONT( spin, "sort_softpins","Problem with pointer" ) ;
773 if (spin->hierarchy == ROOT){
774 permute_pg(pin) ;
775 }
776 }
777
778 /* NOW INSTALL THE PIN GROUPS IN THEIR PROPER ORDER. There are 2 cases: */
779 /* CASE I - CONTIGUOUS INSURE THAT GROUPS REMAIN INTACT */
780 /* It is here that we set numpinS the number of actual pins of a cell */
781 if( contiguous_pinsG ){
782 for( i = 1; i <= howmany; i++ ){
783 pin = ptrS->softpins[i] ;
784 spin = pin->softinfo ;
785 if( spin->hierarchy == ROOT || spin->hierarchy == NONE ){
786 install_pin_groups( pin ) ;
787 }
788 }
789
790 } else {
791 /* CASE II - LEAVES ARE ALIGNED LIKE ORDINARY PINS IF THEY HAVE NO */
792 /* CONSTRAINTS SUCH AS ORDER OR PERMUTE. **/
793 /* put pins in place array then sort pins */
794 for( i = 1; i <= howmany; i++ ){
795 pin = ptrS->softpins[i] ;
796 spin = pin->softinfo ;
797 if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){
798 placearrayS[++numpinS] = pin ;
799 }
800 }
801 Yquicksort( &(placearrayS[1]),numpinS,sizeof(PINBOXPTR),sort_by_pos);
802 }
803 /* at this point numpinS is set properly */
804
805 } /* end sort_softpins */
806 /* ***************************************************************** */
807
808 /*** compare_pins() RETURNS TRUE IF ARG1 > ARG2 BY ITS OWN RULES **/
compare_pins(pinptr1,pinptr2)809 static INT compare_pins( pinptr1, pinptr2 )
810 PINBOXPTR *pinptr1, *pinptr2 ;
811 {
812 PINBOXPTR pin1, pin2;
813 SOFTBOXPTR spin1, spin2;
814
815 pin1 = *pinptr1 ;
816 pin2 = *pinptr2 ;
817 spin1 = pin1->softinfo ;
818 spin2 = pin2->softinfo ;
819
820 /* move the soft equivtypes to the end of the array */
821 /* these don't have a correct side so move to the end */
822 if( pin1->type == SOFTEQUIVTYPE ){
823 return( 1 ) ;
824 } else if( pin2->type == SOFTEQUIVTYPE ){
825 return( 0 ) ;
826 }
827
828 if( spin1->side != spin2->side) {
829 return( spin1->side - spin2->side ) ;
830 }
831 if( spin1->hierarchy != spin2->hierarchy ){
832 /*** MOVE ROOTS TO THE BEGINNING OF ARRAY MOVE */
833 /* LEAVES ARE SEPARATED, ROOTS ARE MERGED **/
834 if( spin1->hierarchy == SUBROOT ){
835 return( 1 ) ;
836 } else if( spin2->hierarchy == SUBROOT ){
837 return( 0 ) ;
838 } else if( spin1->hierarchy == LEAF ){
839 return( 1 ) ;
840 } else if( spin2->hierarchy == LEAF ){
841 return( 0 ) ;
842 }
843 }
844 /* check the position for equality */
845 if( pin1->txpos_new == pin2->txpos_new ){
846 /* hard pins always get preference */
847 if( pin1->type == HARDPINTYPE ){
848 /* move pin2 to the end */
849 return( 0 ) ;
850 } else if( pin2->type == HARDPINTYPE ){
851 /* move pin1 to the beginning */
852 return( 1 ) ;
853 } else { /* a softpin - typos_new field is tiebreaker */
854 /* use the tiebreaker field to break ties */
855 return( pin1->typos_new - pin2->typos_new ) ;
856 }
857 } else {
858 return( pin1->txpos_new - pin2->txpos_new ) ;
859 }
860
861 } /* end compare_pins */
862 /* ***************************************************************** */
863
sort_by_pos(pinptr1,pinptr2)864 static INT sort_by_pos( pinptr1, pinptr2 )
865 PINBOXPTR *pinptr1, *pinptr2 ;
866 {
867
868 PINBOXPTR pin1, pin2;
869 SOFTBOXPTR spin1, spin2;
870
871 pin1 = *pinptr1 ;
872 pin2 = *pinptr2 ;
873 spin1 = pin1->softinfo ;
874 spin2 = pin2->softinfo ;
875
876 /* move the soft equivtypes to the end of the array */
877 /* these don't have a correct side so move to the end */
878 if( pin1->type == SOFTEQUIVTYPE ){
879 return( 1 ) ;
880 } else if( pin2->type == SOFTEQUIVTYPE ){
881 return( 0 ) ;
882 }
883
884 /* always must maintain side */
885 if( spin1->side != spin2->side) {
886 return( spin1->side - spin2->side ) ;
887 }
888 if( spin1->ordered || spin1->permute ){
889 return( 0 ) ;
890 } else if( spin2->ordered || spin2->permute ){
891 return( 1 ) ;
892 } else if( pin1->txpos_new == pin2->txpos_new ){
893 /* hard pins always get preference */
894 if( pin1->type == HARDPINTYPE ){
895 /* move pin2 to the end */
896 return( 0 ) ;
897 } else if( pin2->type == HARDPINTYPE ){
898 /* move pin1 to the beginning */
899 return( 1 ) ;
900 } else { /* a softpin - typos_new field is tiebreaker */
901 /* use the tiebreaker field to break ties */
902 return( pin1->typos_new - pin2->typos_new ) ;
903 }
904 } else {
905 return( pin1->txpos_new - pin2->txpos_new ) ;
906 }
907
908 } /* end sort_by_pos */
909 /* ***************************************************************** */
910
911 /* install the pin groups and set numpinS */
install_pin_groups(pin)912 static void install_pin_groups( pin )
913 PINBOXPTR pin ;
914 {
915 INT i ; /* pin counter */
916 INT howmany ; /* number of pins in group */
917 INT initial_position ; /* position of next open place in placearray */
918 PINBOXPTR child ; /* current child */
919 PINBOXPTR *temparray; /* sort the pingroups */
920 SOFTBOXPTR spin ; /* soft information */
921
922 spin = pin->softinfo ;
923 if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){
924 placearrayS[++numpinS] = pin ;
925 } else {
926 howmany = (INT) spin->children[HOWMANY] ;
927 /* each level of the recursion needs its own temparray */
928 temparray = (PINBOXPTR *)
929 Yvector_alloc( 1,howmany,sizeof(PINBOXPTR) ) ;
930 for( i = 1 ;i <= howmany ; i++ ){
931 child = spin->children[i] ;
932 temparray[i] = child ;
933 }
934 /* now sort the subroots or leaves to obey both order constraints */
935 /* and permutation constraints. Otherwise try to sort by opt. pos.*/
936 Yquicksort( &(temparray[1]), howmany, sizeof(PINBOXPTR), sort_by_pos ) ;
937
938 /* now that we have subroots or leaves in correct order */
939 /* look at next level down */
940 for( i = 1 ;i <= howmany ; i++ ){
941 child = temparray[ i ] ;
942 install_pin_groups( child ) ;
943 }
944 /* now free temp array */
945 Yvector_free( temparray, 1, sizeof(PINBOXPTR) ) ;
946 }
947
948 } /* end install_pin_groups */
949 /* ***************************************************************** */
950
permute_pg(pin)951 static void permute_pg( pin )
952 PINBOXPTR pin ;
953 {
954 INT j, k ; /* used to reverse pins */
955 INT i ; /* pincounter */
956 INT howmany ; /* number of children in current pingroup */
957 INT max_pos ; /* max. value of the ideal positions of pin in pg */
958 INT min_pos ; /* min. value of the ideal positions of pin in pg */
959 INT child_pos ; /* position of children */
960 INT forward_cost ; /* cost to place pins in current order */
961 INT bakward_cost ; /* cost to place pins in reverse order */
962 INT proposed_fpos ; /* proposed uniformly spaced pos in forward order */
963 INT proposed_bpos ; /* proposed uniformly spaced pos in bakward order */
964 DOUBLE spacing ; /* spacing if we place pins in pg uniformly */
965 PINBOXPTR child ; /* current child */
966 PINBOXPTR tmp ; /* used to reverse permutable pins */
967 PINBOXPTR *array ; /* sort the children */
968 SOFTBOXPTR spin ; /* soft information */
969
970 spin = pin->softinfo ;
971 howmany = (INT) spin->children[HOWMANY] ;
972 if( spin->permute ){
973 /* first calculate span of pingroup */
974 ASSERTNRETURN( howmany >= 2,"permute_pg",
975 "Must have at least 2 pins in a pingroup\n");
976 child = spin->children[1] ;
977 child_pos = child->txpos_new ;
978 min_pos = child_pos ;
979 max_pos = child_pos ;
980 for( i = 2; i <= howmany ; i++ ){
981 child = spin->children[i] ;
982 child_pos = child->txpos_new ;
983 min_pos = MIN( child_pos, min_pos ) ;
984 max_pos = MAX( child_pos, max_pos ) ;
985 }
986 /* now find the cost if we evenly space the pins over that region */
987 spacing = (DOUBLE) (max_pos - min_pos) / (DOUBLE) (howmany - 1) ;
988 forward_cost = 0 ;
989 bakward_cost = 0 ;
990 for( i = 1; i <= howmany ; i++ ){
991 child = spin->children[i] ;
992 child_pos = child->txpos_new ;
993 proposed_fpos = min_pos + ROUND( (i - 1) * spacing ) ;
994 proposed_bpos = max_pos - ROUND( (i - 1) * spacing ) ;
995 forward_cost += ABS( child_pos - proposed_fpos ) ;
996 bakward_cost += ABS( child_pos - proposed_bpos ) ;
997 }
998
999 if( bakward_cost < forward_cost ) {
1000 /* we need to reverse the permutation */
1001 array = spin->children + 1;
1002 j = howmany - 1;
1003 k = 0;
1004 while( k < j ){
1005 tmp = array[j];
1006 array[j--] = array[k];
1007 array[k++] = tmp;
1008 }
1009 }
1010 }
1011 /*** NEED TO CHECK THE CHILDREN REGARDLESS OF THE PERMUTABILITY OF
1012 THE PARENT ROOT */
1013 for( i = 1; i <= howmany; i++ ){
1014 child = spin->children[i] ;
1015 if( child->softinfo->hierarchy == SUBROOT){
1016 permute_pg( child ) ;
1017 }
1018 }
1019
1020 } /* end permute_pg */
1021 /* ***************************************************************** */
1022
space_pins()1023 static void space_pins()
1024 {
1025
1026 INT i ; /* counter on pins */
1027 INT j ;
1028 INT pos ;
1029 INT howmany ;
1030 INT old_side ;
1031 INT pincount ; /* count the pins on a side */
1032 INT pos_orig ; /* used to restore original start on side */
1033 INT first_pin_on_side ; /* as the name says */
1034 BOOL invalid ;
1035 BOOL greedy ; /* TRUE if greedy spacing method is on */
1036 BOOL status ; /* TRUE if greedy method failed */
1037 PINBOXPTR pin ;
1038 SOFTBOXPTR spin ;
1039 SIDEBOXPTR sptr ;
1040 SIDEBOXPTR sideptr ;
1041
1042
1043 /* now we only have to space the leaves */
1044 /* find the first pin and last pin on the side */
1045 greedy = FALSE ;
1046 old_side = 0 ;
1047 pincount = 0 ;
1048 for( i = 1 ; i <= numpinS; ){
1049 pin = placearrayS[i] ;
1050 spin = pin->softinfo ;
1051 if( spin->side == old_side ){
1052 while( spin->side == old_side ){
1053 if( pin->type == HARDPINTYPE ){
1054 pos = pin->txpos_new ;
1055 if( greedy ){
1056 /* put hardpin in greedy array to make life simpler */
1057 greedy_posS[pincount++] = pos ;
1058 }
1059 } else if( pin->type != SOFTEQUIVTYPE ){
1060 if( greedy ){
1061 status = find_next_free_spotg( sideptr, pin, &pos ) ;
1062 /* delay storage of this position so we don't wipe */
1063 /* out txpos_new field in case we need to call */
1064 /* minimize overflow later */
1065 greedy_posS[pincount++] = pos ;
1066 if( status ){
1067 /* this means we overflow the side minimize overflow */
1068 /* redo this side */
1069 greedy = FALSE ;
1070 i = first_pin_on_side - 1 ;
1071 /* restore pos */
1072 pos = pos_orig ;
1073 }
1074 } else { /* minimize the overflow on this side */
1075 find_next_free_spotm( sideptr, pin, &pos ) ;
1076 pin->txpos_new = pos ;
1077 }
1078 }
1079 if( ++i > numpinS || pin->type == SOFTEQUIVTYPE ){
1080 /* this is where we exit the loop. Finish off last greedy first*/
1081 if( greedy ){
1082 for( j = 0; j < pincount; j++ ){
1083 pin = placearrayS[first_pin_on_side+j] ;
1084 pin->txpos_new = greedy_posS[j] ;
1085 }
1086 }
1087 if( pin->type == SOFTEQUIVTYPE ){
1088 softequivS = TRUE ;
1089 }
1090 break ;
1091 }
1092 pin = placearrayS[i] ;
1093 spin = pin->softinfo ;
1094 } /* end while loop on this side */
1095 } else if( pin->type != SOFTEQUIVTYPE ){
1096 /* see if we need to process the old side */
1097 if( greedy ){
1098 for( j = 0; j < pincount; j++ ){
1099 pin = placearrayS[first_pin_on_side+j] ;
1100 pin->txpos_new = greedy_posS[j] ;
1101 }
1102 }
1103 /* start a new side */
1104 old_side = spin->side ;
1105 sideptr = sideArrayS[old_side] ;
1106 /* always try to be greedy first */
1107 greedy = TRUE ;
1108 first_pin_on_side = i ;
1109 pincount = 0 ;
1110 /* set the initial position depending on direction on edge */
1111 switch( sideptr->direction ){
1112 case RIGHT:
1113 case UP:
1114 pos = sideptr->start ;
1115 break ;
1116 case DOWN:
1117 case LEFT:
1118 pos = sideptr->end ;
1119 break ;
1120 }
1121 pos_orig = pos ;
1122 } else {
1123 /* set side so we traverse thru SOFTEQUIV pins */
1124 old_side = spin->side ;
1125 softequivS = TRUE ;
1126 }
1127 }
1128
1129 if( softequivS ){
1130 place_soft_equivs() ;
1131 }
1132
1133 D( "space_pins",
1134 for( i = 1 ; i <= numpinS; i++ ){
1135 pin = placearrayS[i] ;
1136 spin = pin->softinfo ;
1137 fprintf( stderr,
1138 "pin:%s signal:%s side:%d oldpos:%d pos:%d pintype:%d\n",
1139 pin->pinname, netarrayG[pin->net]->nname,
1140 spin->side, pin->typos_new, pin->txpos_new, pin->type ) ;
1141
1142 }
1143 fprintf( stderr, "\n\n" ) ;
1144 ) ; /* end of debug */
1145
1146 } /* end space_pins */
1147
place_soft_equivs()1148 static void place_soft_equivs()
1149 {
1150 INT i ; /* counter on pins */
1151 INT j ;
1152 INT k ;
1153 INT pos ;
1154 INT num_restrict ; /* number of side restrictions for pin */
1155 INT orthog1, orthog2 ; /* two directions orthogonal to current one */
1156 BOOL invalid ; /* whether side is invalid */
1157 PINBOXPTR pin ;
1158 PINBOXPTR parent ;
1159 SOFTBOXPTR spin ;
1160 SOFTBOXPTR sparent ;
1161 SIDEBOXPTR sptr ;
1162 SIDEBOXPTR sideptr ;
1163
1164 /* now place the equivalent pins */
1165 for( i = 1 ; i <= numpinS; i++ ){
1166 pin = placearrayS[i] ;
1167 spin = pin->softinfo ;
1168 if( pin->type != SOFTEQUIVTYPE ){
1169 continue ;
1170 }
1171 parent = spin->parent ;
1172 sparent = parent->softinfo ;
1173 /* now find opposite side */
1174 sideptr = sideArrayS[sparent->side] ;
1175 if( sideptr->direction == UP || sideptr->direction == DOWN ){
1176 orthog1 = LEFT ;
1177 orthog2 = RIGHT ;
1178 } else if( sideptr->direction == RIGHT || sideptr->direction == LEFT ){
1179 orthog1 = UP ;
1180 orthog2 = DOWN ;
1181 }
1182 pos = parent->txpos_new ;
1183 /* find the closest side that is valid */
1184 num_restrict = spin->restrict1[HOWMANY] ;
1185 for( j = 1; j <= ptrS->numsides; j++ ){
1186 sptr = sideArrayS[j] ;
1187 if( j == sparent->side || sptr->direction == orthog1 ||
1188 sptr->direction == orthog2 ){
1189 /* avoid the parent side and orthogonal sides */
1190 continue ;
1191 }
1192 if( num_restrict >= 1 ){
1193 /* make sure this side is a valid side */
1194 invalid = TRUE ;
1195 for( k = 1; k <= num_restrict; k++ ){
1196 if( spin->restrict1[k] == j ){
1197 invalid = FALSE ;
1198 break ;
1199 }
1200 }
1201 if( invalid ){
1202 continue ;
1203 }
1204 }
1205 if( sptr->start <= pos && pos <= sptr->end ){
1206 pin->txpos_new = pos ;
1207 pin->softinfo->side = j ;
1208 pin->skip = FALSE ;
1209 } /* end for loop on number of sides */
1210 }
1211 } /* end placing equiv pins */
1212 } /* end place_softequivs */
1213
1214 /* minimize the amount of overflow on this side */
find_next_free_spotm(sideptr,pin,pos)1215 static void find_next_free_spotm( sideptr, pin, pos )
1216 SIDEBOXPTR sideptr ;
1217 PINBOXPTR pin ;
1218 INT *pos ;
1219 {
1220
1221 INT space ;
1222 SOFTBOXPTR spin ;
1223
1224 switch( ABS(pin->layer) ){
1225 case UNCOMMITTED:
1226 space = aveTrackPitchS ;
1227 break ;
1228 case LAYER1:
1229 space = track_spacingXG ;
1230 break ;
1231 case LAYER2:
1232 space = track_spacingYG ;
1233 break ;
1234 case LAYER3:
1235 space = aveTrackPitchS ;
1236 break ;
1237 } /* end switch */
1238
1239 switch( sideptr->direction ){
1240 case RIGHT:
1241 case UP:
1242 *pos += space ;
1243 if( tell_overflowS ){
1244 if( *pos >= sideptr->end ){
1245 /* overflow on this side */
1246 sprintf( YmsgG,
1247 "overflow for cell:%d pin:%s\n", pin->cell, pin->pinname ) ;
1248 M( WARNMSG, "space_pins", YmsgG ) ;
1249 }
1250 }
1251 break ;
1252 case DOWN:
1253 case LEFT:
1254 *pos -= space ;
1255 if( tell_overflowS ){
1256 if( *pos <= sideptr->start ){
1257 /* overflow on this side */
1258 sprintf( YmsgG,
1259 "overflow for cell:%d pin:%s\n", pin->cell, pin->pinname ) ;
1260 M( WARNMSG, "space_pins", YmsgG ) ;
1261 }
1262 }
1263 break ;
1264 }
1265
1266 } /* find_next_free_spotm */
1267 /* ***************************************************************** */
1268
1269 /* this is a greedy method which may overflow quite often */
1270 /* pos is the last place a pin was placed. Returns TRUE if overflow has */
1271 /* occurred while placing on this side */
find_next_free_spotg(sideptr,pin,pos)1272 static BOOL find_next_free_spotg( sideptr, pin, pos )
1273 SIDEBOXPTR sideptr ;
1274 PINBOXPTR pin ;
1275 INT *pos ;
1276 {
1277
1278 INT space ;
1279 INT newpos ;
1280 SOFTBOXPTR spin ;
1281
1282 switch( ABS(pin->layer) ){
1283 case UNCOMMITTED:
1284 space = aveTrackPitchS ;
1285 break ;
1286 case LAYER1:
1287 space = track_spacingXG ;
1288 break ;
1289 case LAYER2:
1290 space = track_spacingYG ;
1291 break ;
1292 case LAYER3:
1293 space = aveTrackPitchS ;
1294 break ;
1295 } /* end switch */
1296
1297 newpos = pin->txpos_new ;
1298
1299 switch( sideptr->direction ){
1300 case RIGHT:
1301 case UP:
1302 /* account for spacing - pos is now at the minimum valid position */
1303 *pos += space ;
1304 if( newpos > *pos ){
1305 *pos = newpos ;
1306 }
1307 if( *pos >= sideptr->end ){
1308 /* overflow on this side */
1309 return( TRUE ) ;
1310 }
1311 break ;
1312 case DOWN:
1313 case LEFT:
1314 /* account for spacing - pos is now at the maximum valid position */
1315 *pos -= space ;
1316 if( newpos < *pos ){
1317 *pos = newpos ;
1318 }
1319 if( *pos <= sideptr->start ){
1320 /* overflow on this side */
1321 return( TRUE ) ;
1322 }
1323 break ;
1324 }
1325 return( FALSE ) ;
1326
1327 } /* find_next_free_spotg */
1328 /* ***************************************************************** */
1329
side_to_global()1330 static void side_to_global()
1331 {
1332 INT i;
1333 INT side ;
1334 INT tmp ;
1335 INT rev_orient ;
1336 INT x, y ;
1337 PINBOXPTR pin ;
1338 SOFTBOXPTR spin ;
1339 SIDEBOXPTR sptr ;
1340
1341 rev_orient = Ytrans_inv_orient( ptrS->orient ) ;
1342 for( i = 1 ; i <= numpinS; i++ ){
1343 pin = placearrayS[i] ;
1344 spin = pin->softinfo ;
1345 if( !spin ){
1346 continue ;
1347 }
1348 side = spin->side ;
1349 if( side > 0 ){
1350 sptr = sideArrayS[side] ;
1351 } else {
1352 if( pin->type == SOFTEQUIVTYPE ){
1353 pin->skip = TRUE ;
1354 } else {
1355 fprintf( stderr, "side = 0\n" ) ;
1356 }
1357 }
1358 switch( sptr->direction ){
1359 case UP:
1360 tmp = pin->txpos_new ;
1361 pin->txpos_new = sptr->loc ;
1362 pin->typos_new = tmp ;
1363 break ;
1364 case DOWN:
1365 tmp = pin->txpos_new ;
1366 pin->txpos_new = sptr->loc ;
1367 pin->typos_new = tmp ;
1368 break ;
1369 case LEFT:
1370 case RIGHT:
1371 pin->txpos_new = pin->txpos_new ;
1372 pin->typos_new = sptr->loc ;
1373 break ;
1374 }
1375 x = pin->txpos_new -= ptrS->xcenter ;
1376 y = pin->typos_new -= ptrS->ycenter ;
1377
1378 /* translate back to current view */
1379 REL_POS( rev_orient,
1380 pin->txpos_new, pin->typos_new, /* result */
1381 x, y, /* cell relative */
1382 0, 0 ) ; /* cell center */
1383
1384 /* now calculate global coordinates */
1385 REL_POS( ptrS->orient,
1386 pin->newx, pin->newy, /* result */
1387 pin->txpos_new, pin->typos_new, /* cell relative */
1388 ptrS->xcenter, ptrS->ycenter ) ; /* cell center */
1389
1390 /* tell unet that this pin has changed position */
1391 pin->flag = TRUE ;
1392
1393 D( "twmc/side_to_global",
1394 fprintf( stderr,
1395 "pin:%s signal:%s side:%d txpos:%d typos:%d xpos:%d ypos:%d\n",
1396 pin->pinname, netarrayG[pin->net]->nname,
1397 spin->side, pin->txpos_new, pin->typos_new,
1398 pin->newx, pin->newy, pin->type ) ;
1399
1400 fprintf( stderr, "\n\n" ) ;
1401 ) ; /* end of debug */
1402
1403 } /* end for loop */
1404 } /* end side_to_global() */
1405
set_up_pinplace()1406 void set_up_pinplace()
1407 {
1408 INT i ; /* counter */
1409 INT j ; /* counter */
1410 INT k ; /* counter */
1411 INT numinst ; /* the number of instances for cell */
1412 INT howmany ; /* the number of sofpins for cell */
1413 INT max_soft ; /* count the number of softpins overall inst. */
1414 INT last_net ; /* last unique net */
1415 PINBOXPTR pin ; /* current pin pointer */
1416 GLISTPTR nlist, tmp ; /* used to build nets of a cell */
1417 INSTBOXPTR instptr ; /* instance information */
1418
1419
1420 if( numsoftG == 0 && numstdcellG == 0 ){
1421 return ;
1422 }
1423 /* find the maximum number of sides on a cell */
1424 for( i = 1; i <= numcellsG ; i++ ){
1425 ptrS = cellarrayG[i] ;
1426 if( ptrS->softflag ){
1427
1428 if( instptr = ptrS->instptr ){
1429 numinst = ptrS->instptr->numinstances ;
1430 for( j = 0; j < numinst ; j++ ){
1431 maxsideS = MAX( maxsideS, instptr->numsides[j] ) ;
1432 }
1433 } else {
1434 maxsideS = MAX( maxsideS, ptrS->numsides ) ;
1435 }
1436
1437 /* build data structure for nets of the cell */
1438 /* pins are sorted by net in sortpins() */
1439 /* make use of this fact to find set of unique nets */
1440 last_net = 0 ;
1441 for( pin = ptrS->pinptr ; pin; pin = pin->nextpin ){
1442 if( pin->net != last_net ){
1443 last_net = pin->net ;
1444 /* allocate space for net list */
1445 if( tmp = ptrS->nets ){
1446 nlist = ptrS->nets = (GLISTPTR)
1447 Ysafe_malloc(sizeof(GLISTBOX));
1448 nlist->next = tmp ;
1449 } else {
1450 nlist = ptrS->nets = (GLISTPTR)
1451 Ysafe_malloc(sizeof(GLISTBOX));
1452 nlist->next = NULL ;
1453 }
1454 nlist->p.net = last_net ;
1455 }
1456 }
1457 }
1458 }
1459 /* now allocate the array */
1460 sideArrayS = (SIDEBOXPTR *)
1461 Yvector_alloc( 1,maxsideS,sizeof(SIDEBOXPTR) ) ;
1462
1463 for( i = 1; i <= maxsideS ; i++ ){
1464 sideArrayS[i] = (SIDEBOXPTR) Ysafe_malloc(sizeof(SIDEBOX) ) ;
1465 }
1466
1467 /* initialize average track pitch */
1468 aveTrackPitchS = (track_spacingXG + track_spacingYG) / 2 ;
1469
1470 max_soft = 0 ;
1471 for( i = 1; i <= numcellsG ; i++ ){
1472 ptrS = cellarrayG[i] ;
1473 if( ptrS->softflag ){
1474 /* need to initialize each instance */
1475 if( instptr = ptrS->instptr ){
1476 numinst = ptrS->instptr->numinstances ;
1477 for( j = 0; j < numinst; j++ ){
1478 ptrS->numsides = instptr->numsides[j] ;
1479 ptrS->vertices = instptr->vert_inst[j] ;
1480 if( !(ptrS->softpins)){
1481 continue ;
1482 }
1483 howmany = (INT) ptrS->softpins[HOWMANY] ;
1484 max_soft = MAX( max_soft, howmany ) ;
1485 /* set each pin's correct instance */
1486 for( k = 1 ; k <= howmany; k++ ){
1487 pin = ptrS->softpins[k] ;
1488 pin->softinfo = pin->soft_inst[j] ;
1489 }
1490 /* now set the pins */
1491 init_side_array( FALSE ) ;
1492 find_hardpin_side() ;
1493 }
1494 /* now set everything as it was */
1495 j = ptrS->cur_inst ;
1496 ptrS->numsides = instptr->numsides[j] ;
1497 ptrS->vertices = instptr->vert_inst[j] ;
1498 } else if( ptrS->softpins ){
1499 howmany = (INT) ptrS->softpins[HOWMANY] ;
1500 max_soft = MAX( max_soft, howmany ) ;
1501 init_side_array( FALSE ) ;
1502 find_hardpin_side() ;
1503 }
1504 }
1505 }
1506 if( max_soft > 0 ){
1507 placearrayS = (PINBOXPTR *) Yvector_alloc( 1, max_soft,sizeof(PINBOXPTR) ) ;
1508 greedy_posS = (INT *) Yvector_alloc( 0, max_soft,sizeof(INT) ) ;
1509 }
1510
1511 } /* end set_up_pinplace */
1512
init_side_array(newVertFlag)1513 static void init_side_array( newVertFlag )
1514 BOOL newVertFlag ; /* use _new fields if true use x, y otherwise */
1515 {
1516
1517 INT i ; /* counter */
1518 INT j ; /* counter */
1519 INT *xvert ; /* the xvertices of cell */
1520 INT *yvert ; /* the yvertices of cell */
1521 VERTBOXPTR vert ; /* the cells vertices */
1522 SIDEBOXPTR this_side ; /* current side pointer */
1523 SIDEBOXPTR next_side ; /* next side pointer */
1524 BOUNBOXPTR bounptr ; /* bounding box pointer */
1525
1526
1527 vert = ptrS->vertices ;
1528 if( newVertFlag ){
1529 xvert = vert->x_new ;
1530 yvert = vert->y_new ;
1531 } else {
1532 xvert = vert->x ;
1533 yvert = vert->y ;
1534 }
1535 /* setup translation of output points */
1536 bounptr = ptrS->bounBox[0] ;
1537 /* now init the translation routines using bounding box */
1538 Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t,
1539 ptrS->orient ) ;
1540 for( i = 1; i <= ptrS->numsides; i++ ){
1541 this_side = sideArrayS[i] ;
1542 /* rel position is a macro which calculates */
1543 /* absolute pin loc - defined in relpos.h */
1544 REL_POST( ptrS->orient,
1545 this_side->x, this_side->y, /* result */
1546 xvert[i], yvert[i], /* cell relative */
1547 ptrS->xcenter, ptrS->ycenter ) ; /* cell center */
1548 }
1549
1550 /* now determine the direction and path for edge */
1551 for( i = 1, j = 1; i <= ptrS->numsides; i++ ){
1552 if( ++j > ptrS->numsides ){
1553 j = 1 ;
1554 }
1555 this_side = sideArrayS[i] ;
1556 next_side = sideArrayS[j] ;
1557 if( this_side->x == next_side->x ){
1558 if( this_side->y < next_side->y ){
1559 this_side->direction = UP ;
1560 this_side->start = this_side->y ;
1561 this_side->end = next_side->y ;
1562 } else {
1563 this_side->direction = DOWN ;
1564 this_side->start = next_side->y ;
1565 this_side->end = this_side->y ;
1566 }
1567 this_side->loc = this_side->x ;
1568 } else if( this_side->y == next_side->y ){
1569 if( this_side->x < next_side->x ){
1570 this_side->direction = RIGHT ;
1571 this_side->start = this_side->x ;
1572 this_side->end = next_side->x ;
1573 } else {
1574 this_side->direction = LEFT ;
1575 this_side->start = next_side->x ;
1576 this_side->end = this_side->x ;
1577 }
1578 this_side->loc = this_side->y ;
1579 }
1580 this_side->length = this_side->end - this_side->start ;
1581
1582 D( "twmc/sidearray",
1583 fprintf( stderr, "x:%d y:%d start:%d end:%d loc:%d len:%d D:%d\n",
1584 this_side->x, this_side->y, this_side->start, this_side->end,
1585 this_side->loc, this_side->length, this_side->direction ) ;
1586 ) ;
1587 }
1588 } /* end init_side_array() */
1589
1590 /* find the side that the hardpin is nearest. */
find_hardpin_side()1591 static void find_hardpin_side()
1592 {
1593
1594 INT i ; /* counter */
1595 INT x, y ; /* pin x,y location */
1596 INT dist ; /* find the best place for pin */
1597 INT dist1 ; /* determine dist for pin */
1598 INT howmany ; /* # of pingroup children */
1599 INT bestdist ; /* determine dist for pin */
1600 INT bestside ; /* best side for the pin */
1601 BOOL intersect ; /* true if ideal pt intersects side */
1602 PINBOXPTR pin ; /* the current pin */
1603 SOFTBOXPTR sptr ; /* soft information */
1604 SIDEBOXPTR sideptr ; /* current side */
1605
1606 for( pin = ptrS->pinptr; pin; pin = pin->nextpin ){
1607 sptr = pin->softinfo ;
1608 if( pin->type != HARDPINTYPE ){
1609 continue ;
1610 }
1611 x = pin->txpos + ptrS->xcenter ;
1612 y = pin->typos + ptrS->ycenter ;
1613 bestdist = INT_MAX ;
1614 for( i = 1; i <= ptrS->numsides; i++ ){
1615 sideptr = sideArrayS[i] ;
1616 intersect = FALSE ;
1617 if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){
1618 if( sideptr->start <= x && x <= sideptr->end ){
1619 /* side is encompasses the point */
1620 dist = ABS( y - sideptr->loc ) ;
1621 intersect = TRUE ;
1622 } else {
1623 /* check the corner point */
1624 dist = ABS( sideptr->x - x ) ;
1625 dist1 = ABS( sideptr->y - y ) ;
1626 /* find Manhattan dist */
1627 dist += dist1 ;
1628 }
1629 } else {
1630 /* else vertical side */
1631 if( sideptr->start <= y && y <= sideptr->end ){
1632 /* side is encompasses the point */
1633 dist = ABS( x - sideptr->loc ) ;
1634 intersect = TRUE ;
1635 } else {
1636 /* check the corner point */
1637 dist = ABS( sideptr->x - x ) ;
1638 dist1 = ABS( sideptr->y - y ) ;
1639 /* find Manhattan dist */
1640 dist += dist1 ;
1641 }
1642 }
1643 if( dist < bestdist || (dist == bestdist && intersect) ){
1644 bestdist = dist ;
1645 bestside = i ;
1646 }
1647 } /* end loop on number of sides */
1648 /* now that we know the best side save it */
1649 sptr->side = bestside ;
1650
1651 } /* end loop on hardpins */
1652 } /* end find_hardpin_side() */
1653
1654
update_pins(BOOL initialFlag)1655 void update_pins( BOOL initialFlag ) /* initialize pin placement */
1656 //BOOL initialFlag ;/* if TRUE set all fields;if FALSE update orig fields */
1657 {
1658 INT howmany ; /* number of cells with soft pins */
1659 INT i ; /* counter */
1660 INT orient ; /* cell orientation */
1661 INT inst ; /* current instance */
1662 CELLBOXPTR cellptr ; /* current cell */
1663 PINBOXPTR pin ; /* current pin */
1664 SOFTBOXPTR spin ; /* current soft pin information */
1665
1666 if( numsoftG > 0 || numstdcellG > 0 ){
1667 howmany = (INT) softPinArrayG[HOWMANY] ;
1668 for( i = 1; i <= howmany; i++ ){
1669 cellptr = softPinArrayG[i] ;
1670 placepin( cellptr->cellnum, FALSE ) ;
1671
1672 inst = cellptr->cur_inst ;
1673
1674 orient = cellptr->orient ;
1675 for( pin = cellptr->pinptr; pin ; pin = pin->nextpin ){
1676 if( initialFlag ){
1677 pin->txpos_orig[inst] = pin->txpos = pin->txpos_new ;
1678 pin->typos_orig[inst] = pin->typos = pin->typos_new ;
1679 } else {
1680 pin->txpos_orig[inst] = pin->txpos ;
1681 pin->typos_orig[inst] = pin->typos ;
1682 }
1683
1684 /* rel pos is a macro which calculates */
1685 /* absolute pin location */
1686 /* defined in relpos.h */
1687 REL_POS( orient,
1688 pin->xpos, pin->ypos, /* result */
1689 pin->txpos, pin->typos, /* cell relative */
1690 cellptr->xcenter, cellptr->ycenter );/* cell center */
1691 }
1692
1693 D( "initial_pinplace",
1694
1695 for( pin = cellptr->pinptr; pin ; pin = pin->nextpin ){
1696 spin = pin->softinfo ;
1697 fprintf( stderr,
1698 "pin:%10s signal:%8s side:%d tx:%d x:%d ",
1699 pin->pinname, netarrayG[pin->net]->nname,
1700 spin->side, pin->txpos, pin->xpos ) ;
1701 fprintf( stderr, "ty:%d y:%d pintype:%d\n",
1702 pin->typos, pin->ypos, pin->type ) ;
1703 } /* end for loop on pins */
1704 fprintf( stderr, "\n\n" ) ;
1705
1706 ) ; /* end of debug */
1707 } /* loop on cells with softpins */
1708 } /* end test on existence of soft cells */
1709 } /* initial pinplace */
1710
set_pin_verbosity(BOOL flag)1711 void set_pin_verbosity( BOOL flag )
1712 {
1713 tell_overflowS = flag ;
1714 } /* end set_pin_verbosity */
1715
1716 /* **************************************************************** */
1717 /* THE FUNCTIONS BELOW ARE USED FOR THE WIRE ESTIMATOR. WE TRY TO */
1718 /* SHARE CODE WITH THE PLACEPIN FUNCTIONS. ******* */
1719
find_pin_sides(cell)1720 INT *find_pin_sides( cell )
1721 INT cell ;
1722 {
1723
1724 INT i ; /* counter */
1725 INT x, y ; /* pin x,y location */
1726 INT dist ; /* find the best place for pin */
1727 INT dist1 ; /* determine dist for pin */
1728 INT howmany ; /* # of pingroup children */
1729 INT bestdist ; /* determine dist for pin */
1730 INT bestside ; /* best side for the pin */
1731 INT *pins_on_a_side ; /* number of pins on each side */
1732 BOOL intersect ; /* true if ideal pt intersects side */
1733 PINBOXPTR pin ; /* the current pin */
1734 SIDEBOXPTR sideptr ; /* current side */
1735
1736 ptrS = cellarrayG[cell] ;
1737
1738 if( ptrS->numpins <= 0 ){
1739 return( NULL ) ; /* no work to do */
1740 }
1741 /* allocate space for pin counter */
1742 pins_on_a_side = (INT *) Yvector_calloc(1,ptrS->numsides,sizeof(INT)) ;
1743
1744 /** DETERMINE THE BOUNDARY OF THE CURRENT CELL **/
1745 init_side_array( FALSE ) ;
1746 for( pin = ptrS->pinptr; pin; pin = pin->nextpin ){
1747 x = pin->xpos ;
1748 y = pin->ypos ;
1749 bestdist = INT_MAX ;
1750 for( i = 1; i <= ptrS->numsides; i++ ){
1751 sideptr = sideArrayS[i] ;
1752 intersect = FALSE ;
1753 if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){
1754 if( sideptr->start <= x && x <= sideptr->end ){
1755 /* side is encompasses the point */
1756 dist = ABS( y - sideptr->loc ) ;
1757 intersect = TRUE ;
1758 } else {
1759 /* check the corner point */
1760 dist = ABS( sideptr->x - x ) ;
1761 dist1 = ABS( sideptr->y - y ) ;
1762 /* find Manhattan dist */
1763 dist += dist1 ;
1764 }
1765 } else {
1766 /* else vertical side */
1767 if( sideptr->start <= y && y <= sideptr->end ){
1768 /* side is encompasses the point */
1769 dist = ABS( x - sideptr->loc ) ;
1770 intersect = TRUE ;
1771 } else {
1772 /* check the corner point */
1773 dist = ABS( sideptr->x - x ) ;
1774 dist1 = ABS( sideptr->y - y ) ;
1775 /* find Manhattan dist */
1776 dist += dist1 ;
1777 }
1778 }
1779 if( dist < bestdist || (dist == bestdist && intersect) ){
1780 bestdist = dist ;
1781 bestside = i ;
1782 }
1783 } /* end loop on number of sides */
1784 pins_on_a_side[bestside]++ ;
1785
1786 } /* end loop on pins */
1787 return( pins_on_a_side ) ;
1788 } /* end find_pinsides() */
1789
1790 #include <dens.h>
1791 /* given a routing tile edge find matching side */
find_tile_side(center,loc,direction)1792 INT find_tile_side( center, loc, direction )
1793 INT center, loc, direction ;
1794 {
1795 INT i ; /* traverse the sides of cell */
1796 SIDEBOXPTR this_side ; /* current side pointer */
1797
1798 for( i = 1; i <= ptrS->numsides; i++ ){
1799 this_side = sideArrayS[i] ;
1800 if( direction == TILEL || direction == TILER ){
1801 if( this_side->direction == UP ||
1802 this_side->direction == DOWN ){
1803 if( this_side->loc == loc &&
1804 this_side->start <= center &&
1805 center <= this_side->end ){
1806 return( i ) ;
1807 }
1808 }
1809 } else { /* TILET or TILEB */
1810 if( this_side->direction == LEFT ||
1811 this_side->direction == RIGHT ){
1812 if( this_side->loc == loc &&
1813 this_side->start <= center &&
1814 center <= this_side->end ){
1815 return( i ) ;
1816 }
1817 }
1818 }
1819 }
1820 return( 0 ) ;
1821 } /* end find_tile_side */
1822
init_wire_est()1823 void init_wire_est()
1824 {
1825 INT i ; /* counter */
1826 INT j ; /* counter */
1827 INT maxsides ; /* the max numsides over all cells */
1828 INT numinst ; /* the number of instances for cell */
1829 INSTBOXPTR instptr ; /* instance information */
1830
1831 maxsides = 0 ;
1832 for( i = 1; i <= numcellsG ; i++ ){
1833 ptrS = cellarrayG[i] ;
1834
1835 if( instptr = ptrS->instptr ){
1836 numinst = ptrS->instptr->numinstances ;
1837 for( j = 0; j < numinst ; j++ ){
1838 maxsides = MAX( maxsides, instptr->numsides[j] ) ;
1839 }
1840 } else {
1841 maxsides = MAX( maxsides, ptrS->numsides ) ;
1842 }
1843 }
1844 if( sideArrayS ){
1845 if( maxsides > maxsideS ){
1846 sideArrayS = (SIDEBOXPTR *)
1847 Yvector_realloc(sideArrayS,1,maxsides,sizeof(SIDEBOXPTR));
1848 for( i = maxsideS+1; i <= maxsides ; i++ ){
1849 sideArrayS[i] = (SIDEBOXPTR)Ysafe_malloc(sizeof(SIDEBOX));
1850 }
1851 }
1852 } else {
1853 sideArrayS = (SIDEBOXPTR *)
1854 Yvector_alloc(1,maxsides,sizeof(SIDEBOXPTR));
1855 for( i = 1; i <= maxsides ; i++ ){
1856 sideArrayS[i] = (SIDEBOXPTR)Ysafe_malloc(sizeof(SIDEBOX));
1857 }
1858 }
1859
1860 } /* end init_wire_est() */
1861
1862
1863 /* ***************************************************************** */
1864 #ifdef DEBUG
print_pins(message,array,howmany)1865 void print_pins( message, array, howmany )
1866 char *message ;
1867 PINBOXPTR *array ;
1868 INT howmany ;
1869 {
1870 INT i ;
1871 PINBOXPTR ptr ;
1872 SOFTBOXPTR sptr ;
1873
1874 fprintf( stderr, "\n%s\n", message ) ;
1875
1876 /* now print them out */
1877 for( i = 1 ; i <= howmany; i++ ){
1878 ptr = array[i] ;
1879 sptr = ptr->softinfo ;
1880 fprintf( stderr,
1881 "pin:%s pos:%d tie:%d type:%d side:%d order:%d fixed:%d\n",
1882 ptr->pinname, ptr->txpos_new, ptr->typos_new, sptr->hierarchy,
1883 sptr->side, sptr->ordered, sptr->fixed ) ;
1884 }
1885 fprintf( stderr, "\n" ) ;
1886
1887 /*
1888 G( process_graphics() ) ;
1889 */
1890
1891 } /* end print_pins */
1892 #endif /* DEBUG */
1893