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
00009
00010 #define BUF_FLAG 1
00011 #define PTRANS_FLAG 2
00012 #define BUF_AND_PTRANS_FLAG 3
00013
00014
00015
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
00023
00024 static boolean rr_graph_error;
00025 static boolean rr_graph_warn;
00026
00027 void
00028 check_rr_graph(IN t_graph_type graph_type,
00029 IN int num_types,
00030 IN t_type_ptr types,
00031 IN int nx,
00032 IN int ny,
00033 IN struct s_grid_tile **grid,
00034 IN int nodes_per_chan,
00035 IN int Fs,
00036 IN int num_seg_types,
00037 IN int num_switches,
00038 IN t_segment_inf * segment_inf,
00039 IN int global_route_switch,
00040 IN int delayless_switch,
00041 IN int wire_to_ipin_switch,
00042 t_seg_details * seg_details,
00043 int *Fc_in,
00044 int *Fc_out,
00045 t_ivec *** rr_node_indices,
00046 int *****opin_to_track_map,
00047 int *****ipin_to_track_map,
00048 t_ivec **** track_to_ipin_lookup,
00049 t_ivec *** switch_block_conn,
00050 boolean * perturb_ipins)
00051 {
00052
00053
00054 int *num_edges_from_current_to_node;
00055 int *total_edges_to_node;
00056 char *switch_types_from_current_to_node;
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
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 }
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
00140
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
00162
00163 #ifdef DEBUG
00164 check_pass_transistors(inode);
00165 #endif
00166
00167 }
00168
00169
00170
00171
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
00187
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 {
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 }
00225
00226
00227 static boolean
00228 rr_node_is_global_clb_ipin(int inode)
00229 {
00230
00231
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 }
00245
00246
00247 void
00248 check_node(int inode,
00249 enum e_route_type route_type)
00250 {
00251
00252
00253
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
00294
00295 switch (rr_type)
00296 {
00297
00298 case SOURCE:
00299 case SINK:
00300 case IPIN:
00301 case OPIN:
00302
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
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
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 {
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
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 }
00570
00571
00572 static void
00573 check_pass_transistors(int from_node)
00574 {
00575
00576
00577
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
00605
00606
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 }
00632 }