VPR-6.0
|
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 }