/* initialization before parsing nets */ init_nets() { YHASHPTR getNetTable() ; numpathsG = 0 ; netTableS = getNetTable() ; net_cap_matchG = (INT **) Ysafe_calloc( numnetsG+1,sizeof(INT *) ) ; net_res_matchG = (INT **) Ysafe_calloc( numnetsG+1,sizeof(INT *) ) ; } /* end init_nets */
outpin() { INT net ; /* counter */ char filename[LRECL] ; /* open this filename for writing */ NETBOXPTR netptr ; /* current net info */ PINBOXPTR pinptr ; /* current pin info */ sprintf( filename, "%s.mpin", cktNameG ) ; fpS = TWOPEN( filename , "w", ABORT ) ; output_alreadyS = (BOOL *) Ysafe_calloc( numpinsG+1, sizeof(BOOL) ) ; output_typeS = NONE ; for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; if( netptr->numpins <= 1 ){ /* no need to global route 1 pin nets */ continue ; } if( netptr->analog_info ){ process_analog_net( netptr ) ; output_typeS |= ANALOG ; continue ; } fprintf(fpS,"net %s\n", netptr->nname ) ; for( pinptr = netptr->pins ;pinptr;pinptr = pinptr->next ) { output_pin( pinptr ) ; output_typeS |= DIGITAL ; } fprintf( fpS,"\n" ) ; } output_matches() ; TWCLOSE(fpS); return ; } /* end outpins */
findrcost() { SEGBOXPTR segptr ; CHANGRDPTR gdptr ; DENSITYPTR *hdptr , headptr , dptr ; INT chan ; INT trackG , max_trk , k ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ initial_tracks( segptr ) ; } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } DboxHeadG = ( DENSITYPTR ** )Ysafe_calloc( numChansG + 1, sizeof( DENSITYPTR * ) ) ; maxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; nmaxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; max_tdensityG = 0 ; tracksG = 0 ; if( uneven_cell_heightG ) { set_cedgebin( ) ; reset_track( ) ; } for( chan = 1 ; chan <= numChansG ; chan++ ) { max_trk = 0 ; for( gdptr = BeginG[ chan ] ; gdptr != GRDNULL ; gdptr = gdptr->nextgrd ) { if( gdptr->tracks > max_trk ) { max_trk = gdptr->tracks ; } } maxTrackG[ chan ] = max_trk ; if( max_trk > max_tdensityG ) { max_tdensityG = max_trk ; } tracksG += max_trk ; } printf(" the starting value of tracks = %4d\n" , tracksG ) ; k = max_tdensityG + 100 ; for( chan = 1 ; chan <= numChansG ; chan++ ) { DboxHeadG[ chan ] = hdptr = ( DENSITYPTR *)Ysafe_calloc( k + 1, sizeof( DENSITYPTR) ) ; for( trackG = 0 ; trackG <= k ; trackG++ ) { hdptr[trackG] = ( DENSITYPTR )Ysafe_calloc( 1, sizeof(DENSITYBOX)); } for( gdptr = BeginG[ chan ] ; gdptr ; gdptr = gdptr->nextgrd ) { trackG = gdptr->tracks ; gdptr->dptr = dptr = ( DENSITYPTR )Ysafe_calloc( 1,sizeof(DENSITYBOX) ) ; headptr = hdptr[trackG] ; if( headptr->next ) { dptr->next = headptr->next ; dptr->next->back = dptr ; headptr->next = dptr ; dptr->back = headptr; } else { headptr->next = dptr ; dptr->back = headptr ; } dptr->grdptr = gdptr ; } } }
feedest() { DOUBLE ratio ; INT net , row , toprow , botrow, maxdesire ; DBOXPTR dimptr ; PINBOXPTR ptr ; fd_estimateS = (DOUBLE *)Ysafe_calloc( numChansG + 1, sizeof(DOUBLE) ) ; min_feedS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; row_flagS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; rowfeed_penaltyG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT) ) ; est_min_ratioS = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; maxdesire = barrayG[1]->desire ; for( row = 2 ; row <= numRowsG ; row++ ) { if( maxdesire < barrayG[row]->desire ) { maxdesire = barrayG[row]->desire ; } } ratio = (DOUBLE)(maxdesire) / (DOUBLE)( barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ) ; ratio = 1.0 / ratio ; /* to fix Kai-Win's bug */ if( absolute_minimum_feedsG ) { if( ratio >= 1.0 ) { chip_width_penaltyS = barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ; } else { chip_width_penaltyS = maxdesire ; } } else { /* chip_width_penaltyS = 2.0 * (DOUBLE) rowHeightG ; */ chip_width_penaltyS = 6.9 * (DOUBLE) rowHeightG ; } if( !absolute_minimum_feedsG ) { add_Lcorner_feedG = TRUE ; /* Carl */ for( row = 1 ; row <= numRowsG ; row++ ) { if( FeedInRowG[row] == 0 ) { add_Lcorner_feedG = FALSE ; break ; } } /* Carl */ } else { add_Lcorner_feedG = FALSE ; } for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( !(dimptr->pins) ) { continue ; } switch( dimptr->numpins ) { case 0 : case 1 : break ; case 2 : ptr = dimptr->pins ; toprow = ptr->row ; botrow = ptr->next->row ; if( toprow > botrow ) { for( row = botrow + 1 ; row < toprow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } else if( toprow < botrow ) { for( row = toprow + 1 ; row < botrow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; case 3 : case 4 : case 5 : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; default : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow]++ ; fd_estimateS[toprow]++ ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; } } estimate_pass_thru_penalty( 1 , numRowsG ) ; }
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 */
postFeedAssgn() { INT net , i , row , botrow , toprow , last_i ; SEGBOXPTR segptr , nextseg ; PINBOXPTR netptr , nextptr , st_head , stptr ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } netsegHeadG[net]->next = NULL ; netptr = netarrayG[net]->pins ; st_head = steinerHeadG[net] ; if( st_head->next ) { /* there are steiner point for this net */ for( stptr = st_head ; stptr->next ; ) { nextptr = stptr->next ; if( nextptr->terminal == 0 || !nextptr->flag ) { /* steiner point in bottom pads or top pads or they are pseudo steiner point. */ stptr->next = nextptr->next ; Ysafe_free( nextptr ) ; } else { stptr = nextptr ; } } stptr->next = netptr ; netarrayG[net]->pins = st_head->next ; /* put all the netbox of the steiner point into the netarrayG linked lists. */ } Ysafe_free( steinerHeadG[net] ) ; } Ysafe_free( steinerHeadG ) ; maxpin_numberS = 0 ; pins_at_rowS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 2 ) { continue ; } botrow = numChansG ; toprow = 0 ; for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { row = netptr->row ; pins_at_rowS[ row ]++ ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } } for( row = botrow ; row <= toprow ; row++ ) { if( pins_at_rowS[row] > maxpin_numberS ) { maxpin_numberS = pins_at_rowS[row] ; } pins_at_rowS[row] = 0 ; } } maxpin_numberS += 3 ; count_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; father_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; root_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; stack_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; first_indexS = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; vertex_G = (PINBOXPTR *)Ysafe_malloc( 2 * Max_numPinsG * sizeof(PINBOXPTR) ); last_i = maxpin_numberS * maxpin_numberS * numRowsG - 1 ; edge_dataS = (EDGE_COST *)Ysafe_malloc( ( last_i + 1 ) * sizeof(EDGE_COST) ) ; for( i = 1 ; i <= last_i ; i++ ) { edge_dataS[i] = (EDGE_COST)Ysafe_malloc( sizeof(EDGE_COST_BOX) ); } z_S = (PINBOXPTR **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(PINBOXPTR *) ) ; for( i = 0 ; i <= numChansG ; i++ ) { z_S[i] = (PINBOXPTR *)Ysafe_malloc( maxpin_numberS * sizeof(PINBOXPTR) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 1 ) { continue ; } rebuild_netgraph( net ) ; /* find minimum cost tree connection from all the pins of a net */ } }