1 /*
2 * Copyright (C) 1989-1992 Yale University
3 * Copyright (C) 2014 Ruben Undheim <ruben.undheim@gmail.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: main.c
44 DESCRIPTION:TimberWolfSC's main function.
45 CONTENTS: main( argc , argv )
46 INT argc ;
47 char *argv[] ;
48 initialize_global_router1()
49 initialize_global_router()
50 execute_global_router()
51 init_utemp()
52 install_swap_pass_thrus( netptr )
53 PINBOXPTR netptr ;
54 incorporate_ECOs()
55 DATE: Mar 27, 1989
56 REVISIONS: Oct 20, 1990 - fixed problem with graphics close.
57 Sat Dec 15 22:08:21 EST 1990 - modified pinloc values
58 so that it will always be positive.
59 Sun Jan 20 21:47:52 PST 1991 - ported to AIX.
60 Wed Jan 23 02:41:07 PST 1991 - output now at density
61 if requested.
62 Fri Jan 25 23:48:09 PST 1991 - avoid crashing if empty
63 rows exist.
64 Fri Feb 15 15:15:52 EST 1991 - place pads here so that
65 initialize_global_router1 save correct state.
66 Thu Mar 7 01:53:39 EST 1991 - now call SGGR automatically.
67 Tue Mar 12 17:10:47 CST 1991 - fixed DN10000 warnings.
68 Fri Mar 15 00:39:41 CST 1991 - now pick best global
69 route based on area.
70 Thu Apr 18 01:48:52 EDT 1991 - now output feed percentage
71 so user can use this in the next run.
72 Wed Jun 5 16:37:52 CDT 1991 - during global routing
73 maintain side.
74 Thu Aug 1 16:12:05 CDT 1991 - now save orient
75 correctly during global routing.
76 Thu Aug 22 22:12:58 CDT 1991 - now let gate_array mode
77 run both row evenning and not.
78 Fri Sep 6 15:14:47 CDT 1991 - fixed graphics calls
79 to make it less confusing to user.
80 Thu Sep 19 14:15:51 EDT 1991 - added equal width cell
81 capability.
82 Fri Sep 27 20:54:48 EDT 1991 - fixed ECO problem.
83 Thu Nov 7 23:03:57 EST 1991 - fixed problem with picking
84 best global route criteria and added new row evener.
85 ----------------------------------------------------------------- */
86
87 #define MAIN_VARS
88 #include "standard.h"
89 #include "main.h"
90 #include "groute.h"
91 #include "readpar.h"
92 #include "parser.h"
93 #include "feeds.h"
94 #include "pads.h"
95
96 #include <string.h>
97 #include <signal.h>
98 #include <yalecad/cleanup.h>
99 #include <yalecad/message.h>
100
101 #include "config-build.h"
102
103 #define EXPECTEDMEMORY (512 * 1024)
104
105 /* global variables definitions */
106 INT row_extentG ;
107 INT **bin_configG ;
108 INT left_row_boundaryG ;
109 INT save_abs_min_flagG ;
110 INT actual_feed_thru_cells_addedG = 0 ;
111 BOOL orientation_optimizationG = FALSE ;
112
113 /* global variable references */
114 extern BOOL do_fast_globalG ;
115 extern BOOL no_row_lengthsG ;
116 extern BOOL do_not_even_rowsG ;
117 extern BOOL ignore_crossbusesG ;
118 extern BOOL output_at_densityG ;
119 extern BOOL absolute_minimum_feedsG ;
120 extern BOOL glob_route_only_crit_netsG ;
121 extern BOOL vertical_track_on_cell_edgeG ;
122 extern BOOL route_padnets_outsideG ;
123 extern BOOL call_row_evenerG ;
124 extern BOOL placement_improveG ;
125 extern BOOL ignore_feedsG ;
126 extern INT ECOs_existG ;
127 extern INT spacer_widthG ;
128 extern INT longest_row_lengthG ;
129 extern INT largest_delta_row_lenG ;
130 extern INT total_row_lengthG ;
131 INT numnetsG;
132 INT *FeedInRowG;
133 INT fdthrusG;
134 INT track_pitchG;
135 INT ffeedsG;
136
137 INT maxCellOG ;
138
139 extern void readnets(FILE* fp);
140
141 /* static variables */
142 static INT routing_loopS ;
143 static INT *save_cell_xS ;
144 static INT *save_cell_yS ;
145 static INT *save_cell_bS ;
146 static INT *save_cell_cS ;
147 static INT *save_desireS ;
148 static INT *save_orientS ;
149 static INT *save_orig_desireS ;
150 static char *twdirS ;
151 static INT num_feeds_addedS ;/* number of feeds added on best iteration */
152 static DOUBLE ave_row_sepS ; /* the row separation for a run */
153
154 void install_swap_pass_thrus(PINBOXPTR netptr);
155 void incorporate_ECOs();
156 void syntax();
157 void init_utemp();
158
main(int argc,char * argv[])159 int main(int argc , char *argv[])
160 {
161
162
163 FILE *fp ;
164 DOUBLE quality_value();
165 char filename[LRECL] ;
166 INT ll, rr, bb, tt ;
167 INT bdxlen , bdylen ;
168 INT block ;
169 INT yaleIntro() ;
170 INT cx, cy, cl, cr, cb, ct, cell ;
171 char *ptr ;
172 char *Ystrclone() ;
173 BOOL debug ;
174 BOOL parasite ;
175 BOOL windowId ;
176 BOOL verbose ;
177 INT arg_count ;
178 char *Ygetenv() ;
179
180 /* ********************** start initialization *********************** */
181 /* start up cleanup handler */
182 YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ;
183
184 Yinit_memsize( EXPECTEDMEMORY ) ;
185
186 USER_INITIALIZATION() ;
187
188 if( argc < 2 || argc > 4 ){
189 syntax() ;
190 } else {
191 debug = FALSE ;
192 parasite = FALSE ;
193 verbose = FALSE ;
194 #ifndef NOGRAPHICS
195 windowId = 0 ;
196 doGraphicsG = TRUE ;
197 #else /* NOGRAPHICS case */
198 doGraphicsG = FALSE ;
199 #endif /* NOGRAPHICS */
200 arg_count = 1 ;
201 if( *argv[1] == '-' ){
202 for( ptr = ++argv[1]; *ptr; ptr++ ){
203 switch( *ptr ){
204 case 'd':
205 debug = TRUE ;
206 break ;
207 case 'n':
208 doGraphicsG = FALSE ;
209 break ;
210 case 'v':
211 verbose = TRUE ;
212 break ;
213 case 'w':
214 parasite = TRUE ;
215 break ;
216 default:
217 sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ;
218 M(ERRMSG,"main",YmsgG);
219 syntax() ;
220 }
221 }
222 YdebugMemory( debug ) ;
223
224 cktNameG = Ystrclone( argv[++arg_count] );
225
226 /* now tell the user what he picked */
227 M(MSG,NULL,"\n\nTimberWolfSC switches:\n" ) ;
228 if( debug ){
229 YsetDebug( TRUE ) ;
230 M(MSG,NULL,"\tdebug on\n" ) ;
231 }
232 if( doGraphicsG ){
233 M(MSG,NULL,"\tGraphics mode on\n" ) ;
234 } else {
235 M(MSG,NULL,"\tGraphics mode off\n" ) ;
236 }
237 if( parasite ){
238 M(MSG,NULL,"\tTimberWolfSC will inherit window\n" ) ;
239 /* look for windowid */
240 if(argc != 4){
241 M(ERRMSG,"main","Need to specify windowID\n" ) ;
242 syntax() ;
243
244 } else {
245 G( windowId = atoi( argv[++arg_count] ) ) ;
246 }
247 }
248 if( verbose ){
249 M(MSG,NULL,"\tVerbose mode on\n" ) ;
250 Ymessage_mode( M_VERBOSE ) ;
251 }
252 M(MSG,NULL,"\n" ) ;
253 } else if( argc == 2 ){
254 /* order is important here */
255 YdebugMemory( FALSE ) ;
256 cktNameG = Ystrclone( argv[1] );
257
258 } else {
259 syntax() ;
260 }
261 }
262 sprintf( filename , "%s.out" , cktNameG ) ;
263 fpoG = TWOPEN( filename, "w", ABORT ) ;
264 Ymessage_init( fpoG ) ; /* send all the messages to a file normally */
265 YinitProgram( "TimberWolfSC", "v6.0", yaleIntro );
266 /* ********************** end initialization ************************* */
267
268 readParFile();
269
270 /* Check if TWDIR overridden */
271 if((twdirS = getenv("TWDIR"))) {
272 M(MSG,NULL, "Directory overridden with 'TWDIR' environment variable\n" ) ;
273 }
274 else {
275 twdirS = TWFLOWDIR;
276 }
277
278 G( initGraphics( argc, argv, windowId ) ) ;
279
280 Yset_random_seed( (INT) randomSeedG ) ;
281 fprintf( fpoG, "\nThe random number generator seed is: %u\n\n\n",
282 randomSeedG ) ;
283
284 /*
285 get a pointer to blockfile
286 */
287 sprintf( filename , "%s.blk" , cktNameG ) ;
288 fp = TWOPEN( filename , "r" , ABORT ) ;
289 readblck( fp ) ;
290 TWCLOSE( fp ) ;
291
292 maxCellOG = 0 ;
293 for( block = 1 ; block <= numRowsG ; block++ ) {
294 if( barrayG[block]->borient == 2 ) {
295 maxCellOG = 1 ;
296 break ;
297 }
298 }
299
300
301 if( rowsG > 0 ) {
302 sprintf( filename , "%s.scel" , cktNameG ) ;
303 } else {
304 sprintf( filename , "%s.cel" , cktNameG ) ;
305 }
306 /* avoid crashes later on */
307 if( spacer_widthG == -1 && (rowsG > 0 || gate_arrayG) ){
308 M( ERRMSG, "main",
309 "Neither spacer width nor feedthru width was specified in .par file\n" ) ;
310 M( ERRMSG, NULL, "FATAL:must exit\n\n" ) ;
311 }
312
313 fp = TWOPEN( filename , "r" , ABORT ) ;
314 readcell( fp ) ;
315 TWCLOSE( fp ) ;
316
317 /*
318 get a pointer to the netlist input file
319 */
320 sprintf( filename , "%s.net" , cktNameG ) ;
321 fp = TWOPEN( filename , "r", NOABORT ) ;
322 readnets( fp ) ;
323 if( fp ) {
324 TWCLOSE( fp ) ;
325 }
326
327
328 if ( Equal_Width_CellsG && file_conversionG ) {
329 closegraphics() ;
330 calc_cells_width();
331 fprintf(stderr,"\n***************************************************");
332 fprintf(stderr,"\nThe file stdcell.comp has the converted equal cells");
333 fprintf(stderr,"\n***************************************************");
334 fprintf(stderr,"\n\n");
335 YexitPgm(PGMOK);
336
337 }
338
339 iterationG = 0 ;
340
341 tt = INT_MIN ;
342 bb = INT_MAX ;
343 rr = INT_MIN ;
344 ll = INT_MAX ;
345 for( block = 1 ; block <= numRowsG ; block++ ) {
346 cx = barrayG[block]->bxcenter ;
347 cy = barrayG[block]->bycenter ;
348 cl = barrayG[block]->bleft;
349 cr = barrayG[block]->bright;
350 cb = barrayG[block]->bbottom;
351 ct = barrayG[block]->btop;
352 if( cx + cr > rr ) {
353 rr = cx + cr ;
354 }
355 if( cx + cl < ll ) {
356 ll = cx + cl ;
357 }
358 if( cy + ct > tt ) {
359 tt = cy + ct ;
360 }
361 if( cy + cb < bb ) {
362 bb = cy + cb ;
363 }
364 }
365 blkxspanG = rr - ll ;
366 blkyspanG = tt - bb ;
367
368 left_row_boundaryG = ll ;
369 row_extentG = rr - ll ;
370
371 fprintf(fpoG,"block x-span:%d block y-span:%d\n",blkxspanG,blkyspanG);
372
373 for( cell = 1 ; cell <= lastpadG ; cell++ ) {
374 if( cell > numcellsG - extra_cellsG && cell <= numcellsG ) {
375 continue ;
376 }
377 cx = carrayG[cell]->cxcenter ;
378 cy = carrayG[cell]->cycenter ;
379 cl = carrayG[cell]->tileptr->left;
380 cr = carrayG[cell]->tileptr->right;
381 cb = carrayG[cell]->tileptr->bottom;
382 ct = carrayG[cell]->tileptr->top;
383 if( cx + cr > rr ) {
384 rr = cx + cr ;
385 }
386 if( cx + cl < ll ) {
387 ll = cx + cl ;
388 }
389 if( cy + ct > tt ) {
390 tt = cy + ct ;
391 }
392 if( cy + cb < bb ) {
393 bb = cy + cb ;
394 }
395 }
396 bdxlen = rr - ll ;
397 bdylen = tt - bb ;
398
399 lrtxspanG = rr ;
400 lrtyspanG = tt ;
401
402
403
404 if( Equal_Width_CellsG ) {
405 binpenConG = 0 ;
406 roLenConG = 0 ;
407 } else {
408 binpenConG = 1.0 ;
409 roLenConG = 6.0 ;
410 }
411 calc_init_timeFactor() ;
412 fprintf(fpoG,"Using default value of bin.penalty.control:%f\n",
413 binpenConG ) ;
414 pairArrayG = NULL ;
415
416 funccostG = findcost() ;
417
418 fprintf( fpoG , "bdxlen:%d bdylen:%d\n", bdxlen , bdylen ) ;
419 fprintf( fpoG , "l:%d t:%d r:%d b:%d\n", ll , tt , rr , bb ) ;
420
421 fprintf( fpoG, "\n\n\nTHIS IS THE ROUTE COST OF THE ");
422 fprintf( fpoG, "CURRENT PLACEMENT: %d\n" , funccostG ) ;
423 fprintf( fpoG, "\n\n\nTHIS IS THE PENALTY OF THE ") ;
424 fprintf( fpoG , "CURRENT PLACEMENT: %d\n" , penaltyG ) ;
425 fflush( fpoG ) ;
426
427 if( intelG && !ignore_crossbusesG ) {
428 handle_crossbuses() ;
429 }
430
431 G( init_heat_index() ) ;
432 G( check_graphics(TRUE) ) ;
433
434 fflush(fpoG);
435 fflush(stdout);
436
437 if( orientation_optimizationG ) {
438 costonlyG = FALSE ;
439 }
440
441 if( ECOs_existG ) {
442 costonlyG = TRUE ;
443 printf("ECOs are being incorporated as requested\n");
444 fprintf(fpoG,"ECOs are being incorporated as requested\n");
445 incorporate_ECOs() ;
446 }
447
448 if( costonlyG ) {
449 orientation_optimizationG = TRUE ;
450 utemp() ;
451 } else {
452 init_utemp() ;
453 utemp() ;
454 }
455
456
457 fprintf( fpoG , "\nStatistics:\n");
458 fprintf( fpoG , "Number of Cells: %d\n", numcellsG );
459 fprintf( fpoG , "Number of Pads: %d \n", numtermsG - numpadgrpsG );
460 fprintf( fpoG , "Number of Nets: %d \n", numnetsG ) ;
461 fprintf( fpoG , "Number of Pins: %d \n", maxtermG ) ;
462 fprintf( fpoG , "Number of PadGroups: %d \n", numpadgrpsG );
463 fprintf( fpoG , "Number of Implicit Feed Thrus: %d\n",
464 implicit_feed_countG++ ) ;
465 fprintf( fpoG , "Number of Feed Thrus Added: %d\n", num_feeds_addedS ) ;
466 fprintf( fpoG , "Feed Percentage: %4.2f%%\n",
467 100.0 * (DOUBLE) (num_feeds_addedS * fdWidthG) /
468 (DOUBLE) total_row_lengthG ) ;
469 fprintf( fpoG , "Average Row Separation: %4.2f\n",
470 ave_row_sepS ) ;
471
472 if( intelG ) {
473 fprintf( fpoG , "Checking violations at the end\n");
474 check_violations() ;
475 }
476
477 Yprint_stats(fpoG);
478 /* TWCLOSE(fpoG) ; */ /* Handled by Ymessage_close() in YexitPgm() */
479
480 closegraphics() ;
481
482 YexitPgm(PGMOK);
483
484 return 0;
485 } /* end main */
486
487
initialize_global_router1()488 void initialize_global_router1()
489 {
490
491 INT cell , row ;
492
493 save_cell_xS = (INT *)
494 Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT));
495 save_cell_yS = (INT *)
496 Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT));
497 save_cell_bS = (INT *)
498 Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT));
499 save_cell_cS = (INT *)
500 Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT));
501 save_orientS = (INT *)
502 Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT));
503 save_desireS = (INT *)
504 Ysafe_malloc( (1 + numRowsG) * sizeof(INT));
505 save_orig_desireS = (INT *)
506 Ysafe_malloc( (1 + numRowsG) * sizeof(INT));
507 for( cell = 1 ; cell <= lastpadG ; cell++ ) {
508 save_cell_xS[cell] = carrayG[cell]->cxcenter ;
509 save_cell_yS[cell] = carrayG[cell]->cycenter ;
510 save_cell_bS[cell] = carrayG[cell]->cblock ;
511 save_cell_cS[cell] = carrayG[cell]->cclass ;
512 save_orientS[cell] = carrayG[cell]->corient ;
513 }
514 for( row = 1 ; row <= numRowsG ; row++ ) {
515 save_desireS[row] = barrayG[row]->desire ;
516 save_orig_desireS[row] = barrayG[row]->orig_desire ;
517 }
518
519 return ;
520 }
521
522
initialize_global_router()523 void initialize_global_router()
524 {
525
526 CBOXPTR ptr ;
527 PINBOXPTR pinptr, pin, cnetptr , netptr ;
528 INT cell , row , net ;
529 BOOL coreConnection ;
530
531
532 rebuild_nextpin() ;
533 insert_row(0) ;
534
535 for( cell = 1 ; cell <= lastpadG; cell++ ) {
536 carrayG[cell]->cxcenter = save_cell_xS[cell] ;
537 row = carrayG[cell]->cblock = save_cell_bS[cell] ;
538 if( row != 0 ){
539 carrayG[cell]->cycenter = barrayG[row]->bycenter ;
540 } else {
541 carrayG[cell]->cycenter = save_cell_yS[cell] ;
542 }
543 carrayG[cell]->cclass = save_cell_cS[cell] ;
544 carrayG[cell]->corient = (char) save_orientS[cell] ;
545 }
546
547 for( cell = 1 ; cell <= lastpadG ; cell++ ) {
548 ptr = carrayG[cell] ;
549 if( cell > numcellsG ) {
550 for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ) {
551 if( route_padnets_outsideG ){
552 /* look at each net on the pads to see if it has a */
553 /* connection in the core */
554 coreConnection = FALSE ;
555 for( pin = netarrayG[pinptr->net]->pins; pin; pin = pin->next ){
556 if( pin->cell <= numcellsG ){
557 coreConnection = TRUE ;
558 break ;
559 }
560 }
561 if(!(coreConnection )){
562 /* no connection to the core we can route this in */
563 /* the top channel */
564 pinptr->row = numRowsG + 1 ;
565 pinptr->pinloc = BOTCELL ;
566 /* now go on to the next pin */
567 continue ;
568 }
569 }
570 /* set the pinlocation for the pads and macros */
571 if( ptr->padptr->padside ) {
572 if( pinptr->row > numRowsG ) {
573 pinptr->pinloc = BOTCELL ;
574 } else {
575 pinptr->pinloc = TOPCELL ;
576 }
577 }
578 }
579 } else {
580 for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ) {
581 if( pinptr->typos[(ptr->corient)%2] > 0 ) {
582 pinptr->pinloc = TOPCELL ;
583 } else if(pinptr->typos[(ptr->corient)%2] < 0 ){
584 pinptr->pinloc = BOTCELL ;
585 } else {
586 pinptr->pinloc = NEITHER ;
587 }
588 }
589 }
590 }
591 for( row = 1 ; row <= numRowsG ; row++ ) {
592 barrayG[row]->desire = save_desireS[row] ;
593 barrayG[row]->orig_desire = save_orig_desireS[row] ;
594 }
595 no_row_lengthsG = 1 ;
596 findunlap(0) ;
597 no_row_lengthsG = 0 ;
598
599 return ;
600 }
601
602
execute_global_router()603 void execute_global_router()
604 {
605
606 PINBOXPTR netptr ;
607 INT i , j, row ;
608 INT loop_boundary ;
609 INT temp ;
610 INT core_height ;
611 INT core_width ;
612 INT total_row_height ;
613 INT best_tracks ;
614 DOUBLE area ;
615 DOUBLE best_area ;
616 BOOL decision ;
617
618 char command[LRECL] ;
619
620 if( gate_arrayG && vertical_track_on_cell_edgeG ) {
621 findunlap(0) ;
622 fprintf(fpoG,"Removed %d redundant implicit feeds\n",
623 rm_overlapping_feeds() ) ;
624 }
625
626 loop_boundary = 4 ;
627 routing_loopS = 8 ;
628
629 /* added by Carl 24 Jan 91 */
630 total_row_height = 0 ;
631 for( row = 1 ; row <= numRowsG ; row++ ) {
632 if( pairArrayG[row][0] < 1 ) {
633 fprintf(fpoG,"Trying to fix empty row problem ...") ;
634 printf("Trying to fix empty row problem ...") ;
635 fflush(fpoG);
636 fflush(stdout);
637 even_the_rows(0,FALSE) ;
638 if( pairArrayG[row][0] < 1 ) {
639 /* take even more drastic measures */
640 even_the_rows(0,TRUE) ;
641 }
642 for( row = 1 ; row <= numRowsG ; row++ ) {
643 if( pairArrayG[row][0] < 1 ) {
644 fprintf(fpoG,"Global router cannot handle a row without cells\n");
645 printf("Global router cannot handle a row without cells\n");
646 YexitPgm(PGMFAIL);
647 }
648 }
649 fprintf(fpoG," fixed\n");
650 printf(" fixed\n");
651 fflush(fpoG);
652 fflush(stdout);
653 break ;
654 }
655 /* accumulate the total row height */
656 total_row_height += barrayG[row]->btop - barrayG[row]->bbottom ;
657 }
658 /* end */
659
660 if( swap_netG > 0 ) {
661 /* there are TW_PASS_THRU pins on a swap-able gate */
662 /* we must add them to the implicit list on the relevant cell */
663 netptr = netarrayG[swap_netG]->pins ;
664 for( ; netptr ; netptr = netptr->next ) {
665 install_swap_pass_thrus( netptr ) ;
666 }
667 netarrayG[swap_netG]->ignore = -1 ;
668 }
669
670 if( glob_route_only_crit_netsG ) {
671 route_only_critical_nets() ;
672 } else {
673 elim_nets(1) ; /* nets which are NOT to be global routed */
674 }
675
676 actual_feed_thru_cells_addedG = 0 ;
677
678 initialize_global_router1() ;
679 if( SGGRG ) {
680 initialize_global_router() ;
681 coarseglb() ; /* this function returns "early" if SGGR */
682 /* now place pads for the final time using real cell positions for core */
683 /* boundary to insure we don't have overlap */
684 setVirtualCore( TRUE ) ;
685 placepads() ;
686 output() ;
687 fprintf(fpoG,"\nTimberWolfSC placement is complete; Now ready for execution of SGGR\n");
688
689 Yprint_stats(fpoG);
690
691 closegraphics() ;
692
693 if( twdirS ){
694 Ymessage_mode( M_VERBOSE ) ;
695 M( MSG, NULL, "\n\nPlacement phase complete...\n\n" ) ;
696 M( MSG, NULL, "\n\nNow calling SGGR...\n\n" ) ;
697
698 TWCLOSE(fpoG) ;
699 sprintf( command, "%s/bin/SGGR %s", twdirS, cktNameG ) ;
700 Ysystem( "SGGR", ABORT, command, NULL ) ;
701 }
702 else TWCLOSE(fpoG) ;
703
704 YexitPgm(PGMOK);
705 }
706
707 best_area = DBL_MAX ;
708
709 USER_NEXT_METER() ;
710 USER_SEND_VALUE( routing_loopS ) ;
711 save_abs_min_flagG = absolute_minimum_feedsG ;
712
713 /* now place pads using real cell positions for core */
714 /* boundary to insure we don't have overlap */
715 setVirtualCore( TRUE ) ;
716 placepads() ;
717 /* draw the data */
718 G( check_graphics(TRUE) ) ;
719
720 if( !(placement_improveG )){
721 /* limit the number of cases since we won't move cells */
722 routing_loopS = 4 ;
723 call_row_evenerG = FALSE ;
724 }
725
726 /* from here on, the pad side must be retained during global routing */
727 placepads_retain_side( TRUE ) ;
728 for( j = 1 ; j <= routing_loopS ; j++ ) {
729
730 if( j == routing_loopS || j == loop_boundary ) {
731 absolute_minimum_feedsG = TRUE ;
732 } else {
733 absolute_minimum_feedsG = save_abs_min_flagG ;
734 }
735 if( j <= loop_boundary ) {
736 if( call_row_evenerG ){
737 do_not_even_rowsG = FALSE ;
738 fprintf(fpoG,"TimberWolfSC did call even_the_rows()\n");
739 } else {
740 do_not_even_rowsG = TRUE ;
741 fprintf(fpoG,"TimberWolfSC did NOT call even_the_rows()\n");
742 }
743 } else {
744 do_not_even_rowsG = FALSE ;
745 fprintf(fpoG,"TimberWolfSC did call even_the_rows()\n");
746 }
747 if( absolute_minimum_feedsG ) {
748 fprintf(fpoG,"TimberWolfSC using absolute_minimum_feeds\n");
749 }
750
751 tracksG = 0 ;
752 initialize_global_router() ;
753
754 coarseglb() ;
755 if( globe() == 0 ) {
756 fprintf(fpoG,"WARNING: refine_fixed_placement failed\n");
757 printf("WARNING: refine_fixed_placement failed\n");
758 fflush(fpoG);
759 fflush(stdout);
760 USER_INCR_METER() ;
761 continue ;
762 }
763 if( output_at_densityG ){
764 density() ;
765 }
766 placepads() ;
767 /* draw the data */
768 G( check_graphics(TRUE) ) ;
769
770 core_width = barrayG[1]->desire ;
771 for( row = 2 ; row <= numRowsG ; row++ ) {
772 if( core_width < barrayG[row]->desire ) {
773 core_width = barrayG[row]->desire ;
774 }
775 }
776 core_width += largest_delta_row_lenG ;
777 core_height = tracksG * track_pitchG + total_row_height ;
778 area = (DOUBLE) core_height * (DOUBLE) core_width ;
779 if( area < best_area ){
780 best_area = area ;
781 decision = TRUE ;
782 best_tracks = tracksG ;
783 } else {
784 decision = FALSE ;
785 }
786
787 if( decision ) {
788 fprintf(fpoG,"THIS G. ROUTING IS BEING SAVED AS BEST SO FAR\n");
789 fprintf(fpoG,"\nFINAL NUMBER OF ROUTING TRACKS: %d\n\n",
790 tracksG);
791 for( i = 1 ; i <= numChansG ; i++ ) {
792 fprintf(fpoG,"MAX OF CHANNEL:%3d is: %3d\n", i
793 , maxTrackG[i]);
794 }
795 outpins() ;
796 output() ;
797 print_paths() ;
798 best_tracks = tracksG ;
799 /* save this for final statistics */
800 num_feeds_addedS = actual_feed_thru_cells_addedG ;
801 /* save the effective row separation */
802 ave_row_sepS = (DOUBLE) (tracksG * track_pitchG) /
803 (DOUBLE) total_row_height ;
804 }
805 globe_free_up() ;
806 final_free_up() ;
807 USER_INCR_METER() ;
808 }
809 fprintf(fpoG,"\n\n***********************************************\n");
810 fprintf(fpoG,"*ACTUAL* FINAL NUMBER OF ROUTING TRACKS: %d\n",
811 best_tracks);
812 fprintf(fpoG,"***********************************************\n\n");
813 fflush(fpoG);
814 fprintf(stdout,"\n\n***********************************************\n");
815 fprintf(stdout,"*ACTUAL* FINAL NUMBER OF ROUTING TRACKS: %d\n",
816 best_tracks);
817 fprintf(stdout,"***********************************************\n\n");
818 fflush(stdout);
819
820
821 return ;
822 }
823
824
825
826
827
init_utemp()828 void init_utemp()
829 {
830
831 INT row , bin ;
832
833 bin_configG = (INT **) Ysafe_malloc( (1 + numRowsG) * sizeof(INT *) ) ;
834 for( row = 1 ; row <= numRowsG ; row++ ) {
835 bin_configG[row] = (INT *) Ysafe_malloc( (1 + numBinsG) * sizeof(INT) );
836 for( bin = 0 ; bin <= numBinsG ; bin++ ) {
837 bin_configG[row][bin] = 0 ;
838 }
839 }
840
841 return ;
842 }
843
844
845
846
847
install_swap_pass_thrus(PINBOXPTR netptr)848 void install_swap_pass_thrus(PINBOXPTR netptr )
849 {
850
851 CBOXPTR ptr ;
852 IPBOXPTR imptr ;
853 PINBOXPTR termptr ;
854 INT impxpos , impypos , cell ;
855 char *pname ;
856
857 /* code borrowed from readcell() */
858 /* fscanf( fp , " %d %d " , &impxpos , &impypos ) ; */
859 /* impxpos and impypos are rel. to cell center -- to
860 get these we need to find the relevant pin on
861 the cell */
862 cell = netptr->cell ;
863 ptr = carrayG[cell] ;
864 for( termptr = ptr->pins ;termptr ; termptr = termptr->nextpin ) {
865 if( termptr == netptr ) {
866 impxpos = termptr->txpos[0] ;
867 impypos = termptr->typos[0] ;
868 fprintf(fpoG,"FOUND the connection in install_swap...\n");
869 break ;
870 }
871 }
872 imptr = ( IPBOXPTR )Ysafe_malloc( sizeof( IPBOX ) ) ;
873 imptr->pinname = (char *) Ysafe_malloc(
874 (strlen( netptr->pinname ) + 1 ) *
875 sizeof( char ) ) ;
876 imptr->eqpinname = (char *) Ysafe_malloc(
877 (strlen( netptr->eqptr->pinname ) + 1 ) *
878 sizeof( char ) ) ;
879 sprintf( imptr->pinname , "%s" , netptr->pinname ) ;
880 sprintf( imptr->eqpinname , "%s" , netptr->eqptr->pinname ) ;
881
882 imptr->txpos = impxpos ;
883 imptr->cell = cell ;
884 imptr->terminal = ++last_pin_numberG ;
885 imptr->next = ptr->imptr ;
886 ptr->imptr = imptr ;
887
888 if( impypos > 0 ) { /* swap the pinnames */
889 pname = imptr->pinname ;
890 imptr->pinname = imptr->eqpinname ;
891 imptr->eqpinname = pname ;
892 }
893
894 return ;
895 }
896
incorporate_ECOs()897 void incorporate_ECOs()
898 {
899
900 PINBOXPTR termptr , netptr ;
901 INT *nets, xspot, yspot , i , net , cell , count, maxpins ;
902 INT orient , row , xmin, xmax, ymin, ymax , x , y ;
903
904 xspot = 0 ;
905 yspot = 0 ;
906 maxpins = get_max_pin() ;
907 nets = (INT *) Ysafe_calloc( maxpins+1, sizeof(INT) ) ;
908 for( cell = 1 ; cell <= numcellsG ; cell++ ) {
909 if( carrayG[cell]->ECO_flag == 1 ) {
910 printf("ECO added cell being processed: <%s> ",
911 carrayG[cell]->cname ) ;
912 fprintf(fpoG,"ECO added cell being processed: <%s> ",
913 carrayG[cell]->cname ) ;
914 termptr = carrayG[cell]->pins ;
915 for( ; termptr ; termptr = termptr->nextpin ) {
916 net = termptr->net ;
917 for( i = 0 ; nets[i] != 0 ; i++ ) {
918 if( nets[i] == net ) {
919 break ;
920 }
921 }
922 if( nets[i] == 0 ) {
923 nets[i] = net ;
924 }
925 }
926 /* nets[] is the list of unique nets for the cell */
927 count = 0 ;
928 for( i = 0 ; nets[i] != 0 ; i++ ) {
929 /* compute bounding boxes of the unique nets,
930 taking care to ignore ECO_added cells */
931 /* ************ updated on 12/21/90 by Carl */
932 net = nets[i] ;
933 if( !(netptr = netarrayG[net]->pins)) {
934 continue ;
935 }
936 if( carrayG[ netptr->cell ]->ECO_flag == 1 ) {
937 /* don't let ECO added cells influence the decision */
938 xmin = INT_MAX ;
939 xmax = INT_MIN ;
940 ymin = INT_MAX ;
941 ymax = INT_MIN ;
942 } else {
943 xmin = xmax = netptr->xpos ;
944 ymin = ymax = netptr->ypos ;
945 }
946 count = 0 ;
947 for( netptr = netptr->next ; netptr ; netptr = netptr->next ) {
948 if( carrayG[ netptr->cell ]->ECO_flag == 1 ) {
949 continue ;
950 /* don't let ECO_added cells influence the decision */
951 }
952 x = netptr->xpos ;
953 y = netptr->ypos ;
954 if( x < xmin ) {
955 xmin = x ;
956 }
957 if( x > xmax ) {
958 xmax = x ;
959 }
960 if( y < ymin ) {
961 ymin = y ;
962 }
963 if( y > ymax ) {
964 ymax = y ;
965 }
966 }
967 /* ************ */
968 xspot += (xmax + xmin) / 2 ;
969 yspot += (ymax + ymin) / 2 ;
970 count++ ;
971 }
972 if( count >= 1 ){
973 xspot /= count ;
974 yspot /= count ;
975 } else {
976 fprintf( stderr, "Incorrectly specified ECO cell:%s",
977 carrayG[cell]->cname ) ;
978 }
979
980 for( row = 1 ; row <= numRowsG ; row++ ) {
981 if( barrayG[row]->bycenter > yspot ) {
982 break ;
983 }
984 }
985 if( row > numRowsG ) {
986 row = numRowsG ;
987 } else if( row > 1 ) {
988 if( barrayG[row]->bycenter - yspot >
989 yspot - barrayG[row-1]->bycenter ) {
990 row-- ;
991 }
992 }
993 yspot = barrayG[row]->bycenter ;
994
995 carrayG[cell]->cxcenter = xspot ;
996 carrayG[cell]->cycenter = yspot ;
997 carrayG[cell]->cblock = row ;
998 carrayG[cell]->ECO_flag = 0 ;
999
1000 printf(" ... placed in row:%d x:%d\n", row , xspot ) ;
1001 fprintf(fpoG," ... placed in row:%d x:%d\n", row , xspot ) ;
1002
1003 orient = carrayG[cell]->corient ;
1004 for( termptr = carrayG[cell]->pins ; termptr ;
1005 termptr = termptr->nextpin ) {
1006 termptr->xpos = termptr->txpos[ orient/2 ] + xspot ;
1007 termptr->ypos = termptr->typos[ orient%2 ] + yspot ;
1008 }
1009 }
1010 }
1011
1012 return ;
1013 }
1014
1015
1016 /* give user correct syntax */
syntax()1017 void syntax()
1018 {
1019 M(ERRMSG,NULL,"\n" ) ;
1020 M(MSG,NULL,"Incorrect syntax. Correct syntax:\n");
1021 sprintf( YmsgG,
1022 "\nTimberWolfSC [-dnw] designName [windowId] \n" ) ;
1023 M(MSG,NULL,YmsgG ) ;
1024 M(MSG,NULL,"\twhose options are zero or more of the following:\n");
1025 M(MSG,NULL,"\t\td - prints debug info and performs extensive\n");
1026 M(MSG,NULL,"\t\t error checking\n");
1027 M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n");
1028 M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n");
1029 M(MSG,NULL,"\t\tv - verbose mode - echo output to the screen\n");
1030 M(MSG,NULL,"\t\tw - parasite mode - user must specify windowId\n");
1031 YexitPgm(PGMFAIL);
1032 } /* end syntax */
1033