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