1 /*
2  *   Copyright (C) 1989-1992 Yale University
3  *   Copyright (C) 2015 Tim Edwards <tim@opencircuitdesign.com>
4  *   Copyright (C) 2015 Staf Verhaegen <staf@stafverhaegen.be>
5  *
6  *   This work is distributed in the hope that it will be useful; you can
7  *   redistribute it and/or modify it under the terms of the
8  *   GNU General Public License as published by the Free Software Foundation;
9  *   either version 2 of the License,
10  *   or any later version, on the following conditions:
11  *
12  *   (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
13  *   ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
14  *   SALE OR
15  *   OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
16  *   PATENT OR
17  *   OTHER RIGHTS NOT VESTED IN YALE.
18  *
19  *   (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
20  *   WARRANTIES
21  *   WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
22  *   INCLUDING,
23  *   BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
24  *   PARTICULAR
25  *   PURPOSE.
26  *
27  *   (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
28  *   WHATSOEVER TO
29  *   ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
30  *   ARTICLE
31  *   (a) AND (b) above.
32  *
33  *   (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
34  *   EMPLOYEES AND
35  *   AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
36  *   INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
37  *   ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
38  *   POSSIBILITY OF THE FOREGOING.
39  *
40  */
41 
42 /* -----------------------------------------------------------------
43 FILE:	    globe.c
44 DESCRIPTION:global routing routines.
45 CONTENTS:   globe()
46 	    preFeedAssgn()
47 	    free_static_in_globe()
48 	    FeedAssgn( row )
49 		INT row ;
50 	    row_seg_intersect( ptr1 , ptr2 , segptr )
51 		PINBOXPTR ptr1 , ptr2 ;
52 		SEGBOXPTR segptr ;
53 	    copy_workerS_field( aptr, bptr )
54 		FEED_SEG_PTR aptr, bptr ;
55 	    assgn_impin( imptr , fsptr , row )
56 		IPBOXPTR imptr ;
57 		FEED_SEG_PTR fsptr ;
58 	    unequiv_pin_pre_processing()
59 	    relax_padPins_pinloc()
60 	    relax_unequiv_pinloc()
61 	    check_unequiv_connectivity()
62 DATE:	    Mar 27, 1989
63 REVISIONS:  Sat Dec 15 22:08:21 EST 1990 - modified pinloc values
64 		so that it will always be positive.
65 	    Tue Jan 15 20:24:49 PST 1991 - added Carl's speedup
66 		to adding feeds and also fixed missing Ysafe_frees.
67 	    Fri Jan 25 23:50:09 PST 1991 - now add extra memory
68 		if needed to worker and L_jog arrays.
69 	    Tue Mar 12 17:10:47 CST 1991 - fixed DN10000 warnings.
70 	    Thu Aug 22 22:29:28 CDT 1991 - Carl made changes
71 		for rigidly fixed cells.
72 	    Wed Aug 28 14:37:40 EDT 1991 - Carl updated feed assignment
73 		code.
74 	    Thu Sep 19 14:15:51 EDT 1991 - added equal width cell
75 		capability.  Fixed initialization problem with
76 		rebuilding pins.
77 	    Thu Nov  7 22:56:29 EST 1991 - added timing cost to
78 		cell swaps.
79 	    Wed Dec 18 21:09:09 EST 1991 - handle special case of
80 		large number of feeds and small number of crossings.
81 	    Tue May 12 22:23:31 EDT 1992 - fixed problem with orientation
82 		movement and added placement_improve switch.
83 ----------------------------------------------------------------- */
84 
85 #define GLOBE_VARS
86 
87 #include "standard.h"
88 #include "groute.h"
89 #include "main.h"
90 #include "parser.h"
91 #include "feeds.h"
92 #include <yalecad/assign.h>
93 #include <yalecad/debug.h>
94 #include <yalecad/message.h>
95 #include <yalecad/file.h>
96 
97 #define CARL_NEW
98 #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l))
99 
100 INT cell_rotate(INT row , INT index );
101 
102 /* global variables */
103 BOOL connectFlagG ;
104 
105 /* external references */
106 extern BOOL rigidly_fixed_cellsG ;
107 extern BOOL placement_improveG ;
108 
109 static LONG swap_cost( P1(BOOL perim_flag ) ) ;
110 
111 void free_static_in_globe();
112 void preFeedAssgn();
113 void FeedAssgn(INT row );
114 void row_seg_intersect(PINBOXPTR ptr1 , PINBOXPTR ptr2 , SEGBOXPTR segptr );
115 void copy_workerS_field(FEED_SEG_PTR aptr, FEED_SEG_PTR bptr );
116 void assgn_impin(IPBOXPTR imptr , FEED_SEG_PTR fsptr , int row );
117 void relax_padPins_pinloc();
118 void relax_unequiv_pinloc();
119 void elim_unused_feedsSC();
120 void rebuild_nextpin();
121 void rebuild_cell_paths();
122 
123 /* static variables */
124 static INT *wk_headS , max_feed_in_a_rowS ;
125 static INT *L_jogS ;
126 static FEED_SEG_PTR *workerS ;
127 static INT wkS ;
128 static LONG global_wire_lengthS ;
129 static INT swap_limitS ;
130 
globe()131 int globe()
132 {
133 
134 INT row , net , cost , last_cost , swaps , found , total_final_cost ;
135 INT total_cost , total_final_global_wire , total_global_wire ;
136 INT last_global_wire , total_reduction , index , i , j , k , check ;
137 INT iterations, initial_time, last_index ;
138 LONG initial_wire ;
139 PINBOXPTR netptr , cnetptr ;
140 int ok = 1;
141 
142 implicit_pins_usedG = 0 ;
143 decide_boundary() ;
144 link_imptr() ;
145 preFeedAssgn() ;
146 printf(" doing feed-through pins assignment\n" ) ;
147 
148 
149 for( row = 1 ; row <= numRowsG ; row++ ) {
150     FeedAssgn(row) ;
151 }
152 free_static_in_globe() ;
153 
154 printf(" building the net-tree now !\n" ) ;
155 postFeedAssgn() ;
156 
157 #define CARL_NEW
158 #ifdef CARL_NEW
159 
160 rebuild_nextpin() ;
161 elim_unused_feedsSC() ;
162 
163 /* if( rigidly_fixed_cellsG ) { */
164 if( refine_fixed_placement() == 0 ) {
165     ok = 0;
166     goto out;
167 }
168 /* } */
169 
170 fprintf(fpoG,"\nrow lengths after steiner trees:\n");
171 findunlap2() ;
172 
173 
174 if( placement_improveG ){
175     iterations = 0 ;
176     total_reduction = 0 ;
177     j = 4 * numcellsG ;
178     if( numcellsG <= 2000 ) {
179 	k = 3 ;
180     } else if( numcellsG <= 4000 ) {
181 	k = 2 ;
182     } else {
183 	k = 1 ;
184     }
185 
186 
187     rebuild_cell_paths() ;
188     initial_wire = global_wire_lengthS = swap_cost( FALSE ) ;
189     initial_time = timingcostG ;
190     sprintf(YmsgG,"initial total global wire   :\t%d\n", global_wire_lengthS);
191     M( MSG, NULL, YmsgG ) ;
192     sprintf(YmsgG,"initial total timing penalty:\t%d\n\n\n", timingcostG);
193     M( MSG, NULL, YmsgG ) ;
194 
195     M( MSG, NULL, "\nSteiner cell swap and rotation optimization\n" ) ;
196     swap_limitS = - (int)( (double) global_wire_lengthS * 0.00005 ) ;
197     sprintf(YmsgG,"swap_limit:%d\n", swap_limitS ) ;
198     M( MSG, NULL, YmsgG ) ;
199 
200     for( ; ; ) {
201 	swaps = 0 ;
202 	check = 0 ;
203 	for( i = 1 ; i <= j ; i++ ) {
204 	    row = PICK_INT( 1 , numRowsG ) ;
205 
206 	    /* added by Carl 12/7/91 */
207 	    if( pairArrayG[row][0] <= 1 ) {
208 		check++ ;
209 		continue ;
210 	    } /* added by Carl 12/7/91 */
211 
212 	    last_index = pairArrayG[row][0] ;
213 	    index = PICK_INT( 1 , last_index ) ;
214 	    if( index < last_index ){
215 		if( carrayG[pairArrayG[row][index]]->cclass < 0 ||
216 				carrayG[pairArrayG[row][index+1]]->cclass < 0 ) {
217 		    i-- ;
218 		    if( ++check > j ) {
219 			break ;
220 		    } else {
221 			continue ;
222 		    }
223 		}
224 		swaps += improve_place_sequential( row , index ) ;
225 	    } /* end if( index <... */
226 
227 	    swaps += cell_rotate( row , index ) ;
228 
229 	} /* end for( i = 1... */
230 	iterations++ ;
231 	total_reduction += swaps ;
232 	if( iterations == 1 || iterations % 10 == 0 ) {
233 	    sprintf(YmsgG,"reduction:\t%d\t\ttotal_red:%d\n", swaps ,
234 		total_reduction ) ;
235 	    M( MSG, NULL, YmsgG ) ;
236 	}
237 	if( swaps >= swap_limitS ) {
238 	    if( --k == 0 ) {
239 		break ;
240 	    }
241 	}
242     }
243 
244     sprintf(YmsgG,"iterations              :\t%d\n", iterations ) ;
245     M( MSG, NULL, YmsgG ) ;
246     sprintf(YmsgG,"final total global wire :\t%d\n", global_wire_lengthS ) ;
247     M( MSG, NULL, YmsgG ) ;
248     sprintf(YmsgG,"final total time penalty:\t%d\n", timingcostG ) ;
249     M( MSG, NULL, YmsgG ) ;
250     sprintf(YmsgG,"\nTotal global wire reduced by:\t%5.3f%%\n",
251       100.0 * (1.0 - (DOUBLE) global_wire_lengthS / (DOUBLE) initial_wire ) ) ;
252     M( MSG, NULL, YmsgG ) ;
253     if( initial_time ){
254 	sprintf(YmsgG,"Total time penalty reduced by:\t%5.3f%%\n",
255 	  100.0 * (1.0 - (DOUBLE) timingcostG / (DOUBLE) initial_time ) ) ;
256 	M( MSG, NULL, YmsgG ) ;
257     }
258 
259     M( MSG, NULL, "\nVERIFICATION\n" ) ;
260 
261     global_wire_lengthS = swap_cost( FALSE ) ;
262     sprintf(YmsgG,"final total global wire :\t%d\n", global_wire_lengthS);
263     M( MSG, NULL, YmsgG ) ;
264     sprintf(YmsgG,"final total time penalty:\t%d\n\n\n", timingcostG);
265     M( MSG, NULL, YmsgG ) ;
266 } else {
267     M( WARNMSG, "globe", "global routing placement improvement off\n" ) ;
268 }
269 
270 postFeedAssgn_carl() ;
271 
272 /* end of added stuff */
273 
274 #endif
275 
276 
277 
278 
279 relax_padPins_pinloc() ;
280 if( case_unequiv_pinG ) {
281     relax_unequiv_pinloc() ;
282 }
283 switchable_or_not() ;
284 
285 
286 printf(" set up the global routing grids\n" ) ;
287 globroute() ;
288 assgn_channel_to_seg() ;
289 connectFlagG = TRUE ;
290 printf(" removing redundant feed-through pins\n" ) ;
291 for( net = 1 ; net <= numnetsG ; net++ ) {
292     remove_overlap_segment( net ) ;
293     remove_unnecessary_feed( net , 1 ) ;
294 }
295 if( connectFlagG ) {
296     printf(" the connectivity of all the nets is verified\n" ) ;
297 } else {
298     printf(" the connectivity of some nets is lost\n" ) ;
299     printf(" please contact with authors\n" ) ;
300 }
301 if( case_unequiv_pinG ) {
302     if( check_unequiv_connectivity() ) {
303 	printf(" the usage of all unequivalent pins is legal\n" );
304     } else {
305 	printf(" illegal usage of some unequivalent pins\n" ) ;
306 	printf(" please contact with the authors\n" ) ;
307     }
308 }
309 
310 out:
311 free_chan_seg() ;
312 free_z_memory() ;
313 
314 return(ok) ;
315 }
316 
317 
globe_free_up()318 void globe_free_up()
319 {
320     netgraph_free_up();
321 }
322 
323 
preFeedAssgn()324 void preFeedAssgn()
325 {
326 
327 SEGBOXPTR segptr , nextptr ;
328 INT i , net ;
329 
330 max_feed_in_a_rowS = 3 * TotRegPinsG / numRowsG ;
331 wk_headS = (INT *)Ysafe_malloc( max_feed_in_a_rowS * sizeof(INT) ) ;
332 L_jogS = (INT *)Ysafe_malloc( max_feed_in_a_rowS * sizeof(INT) ) ;
333 workerS = (FEED_SEG_PTR *)Ysafe_malloc(
334 	    ( max_feed_in_a_rowS + 1 ) * sizeof(FEED_SEG_PTR) ) ;
335 for( i = 1 ; i <= max_feed_in_a_rowS ; i++ ) {
336     workerS[i] = ( FEED_SEG_PTR )Ysafe_malloc( sizeof(FEED_SEG) ) ;
337 }
338 for( net = 1 ; net <= numnetsG ; net++ ) {
339     segptr = netsegHeadG[net]->next ;
340     if( segptr == NULL ) {
341 	continue ;
342     }
343     for( ; segptr ; segptr = nextptr ) {
344 	nextptr = segptr->next ;
345 	if( segptr->pin1ptr->row == segptr->pin2ptr->row &&
346 					    segptr->flag ) {
347 	    segptr->prev->next = nextptr ;
348 	    if( nextptr != NULL ) {
349 		nextptr->prev = segptr->prev ;
350 	    }
351 	    Ysafe_free( segptr ) ;
352 	}
353     }
354 }
355 }
356 
357 
free_static_in_globe()358 void free_static_in_globe()
359 {
360 
361 INT i ;
362 
363 Ysafe_free( L_jogS ) ;
364 for( i = 1 ; i <= max_feed_in_a_rowS ; i++ ) {
365     Ysafe_free( workerS[i] ) ;
366 }
367 Ysafe_free( workerS ) ;
368 Ysafe_free( wk_headS ) ;
369 Ysafe_free( total_feed_in_the_rowG ) ;
370 }
371 
372 
373 #ifdef CARL_NEW
FeedAssgn(INT row)374 void FeedAssgn(INT row )
375 {
376 
377 PINBOXPTR netptr , ptr1 , ptr2 ;
378 SEGBOXPTR segptr , nextptr ;
379 IPBOXPTR imptr , iptr , ipinptr[40] , i_imptr , f_imptr ;
380 INT net , impcount , firstnode , spacing ;
381 INT i , j , k , last_i , last_j ;
382 INT min_i , min_x , x , jog_num ;
383 INT comparenptr() ;
384 
385 /* added by Carl for the wild attempt to optimally align feeds */
386 INT **cost , *assign_to_track , feed , feed_xpos , track , track_xpos ;
387 INT v_tracks , assigned_track , *assigned_to_track ;
388 INT num_parts , bound , assign_iter ;
389 INT i_bound , f_bound , num_feeds , start_feed_xpos , end_feed_xpos ;
390 INT count , i_count , f_count ;
391 INT req_remaining_fds , remaining_fds , tot_imp_fds , num_assigned ;
392 
393 
394 wkS = 0 ;
395 jog_num = 0 ;
396 for( net = 1 ; net <= numnetsG ; net++ ) {
397     for( netptr = steinerHeadG[net]->next ;
398 	netptr ; netptr = netptr->next ) {
399 	if( netptr->flag && netptr->row == row ) {
400 	    row_seg_intersect( netptr , NULL , NULL ) ;
401 	}
402     }
403     for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextptr ) {
404 	nextptr = segptr->next ;
405 	ptr1 = segptr->pin1ptr ;
406 	ptr2 = segptr->pin2ptr ;
407 	if( ptr1->row < row && ptr2->row > row ) {
408 	    if( segptr->switchvalue == swL_down ) {
409 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
410 	    } else {
411 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
412 	    }
413 	} else if( ptr1->row == row && ptr2->row == row ) {
414 	    if( segptr->switchvalue == swL_down ) {
415 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
416 	    } else if( segptr->switchvalue == swL_up ) {
417 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
418 	    } else if( ABS( segptr->pin1ptr->pinloc -
419 			segptr->pin2ptr->pinloc ) > 1 ) {
420 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
421 	    }
422 	} else if( ptr1->row == row ) {
423 	    if( segptr->switchvalue == swL_down && !segptr->flag ) {
424 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
425 		if( ptr1->pinloc >= NEITHER ) {
426 		    L_jogS[ ++jog_num ] = wkS ;
427 		}
428 	    } else if( (INT) ptr1->pinloc == BOTCELL ) {
429 		if( segptr->switchvalue == swL_down ) {
430 		    row_seg_intersect( ptr2 , ptr1 , segptr ) ;
431 		} else {
432 		    row_seg_intersect( ptr1 , ptr2 , segptr ) ;
433 		}
434 	    }
435 	} else if( ptr2->row == row ) {
436 	    if( segptr->switchvalue == swL_up && !segptr->flag ) {
437 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
438 		if( ptr2->pinloc <= NEITHER ) {
439 		    L_jogS[ ++jog_num ] = wkS ;
440 		}
441 	    } else if( ptr2->pinloc == TOPCELL ) {
442 		if( segptr->switchvalue == swL_down ) {
443 		    row_seg_intersect( ptr2 , ptr1 , segptr ) ;
444 		} else {
445 		    row_seg_intersect( ptr1 , ptr2 , segptr ) ;
446 		}
447 	    }
448 	} else if( ptr2->row < row ) {
449 	    segptr->prev->next = nextptr ;
450 	    if( nextptr != NULL ) {
451 		nextptr->prev = segptr->prev ;
452 	    }
453 	    Ysafe_free( segptr ) ;
454 	}
455     }
456 }
457 if( wkS == 0 ) {
458     return ;
459 }
460 
461 while( wkS > total_feed_in_the_rowG[row] ) {
462     segptr = workerS[ L_jogS[1] ]->segptr ;
463     min_i = 1 ;
464     min_x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ;
465     for( i = 2 ; i <= jog_num ; i++ ) {
466 	segptr = workerS[ L_jogS[i] ]->segptr ;
467 	x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ;
468 	if( x < min_x ) {
469 	    min_i = i ;
470 	    min_x = x ;
471 	}
472     }
473     if( min_i == jog_num ) {
474 	if( L_jogS[jog_num] < wkS ) {
475 	    copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ;
476 	}
477     } else {
478 	copy_workerS_field( workerS[ L_jogS[min_i] ],
479 			   workerS[ L_jogS[jog_num] ] ) ;
480 	copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ;
481     }
482     wkS-- ;
483     jog_num-- ;
484 }
485 
486 
487 
488 /* Carl's attempt at improving the feed position assignment 	*/
489 /* using, god forbid, a nonheuristic, nonhack algorithm for	*/
490 /* once (linear assignment)					*/
491 
492 
493 Yquicksort( (char *)(workerS+1), wkS, sizeof(FEED_SEG_PTR), comparenptr);
494 
495 if( impFeedsG[row]->next == NULL ) {
496     return ;
497 }
498 
499 /* find out the number of available feeds			*/
500 v_tracks = 0 ;
501 for( imptr = impFeedsG[row]->next ; imptr ; imptr = imptr->next ) {
502     v_tracks++ ;
503 }
504 
505 #ifdef CARL_NEW
506 
507 assigned_to_track = (INT *) Ysafe_calloc( (1+v_tracks) , sizeof(INT) ) ;
508 
509 num_parts = v_tracks / 400 ;
510 /* if remainder >= 100 or num_parts == 0 ) */
511 if( v_tracks - 400 * num_parts >= 100 || num_parts == 0 ) {
512     num_parts++ ;
513 }
514 
515 if( row % 5 == 0 ) {
516     fprintf(fpoG,"Divide-and-Conquer Subdivisions in LA:%d at row:%d\n",
517 						num_parts, row ) ;
518     fflush(fpoG);
519 }
520 
521 /* READER: don't expect to understand anything until the end of the  */
522 /* the "for" loop */
523 
524 
525 tot_imp_fds = 0 ;
526 imptr = impFeedsG[row]->next ;
527 for( ; ; ) {
528     tot_imp_fds++ ;
529     if( imptr->next != NULL ) {
530 	imptr = imptr->next ;
531     } else {
532 	break ;
533     }
534 }
535 
536 
537 bound = wkS / num_parts ;
538 /* special case of large number of feeds and small number of crossings */
539 if( bound < num_parts ){
540     bound = wkS ;
541     num_parts = 1 ;
542 }
543 f_count = 0 ;
544 for( assign_iter = 1 ; assign_iter <= num_parts ; assign_iter++ ) {
545 
546     req_remaining_fds = wkS - bound * num_parts ;
547     req_remaining_fds += bound * (num_parts - assign_iter + 1) ;
548 
549     i_bound = (assign_iter - 1) * bound + 1 ;
550     if( assign_iter < num_parts ) {
551 	f_bound = assign_iter * bound ;
552     } else {
553 	f_bound = wkS ;
554     }
555     num_feeds = f_bound - i_bound + 1 ;
556     /* determines bounds */
557     start_feed_xpos = workerS[i_bound]->netptr->xpos ;
558     end_feed_xpos = workerS[f_bound]->netptr->xpos ;
559 
560 
561     remaining_fds = tot_imp_fds ;
562     i_count = 0 ;
563     imptr = impFeedsG[row]->next ;
564     for( ; ; ) {
565 	i_count++ ;
566 	remaining_fds-- ;
567 	if( imptr->xpos >= start_feed_xpos && i_count > f_count ) {
568 	    break ;
569 	}
570 	if( imptr->next != NULL ) {
571 	    if( remaining_fds >= req_remaining_fds ) {
572 		imptr = imptr->next ;
573 	    } else {
574 		break ;
575 	    }
576 	} else {
577 	    break ;
578 	}
579     }
580 
581     count = 0 ; /* count is the number of unused feeds in the interval */
582 
583     if( assign_iter < num_parts ) {
584 	req_remaining_fds = wkS - bound * num_parts ;
585 	req_remaining_fds += bound * (num_parts - assign_iter) ;
586     } else {
587 	req_remaining_fds = 0 ;
588     }
589 
590     i_imptr = imptr ;
591     f_count = i_count - 1 ;
592     remaining_fds++ ;
593     for( ; ; ) {
594 	f_imptr = imptr ;
595 	f_count++ ;
596 	count++ ;
597 	remaining_fds-- ;
598 	if( imptr->xpos >= end_feed_xpos && count >= num_feeds ) {
599 	    break ;
600 	}
601 	if( imptr->next != NULL ) {
602 	    if( remaining_fds - 1 >= req_remaining_fds ) {
603 		imptr = imptr->next ;
604 	    } else {
605 		break ;
606 	    }
607 	} else {
608 	    break ;
609 	}
610     }
611     if( count < num_feeds ) {
612 	fprintf(fpoG,"GR fails at line 501\n");
613 	fflush(fpoG);
614     }
615 
616 
617     cost = Yassign_init( count , count ) ;
618 
619     for( feed = i_bound ; feed <= f_bound ; feed++ ) {
620 	feed_xpos = workerS[feed]->netptr->xpos ;
621 	track = 0 ;
622 	imptr = i_imptr ;
623 	for( i = i_count ; i <= f_count ; i++ ) {
624 	    track++ ;
625 	    track_xpos = imptr->xpos ;
626 	    cost[feed-i_bound+1][track] = ABS( feed_xpos - track_xpos ) ;
627 	    imptr = imptr->next ;
628 	}
629     }
630     for( feed = num_feeds + 1 ; feed <= count ; feed++ ) {
631 	track = 0 ;
632 	for( i = i_count ; i <= f_count ; i++ ) {
633 	    track++ ;
634 	    cost[feed][track] = 1000000 ;
635 	}
636     }
637 
638     assign_to_track = Yassign( cost , count , count ) ;
639 
640     num_assigned = 0 ;
641     for( feed = i_bound ; feed <= f_bound ; feed++ ) {
642 	assigned_track = assign_to_track[feed-i_bound+1] ;
643 	track = 0 ;
644 	imptr = i_imptr ;
645 	for( i = i_count ; i <= f_count ; i++ ) {
646 	    if( ++track == assigned_track ) {
647 		break ;
648 	    }
649 	    imptr = imptr->next ;
650 	}
651 	if( assigned_to_track[i] != 0 ) {
652 	    printf("total screw up\n");
653 	    fflush(stdout);
654 	} else {
655 	    assigned_to_track[i] = feed ;
656 	}
657 
658 	assgn_impin( imptr , workerS[feed] , row ) ;
659 	num_assigned++ ;
660     }
661     /*
662     fprintf(fpoG,"row:%d\tnum_feeds:%d\tnum_assigned:%d\t\tcount:%d\n",
663 				row, num_feeds, num_assigned , count ) ;
664     printf("row:%d\tnum_feeds:%d\tnum_assigned:%d\t\tcount:%d\n",
665 				row, num_feeds, num_assigned , count ) ;
666     fflush(fpoG);
667     fflush(stdout);
668     */
669     Yassign_free( cost , count , count ) ;
670 
671     /* end of this fly-by-night attempt	*/
672 }
673 
674 Ysafe_free( assigned_to_track ) ;
675 
676 
677 
678 #else
679 cost = Yassign_init( v_tracks , v_tracks ) ;
680 
681 for( feed = 1 ; feed <= wkS ; feed++ ) {
682     feed_xpos = workerS[feed]->netptr->xpos ;
683     track = 0 ;
684     for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) {
685 	track++ ;
686 	track_xpos = imptr->xpos ;
687 	cost[feed][track] = ABS( feed_xpos - track_xpos ) ;
688     }
689 }
690 for( ; feed <= v_tracks ; feed++ ) {
691     track = 0 ;
692     for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) {
693 	track++ ;
694 	cost[feed][track] = 1000000 ;
695     }
696 }
697 
698 assign_to_track = Yassign( cost , v_tracks , v_tracks ) ;
699 
700 
701 for( feed = 1 ; feed <= wkS ; feed++ ) {
702     assigned_track = assign_to_track[feed] ;
703     track = 0 ;
704     for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) {
705 	if( ++track == assigned_track ) {
706 	    break ;
707 	}
708     }
709     assgn_impin( imptr , workerS[feed] , row ) ;
710 }
711 
712 
713 Yassign_free( cost , v_tracks , v_tracks ) ;
714 
715 Ysafe_free( assigned_to_track ) ;
716 
717 /* end of this fly-by-night attempt				*/
718 #endif
719 
720 return ;
721 }
722 #else
723 
FeedAssgn(INT row)724 void FeedAssgn(INT row )
725 {
726 
727 PINBOXPTR netptr , ptr1 , ptr2 ;
728 SEGBOXPTR segptr , nextptr ;
729 IPBOXPTR imptr , iptr , ipinptr[40] ;
730 FEED_DATA *feedptr ;
731 INT net , impcount , firstnode , spacing ;
732 INT i , j , k , last_i , last_j ;
733 INT min_i , min_x , x , jog_num ;
734 INT comparenptr() ;
735 
736 wkS = 0 ;
737 jog_num = 0 ;
738 feedptr = feedpptr[row] ;
739 for( net = 1 ; net <= numnetsG ; net++ ) {
740     for( netptr = steinerHead[net]->next ;
741 	netptr ; netptr = netptr->next ) {
742 	if( netptr->flag && netptr->row == row ) {
743 	    row_seg_intersect( netptr , NULL , NULL ) ;
744 	}
745     }
746     for( segptr = netsegHead[net]->next ; segptr ; segptr = nextptr ) {
747 	nextptr = segptr->next ;
748 	ptr1 = segptr->pin1ptr ;
749 	ptr2 = segptr->pin2ptr ;
750 	if( ptr1->row < row && ptr2->row > row ) {
751 	    if( segptr->switchvalue == swL_down ) {
752 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
753 	    } else {
754 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
755 	    }
756 	} else if( ptr1->row == row && ptr2->row == row ) {
757 	    if( segptr->switchvalue == swL_down ) {
758 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
759 	    } else if( segptr->switchvalue == swL_up ) {
760 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
761 	    } else if( ABS( segptr->pin1ptr->pinloc -
762 			segptr->pin2ptr->pinloc ) > 1 ) {
763 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
764 	    }
765 	} else if( ptr1->row == row ) {
766 	    if( segptr->switchvalue == swL_down && !segptr->flag ) {
767 		row_seg_intersect( ptr2 , ptr1 , segptr ) ;
768 		if( ptr1->pinloc >= NEITHER ) {
769 		    L_jogS[ ++jog_num ] = wkS ;
770 		}
771 	    } else if( (INT) ptr1->pinloc == BOTCELL ) {
772 		if( segptr->switchvalue == swL_down ) {
773 		    row_seg_intersect( ptr2 , ptr1 , segptr ) ;
774 		} else {
775 		    row_seg_intersect( ptr1 , ptr2 , segptr ) ;
776 		}
777 	    }
778 	} else if( ptr2->row == row ) {
779 	    if( segptr->switchvalue == swL_up && !segptr->flag ) {
780 		row_seg_intersect( ptr1 , ptr2 , segptr ) ;
781 		if( ptr2->pinloc <= NEITHER ) {
782 		    L_jogS[ ++jog_num ] = wkS ;
783 		}
784 	    } else if( ptr2->pinloc == TOPCELL ) {
785 		if( segptr->switchvalue == swL_down ) {
786 		    row_seg_intersect( ptr2 , ptr1 , segptr ) ;
787 		} else {
788 		    row_seg_intersect( ptr1 , ptr2 , segptr ) ;
789 		}
790 	    }
791 	} else if( ptr2->row < row ) {
792 	    segptr->prev->next = nextptr ;
793 	    if( nextptr != NULL ) {
794 		nextptr->prev = segptr->prev ;
795 	    }
796 	    Ysafe_free( segptr ) ;
797 	}
798     }
799 }
800 if( wkS == 0 ) {
801     return ;
802 }
803 
804 while( wkS > total_feed_in_the_rowG[row] ) {
805     segptr = workerS[ L_jogS[1] ]->segptr ;
806     min_i = 1 ;
807     min_x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ;
808     for( i = 2 ; i <= jog_num ; i++ ) {
809 	segptr = workerS[ L_jogS[i] ]->segptr ;
810 	x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ;
811 	if( x < min_x ) {
812 	    min_i = i ;
813 	    min_x = x ;
814 	}
815     }
816     if( min_i == jog_num ) {
817 	if( L_jogS[jog_num] < wkS ) {
818 	    copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ;
819 	}
820     } else {
821 	copy_workerS_field( workerS[ L_jogS[min_i] ],
822 			   workerS[ L_jogS[jog_num] ] ) ;
823 	copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ;
824     }
825     wkS-- ;
826     jog_num-- ;
827 }
828 
829 
830 imptr = impFeeds[row]->next ;
831 
832 Yquicksort( (char *)(workerS+1) , wkS , sizeof(FEED_SEG_PTR),comparenptr );
833 firstnode = set_node( workerS[1]->netptr->xpos ) ;
834 i = 1 ;
835 for( i = 1 ; i <= chan_node_no ; i++ ) {
836     feedptr[i]->needed = 0 ;
837 }
838 for( i = 1 ; i <= wkS ; i++ ) {
839     j = set_node( workerS[i]->netptr->xpos ) ;
840     if( feedptr[j]->needed == 0 ) {
841 	wk_headS[j] = i ;
842     }
843     feedptr[j]->needed++ ;
844 }
845 
846 /* assign the feedthru pin for the segment from count down to i */
847 
848 for( k = firstnode ; k <= chan_node_no ; k++ ) {
849     if( feedptr[k]->needed > feedptr[k]->actual ) {
850 	local_Assgn( row , k ) ;
851     }
852 }
853 
854 for( k = 1 ; k <= chan_node_no ; k++ ) {
855     if( feedptr[k]->actual == 0 || feedptr[k]->needed == 0 ) {
856 	continue ;
857     } else if( feedptr[k]->needed == feedptr[k]->actual ) {
858 	for( imptr = feedptr[k]->firstimp ;
859 	  tearray[ imptr->terminal ] ; imptr = imptr->next );
860 	last_i = wk_headS[k] + feedptr[k]->needed - 1 ;
861 	for( i = wk_headS[k] ; i <= last_i ; i++ ) {
862 	    assgn_impin( imptr , workerS[i] , row ) ;
863 	    imptr = imptr->next ;
864 	}
865     } else {
866 	impcount = 0 ;
867 	for( imptr = feedptr[k]->firstimp ;
868 	  tearray[ imptr->terminal ] ; imptr = imptr->next );
869 	for( ; tearray[ imptr->terminal ] == NULL ;
870 				imptr = imptr->next ) {
871 	    ipinptr[++impcount] = imptr ;
872 	    if( impcount >= feedptr[k]->actual ) {
873 		break ;
874 	    }
875 	}
876 	last_j = wk_headS[k] + feedptr[k]->needed - 1 ;
877 	for( j = wk_headS[k] ; j <= last_j ; j++ ) {
878 	    spacing  = INT_MAX ;
879 	    for( i = 1 ; i <= impcount ; i++ ) {
880 		if( tearray[ ipinptr[i]->terminal ] ) {
881 		    continue ;
882 		}
883 		if( ABS( ipinptr[i]->xpos - workerS[j]->netptr->xpos )
884 							< spacing ) {
885 		    iptr = ipinptr[i] ;
886 		    spacing =
887 			ABS( iptr->xpos - workerS[j]->netptr->xpos ) ;
888 		}
889 	    }
890 	    assgn_impin( iptr , workerS[j] , row ) ;
891 	}
892     }
893     feedptr[k]->actual -= feedptr[k]->needed ;
894     feedptr[k]->needed = 0 ;
895 }
896 }
897 #endif
898 
899 
row_seg_intersect(PINBOXPTR ptr1,PINBOXPTR ptr2,SEGBOXPTR segptr)900 void row_seg_intersect(PINBOXPTR ptr1 , PINBOXPTR ptr2 , SEGBOXPTR segptr )
901 {
902 
903 INT i ;
904 
905 if( ++wkS > max_feed_in_a_rowS ) {
906     max_feed_in_a_rowS = max_feed_in_a_rowS + 100 ;
907 
908     wk_headS = (INT *) Ysafe_realloc( wk_headS ,
909 	max_feed_in_a_rowS * sizeof(INT) ) ;
910     L_jogS = (INT *) Ysafe_realloc( L_jogS ,
911 	max_feed_in_a_rowS * sizeof(INT) ) ;
912     workerS = (FEED_SEG_PTR *)Ysafe_realloc( workerS ,
913 		( max_feed_in_a_rowS + 1 ) * sizeof(FEED_SEG_PTR) ) ;
914     for( i = wkS ; i <= max_feed_in_a_rowS ; i++ ) {
915 	workerS[i] = ( FEED_SEG_PTR )Ysafe_malloc( sizeof(FEED_SEG) ) ;
916     }
917 }
918 
919 workerS[ wkS ]->netptr = ptr1 ;
920 workerS[ wkS ]->refer  = ptr2 ;
921 workerS[ wkS ]->segptr = segptr ;
922 }
923 
924 
copy_workerS_field(FEED_SEG_PTR aptr,FEED_SEG_PTR bptr)925 void copy_workerS_field(FEED_SEG_PTR aptr, FEED_SEG_PTR bptr )
926 {
927 aptr->netptr = bptr->netptr ;
928 aptr->refer  = bptr->refer ;
929 aptr->segptr = bptr->segptr ;
930 }
931 
932 
933 #ifdef CARL_NEW
assgn_impin(IPBOXPTR imptr,FEED_SEG_PTR fsptr,int row)934 void assgn_impin(IPBOXPTR imptr , FEED_SEG_PTR fsptr , int row )
935 {
936 
937 INT net ;
938 PINBOXPTR netptr , ptr1 , ptr2 ;
939 SEGBOXPTR segptr ;
940 
941 ++implicit_pins_usedG ;
942 if( fsptr->segptr ) {
943     netptr = ( PINBOXPTR )Ysafe_calloc( 1, sizeof( PINBOX ) ) ;
944     netptr->adjptr = (ADJASEGPTR)Ysafe_calloc(
945 			    1, sizeof(ADJASEG) ) ;
946     netptr->net  = net = fsptr->segptr->pin1ptr->net ;
947     netptr->row  = row ;
948 
949     netptr->next = netarrayG[net]->pins ;
950     netarrayG[net]->pins = netptr ;
951 
952     segptr = fsptr->segptr ;
953     netptr->xpos = imptr->xpos ;
954     /* FIXME: the following line leaks memory but just freeing it gives freed memory access */
955     segptr->pin1ptr = netptr ;
956     ptr1 = segptr->pin1ptr ;
957     ptr2 = segptr->pin2ptr ;
958 
959 #define TWF
960 #ifdef TWF
961     if( ptr2->row == ptr1->row ) {
962 	segptr->switchvalue == nswLINE ;
963 	segptr->flag = TRUE ;
964     } else if( add_Lcorner_feedG &&
965 	ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sepG ) {
966 	segptr->flag = FALSE ;
967     } else {
968 	segptr->flag = TRUE ;
969     }
970 #else
971     if( ptr2->row == ptr1->row ) {
972 	segptr->switchvalue == nswLINE ;
973 	segptr->flag = TRUE ;
974 	/*  else if( add_Lcorner_feed &&			 */
975 	/*  ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sep ) */
976     } else {
977 	segptr->flag = FALSE ;
978 	/* else  		 */
979 	/* segptr->flag = TRUE ; */
980     }
981 #endif
982 
983 } else { /* a steiner point */
984     netptr = fsptr->netptr ;
985     netptr->xpos = imptr->xpos ;
986 }
987 netptr->ypos = barrayG[row]->bycenter ;
988 netptr->cell = imptr->cell ;
989 netptr->pinloc = NEITHER   ;
990 netptr->terminal = imptr->terminal ;
991 netptr->pinname  = imptr->pinname  ;
992 tearrayG[ netptr->terminal ] = netptr ;
993 netptr->eqptr = ( EQ_NBOXPTR )Ysafe_calloc( 1, sizeof(EQ_NBOX) ) ;
994 netptr->eqptr->typos = carrayG[ netptr->cell ]->tileptr->bottom ;
995 netptr->eqptr->pinname = imptr->eqpinname ;
996 /* now add timing to feed thru */
997 if( strncmp( carrayG[netptr->cell]->cname, "twfeed", 6 ) == STRINGEQ ){
998     carrayG[netptr->cell]->paths = netarrayG[netptr->net]->paths ;
999 }
1000 }
1001 #else
assgn_impin(IPBOXPTR imptr,FEED_SEG_PTR fsptr,int row)1002 void assgn_impin(IPBOXPTR imptr , FEED_SEG_PTR fsptr , int row )
1003 {
1004 
1005 INT net ;
1006 PINBOXPTR netptr , ptr1 , ptr2 ;
1007 SEGBOXPTR segptr ;
1008 
1009 ++implicit_pins_used ;
1010 if( fsptr->segptr ) {
1011     netptr = ( PINBOXPTR )Ysafe_malloc( sizeof( PINBOX ) ) ;
1012     netptr->adjptr = (ADJASEGPTR)Ysafe_calloc(
1013 			    1, sizeof(ADJASEG) ) ;
1014     netptr->net  = net = fsptr->segptr->pin1ptr->net ;
1015     netptr->row  = row ;
1016     netptr->next = netarrayG[net]->pins ;
1017     netarrayG[net]->pins = netptr ;
1018     segptr = fsptr->segptr ;
1019     segptr->pin1ptr = netptr ;
1020     ptr1 = segptr->pin1ptr ;
1021     ptr2 = segptr->pin2ptr ;
1022     netptr->xpos = imptr->xpos ;
1023     if( ptr2->row == ptr1->row ) {
1024 	segptr->switchvalue == nswLINE ;
1025 	segptr->flag = TRUE ;
1026     } else if( add_Lcorner_feed &&
1027 	ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sep ) {
1028 	segptr->flag = FALSE ;
1029     } else {
1030 	segptr->flag = TRUE ;
1031     }
1032 } else { /* a steiner point */
1033     netptr = fsptr->netptr ;
1034     netptr->xpos = imptr->xpos ;
1035 }
1036 netptr->ypos = barrayG[row]->bycenter ;
1037 netptr->cell = imptr->cell ;
1038 netptr->pinloc = NEITHER   ;
1039 netptr->terminal = imptr->terminal ;
1040 netptr->pinname  = imptr->pinname  ;
1041 tearray[ netptr->terminal ] = netptr ;
1042 netptr->eqptr = ( EQ_NBOXPTR )Ysafe_calloc( 1, sizeof(EQ_NBOX) ) ;
1043 netptr->eqptr->typos = carrayG[ netptr->cell ]->tileptr->bottom ;
1044 netptr->eqptr->pinname = imptr->eqpinname ;
1045 }
1046 
1047 
local_Assgn(row,node)1048 void local_Assgn( row , node )
1049 INT row , node ;
1050 {
1051 
1052 INT next , back , head , end , LeftFlag , left_node , rite_node ;
1053 INT i , n , k , t , diff , orig_feed_needed , feed_need ;
1054 INT shift_left_start_index , shift_rite_start_index ;
1055 INT left_start , rite_start ;
1056 FEED_DATA *feedptr ;
1057 IPBOXPTR imptr ;
1058 
1059 back = 0 ;
1060 next = 0 ;
1061 left_node = rite_node = node ;
1062 feedptr = feedpptr[row] ;
1063 orig_feed_needed = feedptr[node]->needed ;
1064 feed_need = feedptr[node]->needed - feedptr[node]->actual ;
1065 head = wk_headS[node] ;
1066 end  = head + orig_feed_needed - 1 ;
1067 shellsort_referx( workerS , head , orig_feed_needed ) ;
1068 LeftFlag = 0 ;
1069 while( feed_need > back + next ) {
1070     if( left_node > 1 ) {
1071 	left_node-- ;
1072 	t = feedptr[left_node]->actual - feedptr[left_node]->needed ;
1073 	if( t > 0 ) {
1074 	    back += t ;
1075 	    if( back + next >= feed_need ) {
1076 		LeftFlag = 1 ;
1077 		break ;
1078 	    }
1079 	}
1080     }
1081     if( rite_node < chan_node_no ) {
1082 	rite_node++ ;
1083 	t = feedptr[rite_node]->actual - feedptr[rite_node]->needed ;
1084 	if( t > 0 ) {
1085 	    next += t ;
1086 	}
1087     }
1088 }
1089 if( LeftFlag ) {
1090     shift_left_start_index = head + feed_need - next - 1 ;
1091 } else {
1092     shift_left_start_index = head + back - 1 ;
1093 }
1094 if( shift_left_start_index < head ) {
1095     shift_rite_start_index = head + feedptr[node]->actual ;
1096 } else {
1097     shift_rite_start_index = shift_left_start_index
1098 				+ feedptr[node]->actual + 1 ;
1099 }
1100 left_start = shift_left_start_index ;
1101 rite_start = shift_rite_start_index ;
1102 for( n = node - 1 ; n >= left_node ; n-- ) {
1103     diff = feedptr[n]->actual - feedptr[n]->needed ;
1104     if( diff <= 0 ) {
1105 	continue ;
1106     }
1107     for( imptr = feedptr[n]->lastimp ;
1108 	tearray[ imptr->terminal ] ; imptr = imptr->prev ) ;
1109     k = 0 ;
1110     for( i = 1 ; i <= diff ; i++ ) {
1111 	if( left_start >= head ) {
1112 	    assgn_impin( imptr , workerS[ left_start-- ] , row ) ;
1113 	    imptr = imptr->prev ;
1114 	    ++k ;
1115 	} else {
1116 	    break ;
1117 	}
1118     }
1119     feedptr[n]->actual -= k ;
1120 }
1121 for( n = node + 1 ; n <= rite_node ; n++ ) {
1122     diff = feedptr[n]->actual - feedptr[n]->needed ;
1123     if( diff <= 0 ) {
1124 	continue ;
1125     }
1126     for( imptr = feedptr[n]->firstimp ;
1127 	tearray[ imptr->terminal ] ; imptr = imptr->next ) ;
1128     k = 0 ;
1129     for( i = 1 ; i <= diff ; i++ ) {
1130 	if(  rite_start <= end ) {
1131 	    assgn_impin( imptr , workerS[ rite_start++ ] , row ) ;
1132 	    imptr = imptr->next ;
1133 	    ++k ;
1134 	} else {
1135 	    break ;
1136 	}
1137     }
1138     feedptr[n]->actual -= k ;
1139 }
1140 imptr = feedptr[node]->firstimp ;
1141 
1142 k = shift_rite_start_index - 1 ;
1143 if( shift_rite_start_index > end ) {
1144     k = end ;
1145 }
1146 i = shift_left_start_index + 1 ;
1147 if( i < head ) {
1148     i = head ;
1149 }
1150 for( ; i <= k ; i++ ) {
1151     assgn_impin( imptr , workerS[i] , row ) ;
1152     imptr = imptr->next ;
1153 }
1154 feedptr[node]->actual = 0 ;
1155 feedptr[node]->needed = 0 ;
1156 }
1157 
1158 
1159 #endif
1160 
1161 
1162 
unequiv_pin_pre_processing()1163 void unequiv_pin_pre_processing()
1164 {
1165 DBOXPTR dimptr ;
1166 PINBOXPTR ptr ;
1167 INT net, row, hi, lo, k, xmin, xmax ;
1168 
1169 for( net = 1 ; net <= numnetsG ; net++ ) {
1170     dimptr = netarrayG[net] ;
1171     if( dimptr->numpins <= 1 ) continue ;
1172     ptr = dimptr->pins ;
1173     lo = hi = ptr->row ;
1174     for( ptr = ptr->next ; ptr ; ptr = ptr->next ) {
1175 	if( lo > ptr->row ) lo = ptr->row ;
1176 	if( hi < ptr->row ) hi = ptr->row ;
1177     }
1178     if( lo == hi ) {
1179 	if( dimptr->numpins == 2 ) continue ;
1180 	ptr = dimptr->pins ;
1181 	xmin = xmax = ptr->xpos ;
1182 	for( ptr = ptr->next ; ptr ; ptr = ptr->next ) {
1183 	    if( ptr->xpos < xmin ) {
1184 		xmin = ptr->xpos ;
1185 	    } else if( ptr->xpos > xmax ) {
1186 		xmax = ptr->xpos ;
1187 	    }
1188 	}
1189 	for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) {
1190 	    if( ptr->eqptr == NULL || ptr->eqptr->unequiv == 0 ) {
1191 		continue ;
1192 	    }
1193 	    if( ptr->xpos != xmin && ptr->xpos != xmax ) {
1194 		ptr->pinloc = BOTCELL ;
1195 	    }
1196 	}
1197     }
1198     for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) {
1199 	if( ptr->eqptr == NULL || ptr->eqptr->unequiv == 0 ) {
1200 	    continue ;
1201 	}
1202 	row = ptr->row ;
1203 	if( row == hi ) {
1204 	    ptr->pinloc = BOTCELL ;
1205 	} else if( row == lo ) {
1206 	    ptr->pinloc = TOPCELL ;
1207 	} else {
1208 	    k = ( row - lo ) % 2 ;
1209 	    if( k == 1 ) {
1210 		ptr->pinloc = BOTCELL ;
1211 	    } else {
1212 		ptr->pinloc = TOPCELL ;
1213 	    }
1214 	}
1215     }
1216 }
1217 }
1218 
1219 
relax_padPins_pinloc()1220 void relax_padPins_pinloc()
1221 {
1222 INT i ;
1223 PINBOXPTR pinptr ;
1224 
1225 for( i = lastpadG ; i > numcellsG ; i-- ) {
1226     for( pinptr = carrayG[i]->pins ;pinptr ; pinptr = pinptr->nextpin ) {
1227 	if( pinptr->adjptr->next == NULL ) {
1228 	    pinptr->pinloc = NEITHER ;
1229 	} else if( pinptr->adjptr->next->next == NULL ) {
1230 	    pinptr->pinloc = NEITHER ;
1231 	}
1232     }
1233 }
1234 }
1235 
1236 
relax_unequiv_pinloc()1237 void relax_unequiv_pinloc()
1238 {
1239 DBOXPTR dimptr ;
1240 PINBOXPTR ptr ;
1241 INT net ;
1242 
1243 for( net = 1 ; net <= numnetsG ; net++ ) {
1244     dimptr = netarrayG[net] ;
1245     if( dimptr->numpins <= 2 ) continue ;
1246     for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) {
1247 	if( ptr->pinloc == NEITHER || ptr->eqptr == NULL ||
1248 		    ptr->eqptr->unequiv == 0 ) continue ;
1249 	if( ptr->adjptr->next == NULL ) {
1250 	    ptr->pinloc = NEITHER ;
1251 	} else if( ptr->adjptr->next->next == NULL ) {
1252 	    ptr->pinloc = NEITHER ;
1253 	}
1254     }
1255 }
1256 }
1257 
1258 
check_unequiv_connectivity()1259 int check_unequiv_connectivity()
1260 {
1261 INT net, channel, correctness ;
1262 ADJASEG *adj ;
1263 PINBOXPTR pinptr ;
1264 DBOXPTR dimptr ;
1265 
1266 correctness = 1 ;
1267 for( net = 1 ; net <= numnetsG ; net++ ) {
1268     dimptr = netarrayG[net] ;
1269     if( dimptr->numpins <= 1 ) {
1270 	continue ;
1271     }
1272     for( pinptr = dimptr->pins ; pinptr ; pinptr = pinptr->next ) {
1273 	if( pinptr->eqptr == NULL || pinptr->eqptr->unequiv == 0 ) {
1274 	    continue ;
1275 	}
1276 	adj = pinptr->adjptr->next ;
1277 	channel = adj->segptr->flag ;
1278 	for( adj = adj->next ; adj ; adj = adj->next ) {
1279 	    if( channel != adj->segptr->flag ) {
1280 		correctness = 0 ;
1281 		printf(" unequivalent pin connection violation" ) ;
1282 		printf(" for net %d pin %d\n", net, pinptr->terminal ) ;
1283 	    }
1284 	}
1285     }
1286 }
1287 return( correctness ) ;
1288 }
1289 
1290 
1291 #define	UNVISITED_SEG	0
1292 #define	VISITED_SEG	1
1293 #define	REVISITED_SEG	1
1294 
swap_cost(perim_flag)1295 static LONG swap_cost( perim_flag )
1296 BOOL perim_flag ;
1297 {
1298 
1299     PINBOXPTR pin1ptr , pin2ptr ;
1300     SEGBOXPTR segptr ;
1301     DBOXPTR net_p ;
1302     INT xwire, ywire ;
1303     INT net ;
1304     LONG global_wire_length ;
1305     INT newtimepenal ;
1306     FILE *fp ;
1307     static BOOL outputL = TRUE ;
1308     INT p_path, s_path ;
1309     INT Px, Sx, Py, Sy, Ppath, Spath ; 	/* used to cummulate info */
1310 
1311     /* -----------------------------------------------------------------
1312 	We are going to use the half perimeter fields to calculate the
1313 	timing costs.  We find the global wire cost by adding up the
1314 	length from the segments.
1315     ----------------------------------------------------------------- */
1316     global_wire_length = 0 ;
1317     D( "twsc/swap_cost",
1318 	if( outputL == TRUE ){
1319 	    fp = TWOPEN( "wire", "w", ABORT ) ;
1320 	    fprintf( fp, "net\tnumpins\tPx\tSx\tPy\tSy\tPtime\tStime\n" ) ;
1321 	    Px = 0 ;
1322 	    Py = 0 ;
1323 	    Sx = 0 ;
1324 	    Sy = 0 ;
1325 	    Spath = 0 ;
1326 	    Ppath = 0 ;
1327 	}
1328     ) ;
1329 
1330     for( net = 1; net <= numnetsG; net++ ){
1331 	xwire = 0 ;
1332 	ywire = 0 ;
1333 	for( segptr = netsegHeadG[net]->next;segptr;segptr = segptr->next ){
1334 	    pin1ptr = segptr->pin1ptr ;
1335 	    pin2ptr = segptr->pin2ptr ;
1336 	    segptr->swap_flag = UNVISITED_SEG ;
1337 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1338 	    ywire += ABS(pin1ptr->ypos - pin2ptr->ypos) ;
1339 	} /* end for( segptr = netsegHeadG[net]... */
1340 
1341 	global_wire_length += (LONG)xwire ;
1342 
1343 	/* now save result in netarray */
1344 	net_p = netarrayG[net] ;
1345 	if( perim_flag ){
1346 	    if( net_p->newhalfPx != xwire ){
1347 		fprintf( stderr, "new x half perim:%d doesn't match calc.:%d\n",
1348 		    net_p->newhalfPx, xwire ) ;
1349 		net_p->newhalfPx = xwire ;
1350 	    }
1351 	    if( net_p->newhalfPy != ywire ){
1352 		fprintf( stderr, "new y half perim:%d doesn't match calc.:%d\n",
1353 		    net_p->newhalfPy, ywire ) ;
1354 		net_p->newhalfPy = ywire ;
1355 	    }
1356 
1357 	} else {
1358 	    D( "twsc/swap_cost",
1359 		if( outputL == TRUE ){
1360 		    net_p->newhalfPx = xwire ;
1361 		    net_p->newhalfPy = ywire ;
1362 		    p_path = dpath_len( net, TRUE ) ;
1363 		    s_path = dpath_len( net, FALSE ) ;
1364 		    fprintf( fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", net,
1365 		    net_p->numpins, net_p->halfPx, xwire, net_p->halfPy, ywire,
1366 		    p_path, s_path ) ;
1367 		    Px += net_p->halfPx ;
1368 		    Py += net_p->halfPy ;
1369 		    Sx += xwire ;
1370 		    Sy += ywire ;
1371 		    Spath += s_path ;
1372 		    Ppath += p_path ;
1373 		}
1374 	    ) ;
1375 	    net_p->halfPx = net_p->newhalfPx = xwire ;
1376 	    net_p->halfPy = net_p->newhalfPy = ywire ;
1377 	}
1378     } /* end for( net = 1... */
1379 
1380     D( "twsc/swap_cost",
1381 	if( outputL == TRUE ){
1382 	    outputL = FALSE ;
1383 	    fprintf( fp,
1384 	    "----------------------------------------------------------------\n");
1385 	    fprintf( fp, " \t \t%d\t%d\t%d\t%d\t%d\t%d\n",
1386 		Px,Sx,Py,Sy,Ppath,Spath ) ;
1387 	    TWCLOSE(fp) ;
1388 	}
1389     ) ;
1390 
1391     /* now recompute the timing penalty */
1392     newtimepenal = recompute_timecost() ;
1393 
1394     D( "twsc/swap_cost",
1395 	if( timingcostG != newtimepenal ){
1396 	    fprintf( stderr, "Timing penalty mismatch %d vs %d\n",
1397 		timingcostG, newtimepenal ) ;
1398 	}
1399     ) ;
1400 
1401     timingcostG = newtimepenal ;
1402 
1403 
1404     return( global_wire_length ) ;
1405 } /* end swap_cost() */
1406 
1407 
1408 
improve_place_sequential(row,index)1409 int improve_place_sequential( row , index )
1410 INT row , index ;
1411 {
1412 
1413 INT cell1 , cell2 , shift1 , shift2 , swap ;
1414 LONG global_wire , new_global_wire ;
1415 INT cell , pin , xpos , other_cell ;
1416 LONG ic , fc ;
1417 INT net, xwire ;
1418 INT newtimepenal ;
1419 DBOXPTR net_p ;
1420 CBOXPTR ptr ;
1421 PINBOXPTR pin1ptr , pin2ptr , termptr ;
1422 ADJASEGPTR adjptr ;
1423 SEGBOXPTR segptr ;
1424 
1425 /* -----------------------------------------------------------------
1426     In order to avoid counting segments twice, use the swap_flag field.
1427     Initially all segments are marked unvisited.  When traversing
1428     segments of first cell mark them as visited.  When traversing
1429     second cell we do not update any segments that have been visited.
1430     Everything is fine at this point but we need to set the flags
1431     back.  We do this when traversing the cells a second time to
1432     find the new cost.  We then reverse the roles of the flags.
1433     It is important to note that VISITED_SEG == REVISITED_SEG.
1434 ----------------------------------------------------------------- */
1435 newtimepenal = timingcostG ;
1436 global_wire = 0 ;
1437 clear_net_set() ;
1438 
1439 D( "twsc/cell_swap_opt",
1440     ic = swap_cost( FALSE ) ;
1441 ) ;
1442 
1443 /* find current global wire lengths */
1444 other_cell = cell = pairArrayG[row][index] ;
1445 ptr = carrayG[cell] ;
1446 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1447     pin = termptr->terminal ;
1448     net = termptr->net ;
1449     net_p = netarrayG[net] ;
1450     /* check to see if this net has been initialized */
1451     if(!(member_net_set(net) )){
1452 	add2net_set( net ) ;
1453 	net_p->newhalfPx = net_p->halfPx ;
1454     }
1455     xwire = 0 ;
1456     /* look at all the segments that this pin connects */
1457     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1458 	segptr = adjptr->segptr ;
1459 	if( segptr->swap_flag == UNVISITED_SEG ){
1460 	    segptr->swap_flag = VISITED_SEG ; /* set to membership */
1461 	    pin1ptr = segptr->pin1ptr ;
1462 	    pin2ptr = segptr->pin2ptr ;
1463 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1464 	}
1465     }
1466     net_p->newhalfPx -= xwire ;
1467     global_wire += (LONG)xwire ;
1468 }
1469 cell = pairArrayG[row][index+1] ;
1470 ptr = carrayG[cell] ;
1471 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1472     pin = termptr->terminal ;
1473     net = termptr->net ;
1474     net_p = netarrayG[net] ;
1475     /* check to see if this net has been initialized */
1476     if(!(member_net_set(net) )){
1477 	add2net_set( net ) ;
1478 	net_p->newhalfPx = net_p->halfPx ;
1479     }
1480     xwire = 0 ;
1481     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1482 	segptr = adjptr->segptr ;
1483 	if( segptr->swap_flag == UNVISITED_SEG ){
1484 	    segptr->swap_flag = VISITED_SEG ;
1485 	    pin1ptr = segptr->pin1ptr ;
1486 	    pin2ptr = segptr->pin2ptr ;
1487 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1488 	}
1489     }
1490     net_p->newhalfPx -= xwire ;
1491     global_wire += (LONG)xwire ;
1492 }
1493 
1494 /* swap cells */
1495 cell1 = pairArrayG[row][index] ;
1496 cell2 = pairArrayG[row][index+1] ;
1497 shift1 = carrayG[cell2]->clength ;
1498 shift2 = -carrayG[cell1]->clength ;
1499 carrayG[cell1]->cxcenter += shift1 ;
1500 carrayG[cell2]->cxcenter += shift2 ;
1501 pairArrayG[row][index] = cell2 ;
1502 pairArrayG[row][index+1] = cell1 ;
1503 /* ...update pin positions now..... */
1504 for( termptr = carrayG[cell1]->pins; termptr;
1505 				termptr = termptr->nextpin ) {
1506     termptr->xpos += shift1 ;
1507 }
1508 for( termptr = carrayG[cell2]->pins; termptr;
1509 				termptr = termptr->nextpin ) {
1510     termptr->xpos += shift2 ;
1511 }
1512 
1513 
1514 /* find new global wire lengths */
1515 new_global_wire = 0 ;
1516 other_cell = cell = pairArrayG[row][index] ;
1517 ptr = carrayG[cell] ;
1518 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1519     pin = termptr->terminal ;
1520     net_p = netarrayG[termptr->net] ;
1521     xwire = 0 ;
1522     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1523 	segptr = adjptr->segptr ;
1524 	if( segptr->swap_flag == REVISITED_SEG ){
1525 	    segptr->swap_flag = UNVISITED_SEG ;
1526 	    pin1ptr = segptr->pin1ptr ;
1527 	    pin2ptr = segptr->pin2ptr ;
1528 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1529 	}
1530     }
1531     net_p->newhalfPx += xwire ;
1532     new_global_wire += (LONG)xwire ;
1533 }
1534 cell = pairArrayG[row][index+1] ;
1535 ptr = carrayG[cell] ;
1536 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1537     pin = termptr->terminal ;
1538     net_p = netarrayG[termptr->net] ;
1539     xwire = 0 ;
1540     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1541 	segptr = adjptr->segptr ;
1542 	if( segptr->swap_flag == REVISITED_SEG ){
1543 	    segptr->swap_flag = UNVISITED_SEG ;
1544 	    pin1ptr = segptr->pin1ptr ;
1545 	    pin2ptr = segptr->pin2ptr ;
1546 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1547 	}
1548     }
1549     net_p->newhalfPx += xwire ;
1550     new_global_wire += (LONG)xwire ;
1551 }
1552 
1553 /* -----------------------------------------------------------------
1554     Calculate the timing penalty for swap.
1555 ----------------------------------------------------------------- */
1556 newtimepenal += calc_incr_time2( cell1, cell2 ) ;
1557 D( "twsc/check_timing/globe",
1558     if( dcalc_full_penalty(newtimepenal) == FALSE ){
1559 	fprintf( stderr, "Problem with timing penalty\n" ) ;
1560     }
1561 ) ;
1562 
1563 D( "twsc/cell_swap_opt",
1564     fc = swap_cost( TRUE ) ;
1565 
1566     if( fc - ic != new_global_wire - global_wire ) {
1567 	fprintf(stderr,"error in improve_place_sequential()\n");
1568     }
1569 ) ;
1570 
1571 
1572 // (global_wire - new_global_wire) is assumed to not exceed size INT
1573 // although each termin is size LONG
1574 
1575 if( accept_greedy( (INT)(global_wire-new_global_wire), timingcostG-newtimepenal, 0 )){
1576 
1577     swap = (INT)(new_global_wire - global_wire) ;
1578     global_wire_lengthS += (LONG)swap ;
1579     swap += newtimepenal - timingcostG ;
1580     if( numpathsG ){
1581 	update_time2() ;
1582 	timingcostG = newtimepenal ;
1583 	/* -----------------------------------------------------------------
1584 	    There might be some redundancy here but the checking for it
1585 	    has overhead.  Do simple method for now.
1586 	----------------------------------------------------------------- */
1587 	ptr = carrayG[cell1] ;
1588 	for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) {
1589 	    net_p = netarrayG[termptr->net] ;
1590 	    net_p->halfPx = net_p->newhalfPx ;
1591 	}
1592 	ptr = carrayG[cell2] ;
1593 	for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) {
1594 	    net_p = netarrayG[termptr->net] ;
1595 	    net_p->halfPx = net_p->newhalfPx ;
1596 	}
1597     }
1598     return( swap ) ;
1599 } else {
1600     /* swap cells back to original position */
1601     cell1 = pairArrayG[row][index] ;
1602     cell2 = pairArrayG[row][index+1] ;
1603     shift1 = carrayG[cell2]->clength ;
1604     shift2 = -carrayG[cell1]->clength ;
1605     carrayG[cell1]->cxcenter += shift1 ;
1606     carrayG[cell2]->cxcenter += shift2 ;
1607     pairArrayG[row][index] = cell2 ;
1608     pairArrayG[row][index+1] = cell1 ;
1609     /* ...update pin positions now..... */
1610     for( termptr = carrayG[cell1]->pins; termptr;
1611 				    termptr = termptr->nextpin ) {
1612 	termptr->xpos += shift1 ;
1613     }
1614     for( termptr = carrayG[cell2]->pins; termptr;
1615 				    termptr = termptr->nextpin ) {
1616 	termptr->xpos += shift2 ;
1617     }
1618     return(0);
1619 }
1620 }
1621 
1622 
cell_rotate(INT row,INT index)1623 INT cell_rotate(INT row , INT index )
1624 {
1625 
1626 INT cell, swap ;
1627 LONG global_wire , new_global_wire ;
1628 INT pin , xpos ;
1629 LONG ic, fc ;
1630 INT net, xwire, xc, left, right, dist_l, dist_r ;
1631 INT newtimepenal ;
1632 DBOXPTR net_p ;
1633 CBOXPTR ptr ;
1634 PINBOXPTR pin1ptr , pin2ptr , termptr ;
1635 ADJASEGPTR adjptr ;
1636 SEGBOXPTR segptr ;
1637 
1638 /* -----------------------------------------------------------------
1639     In order to avoid counting segments twice, use the swap_flag field.
1640 ----------------------------------------------------------------- */
1641 D( "twsc/cell_swap_opt",
1642     ic = swap_cost( FALSE ) ;
1643 ) ;
1644 
1645 global_wire = 0 ;
1646 clear_net_set() ;
1647 /* find current global wire lengths */
1648 cell = pairArrayG[row][index] ;
1649 ptr = carrayG[cell] ;
1650 if( ptr->orflag == 0){
1651     return(0) ;
1652 }
1653 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1654     pin = termptr->terminal ;
1655     net = termptr->net ;
1656     net_p = netarrayG[net] ;
1657     /* check to see if this net has been initialized */
1658     if(!(member_net_set(net) )){
1659 	add2net_set( net ) ;
1660 	net_p->newhalfPx = net_p->halfPx ;
1661     }
1662     xwire = 0 ;
1663     /* look at all the segments that this pin connects */
1664     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1665 	segptr = adjptr->segptr ;
1666 	if( segptr->swap_flag == UNVISITED_SEG ){
1667 	    segptr->swap_flag = VISITED_SEG ; /* set to membership */
1668 	    pin1ptr = segptr->pin1ptr ;
1669 	    pin2ptr = segptr->pin2ptr ;
1670 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1671 	}
1672     }
1673     net_p->newhalfPx -= xwire ;
1674     global_wire += (LONG)xwire ;
1675 }
1676 
1677 /* rotate the cell */
1678 xc = ptr->cxcenter ;
1679 left = xc + ptr->tileptr->left ;
1680 right = xc + ptr->tileptr->right ;
1681 
1682 /* ...update pin positions now..... */
1683 for( termptr = carrayG[cell]->pins; termptr; termptr = termptr->nextpin ) {
1684     dist_l = termptr->xpos - left ;
1685     dist_r = right - termptr->xpos ;
1686     if( dist_l < dist_r ){
1687 	/* pin closer to left edge move to right edge */
1688 	termptr->xpos = right - dist_l ;
1689     } else {
1690 	/* pin closer to right edge move to left edge */
1691 	termptr->xpos = left + dist_r ;
1692     }
1693 }
1694 
1695 /* find new global wire lengths */
1696 new_global_wire = 0 ;
1697 for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) {
1698     pin = termptr->terminal ;
1699     net_p = netarrayG[termptr->net] ;
1700     xwire = 0 ;
1701     for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) {
1702 	segptr = adjptr->segptr ;
1703 	if( segptr->swap_flag == REVISITED_SEG ){
1704 	    segptr->swap_flag = UNVISITED_SEG ;
1705 	    pin1ptr = segptr->pin1ptr ;
1706 	    pin2ptr = segptr->pin2ptr ;
1707 	    xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ;
1708 	}
1709     }
1710     net_p->newhalfPx += xwire ;
1711     new_global_wire += (LONG)xwire ;
1712 }
1713 
1714 /* -----------------------------------------------------------------
1715     Calculate the timing penalty for swap.
1716 ----------------------------------------------------------------- */
1717 newtimepenal = timingcostG + calc_incr_time( cell ) ;
1718 D( "twsc/check_timing",
1719     ASSERT( dcalc_full_penalty(newtimepenal), NULL, "time problem\n" ) ;
1720 ) ;
1721 
1722 D( "twsc/cell_swap_opt",
1723     fc = swap_cost( TRUE ) ;
1724 
1725     if( fc - ic != new_global_wire - global_wire ) {
1726 	fprintf(stderr,"error in cell_rotate()\n");
1727     }
1728 ) ;
1729 
1730 if( accept_greedy( (INT)(global_wire-new_global_wire), timingcostG-newtimepenal, 0 )){
1731     swap = (INT)(new_global_wire - global_wire );
1732     global_wire_lengthS += (LONG)swap ;
1733     swap += newtimepenal - timingcostG ;
1734     if( numpathsG ){
1735 	update_time(cell) ;
1736 	timingcostG = newtimepenal ;
1737 	/* -----------------------------------------------------------------
1738 	    There might be some redundancy here but the checking for it
1739 	    has overhead.  Do simple method for now.
1740 	----------------------------------------------------------------- */
1741 	ptr = carrayG[cell] ;
1742 	for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) {
1743 	    net_p = netarrayG[termptr->net] ;
1744 	    net_p->halfPx = net_p->newhalfPx ;
1745 	}
1746     }
1747     /* make sure to update cell orient field */
1748     if( ptr->corient == 0 ){
1749 	ptr->corient = 2 ;
1750     } else if( ptr->corient == 2 ){
1751 	ptr->corient = 0 ;
1752     } else if( ptr->corient == 1 ){
1753 	ptr->corient = 3;
1754     } else if( ptr->corient == 3 ){
1755 	ptr->corient = 1;
1756     } else {
1757 	sprintf( YmsgG, "Invalid rotation for cell:%s\n", ptr->cname ) ;
1758 	M( ERRMSG, "cell_rotate", YmsgG ) ;
1759     }
1760     return( swap ) ;
1761 } else {
1762     /* rotate cells back to original position */
1763     for( termptr = carrayG[cell]->pins; termptr; termptr = termptr->nextpin ) {
1764 	dist_l = termptr->xpos - left ;
1765 	dist_r = right - termptr->xpos ;
1766 	if( dist_l < dist_r ){
1767 	    /* pin closer to left edge move to right edge */
1768 	    termptr->xpos = right - dist_l ;
1769 	} else {
1770 	    /* pin closer to right edge move to left edge */
1771 	    termptr->xpos = left + dist_r ;
1772 	}
1773     }
1774     return(0);
1775 }
1776 } /* end cell_rotate() */
1777 
elim_unused_feedsSC()1778 void elim_unused_feedsSC()
1779 {
1780 
1781 CBOXPTR ptr , cellptr , first_cptr , last_cptr ;
1782 PINBOXPTR termptr ;
1783 INT row, feed_count, i , last , cell_left , length , max_length ;
1784 INT j , k , elim , cell , limit , left_edge , corient ;
1785 INT *Aray , longest_row , shift , *row_len , total_elim ;
1786 
1787 row_len = (INT *) Ysafe_calloc( (1+numRowsG) , sizeof(INT) ) ;
1788 for( i = 1 ; i <= numRowsG ; i++ ) {
1789     Aray = pairArrayG[i] ;
1790     first_cptr = carrayG[ Aray[1] ] ;
1791     last_cptr  = carrayG[ Aray[ Aray[0] ] ] ;
1792     length = last_cptr->cxcenter + last_cptr->tileptr->right -
1793 	     first_cptr->cxcenter - first_cptr->tileptr->left ;
1794     row_len[i] = length ;
1795 }
1796 
1797 total_elim = 0 ;
1798 for( ; ; ) {
1799     /* find longest row */
1800     max_length = 0 ;
1801     for( i = 1 ; i <= numRowsG ; i++ ) {
1802 	if( row_len[i] > max_length ) {
1803 	    max_length = row_len[i] ;
1804 	    row = i ;
1805 	}
1806     }
1807 
1808     i = 0 ;
1809     limit = pairArrayG[row][0] ;
1810     for( k = limit ; k >= 1 ; k-- ) {
1811 	cell = pairArrayG[row][k] ;
1812 	if( strncmp(carrayG[cell]->cname,"twfeed",6) == STRINGEQ ) {
1813 	    if( tearrayG[carrayG[cell]->imptr->terminal] == NULL ) {
1814 		if( carrayG[cell]->clength != 0 ) {
1815 		    /* we have here an unused feed cell */
1816 		    row_len[row] -= carrayG[cell]->clength ;
1817 		    carrayG[cell]->clength = 0 ;
1818 		    carrayG[cell]->tileptr->left = 0 ;
1819 		    carrayG[cell]->tileptr->right = 0 ;
1820 		    i++ ;
1821 		    break ;
1822 		}
1823 	    }
1824 	}
1825     }
1826 
1827     if( i == 0 ) {
1828 	fprintf(fpoG,"Eliminated %d unused feeds in the longest row\n",
1829 							total_elim ) ;
1830 	break ;
1831     } else {
1832 	total_elim++ ;
1833 	/* replace, i.e. repack, the cells for this row */
1834 	left_edge  = barrayG[row]->bxcenter + barrayG[row]->bleft ;
1835 	for( i = 1 ; i <= limit ; i++ ) {
1836 	    cellptr = carrayG[ pairArrayG[row][i] ] ;
1837 	    cell_left = cellptr->tileptr->left ;
1838 	    shift = (left_edge - cell_left) - cellptr->cxcenter ;
1839 		/* new minus old */
1840 	    cellptr->cxcenter += shift ;
1841 	    for( termptr = cellptr->pins; termptr;
1842 					    termptr = termptr->nextpin ){
1843 		termptr->xpos += shift ;
1844 	    }
1845 	    left_edge += cellptr->tileptr->right - cell_left ;
1846 	}
1847     }
1848 }
1849 
1850 
1851 /* now print out the new row lengths */
1852 fprintf(fpoG,"BLOCK      TOTAL CELL LENGTHS      OVER/UNDER TARGET\n");
1853 max_length = 0 ;
1854 for( i = 1 ; i <= numRowsG ; i++ ) {
1855     Aray = pairArrayG[i] ;
1856     first_cptr = carrayG[ Aray[1] ] ;
1857     last_cptr  = carrayG[ Aray[ Aray[0] ] ] ;
1858     length = last_cptr->cxcenter + last_cptr->tileptr->right -
1859 	     first_cptr->cxcenter - first_cptr->tileptr->left ;
1860     fprintf( fpoG, "%3d            %7d \n", i, length );
1861     if( max_length < length ) {
1862 	longest_row = i ;
1863 	max_length = length ;
1864     }
1865 }
1866 fprintf( fpoG, "\nLONGEST Row is:%d   Its length is:%d\n",
1867 			    longest_row , max_length ) ;
1868 
1869 
1870 Ysafe_free( row_len );
1871 return ;
1872 }
1873 
rebuild_nextpin()1874 void rebuild_nextpin()
1875 {
1876     INT net, cell ;
1877     PINBOXPTR netptr , cnetptr ;
1878 
1879     /* added by Carl 22 July 1990 */
1880     /* blow off the old nextpin fields as they may be corrupted anyway */
1881     for( net = 1 ; net <= numnetsG ; net++ ) {
1882 	for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) {
1883 	    netptr->nextpin = NULL ;
1884 	}
1885     }
1886 
1887     for( cell = 1 ; cell <= lastpadG ; cell++ ) {
1888 	carrayG[cell]->pins = NULL ;
1889     }
1890 
1891     /* now rebuild the nextpin fields */
1892     for( net = 1 ; net <= numnetsG ; net++ ) {
1893 	for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) {
1894 
1895 	    if( netptr->net <= 0 ){
1896 		fprintf( stderr, "We have an zero net\n" ) ;
1897 		continue ;
1898 	    }
1899 	    /* add it into this cell's pin list */
1900 	    cnetptr = carrayG[netptr->cell]->pins ;
1901 	    carrayG[netptr->cell]->pins = netptr ;
1902 	    carrayG[netptr->cell]->pins->nextpin = cnetptr ;
1903 	}
1904     }
1905 } /* end rebuild_nextpin */
1906 
rebuild_cell_paths()1907 void rebuild_cell_paths()
1908 {
1909     INT i ;
1910     CBOXPTR ptr ;
1911     GLISTPTR path_p, freepath_p ;
1912 
1913     for( i=1;i<=lastpadG; i++ ){
1914 
1915 	ptr = carrayG[i] ;
1916 	for( path_p = ptr->paths;path_p; ){
1917 	    freepath_p = path_p ;
1918 	    path_p = path_p->next ;
1919 	    Ysafe_free( freepath_p ) ;
1920 	}
1921 	ptr->paths = NULL ;
1922     }
1923     add_paths_to_cells() ;
1924 } /* end rebuild_cell_paths() */
1925