SRC/check_rr_graph.c File Reference

#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "check_rr_graph.h"
Include dependency graph for check_rr_graph.c:

Go to the source code of this file.

Defines

#define BUF_FLAG   1
#define PTRANS_FLAG   2
#define BUF_AND_PTRANS_FLAG   3

Functions

static boolean rr_node_is_global_clb_ipin (int inode)
static void check_pass_transistors (int from_node)
void check_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 nodes_per_chan, 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 int wire_to_ipin_switch, t_seg_details *seg_details, int *Fc_in, int *Fc_out, t_ivec ***rr_node_indices, int *****opin_to_track_map, int *****ipin_to_track_map, t_ivec ****track_to_ipin_lookup, t_ivec ***switch_block_conn, boolean *perturb_ipins)
void check_node (int inode, enum e_route_type route_type)

Variables

static boolean rr_graph_error
static boolean rr_graph_warn

Define Documentation

#define BUF_AND_PTRANS_FLAG   3

Definition at line 12 of file check_rr_graph.c.

#define BUF_FLAG   1

Definition at line 10 of file check_rr_graph.c.

#define PTRANS_FLAG   2

Definition at line 11 of file check_rr_graph.c.


Function Documentation

void check_node ( int  inode,
enum e_route_type  route_type 
)

Definition at line 248 of file check_rr_graph.c.

00250 {
00251 
00252 /* This routine checks that the rr_node is inside the grid and has a valid  *
00253  * pin number, etc.                                                         */
00254 
00255     int xlow, ylow, xhigh, yhigh, ptc_num, capacity;
00256     t_rr_type rr_type;
00257     t_type_ptr type;
00258     int nodes_per_chan, tracks_per_node, num_edges, cost_index;
00259     float C, R;
00260 
00261     rr_type = rr_node[inode].type;
00262     xlow = rr_node[inode].xlow;
00263     xhigh = rr_node[inode].xhigh;
00264     ylow = rr_node[inode].ylow;
00265     yhigh = rr_node[inode].yhigh;
00266     ptc_num = rr_node[inode].ptc_num;
00267     capacity = rr_node[inode].capacity;
00268     type = NULL;
00269 
00270     if(xlow > xhigh || ylow > yhigh)
00271         {
00272             printf
00273                 ("Error in check_node:  rr endpoints are (%d,%d) and (%d,%d).\n",
00274                  xlow, ylow, xhigh, yhigh);
00275             exit(1);
00276         }
00277 
00278     if(xlow < 0 || xhigh > nx + 1 || ylow < 0 || yhigh > ny + 1)
00279         {
00280             printf
00281                 ("Error in check_node:  rr endpoints, (%d,%d) and (%d,%d), \n"
00282                  "are out of range.\n", xlow, ylow, xhigh, yhigh);
00283             exit(1);
00284         }
00285 
00286     if(ptc_num < 0)
00287         {
00288             printf("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00289                    "of %d.\n", inode, rr_type, ptc_num);
00290             exit(1);
00291         }
00292 
00293 /* Check that the segment is within the array and such. */
00294 
00295     switch (rr_type)
00296         {
00297 
00298         case SOURCE:
00299         case SINK:
00300         case IPIN:
00301         case OPIN:
00302             /* This is used later as well */
00303             type = grid[xlow][ylow].type;
00304 
00305             if(type == NULL)
00306                 {
00307                     printf
00308                         ("Error in check_node:  Node %d (type %d) is at an illegal\n"
00309                          " clb location (%d, %d).\n", inode, rr_type, xlow,
00310                          ylow);
00311                     exit(1);
00312                 }
00313             if(xlow != xhigh || ylow != (yhigh - type->height + 1))
00314                 {
00315                     printf
00316                         ("Error in check_node:  Node %d (type %d) has endpoints of\n"
00317                          "(%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow,
00318                          xhigh, yhigh);
00319                     exit(1);
00320                 }
00321             break;
00322 
00323         case CHANX:
00324             if(xlow < 1 || xhigh > nx || yhigh > ny || yhigh != ylow)
00325                 {
00326                     printf("Error in check_node:  CHANX out of range.\n");
00327                     printf("Endpoints: (%d,%d) and (%d,%d)\n", xlow, ylow,
00328                            xhigh, yhigh);
00329                     exit(1);
00330                 }
00331             if(route_type == GLOBAL && xlow != xhigh)
00332                 {
00333                     printf
00334                         ("Error in check_node:  node %d spans multiple channel segments\n"
00335                          "which is not allowed with global routing.\n",
00336                          inode);
00337                     exit(1);
00338                 }
00339             break;
00340 
00341         case CHANY:
00342             if(xhigh > nx || ylow < 1 || yhigh > ny || xlow != xhigh)
00343                 {
00344                     printf("Error in check_node:  CHANY out of range.\n");
00345                     printf("Endpoints: (%d,%d) and (%d,%d)\n", xlow, ylow,
00346                            xhigh, yhigh);
00347                     exit(1);
00348                 }
00349             if(route_type == GLOBAL && ylow != yhigh)
00350                 {
00351                     printf
00352                         ("Error in check_node:  node %d spans multiple channel segments\n"
00353                          "which is not allowed with global routing.\n",
00354                          inode);
00355                     exit(1);
00356                 }
00357             break;
00358 
00359         default:
00360             printf("Error in check_node:  Unexpected segment type: %d\n",
00361                    rr_type);
00362             exit(1);
00363         }
00364 
00365 /* Check that it's capacities and such make sense. */
00366 
00367     switch (rr_type)
00368         {
00369 
00370         case SOURCE:
00371 
00372             if(ptc_num >= type->num_class
00373                || type->class_inf[ptc_num].type != DRIVER)
00374                 {
00375                     printf
00376                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00377                          "of %d.\n", inode, rr_type, ptc_num);
00378                     exit(1);
00379                 }
00380             if(type->class_inf[ptc_num].num_pins != capacity)
00381                 {
00382                     printf
00383                         ("Error in check_node.  Inode %d (type %d) had a capacity\n"
00384                          "of %d.\n", inode, rr_type, capacity);
00385                     exit(1);
00386                 }
00387 
00388             break;
00389 
00390         case SINK:
00391 
00392             if(ptc_num >= type->num_class
00393                || type->class_inf[ptc_num].type != RECEIVER)
00394                 {
00395                     printf
00396                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00397                          "of %d.\n", inode, rr_type, ptc_num);
00398                     exit(1);
00399                 }
00400             if(type->class_inf[ptc_num].num_pins != capacity)
00401                 {
00402                     printf
00403                         ("Error in check_node.  Inode %d (type %d) has a capacity\n"
00404                          "of %d.\n", inode, rr_type, capacity);
00405                     exit(1);
00406                 }
00407             break;
00408 
00409         case OPIN:
00410 
00411             if(ptc_num >= type->num_pins
00412                || type->class_inf[type->pin_class[ptc_num]].type != DRIVER)
00413                 {
00414                     printf
00415                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00416                          "of %d.\n", inode, rr_type, ptc_num);
00417                     exit(1);
00418                 }
00419 
00420             if(capacity != 1)
00421                 {
00422                     printf
00423                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00424                          "of %d.\n", inode, rr_type, capacity);
00425                     exit(1);
00426                 }
00427             break;
00428 
00429         case IPIN:
00430             if(ptc_num >= type->num_pins
00431                || type->class_inf[type->pin_class[ptc_num]].type != RECEIVER)
00432                 {
00433                     printf
00434                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00435                          "of %d.\n", inode, rr_type, ptc_num);
00436                     exit(1);
00437                 }
00438             if(capacity != 1)
00439                 {
00440                     printf
00441                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00442                          "of %d.\n", inode, rr_type, capacity);
00443                     exit(1);
00444                 }
00445             break;
00446 
00447         case CHANX:
00448             if(route_type == DETAILED)
00449                 {
00450                     nodes_per_chan = chan_width_x[ylow];
00451                     tracks_per_node = 1;
00452                 }
00453             else
00454                 {
00455                     nodes_per_chan = 1;
00456                     tracks_per_node = chan_width_x[ylow];
00457                 }
00458 
00459             if(ptc_num >= nodes_per_chan)
00460                 {
00461                     printf
00462                         ("Error in check_node:  Inode %d (type %d) has a ptc_num\n"
00463                          "of %d.\n", inode, rr_type, ptc_num);
00464                     exit(1);
00465                 }
00466 
00467             if(capacity != tracks_per_node)
00468                 {
00469                     printf
00470                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00471                          "of %d.\n", inode, rr_type, capacity);
00472                     exit(1);
00473                 }
00474             break;
00475 
00476         case CHANY:
00477             if(route_type == DETAILED)
00478                 {
00479                     nodes_per_chan = chan_width_y[xlow];
00480                     tracks_per_node = 1;
00481                 }
00482             else
00483                 {
00484                     nodes_per_chan = 1;
00485                     tracks_per_node = chan_width_y[xlow];
00486                 }
00487 
00488             if(ptc_num >= nodes_per_chan)
00489                 {
00490                     printf
00491                         ("Error in check_node:  Inode %d (type %d) has a ptc_num\n"
00492                          "of %d.\n", inode, rr_type, ptc_num);
00493                     exit(1);
00494                 }
00495 
00496             if(capacity != tracks_per_node)
00497                 {
00498                     printf
00499                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00500                          "of %d.\n", inode, rr_type, capacity);
00501                     exit(1);
00502                 }
00503             break;
00504 
00505         default:
00506             printf("Error in check_node:  Unexpected segment type: %d\n",
00507                    rr_type);
00508             exit(1);
00509 
00510         }
00511 
00512 /* Check that the number of (out) edges is reasonable. */
00513     num_edges = rr_node[inode].num_edges;
00514 
00515     if(rr_type != SINK)
00516         {
00517             if(num_edges <= 0)
00518                 {
00519                     printf("Error: in check_node: node %d has no edges.\n",
00520                            inode);
00521                     exit(1);
00522                 }
00523         }
00524 
00525     else
00526         {                       /* SINK -- remove this check if feedthroughs allowed */
00527             if(num_edges != 0)
00528                 {
00529                     printf("Error in check_node: node %d is a sink, but has "
00530                            "%d edges.\n", inode, num_edges);
00531                     exit(1);
00532                 }
00533         }
00534 
00535 /* Check that the capacitance, resistance and cost_index are reasonable. */
00536 
00537     C = rr_node[inode].C;
00538     R = rr_node[inode].R;
00539 
00540     if(rr_type == CHANX || rr_type == CHANY)
00541         {
00542             if(C < 0. || R < 0.)
00543                 {
00544                     printf
00545                         ("Error in check_node: node %d of type %d has R = %g "
00546                          "and C = %g.\n", inode, rr_type, R, C);
00547                     exit(1);
00548                 }
00549         }
00550 
00551     else
00552         {
00553             if(C != 0. || R != 0.)
00554                 {
00555                     printf
00556                         ("Error in check_node: node %d of type %d has R = %g "
00557                          "and C = %g.\n", inode, rr_type, R, C);
00558                     exit(1);
00559                 }
00560         }
00561 
00562     cost_index = rr_node[inode].cost_index;
00563     if(cost_index < 0 || cost_index >= num_rr_indexed_data)
00564         {
00565             printf("Error in check_node:  node %d cost index (%d) is out of "
00566                    "range.\n", inode, cost_index);
00567             exit(1);
00568         }
00569 }

Here is the caller graph for this function:

static void check_pass_transistors ( int  from_node  )  [static]

Definition at line 573 of file check_rr_graph.c.

00574 {
00575 
00576 /* This routine checks that all pass transistors in the routing truly are  *
00577  * bidirectional.  It may be a slow check, so don't use it all the time.   */
00578 
00579     int from_edge, to_node, to_edge, from_num_edges, to_num_edges;
00580     t_rr_type from_rr_type, to_rr_type;
00581     short from_switch_type;
00582     boolean trans_matched;
00583 
00584 
00585     from_rr_type = rr_node[from_node].type;
00586     if(from_rr_type != CHANX && from_rr_type != CHANY)
00587         return;
00588 
00589     from_num_edges = rr_node[from_node].num_edges;
00590 
00591     for(from_edge = 0; from_edge < from_num_edges; from_edge++)
00592         {
00593             to_node = rr_node[from_node].edges[from_edge];
00594             to_rr_type = rr_node[to_node].type;
00595 
00596             if(to_rr_type != CHANX && to_rr_type != CHANY)
00597                 continue;
00598 
00599             from_switch_type = rr_node[from_node].switches[from_edge];
00600 
00601             if(switch_inf[from_switch_type].buffered)
00602                 continue;
00603 
00604             /* We know that we have a pass transitor from from_node to to_node.  Now *
00605              * check that there is a corresponding edge from to_node back to         *
00606              * from_node.                                                            */
00607 
00608             to_num_edges = rr_node[to_node].num_edges;
00609             trans_matched = FALSE;
00610 
00611             for(to_edge = 0; to_edge < to_num_edges; to_edge++)
00612                 {
00613                     if(rr_node[to_node].edges[to_edge] == from_node &&
00614                        rr_node[to_node].switches[to_edge] == from_switch_type)
00615                         {
00616                             trans_matched = TRUE;
00617                             break;
00618                         }
00619                 }
00620 
00621             if(trans_matched == FALSE)
00622                 {
00623                     printf
00624                         ("Error in check_pass_transistors:  Connection from node %d to\n"
00625                          "node %d uses a pass transistor (switch type %d), but there is\n"
00626                          "no corresponding pass transistor edge in the other direction.\n",
00627                          from_node, to_node, from_switch_type);
00628                     exit(1);
00629                 }
00630 
00631         }                       /* End for all from_node edges */
00632 }

Here is the caller graph for this function:

void check_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  nodes_per_chan,
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 int  wire_to_ipin_switch,
t_seg_details seg_details,
int *  Fc_in,
int *  Fc_out,
t_ivec ***  rr_node_indices,
int *****  opin_to_track_map,
int *****  ipin_to_track_map,
t_ivec ****  track_to_ipin_lookup,
t_ivec ***  switch_block_conn,
boolean perturb_ipins 
)

Definition at line 28 of file check_rr_graph.c.

00051 {
00052 
00053 
00054     int *num_edges_from_current_to_node;        /* [0..num_rr_nodes-1] */
00055     int *total_edges_to_node;   /* [0..num_rr_nodes-1] */
00056     char *switch_types_from_current_to_node;    /* [0..num_rr_nodes-1] */
00057     int inode, iedge, to_node, num_edges;
00058     short switch_type;
00059     t_rr_type rr_type, to_rr_type;
00060     enum e_route_type route_type;
00061         boolean is_fringe_warning_sent;
00062 
00063     route_type = DETAILED;
00064     if(graph_type == GRAPH_GLOBAL)
00065         {
00066             route_type = GLOBAL;
00067         }
00068 
00069     total_edges_to_node = (int *)my_calloc(num_rr_nodes, sizeof(int));
00070     num_edges_from_current_to_node = (int *)my_calloc(num_rr_nodes,
00071                                                       sizeof(int));
00072     switch_types_from_current_to_node = (char *)my_calloc(num_rr_nodes,
00073                                                           sizeof(char));
00074 
00075     for(inode = 0; inode < num_rr_nodes; inode++)
00076         {
00077             rr_type = rr_node[inode].type;
00078             num_edges = rr_node[inode].num_edges;
00079 
00080             check_node(inode, route_type);
00081 
00082 /* Check all the connectivity (edges, etc.) information.                    */
00083 
00084             for(iedge = 0; iedge < num_edges; iedge++)
00085                 {
00086                     to_node = rr_node[inode].edges[iedge];
00087 
00088                     if(to_node < 0 || to_node >= num_rr_nodes)
00089                         {
00090                             printf
00091                                 ("Error in check_rr_graph:  node %d has an edge %d.\n"
00092                                  "Edge is out of range.\n", inode, to_node);
00093                             exit(1);
00094                         }
00095 
00096                     num_edges_from_current_to_node[to_node]++;
00097                     total_edges_to_node[to_node]++;
00098 
00099                     switch_type = rr_node[inode].switches[iedge];
00100 
00101                     if(switch_type < 0 || switch_type >= num_switches)
00102                         {
00103                             printf
00104                                 ("Error in check_rr_graph:  node %d has a switch type %d.\n"
00105                                  "Switch type is out of range.\n", inode,
00106                                  switch_type);
00107                             exit(1);
00108                         }
00109 
00110                     if(switch_inf[switch_type].buffered)
00111                         switch_types_from_current_to_node[to_node] |=
00112                             BUF_FLAG;
00113                     else
00114                         switch_types_from_current_to_node[to_node] |=
00115                             PTRANS_FLAG;
00116 
00117                 }               /* End for all edges of node. */
00118 
00119 
00120             for(iedge = 0; iedge < num_edges; iedge++)
00121                 {
00122                     to_node = rr_node[inode].edges[iedge];
00123 
00124                     if(num_edges_from_current_to_node[to_node] > 1)
00125                         {
00126                             to_rr_type = rr_node[to_node].type;
00127 
00128                             if((to_rr_type != CHANX && to_rr_type != CHANY) ||
00129                                (rr_type != CHANX && rr_type != CHANY))
00130                                 {
00131                                     printf
00132                                         ("Error in check_rr_graph:  node %d connects to node %d "
00133                                          "%d times.\n", inode, to_node,
00134                                          num_edges_from_current_to_node
00135                                          [to_node]);
00136                                     exit(1);
00137                                 }
00138 
00139                             /* Between two wire segments.  Two connections are legal only if  *
00140                              * one connection is a buffer and the other is a pass transistor. */
00141 
00142                             else if(num_edges_from_current_to_node[to_node] !=
00143                                     2
00144                                     ||
00145                                     switch_types_from_current_to_node[to_node]
00146                                     != BUF_AND_PTRANS_FLAG)
00147                                 {
00148                                     printf
00149                                         ("Error in check_rr_graph:  node %d connects to node %d "
00150                                          "%d times.\n", inode, to_node,
00151                                          num_edges_from_current_to_node
00152                                          [to_node]);
00153                                     exit(1);
00154                                 }
00155                         }
00156 
00157                     num_edges_from_current_to_node[to_node] = 0;
00158                     switch_types_from_current_to_node[to_node] = 0;
00159                 }
00160 
00161             /* Slow test below.  Leave commented out most of the time. */
00162 
00163 #ifdef DEBUG
00164             check_pass_transistors(inode);
00165 #endif
00166 
00167         }                       /* End for all rr_nodes */
00168 
00169 
00170 /* I built a list of how many edges went to everything in the code above -- *
00171  * now I check that everything is reachable.                                */
00172         is_fringe_warning_sent = FALSE;
00173 
00174     for(inode = 0; inode < num_rr_nodes; inode++)
00175         {
00176             rr_type = rr_node[inode].type;
00177 
00178             if(rr_type != SOURCE)
00179                 {
00180                     if(total_edges_to_node[inode] < 1 &&
00181                        !rr_node_is_global_clb_ipin(inode))
00182                         {
00183                                 boolean is_fringe;
00184                                 boolean is_wire;
00185 
00186                             /* A global FB input pin will not have any edges, and neither will  *
00187                              * a SOURCE.  Anything else is an error.                             */
00188 
00189                                 is_fringe =  ((rr_node[inode].xlow == 1) || (rr_node[inode].ylow == 1) 
00190                                                 || (rr_node[inode].xhigh == nx) || (rr_node[inode].yhigh == ny));
00191                                 is_wire = (rr_node[inode].type == CHANX || rr_node[inode].type == CHANY);  
00192 
00193                                 if (!is_fringe && !is_wire)
00194                                 {
00195                                         printf ("Error in check_rr_graph:  node %d has no fanin.\n", inode);
00196                                         exit(1);
00197                                 }
00198                                 else if (!is_fringe_warning_sent) 
00199                                 {
00200                                         printf ("WARNING: in check_rr_graph:  fringe node %d has no fanin.\n"
00201                                                         "This is possible on the fringe for low Fc_out, N, and certain Lengths\n"
00202                                                         , inode);
00203                                         is_fringe_warning_sent = TRUE;
00204                                 }
00205                         }
00206                 }
00207 
00208             else
00209                 {               /* SOURCE.  No fanin for now; change if feedthroughs allowed. */
00210                     if(total_edges_to_node[inode] != 0)
00211                         {
00212                             printf
00213                                 ("Error in check_rr_graph:  SOURCE node %d has a fanin\n"
00214                                  "\tof %d, expected 0.\n", inode,
00215                                  total_edges_to_node[inode]);
00216                             exit(1);
00217                         }
00218                 }
00219         }
00220 
00221     free(num_edges_from_current_to_node);
00222     free(total_edges_to_node);
00223     free(switch_types_from_current_to_node);
00224 }

Here is the call graph for this function:

Here is the caller graph for this function:

static boolean rr_node_is_global_clb_ipin ( int  inode  )  [static]

Definition at line 228 of file check_rr_graph.c.

00229 {
00230 
00231 /* Returns TRUE if inode refers to a global FB input pin node.   */
00232 
00233     int ipin;
00234     t_type_ptr type;
00235 
00236     type = grid[rr_node[inode].xlow][rr_node[inode].ylow].type;
00237 
00238     if(rr_node[inode].type != IPIN)
00239         return (FALSE);
00240 
00241     ipin = rr_node[inode].ptc_num;
00242 
00243     return (type->is_global_pin[ipin]);
00244 }

Here is the caller graph for this function:


Variable Documentation

Definition at line 24 of file check_rr_graph.c.

Definition at line 25 of file check_rr_graph.c.


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