SRC/rr_graph2.c File Reference

#include <stdio.h>
#include <assert.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_util.h"
#include "rr_graph2.h"
#include "rr_graph_sbox.h"
Include dependency graph for rr_graph2.c:

Go to the source code of this file.

Defines

#define ALLOW_SWITCH_OFF
#define ENABLE_REVERSE   0
#define SAME_TRACK   -5
#define UN_SET   -1

Functions

static void get_switch_type (boolean is_from_sbox, boolean is_to_sbox, short from_node_switch, short to_node_switch, short switch_types[2])
static void load_chan_rr_indices (IN int nodes_per_chan, IN int chan_len, IN int num_chans, IN t_rr_type type, IN t_seg_details *seg_details, INOUT int *index, INOUT t_ivec ***indices)
static int get_bidir_track_to_chan_seg (IN struct s_ivec conn_tracks, IN t_ivec ***rr_node_indices, IN int to_chan, IN int to_seg, IN int to_sb, IN t_rr_type to_type, IN t_seg_details *seg_details, IN boolean from_is_sbox, IN int from_switch, INOUT boolean *rr_edge_done, IN enum e_directionality directionality, INOUT struct s_linked_edge **edge_list)
static int get_unidir_track_to_chan_seg (IN boolean is_end_sb, IN int from_track, IN int to_chan, IN int to_seg, IN int to_sb, IN t_rr_type to_type, IN int nodes_per_chan, IN int nx, IN int ny, IN enum e_side from_side, IN enum e_side to_side, IN int Fs_per_side, IN int *opin_mux_size, IN short *****sblock_pattern, IN t_ivec ***rr_node_indices, IN t_seg_details *seg_details, INOUT boolean *rr_edge_done, OUT boolean *Fs_clipped, INOUT struct s_linked_edge **edge_list)
static int vpr_to_phy_track (IN int itrack, IN int chan_num, IN int seg_num, IN t_seg_details *seg_details, IN enum e_directionality directionality)
static int * get_seg_track_counts (IN int num_sets, IN int num_seg_types, IN t_segment_inf *segment_inf, IN boolean use_full_seg_groups)
static int * label_wire_muxes (IN int chan_num, IN int seg_num, IN t_seg_details *seg_details, IN int max_len, IN enum e_direction dir, IN int nodes_per_chan, OUT int *num_wire_muxes)
static int * label_wire_muxes_for_balance (IN int chan_num, IN int seg_num, IN t_seg_details *seg_details, IN int max_len, IN enum e_direction direction, IN int nodes_per_chan, IN int *num_wire_muxes, IN t_rr_type chan_type, IN int *opin_mux_size, IN t_ivec ***rr_node_indices)
static int * label_incoming_wires (IN int chan_num, IN int seg_num, IN int sb_seg, IN t_seg_details *seg_details, IN int max_len, IN enum e_direction dir, IN int nodes_per_chan, OUT int *num_incoming_wires, OUT int *num_ending_wires)
static int find_label_of_track (int *wire_mux_on_track, int num_wire_muxes, int from_track)
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 free_seg_details (t_seg_details *seg_details, int nodes_per_chan)
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)
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)
boolean is_cbox (IN int chan, IN int seg, IN int track, IN t_seg_details *seg_details, IN enum e_directionality directionality)
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)
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)
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)
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
t_linked_edgefree_edge_list_head = NULL

Define Documentation

#define ALLOW_SWITCH_OFF

Definition at line 10 of file rr_graph2.c.

#define ENABLE_REVERSE   0

Definition at line 15 of file rr_graph2.c.

#define SAME_TRACK   -5

Definition at line 18 of file rr_graph2.c.

#define UN_SET   -1

Definition at line 19 of file rr_graph2.c.


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:

static int find_label_of_track ( int *  wire_mux_on_track,
int  num_wire_muxes,
int  from_track 
) [static]

Definition at line 2619 of file rr_graph2.c.

02622 {
02623     int i, max_label, nearest_label, max_entry, nearest_entry;
02624 
02625     /* Returns the index/label in array wire_mux_on_track whose entry equals from_track. If none are
02626      * found, then returns the index of the entry whose value is the largest */
02627 
02628     max_label = nearest_label = max_entry = nearest_entry = -1;
02629 
02630     for(i = 0; i < num_wire_muxes; i++)
02631         {
02632             if(wire_mux_on_track[i] == from_track)
02633                 {
02634                     return i;   /* matched, return now */
02635                 }
02636         }
02637 
02638     printf("Error: Expected mux not found.\n");
02639     exit(1);
02640 }

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:

static int get_bidir_track_to_chan_seg ( IN struct s_ivec  conn_tracks,
IN t_ivec ***  rr_node_indices,
IN int  to_chan,
IN int  to_seg,
IN int  to_sb,
IN t_rr_type  to_type,
IN t_seg_details seg_details,
IN boolean  from_is_sbox,
IN int  from_switch,
INOUT boolean rr_edge_done,
IN enum e_directionality  directionality,
INOUT struct s_linked_edge **  edge_list 
) [static]

Definition at line 1541 of file rr_graph2.c.

01553 {
01554     int iconn, to_track, to_node, to_switch, num_conn, to_x, to_y, i;
01555     boolean to_is_sbox;
01556     short switch_types[2];
01557 
01558     /* x, y coords for get_rr_node lookups */
01559     if(CHANX == to_type)
01560         {
01561             to_x = to_seg;
01562             to_y = to_chan;
01563         }
01564     else
01565         {
01566             assert(CHANY == to_type);
01567             to_x = to_chan;
01568             to_y = to_seg;
01569         }
01570 
01571     /* Go through the list of tracks we can connect to */
01572     num_conn = 0;
01573     for(iconn = 0; iconn < conn_tracks.nelem; ++iconn)
01574         {
01575             to_track = conn_tracks.list[iconn];
01576             to_node = get_rr_node_index(to_x, to_y, to_type, to_track,
01577                                         rr_node_indices);
01578 
01579             /* Skip edge if already done */
01580             if(rr_edge_done[to_node])
01581                 {
01582                     continue;
01583                 }
01584 
01585             /* Get the switches for any edges between the two tracks */
01586             to_switch = seg_details[to_track].wire_switch;
01587 
01588             to_is_sbox = is_sbox(to_chan, to_seg, to_sb, to_track,
01589                                  seg_details, directionality);
01590             get_switch_type(from_is_sbox, to_is_sbox,
01591                             from_switch, to_switch, switch_types);
01592 
01593             /* There are up to two switch edges allowed from track to track */
01594             for(i = 0; i < 2; ++i)
01595                 {
01596                     /* If the switch_type entry is empty, skip it */
01597                     if(OPEN == switch_types[i])
01598                         {
01599                             continue;
01600                         }
01601 
01602                     /* Add the edge to the list */
01603                     *edge_list = insert_in_edge_list(*edge_list,
01604                                                      to_node,
01605                                                      switch_types[i]);
01606                     /* Mark the edge as now done */
01607                     rr_edge_done[to_node] = TRUE;
01608                     ++num_conn;
01609                 }
01610         }
01611 
01612     return num_conn;
01613 }

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:

static int * get_seg_track_counts ( IN int  num_sets,
IN int  num_seg_types,
IN t_segment_inf segment_inf,
IN boolean  use_full_seg_groups 
) [static]

Definition at line 163 of file rr_graph2.c.

00167 {
00168     int *result;
00169         double *demand;
00170     int i, imax, freq_sum, assigned, size;
00171         double scale, max, reduce;
00172 
00173     result = (int *)my_malloc(sizeof(int) * num_seg_types);
00174     demand = (double *)my_malloc(sizeof(double) * num_seg_types);
00175 
00176     /* Scale factor so we can divide by any length
00177      * and still use integers */
00178     scale = 1;
00179     freq_sum = 0;
00180     for(i = 0; i < num_seg_types; ++i)
00181         {
00182             scale *= segment_inf[i].length;
00183             freq_sum += segment_inf[i].frequency;
00184         }
00185     reduce = scale * freq_sum;
00186 
00187     /* Init assignments to 0 and set the demand values */
00188     for(i = 0; i < num_seg_types; ++i)
00189         {
00190             result[i] = 0;
00191             demand[i] = scale * num_sets * segment_inf[i].frequency;
00192             if(use_full_seg_groups)
00193                 {
00194                     demand[i] /= segment_inf[i].length;
00195                 }
00196         }
00197 
00198     /* Keep assigning tracks until we use them up */
00199     assigned = 0;
00200     size = 0;
00201     imax = 0;
00202     while(assigned < num_sets)
00203         {
00204             /* Find current maximum demand */
00205             max = 0;
00206             for(i = 0; i < num_seg_types; ++i)
00207                 {
00208                     if(demand[i] > max)
00209                         {
00210                             imax = i;
00211                             max = demand[i];
00212                         }
00213                 }
00214 
00215             /* Assign tracks to the type and reduce the types demand */
00216             size = (use_full_seg_groups ? segment_inf[imax].length : 1);
00217             demand[imax] -= reduce;
00218             result[imax] += size;
00219             assigned += size;
00220         }
00221 
00222     /* Undo last assignment if we were closer to goal without it */
00223     if((assigned - num_sets) > (size / 2))
00224         {
00225             result[imax] -= size;
00226         }
00227 
00228     /* Free temps */
00229     if(demand)
00230         {
00231             free(demand);
00232             demand = NULL;
00233         }
00234 
00235     /* This must be freed by caller */
00236     return result;
00237 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void get_switch_type ( boolean  is_from_sbox,
boolean  is_to_sbox,
short  from_node_switch,
short  to_node_switch,
short  switch_types[2] 
) [static]

Definition at line 1792 of file rr_graph2.c.

01797 {
01798     /* This routine looks at whether the from_node and to_node want a switch,  *
01799      * and what type of switch is used to connect *to* each type of node       *
01800      * (from_node_switch and to_node_switch).  It decides what type of switch, *
01801      * if any, should be used to go from from_node to to_node.  If no switch   *
01802      * should be inserted (i.e. no connection), it returns OPEN.  Its returned *
01803      * values are in the switch_types array.  It needs to return an array      *
01804      * because one topology (a buffer in the forward direction and a pass      *
01805      * transistor in the backward direction) results in *two* switches.        */
01806 
01807     boolean forward_pass_trans;
01808     boolean backward_pass_trans;
01809     int used, min, max;
01810 
01811     switch_types[0] = OPEN;     /* No switch */
01812     switch_types[1] = OPEN;
01813     used = 0;
01814     forward_pass_trans = FALSE;
01815     backward_pass_trans = FALSE;
01816 
01817     /* Connect forward if we are a sbox */
01818     if(is_from_sbox)
01819         {
01820             switch_types[used] = to_node_switch;
01821             if(FALSE == switch_inf[to_node_switch].buffered)
01822                 {
01823                     forward_pass_trans = TRUE;
01824                 }
01825             ++used;
01826         }
01827 
01828     /* Check for pass_trans coming backwards */
01829     if(is_to_sbox)
01830         {
01831             if(FALSE == switch_inf[from_node_switch].buffered)
01832                 {
01833                     switch_types[used] = from_node_switch;
01834                     backward_pass_trans = TRUE;
01835                     ++used;
01836                 }
01837         }
01838 
01839     /* Take the larger pass trans if there are two */
01840     if(forward_pass_trans && backward_pass_trans)
01841         {
01842             min = min(to_node_switch, from_node_switch);
01843             max = max(to_node_switch, from_node_switch);
01844 
01845             /* Take the smaller index unless the other 
01846              * pass_trans is bigger (smaller R). */
01847             switch_types[used] = min;
01848             if(switch_inf[max].R < switch_inf[min].R)
01849                 {
01850                     switch_types[used] = max;
01851                 }
01852             ++used;
01853         }
01854 }

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:

static int get_unidir_track_to_chan_seg ( IN boolean  is_end_sb,
IN int  from_track,
IN int  to_chan,
IN int  to_seg,
IN int  to_sb,
IN t_rr_type  to_type,
IN int  nodes_per_chan,
IN int  nx,
IN int  ny,
IN enum e_side  from_side,
IN enum e_side  to_side,
IN int  Fs_per_side,
IN int *  opin_mux_size,
IN short *****  sblock_pattern,
IN t_ivec ***  rr_node_indices,
IN t_seg_details seg_details,
INOUT boolean rr_edge_done,
OUT boolean Fs_clipped,
INOUT struct s_linked_edge **  edge_list 
) [static]

Definition at line 1616 of file rr_graph2.c.

01635 {
01636     int to_track, to_mux, to_node, to_x, to_y, i, max_len, num_labels;
01637     int sb_x, sb_y, count;
01638     int *mux_labels = NULL;
01639     enum e_direction to_dir;
01640     boolean is_fringe, is_core, is_corner, is_straight;
01641 
01642     /* x, y coords for get_rr_node lookups */
01643     if(CHANX == to_type)
01644         {
01645             to_x = to_seg;
01646             to_y = to_chan;
01647             sb_x = to_sb;
01648             sb_y = to_chan;
01649             max_len = nx;
01650         }
01651     else
01652         {
01653             assert(CHANY == to_type);
01654             to_x = to_chan;
01655             to_y = to_seg;
01656             sb_x = to_chan;
01657             sb_y = to_sb;
01658             max_len = ny;
01659         }
01660 
01661 
01662     to_dir = DEC_DIRECTION;
01663     if(to_sb < to_seg)
01664         {
01665             to_dir = INC_DIRECTION;
01666         }
01667 
01668     *Fs_clipped = FALSE;
01669 
01670     /* SBs go from (0, 0) to (nx, ny) */
01671     is_corner = ((sb_x < 1) || (sb_x >= nx)) && ((sb_y < 1) || (sb_y >= ny));
01672     is_fringe = (FALSE == is_corner) && ((sb_x < 1) || (sb_y < 1)
01673                                          || (sb_x >= nx) || (sb_y >= ny));
01674     is_core = (FALSE == is_corner) && (FALSE == is_fringe);
01675     is_straight = (from_side == RIGHT && to_side == LEFT) ||
01676         (from_side == LEFT && to_side == RIGHT) ||
01677         (from_side == TOP && to_side == BOTTOM) ||
01678         (from_side == BOTTOM && to_side == TOP);
01679 
01680     /* Ending wires use N-to-N mapping if not fringe or if goes straight */
01681     if(is_end_sb && (is_core || is_corner || is_straight))
01682         {
01683             /* Get the list of possible muxes for the N-to-N mapping. */
01684             mux_labels = label_wire_muxes(to_chan, to_seg, seg_details,
01685                                           max_len, to_dir, nodes_per_chan,
01686                                           &num_labels);
01687         }
01688     else
01689         {
01690             assert(is_fringe || !is_end_sb);
01691 
01692             mux_labels = label_wire_muxes_for_balance(to_chan, to_seg,
01693                                                       seg_details, max_len,
01694                                                       to_dir, nodes_per_chan,
01695                                                       &num_labels, to_type,
01696                                                       opin_mux_size,
01697                                                       rr_node_indices);
01698         }
01699 
01700     /* Can't connect if no muxes. */
01701     if(num_labels < 1)
01702         {
01703             if(mux_labels)
01704                 {
01705                     free(mux_labels);
01706                     mux_labels = NULL;
01707                 }
01708             return 0;
01709         }
01710 
01711     /* Check if Fs demand was too high. */
01712     if(Fs_per_side > num_labels)
01713         {
01714             *Fs_clipped = TRUE;
01715         }
01716 
01717     /* Get the target label */
01718     to_mux = sblock_pattern[sb_x][sb_y][from_side][to_side][from_track];
01719     assert(to_mux != UN_SET);
01720 
01721     /* Handle Fs > 3 but assigning consecutive muxes. */
01722     count = 0;
01723     for(i = 0; i < Fs_per_side; ++i)
01724         {
01725             /* Use the balanced labeling for passing and fringe wires */
01726             to_track = mux_labels[(to_mux + i) % num_labels];
01727             to_node =
01728                 get_rr_node_index(to_x, to_y, to_type, to_track,
01729                                   rr_node_indices);
01730 
01731             /* Add edge to list. */
01732             if(FALSE == rr_edge_done[to_node])
01733                 {
01734                     rr_edge_done[to_node] = TRUE;
01735                     *edge_list =
01736                         insert_in_edge_list(*edge_list, to_node,
01737                                             seg_details[to_track].
01738                                             wire_switch);
01739                     ++count;
01740                 }
01741         }
01742 
01743     if(mux_labels)
01744         {
01745             free(mux_labels);
01746             mux_labels = NULL;
01747         }
01748 
01749     return count;
01750 }

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:

static int * label_incoming_wires ( IN int  chan_num,
IN int  seg_num,
IN int  sb_seg,
IN t_seg_details seg_details,
IN int  max_len,
IN enum e_direction  dir,
IN int  nodes_per_chan,
OUT int *  num_incoming_wires,
OUT int *  num_ending_wires 
) [static]

Definition at line 2532 of file rr_graph2.c.

02541 {
02542 
02543     /* Labels the incoming wires on that side (seg_num, chan_num, direction). 
02544      * The returned array maps a track # to a label: array[0] = <the new hash value/label for track 0>,
02545      * the labels 0,1,2,.. identify consecutive incoming wires that have sbox (passing wires with sbox and ending wires) */
02546 
02547     int itrack, start, end, i, num_passing, num_ending, pass;
02548     int *labels;
02549     boolean sbox_exists, is_endpoint;
02550 
02551     /* Alloc the list of labels for the tracks */
02552     labels = (int *)my_malloc(nodes_per_chan * sizeof(int));
02553     for(i = 0; i < nodes_per_chan; ++i)
02554         {
02555             labels[i] = UN_SET; /* crash hard if unset */
02556         }
02557 
02558     num_ending = 0;
02559     num_passing = 0;
02560     for(pass = 0; pass < 2; ++pass)
02561         {
02562             for(itrack = 0; itrack < nodes_per_chan; ++itrack)
02563                 {
02564                     if(seg_details[itrack].direction == dir)
02565                         {
02566                             start =
02567                                 get_seg_start(seg_details, itrack, chan_num,
02568                                               seg_num);
02569                             end =
02570                                 get_seg_end(seg_details, itrack, start,
02571                                             chan_num, max_len);
02572 
02573                             /* Determine if we are a wire endpoint */
02574                             is_endpoint = (seg_num == end);
02575                             if(DEC_DIRECTION == seg_details[itrack].direction)
02576                                 {
02577                                     is_endpoint = (seg_num == start);
02578                                 }
02579 
02580                             /* Determine if we have a sbox on the wire */
02581                             sbox_exists = is_sbox(chan_num, seg_num, sb_seg,
02582                                                   itrack, seg_details,
02583                                                   UNI_DIRECTIONAL);
02584 
02585                             switch (pass)
02586                                 {
02587                                     /* On first pass, only load ending wire labels. */
02588                                 case 0:
02589                                     if(is_endpoint)
02590                                         {
02591                                             labels[itrack] = num_ending;
02592                                             ++num_ending;
02593                                         }
02594                                     break;
02595 
02596                                     /* On second pass, load the passing wire labels. They
02597                                      * will follow after the ending wire labels. */
02598                                 case 1:
02599                                     if((FALSE == is_endpoint) && sbox_exists)
02600                                         {
02601                                             labels[itrack] =
02602                                                 num_ending + num_passing;
02603                                             ++num_passing;
02604                                         }
02605                                     break;
02606                                 }
02607                         }
02608                 }
02609         }
02610 
02611     *num_incoming_wires = num_passing + num_ending;
02612     *num_ending_wires = num_ending;
02613     return labels;
02614 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int * label_wire_muxes ( IN int  chan_num,
IN int  seg_num,
IN t_seg_details seg_details,
IN int  max_len,
IN enum e_direction  dir,
IN int  nodes_per_chan,
OUT int *  num_wire_muxes 
) [static]

Definition at line 2463 of file rr_graph2.c.

02470 {
02471 
02472     /* Labels the muxes on that side (seg_num, chan_num, direction). The returned array
02473      * maps a label to the actual track #: array[0] = <the track number of the first/lowest mux> 
02474      * This routine orders wire muxes by their natural order, i.e. track # */
02475 
02476     int itrack, start, end, num_labels, pass;
02477     int *labels = NULL;
02478     boolean is_endpoint;
02479 
02480     /* COUNT pass then a LOAD pass */
02481     num_labels = 0;
02482     for(pass = 0; pass < 2; ++pass)
02483         {
02484             /* Alloc the list on LOAD pass */
02485             if(pass > 0)
02486                 {
02487                     labels = (int *)my_malloc(sizeof(int) * num_labels);
02488                     num_labels = 0;
02489                 }
02490 
02491             /* Find the tracks that are starting. */
02492             for(itrack = 0; itrack < nodes_per_chan; ++itrack)
02493                 {
02494                     start =
02495                         get_seg_start(seg_details, itrack, chan_num, seg_num);
02496                     end =
02497                         get_seg_end(seg_details, itrack, start, chan_num,
02498                                     max_len);
02499 
02500                     /* Skip tracks going the wrong way */
02501                     if(seg_details[itrack].direction != dir)
02502                         {
02503                             continue;
02504                         }
02505 
02506                     /* Determine if we are a wire startpoint */
02507                     is_endpoint = (seg_num == start);
02508                     if(DEC_DIRECTION == seg_details[itrack].direction)
02509                         {
02510                             is_endpoint = (seg_num == end);
02511                         }
02512 
02513                     /* Count the labels and load if LOAD pass */
02514                     if(is_endpoint)
02515                         {
02516                             if(pass > 0)
02517                                 {
02518                                     labels[num_labels] = itrack;
02519                                 }
02520                             ++num_labels;
02521                         }
02522                 }
02523         }
02524 
02525     *num_wire_muxes = num_labels;
02526     return labels;
02527 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int * label_wire_muxes_for_balance ( IN int  chan_num,
IN int  seg_num,
IN t_seg_details seg_details,
IN int  max_len,
IN enum e_direction  direction,
IN int  nodes_per_chan,
IN int *  num_wire_muxes,
IN t_rr_type  chan_type,
IN int *  opin_mux_size,
IN t_ivec ***  rr_node_indices 
) [static]

Definition at line 2346 of file rr_graph2.c.

02356 {
02357 
02358     /* Labels the muxes on that side (seg_num, chan_num, direction). The returned array
02359      * maps a label to the actual track #: array[0] = <the track number of the first mux> */
02360 
02361     /* Sblock (aka wire2mux) pattern generation occurs after opin2mux connections have been 
02362      * made. Since opin2muxes are done with a pattern with which I guarantee imbalance of at most 1 due 
02363      * to them, we will observe that, for each side of an sblock some muxes have one fewer size 
02364      * than the others, considering only the contribution from opins. I refer to these muxes as "holes"
02365      * as they have one fewer opin connection going to them than the rest (like missing one electron)*/
02366 
02367     /* Before May 14, I was labelling wire muxes in the natural order of their track # (lowest first). 
02368      * Now I want to label wire muxes like this: first label the holes in order of their track #,
02369      * then label the non-holes in order of their track #. This way the wire2mux generation will 
02370      * not overlap its own "holes" with the opin "holes", thus creating imbalance greater than 1. */
02371 
02372     /* The best approach in sblock generation is do one assignment of all incoming wires from 3 other
02373      * sides to the muxes on the fourth side, connecting the "opin hole" muxes first (i.e. filling
02374      * the holes) then the rest -> this means after all opin2mux and wire2mux connections the 
02375      * mux size imbalance on one side is at most 1. The mux size imbalance in one sblock is thus
02376      * also one, since the number of muxes per side is identical for all four sides, and they number
02377      * of incoming wires per side is identical for full pop, and almost the same for depop (due to 
02378      * staggering) within +1 or -1. For different tiles (different sblocks) the imbalance is irrelevant,
02379      * since if the tiles are different in mux count then they have to be designed with a different
02380      * physical tile. */
02381 
02382     int num_labels, max_opin_mux_size, min_opin_mux_size;
02383     int inode, i, j, x, y;
02384     int *pre_labels, *final_labels;
02385 
02386         if (chan_type == CHANX){
02387                 x = seg_num;
02388                 y = chan_num;
02389         }
02390         else if (chan_type == CHANY){
02391                 x = chan_num;
02392                 y = seg_num;
02393         }
02394         else {
02395                 printf("Error: Bad channel type (%d).\n", chan_type);
02396                 exit(1);
02397         }
02398 
02399     /* Generate the normal labels list as the baseline. */
02400     pre_labels =
02401         label_wire_muxes(chan_num, seg_num, seg_details, max_len,
02402                          direction, nodes_per_chan, &num_labels);
02403 
02404     /* Find the min and max mux size. */
02405     min_opin_mux_size = MAX_SHORT;
02406     max_opin_mux_size = 0;
02407     for(i = 0; i < num_labels; ++i)
02408         {
02409             inode = get_rr_node_index(x, y, chan_type, pre_labels[i],
02410                                   rr_node_indices);
02411             if(opin_mux_size[inode] < min_opin_mux_size)
02412                 {
02413                     min_opin_mux_size = opin_mux_size[inode];
02414                 }
02415             if(opin_mux_size[inode] > max_opin_mux_size)
02416                 {
02417                     max_opin_mux_size = opin_mux_size[inode];
02418                 }
02419         }
02420     if(max_opin_mux_size > (min_opin_mux_size + 1))
02421         {
02422             printf(ERRTAG "opin muxes are not balanced!\n");
02423                 printf("max_opin_mux_size %d min_opin_mux_size %d chan_type %d x %d y %d\n", 
02424                 max_opin_mux_size, min_opin_mux_size, chan_type, x, y);
02425             exit(1);
02426         }
02427         
02428     /* Create a new list that we will move the muxes with 'holes' to the start of list. */
02429     final_labels = (int *)my_malloc(sizeof(int) * num_labels);
02430     j = 0;
02431     for(i = 0; i < num_labels; ++i)
02432         {
02433             inode = pre_labels[i];
02434             if(opin_mux_size[inode] < max_opin_mux_size)
02435                 {
02436                     final_labels[j] = inode;
02437                     ++j;
02438                 }
02439         }
02440     for(i = 0; i < num_labels; ++i)
02441         {
02442             inode = pre_labels[i];
02443             if(opin_mux_size[inode] >= max_opin_mux_size)
02444                 {
02445                     final_labels[j] = inode;
02446                     ++j;
02447                 }
02448         }
02449 
02450     /* Free the baseline labelling. */
02451     if(pre_labels)
02452         {
02453             free(pre_labels);
02454             pre_labels = NULL;
02455         }
02456 
02457     *num_wire_muxes = num_labels;
02458     return final_labels;
02459 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void load_chan_rr_indices ( IN int  nodes_per_chan,
IN int  chan_len,
IN int  num_chans,
IN t_rr_type  type,
IN t_seg_details seg_details,
INOUT int *  index,
INOUT t_ivec ***  indices 
) [static]

Definition at line 864 of file rr_graph2.c.

00871 {
00872     int chan, seg, track, start, inode;
00873 
00874     indices[type] = (t_ivec **) my_malloc(sizeof(t_ivec *) * num_chans);
00875     for(chan = 0; chan < num_chans; ++chan)
00876         {
00877             indices[type][chan] =
00878                 (t_ivec *) my_malloc(sizeof(t_ivec) * chan_len);
00879 
00880             indices[type][chan][0].nelem = 0;
00881             indices[type][chan][0].list = NULL;
00882 
00883             for(seg = 1; seg < chan_len; ++seg)
00884                 {
00885                     /* Alloc the track inode lookup list */
00886                     indices[type][chan][seg].nelem = nodes_per_chan;
00887                     indices[type][chan][seg].list =
00888                         (int *)my_malloc(sizeof(int) * nodes_per_chan);
00889                     for(track = 0; track < nodes_per_chan; ++track)
00890                         {
00891                             indices[type][chan][seg].list[track] = OPEN;
00892                         }
00893                 }
00894         }
00895 
00896     for(chan = 0; chan < num_chans; ++chan)
00897         {
00898             for(seg = 1; seg < chan_len; ++seg)
00899                 {
00900                     /* Assign an inode to the starts of tracks */
00901                     for(track = 0; track < indices[type][chan][seg].nelem;
00902                         ++track)
00903                         {
00904                             start =
00905                                 get_seg_start(seg_details, track, chan, seg);
00906 
00907                             /* If the start of the wire doesn't have a inode, 
00908                              * assign one to it. */
00909                             inode = indices[type][chan][start].list[track];
00910                             if(OPEN == inode)
00911                                 {
00912                                     inode = *index;
00913                                     ++(*index);
00914 
00915                                     indices[type][chan][start].list[track] =
00916                                         inode;
00917                                 }
00918 
00919                             /* Assign inode of start of wire to current position */
00920                             indices[type][chan][seg].list[track] = inode;
00921                         }
00922                 }
00923         }
00924 }

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:

static int vpr_to_phy_track ( IN int  itrack,
IN int  chan_num,
IN int  seg_num,
IN t_seg_details seg_details,
IN enum e_directionality  directionality 
) [static]

Definition at line 1857 of file rr_graph2.c.

01862 {
01863     int group_start, group_size;
01864     int vpr_offset_for_first_phy_track;
01865     int vpr_offset, phy_offset;
01866     int phy_track;
01867     int fac;
01868 
01869     /* Assign in pairs if unidir. */
01870     fac = 1;
01871     if(UNI_DIRECTIONAL == directionality)
01872         {
01873             fac = 2;
01874         }
01875 
01876     group_start = seg_details[itrack].group_start;
01877     group_size = seg_details[itrack].group_size;
01878 
01879     vpr_offset_for_first_phy_track =
01880         (chan_num + seg_num - 1) % (group_size / fac);
01881     vpr_offset = (itrack - group_start) / fac;
01882     phy_offset =
01883         (vpr_offset_for_first_phy_track + vpr_offset) % (group_size / fac);
01884     phy_track =
01885         group_start + (fac * phy_offset) + (itrack - group_start) % fac;
01886 
01887     return phy_track;
01888 }

Here is the caller graph for this function:


Variable Documentation

Definition at line 32 of file rr_graph2.c.

Definition at line 27 of file rr_graph2.c.


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