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