VPR-6.0

vpr/SRC/route/check_rr_graph.c

Go to the documentation of this file.
00001 #include "util.h"
00002 #include "vpr_types.h"
00003 #include "globals.h"
00004 #include "rr_graph.h"
00005 #include "check_rr_graph.h"
00006 
00007 
00008 /********************** Local defines and types *****************************/
00009 
00010 #define BUF_FLAG 1
00011 #define PTRANS_FLAG 2
00012 #define BUF_AND_PTRANS_FLAG 3
00013 
00014 
00015 /*********************** Subroutines local to this module *******************/
00016 
00017 static boolean rr_node_is_global_clb_ipin(int inode);
00018 
00019 static void check_pass_transistors(int from_node);
00020 
00021 
00022 /************************ Subroutine definitions ****************************/
00023 
00024 void
00025 check_rr_graph(INP t_graph_type graph_type,
00026                INP int num_types,
00027                INP t_type_ptr types,
00028                INP int nx,
00029                INP int ny,
00030                INP struct s_grid_tile **grid,
00031                INP int nodes_per_chan,
00032                INP int Fs,
00033                INP int num_seg_types,
00034                    INP int num_switches,
00035                INP t_segment_inf * segment_inf,
00036                INP int global_route_switch,
00037                INP int delayless_switch,
00038                INP int wire_to_ipin_switch,
00039                t_seg_details * seg_details,
00040                int *Fc_in,
00041                int *Fc_out,
00042                t_ivec *** rr_node_indices,
00043                int *****opin_to_track_map,
00044                int *****ipin_to_track_map,
00045                t_ivec **** track_to_ipin_lookup,
00046                t_ivec *** switch_block_conn,
00047                boolean * perturb_ipins)
00048 {
00049 
00050 
00051     int *num_edges_from_current_to_node;        /* [0..num_rr_nodes-1] */
00052     int *total_edges_to_node;   /* [0..num_rr_nodes-1] */
00053     char *switch_types_from_current_to_node;    /* [0..num_rr_nodes-1] */
00054     int inode, iedge, to_node, num_edges;
00055     short switch_type;
00056     t_rr_type rr_type, to_rr_type;
00057     enum e_route_type route_type;
00058         boolean is_fringe_warning_sent;
00059 
00060     route_type = DETAILED;
00061     if(graph_type == GRAPH_GLOBAL)
00062         {
00063             route_type = GLOBAL;
00064         }
00065 
00066     total_edges_to_node = (int *)my_calloc(num_rr_nodes, sizeof(int));
00067     num_edges_from_current_to_node = (int *)my_calloc(num_rr_nodes,
00068                                                       sizeof(int));
00069     switch_types_from_current_to_node = (char *)my_calloc(num_rr_nodes,
00070                                                           sizeof(char));
00071 
00072     for(inode = 0; inode < num_rr_nodes; inode++)
00073         {
00074             rr_type = rr_node[inode].type;
00075             num_edges = rr_node[inode].num_edges;
00076 
00077             check_node(inode, route_type);
00078 
00079 /* Check all the connectivity (edges, etc.) information.                    */
00080 
00081             for(iedge = 0; iedge < num_edges; iedge++)
00082                 {
00083                     to_node = rr_node[inode].edges[iedge];
00084 
00085                     if(to_node < 0 || to_node >= num_rr_nodes)
00086                         {
00087                             printf
00088                                 ("Error in check_rr_graph:  node %d has an edge %d.\n"
00089                                  "Edge is out of range.\n", inode, to_node);
00090                             exit(1);
00091                         }
00092 
00093                     num_edges_from_current_to_node[to_node]++;
00094                     total_edges_to_node[to_node]++;
00095 
00096                     switch_type = rr_node[inode].switches[iedge];
00097 
00098                     if(switch_type < 0 || switch_type >= num_switches)
00099                         {
00100                             printf
00101                                 ("Error in check_rr_graph:  node %d has a switch type %d.\n"
00102                                  "Switch type is out of range.\n", inode,
00103                                  switch_type);
00104                             exit(1);
00105                         }
00106 
00107                     if(switch_inf[switch_type].buffered)
00108                         switch_types_from_current_to_node[to_node] |=
00109                             BUF_FLAG;
00110                     else
00111                         switch_types_from_current_to_node[to_node] |=
00112                             PTRANS_FLAG;
00113 
00114                 }               /* End for all edges of node. */
00115 
00116 
00117             for(iedge = 0; iedge < num_edges; iedge++)
00118                 {
00119                     to_node = rr_node[inode].edges[iedge];
00120 
00121                     if(num_edges_from_current_to_node[to_node] > 1)
00122                         {
00123                             to_rr_type = rr_node[to_node].type;
00124 
00125                             if((to_rr_type != CHANX && to_rr_type != CHANY) ||
00126                                (rr_type != CHANX && rr_type != CHANY))
00127                                 {
00128                                     printf
00129                                         ("Error in check_rr_graph:  node %d connects to node %d "
00130                                          "%d times.\n", inode, to_node,
00131                                          num_edges_from_current_to_node
00132                                          [to_node]);
00133                                     exit(1);
00134                                 }
00135 
00136                             /* Between two wire segments.  Two connections are legal only if  *
00137                              * one connection is a buffer and the other is a pass transistor. */
00138 
00139                             else if(num_edges_from_current_to_node[to_node] !=
00140                                     2
00141                                     ||
00142                                     switch_types_from_current_to_node[to_node]
00143                                     != BUF_AND_PTRANS_FLAG)
00144                                 {
00145                                     printf
00146                                         ("Error in check_rr_graph:  node %d connects to node %d "
00147                                          "%d times.\n", inode, to_node,
00148                                          num_edges_from_current_to_node
00149                                          [to_node]);
00150                                     exit(1);
00151                                 }
00152                         }
00153 
00154                     num_edges_from_current_to_node[to_node] = 0;
00155                     switch_types_from_current_to_node[to_node] = 0;
00156                 }
00157 
00158             /* Slow test below.  Leave commented out most of the time. */
00159 
00160 #ifdef DEBUG
00161             check_pass_transistors(inode);
00162 #endif
00163 
00164         }                       /* End for all rr_nodes */
00165 
00166 
00167 /* I built a list of how many edges went to everything in the code above -- *
00168  * now I check that everything is reachable.                                */
00169         is_fringe_warning_sent = FALSE;
00170 
00171     for(inode = 0; inode < num_rr_nodes; inode++)
00172         {
00173             rr_type = rr_node[inode].type;
00174 
00175             if(rr_type != SOURCE)
00176                 {
00177                     if(total_edges_to_node[inode] < 1 &&
00178                        !rr_node_is_global_clb_ipin(inode))
00179                         {
00180                                 boolean is_fringe;
00181                                 boolean is_wire;
00182 
00183                             /* A global CLB input pin will not have any edges, and neither will  *
00184                              * a SOURCE.  Anything else is an error.                             */
00185 
00186                                 is_fringe =  ((rr_node[inode].xlow == 1) || (rr_node[inode].ylow == 1) 
00187                                                 || (rr_node[inode].xhigh == nx) || (rr_node[inode].yhigh == ny));
00188                                 is_wire = (rr_node[inode].type == CHANX || rr_node[inode].type == CHANY);  
00189 
00190                                 if (!is_fringe && !is_wire)
00191                                 {
00192                                         printf ("Error in check_rr_graph:  node %d has no fanin.\n", inode);
00193                                         exit(1);
00194                                 }
00195                                 else if (!is_fringe_warning_sent) 
00196                                 {
00197                                         printf ("WARNING: in check_rr_graph:  fringe node %d has no fanin.\n"
00198                                                         "This is possible on the fringe for low Fc_out, N, and certain Lengths\n"
00199                                                         , inode);
00200                                         is_fringe_warning_sent = TRUE;
00201                                 }
00202                         }
00203                 }
00204 
00205             else
00206                 {               /* SOURCE.  No fanin for now; change if feedthroughs allowed. */
00207                     if(total_edges_to_node[inode] != 0)
00208                         {
00209                             printf
00210                                 ("Error in check_rr_graph:  SOURCE node %d has a fanin\n"
00211                                  "\tof %d, expected 0.\n", inode,
00212                                  total_edges_to_node[inode]);
00213                             exit(1);
00214                         }
00215                 }
00216         }
00217 
00218     free(num_edges_from_current_to_node);
00219     free(total_edges_to_node);
00220     free(switch_types_from_current_to_node);
00221 }
00222 
00223 
00224 /** Returns TRUE if inode refers to a global CLB input pin node.   */
00225 static boolean
00226 rr_node_is_global_clb_ipin(int inode)
00227 {
00228     int ipin;
00229     t_type_ptr type;
00230 
00231     type = grid[rr_node[inode].xlow][rr_node[inode].ylow].type;
00232 
00233     if(rr_node[inode].type != IPIN)
00234         return (FALSE);
00235 
00236     ipin = rr_node[inode].ptc_num;
00237 
00238     return (type->is_global_pin[ipin]);
00239 }
00240 
00241 /** This routine checks that the rr_node is inside the grid and has a valid  
00242  * pin number, etc.                                                         
00243  */
00244 void
00245 check_node(int inode,
00246            enum e_route_type route_type)
00247 {
00248     int xlow, ylow, xhigh, yhigh, ptc_num, capacity;
00249     t_rr_type rr_type;
00250     t_type_ptr type;
00251     int nodes_per_chan, tracks_per_node, num_edges, cost_index;
00252     float C, R;
00253 
00254     rr_type = rr_node[inode].type;
00255     xlow = rr_node[inode].xlow;
00256     xhigh = rr_node[inode].xhigh;
00257     ylow = rr_node[inode].ylow;
00258     yhigh = rr_node[inode].yhigh;
00259     ptc_num = rr_node[inode].ptc_num;
00260     capacity = rr_node[inode].capacity;
00261     type = NULL;
00262 
00263     if(xlow > xhigh || ylow > yhigh)
00264         {
00265             printf
00266                 ("Error in check_node:  rr endpoints are (%d,%d) and (%d,%d).\n",
00267                  xlow, ylow, xhigh, yhigh);
00268             exit(1);
00269         }
00270 
00271     if(xlow < 0 || xhigh > nx + 1 || ylow < 0 || yhigh > ny + 1)
00272         {
00273             printf
00274                 ("Error in check_node:  rr endpoints, (%d,%d) and (%d,%d), \n"
00275                  "are out of range.\n", xlow, ylow, xhigh, yhigh);
00276             exit(1);
00277         }
00278 
00279     if(ptc_num < 0)
00280         {
00281             printf("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00282                    "of %d.\n", inode, rr_type, ptc_num);
00283             exit(1);
00284         }
00285 
00286 /* Check that the segment is within the array and such. */
00287 
00288     switch (rr_type)
00289         {
00290 
00291         case SOURCE:
00292         case SINK:
00293         case IPIN:
00294         case OPIN:
00295             /* This is used later as well */
00296             type = grid[xlow][ylow].type;
00297 
00298             if(type == NULL)
00299                 {
00300                     printf
00301                         ("Error in check_node:  Node %d (type %d) is at an illegal\n"
00302                          " clb location (%d, %d).\n", inode, rr_type, xlow,
00303                          ylow);
00304                     exit(1);
00305                 }
00306             if(xlow != xhigh || ylow != (yhigh - type->height + 1))
00307                 {
00308                     printf
00309                         ("Error in check_node:  Node %d (type %d) has endpoints of\n"
00310                          "(%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow,
00311                          xhigh, yhigh);
00312                     exit(1);
00313                 }
00314             break;
00315 
00316         case CHANX:
00317             if(xlow < 1 || xhigh > nx || yhigh > ny || yhigh != ylow)
00318                 {
00319                     printf("Error in check_node:  CHANX out of range.\n");
00320                     printf("Endpoints: (%d,%d) and (%d,%d)\n", xlow, ylow,
00321                            xhigh, yhigh);
00322                     exit(1);
00323                 }
00324             if(route_type == GLOBAL && xlow != xhigh)
00325                 {
00326                     printf
00327                         ("Error in check_node:  node %d spans multiple channel segments\n"
00328                          "which is not allowed with global routing.\n",
00329                          inode);
00330                     exit(1);
00331                 }
00332             break;
00333 
00334         case CHANY:
00335             if(xhigh > nx || ylow < 1 || yhigh > ny || xlow != xhigh)
00336                 {
00337                     printf("Error in check_node:  CHANY out of range.\n");
00338                     printf("Endpoints: (%d,%d) and (%d,%d)\n", xlow, ylow,
00339                            xhigh, yhigh);
00340                     exit(1);
00341                 }
00342             if(route_type == GLOBAL && ylow != yhigh)
00343                 {
00344                     printf
00345                         ("Error in check_node:  node %d spans multiple channel segments\n"
00346                          "which is not allowed with global routing.\n",
00347                          inode);
00348                     exit(1);
00349                 }
00350             break;
00351 
00352         default:
00353             printf("Error in check_node:  Unexpected segment type: %d\n",
00354                    rr_type);
00355             exit(1);
00356         }
00357 
00358 /* Check that it's capacities and such make sense. */
00359 
00360     switch (rr_type)
00361         {
00362 
00363         case SOURCE:
00364 
00365             if(ptc_num >= type->num_class
00366                || type->class_inf[ptc_num].type != DRIVER)
00367                 {
00368                     printf
00369                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00370                          "of %d.\n", inode, rr_type, ptc_num);
00371                     exit(1);
00372                 }
00373             if(type->class_inf[ptc_num].num_pins != capacity)
00374                 {
00375                     printf
00376                         ("Error in check_node.  Inode %d (type %d) had a capacity\n"
00377                          "of %d.\n", inode, rr_type, capacity);
00378                     exit(1);
00379                 }
00380 
00381             break;
00382 
00383         case SINK:
00384 
00385             if(ptc_num >= type->num_class
00386                || type->class_inf[ptc_num].type != RECEIVER)
00387                 {
00388                     printf
00389                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00390                          "of %d.\n", inode, rr_type, ptc_num);
00391                     exit(1);
00392                 }
00393             if(type->class_inf[ptc_num].num_pins != capacity)
00394                 {
00395                     printf
00396                         ("Error in check_node.  Inode %d (type %d) has a capacity\n"
00397                          "of %d.\n", inode, rr_type, capacity);
00398                     exit(1);
00399                 }
00400             break;
00401 
00402         case OPIN:
00403 
00404             if(ptc_num >= type->num_pins
00405                || type->class_inf[type->pin_class[ptc_num]].type != DRIVER)
00406                 {
00407                     printf
00408                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00409                          "of %d.\n", inode, rr_type, ptc_num);
00410                     exit(1);
00411                 }
00412 
00413             if(capacity != 1)
00414                 {
00415                     printf
00416                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00417                          "of %d.\n", inode, rr_type, capacity);
00418                     exit(1);
00419                 }
00420             break;
00421 
00422         case IPIN:
00423             if(ptc_num >= type->num_pins
00424                || type->class_inf[type->pin_class[ptc_num]].type != RECEIVER)
00425                 {
00426                     printf
00427                         ("Error in check_node.  Inode %d (type %d) had a ptc_num\n"
00428                          "of %d.\n", inode, rr_type, ptc_num);
00429                     exit(1);
00430                 }
00431             if(capacity != 1)
00432                 {
00433                     printf
00434                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00435                          "of %d.\n", inode, rr_type, capacity);
00436                     exit(1);
00437                 }
00438             break;
00439 
00440         case CHANX:
00441             if(route_type == DETAILED)
00442                 {
00443                     nodes_per_chan = chan_width_x[ylow];
00444                     tracks_per_node = 1;
00445                 }
00446             else
00447                 {
00448                     nodes_per_chan = 1;
00449                     tracks_per_node = chan_width_x[ylow];
00450                 }
00451 
00452             if(ptc_num >= nodes_per_chan)
00453                 {
00454                     printf
00455                         ("Error in check_node:  Inode %d (type %d) has a ptc_num\n"
00456                          "of %d.\n", inode, rr_type, ptc_num);
00457                     exit(1);
00458                 }
00459 
00460             if(capacity != tracks_per_node)
00461                 {
00462                     printf
00463                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00464                          "of %d.\n", inode, rr_type, capacity);
00465                     exit(1);
00466                 }
00467             break;
00468 
00469         case CHANY:
00470             if(route_type == DETAILED)
00471                 {
00472                     nodes_per_chan = chan_width_y[xlow];
00473                     tracks_per_node = 1;
00474                 }
00475             else
00476                 {
00477                     nodes_per_chan = 1;
00478                     tracks_per_node = chan_width_y[xlow];
00479                 }
00480 
00481             if(ptc_num >= nodes_per_chan)
00482                 {
00483                     printf
00484                         ("Error in check_node:  Inode %d (type %d) has a ptc_num\n"
00485                          "of %d.\n", inode, rr_type, ptc_num);
00486                     exit(1);
00487                 }
00488 
00489             if(capacity != tracks_per_node)
00490                 {
00491                     printf
00492                         ("Error in check_node:  Inode %d (type %d) has a capacity\n"
00493                          "of %d.\n", inode, rr_type, capacity);
00494                     exit(1);
00495                 }
00496             break;
00497 
00498         default:
00499             printf("Error in check_node:  Unexpected segment type: %d\n",
00500                    rr_type);
00501             exit(1);
00502 
00503         }
00504 
00505 /* Check that the number of (out) edges is reasonable. */
00506     num_edges = rr_node[inode].num_edges;
00507 
00508     if(rr_type != SINK)
00509         {
00510             if(num_edges <= 0)
00511                 {
00512                     printf("Error: in check_node: node %d has no edges.\n",
00513                            inode);
00514                     exit(1);
00515                 }
00516         }
00517 
00518     else
00519         {                       /* SINK -- remove this check if feedthroughs allowed */
00520             if(num_edges != 0)
00521                 {
00522                     printf("Error in check_node: node %d is a sink, but has "
00523                            "%d edges.\n", inode, num_edges);
00524                     exit(1);
00525                 }
00526         }
00527 
00528 /* Check that the capacitance, resistance and cost_index are reasonable. */
00529 
00530     C = rr_node[inode].C;
00531     R = rr_node[inode].R;
00532 
00533     if(rr_type == CHANX || rr_type == CHANY)
00534         {
00535             if(C < 0. || R < 0.)
00536                 {
00537                     printf
00538                         ("Error in check_node: node %d of type %d has R = %g "
00539                          "and C = %g.\n", inode, rr_type, R, C);
00540                     exit(1);
00541                 }
00542         }
00543 
00544     else
00545         {
00546             if(C != 0. || R != 0.)
00547                 {
00548                     printf
00549                         ("Error in check_node: node %d of type %d has R = %g "
00550                          "and C = %g.\n", inode, rr_type, R, C);
00551                     exit(1);
00552                 }
00553         }
00554 
00555     cost_index = rr_node[inode].cost_index;
00556     if(cost_index < 0 || cost_index >= num_rr_indexed_data)
00557         {
00558             printf("Error in check_node:  node %d cost index (%d) is out of "
00559                    "range.\n", inode, cost_index);
00560             exit(1);
00561         }
00562 }
00563 
00564 /** This routine checks that all pass transistors in the routing truly are  
00565  * bidirectional.  It may be a slow check, so don't use it all the time.   
00566  */
00567 static void
00568 check_pass_transistors(int from_node)
00569 {
00570     int from_edge, to_node, to_edge, from_num_edges, to_num_edges;
00571     t_rr_type from_rr_type, to_rr_type;
00572     short from_switch_type;
00573     boolean trans_matched;
00574 
00575 
00576     from_rr_type = rr_node[from_node].type;
00577     if(from_rr_type != CHANX && from_rr_type != CHANY)
00578         return;
00579 
00580     from_num_edges = rr_node[from_node].num_edges;
00581 
00582     for(from_edge = 0; from_edge < from_num_edges; from_edge++)
00583         {
00584             to_node = rr_node[from_node].edges[from_edge];
00585             to_rr_type = rr_node[to_node].type;
00586 
00587             if(to_rr_type != CHANX && to_rr_type != CHANY)
00588                 continue;
00589 
00590             from_switch_type = rr_node[from_node].switches[from_edge];
00591 
00592             if(switch_inf[from_switch_type].buffered)
00593                 continue;
00594 
00595             /* We know that we have a pass transitor from from_node to to_node.  Now *
00596              * check that there is a corresponding edge from to_node back to         *
00597              * from_node.                                                            */
00598 
00599             to_num_edges = rr_node[to_node].num_edges;
00600             trans_matched = FALSE;
00601 
00602             for(to_edge = 0; to_edge < to_num_edges; to_edge++)
00603                 {
00604                     if(rr_node[to_node].edges[to_edge] == from_node &&
00605                        rr_node[to_node].switches[to_edge] == from_switch_type)
00606                         {
00607                             trans_matched = TRUE;
00608                             break;
00609                         }
00610                 }
00611 
00612             if(trans_matched == FALSE)
00613                 {
00614                     printf
00615                         ("Error in check_pass_transistors:  Connection from node %d to\n"
00616                          "node %d uses a pass transistor (switch type %d), but there is\n"
00617                          "no corresponding pass transistor edge in the other direction.\n",
00618                          from_node, to_node, from_switch_type);
00619                     exit(1);
00620                 }
00621 
00622         }                       /* End for all from_node edges */
00623 }