#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "check_rr_graph.h"
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 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.
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 }
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 }
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 }
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 }
boolean rr_graph_error [static] |
Definition at line 24 of file check_rr_graph.c.
boolean rr_graph_warn [static] |
Definition at line 25 of file check_rr_graph.c.