SRC/rr_graph2.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

struct s_ivec *** alloc_and_load_rr_node_indices (IN int nodes_per_chan, IN int nx, IN int ny, INOUT int *index, IN t_seg_details *seg_details)
void free_rr_node_indices (IN t_ivec ***rr_node_indices)
int get_rr_node_index (int x, int y, t_rr_type rr_type, int ptc, t_ivec ***rr_node_indices)
void free_seg_details (t_seg_details *seg_details, int nodes_per_chan)
t_seg_detailsalloc_and_load_seg_details (INOUT int *nodes_per_chan, IN int max_len, IN int num_seg_types, IN t_segment_inf *segment_inf, IN boolean use_full_seg_groups, IN boolean is_global_graph, IN enum e_directionality directionality)
void dump_seg_details (t_seg_details *seg_details, int nodes_per_chan, char *fname)
int get_seg_start (IN t_seg_details *seg_details, IN int itrack, IN int chan_num, IN int seg_num)
int get_seg_end (IN t_seg_details *seg_details, IN int itrack, IN int istart, IN int chan_num, IN int seg_max)
boolean is_cbox (IN int chan, IN int seg, IN int track, IN t_seg_details *seg_details, IN enum e_directionality directionality)
boolean is_sbox (IN int chan, IN int wire_seg, IN int sb_seg, IN int track, IN t_seg_details *seg_details, IN enum e_directionality directionality)
int get_bidir_opin_connections (IN int i, IN int j, IN int ipin, IN struct s_linked_edge **edge_list, IN int *****opin_to_track_map, IN int Fc, IN boolean *rr_edge_done, IN t_ivec ***rr_node_indices, IN t_seg_details *seg_details)
int get_unidir_opin_connections (IN int chan, IN int seg, IN int Fc, IN t_rr_type chan_type, IN t_seg_details *seg_details, INOUT t_linked_edge **edge_list_ptr, INOUT int **Fc_ofs, INOUT boolean *rr_edge_done, IN int max_len, IN int nodes_per_chan, IN t_ivec ***rr_node_indices, OUT boolean *Fc_clipped)
int get_track_to_ipins (int seg, int chan, int track, t_linked_edge **edge_list_ptr, t_ivec ***rr_node_indices, struct s_ivec ****track_to_ipin_lookup, t_seg_details *seg_details, enum e_rr_type chan_type, int chan_length, int wire_to_ipin_switch, enum e_directionality directionality)
int get_track_to_tracks (IN int from_chan, IN int from_seg, IN int from_track, IN t_rr_type from_type, IN int to_seg, IN t_rr_type to_type, IN int chan_len, IN int nodes_per_chan, IN int *opin_mux_size, IN int Fs_per_side, IN short *****sblock_pattern, INOUT struct s_linked_edge **edge_list, IN t_seg_details *seg_details, IN enum e_directionality directionality, IN t_ivec ***rr_node_indices, INOUT boolean *rr_edge_done, IN struct s_ivec ***switch_block_conn)
short ***** alloc_sblock_pattern_lookup (IN int nx, IN int ny, IN int nodes_per_chan)
void free_sblock_pattern_lookup (INOUT short *****sblock_pattern)
void load_sblock_pattern_lookup (IN int i, IN int j, IN int nodes_per_chan, IN t_seg_details *seg_details, IN int Fs, IN enum e_switch_block_type switch_block_type, INOUT short *****sblock_pattern)

Variables

booleanrr_edge_done

Function Documentation

struct s_ivec*** alloc_and_load_rr_node_indices ( IN int  nodes_per_chan,
IN int  nx,
IN int  ny,
INOUT int *  index,
IN t_seg_details seg_details 
) [read]

Definition at line 928 of file rr_graph2.c.

00933 {
00934 
00935     /* Allocates and loads all the structures needed for fast lookups of the   *
00936      * index of an rr_node.  rr_node_indices is a matrix containing the index  *
00937      * of the *first* rr_node at a given (i,j) location.                       */
00938 
00939     int i, j, k, ofs;
00940     t_ivec ***indices;
00941     t_ivec tmp;
00942     t_type_ptr type;
00943 
00944     /* Alloc the lookup table */
00945     indices = (t_ivec ***) my_malloc(sizeof(t_ivec **) * NUM_RR_TYPES);
00946     indices[IPIN] = (t_ivec **) my_malloc(sizeof(t_ivec *) * (nx + 2));
00947     indices[SINK] = (t_ivec **) my_malloc(sizeof(t_ivec *) * (nx + 2));
00948     for(i = 0; i <= (nx + 1); ++i)
00949         {
00950             indices[IPIN][i] =
00951                 (t_ivec *) my_malloc(sizeof(t_ivec) * (ny + 2));
00952             indices[SINK][i] =
00953                 (t_ivec *) my_malloc(sizeof(t_ivec) * (ny + 2));
00954             for(j = 0; j <= (ny + 1); ++j)
00955                 {
00956                     indices[IPIN][i][j].nelem = 0;
00957                     indices[IPIN][i][j].list = NULL;
00958 
00959                     indices[SINK][i][j].nelem = 0;
00960                     indices[SINK][i][j].list = NULL;
00961                 }
00962         }
00963 
00964 
00965     /* Count indices for block nodes */
00966     for(i = 0; i <= (nx + 1); i++)
00967         {
00968             for(j = 0; j <= (ny + 1); j++)
00969                 {
00970                     ofs = grid[i][j].offset;
00971                     if(0 == ofs)
00972                         {
00973                             type = grid[i][j].type;
00974 
00975                             /* Load the pin class lookups. The ptc nums for SINK and SOURCE
00976                              * are disjoint so they can share the list. */
00977                             tmp.nelem = type->num_class;
00978                             tmp.list = NULL;
00979                             if(tmp.nelem > 0)
00980                                 {
00981                                     tmp.list =
00982                                         (int *)my_malloc(sizeof(int) *
00983                                                          tmp.nelem);
00984                                     for(k = 0; k < tmp.nelem; ++k)
00985                                         {
00986                                             tmp.list[k] = *index;
00987                                             ++(*index);
00988                                         }
00989                                 }
00990                             indices[SINK][i][j] = tmp;
00991 
00992                             /* Load the pin lookups. The ptc nums for IPIN and OPIN
00993                              * are disjoint so they can share the list. */
00994                             tmp.nelem = type->num_pins;
00995                             tmp.list = NULL;
00996                             if(tmp.nelem > 0)
00997                                 {
00998                                     tmp.list =
00999                                         (int *)my_malloc(sizeof(int) *
01000                                                          tmp.nelem);
01001                                     for(k = 0; k < tmp.nelem; ++k)
01002                                         {
01003                                             tmp.list[k] = *index;
01004                                             ++(*index);
01005                                         }
01006                                 }
01007                             indices[IPIN][i][j] = tmp;
01008                         }
01009                 }
01010         }
01011 
01012     /* Point offset blocks of a large block to base block */
01013     for(i = 0; i <= (nx + 1); i++)
01014         {
01015             for(j = 0; j <= (ny + 1); j++)
01016                 {
01017                     ofs = grid[i][j].offset;
01018                     if(ofs > 0)
01019                         {
01020                             /* NOTE: this only supports vertical large blocks */
01021                             indices[SINK][i][j] = indices[SINK][i][j - ofs];
01022                             indices[IPIN][i][j] = indices[IPIN][i][j - ofs];
01023                         }
01024                 }
01025         }
01026 
01027     /* SOURCE and SINK have unique ptc values so their data can be shared.
01028      * IPIN and OPIN have unique ptc values so their data can be shared. */
01029     indices[SOURCE] = indices[SINK];
01030     indices[OPIN] = indices[IPIN];
01031 
01032     /* Load the data for x and y channels */
01033     load_chan_rr_indices(nodes_per_chan, nx + 1, ny + 1, CHANX,
01034                          seg_details, index, indices);
01035     load_chan_rr_indices(nodes_per_chan, ny + 1, nx + 1, CHANY,
01036                          seg_details, index, indices);
01037 
01038     return indices;
01039 }

Here is the call graph for this function:

Here is the caller graph for this function:

t_seg_details* alloc_and_load_seg_details ( INOUT int *  nodes_per_chan,
IN int  max_len,
IN int  num_seg_types,
IN t_segment_inf segment_inf,
IN boolean  use_full_seg_groups,
IN boolean  is_global_graph,
IN enum e_directionality  directionality 
)

Definition at line 241 of file rr_graph2.c.

00248 {
00249 
00250     /* Allocates and loads the seg_details data structure.  Max_len gives the   *
00251      * maximum length of a segment (dimension of array).  The code below tries  *
00252      * to:                                                                      *
00253      * (1) stagger the start points of segments of the same type evenly;        *
00254      * (2) spread out the limited number of connection boxes or switch boxes    *
00255      *     evenly along the length of a segment, starting at the segment ends;  *
00256      * (3) stagger the connection and switch boxes on different long lines,     *
00257      *     as they will not be staggered by different segment start points.     */
00258 
00259     int i, cur_track, ntracks, itrack, length, j, index;
00260     int wire_switch, opin_switch, fac, num_sets, tmp;
00261     int group_start, first_track;
00262     int *sets_per_seg_type = NULL;
00263     t_seg_details *seg_details = NULL;
00264     boolean longline;
00265 
00266     /* Unidir tracks are assigned in pairs, and bidir tracks individually */
00267     if(directionality == BI_DIRECTIONAL)
00268         {
00269             fac = 1;
00270         }
00271     else
00272         {
00273             assert(directionality == UNI_DIRECTIONAL);
00274             fac = 2;
00275         }
00276     assert(*nodes_per_chan % fac == 0);
00277 
00278     /* Map segment type fractions and groupings to counts of tracks */
00279     sets_per_seg_type = get_seg_track_counts((*nodes_per_chan / fac),
00280                                              num_seg_types,
00281                                              segment_inf,
00282                                              use_full_seg_groups);
00283 
00284     /* Count the number tracks actually assigned. */
00285     tmp = 0;
00286     for(i = 0; i < num_seg_types; ++i)
00287         {
00288             tmp += sets_per_seg_type[i] * fac;
00289         }
00290     assert(use_full_seg_groups || (tmp == *nodes_per_chan));
00291     *nodes_per_chan = tmp;
00292 
00293     seg_details = (t_seg_details *)
00294         my_malloc(*nodes_per_chan * sizeof(t_seg_details));
00295 
00296     /* Setup the seg_details data */
00297     cur_track = 0;
00298     for(i = 0; i < num_seg_types; ++i)
00299         {
00300             first_track = cur_track;
00301 
00302             num_sets = sets_per_seg_type[i];
00303             ntracks = fac * num_sets;
00304             if(ntracks < 1)
00305                 {
00306                     continue;
00307                 }
00308             /* Avoid divide by 0 if ntracks */
00309             longline = segment_inf[i].longline;
00310             length = segment_inf[i].length;
00311             if(longline)
00312                 {
00313                     length = max_len;
00314                 }
00315 
00316             wire_switch = segment_inf[i].wire_switch;
00317             opin_switch = segment_inf[i].opin_switch;
00318             assert((wire_switch == opin_switch)
00319                    || (directionality != UNI_DIRECTIONAL));
00320 
00321             /* Set up the tracks of same type */
00322             group_start = 0;
00323             for(itrack = 0; itrack < ntracks; itrack++)
00324                 {
00325 
00326                     /* Remember the start track of the current wire group */
00327                     if((itrack / fac) % length == 0 && (itrack % fac) == 0)
00328                         {
00329                             group_start = cur_track;
00330                         }
00331 
00332                     seg_details[cur_track].length = length;
00333                     seg_details[cur_track].longline = longline;
00334 
00335                     /* Stagger the start points in for each track set. The 
00336                      * pin mappings should be aware of this when chosing an
00337                      * intelligent way of connecting pins and tracks.
00338                      * cur_track is used as an offset so that extra tracks
00339                      * from different segment types are hopefully better
00340                      * balanced. */
00341                     seg_details[cur_track].start =
00342                         (cur_track / fac) % length + 1;
00343 
00344                     /* These properties are used for vpr_to_phy_track to determine
00345                      * * twisting of wires. */
00346                     seg_details[cur_track].group_start = group_start;
00347                     seg_details[cur_track].group_size =
00348                         min(ntracks + first_track - group_start,
00349                             length * fac);
00350                     assert(0 == seg_details[cur_track].group_size % fac);
00351                     if(0 == seg_details[cur_track].group_size)
00352                         {
00353                             seg_details[cur_track].group_size = length * fac;
00354                         }
00355 
00356                     /* Setup the cb and sb patterns. Global route graphs can't depopulate cb and sb
00357                      * since this is a property of a detailed route. */
00358                     seg_details[cur_track].cb =
00359                         (boolean *) my_malloc(length * sizeof(boolean));
00360                     seg_details[cur_track].sb =
00361                         (boolean *) my_malloc((length + 1) * sizeof(boolean));
00362                     for(j = 0; j < length; ++j)
00363                         {
00364                             if(is_global_graph)
00365                                 {
00366                                     seg_details[cur_track].cb[j] = TRUE;
00367                                 }
00368                             else
00369                                 {
00370                                     index = j;
00371 
00372                                     /* Rotate longline's so they vary across the FPGA */
00373                                     if(longline)
00374                                         {
00375                                             index = (index + itrack) % length;
00376                                         }
00377 
00378                                     /* Reverse the order for tracks going in DEC_DIRECTION */
00379                                     if(itrack % fac == 1)
00380                                         {
00381                                             index = (length - 1) - j;
00382                                         }
00383 
00384                                     /* Use the segment's pattern. */
00385                                     index = j % segment_inf[i].cb_len;
00386                                     seg_details[cur_track].cb[j] =
00387                                         segment_inf[i].cb[index];
00388                                 }
00389                         }
00390                     for(j = 0; j < (length + 1); ++j)
00391                         {
00392                             if(is_global_graph)
00393                                 {
00394                                     seg_details[cur_track].sb[j] = TRUE;
00395                                 }
00396                             else
00397                                 {
00398                                     index = j;
00399 
00400                                     /* Rotate longline's so they vary across the FPGA */
00401                                     if(longline)
00402                                         {
00403                                             index =
00404                                                 (index + itrack) % (length +
00405                                                                     1);
00406                                         }
00407 
00408                                     /* Reverse the order for tracks going in DEC_DIRECTION */
00409                                     if(itrack % fac == 1)
00410                                         {
00411                                             index = ((length + 1) - 1) - j;
00412                                         }
00413 
00414                                     /* Use the segment's pattern. */
00415                                     index = j % segment_inf[i].sb_len;
00416                                     seg_details[cur_track].sb[j] =
00417                                         segment_inf[i].sb[index];
00418                                 }
00419                         }
00420 
00421                     seg_details[cur_track].Rmetal = segment_inf[i].Rmetal;
00422                     seg_details[cur_track].Cmetal = segment_inf[i].Cmetal;
00423 
00424                     seg_details[cur_track].wire_switch = wire_switch;
00425                     seg_details[cur_track].opin_switch = opin_switch;
00426 
00427                     if(BI_DIRECTIONAL == directionality)
00428                         {
00429                             seg_details[cur_track].direction = BI_DIRECTION;
00430                         }
00431                     else
00432                         {
00433                             assert(UNI_DIRECTIONAL == directionality);
00434                             seg_details[cur_track].direction =
00435                                 (itrack % 2) ? DEC_DIRECTION : INC_DIRECTION;
00436                         }
00437 
00438                     switch (segment_inf[i].directionality)
00439                         {
00440                         case UNI_DIRECTIONAL:
00441                             seg_details[cur_track].drivers = SINGLE;
00442                             break;
00443                         case BI_DIRECTIONAL:
00444                             seg_details[cur_track].drivers = MULTI_BUFFERED;
00445                             break;
00446                         }
00447 
00448                     seg_details[cur_track].index = i;
00449 
00450                     ++cur_track;
00451                 }
00452         }                       /* End for each segment type. */
00453 
00454         /* free variables */
00455         free(sets_per_seg_type);
00456 
00457     return seg_details;
00458 }

Here is the call graph for this function:

Here is the caller graph for this function:

short***** alloc_sblock_pattern_lookup ( IN int  nx,
IN int  ny,
IN int  nodes_per_chan 
)

Definition at line 1893 of file rr_graph2.c.

01896 {
01897     int i, j, from_side, to_side, itrack, items;
01898     short *****result;
01899     short *****i_list;
01900     short ****j_list;
01901     short ***from_list;
01902     short **to_list;
01903     short *track_list;
01904 
01905     /* loading up the sblock connection pattern matrix. It's a huge matrix because
01906      * for nonquantized W, it's impossible to make simple permutations to figure out
01907      * where muxes are and how to connect to them such that their sizes are balanced */
01908 
01909     /* Do chunked allocations to make freeing easier, speed up malloc and free, and
01910      * reduce some of the memory overhead. Could use fewer malloc's but this way
01911      * avoids all considerations of pointer sizes and allignment. */
01912 
01913     /* Alloc each list of pointers in one go. items is a running product that increases
01914      * with each new dimension of the matrix. */
01915     items = 1;
01916     items *= (nx + 1);
01917     i_list = (short *****)my_malloc(sizeof(short ****) * items);
01918     items *= (ny + 1);
01919     j_list = (short ****)my_malloc(sizeof(short ***) * items);
01920     items *= (4);
01921     from_list = (short ***)my_malloc(sizeof(short **) * items);
01922     items *= (4);
01923     to_list = (short **)my_malloc(sizeof(short *) * items);
01924     items *= (nodes_per_chan);
01925     track_list = (short *)my_malloc(sizeof(short) * items);
01926 
01927     /* Build the pointer lists to form the multidimensional array */
01928     result = i_list;
01929     i_list += (nx + 1);         /* Skip forward nx+1 items */
01930     for(i = 0; i < (nx + 1); ++i)
01931         {
01932 
01933             result[i] = j_list;
01934             j_list += (ny + 1); /* Skip forward ny+1 items */
01935             for(j = 0; j < (ny + 1); ++j)
01936                 {
01937 
01938                     result[i][j] = from_list;
01939                     from_list += (4);   /* Skip forward 4 items */
01940                     for(from_side = 0; from_side < 4; ++from_side)
01941                         {
01942 
01943                             result[i][j][from_side] = to_list;
01944                             to_list += (4);     /* Skip forward 4 items */
01945                             for(to_side = 0; to_side < 4; ++to_side)
01946                                 {
01947 
01948                                     result[i][j][from_side][to_side] =
01949                                         track_list;
01950                                     track_list += (nodes_per_chan);     /* Skip forward nodes_per_chan items */
01951                                     for(itrack = 0; itrack < nodes_per_chan;
01952                                         itrack++)
01953                                         {
01954 
01955                                             /* Set initial value to be unset */
01956                                             result[i][j][from_side][to_side]
01957                                                 [itrack] = UN_SET;
01958                                         }
01959                                 }
01960                         }
01961                 }
01962         }
01963 
01964     /* This is the outer pointer to the full matrix */
01965     return result;
01966 }

Here is the call graph for this function:

Here is the caller graph for this function:

void dump_seg_details ( t_seg_details seg_details,
int  nodes_per_chan,
char *  fname 
)

Definition at line 481 of file rr_graph2.c.

00484 {
00485 
00486     FILE *fp;
00487     int i, j;
00488     const char *drivers_names[] = { "multi_buffered",
00489         "multi_muxed",
00490         "multi_merged",
00491         "single"
00492     };
00493     const char *direction_names[] = { "inc_direction",
00494         "dec_direction",
00495         "bi_direction"
00496     };
00497 
00498     fp = my_fopen(fname, "w");
00499 
00500     for(i = 0; i < nodes_per_chan; i++)
00501         {
00502             fprintf(fp, "Track: %d.\n", i);
00503             fprintf(fp, "Length: %d,  Start: %d,  Long line: %d  "
00504                     "wire_switch: %d  opin_switch: %d.\n",
00505                     seg_details[i].length,
00506                     seg_details[i].start,
00507                     seg_details[i].longline,
00508                     seg_details[i].wire_switch, seg_details[i].opin_switch);
00509 
00510             fprintf(fp, "Rmetal: %g  Cmetal: %g\n",
00511                     seg_details[i].Rmetal, seg_details[i].Cmetal);
00512 
00513             fprintf(fp, "Direction: %s  Drivers: %s\n",
00514                     direction_names[seg_details[i].direction],
00515                     drivers_names[seg_details[i].drivers]);
00516 
00517             fprintf(fp, "Start Track: %d  End Track: %d\n",
00518                     seg_details[i].start_track, seg_details[i].end_track);
00519 
00520             fprintf(fp, "cb list:  ");
00521             for(j = 0; j < seg_details[i].length; j++)
00522                 fprintf(fp, "%d ", seg_details[i].cb[j]);
00523             fprintf(fp, "\n");
00524 
00525             fprintf(fp, "sb list: ");
00526             for(j = 0; j <= seg_details[i].length; j++)
00527                 fprintf(fp, "%d ", seg_details[i].sb[j]);
00528             fprintf(fp, "\n");
00529 
00530             fprintf(fp, "\n");
00531         }
00532 
00533     fclose(fp);
00534 }

Here is the call graph for this function:

Here is the caller graph for this function:

void free_rr_node_indices ( IN t_ivec ***  rr_node_indices  ) 

Definition at line 1043 of file rr_graph2.c.

01044 {
01045         int i, j, ofs;
01046     /* This function must unallocate the structure allocated in 
01047      * alloc_and_load_rr_node_indices. */
01048         for(i = 0; i <= (nx + 1); ++i)
01049         {
01050                 for(j = 0; j <= (ny + 1); ++j)
01051                 {
01052                         ofs = grid[i][j].offset;
01053                     if(ofs > 0)
01054                         {
01055                             /* Vertical large blocks reference is same as offset 0 */
01056                             rr_node_indices[SINK][i][j].list = NULL;
01057                                 rr_node_indices[IPIN][i][j].list = NULL;
01058                                 continue;
01059                         }
01060                         if(rr_node_indices[SINK][i][j].list != NULL) {
01061                                 free(rr_node_indices[SINK][i][j].list);
01062                         }
01063                         if(rr_node_indices[IPIN][i][j].list != NULL) {
01064                                 free(rr_node_indices[IPIN][i][j].list);
01065                         }
01066                 }
01067                 free(rr_node_indices[SINK][i]);
01068                 free(rr_node_indices[IPIN][i]);
01069         }
01070         free(rr_node_indices[SINK]);
01071         free(rr_node_indices[IPIN]);
01072 
01073         for(i = 0; i < (nx + 1); ++i)
01074         {
01075                 for(j = 0; j < (ny + 1); ++j)
01076                 {
01077                         if(rr_node_indices[CHANY][i][j].list != NULL) {
01078                                 free(rr_node_indices[CHANY][i][j].list);
01079                         }
01080                 }
01081                 free(rr_node_indices[CHANY][i]);
01082         }
01083         free(rr_node_indices[CHANY]);
01084 
01085         for(i = 0; i < (ny + 1); ++i)
01086         {
01087                 for(j = 0; j < (nx + 1); ++j)
01088                 {
01089                         if(rr_node_indices[CHANX][i][j].list != NULL) {
01090                                 free(rr_node_indices[CHANX][i][j].list);
01091                         }
01092                 }
01093                 free(rr_node_indices[CHANX][i]);
01094         }
01095         free(rr_node_indices[CHANX]);
01096 
01097         free(rr_node_indices);
01098 }

Here is the caller graph for this function:

void free_sblock_pattern_lookup ( INOUT short *****  sblock_pattern  ) 

Definition at line 1970 of file rr_graph2.c.

01971 {
01972     /* This free function corresponds to the chunked matrix 
01973      * allocation above and there should only be one free
01974      * call for each dimension. */
01975 
01976     /* Free dimensions from the inner one, outwards so
01977      * we can still access them. The comments beside
01978      * each one indicate the corresponding name used when
01979      * allocating them. */
01980     free(****sblock_pattern);   /* track_list */
01981     free(***sblock_pattern);    /* to_list */
01982     free(**sblock_pattern);     /* from_list */
01983     free(*sblock_pattern);      /* j_list */
01984     free(sblock_pattern);       /* i_list */
01985 }

Here is the caller graph for this function:

void free_seg_details ( t_seg_details seg_details,
int  nodes_per_chan 
)

Definition at line 461 of file rr_graph2.c.

00463 {
00464 
00465     /* Frees all the memory allocated to an array of seg_details structures. */
00466 
00467     int i;
00468 
00469     for(i = 0; i < nodes_per_chan; i++)
00470         {
00471             free(seg_details[i].cb);
00472             free(seg_details[i].sb);
00473         }
00474     free(seg_details);
00475 }

Here is the caller graph for this function:

int get_bidir_opin_connections ( IN int  i,
IN int  j,
IN int  ipin,
IN struct s_linked_edge **  edge_list,
IN int *****  opin_to_track_map,
IN int  Fc,
IN boolean rr_edge_done,
IN t_ivec ***  rr_node_indices,
IN t_seg_details seg_details 
)

Definition at line 621 of file rr_graph2.c.

00630 {
00631 
00632     int iside, num_conn, ofs, tr_i, tr_j, chan, seg;
00633     int to_track, to_switch, to_node, iconn;
00634         int is_connected_track;
00635     t_type_ptr type;
00636     t_rr_type to_type;
00637 
00638     type = grid[i][j].type;
00639     ofs = grid[i][j].offset;
00640 
00641     num_conn = 0;
00642 
00643     /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */
00644     for(iside = 0; iside < 4; iside++)
00645         {
00646 
00647             /* Figure out coords of channel segment based on side */
00648             tr_i = ((iside == LEFT) ? (i - 1) : i);
00649             tr_j = ((iside == BOTTOM) ? (j - 1) : j);
00650 
00651             to_type = ((iside == LEFT) || (iside == RIGHT)) ? CHANY : CHANX;
00652 
00653             chan = ((to_type == CHANX) ? tr_j : tr_i);
00654             seg = ((to_type == CHANX) ? tr_i : tr_j);
00655 
00656             /* Don't connect where no tracks on fringes */
00657             if((tr_i < 0) || (tr_i > nx))
00658                 {
00659                     continue;
00660                 }
00661             if((tr_j < 0) || (tr_j > ny))
00662                 {
00663                     continue;
00664                 }
00665             if((CHANX == to_type) && (tr_i < 1))
00666                 {
00667                     continue;
00668                 }
00669             if((CHANY == to_type) && (tr_j < 1))
00670                 {
00671                     continue;
00672                 }
00673 
00674                 is_connected_track = FALSE;
00675 
00676             /* Itterate of the opin to track connections */
00677             for(iconn = 0; iconn < Fc; ++iconn)
00678                 {
00679                     to_track =
00680                         opin_to_track_map[type->
00681                                           index][ipin][ofs][iside][iconn];
00682 
00683                     /* Skip unconnected connections */
00684                     if(OPEN == to_track || is_connected_track)
00685                         {
00686                                 is_connected_track = TRUE;
00687                             assert(OPEN ==
00688                                    opin_to_track_map[type->
00689                                                      index][ipin][ofs][iside]
00690                                    [0]);
00691                             continue;
00692                         }
00693 
00694                     /* Only connect to wire if there is a CB */
00695                     if(is_cbox
00696                        (chan, seg, to_track, seg_details, BI_DIRECTIONAL))
00697                         {
00698                             to_switch = seg_details[to_track].wire_switch;
00699                             to_node =
00700                                 get_rr_node_index(tr_i, tr_j, to_type,
00701                                                   to_track, rr_node_indices);
00702 
00703                             *edge_list =
00704                                 insert_in_edge_list(*edge_list, to_node,
00705                                                     to_switch);
00706                             rr_edge_done[to_node] = TRUE;
00707                             ++num_conn;
00708                         }
00709                 }
00710         }
00711 
00712     return num_conn;
00713 }

Here is the call graph for this function:

Here is the caller graph for this function:

int get_rr_node_index ( int  x,
int  y,
t_rr_type  rr_type,
int  ptc,
t_ivec ***  rr_node_indices 
)

Definition at line 1102 of file rr_graph2.c.

01107 {
01108     /* Returns the index of the specified routing resource node.  (x,y) are     *
01109      * the location within the FPGA, rr_type specifies the type of resource,    *
01110      * and ptc gives the number of this resource.  ptc is the class number,   *
01111      * pin number or track number, depending on what type of resource this      *
01112      * is.  All ptcs start at 0 and go up to pins_per_clb-1 or the equivalent. *
01113      * The order within a clb is:  SOURCEs + SINKs (type->num_class of them); IPINs,  *
01114      * and OPINs (pins_per_clb of them); CHANX; and CHANY (nodes_per_chan of    *
01115      * each).  For (x,y) locations that point at pads the order is:  type->capacity     *
01116      * occurances of SOURCE, SINK, OPIN, IPIN (one for each pad), then one      *
01117      * associated channel (if there is a channel at (x,y)).  All IO pads are    *
01118      * bidirectional, so while each will be used only as an INPAD or as an      *
01119      * OUTPAD, all the switches necessary to do both must be in each pad.       *
01120      *                                                                          *
01121      * Note that for segments (CHANX and CHANY) of length > 1, the segment is   *
01122      * given an rr_index based on the (x,y) location at which it starts (i.e.   *
01123      * lowest (x,y) location at which this segment exists).                     *
01124      * This routine also performs error checking to make sure the node in       *
01125      * question exists.                                                         */
01126 
01127     int iclass, tmp;
01128     t_type_ptr type;
01129     t_ivec lookup;
01130 
01131     assert(ptc >= 0);
01132     assert(x >= 0 && x <= (nx + 1));
01133     assert(y >= 0 && y <= (ny + 1));
01134 
01135     type = grid[x][y].type;
01136 
01137     /* Currently need to swap x and y for CHANX because of chan, seg convention */
01138     if(CHANX == rr_type)
01139         {
01140             tmp = x;
01141             x = y;
01142             y = tmp;
01143         }
01144 
01145     /* Start of that block.  */
01146     lookup = rr_node_indices[rr_type][x][y];
01147 
01148     /* Check valid ptc num */
01149     assert(ptc >= 0);
01150     assert(ptc < lookup.nelem);
01151 
01152 #ifdef DEBUG
01153     switch (rr_type)
01154         {
01155         case SOURCE:
01156             assert(ptc < type->num_class);
01157             assert(type->class_inf[ptc].type == DRIVER);
01158             break;
01159 
01160         case SINK:
01161             assert(ptc < type->num_class);
01162             assert(type->class_inf[ptc].type == RECEIVER);
01163             break;
01164 
01165         case OPIN:
01166             assert(ptc < type->num_pins);
01167             iclass = type->pin_class[ptc];
01168             assert(type->class_inf[iclass].type == DRIVER);
01169             break;
01170 
01171         case IPIN:
01172             assert(ptc < type->num_pins);
01173             iclass = type->pin_class[ptc];
01174             assert(type->class_inf[iclass].type == RECEIVER);
01175             break;
01176 
01177         case CHANX:
01178         case CHANY:
01179             break;
01180 
01181         default:
01182             printf("Error:  Bad rr_node passed to get_rr_node_index.\n"
01183                    "Request for type=%d ptc=%d at (%d, %d).\n",
01184                    rr_type, ptc, x, y);
01185             exit(1);
01186         }
01187 #endif
01188 
01189     return lookup.list[ptc];
01190 }

Here is the caller graph for this function:

int get_seg_end ( IN t_seg_details seg_details,
IN int  itrack,
IN int  istart,
IN int  chan_num,
IN int  seg_max 
)

Definition at line 578 of file rr_graph2.c.

00583 {
00584     int len, ofs, end, first_full;
00585 
00586     len = seg_details[itrack].length;
00587     ofs = seg_details[itrack].start;
00588 
00589     /* Normal endpoint */
00590     end = istart + len - 1;
00591 
00592     /* If start is against edge it may have been clipped */
00593     if(1 == istart)
00594         {
00595             /* If the (staggered) startpoint of first full wire wasn't
00596              * also 1, we must be the clipped wire */
00597             first_full = (len - (chan_num % len) + ofs - 1) % len + 1;
00598             if(first_full > 1)
00599                 {
00600                     /* then we stop just before the first full seg */
00601                     end = first_full - 1;
00602                 }
00603         }
00604 
00605     /* Clip against far edge */
00606     if(end > seg_max)
00607         {
00608             end = seg_max;
00609         }
00610 
00611     return end;
00612 }

Here is the caller graph for this function:

int get_seg_start ( IN t_seg_details seg_details,
IN int  itrack,
IN int  chan_num,
IN int  seg_num 
)

Definition at line 541 of file rr_graph2.c.

00545 {
00546 
00547     int seg_start, length, start;
00548 
00549     seg_start = 1;
00550     if(FALSE == seg_details[itrack].longline)
00551         {
00552 
00553             length = seg_details[itrack].length;
00554             start = seg_details[itrack].start;
00555 
00556             /* Start is guaranteed to be between 1 and length.  Hence adding length to *
00557              * the quantity in brackets below guarantees it will be nonnegative.       */
00558 
00559             assert(start > 0);
00560             assert(start <= length);
00561 
00562             /* NOTE: Start points are staggered between different channels.
00563              * The start point must stagger backwards as chan_num increases.
00564              * Unidirectional routing expects this to allow the N-to-N 
00565              * assumption to be made with respect to ending wires in the core. */
00566             seg_start =
00567                 seg_num - (seg_num + length + chan_num - start) % length;
00568             if(seg_start < 1)
00569                 {
00570                     seg_start = 1;
00571                 }
00572         }
00573 
00574     return seg_start;
00575 }

Here is the caller graph for this function:

int get_track_to_ipins ( int  seg,
int  chan,
int  track,
t_linked_edge **  edge_list_ptr,
t_ivec ***  rr_node_indices,
struct s_ivec ****  track_to_ipin_lookup,
t_seg_details seg_details,
enum e_rr_type  chan_type,
int  chan_length,
int  wire_to_ipin_switch,
enum e_directionality  directionality 
)

Definition at line 1194 of file rr_graph2.c.

01205 {
01206 
01207     /* This counts the fan-out from wire segment (chan, seg, track) to blocks on either side */
01208 
01209     t_linked_edge *edge_list_head;
01210     int j, pass, iconn, phy_track, end, to_node, max_conn, ipin, side, x,
01211         y, num_conn;
01212     t_type_ptr type;
01213     int off;
01214 
01215     /* End of this wire */
01216     end = get_seg_end(seg_details, track, seg, chan, chan_length);
01217 
01218     edge_list_head = *edge_list_ptr;
01219     num_conn = 0;
01220 
01221     for(j = seg; j <= end; j++)
01222         {
01223             if(is_cbox(chan, j, track, seg_details, directionality))
01224                 {
01225                     for(pass = 0; pass < 2; ++pass)
01226                         {
01227                             if(CHANX == chan_type)
01228                                 {
01229                                     x = j;
01230                                     y = chan + pass;
01231                                     side = (0 == pass ? TOP : BOTTOM);
01232                                 }
01233                             else
01234                                 {
01235                                     assert(CHANY == chan_type);
01236                                     x = chan + pass;
01237                                     y = j;
01238                                     side = (0 == pass ? RIGHT : LEFT);
01239                                 }
01240 
01241                             /* PAJ - if the pointed to is an EMPTY then shouldn't look for ipins */
01242                             if(grid[x][y].type == EMPTY_TYPE)
01243                                 continue;
01244 
01245                             /* Move from logical (straight) to physical (twisted) track index 
01246                              * - algorithm assigns ipin connections to same physical track index
01247                              * so that the logical track gets distributed uniformly */
01248                             phy_track =
01249                                 vpr_to_phy_track(track, chan, j, seg_details,
01250                                                  directionality);
01251 
01252                             /* We need the type to find the ipin map for this type */
01253                             type = grid[x][y].type;
01254                             off = grid[x][y].offset;
01255 
01256                             max_conn =
01257                                 track_to_ipin_lookup[type->
01258                                                      index][phy_track][off]
01259                                 [side].nelem;
01260                             for(iconn = 0; iconn < max_conn; iconn++)
01261                                 {
01262                                     ipin =
01263                                         track_to_ipin_lookup[type->
01264                                                              index][phy_track]
01265                                         [off][side].list[iconn];
01266 
01267                                     /* Check there is a connection and Fc map isn't wrong */
01268                                     assert(type->pinloc[off][side][ipin]);
01269                                     assert(type->is_global_pin[ipin] ==
01270                                            FALSE);
01271 
01272                                     to_node =
01273                                         get_rr_node_index(x, y, IPIN, ipin,
01274                                                           rr_node_indices);
01275                                     edge_list_head =
01276                                         insert_in_edge_list(edge_list_head,
01277                                                             to_node,
01278                                                             wire_to_ipin_switch);
01279                                 }
01280                             num_conn += max_conn;
01281                         }
01282                 }
01283         }
01284 
01285     *edge_list_ptr = edge_list_head;
01286     return (num_conn);
01287 }

Here is the call graph for this function:

Here is the caller graph for this function:

int get_track_to_tracks ( IN int  from_chan,
IN int  from_seg,
IN int  from_track,
IN t_rr_type  from_type,
IN int  to_seg,
IN t_rr_type  to_type,
IN int  chan_len,
IN int  nodes_per_chan,
IN int *  opin_mux_size,
IN int  Fs_per_side,
IN short *****  sblock_pattern,
INOUT struct s_linked_edge **  edge_list,
IN t_seg_details seg_details,
IN enum e_directionality  directionality,
IN t_ivec ***  rr_node_indices,
INOUT boolean rr_edge_done,
IN struct s_ivec ***  switch_block_conn 
)

Definition at line 1307 of file rr_graph2.c.

01324 {
01325     int num_conn;
01326     int from_switch, from_end, from_sb, from_first;
01327     int to_chan, to_sb;
01328     int start, end;
01329     struct s_ivec conn_tracks;
01330     boolean from_is_sbox, is_behind, Fs_clipped;
01331     enum e_side from_side_a, from_side_b, to_side;
01332 
01333     assert(from_seg ==
01334            get_seg_start(seg_details, from_track, from_chan, from_seg));
01335 
01336     from_switch = seg_details[from_track].wire_switch;
01337     from_end =
01338         get_seg_end(seg_details, from_track, from_seg, from_chan, chan_len);
01339     from_first = from_seg - 1;
01340 
01341     /* Figure out the sides of SB the from_wire will use */
01342     if(CHANX == from_type)
01343         {
01344             from_side_a = RIGHT;
01345             from_side_b = LEFT;
01346         }
01347     else
01348         {
01349             assert(CHANY == from_type);
01350             from_side_a = TOP;
01351             from_side_b = BOTTOM;
01352         }
01353 
01354     /* Figure out if the to_wire is connecting to a SB 
01355      * that is behind it. */
01356     is_behind = FALSE;
01357     if(to_type == from_type)
01358         {
01359             /* If inline, check that they only are trying
01360              * to connect at endpoints. */
01361             assert((to_seg == (from_end + 1)) || (to_seg == (from_seg - 1)));
01362             if(to_seg > from_end)
01363                 {
01364                     is_behind = TRUE;
01365                 }
01366         }
01367     else
01368         {
01369             /* If bending, check that they are adjacent to
01370              * our channel. */
01371             assert((to_seg == from_chan) || (to_seg == (from_chan + 1)));
01372             if(to_seg > from_chan)
01373                 {
01374                     is_behind = TRUE;
01375                 }
01376         }
01377 
01378     /* Figure out the side of SB the to_wires will use.
01379      * The to_seg and from_chan are in same direction. */
01380     if(CHANX == to_type)
01381         {
01382             to_side = (is_behind ? RIGHT : LEFT);
01383         }
01384     else
01385         {
01386             assert(CHANY == to_type);
01387             to_side = (is_behind ? TOP : BOTTOM);
01388         }
01389 
01390     /* Set the loop bounds */
01391     start = from_first;
01392     end = from_end;
01393 
01394     /* If we are connecting in same direction the connection is 
01395      * on one of the two sides so clip the bounds to the SB of
01396      * interest and proceed normally. */
01397     if(to_type == from_type)
01398         {
01399             start = (is_behind ? end : start);
01400             end = start;
01401         }
01402 
01403     /* Iterate over the SBs */
01404     num_conn = 0;
01405     for(from_sb = start; from_sb <= end; ++from_sb)
01406         {
01407             /* Figure out if we are at a sbox */
01408             from_is_sbox = is_sbox(from_chan, from_seg, from_sb, from_track,
01409                                    seg_details, directionality);
01410             /* end of wire must be an sbox */
01411             if(from_sb == from_end || from_sb == from_first)
01412                 {
01413                     from_is_sbox = TRUE;        /* Endpoints always default to true */
01414                 }
01415 
01416             /* to_chan is the current segment if different directions,
01417              * otherwise to_chan is the from_chan */
01418             to_chan = from_sb;
01419             to_sb = from_chan;
01420             if(from_type == to_type)
01421                 {
01422                     to_chan = from_chan;
01423                     to_sb = from_sb;
01424                 }
01425 
01426             /* Do the edges going to the left or down */
01427             if(from_sb < from_end)
01428                 {
01429                     if(BI_DIRECTIONAL == directionality)
01430                         {
01431                             conn_tracks =
01432                                 switch_block_conn[from_side_a][to_side]
01433                                 [from_track];
01434                             num_conn +=
01435                                 get_bidir_track_to_chan_seg(conn_tracks,
01436                                                             rr_node_indices,
01437                                                             to_chan, to_seg,
01438                                                             to_sb, to_type,
01439                                                             seg_details,
01440                                                             from_is_sbox,
01441                                                             from_switch,
01442                                                             rr_edge_done,
01443                                                             directionality,
01444                                                             edge_list);
01445                         }
01446                     if(UNI_DIRECTIONAL == directionality)
01447                         {
01448                             /* No fanout if no SB. */
01449                             /* We are connecting from the top or right of SB so it
01450                              * makes the most sense to only there from DEC_DIRECTION wires. */
01451                             if((from_is_sbox) &&
01452                                (DEC_DIRECTION ==
01453                                 seg_details[from_track].direction))
01454                                 {
01455                                     num_conn +=
01456                                         get_unidir_track_to_chan_seg((from_sb
01457                                                                       ==
01458                                                                       from_first),
01459                                                                      from_track,
01460                                                                      to_chan,
01461                                                                      to_seg,
01462                                                                      to_sb,
01463                                                                      to_type,
01464                                                                      nodes_per_chan,
01465                                                                      nx, ny,
01466                                                                      from_side_a,
01467                                                                      to_side,
01468                                                                      Fs_per_side,
01469                                                                      opin_mux_size,
01470                                                                      sblock_pattern,
01471                                                                      rr_node_indices,
01472                                                                      seg_details,
01473                                                                      rr_edge_done,
01474                                                                      &Fs_clipped,
01475                                                                      edge_list);
01476                                 }
01477                         }
01478                 }
01479 
01480             /* Do the edges going to the right or up */
01481             if(from_sb > from_first)
01482                 {
01483                     if(BI_DIRECTIONAL == directionality)
01484                         {
01485                             conn_tracks =
01486                                 switch_block_conn[from_side_b][to_side]
01487                                 [from_track];
01488                             num_conn +=
01489                                 get_bidir_track_to_chan_seg(conn_tracks,
01490                                                             rr_node_indices,
01491                                                             to_chan, to_seg,
01492                                                             to_sb, to_type,
01493                                                             seg_details,
01494                                                             from_is_sbox,
01495                                                             from_switch,
01496                                                             rr_edge_done,
01497                                                             directionality,
01498                                                             edge_list);
01499                         }
01500                     if(UNI_DIRECTIONAL == directionality)
01501                         {
01502                             /* No fanout if no SB. */
01503                             /* We are connecting from the bottom or left of SB so it
01504                              * makes the most sense to only there from INC_DIRECTION wires. */
01505                             if((from_is_sbox) &&
01506                                (INC_DIRECTION ==
01507                                 seg_details[from_track].direction))
01508                                 {
01509                                     num_conn +=
01510                                         get_unidir_track_to_chan_seg((from_sb
01511                                                                       ==
01512                                                                       from_end),
01513                                                                      from_track,
01514                                                                      to_chan,
01515                                                                      to_seg,
01516                                                                      to_sb,
01517                                                                      to_type,
01518                                                                      nodes_per_chan,
01519                                                                      nx, ny,
01520                                                                      from_side_b,
01521                                                                      to_side,
01522                                                                      Fs_per_side,
01523                                                                      opin_mux_size,
01524                                                                      sblock_pattern,
01525                                                                      rr_node_indices,
01526                                                                      seg_details,
01527                                                                      rr_edge_done,
01528                                                                      &Fs_clipped,
01529                                                                      edge_list);
01530                                 }
01531                         }
01532                 }
01533         }
01534 
01535     return num_conn;
01536 }

Here is the call graph for this function:

Here is the caller graph for this function:

int get_unidir_opin_connections ( IN int  chan,
IN int  seg,
IN int  Fc,
IN t_rr_type  chan_type,
IN t_seg_details seg_details,
INOUT t_linked_edge **  edge_list_ptr,
INOUT int **  Fc_ofs,
INOUT boolean rr_edge_done,
IN int  max_len,
IN int  nodes_per_chan,
IN t_ivec ***  rr_node_indices,
OUT boolean Fc_clipped 
)

Definition at line 718 of file rr_graph2.c.

00730 {
00731     /* Gets a linked list of Fc nodes to connect to in given
00732      * chan seg.  Fc_ofs is used for the for the opin staggering
00733      * pattern. */
00734 
00735     int *inc_muxes = NULL;
00736     int *dec_muxes = NULL;
00737     int num_inc_muxes, num_dec_muxes, iconn;
00738     int inc_inode, dec_inode;
00739     int inc_mux, dec_mux;
00740     int inc_track, dec_track;
00741     int x, y;
00742     int num_edges;
00743 
00744     *Fc_clipped = FALSE;
00745 
00746     /* Fc is assigned in pairs so check it is even. */
00747     assert(Fc % 2 == 0);
00748 
00749     /* get_rr_node_indices needs x and y coords. */
00750     x = ((CHANX == chan_type) ? seg : chan);
00751     y = ((CHANX == chan_type) ? chan : seg);
00752 
00753     /* Get the lists of possible muxes. */
00754     inc_muxes = label_wire_muxes(chan, seg, seg_details, max_len,
00755                                  INC_DIRECTION, nodes_per_chan,
00756                                  &num_inc_muxes);
00757     dec_muxes =
00758         label_wire_muxes(chan, seg, seg_details, max_len, DEC_DIRECTION,
00759                          nodes_per_chan, &num_dec_muxes);
00760 
00761     /* Clip Fc to the number of muxes. */
00762     if(((Fc / 2) > num_inc_muxes) || ((Fc / 2) > num_dec_muxes))
00763         {
00764             *Fc_clipped = TRUE;
00765             Fc = 2 * min(num_inc_muxes, num_dec_muxes);
00766         }
00767 
00768     /* Assign tracks to meet Fc demand */
00769     num_edges = 0;
00770     for(iconn = 0; iconn < (Fc / 2); ++iconn)
00771         {
00772             /* Figure of the next mux to use */
00773             inc_mux = Fc_ofs[chan][seg] % num_inc_muxes;
00774             dec_mux = Fc_ofs[chan][seg] % num_dec_muxes;
00775             ++Fc_ofs[chan][seg];
00776 
00777             /* Figure out the track it corresponds to. */
00778             inc_track = inc_muxes[inc_mux];
00779             dec_track = dec_muxes[dec_mux];
00780 
00781             /* Figure the inodes of those muxes */
00782             inc_inode =
00783                 get_rr_node_index(x, y, chan_type, inc_track,
00784                                   rr_node_indices);
00785             dec_inode =
00786                 get_rr_node_index(x, y, chan_type, dec_track,
00787                                   rr_node_indices);
00788 
00789             /* Add to the list. */
00790             if(FALSE == rr_edge_done[inc_inode])
00791                 {
00792                     rr_edge_done[inc_inode] = TRUE;
00793                     *edge_list_ptr = insert_in_edge_list(*edge_list_ptr,
00794                                                          inc_inode,
00795                                                          seg_details
00796                                                          [inc_track].
00797                                                          opin_switch);
00798                     ++num_edges;
00799                 }
00800             if(FALSE == rr_edge_done[dec_inode])
00801                 {
00802                     rr_edge_done[dec_inode] = TRUE;
00803                     *edge_list_ptr = insert_in_edge_list(*edge_list_ptr,
00804                                                          dec_inode,
00805                                                          seg_details
00806                                                          [dec_track].
00807                                                          opin_switch);
00808                     ++num_edges;
00809                 }
00810         }
00811 
00812     if(inc_muxes)
00813         {
00814             free(inc_muxes);
00815             inc_muxes = NULL;
00816         }
00817     if(dec_muxes)
00818         {
00819             free(dec_muxes);
00820             dec_muxes = NULL;
00821         }
00822 
00823     return num_edges;
00824 }

Here is the call graph for this function:

Here is the caller graph for this function:

boolean is_cbox ( IN int  chan,
IN int  seg,
IN int  track,
IN t_seg_details seg_details,
IN enum e_directionality  directionality 
)

Definition at line 827 of file rr_graph2.c.

00832 {
00833 
00834     int start, length, ofs, fac, start_seg;
00835 
00836     fac = 1;
00837     if(UNI_DIRECTIONAL == directionality)
00838         {
00839             fac = 2;
00840         }
00841 
00842     start = seg_details[track].start;
00843     length = seg_details[track].length;
00844 
00845     /* Make sure they gave us correct start */
00846     start_seg = get_seg_start(seg_details, track, chan, seg);
00847 
00848     ofs = seg - start_seg;
00849 
00850     assert(ofs >= 0);
00851     assert(ofs < length);
00852 
00853     /* If unidir segment that is going backwards, we need to flip the ofs */
00854     if(DEC_DIRECTION == seg_details[track].direction)
00855         {
00856             ofs = (length - 1) - ofs;
00857         }
00858 
00859     return seg_details[track].cb[ofs];
00860 }

Here is the call graph for this function:

Here is the caller graph for this function:

boolean is_sbox ( IN int  chan,
IN int  wire_seg,
IN int  sb_seg,
IN int  track,
IN t_seg_details seg_details,
IN enum e_directionality  directionality 
)

Definition at line 1753 of file rr_graph2.c.

01759 {
01760 
01761     int start, length, ofs, fac;
01762 
01763     fac = 1;
01764     if(UNI_DIRECTIONAL == directionality)
01765         {
01766             fac = 2;
01767         }
01768 
01769     start = seg_details[track].start;
01770     length = seg_details[track].length;
01771 
01772     /* Make sure they gave us correct start */
01773     wire_seg = get_seg_start(seg_details, track, chan, wire_seg);
01774 
01775     ofs = sb_seg - wire_seg + 1;        /* Ofset 0 is behind us, so add 1 */
01776 
01777     assert(ofs >= 0);
01778     assert(ofs < (length + 1));
01779 
01780     /* If unidir segment that is going backwards, we need to flip the ofs */
01781     if((ofs % fac) > 0)
01782         {
01783             ofs = length - ofs;
01784         }
01785 
01786     return seg_details[track].sb[ofs];
01787 }

Here is the call graph for this function:

Here is the caller graph for this function:

void load_sblock_pattern_lookup ( IN int  i,
IN int  j,
IN int  nodes_per_chan,
IN t_seg_details seg_details,
IN int  Fs,
IN enum e_switch_block_type  switch_block_type,
INOUT short *****  sblock_pattern 
)

Definition at line 1989 of file rr_graph2.c.

01996 {
01997 
01998     /* This routine loads a lookup table for sblock topology. The lookup table is huge
01999      * because the sblock varies from location to location. The i, j means the owning
02000      * location of the sblock under investigation. */
02001 
02002     int side_cw_incoming_wire_count, side_ccw_incoming_wire_count,
02003         opp_incoming_wire_count;
02004     int to_side, side, side_cw, side_ccw, side_opp, itrack;
02005     int Fs_per_side, chan, seg, chan_len, sb_seg;
02006     boolean is_core_sblock, is_corner_sblock, x_edge, y_edge;
02007     int *incoming_wire_label[4];
02008     int *wire_mux_on_track[4];
02009     int num_incoming_wires[4];
02010     int num_ending_wires[4];
02011     int num_wire_muxes[4];
02012     boolean skip, vert, pos_dir;
02013     enum e_direction dir;
02014 
02015     Fs_per_side = 1;
02016     if(Fs != -1)
02017         {
02018             Fs_per_side = Fs / 3;
02019         }
02020 
02021     /* SB's have coords from (0, 0) to (nx, ny) */
02022     assert(i >= 0);
02023     assert(i <= nx);
02024     assert(j >= 0);
02025     assert(j <= ny);
02026 
02027     /* May 12 - 15, 2007
02028      *
02029      * I identify three types of sblocks in the chip: 1) The core sblock, whose special
02030      * property is that the number of muxes (and ending wires) on each side is the same (very useful
02031      * property, since it leads to a N-to-N assignment problem with ending wires). 2) The corner sblock
02032      * which is same as a L=1 core sblock with 2 sides only (again N-to-N assignment problem). 3) The
02033      * fringe / chip edge sblock which is most troublesome, as balance in each side of muxes is 
02034      * attainable but balance in the entire sblock is not. The following code first identifies the
02035      * incoming wires, which can be classified into incoming passing wires with sbox and incoming
02036      * ending wires (the word "incoming" is sometimes dropped for ease of discussion). It appropriately 
02037      * labels all the wires on each side by the following order: By the call to label_incoming_wires, 
02038      * which labels for one side, the order is such that the incoming ending wires (always with sbox) 
02039      * are labelled first 0,1,2,... p-1, then the incoming passing wires with sbox are labelled 
02040      * p,p+1,p+2,... k-1 (for total of k). By this convention, one can easily distinguish the ending
02041      * wires from the passing wires by checking a label against num_ending_wires variable. 
02042      *
02043      * After labelling all the incoming wires, this routine labels the muxes on the side we're currently
02044      * connecting to (iterated for four sides of the sblock), called the to_side. The label scheme is
02045      * the natural order of the muxes by their track #. Also we find the number of muxes.
02046      *
02047      * For each to_side, the total incoming wires that connect to the muxes on to_side 
02048      * come from three sides: side_1 (to_side's right), side_2 (to_side's left) and opp_side.
02049      * The problem of balancing mux size is then: considering all incoming passing wires
02050      * with sbox on side_1, side_2 and opp_side, how to assign them to the muxes on to_side
02051      * (with specified Fs) in a way that mux size is imbalanced by at most 1. I solve this
02052      * problem by this approach: the first incoming passing wire will connect to 0, 1, 2, 
02053      * ..., Fs_per_side - 1, then the next incoming passing wire will connect to 
02054      * Fs_per_side, Fs_per_side+1, ..., Fs_per_side*2-1, and so on. This consistent STAGGERING
02055      * ensures N-to-N assignment is perfectly balanced and M-to-N assignment is imbalanced by no
02056      * more than 1.
02057      *
02058      * For the sblock_pattern_init_mux_lookup lookup table, I will only need the lookup
02059      * table to remember the first/init mux to connect, since the convention is Fs_per_side consecutive
02060      * muxes to connect. Then how do I determine the order of the incoming wires? I use the labels
02061      * on side_1, then labels on side_2, then labels on opp_side. Effectively I listed all
02062      * incoming passing wires from the three sides, and order them to each make Fs_per_side
02063      * consecutive connections to muxes, and use % to rotate to keep imbalance at most 1. 
02064      */
02065 
02066     /* SB's range from (0, 0) to (nx, ny) */
02067     /* First find all four sides' incoming wires */
02068     x_edge = ((i < 1) || (i >= nx));
02069     y_edge = ((j < 1) || (j >= ny));
02070 
02071     is_corner_sblock = (x_edge && y_edge);
02072     is_core_sblock = (!x_edge && !y_edge);
02073 
02074     /* "Label" the wires around the switch block by connectivity. */
02075     for(side = 0; side < 4; ++side)
02076         {
02077             /* Assume the channel segment doesn't exist. */
02078             wire_mux_on_track[side] = NULL;
02079             incoming_wire_label[side] = NULL;
02080             num_incoming_wires[side] = 0;
02081             num_ending_wires[side] = 0;
02082             num_wire_muxes[side] = 0;
02083 
02084             /* Skip the side and leave the zero'd value if the
02085              * channel segment doesn't exist. */
02086             skip = TRUE;
02087             switch (side)
02088                 {
02089                 case TOP:
02090                     if(j < ny)
02091                         {
02092                             skip = FALSE;
02093                         };
02094                     break;
02095                 case RIGHT:
02096                     if(i < nx)
02097                         {
02098                             skip = FALSE;
02099                         }
02100                     break;
02101                 case BOTTOM:
02102                     if(j > 0)
02103                         {
02104                             skip = FALSE;
02105                         }
02106                     break;
02107                 case LEFT:
02108                     if(i > 0)
02109                         {
02110                             skip = FALSE;
02111                         }
02112                     break;
02113                 }
02114             if(skip)
02115                 {
02116                     continue;
02117                 }
02118 
02119             /* Figure out the channel and segment for a certain direction */
02120             vert = ((side == TOP) || (side == BOTTOM));
02121             pos_dir = ((side == TOP) || (side == RIGHT));
02122             chan = (vert ? i : j);
02123             sb_seg = (vert ? j : i);
02124             seg = (pos_dir ? (sb_seg + 1) : sb_seg);
02125             chan_len = (vert ? ny : nx);
02126 
02127             /* Figure out all the tracks on a side that are ending and the
02128              * ones that are passing through and have a SB. */
02129             dir = (pos_dir ? DEC_DIRECTION : INC_DIRECTION);
02130             incoming_wire_label[side] =
02131                 label_incoming_wires(chan, seg, sb_seg, seg_details, chan_len,
02132                                      dir, nodes_per_chan,
02133                                      &num_incoming_wires[side],
02134                                      &num_ending_wires[side]);
02135 
02136             /* Figure out all the tracks on a side that are starting. */
02137             dir = (pos_dir ? INC_DIRECTION : DEC_DIRECTION);
02138             wire_mux_on_track[side] = label_wire_muxes(chan, seg,
02139                                                        seg_details, chan_len,
02140                                                        dir, nodes_per_chan,
02141                                                        &num_wire_muxes[side]);
02142         }
02143 
02144     for(to_side = 0; to_side < 4; to_side++)
02145         {
02146             /* Can't do anything if no muxes on this side. */
02147             if(0 == num_wire_muxes[to_side])
02148                 {
02149                     continue;
02150                 }
02151 
02152             /* Figure out side rotations */
02153             assert((TOP == 0) && (RIGHT == 1) && (BOTTOM == 2)
02154                    && (LEFT == 3));
02155             side_cw = (to_side + 1) % 4;
02156             side_opp = (to_side + 2) % 4;
02157             side_ccw = (to_side + 3) % 4;
02158 
02159             /* For the core sblock:
02160              * The new order for passing wires should appear as
02161              * 0,1,2..,scw-1, for passing wires with sbox on side_cw 
02162              * scw,scw+1,...,sccw-1, for passing wires with sbox on side_ccw
02163              * sccw,sccw+1,... for passing wires with sbox on side_opp.
02164              * This way, I can keep the imbalance to at most 1.
02165              *
02166              * For the fringe sblocks, I don't distinguish between
02167              * passing and ending wires so the above statement still holds
02168              * if you replace "passing" by "incoming" */
02169 
02170             side_cw_incoming_wire_count = 0;
02171             if(incoming_wire_label[side_cw])
02172                 {
02173                     for(itrack = 0; itrack < nodes_per_chan; itrack++)
02174                         {
02175                             /* Ending wire, or passing wire with sbox. */
02176                             if(incoming_wire_label[side_cw][itrack] != UN_SET)
02177                                 {
02178 
02179                                     if((is_corner_sblock || is_core_sblock) &&
02180                                        (incoming_wire_label[side_cw][itrack] <
02181                                         num_ending_wires[side_cw]))
02182                                         {
02183                                             /* The ending wires in core sblocks form N-to-N assignment 
02184                                              * problem, so can use any pattern such as Wilton. This N-to-N 
02185                                              * mapping depends on the fact that start points stagger across
02186                                              * channels. */
02187                                             assert(num_ending_wires[side_cw]
02188                                                    ==
02189                                                    num_wire_muxes[to_side]);
02190                                             sblock_pattern[i][j][side_cw]
02191                                                 [to_side][itrack] =
02192                                                 get_simple_switch_block_track
02193                                                 (side_cw, to_side,
02194                                                  incoming_wire_label[side_cw]
02195                                                  [itrack], switch_block_type,
02196                                                  num_wire_muxes[to_side]);
02197 
02198                                         }
02199                                     else
02200                                         {
02201 
02202                                             /* These are passing wires with sbox only for core sblocks
02203                                              * or passing and ending wires (for fringe cases). */
02204                                             sblock_pattern[i][j][side_cw]
02205                                                 [to_side][itrack] =
02206                                                 (side_cw_incoming_wire_count *
02207                                                  Fs_per_side) %
02208                                                 num_wire_muxes[to_side];
02209                                             side_cw_incoming_wire_count++;
02210                                         }
02211                                 }
02212                         }
02213                 }
02214 
02215 
02216             side_ccw_incoming_wire_count = 0;
02217             for(itrack = 0; itrack < nodes_per_chan; itrack++)
02218                 {
02219 
02220                     /* if that side has no channel segment skip it */
02221                     if(incoming_wire_label[side_ccw] == NULL)
02222                         break;
02223 
02224                     /* not ending wire nor passing wire with sbox */
02225                     if(incoming_wire_label[side_ccw][itrack] != UN_SET)
02226                         {
02227 
02228                             if((is_corner_sblock || is_core_sblock) &&
02229                                (incoming_wire_label[side_ccw][itrack] <
02230                                 num_ending_wires[side_ccw]))
02231                                 {
02232                                     /* The ending wires in core sblocks form N-to-N assignment problem, so can
02233                                      * use any pattern such as Wilton */
02234                                     assert(incoming_wire_label[side_ccw]
02235                                            [itrack] <
02236                                            num_wire_muxes[to_side]);
02237                                     sblock_pattern[i][j][side_ccw][to_side]
02238                                         [itrack] =
02239                                         get_simple_switch_block_track
02240                                         (side_ccw, to_side,
02241                                          incoming_wire_label[side_ccw]
02242                                          [itrack], switch_block_type,
02243                                          num_wire_muxes[to_side]);
02244                                 }
02245                             else
02246                                 {
02247 
02248                                     /* These are passing wires with sbox only for core sblocks
02249                                      * or passing and ending wires (for fringe cases). */
02250                                     sblock_pattern[i][j][side_ccw][to_side]
02251                                         [itrack] =
02252                                         ((side_ccw_incoming_wire_count +
02253                                           side_cw_incoming_wire_count) *
02254                                          Fs_per_side) %
02255                                         num_wire_muxes[to_side];
02256                                     side_ccw_incoming_wire_count++;
02257                                 }
02258                         }
02259                 }
02260 
02261 
02262             opp_incoming_wire_count = 0;
02263             if(incoming_wire_label[side_opp])
02264                 {
02265                     for(itrack = 0; itrack < nodes_per_chan; itrack++)
02266                         {
02267                             /* not ending wire nor passing wire with sbox */
02268                             if(incoming_wire_label[side_opp][itrack] !=
02269                                UN_SET)
02270                                 {
02271 
02272                                     /* corner sblocks for sure have no opposite channel segments so don't care about them */
02273                                     if(is_core_sblock)
02274                                         {
02275                                             if(incoming_wire_label[side_opp]
02276                                                [itrack] <
02277                                                num_ending_wires[side_opp])
02278                                                 {
02279                                                     /* The ending wires in core sblocks form N-to-N assignment problem, so can
02280                                                      * use any pattern such as Wilton */
02281                                                     /* In the direct connect case, I know for sure the init mux is at the same track #
02282                                                      * as this ending wire, but still need to find the init mux label for Fs > 3 */
02283                                                     sblock_pattern[i][j]
02284                                                         [side_opp][to_side]
02285                                                         [itrack] =
02286                                                         find_label_of_track
02287                                                         (wire_mux_on_track
02288                                                          [to_side],
02289                                                          num_wire_muxes
02290                                                          [to_side], itrack);
02291                                                 }
02292                                             else
02293                                                 {
02294                                                     /* These are passing wires with sbox for core sblocks */
02295                                                     sblock_pattern[i][j]
02296                                                         [side_opp][to_side]
02297                                                         [itrack] =
02298                                                         ((side_ccw_incoming_wire_count + side_cw_incoming_wire_count) * Fs_per_side + opp_incoming_wire_count * (Fs_per_side - 1)) % num_wire_muxes[to_side];
02299                                                     opp_incoming_wire_count++;
02300                                                 }
02301                                         }
02302                                     else
02303                                         {
02304                                             if(incoming_wire_label[side_opp]
02305                                                [itrack] <
02306                                                num_ending_wires[side_opp])
02307                                                 {
02308                                                     sblock_pattern[i][j]
02309                                                         [side_opp][to_side]
02310                                                         [itrack] =
02311                                                         find_label_of_track
02312                                                         (wire_mux_on_track
02313                                                          [to_side],
02314                                                          num_wire_muxes
02315                                                          [to_side], itrack);
02316                                                 }
02317                                             else
02318                                                 {
02319                                                     /* These are passing wires with sbox for fringe sblocks */
02320                                                     sblock_pattern[i][j]
02321                                                         [side_opp][to_side]
02322                                                         [itrack] =
02323                                                         ((side_ccw_incoming_wire_count + side_cw_incoming_wire_count) * Fs_per_side + opp_incoming_wire_count * (Fs_per_side - 1)) % num_wire_muxes[to_side];
02324                                                     opp_incoming_wire_count++;
02325                                                 }
02326                                         }
02327                                 }
02328                         }
02329                 }
02330         }
02331 
02332     for(side = 0; side < 4; ++side)
02333         {
02334             if(incoming_wire_label[side])
02335                 {
02336                     free(incoming_wire_label[side]);
02337                 }
02338             if(wire_mux_on_track[side])
02339                 {
02340                     free(wire_mux_on_track[side]);
02341                 }
02342         }
02343 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 27 of file rr_graph2.c.


Generated on Tue Jan 5 15:26:31 2010 for VPR5.0 by  doxygen 1.6.1