SRC/rr_graph.h File Reference

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

Go to the source code of this file.

Typedefs

typedef enum e_graph_type t_graph_type

Enumerations

enum  e_graph_type { GRAPH_GLOBAL, GRAPH_BIDIR, GRAPH_UNIDIR, GRAPH_UNIDIR_TILEABLE }
enum  { RR_GRAPH_NO_WARN = 0x00, RR_GRAPH_WARN_FC_CLIPPED = 0x01, RR_GRAPH_WARN_CHAN_WIDTH_CHANGED = 0x02 }

Functions

void build_rr_graph (IN t_graph_type graph_type, IN int num_types, IN t_type_ptr types, IN int nx, IN int ny, IN struct s_grid_tile **grid, IN int chan_width, IN struct s_chan_width_dist *chan_capacity_inf, IN enum e_switch_block_type sb_type, IN int Fs, IN int num_seg_types, IN int num_switches, IN t_segment_inf *segment_inf, IN int global_route_switch, IN int delayless_switch, IN t_timing_inf timing_inf, IN int wire_to_ipin_switch, IN enum e_base_cost_type base_cost_type, OUT int *Warnings)
void free_rr_graph (void)
void dump_rr_graph (IN const char *file_name)
void print_rr_indexed_data (FILE *fp, int index)
void load_net_rr_terminals (t_ivec ***rr_node_indices)

Typedef Documentation

typedef enum e_graph_type t_graph_type

Definition at line 9 of file rr_graph.h.


Enumeration Type Documentation

anonymous enum
Enumerator:
RR_GRAPH_NO_WARN 
RR_GRAPH_WARN_FC_CLIPPED 
RR_GRAPH_WARN_CHAN_WIDTH_CHANGED 

Definition at line 13 of file rr_graph.h.

00014 {
00015     RR_GRAPH_NO_WARN = 0x00,
00016     RR_GRAPH_WARN_FC_CLIPPED = 0x01,
00017     RR_GRAPH_WARN_CHAN_WIDTH_CHANGED = 0x02
00018 };

Enumerator:
GRAPH_GLOBAL 
GRAPH_BIDIR 
GRAPH_UNIDIR 
GRAPH_UNIDIR_TILEABLE 

Definition at line 1 of file rr_graph.h.

00002 {
00003     GRAPH_GLOBAL,               /* One node per channel with wire capacity > 1 and full connectivity */
00004     GRAPH_BIDIR,                /* Detailed bidirectional graph */
00005     GRAPH_UNIDIR,               /* Detailed unidir graph, untilable */
00006     /* RESEARCH TODO: Get this option debugged */
00007     GRAPH_UNIDIR_TILEABLE       /* Detail unidir graph with wire groups multiples of 2*L */
00008 };


Function Documentation

void build_rr_graph ( IN t_graph_type  graph_type,
IN int  num_types,
IN t_type_ptr  types,
IN int  nx,
IN int  ny,
IN struct s_grid_tile **  grid,
IN int  chan_width,
IN struct s_chan_width_dist chan_capacity_inf,
IN enum e_switch_block_type  sb_type,
IN int  Fs,
IN int  num_seg_types,
IN int  num_switches,
IN t_segment_inf segment_inf,
IN int  global_route_switch,
IN int  delayless_switch,
IN t_timing_inf  timing_inf,
IN int  wire_to_ipin_switch,
IN enum e_base_cost_type  base_cost_type,
OUT int *  Warnings 
)

Definition at line 280 of file rr_graph.c.

00299 {
00300     /* Temp structures used to build graph */
00301     int nodes_per_chan, i, j;
00302     t_seg_details *seg_details = NULL;
00303     int *Fc_in = NULL;
00304     int *Fc_out = NULL;
00305    
00306     int *****opin_to_track_map = NULL;  /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */
00307     int *****ipin_to_track_map = NULL;  /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */
00308     t_ivec ****track_to_ipin_lookup = NULL;     /* [0..num_types-1][0..nodes_per_chan-1][0..height][0..3] */
00309     t_ivec ***switch_block_conn = NULL;
00310     short *****unidir_sb_pattern = NULL;
00311     boolean *rr_edge_done = NULL;
00312     boolean is_global_graph;
00313     boolean Fc_clipped;
00314     boolean use_full_seg_groups;
00315     boolean *perturb_ipins = NULL;
00316     enum e_directionality directionality;
00317     int **Fc_xofs = NULL;       /* [0..ny-1][0..nx-1] */
00318     int **Fc_yofs = NULL;       /* [0..nx-1][0..ny-1] */
00319 
00320         rr_node_indices = NULL;
00321         rr_node = NULL;
00322         num_rr_nodes = 0;
00323 
00324     /* Reset warning flag */
00325     *Warnings = RR_GRAPH_NO_WARN;
00326 
00327     /* Decode the graph_type */
00328     is_global_graph = FALSE;
00329     if(GRAPH_GLOBAL == graph_type)
00330         {
00331             is_global_graph = TRUE;
00332         }
00333     use_full_seg_groups = FALSE;
00334     if(GRAPH_UNIDIR_TILEABLE == graph_type)
00335         {
00336             use_full_seg_groups = TRUE;
00337         }
00338     directionality = UNI_DIRECTIONAL;
00339     if(GRAPH_BIDIR == graph_type)
00340         {
00341             directionality = BI_DIRECTIONAL;
00342         }
00343     if(is_global_graph)
00344         {
00345             directionality = BI_DIRECTIONAL;
00346         }
00347 
00348 
00349     /* Global routing uses a single longwire track */
00350     nodes_per_chan = (is_global_graph ? 1 : chan_width);
00351     assert(nodes_per_chan > 0);
00352 
00353 
00354 
00355     /* START SEG_DETAILS */
00356     if(is_global_graph)
00357         {
00358             /* Sets up a single unit length segment type for global routing. */
00359             seg_details =
00360                 alloc_and_load_global_route_seg_details(nodes_per_chan,
00361                                                         global_route_switch);
00362         }
00363     else
00364         {
00365             /* Setup segments including distrubuting tracks and staggering.
00366              * If use_full_seg_groups is specified, nodes_per_chan may be 
00367              * changed. Warning should be singled to caller if this happens. */
00368             seg_details = alloc_and_load_seg_details(&nodes_per_chan,
00369                                                      max(nx, ny),
00370                                                      num_seg_types,
00371                                                      segment_inf,
00372                                                      use_full_seg_groups,
00373                                                      is_global_graph,
00374                                                      directionality);
00375             if((is_global_graph ? 1 : chan_width) != nodes_per_chan)
00376                 {
00377                     *Warnings |= RR_GRAPH_WARN_CHAN_WIDTH_CHANGED;
00378                 }
00379 #ifdef CREATE_ECHO_FILES
00380             dump_seg_details(seg_details, nodes_per_chan, "seg_details.txt");
00381 #endif /* CREATE_ECHO_FILES */
00382         }
00383     /* END SEG_DETAILS */
00384 
00385 
00386 
00387     /* START FC */
00388     /* Determine the actual value of Fc */
00389     if(is_global_graph)
00390         {
00391             Fc_in = (int *)my_malloc(sizeof(int) * num_types);
00392             Fc_out = (int *)my_malloc(sizeof(int) * num_types);
00393             for(i = 0; i < num_types; ++i)
00394                 {
00395                     Fc_in[i] = 1;
00396                     Fc_out[i] = 1;
00397                 }
00398         }
00399     else
00400         {
00401             Fc_clipped = FALSE;
00402             Fc_in =
00403                 alloc_and_load_actual_fc(num_types, types, nodes_per_chan,
00404                                          FALSE, directionality, &Fc_clipped);
00405             if(Fc_clipped)
00406                 {
00407                     *Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
00408                 }
00409             Fc_clipped = FALSE;
00410             Fc_out =
00411                 alloc_and_load_actual_fc(num_types, types, nodes_per_chan,
00412                                          TRUE, directionality, &Fc_clipped);
00413             if(Fc_clipped)
00414                 {
00415                     *Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
00416                 }
00417 
00418 
00419 #ifdef VERBOSE
00420             for(i = 1; i < num_types; ++i)
00421                 {               /* Skip "<EMPTY>" */
00422                     if(type_descriptors[i].is_Fc_out_full_flex)
00423                         {
00424                             printf
00425                                 ("Fc Actual Values: Type = %s, Fc_out = full, Fc_in = %d.\n",
00426                                  type_descriptors[i].name, Fc_input[i]);
00427                         }
00428                     else
00429                         {
00430                             printf
00431                                 ("Fc Actual Values: Type = %s, Fc_out = %d, Fc_in = %d.\n",
00432                                  type_descriptors[i].name, Fc_output[i],
00433                                  Fc_input[i]);
00434                         }
00435                 }
00436 #endif /* VERBOSE */
00437         }
00438         
00439         perturb_ipins =
00440                 alloc_and_load_perturb_ipins(nodes_per_chan, num_types, Fc_in,
00441                                              Fc_out, directionality);
00442     /* END FC */
00443 
00444 
00445     /* Alloc node lookups, count nodes, alloc rr nodes */
00446     num_rr_nodes = 0;
00447     rr_node_indices =
00448         alloc_and_load_rr_node_indices(nodes_per_chan, nx, ny, &num_rr_nodes,
00449                                        seg_details);
00450     rr_node = (t_rr_node *) my_malloc(sizeof(t_rr_node) * num_rr_nodes);
00451     memset(rr_node, 0, sizeof(t_rr_node) * num_rr_nodes);
00452     rr_edge_done = (boolean *) my_malloc(sizeof(boolean) * num_rr_nodes);
00453     memset(rr_edge_done, 0, sizeof(boolean) * num_rr_nodes);
00454 
00455     /* These are data structures used by the the unidir opin mapping. */
00456     if(UNI_DIRECTIONAL == directionality)
00457         {
00458             Fc_xofs = (int **)alloc_matrix(0, ny, 0, nx, sizeof(int));
00459             Fc_yofs = (int **)alloc_matrix(0, nx, 0, ny, sizeof(int));
00460             for(i = 0; i <= nx; ++i)
00461                 {
00462                     for(j = 0; j <= ny; ++j)
00463                         {
00464                             Fc_xofs[j][i] = 0;
00465                             Fc_yofs[i][j] = 0;
00466                         }
00467                 }
00468         }
00469 
00470 
00471 
00472     /* START SB LOOKUP */
00473     /* Alloc and load the switch block lookup */
00474     if(is_global_graph)
00475         {
00476             assert(nodes_per_chan == 1);
00477             switch_block_conn =
00478                 alloc_and_load_switch_block_conn(1, SUBSET, 3);
00479         }
00480     else if(BI_DIRECTIONAL == directionality)
00481         {
00482             switch_block_conn =
00483                 alloc_and_load_switch_block_conn(nodes_per_chan, sb_type, Fs);
00484         }
00485     else
00486         {
00487             assert(UNI_DIRECTIONAL == directionality);
00488 
00489             unidir_sb_pattern =
00490                 alloc_sblock_pattern_lookup(nx, ny, nodes_per_chan);
00491             for(i = 0; i <= nx; i++)
00492                 {
00493                     for(j = 0; j <= ny; j++)
00494                         {
00495                             load_sblock_pattern_lookup(i, j, nodes_per_chan,
00496                                                        seg_details, Fs,
00497                                                        sb_type,
00498                                                        unidir_sb_pattern);
00499                         }
00500                 }
00501         }
00502     /* END SB LOOKUP */
00503 
00504 
00505 
00506     /* START IPIN MAP */
00507     /* Create ipin map lookups */
00508     ipin_to_track_map = (int *****)my_malloc(sizeof(int ****) * num_types);
00509     track_to_ipin_lookup =
00510         (struct s_ivec ****)my_malloc(sizeof(struct s_ivec ***) * num_types);
00511     for(i = 0; i < num_types; ++i)
00512         {
00513             ipin_to_track_map[i] = alloc_and_load_pin_to_track_map(RECEIVER,
00514                                                                    nodes_per_chan,
00515                                                                    Fc_in[i],
00516                                                                    &types[i],
00517                                                                    perturb_ipins
00518                                                                    [i],
00519                                                                    directionality);
00520             track_to_ipin_lookup[i] =
00521                 alloc_and_load_track_to_pin_lookup(ipin_to_track_map[i],
00522                                                    Fc_in[i], types[i].height,
00523                                                    types[i].num_pins,
00524                                                    nodes_per_chan);
00525         }
00526     /* END IPIN MAP */
00527 
00528 
00529 
00530     /* START OPIN MAP */
00531     /* Create opin map lookups */
00532     if(BI_DIRECTIONAL == directionality)
00533         {
00534             opin_to_track_map =
00535                 (int *****)my_malloc(sizeof(int ****) * num_types);
00536             for(i = 0; i < num_types; ++i)
00537                 {
00538                     opin_to_track_map[i] =
00539                         alloc_and_load_pin_to_track_map(DRIVER,
00540                                                         nodes_per_chan,
00541                                                         Fc_out[i], &types[i],
00542                                                         FALSE,
00543                                                         directionality);
00544                 }
00545         }
00546     /* END OPIN MAP */
00547 
00548     /* UDSD Modifications by WMF begin */
00549     /* I'm adding 2 new fields to t_rr_node, and I want them initialized to 0. */
00550     for(i = 0; i < num_rr_nodes; i++)
00551         {
00552             rr_node[i].num_wire_drivers = 0;
00553             rr_node[i].num_opin_drivers = 0;
00554         }
00555 
00556 
00557     alloc_and_load_rr_graph(num_rr_nodes, rr_node, num_seg_types,
00558                             seg_details, rr_edge_done,
00559                             track_to_ipin_lookup, opin_to_track_map,
00560                             switch_block_conn, grid, nx,
00561                             ny, Fs, unidir_sb_pattern, Fc_out, Fc_xofs,
00562                             Fc_yofs, rr_node_indices, nodes_per_chan,
00563                             sb_type, delayless_switch, directionality,
00564                             wire_to_ipin_switch, &Fc_clipped);
00565 
00566 
00567 #if 0
00568 #ifdef MUX_SIZE_DIST_DISPLAY
00569     if(UNI_DIRECTIONAL == directionality)
00570         {
00571             view_mux_size_distribution(rr_node_indices, nodes_per_chan,
00572                                        seg_details, seg_details);
00573         }
00574 #endif
00575 #endif
00576 
00577         /* Update rr_nodes capacities if global routing */
00578         if(graph_type == GLOBAL) {
00579                 for(i = 0; i < num_rr_nodes; i++) {
00580                         if(rr_node[i].type == CHANX || rr_node[i].type == CHANY) {
00581                                 rr_node[i].capacity = chan_width;
00582                         }
00583                 }
00584         }
00585 
00586     rr_graph_externals(timing_inf, segment_inf, num_seg_types,
00587                        nodes_per_chan, wire_to_ipin_switch, base_cost_type);
00588 
00589 #ifdef CREATE_ECHO_FILES
00590     dump_rr_graph("rr_graph.echo");
00591 #endif /* CREATE_ECHO_FILES */
00592 
00593     check_rr_graph(graph_type, num_types, types, nx, ny,
00594                    grid, nodes_per_chan, Fs, num_seg_types, num_switches, segment_inf,
00595                    global_route_switch, delayless_switch,
00596                    wire_to_ipin_switch, seg_details, Fc_in, Fc_out,
00597                    rr_node_indices, opin_to_track_map, ipin_to_track_map,
00598                    track_to_ipin_lookup, switch_block_conn, perturb_ipins);
00599 
00600     /* Free all temp structs */
00601     if(seg_details)
00602         {
00603             free_seg_details(seg_details, nodes_per_chan);
00604             seg_details = NULL;
00605         }
00606     if(Fc_in)
00607         {
00608             free(Fc_in);
00609             Fc_in = NULL;
00610         }
00611     if(Fc_out)
00612         {
00613             free(Fc_out);
00614             Fc_out = NULL;
00615         }
00616     if(perturb_ipins)
00617         {
00618             free(perturb_ipins);
00619             perturb_ipins = NULL;
00620         }
00621     if(switch_block_conn)
00622         {
00623             free_switch_block_conn(switch_block_conn, nodes_per_chan);
00624             switch_block_conn = NULL;
00625         }
00626     if(rr_edge_done)
00627         {
00628             free(rr_edge_done);
00629             rr_edge_done = NULL;
00630         }
00631     if(Fc_xofs)
00632         {
00633             free_matrix(Fc_xofs, 0, ny, 0, sizeof(int));
00634                 Fc_xofs = NULL;
00635         }
00636     if(Fc_yofs)
00637         {
00638             free_matrix(Fc_yofs, 0, nx, 0, sizeof(int));
00639                 Fc_yofs = NULL;
00640         }
00641         if(unidir_sb_pattern)
00642         {
00643                 free_sblock_pattern_lookup(unidir_sb_pattern);
00644                 unidir_sb_pattern = NULL;
00645         }
00646         if(opin_to_track_map) {
00647             for(i = 0; i < num_types; ++i)
00648                 {
00649                     free_matrix4(opin_to_track_map[i], 0, types[i].num_pins - 1,
00650                       0, types[i].height - 1, 0, 3, 0, sizeof(int));
00651                 }
00652                 free(opin_to_track_map);
00653         }
00654         
00655     free_type_pin_to_track_map(ipin_to_track_map, types, Fc_in);
00656     free_type_track_to_ipin_map(track_to_ipin_lookup, types, nodes_per_chan);
00657 }

Here is the call graph for this function:

Here is the caller graph for this function:

void dump_rr_graph ( IN const char *  file_name  ) 

Definition at line 2259 of file rr_graph.c.

02260 {
02261 
02262     int inode;
02263     FILE *fp;
02264 
02265     fp = my_fopen(file_name, "w");
02266 
02267     for(inode = 0; inode < num_rr_nodes; inode++)
02268         {
02269             print_rr_node(fp, rr_node, inode);
02270             fprintf(fp, "\n");
02271         }
02272 
02273 #if 0
02274     fprintf(fp, "\n\n%d rr_indexed_data entries.\n\n", num_rr_indexed_data);
02275 
02276     for(index = 0; index < num_rr_indexed_data; index++)
02277         {
02278             print_rr_indexed_data(fp, index);
02279             fprintf(fp, "\n");
02280         }
02281 #endif
02282 
02283     fclose(fp);
02284 }

Here is the call graph for this function:

Here is the caller graph for this function:

void free_rr_graph ( void   ) 

Definition at line 1045 of file rr_graph.c.

01046 {
01047     int i;
01048 
01049     /* Frees all the routing graph data structures, if they have been       *
01050      * allocated.  I use rr_mem_chunk_list_head as a flag to indicate       *
01051      * whether or not the graph has been allocated -- if it is not NULL,    *
01052      * a routing graph exists and can be freed.  Hence, you can call this   *
01053      * routine even if you're not sure of whether a rr_graph exists or not. */
01054 
01055     if(rr_mem_chunk_list_head == NULL)  /* Nothing to free. */
01056         return;
01057 
01058     free_chunk_memory(rr_mem_chunk_list_head);  /* Frees ALL "chunked" data */
01059     rr_mem_chunk_list_head = NULL;      /* No chunks allocated now. */
01060     chunk_bytes_avail = 0;      /* 0 bytes left in current "chunk". */
01061     chunk_next_avail_mem = NULL;        /* No current chunk.                */
01062 
01063     /* Before adding any more free calls here, be sure the data is NOT chunk *
01064      * allocated, as ALL the chunk allocated data is already free!           */
01065 
01066     free(net_rr_terminals);
01067 
01068         for(i = 0; i < num_rr_nodes; i++) {
01069                 if(rr_node[i].edges != NULL) {
01070                         free(rr_node[i].edges);
01071                 }
01072                 if(rr_node[i].switches != NULL) {
01073                         free(rr_node[i].switches);
01074                 }
01075         }
01076 
01077         assert(rr_node_indices);
01078     free_rr_node_indices(rr_node_indices);
01079     free(rr_node);
01080     free(rr_indexed_data);
01081     for(i = 0; i < num_blocks; i++)
01082         {
01083             free(rr_blk_source[i]);
01084         }
01085     free(rr_blk_source);
01086     rr_blk_source = NULL;
01087     net_rr_terminals = NULL;
01088     rr_node = NULL;
01089         rr_node_indices = NULL;
01090     rr_indexed_data = NULL;
01091 }

Here is the call graph for this function:

Here is the caller graph for this function:

void load_net_rr_terminals ( t_ivec ***  rr_node_indices  ) 

Definition at line 1113 of file rr_graph.c.

01114 {
01115 
01116     /* Allocates and loads the net_rr_terminals data structure.  For each net   *
01117      * it stores the rr_node index of the SOURCE of the net and all the SINKs   *
01118      * of the net.  [0..num_nets-1][0..num_pins-1].  Entry [inet][pnum] stores  *
01119      * the rr index corresponding to the SOURCE (opin) or SINK (ipin) of pnum.  */
01120 
01121     int inet, ipin, inode, iblk, i, j, k, node_block_pin, iclass;
01122     t_type_ptr type;
01123 
01124     for(inet = 0; inet < num_nets; inet++)
01125         {
01126             for(ipin = 0; ipin <= net[inet].num_sinks; ipin++)
01127                 {
01128                     iblk = net[inet].node_block[ipin];
01129                     i = block[iblk].x;
01130                     j = block[iblk].y;
01131                     k = block[iblk].z;
01132                     type = block[iblk].type;
01133 
01134                     /* In the routing graph, each (x, y) location has unique pins on it
01135                      * so when there is capacity, blocks are packed and their pin numbers
01136                      * are offset to get their actual rr_node */
01137                     node_block_pin = net[inet].node_block_pin[ipin];
01138 
01139                     iclass = type->pin_class[node_block_pin];
01140 
01141                     inode = get_rr_node_index(i, j, (ipin == 0 ? SOURCE : SINK),        /* First pin is driver */
01142                                               iclass, rr_node_indices);
01143                     net_rr_terminals[inet][ipin] = inode;
01144                 }
01145         }
01146 }

Here is the call graph for this function:

Here is the caller graph for this function:

void print_rr_indexed_data ( FILE *  fp,
int  index 
)

Definition at line 2354 of file rr_graph.c.

02356 {
02357 
02358     fprintf(fp, "Index: %d\n", index);
02359 
02360     fprintf(fp, "ortho_cost_index: %d  ",
02361             rr_indexed_data[index].ortho_cost_index);
02362     fprintf(fp, "base_cost: %g  ", rr_indexed_data[index].saved_base_cost);
02363     fprintf(fp, "saved_base_cost: %g\n",
02364             rr_indexed_data[index].saved_base_cost);
02365 
02366     fprintf(fp, "Seg_index: %d  ", rr_indexed_data[index].seg_index);
02367     fprintf(fp, "inv_length: %g\n", rr_indexed_data[index].inv_length);
02368 
02369     fprintf(fp, "T_linear: %g  ", rr_indexed_data[index].T_linear);
02370     fprintf(fp, "T_quadratic: %g  ", rr_indexed_data[index].T_quadratic);
02371     fprintf(fp, "C_load: %g\n", rr_indexed_data[index].C_load);
02372 }

Here is the caller graph for this function:


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