diff -Naur graywolf/src/twsc/gateswap.c graywolf_new/src/twsc/gateswap.c --- graywolf/src/twsc/gateswap.c 2015-05-15 22:22:22.406535822 -0400 +++ graywolf_new/src/twsc/gateswap.c 2015-05-15 21:42:44.542599522 -0400 @@ -20,8 +20,9 @@ #include #include "readnets.h" -gate_swap( between_two_cells ) +gate_swap( between_two_cells, sgidxa, sgidxb ) INT between_two_cells ; +INT sgidxa, sgidxb ; { CBOXPTR cell1ptr , cell2ptr ; @@ -30,64 +31,72 @@ char *tmp_char_ptr ; struct equiv_box *tmp_eqptr ; INT cost , cell1 , cell2 , length ; -INT tmp , swap_group ; -INT truth , i , count ; +INT tmp , i, swap_group ; +INT truth , count ; INT pg1 , pg2 ; /* pg stands for 'pin group' */ INT newtimepenal ; +SGLISTPTR cell1sgl, cell2sgl; + +term_list1 = NULL; +term_list2 = NULL; if( between_two_cells ) { cell1 = aG ; cell2 = bG ; cell1ptr = carrayG[cell1] ; cell2ptr = carrayG[cell2] ; - swap_group = cell1ptr->swap_group ; - pg1 = XPICK_INT( 1 , cell1ptr->num_pin_group , 0 ) ; - pg2 = XPICK_INT( 1 , cell2ptr->num_pin_group , 0 ) ; - count = 0 ; - for( i = 1 ; ; i++ ) { - term_list1 = swap_group_listG[swap_group].pin_grp_array[i] ; - if( term_list1->swap_pin->cell == cell1 ) { - if( ++count == pg1 ) { - break ; - } - } + cell1sgl = cell1ptr->swapgroups + sgidxa; + cell2sgl = cell2ptr->swapgroups + sgidxb; + pg1 = XPICK_INT( 1 , cell1sgl->num_pin_group , 0 ) ; + pg2 = XPICK_INT( 1 , cell2sgl->num_pin_group , 0 ) ; + swap_group = cell1sgl->swap_group; + + term_list1 = (PINLISTPTR) Yhash_search( + swap_group_listG[swap_group].pin_grp_hash, + cell1ptr->cname, NULL, FIND ); + + while (pg1 > 1) { + if (term_list1->next_grp == NULL) break; + term_list1 = term_list1->next_grp; } - count = 0 ; - for( i = 1 ; ; i++ ) { - term_list2 = swap_group_listG[swap_group].pin_grp_array[i] ; - if( term_list2->swap_pin->cell == cell2 ) { - if( ++count == pg2 ) { - break ; - } - } + + term_list2 = (PINLISTPTR) Yhash_search( + swap_group_listG[swap_group].pin_grp_hash, + cell2ptr->cname, NULL, FIND ); + + while (pg2 > 1) { + if (term_list2->next_grp == NULL) break; + term_list2 = term_list2->next_grp; } } else { cell1 = aG ; cell2 = aG ; cell1ptr = carrayG[cell1] ; - swap_group = cell1ptr->swap_group ; - pg1 = XPICK_INT( 1 , cell1ptr->num_pin_group , 0 ) ; - pg2 = XPICK_INT( 1 , cell1ptr->num_pin_group , pg1 ) ; - count = 0 ; + cell1sgl = cell1ptr->swapgroups + sgidxa; + swap_group = cell1sgl->swap_group ; + pg1 = XPICK_INT( 1 , cell1sgl->num_pin_group , 0 ) ; + pg2 = XPICK_INT( 1 , cell1sgl->num_pin_group , pg1 ) ; + if( pg1 > pg2 ) { /* we want to ensure that pg1 < pg2 */ i = pg1 ; pg1 = pg2 ; pg2 = i ; } - for( i = 1 ; ; i++ ) { - term = swap_group_listG[swap_group].pin_grp_array[i] ; - if( term->swap_pin->cell == cell1 ) { - if( ++count == pg1 ) { - term_list1 = term ; - continue ; - } - if( count == pg2 ) { - term_list2 = term ; - break ; - } - } + + term = (PINLISTPTR) Yhash_search( + swap_group_listG[swap_group].pin_grp_hash, + cell1ptr->cname, NULL, FIND ); + + term_list1 = term; + while (pg1 > 1) { + term_list1 = term_list1->next_grp; + } + + term_list2 = term; + while (pg2 > 1) { + term_list2 = term_list2->next_grp; } } diff -Naur graywolf/src/twsc/parser.c graywolf_new/src/twsc/parser.c --- graywolf/src/twsc/parser.c 2015-05-15 22:22:22.408535827 -0400 +++ graywolf_new/src/twsc/parser.c 2015-05-15 21:42:26.041547615 -0400 @@ -113,6 +113,7 @@ static INT swapAllocS ; /* current space in swap_group_listG */ static INT totalCellS ; /* current cell number and running total */ static INT swap_groupS ; /* current swap group number from hashtable */ +static INT swap_nextS ; /* next swap group number to assign */ static INT pin_typeS ; /* current pin type */ static INT numchildrenS ; /* # of children in current padgroup */ static INT childAllocS ; /* current space in current pptr->children */ @@ -120,7 +121,8 @@ static INT minyS, maxyS ; /* Y bounding box for cell or pad */ static char *curCellNameS ; /* current cell name */ static BOOL abortS = FALSE ; /* switch allow us to find multiple errors */ -static BOOL pin_group_light_is_onS;/* currently in a pin group */ +static INT pin_group_light_is_onS;/* currently in a pin group at position cnt */ +static BOOL need_swap_groupS; /* pin_group called without swap_group */ static BOOL old_pad_formatS = FALSE;/* we need to do more work if old format */ static CBOXPTR ptrS ; /* pointer to current cell box */ static PINBOXPTR pinptrS ; /* the current pin */ @@ -223,6 +225,9 @@ implicit_feed_countG = 0 ; totalCellS = 0 ; swap_groupS = 0 ; + swap_nextS = 0 ; + pin_group_light_is_onS = 0 ; + need_swap_groupS = FALSE ; fixLRBTG = (INT *) Ysafe_malloc( 4 * sizeof( INT ) ) ; fixLRBTG[0] = 0 ; @@ -272,6 +277,10 @@ curCellNameS = cellname ; curCellTypeS = celltype ; + /* Undefine pin and swap groups, if used in the last cell */ + pin_group_light_is_onS = 0 ; + need_swap_groupS = FALSE ; + totalCellS++ ; ERRORABORT() ; @@ -304,8 +313,8 @@ ptrS->cbclass[7] = 0 ; ptrS->corient = 0 ; ptrS->numterms = 0 ; - ptrS->swap_group = 0 ; - ptrS->num_pin_group = 0 ; + ptrS->num_swap_group = 0 ; + ptrS->swapgroups = NULL ; ptrS->fence = NULL ; ptrS->paths = NULL ; ptrS->tileptr = TILENULL ; @@ -441,7 +450,7 @@ /* create space for data */ data = (INT *) Ysafe_malloc( sizeof(INT) ) ; /* if data is not found in hash table update swap_groupS */ - *data = ++swap_groupS ; + *data = ++swap_nextS ; return( (char *) data ) ; } /* end add_swap_func */ @@ -453,16 +462,51 @@ INT oldalloc ; /* allocation before expanding the array */ BOOL newflag ; /* TRUE if this item has been added to hash table */ SWAPBOX *swapptr ; /* pointer to the current swap group list */ + SGLIST *sglistptr ; ERRORABORT() ; swappable_gates_existG = TRUE ; groupptr = (INT *)Yhash_add( swap_hash_tableS, swap_name, add_swap_func, &newflag ) ; /* check to make sure all is well. newflag is set if swap_name wasn't in hashtable */ - if( !(groupptr) || *groupptr != swap_groupS ){ - M( ERRMSG, "add_swap_group", "Problem with swap hash table\n" ) ; + if(!(groupptr) || (*groupptr <= 0)) { + sprintf(YmsgG, "Problem with swap hash table for group <%s>\n", swap_name ); + M( ERRMSG, "add_swap_group", YmsgG ) ; abortS = TRUE ; } - ptrS->swap_group = swap_groupS ; + swap_groupS = *groupptr; + + /* Check if swapgroups exists. Create it if not. */ + + if (ptrS->swapgroups == NULL) { + ptrS->swapgroups = (SGLIST *) Ysafe_malloc( sizeof( SGLIST ) ) ; + ptrS->num_swap_group = 1; + sglistptr = ptrS->swapgroups; + sglistptr->num_pin_group = 0; + sglistptr->swap_group = swap_groupS; + } + else { + + /* Does this swap group already exist in the list? If */ + /* so, then ignore it, otherwise add it to the list. */ + + for (i = 0; i < ptrS->num_swap_group; i++) { + sglistptr = ptrS->swapgroups + i; + if (sglistptr->swap_group == swap_groupS) break; + } + if (i == ptrS->num_swap_group) { + ptrS->num_swap_group++; + ptrS->swapgroups = (SGLIST *) Ysafe_realloc( ptrS->swapgroups, + ptrS->num_swap_group * sizeof( SGLIST ) ) ; + sglistptr = ptrS->swapgroups + i; + sglistptr->swap_group = swap_groupS; + sglistptr->num_pin_group = 0; + } + } + + if (newflag && need_swap_groupS) { + sprintf(YmsgG, "Implicit swap group <%s> created\n", swap_name ); + M( MSG, "add_swap_group", YmsgG ) ; + } if( newflag && swap_groupS >= swapAllocS ){ oldalloc = swapAllocS ; @@ -472,8 +516,7 @@ for( i = oldalloc; i < swapAllocS; i++ ){ swapptr = &(swap_group_listG[i]) ; swapptr->num_pin_grps = 0 ; - swapptr->pin_grp_array = (PINLISTPTR *) - Ysafe_calloc( 10, sizeof(PINLISTPTR)) ; + swapptr->pin_grp_hash = Yhash_table_create( TW_PRIME2 ); } } @@ -483,26 +526,38 @@ { INT i ; /* counter */ INT j ; /* counter */ + SGLIST *sglistptr = NULL; ERRORABORT() ; - ptrS->num_pin_group++ ; - pin_group_light_is_onS = TRUE ; - if( ++( swap_group_listG[swap_groupS].num_pin_grps ) % 10 == 0 ) { - swap_group_listG[swap_groupS].pin_grp_array = - (PINLISTPTR *) Ysafe_realloc( - swap_group_listG[swap_groupS].pin_grp_array , - (swap_group_listG[swap_groupS].num_pin_grps + 10) * - sizeof(PINLISTPTR) ) ; - i = swap_group_listG[swap_groupS].num_pin_grps ; - for( j = i + 10 ; i < j ; i++ ) { - swap_group_listG[swap_groupS].pin_grp_array[i] = NULL ; - } + + /* Find the swap group in the cell record */ + for (i = 0; i < ptrS->num_swap_group; i++) { + sglistptr = ptrS->swapgroups + i; + if (sglistptr->swap_group == swap_groupS) + break; + } + if (i == ptrS->num_swap_group) { + // If no swap group was defined for the cell, then + // each pin_group will implicitly define a swap + // group with the name of the first pin before the + // slash character. + need_swap_groupS = TRUE; + return; } + + sglistptr->num_pin_group++ ; + pin_group_light_is_onS = 1 ; + } /* end add_pingroup */ end_pingroup() { - pin_group_light_is_onS = FALSE ; + pin_group_light_is_onS = 0 ; + + // Reset the swap_group if each pin group defines its own + // swap group (enabled by not having a "swap_group" line in + // the cell options). + if (need_swap_groupS == TRUE) swap_groupS = 0; } /* end end_pingroup */ static add_implicit_feed( pin_name, signal, layer, xpos, ypos ) @@ -552,20 +607,50 @@ return( (char *) data ) ; } /* end add_swap_func */ +static char *add_pin_func() +{ + INT *data ; /* pointer to allocated space for pin_grp_hash record */ + + ERRORABORT() ; + + /* how to add the data to the hash table */ + /* create space for data */ + data = (PINLIST *) Ysafe_malloc( sizeof(PINLIST) ) ; + return( (char *) data ) ; +} /* end add_swap_func */ + add_pin( pin_name, signal, layer, xpos, ypos ) char *pin_name, *signal ; INT layer, xpos, ypos ; { INT *netreturn ; /* net number found in hash table */ - INT cur_group ; /* current pin group number */ + INT newflag ; BOOL notInTable ; /* net added to table if true */ DBOXPTR nptr ; /* the current net record */ PINLISTPTR pin_ptr ; /* pointer to current pinlistgroup */ - PINLISTPTR save_ptr ; /* pointer to old pinlistgroup */ + PINLISTPTR new_pin_ptr ; /* pointer to new pinlistgroup */ static PINBOXPTR botpinL = NULL ; /* save the last pinptr */ ERRORABORT() ; + // If a swap group was not defined for this cell in the + // traditional way (with "swap_group" in cell options list), + // but pin_group was called, then we generate an implicit + // swap_group with the name of the pin before the slash. + + if (need_swap_groupS) { + char *slashptr = strrchr(pin_name, '/'); + if (slashptr != NULL) { + *slashptr = '\0'; + add_swap_group(pin_name); + *slashptr = '/'; + add_pingroup(); + } + /* In case of error this is just a normal pin, not */ + /* swappable, which may result in non-optimal */ + /* placement but does not invalidate the netlist. */ + } + if( curCellTypeS == PADTYPE || curCellTypeS == HARDCELLTYPE ){ /* these types may have global pin positions */ /* subtract off cell center */ @@ -665,24 +750,44 @@ pinptrS->pinname = pin_name ; } - pinptrS->txpos[0] = xpos ; pinptrS->typos[0] = ypos ; - if( pin_group_light_is_onS ) { + if( pin_group_light_is_onS > 0 ) { - /* form a list of pins in each swap group */ - cur_group = swap_group_listG[swap_groupS].num_pin_grps ; - save_ptr = swap_group_listG[swap_groupS].pin_grp_array[cur_group] ; - pin_ptr = swap_group_listG[swap_groupS].pin_grp_array[cur_group] = - (PINLISTPTR) Ysafe_malloc( sizeof(PINLIST) ) ; - pin_ptr->next = save_ptr ; - pin_ptr->swap_pin = pinptrS ; + pin_ptr = (PINLISTPTR) Yhash_add( swap_group_listG[swap_groupS].pin_grp_hash, + ptrS->cname, add_pin_func, &newflag ) ; + + if (newflag) { + /* This is the first pin group for this swap group in this cell */ + pin_ptr->swap_pin = pinptrS; + pin_ptr->next = NULL; + pin_ptr->next_grp = NULL; + } + else { + if (pin_group_light_is_onS == 1) { + /* Additional pin group for this swap group in this cell */ + while (pin_ptr->next_grp) pin_ptr = pin_ptr->next_grp; + new_pin_ptr = (PINLISTPTR) Ysafe_malloc( sizeof(PINLIST) ) ; + pin_ptr->next_grp = new_pin_ptr; + } + else { + /* Additional pins in this pin group */ + while (pin_ptr->next) pin_ptr = pin_ptr->next; + new_pin_ptr = (PINLISTPTR) Ysafe_malloc( sizeof(PINLIST) ) ; + pin_ptr->next = new_pin_ptr; + } + new_pin_ptr->swap_pin = pinptrS; + new_pin_ptr->next = NULL; + new_pin_ptr->next_grp = NULL; + } if( pin_typeS == SWAP_PASS ){ swap_netG = curNetS ; netarrayG[curNetS]->ignore = 1 ; } + + pin_group_light_is_onS++; } /* pin location determination */ diff -Naur graywolf/src/twsc/sortpin.c graywolf_new/src/twsc/sortpin.c --- graywolf/src/twsc/sortpin.c 2015-05-15 22:22:22.410535833 -0400 +++ graywolf_new/src/twsc/sortpin.c 2015-05-15 11:26:40.010562495 -0400 @@ -43,6 +43,7 @@ INT maxpins ; /* maximum numpins over all pins */ CBOXPTR ptr ; /* current cell */ BOOL pin_groups ; /* true if swappable gates occur */ + INT i; /* find the maximum number of pins on a cell for allocation */ /* also see if pin groups exist on any of the cells */ @@ -51,8 +52,15 @@ for( cell = 1; cell <= numcellsG; cell++ ){ ptr = carrayG[cell] ; maxpins = MAX( ptr->numterms, maxpins ) ; - if( ptr->num_pin_group > 0 ){ - pin_groups = TRUE ; + if( ptr->num_swap_group > 0 ) { + for (i = 0; i < ptr->num_swap_group; i++) { + SGLIST *sglistptr; + sglistptr = ptr->swapgroups + i; + if( sglistptr->num_pin_group > 0 ){ + pin_groups = TRUE ; + break; + } + } } } diff -Naur graywolf/src/twsc/standard.h graywolf_new/src/twsc/standard.h --- graywolf/src/twsc/standard.h 2015-05-15 22:22:22.410535833 -0400 +++ graywolf_new/src/twsc/standard.h 2015-05-15 21:41:31.079393411 -0400 @@ -36,6 +36,9 @@ /* I/O macros */ #include +/* Pin list includes an embedded hash table */ +#include + #ifdef MAIN_VARS #define EXTERN #else @@ -170,6 +173,24 @@ SHORT_LONG top ; } *TIBOXPTR, TIBOX ; +// Each cell defines any number of swap groups. +// Each swap group has a record containing the +// swap group number and the number of pin groups +// in the cell belonging to that swap group. +// +// The most common uses are clock/buffer tree +// optimization and scan chain optimization. +// For these, num_pin_group is normally 1. +// +// Note that this record does not specify +// where in the swap group to find the pin +// group(s). + +typedef struct swapgrouplist { + SHORT swap_group ; + SHORT num_pin_group ; +} *SGLISTPTR, SGLIST ; + typedef struct cellbox { char *cname ; char corient ; @@ -184,8 +205,8 @@ SHORT_LONG clength ; SHORT cblock ; SHORT numterms ; - SHORT swap_group ; - SHORT num_pin_group ; + SHORT num_swap_group ; + SGLISTPTR swapgroups ; GLISTPTR paths ; /* timing paths of a cell */ struct pad_rec *padptr; struct fencebox *fence; @@ -249,12 +270,13 @@ typedef struct pin_list { /* list of pins */ PINBOXPTR swap_pin ; - struct pin_list *next ; + struct pin_list *next ; /* Next pin in pin group */ + struct pin_list *next_grp ; /* Next pin group in same cell */ } PINLIST, *PINLISTPTR ; typedef struct swapbox { /* list of list of pins to be swapped */ INT num_pin_grps ; - PINLISTPTR *pin_grp_array ; + YHASHPTR pin_grp_hash ; } SWAPBOX ; /* ****************** GLOBALS ************************** */ diff -Naur graywolf/src/twsc/uloop.c graywolf_new/src/twsc/uloop.c --- graywolf/src/twsc/uloop.c 2015-05-15 22:22:22.411535835 -0400 +++ graywolf_new/src/twsc/uloop.c 2015-05-15 19:24:08.971148504 -0400 @@ -259,7 +259,14 @@ If two cells have the same swap_group then parts of the cells are interchangable. Below we check if the cell#aG belongs to a swap_group ------------------------------------------------------------------------ */ - if( acellptr->swap_group > 0 ) { + if( acellptr->num_swap_group > 0 ) { + INT sgroup; + SGLISTPTR sglistptr; + i = PICK_INT( 0 , acellptr->num_swap_group ) ; + sglistptr = acellptr->swapgroups + i; + sgroup = sglistptr->swap_group; + + trials = 0 ; /*--- number of max trials (heuristically)=50 ---*/ do { /* ----------------------------------------------------------------- @@ -288,7 +295,12 @@ bG = 0 ; } if( bG != 0 && aG != bG ) { - if( acellptr->swap_group == bcellptr->swap_group ) { + for (j = 0; j < bcellptr->num_swap_group; j++) { + sglistptr = bcellptr->swapgroups + j; + if (sglistptr->swap_group == sgroup) + break; + } + if (j < bcellptr->num_swap_group) { break ; } else { trials++ ; @@ -301,18 +313,20 @@ if( trials <= 50 ) { for( swaps = 1 ; swaps <= 4 ; swaps++ ) { /* -- gate_swap evaluates the proposed gate swaps --*/ - gate_switches += gate_swap( 1 ) ; + gate_switches += gate_swap( 1, i, j ) ; gate_attempts++ ; } } - if( acellptr->num_pin_group > 1 ) { + sglistptr = acellptr->swapgroups + i; + + // If a cell has more than one pin group in the same + // swap group, then it can permute pin groups within + // itself. + + if( sglistptr->num_pin_group > 1 ) { for( swaps = 1 ; swaps <= 4 ; swaps++ ) { - gate_swap( 0 ) ; - /* - gate_switches += gate_swap( 0 ) ; - gate_attempts++ ; - */ + gate_swap( 0, i, j ) ; } } }