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