void sortpins() { INT j , n , cell ; CELLBOXPTR ptr ; PINBOXPTR pin, *xpptr ; /* static INT comparePin() ;*/ INT maxpins ; /* find maximum number of pins on a cell for allocation */ maxpins = INT_MIN ; for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; maxpins = MAX( ptr->numpins, maxpins ) ; } /* allocate array for sort */ xpptr = (PINBOXPTR *) Ysafe_malloc((maxpins+1) * sizeof(PINBOXPTR) ) ; /* now go thru all cells sorting pins */ for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; n = 0 ; for( pin = ptr->pinptr ; pin ; pin = pin->nextpin ) { xpptr[ n++ ] = pin ; } /* net number then by pin name */ Yquicksort( (char *)xpptr, n, sizeof(PINBOXPTR),comparePin ) ; /* terminate list */ xpptr[ n ] = NIL(PINBOXPTR) ; ptr->pinptr = xpptr[ 0 ] ; for( j = 0 ; j < n ; j++ ) { xpptr[j]->nextpin = xpptr[j+1] ; } } Ysafe_free( xpptr ) ; } /* end sortpins */
sortpin() { INT cell ; /* current cell */ INT maxpins ; /* maximum numpins over all pins */ CBOXPTR ptr ; /* current cell */ BOOL pin_groups ; /* true if swappable gates occur */ /* find the maximum number of pins on a cell for allocation */ /* also see if pin groups exist on any of the cells */ maxpins = INT_MIN ; pin_groups = FALSE ; for( cell = 1; cell <= numcellsG; cell++ ){ ptr = carrayG[cell] ; maxpins = MAX( ptr->numterms, maxpins ) ; if( ptr->num_pin_group > 0 ){ pin_groups = TRUE ; } } sortArrayS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); for( cell = 1 ; cell <= numcellsG ; cell++ ) { sortpin1( cell ) ; } if( pin_groups ){ /* we we have swappable gates we need to create second array */ /* and leave first one allocated */ sortArraySwapS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); } else { /* in the normal case we are done with sorting free array */ Ysafe_free( sortArrayS ) ; } } /* end sortpin */
void output() { FILE *fpp1 , *fpp2 ; INT locx , locy , height , width ; INT xloc , i , cell , block , orient ; INT num ; INT xloc2 , yloc2 , yloc ; INT *array , desire , k , limit ; INT left , right , bottom , top , end ; INT *deleted_feeds ; INT eliminated_feeds ; char filename[LRECL] , ctmp[32] ; CBOXPTR cellptr ; TIBOXPTR tptr ; PADBOXPTR pptr ; /* added on 06/01/90 Sury */ INT length; INT row ; char instance_name[LRECL], tmp_name[LRECL], *tmp_string; deleted_feeds = (INT *) Ysafe_malloc( numcellsG * sizeof(INT) ) ; eliminated_feeds = 0 ; sprintf( filename , "%s.pl1" , cktNameG ) ; fpp1 = TWOPEN( filename , "w", ABORT ) ; sprintf( filename , "%s.pl2" , cktNameG ) ; fpp2 = TWOPEN( filename , "w", ABORT ) ; for( block = 1 ; block <= numRowsG ; block++ ) { left = barrayG[block]->bxcenter + barrayG[block]->bleft ; right = barrayG[block]->bxcenter + barrayG[block]->bright ; bottom = barrayG[block]->bycenter + barrayG[block]->bbottom ; top = barrayG[block]->bycenter + barrayG[block]->btop ; if( restartG == 0 && costonlyG == 1 ) { desire = barrayG[block]->desire ; } else { if( pairArrayG[block][0] > 0 ) { cell = pairArrayG[block][ pairArrayG[block][0] ] ; end = carrayG[cell]->cxcenter + carrayG[cell]->tileptr ->right ; desire = end - left ; } else { desire = 0 ; } } if( barrayG[block]->borient > 0 ) { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, left + desire, top ) ; } else { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, right, bottom + desire ) ; } num = pairArrayG[block][0] ; if( num == 0 ) { continue ; } array = pairArrayG[block] + 1 ; for( i = 0 ; i < num ; i++ ) { cell = array[ i ] ; cellptr = carrayG[ cell ] ; if( cellptr->clength == 0 ){ continue ; } if( strcmp( cellptr->cname , "TW_EXCEPT" ) == 0 ) { continue ; } if( stand_cell_as_gate_arrayG ) { if( strcmp( cellptr->cname , "GATE_ARRAY_SPACER" ) == 0 ) { continue ; } } if( unused_feed_name_twspacerG ) { if( strncmp(cellptr->cname,"twfeed",6) == STRINGEQ ) { if( tearrayG[cellptr->imptr->terminal] == NULL ) { strcpy( ctmp , cellptr->cname ) ; cellptr->cname = (char *) Ysafe_realloc( cellptr->cname, (strlen(cellptr->cname)+3) * sizeof(char) ) ; sprintf( cellptr->cname , "%s%s" , "twspacer", strpbrk(ctmp, "0123456789") ) ; } } } orient = cellptr->corient ; xloc = cellptr->cxcenter + cellptr->tileptr->left ; yloc = cellptr->cycenter + cellptr->tileptr->bottom ; xloc2 = cellptr->tileptr->right - cellptr->tileptr->left ; yloc2 = cellptr->tileptr->top - cellptr->tileptr->bottom ; /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #else fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #endif } } if( deleted_feeds[0] > 0 ) { fprintf(fpoG,"Confirming number of eliminated feeds:%d\n", eliminated_feeds ) ; } /* now output the pads and macros */ for( i = numcellsG + 1 ; i <= lastpadG ; i++ ) { cellptr = carrayG[ i ] ; orient = cellptr->corient ; tptr = cellptr->tileptr ; left = tptr->left ; right = tptr->right ; bottom = tptr->bottom ; top = tptr->top ; YtranslateT( &left, &bottom, &right, &top, orient ) ; locx = cellptr->cxcenter + left ; locy = cellptr->cycenter + bottom ; height = top - bottom ; width = right - left ; /* determine row */ pptr = cellptr->padptr ; if( pptr->macroNotPad ){ row = 0 ; } else { switch( pptr->padside ){ case L: row = - 1 ; break ; case T: row = -4 ; break ; case R: row = - 2 ; break ; case B: row = - 3 ; break ; default: M(ERRMSG,"output", "Unknown padside\n" ) ; } } #ifndef DEC /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; #else /* normal case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; #endif #else /* DEC case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; #endif } TWCLOSE( fpp1 ) ; TWCLOSE( fpp2 ) ; if( create_new_cel_fileG ) { create_cel_file() ; } Ysafe_free( deleted_feeds ) ; return ; }
void final_free_up() { INT i, j, k, row, pin, net, cell, chan, track ; CBOXPTR cellptr ; DBOXPTR dimptr ; PINBOXPTR ptr, nextptr ; ADJASEGPTR adj, nextadj ; SEGBOXPTR segptr, nextseg ; CHANGRDPTR gdptr, nextgrd ; DENSITYPTR *hdptr ; IPBOXPTR imptr ; FEED_DATA *feedptr ; Ysafe_free( FeedInRowG ) ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( impFeedsG[row] ) ; } Ysafe_free( impFeedsG ) ; for( i = 1 ; i <= numRowsG ; i++ ) { feedptr = feedpptrG[i] ; for( j = 1 ; j <= chan_node_noG ; j++ ) { Ysafe_free( feedptr[j] ) ; } Ysafe_free( feedpptrG[i] ) ; } Ysafe_free( feedpptrG ) ; k = max_tdensityG + 100 ; for( chan = 1 ; chan <= numChansG ; chan++ ) { Ysafe_free( BeginG[chan]->netptr ) ; Ysafe_free( EndG[chan]->netptr ) ; for( gdptr = BeginG[chan] ; gdptr ; gdptr = nextgrd ) { nextgrd = gdptr->nextgrd ; Ysafe_free( gdptr->dptr ) ; Ysafe_free( gdptr ) ; } hdptr = DboxHeadG[chan] ; for( track = 0 ; track <= k ; track++ ) { Ysafe_free( hdptr[track] ) ; } Ysafe_free( DboxHeadG[chan] ) ; } Ysafe_free( BeginG ) ; Ysafe_free( EndG ) ; Ysafe_free( DboxHeadG ) ; Ysafe_free( maxTrackG ) ; Ysafe_free( nmaxTrackG ) ; k = maxtermG + 2 * numChansG ; for( pin = 1 ; pin <= k ; pin++ ) { Ysafe_free( TgridG[pin] ) ; } Ysafe_free( TgridG ) ; /* Not needed as this is done in findunlap.c for( i = 1 ; i <= numRowsG ; i++ ) { Ysafe_free( pairArrayG[i] ) ; } Ysafe_free( pairArrayG ) ; pairArrayG = NULL ; */ for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; imptr = cellptr->imptr ; if( imptr ) { for( ; imptr->next; imptr = imptr->next ) { if( imptr->next->cell != cell ) break ; } imptr->next = NULL ; } } fprintf( fpoG,"Actual # of Feed Cells Added:\t%d\n\n\n", actual_feed_thru_cells_addedG ) ; k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ; for( cell = numcellsG + numtermsG + 1 ; cell <= k ; cell++ ) { cellptr = carrayG[cell] ; cellptr->imptr->next = NULL ; Ysafe_free( cellptr->cname ) ; Ysafe_free( cellptr->tileptr ) ; Ysafe_free( cellptr->imptr->pinname ) ; Ysafe_free( cellptr->imptr->eqpinname ) ; Ysafe_free( cellptr->imptr ) ; Ysafe_free( carrayG[cell] ) ; carrayG[cell] = NULL ; } actual_feed_thru_cells_addedG = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net] ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } dimptr = netarrayG[net] ; if( !dimptr->pins ) { continue ; } if( dimptr->pins->terminal > TotRegPinsG ) { for( ptr = dimptr->pins ; ptr ; ptr = nextptr ) { nextptr = ptr->next ; for( adj = ptr->adjptr ; adj ; adj = nextadj ) { nextadj = adj->next ; Ysafe_free( adj ) ; } Ysafe_free( ptr->eqptr ) ; if( nextptr->terminal <= TotRegPinsG ) break ; } dimptr->pins = nextptr ; } for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) { for( adj = ptr->adjptr->next ; adj ; adj = nextadj ) { nextadj = adj->next ; Ysafe_free( adj ) ; } ptr->adjptr->next = NULL ; } } Ysafe_free( netsegHeadG ) ; }
void construct_segment() { register int i ; register int j ; register int v ; register int v1 ; register int v2 ; int count ; int degree ; int Degree ; int order ; LISTPTR Pnode ; MDATAPTR Pcurrent ; /* vertex of its adjdacent list is searched */ MDATAPTR Plast ; /* last vertex in the segment tree list */ MDATAPTR Pparent ; /* start of the path to current vertex */ MDATAPTR Pnew ; /* temporary pointer for new vertex */ PINPTR Pfirst ; PINPTR Ppin ; STACKPTR Pstack ; STACKPTR Psteiner ; /*********************************************************** * Label all the vertices in the minimum Steiner tree with * one and label the others with zero. ***********************************************************/ numnode = numpins ; numtree_e = 0 ; for (i=1; i<=numnodes; i++) { garray[i]->status = FALSE ; iarray[i] = 0 ; } for (i=numnodes+1; i<=totnodes; i++) { garray[i]->status = TRUE ; iarray[i] = 0 ; } for (i=1; i<=totedges; i++) { earray[i]->numpins = FALSE ; if (earray[i]->intree&MIN_MASK) { earray[i]->numpins = TRUE ; jarray[++numtree_e] = i ; v1 = earray[i]->node[0] ; v2 = earray[i]->node[1] ; if (!garray[v1]->status) { numnode++ ; garray[v1]->status = TRUE ; } if (!garray[v2]->status) { numnode++ ; garray[v2]->status = TRUE ; } } } /*********************************************************** * Initialize field key of parray to be zero. ***********************************************************/ for (i=1; i<=numpins; i++) { parray[i]->key = FALSE ; } i = numnodes + 1 ; /*********************************************************** * Find a pin which is a leaf of the minimum Steiner tree. ***********************************************************/ while (1) { degree = 0 ; Pnode = garray[i]->first ; while (Pnode) { if (earray[Pnode->edge]->numpins) { degree++ ; } Pnode = Pnode->next ; } if (degree==1) { break ; } i++ ; } Pstack = NIL(STACK) ; count = 0 ; order = 1 ; Pcurrent = Plast = Pparent = Proot = make_node() ; Proot->dist = 0 ; Proot->leaf = FALSE ; Proot->order = 1 ; Proot->parent = 0 ; Proot->vertex = i ; Proot->prev = NIL(MDATA) ; Proot->next = NIL(MDATA) ; Proot->f_node = NIL(MDATA) ; if (parray[i-numnodes]->equiv) { Proot->equiv = TRUE ; parray[i-numnodes]->key = TRUE ; } else { Proot->equiv = FALSE ; } if (EQUIVAL==FALSE) { do { degree = 0 ; Pnode = garray[i]->first ; if (!count) { /*********************************************************** * Search the adjacent list of the current vertex to test if * a vertex in the list is a pin or has a degree greater than * two. * count = 0 --- the current vertex is not a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } } Pnode = Pnode->next ; } } else { /*********************************************************** * The search just returns to a Steiner vertex. We need to * go through the number of count times for adjacent vertices * which are in the minimum Steiner tree and add the vertex * into the segment tree. * count!=0 --- the current vertex is a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } if (degree==count) { count = 0 ; break ; } } Pnode = Pnode->next ; } } if (degree) { /*********************************************************** * The current vertex is not a leaf. Generate a new node and * expand the tree. ***********************************************************/ Pnew = make_node() ; Pnew->equiv = FALSE ; Pnew->leaf = FALSE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = j ; Plast->next = Pnew ; Pnew->prev = Plast ; Plast = Pnew ; Pnew->next = NIL(MDATA) ; Pnew->f_node = Pparent ; Pcurrent = Pnew ; v = i ; i = j ; } else { Pcurrent->leaf = TRUE ; } if (degree==1 && j>numnodes) { /*********************************************************** * A pin is reached which, with the start vertex i, forms a * segment. Set Pparent to be Pnew and continue the search. ***********************************************************/ Pparent = Pnew ; } else if (degree>1) { /*********************************************************** * A Steiner vertex is reached which, with the start vertex * i, forms a segment. Set Pparent to be Pnew, update the * stack, and continue the search. ***********************************************************/ if (Pstack && Pstack->Pparent->vertex==v) { Pnew->f_node = Pstack->Pparent ; /********************************************************* * The Steiner point is in the stack already. Use goto to * jump over the part of pushing it to the stack. *********************************************************/ goto contin ; } Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = --degree ; Psteiner->Pparent = Pnew->prev ; Psteiner->next = Pstack ; Pstack = Psteiner ; Pnew->f_node = Pnew->prev ; contin: if (j>numnodes) { Pparent = Pnew ; } else { Pparent = Pnew->f_node ; } } else if (!degree) { /*********************************************************** * A leaf is reached. Pop a vertex from the stack and continue * the search from that vertex. ***********************************************************/ Psteiner = Pstack ; Pcurrent = Pparent = Psteiner->Pparent ; count = Psteiner->degree ; i = Pcurrent->vertex ; Psteiner->degree-- ; if (!Psteiner->degree) { Pstack = Pstack->next ; Ysafe_free(Psteiner) ; } } } while (order<numnode) ; } else { do { degree = 0 ; Pnode = garray[i]->first ; if (!count) { /*********************************************************** * Search the adjacent list of the current vertex to test if * a vertex in the list is a pin or has a degree greater than * two. * count = 0 --- the current vertex is not a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } } Pnode = Pnode->next ; } } else { /*********************************************************** * The search just returns to a Steiner vertex. We need to * go through the number of count times for adjacent vertices * which are in the minimum Steiner tree and add the vertex * into the segment tree. * count!=0 --- the current vertex is a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } if (degree==count) { count = 0 ; break ; } } Pnode = Pnode->next ; } } if (i>numnodes && parray[i-numnodes]->equiv) { /*********************************************************** * The vertex is an equivalent pin. Scan through all its * equivalent pins. If one is an isolated equivalent pin, * then created a node in the segment tree for it and skip * it; otherwise, create a node in the segment tree for it * and push it into the stack. ***********************************************************/ Pcurrent->equiv = TRUE ; Pfirst = parray[i-numnodes] ; Pfirst->key = TRUE ; Ppin = Pfirst->next ; while (Ppin!=Pfirst) { if (Ppin->key==TRUE) { Ppin = Ppin->next ; continue ; } else { Ppin->key = TRUE ; } Pnew = make_node() ; Pnew->equiv = TRUE ; Pnew->leaf = TRUE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = Ppin->vertex + numnodes ; Pnew->f_node = Pcurrent ; Plast->next = Pnew ; Pnew->prev = Plast ; Pnew->next = NIL(MDATA) ; Plast = Pnew ; Degree = 0 ; Pnode = garray[Ppin->vertex+numnodes]->first ; while (Pnode) { if (earray[Pnode->edge]->numpins) { Degree++ ; } Pnode = Pnode->next ; } if (Degree) { /***************************************************** * The pin is not isolated. Push it into the stack. *****************************************************/ Pnew->leaf = FALSE ; Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = Degree ; Psteiner->Pparent = Pnew ; Psteiner->next = Pstack ; Pstack = Psteiner ; } /* Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = Degree ; Psteiner->Pparent = Pnew ; Psteiner->next = Pstack ; Pstack = Psteiner ; */ Ppin = Ppin->next ; } } if (degree) { /*********************************************************** * The current vertex is not a leaf. Generate a new node and * expand the tree. ***********************************************************/ Pnew = make_node() ; Pnew->equiv = FALSE ; Pnew->leaf = FALSE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = j ; Plast->next = Pnew ; Pnew->prev = Plast ; Plast = Pnew ; Pnew->next = NIL(MDATA) ; Pnew->f_node = Pparent ; Pcurrent = Pnew ; v = i ; i = j ; } else { /*********************************************************** * If the current vertex is an equivalent pin, then check * whether it has a son. ***********************************************************/ if (Pcurrent->equiv && Pcurrent->next) { v1 = Pcurrent->vertex - numnodes ; v2 = Pcurrent->next->vertex - numnodes ; if (parray[v1]->equiv==parray[v2]->equiv) { Pcurrent->leaf = FALSE ; } } else { Pcurrent->leaf = TRUE ; } } if (degree==1 && j>numnodes) { /*********************************************************** * A pin is reached which, with the start vertex i, forms a * segment. Set Pparent to be Pnew and continue the search. ***********************************************************/ Pparent = Pnew ; } else if (degree>1) { /*********************************************************** * A Steiner vertex is reached which, with the start vertex * i, forms a segment. Set Pparent to be Pnew, update the * stack, and continue the search. ***********************************************************/ if (Pstack && Pstack->Pparent->vertex==v) { Pnew->f_node = Pstack->Pparent ; /********************************************************* * The Steiner point is in the stack already. Use goto to * jump over the part of pushing it to the stack. *********************************************************/ goto contin_equiv ; } Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = --degree ; Psteiner->Pparent = Pnew->prev ; Psteiner->next = Pstack ; Pstack = Psteiner ; Pnew->f_node = Pnew->prev ; contin_equiv: if (j>numnodes) { Pparent = Pnew ; } else { Pparent = Pnew->f_node ; } } else if (!degree && Pstack) { /*********************************************************** * A leaf is reached. Pop a vertex from the stack and continue * the search from that vertex. ***********************************************************/ Psteiner = Pstack ; Pparent = Pcurrent = Psteiner->Pparent ; count = Psteiner->degree ; i = Pcurrent->vertex ; Psteiner->degree-- ; if (!Psteiner->degree) { Pstack = Pstack->next ; Ysafe_free(Psteiner) ; } } } while (order<numnode) ; } /*********************************************************** * Assign the segment tree to an array and set up the index * array for quick access. ***********************************************************/ marray = (MDATAPTR *) Ysafe_malloc((numnode+1) * sizeof(MDATAPTR)) ; marray[0] = NIL(MDATA) ; Pcurrent = Proot ; while (Pcurrent) { i = Pcurrent->order ; marray[i] = Pcurrent ; j = Pcurrent->vertex ; iarray[j] = i ; Pcurrent = Pcurrent->next ; } /*********************************************************** * Assign the distance to the field in each entry of marray. ***********************************************************/ if (EQUIVAL==FALSE) { for (i=2; i<=numnode; i++) { v1 = marray[i-1]->vertex ; v2 = marray[i]->vertex ; Pnode = garray[v1]->first ; while (Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } if (Pnode && earray[Pnode->edge]->intree) { marray[i]->dist = marray[i-1]->dist + Pnode->length ; } else { j = marray[i]->f_node->order ; v1 = marray[j]->vertex ; Pnode = garray[v1]->first ; while(Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } marray[i]->dist = marray[j]->dist + Pnode->length ; } } } else { for (i=2; i<=numnode; i++) { if (marray[i]->equiv && marray[i]->f_node->equiv) { /*********************************************************** * Both pins are equivalent pins. ***********************************************************/ v1 = marray[i]->vertex - numnodes ; v2 = marray[i]->f_node->vertex - numnodes ; if (parray[v1]->equiv==parray[v2]->equiv) { /********************************************************* * Both pins are in the same group of equivalent pins. *********************************************************/ marray[i]->dist = marray[i]->f_node->dist ; } else { /********************************************************* * Both pins are not in the same group of equivalent pins. *********************************************************/ goto USUAL_CASE ; } } else { USUAL_CASE: v1 = marray[i-1]->vertex ; v2 = marray[i]->vertex ; Pnode = garray[v1]->first ; while (Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } if (Pnode && earray[Pnode->edge]->intree) { marray[i]->dist = marray[i-1]->dist + Pnode->length ; } else { j = marray[i]->f_node->order ; v1 = marray[j]->vertex ; Pnode = garray[v1]->first ; while(Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } marray[i]->dist = marray[j]->dist + Pnode->length ; } } } } marray[numnode]->leaf = TRUE ; } /* end of construct_segment */
globroute() { INT flips , attempts , net ; INT pick , number , attlimit ; INT found , trys , maxtrys ; INT x , x1 , x2 , channel ; SEGBOXPTR segptr , *segment ; DENSITYPTR denptr ; PINBOXPTR netptr1 , netptr2 ; changrid( ) ; pre_findrcost( ) ; findrcost() ; fprintf(fpoG,"\n\nTHIS IS THE ORIGINAL NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); flips = 0 ; attempts = 0 ; attlimit = 25 * numnetsG ; segment = ( SEGBOXPTR *)Ysafe_malloc( ( Max_numPinsG + 1 ) * sizeof( SEGBOXPTR ) ) ; while( ++attempts < attlimit ) { if( attempts % 1000 == 0 ) { printf(" tracks = %3d at attempts = %5d\n" ,tracksG ,attempts ) ; } do { net = (INT) ( (DOUBLE) numnetsG * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( net == numnetsG + 1 ) ; number = 0 ; for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 1 ) ; if( segptr->switchvalue != nswLINE ) { segment[ ++number ] = segptr ; } } maxtrys = 4 * number ; trys = 0 ; while( ++trys <= maxtrys ) { do { pick = (INT) ( (DOUBLE) number * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( pick == number + 1 ) ; segptr = segment[ pick ] ; netptr1 = segptr->pin1ptr ; netptr2 = segptr->pin2ptr ; if( segptr->switchvalue == swUP ) { channel = netptr1->row + 1 ; } else { channel = netptr2->row ; } x1 = netptr1->xpos ; x2 = netptr2->xpos ; found = NO ; for( denptr = DboxHeadG[ channel ][ maxTrackG[channel] ]->next ; denptr != DENSENULL ; denptr = denptr->next ) { x = denptr->grdptr->netptr->xpos ; if( x1 <= x && x2 >= x ) { found = YES ; break ; } } if( !found ) { continue ; } if( urcost( segptr ) ) { flips++ ; } } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } Ysafe_free( segment ); fprintf(fpoG,"no. of accepted flips: %d\n", flips ) ; fprintf(fpoG,"no. of attempted flips: %d\n", attempts ) ; fprintf(fpoG,"THIS IS THE NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); return ; }
findcostf() { TIBOXPTR tileptr1 ; CBOXPTR cellptr1 ; BINPTR bptr ; INT left , right ; INT bin , LoBin , HiBin ; INT block , cell , blk ; INT startx , endx ; INT cost ; INT k , cbin , row ; blkleftG = INT_MAX ; blkriteG = INT_MIN ; for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[ block ]->bxcenter + barrayG[ block ]->bleft < blkleftG ) { blkleftG = barrayG[ block ]->bxcenter + barrayG[ block ]->bleft ; } if( barrayG[ block ]->bxcenter + barrayG[ block ]->bright > blkriteG ) { blkriteG = barrayG[ block ]->bxcenter + barrayG[ block ]->bright ; } } binOffstG = blkleftG ; max_blklengthG = blkriteG - blkleftG ; old_numBinS = numBinsG ; numBinsG = (INT)( ( blkriteG - binOffstG ) / binWidthG ) ; if( ( blkriteG - binOffstG ) > ( numBinsG * binWidthG ) ) { numBinsG++ ; } if( numBinsG > old_numBinS ) { for( row = 1 ; row <= numRowsG ; row++ ) { bin_configG[row] = (INT *) Ysafe_realloc( bin_configG[row] , (1 + numBinsG) * sizeof(INT) ) ; for( bin = old_numBinS + 1 ; bin <= numBinsG ; bin++ ) { bin_configG[row][bin] = 0 ; } } } cost = recompute_wirecost() ; binpenalG = 0 ; rowpenalG = 0 ; penaltyG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= old_numBinS ; bin++ ) { Ysafe_free( binptrG[block][bin]->cell ) ; Ysafe_free( binptrG[block][bin] ) ; } Ysafe_free( binptrG[block] ) ; } for( block = 1 ; block <= numRowsG ; block++ ) { binptrG[block] = (BINPTR * ) Ysafe_malloc( (numBinsG + 1) * sizeof( BINPTR ) ) ; left = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter ; right = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter + barrayG[ block ]->desire ; /* set barray->oldsize to zero for upcoming calculation */ barrayG[ block ]->oldsize = 0 ; LoBin = SetBin( left ) ; HiBin = SetBin( right ) ; for( bin = 0 ; bin <= numBinsG ; bin++ ) { binptrG[block][bin] = (BINBOX *) Ysafe_malloc( sizeof(BINBOX) ) ; binptrG[block][bin]->cell = (INT *)Ysafe_malloc( 10 * sizeof(INT) ); bptr = binptrG[block][bin] ; bptr->cell[0] = 0 ; bptr->right = binOffstG + bin * binWidthG ; bptr->left = bptr->right - binWidthG ; if( bin == LoBin ) { bptr->penalty = left - bptr->right ; } else if( bin == HiBin ) { bptr->penalty = bptr->left - right ; } else if( bin > HiBin || bin < LoBin ) { bptr->penalty = 0 ; } else { bptr->penalty = - binWidthG ; } } } installf() ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr1 = carrayG[ cell ] ; tileptr1 = cellptr1->tileptr ; block = cellptr1->cblock ; startx = cellptr1->cxcenter + tileptr1->left ; endx = cellptr1->cxcenter + tileptr1->right ; barrayG[block]->oldsize += endx - startx ; cbin = SetBin( cellptr1->cxcenter ) ; LoBin = SetBin( startx ) ; HiBin = SetBin( endx ) ; k = ++(binptrG[block][cbin]->cell[0]) ; if( k % 10 == 0 ) { binptrG[block][cbin]->cell = (INT *) Ysafe_realloc( binptrG[block][cbin]->cell, (k + 10) * sizeof( INT ) ) ; } binptrG[block][cbin]->cell[k] = cell ; if( LoBin == HiBin ) { binptrG[block][LoBin]->penalty += ( endx - startx ) ; } else { bptr = binptrG[block][LoBin] ; bptr->penalty += ( bptr->right - startx ) ; bptr = binptrG[block][HiBin] ; bptr->penalty += ( endx - bptr->left ) ; if( LoBin + 1 < HiBin ) { for( bin = LoBin + 1 ; bin <= HiBin - 1 ; bin++ ) { binptrG[block][bin]->penalty += binWidthG ; } } } } for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { binpenalG += ABS( binptrG[block][bin]->penalty ) ; } } for( blk = 1 ; blk <= numRowsG ; blk++ ) { rowpenalG += ABS(barrayG[blk]->oldsize - barrayG[blk]->desire) ; } penaltyG = (INT)( binpenConG * (DOUBLE) binpenalG + roLenConG * (DOUBLE) rowpenalG ) ; timingcostG = recompute_timecost() ; return( cost ) ; }
install_clusters() { INT row , n , i , bin , i_error , delta_bin , length_in_row , cell ; INT total ; INT total_actual_clusters ; DOUBLE error , n_DOUBLE , cluster_norm ; fprintf(fpoG,"total number of clusters which should be added in: %d\n", num_clustersG ) ; total_actual_clusters = 0 ; cluster_configS = (INT **) Ysafe_malloc((1 + numRowsG) * sizeof(INT *)) ; for( row = 1 ; row <= numRowsG ; row++ ) { cluster_configS[row] = (INT *) Ysafe_malloc((1+numBinsG)*sizeof(INT)); for( bin = 0 ; bin <= numBinsG ; bin++ ) { cluster_configS[row][bin] = 0 ; } } cluster_norm = (DOUBLE) num_clustersG / (DOUBLE) numRowsG + cluster_norm_offsetS ; if( num_clustersG == 0 ) { return ; } error = 0.0 ; total = 0 ; for( row = 1 ; total < num_clustersG && row <= numRowsG ; row++ ) { length_in_row = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cblock == row ) { if( carrayG[cell]->cclass < 0 ) { length_in_row += carrayG[cell]->clength ; } } } n_DOUBLE = cluster_norm + error ; n = (INT) n_DOUBLE ; if( n_DOUBLE - (DOUBLE) n >= 0.5 ) { n++ ; } error = n_DOUBLE - (DOUBLE) n ; while( total + n > num_clustersG ) { n-- ; } if( length_in_row + n * cluster_widthG > barrayG[row]->desire ) { if( row == numRowsG ) { /* can't fit all the required clusters; increase cluster_norm */ ++cluster_norm_offsetS ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( cluster_configS[row] ) ; } Ysafe_free( cluster_configS ) ; install_clusters() ; return ; } n = (barrayG[row]->desire - length_in_row) / cluster_widthG ; if( n < 0 ) { n = 0 ; } error += (DOUBLE)( (INT) n_DOUBLE - n ) ; } if( n == 0 ) { continue ; } total += n ; i_error = 0 ; bin = 0 ; for( i = 0 ; i < n ; i++ ) { delta_bin = (numBinsG + i_error) / n ; bin += delta_bin ; i_error += numBinsG - delta_bin * n ; if( bin < 1 ) bin = 1 ; if( bin > numBinsG ) bin = numBinsG ; cluster_configS[row][bin]++ ; } fprintf(fpoG,"Number of clusters added to row:%d was:%d\n", row,i); total_actual_clusters += i ; for( bin = 1 ; bin <= numBinsG ; bin++ ) { if( cluster_configS[row][bin] >= 1 ) { barrayG[row]->oldsize += cluster_configS[row][bin] * cluster_widthG ; } } } fprintf(fpoG,"actual total number of clusters which were added in: %d\n", total_actual_clusters ) ; return; } /* end install_clusters */
void free_mem() { int i; int j; LISTPTR Pnode; TREEPTR *tarray; totnodes = numnodes + maxpins; totedges = numedges + maxpins; for (i = 1; i <= totnodes; i++) { tarray = garray[i]->tree; for (j = 0; j <= totnodes; j++) { Ysafe_free((char *) tarray[j]); } Ysafe_free((char *) tarray); Pnode = garray[i]->first; while (Pnode) { garray[i]->first = garray[i]->first->next; Ysafe_free((char *) Pnode); Pnode = garray[i]->first; } Ysafe_free((char *) garray[i]); } Ysafe_free((char *) garray); for (i = 1; i <= numnodes; i++) { tarray = sarray[i]->tree; for (j = 0; j <= numnodes; j++) { Ysafe_free((char *) tarray[j]); } Ysafe_free((char *) tarray); sarray[i]->tree = NIL(TREEPTR); } garray = sarray; for (i = 1; i <= totedges; i++) { Ysafe_free((char *) earray[i]); } Ysafe_free((char *) earray); for (i = 1; i <= numedges; i++) { Ysafe_free((char *) carray[i]); } Ysafe_free((char *) carray); } /* end of free_mem */
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 */
/*===================================================================== * In order to have this file work properly, there must be a blank line * between the records of two consecutive nets and the very first line * can not be a blank line. Also the name of nets can not be over 256 * characters. =====================================================================*/ BOOLEAN read_one_net() { char input[LRECL]; char **tokens; int i; int v1; /* Vertex index */ int v2; /* Vertex index */ int pin; int equiv; INT numtokens; C_LISTPTR Pnew; LISTPTR Pnode; PINPTR Pfirst; /* Header of the pin list */ PINPTR Ppin; EQUIVAL = FALSE; SHIFTED = FALSE; CAP_MATCH = FALSE; MIX_MATCH = FALSE; RES_MATCH = FALSE; COMMON_POINT = FALSE; equiv = 0; numpins = 0; net_type = 0; numcomms = 0; max_volt_drop = 0; Pfirst = NIL(PIN); Plist = NIL(C_LIST); while (fgets(input, LRECL, fin)) { tokens = Ystrparser(input, " \t\n", &numtokens); if (numtokens == 0) { /*********************************************************** * An empty line is reached. A complete record is read in * so quit reading the net. ***********************************************************/ break; } if (strncmp(tokens[0], "net", 3) == STRINGEQ) { /*********************************************************** * The beginning of a digital net is read in. Get the net * name and set the net type to be noisy. ***********************************************************/ (void) strcpy(netName, tokens[1]); DIGITAL = TRUE; net_type = NOISY; } else if (strncmp(tokens[0], "analog_net", 10) == STRINGEQ) { /*********************************************************** * The beginning of an analog net is read in. Get the net * name and read in the capacitance upper bound, resistance * upper bound, maximum value of the voltage drop, plus the * net type specification. Note that not all the parameters * have to be present. ***********************************************************/ (void) strcpy(netName, tokens[1]); if (numtokens < 3) { ERROR1("\n\nThe entry line for an analog net must have "); ERROR1("at least 3 fields!\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } for (i = 2; i < numtokens; i += 2) { if (strncmp(tokens[i], "cap", 3) == STRINGEQ) { cap_upper_bound = atof(tokens[i+1]); } else if (strncmp(tokens[i], "res", 3) == STRINGEQ) { res_upper_bound = atof(tokens[i+1]); } else if (strncmp(tokens[i], "max_drop", 8) == STRINGEQ) { max_volt_drop = atof(tokens[i+1]); } else if (strncmp(tokens[i], "noisy", 5) == STRINGEQ) { if (net_type == SENSITIVE) { net_type = MIXED; } else if(net_type == SHIELD) { ERROR1("\n\n"); ERROR1("A net can not be NOISY and SHIELDING "); ERROR1("at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = NOISY; } i--; } else if(strncmp(tokens[i], "sensitive", 9) == STRINGEQ) { if (net_type == NOISY) { net_type = MIXED; } else if(net_type == SHIELD) { ERROR1("\n\nA net can not be SENSITIVE and "); ERROR1("SHIELDING at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = SENSITIVE; } i--; } else if (strncmp(tokens[i], "shielding", 9) == STRINGEQ) { if (net_type == NOISY || net_type == SENSITIVE) { ERROR1("\n\nA net can not be SENSITIVE and "); ERROR1("SHIELDING or NOISY and\n"); ERROR1("SHIELDING at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = SHIELD; } i--; } else { ERROR1("\n\n"); ERROR2("Unknown keyword \"%s\" for the ", tokens[i]); ERROR2("net %s.\nNotice that the keywords", netName); ERROR1(" are case-sensitive. DO NOT USE capital"); ERROR1(" letters in the keywords.\n"); exit(GP_FAIL); } } if (!net_type) { ERROR1("\n\nNet type must be specified for analog nets"); ERROR2(".\nNo net type is specified for net %s\n", netName); exit(GP_FAIL); } DIGITAL = FALSE; } else if (strncmp(tokens[0], "common_point", 12) == STRINGEQ) { numcomms++; Pnew = (C_LISTPTR) Ysafe_malloc(sizeof(C_LIST)); Pnew->numpin = atoi(tokens[1]); Pnew->cap_match = FALSE; Pnew->res_match = FALSE; Pnew->next = Plist; Plist = Pnew; COMMON_POINT = TRUE; } else if (strncmp(tokens[0], "pin", 3) == STRINGEQ || strncmp(tokens[0], "equiv", 5) == STRINGEQ) { Ppin = (PINPTR) Ysafe_malloc(sizeof(PIN)); if (tokens[0][0] == 'e') { /********************************************************* * This pin is an equivalent pin of the previous pin(s). *********************************************************/ EQUIVAL = TRUE; if (Pfirst->equiv) { Ppin->equiv = Pfirst->equiv; } else { Ppin->equiv = ++equiv; Pfirst->equiv = equiv; } } else { Ppin->equiv = FALSE; } Ppin->node[0] = v1 = atoi(tokens[5]); Ppin->node[1] = v2 = atoi(tokens[6]); Ppin->shifted = FALSE; Ppin->vertex = ++numpins; Ppin->pin[0] = Ppin->pin[1] = 0; Ppin->dist[0] = atoi(tokens[8]); if (numtokens == ANALOG_PIN) { Ppin->density = atoi(tokens[11]); } else { Ppin->density = 0; } /*********************************************************** * Find the edge index of the channel on which the pin is * located. This is for removing the rectilinear restriction. ***********************************************************/ Pnode = garray[v1]->first; while (Pnode->t_vertex != v2) { Pnode = Pnode->next; } Ppin->dist[1] = Pnode->length - Ppin->dist[0]; /********************************************************* * Check if the pin overlaps with a vertex of the channel * graph. If so, we have to shift the pin along the channel * a bit due to the data structure. *********************************************************/ if (!(Ppin->dist[0])) { /***************************************************** * The pin overlaps with vertex v1 of the channel * graph. *****************************************************/ Ppin->dist[0]++; Ppin->dist[1]--; Ppin->shifted = 1; SHIFTED = TRUE; } if (!(Ppin->dist[1])) { /***************************************************** * The pin overlaps with vertex v2 of the channel * graph. *****************************************************/ Ppin->dist[0]--; Ppin->dist[1]++; Ppin->shifted = -1; SHIFTED = TRUE; } Ppin->next = Pfirst; Pfirst = Ppin; } else if (strncmp(tokens[0], "cap_match", 9) == STRINGEQ) { Pnew->cap_match = TRUE; } else if (strncmp(tokens[0], "res_match", 9) == STRINGEQ) { Pnew->res_match = TRUE; } else { ERROR1("\n\n"); ERROR2("Unknown keyword \"%s\" in the record ", tokens[0]); ERROR2("for the net %s\n", netName); exit(GP_FAIL); } } if (numpins) { /*********************************************************** * Make an array for the list of pins. ***********************************************************/ pin = numpins; parray = (PINPTR *) Ysafe_malloc((numpins+1) * sizeof(PINPTR)); while (Pfirst) { parray[pin--] = Pfirst; Pfirst = Pfirst->next; } } if (EQUIVAL == TRUE) { /*********************************************************** * Make each group of equivalent pins a circular linked list * which will be used to construct the segment tree. ***********************************************************/ for (i = 1; i <= numpins ;) { if (parray[i]->equiv) { v1 = i; v2 = i + 1; pin = parray[i]->equiv; while (v2 <= numpins && parray[v2]->equiv == pin) { parray[v1]->next = parray[v2]; v1++; v2++; } parray[v1]->next = parray[i]; i = v2; } else { parray[i]->next = NIL(PIN); i++; } } /*********************************************************** * Check each set of equivalent pins on their geometric * positions and make sure that they are NOT on top each * other. ***********************************************************/ for (i = 1; i <= numpins; i++) { if (parray[i]->next) { /********************************************************* * A set of equivalent pins is found. Check each pair of * the equivalent pins in the set and make sure that none * of them are on top each other. *********************************************************/ Pfirst = parray[i]; while (Pfirst->next != parray[i]) { for (Ppin = Pfirst->next; Ppin != Pfirst; Ppin = Ppin->next) { if (Pfirst->dist[0] == Ppin->dist[0] && Pfirst->node[0] == Ppin->node[0] && Pfirst->node[1] == Ppin->node[1]) { ERROR1("\n\n"); ERROR1("FATAL ERROR: Equivalent pins are "); ERROR1("on top each other in the net "); ERROR2("%s.\nMust exit. Sorry!\n\n", netName); exit(GP_FAIL); } } Pfirst = Pfirst->next; } } } } else { /*********************************************************** * There are equivalent pins in this net. Clean the field * next in parray. ***********************************************************/ for (i = 1; i <= numpins; i++) { parray[i]->next = NIL(PIN); } } if (COMMON_POINT != FALSE) { /*********************************************************** * There exit common pins in this net. Make sure the common * pins have no equivalent pins to them. Mickey can not * handle common pins with equivalent pins. ***********************************************************/ v1 = 0; Pnew = Plist; while (Pnew) { v2 = Pnew->numpin; for (i = ++v1; i < v2; i++) { if (parray[i]->next) { ERROR1("\n\nMickey can not handle pins which are"); ERROR1(" equivalent pins\n and"); ERROR1(" are to be connected to a common point\n"); exit(GP_FAIL); } parray[i]->next = parray[i+1]; } parray[i]->next = parray[v1]; v1 = i + 1; Pnew = Pnew->next; } while (Plist) { Pnew = Plist; Plist = Plist->next; Ysafe_free((char *) Pnew); } } return(numpins); } /* end of read_one_net */
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 */ } }