/* cleanup after parsing nets */ cleanup_nets() { if( abortFlagS ){ closegraphics() ; YexitPgm( FAIL ) ; } build_path_array() ; init_path_set() ; init_net_set() ; add_paths_to_cells() ; } /* end cleanup_nets */
finalout() { INT c ; INT bbtop, bbbottom, bbleft, bbright ; /* dump the results of the placement to graphics file */ G( graphics_dump() ) ; G( TWsetMode(1) ) ; G( draw_the_data() ) ; G( TWsetMode(0) ) ; /* we known wire area at this point don't need to estimate */ turn_wireest_on(FALSE) ; /* let the user know which pins we couldn't place */ set_pin_verbosity( TRUE ) ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ if( doGraphicsG && wait_for_userG ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; } savewolf( TRUE ) ; /* for debug purposes force save to occur */ if( scale_dataG > 1 ){ /* end of the line for scaled case - will return to parent to continue using saved placement. */ closegraphics() ; YexitPgm( PGMOK ) ; } grid_cells() ; /* force cells to grid locations */ compact(VIOLATIONSONLY); /* remove cell overlap */ /* if this is a partitioning run determine row placement */ if( doPartitionG && !(quickrouteG) ){ set_determine_side( FALSE ) ; /* allow SC to pick side */ G( set_graphic_context( PARTITION_PLACEMENT ) ) ; config_rows() ; print_paths() ; /* print path information */ Output( 0 ) ; return ; } /* do final placement of pads using virtual core to insure pads */ /* are outside of core */ setVirtualCore( TRUE ) ; placepads() ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ check_graphics() ; if( !scale_dataG ){ /* reload bins to get new overlap penalty */ loadbins(FALSE) ; /* wireArea not known */ } prnt_cost( "\nFINAL PLACEMENT RESULTS AFTER VIOLATION REMOVAL ARE:\n" ) ; print_paths() ; /* print path information */ Output( 0 ) ; if( doCompactionG > 0 || quickrouteG ) { gmain( CHANNELGRAPH ) ; rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; if( quickrouteG ){ return ; } for( c = 1 ; c <= doCompactionG ; c++ ) { funccostG = findcost() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d begins with:\n", c ) ; prnt_cost( YmsgG ) ; wirecosts() ; grid_cells() ; /* force cells to grid locations */ compact(COMPACT); /* remove white space */ reorigin() ; check_graphics() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d after cost:\n", c ) ; prnt_cost( YmsgG ) ; Output( c ) ; gmain( CHANNELGRAPH ) ; if( c == doCompactionG ){ rmain( CONSTRAINTS ) ; } else { rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; } } /* end compaction - global route loop */ } else { if( doChannelGraphG ) { gmain( CHANNELGRAPH ) ; } if( doGlobalRouteG ) { rmain( CONSTRAINTS ) ; } } prnt_cost("\nTIMBERWOLFMC FINAL RESULTS ARE:\n" ) ; return ; } /* end finalout */
ERRORPTR buildYGraph() { int i ; /* counter */ int overlapx ; /* overlap conditions in x direction */ int overlapy ; /* overlap conditions in y direction */ int sortbyYX() ; /* sort the tiles Y then X */ int left, right ; /* coordinates of tiles */ int bottom, top ; /* coordinates of tiles */ BOOL firstPick ; /* TRUE if first picket which matches */ BOOL possibleEdgetoSource; /* TRUE if this could be edge to source */ BOOL *yancestorB ; /* TRUE for a cell if cell has B ancestors */ BOOL *yancestorF ; /* TRUE for a cell if cell has F ancestors */ COMPACTPTR candidate ; /* this is the tile in question */ COMPACTPTR t ; /* this is the current picket */ PICKETPTR freepick ; /* used to free the pickets at the end */ PICKETPTR curPick ; /* traverse the pickets */ PICKETPTR lowerLimit ; /* first picket tile overlaps/touches */ PICKETPTR upperLimit ; /* last picket tile overlaps or touches */ ERRORPTR errorPtr ; /* form a list of errors to be processed*/ ERRORPTR lasterror ; /* last error in list */ ERRORPTR violations ; /* head of the error list */ /* initialize error list */ lasterror = NULL ; violations = NULL ; yancestorB = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; yancestorF = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; inityPicket() ; /* yGraphG is now initialized */ /* sort by ymin xmin of the bounding box */ /* we give it two chances - second time we expand core if necessary */ for( i=0; i <= 1 ; i++ ){ Yquicksort((char *)yGraphG,numtilesG+2,sizeof(COMPACTPTR),sortbyYX); if( yGraphG[SOURCE]->cell == YSOURCEC && yGraphG[SINK]->cell == YSINKC ){ break ; } else { find_core( &left, &right, &bottom, &top ) ; /* expand core region */ t = tileNodeG[YSOURCE] ; t->b = bottom ; t->t = t->b ; t = tileNodeG[YSINK] ; t->b = top ; t->t = t->b ; } } if( yGraphG[SOURCE]->cell != YSOURCEC || yGraphG[SINK]->cell != YSINKC ){ M( ERRMSG, "ycompact", "Fatal error in configuration\n" ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm( PGMFAIL ) ; } for( i=1 ; i<= numtilesG ; i++ ){ firstPick = TRUE ; lowerLimit = NULL ; upperLimit = NULL ; possibleEdgetoSource = FALSE ; candidate = yGraphG[i] ; /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ overlapx = projectX( curPick->pt2.lft, curPick->pt1.rght, candidate->l, candidate->r) ; if( overlapx > 0 ){ /* allow touching */ /* save span of overlap */ if( firstPick ){ lowerLimit = curPick ; firstPick = FALSE ; } upperLimit = curPick ; t = tileNodeG[curPick->node] ; /* multiple tile case - no error possible */ if( candidate->cell == t->cell ){ continue ; } /* check for errors */ overlapy = projectY( t->b, t->t, candidate->b, candidate->t ) ; if( overlapx > 0 && overlapy > 0 ){ /* save violations - add to violation list */ if( lasterror ){ errorPtr = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; lasterror->next = errorPtr ; lasterror = errorPtr ; } else { violations = errorPtr = lasterror = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; } errorPtr->next = NULL ; errorPtr->nodeI = candidate->node ; errorPtr->nodeJ = t->node ; /* for debug only : sprintf( YmsgG, Overlap detected: cell %d and cell %d\n", candidate->cell, t->cell ) ; M( MSG, NULL, YmsgG ) ; */ } ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; /* form edge on only first occurance of cell */ if( t->node == numtilesG+2 ){ /* source node */ /* delay adding this edge */ possibleEdgetoSource = TRUE ; } else { formyEdge( t->node, candidate->node ) ; } } else if( upperLimit ){ /* we are past the upper limit so break & save time */ break ; } } ASSERT( lowerLimit, "compact", "lowerLimit is NULL" ) ; ASSERT( upperLimit, "compact", "lowerLimit is NULL" ) ; if( possibleEdgetoSource && yancestorF[candidate->cell] == FALSE ){ /* no need to make an edge to source if we already */ /* have an ancestor. Always make sure it is one of the lowest */ /* nodes of the multi-tiled cell */ formyEdge( numtilesG+2, cellarrayG[candidate->cell]->ylo ) ; yancestorF[candidate->cell] = TRUE ; } update_ypicket( i, lowerLimit, upperLimit ) ; } /* end for loop */ /* process sink last */ /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ /* remaining pickets must necessarily overlap sink */ t = tileNodeG[curPick->node] ; ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; if( curPick->node != numtilesG+2 && /* avoid the source */ yancestorB[t->cell] == FALSE ){ /* no parents */ formyEdge( cellarrayG[t->cell]->yhi, yGraphG[last_tileG]->node ) ; yancestorB[t->cell] = TRUE ; } } /* now add multiple tile edges to graph. Precomputed in multi.c */ add_mtiles_to_ygraph() ; cleanupGraph( YFORWARD ) ; cleanupGraph( YBACKWARD ) ; Ysafe_free( yancestorB ) ; Ysafe_free( yancestorF ) ; /* delete all pickets */ for( curPick = leftPickS; curPick ; ) { freepick = curPick ; curPick = curPick->next ; Ysafe_free( freepick ) ; } return( violations ) ; } /* end buildYGraph */