00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include "util.h"
00004 #include "vpr_types.h"
00005 #include "globals.h"
00006 #include "mst.h"
00007 #include "route_export.h"
00008 #include "check_route.h"
00009 #include "rr_graph.h"
00010 #include "check_rr_graph.h"
00011
00012
00013
00014 static void check_node_and_range(int inode,
00015 enum e_route_type route_type);
00016 static void check_source(int inode,
00017 int inet);
00018 static void check_sink(int inode,
00019 int inet,
00020 boolean * pin_done);
00021 static void check_switch(struct s_trace *tptr,
00022 int num_switch);
00023 static boolean check_adjacent(int from_node,
00024 int to_node);
00025 static int pin_and_chan_adjacent(int pin_node,
00026 int chan_node);
00027 static int chanx_chany_adjacent(int chanx_node,
00028 int chany_node);
00029 static void reset_flags(int inet,
00030 boolean * connected_to_route);
00031 static void recompute_occupancy_from_scratch(t_ivec ** fb_opins_used_locally);
00032 static void check_locally_used_fb_opins(t_ivec ** fb_opins_used_locally,
00033 enum e_route_type route_type);
00034
00035
00036
00037
00038 void
00039 check_route(enum e_route_type route_type,
00040 int num_switch,
00041 t_ivec ** fb_opins_used_locally)
00042 {
00043
00044
00045
00046
00047
00048
00049
00050 int inet, ipin, max_pins, inode, prev_node;
00051 boolean valid, connects;
00052 boolean *connected_to_route;
00053 struct s_trace *tptr;
00054 boolean *pin_done;
00055
00056 printf("\nChecking to ensure routing is legal ...\n");
00057
00058
00059
00060
00061
00062 recompute_occupancy_from_scratch(fb_opins_used_locally);
00063 valid = feasible_routing();
00064 if(valid == FALSE)
00065 {
00066 printf
00067 ("Error in check_route -- routing resources are overused.\n");
00068 exit(1);
00069 }
00070
00071 check_locally_used_fb_opins(fb_opins_used_locally, route_type);
00072
00073 connected_to_route = (boolean *) my_calloc(num_rr_nodes, sizeof(boolean));
00074
00075 max_pins = 0;
00076 for(inet = 0; inet < num_nets; inet++)
00077 max_pins = max(max_pins, (net[inet].num_sinks + 1));
00078
00079 pin_done = (boolean *) my_malloc(max_pins * sizeof(boolean));
00080
00081
00082
00083 for(inet = 0; inet < num_nets; inet++)
00084 {
00085
00086 if(net[inet].is_global)
00087 continue;
00088
00089 for(ipin = 0; ipin < (net[inet].num_sinks + 1); ipin++)
00090 pin_done[ipin] = FALSE;
00091
00092
00093
00094 tptr = trace_head[inet];
00095 if(tptr == NULL)
00096 {
00097 printf("Error in check_route: net %d has no routing.\n",
00098 inet);
00099 exit(1);
00100 }
00101
00102 inode = tptr->index;
00103 check_node_and_range(inode, route_type);
00104 check_switch(tptr, num_switch);
00105 connected_to_route[inode] = TRUE;
00106
00107 check_source(inode, inet);
00108 pin_done[0] = TRUE;
00109
00110 prev_node = inode;
00111 tptr = tptr->next;
00112
00113
00114
00115 while(tptr != NULL)
00116 {
00117 inode = tptr->index;
00118 check_node_and_range(inode, route_type);
00119 check_switch(tptr, num_switch);
00120
00121 if(rr_node[prev_node].type == SINK)
00122 {
00123 if(connected_to_route[inode] == FALSE)
00124 {
00125 printf
00126 ("Error in check_route. Node %d does not link "
00127 "into the existing routing for net %d.\n",
00128 inode, inet);
00129 exit(1);
00130 }
00131 }
00132
00133 else
00134 {
00135 connects = check_adjacent(prev_node, inode);
00136 if(!connects)
00137 {
00138 printf
00139 ("Error in check_route while checking net %d.\n",
00140 inet);
00141 printf
00142 ("Non-adjacent segments in traceback.\n");
00143 exit(1);
00144 }
00145
00146 if(connected_to_route[inode]
00147 && rr_node[inode].type != SINK)
00148 {
00149
00150
00151
00152
00153 printf
00154 ("Error in check_route: net %d routing is not a tree.\n",
00155 inet);
00156 exit(1);
00157 }
00158
00159 connected_to_route[inode] = TRUE;
00160
00161 if(rr_node[inode].type == SINK)
00162 check_sink(inode, inet, pin_done);
00163
00164 }
00165 prev_node = inode;
00166 tptr = tptr->next;
00167 }
00168
00169 if(rr_node[prev_node].type != SINK)
00170 {
00171 printf("Error in check_route. Net %d does not end\n",
00172 inet);
00173 printf("with a SINK.\n");
00174 exit(1);
00175 }
00176
00177 for(ipin = 0; ipin < (net[inet].num_sinks + 1); ipin++)
00178 {
00179 if(pin_done[ipin] == FALSE)
00180 {
00181 printf
00182 ("Error in check_route. Net %d does not \n",
00183 inet);
00184 printf("connect to pin %d.\n", ipin);
00185 exit(1);
00186 }
00187 }
00188
00189 reset_flags(inet, connected_to_route);
00190
00191 }
00192
00193 free(pin_done);
00194 free(connected_to_route);
00195 printf("Completed routing consistency check successfully.\n\n");
00196 }
00197
00198 static void
00199 check_sink(int inode,
00200 int inet,
00201 boolean * pin_done)
00202 {
00203
00204
00205
00206
00207 int i, j, ipin, ifound, ptc_num, bnum, iclass, node_block_pin, iblk;
00208 t_type_ptr type;
00209
00210 assert(rr_node[inode].type == SINK);
00211 i = rr_node[inode].xlow;
00212 j = rr_node[inode].ylow;
00213 type = grid[i][j].type;
00214 ptc_num = rr_node[inode].ptc_num;
00215 ifound = 0;
00216
00217 for(iblk = 0; iblk < type->capacity; iblk++)
00218 {
00219 bnum = grid[i][j].blocks[iblk];
00220 for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)
00221 {
00222 if(net[inet].node_block[ipin] == bnum)
00223 {
00224 node_block_pin = net[inet].node_block_pin[ipin];
00225 iclass = type->pin_class[node_block_pin];
00226 if(iclass == ptc_num)
00227 {
00228
00229
00230
00231 if(pin_done[ipin] == FALSE)
00232 {
00233 ifound++;
00234 pin_done[ipin] = TRUE;
00235 }
00236 }
00237 }
00238 }
00239 }
00240
00241 if(ifound > 1 && type == IO_TYPE)
00242 {
00243 printf("Error in check_sink: found %d terminals of net %d of pad"
00244 "\n %d at location (%d, %d).\n", ifound, inet, ptc_num, i,
00245 j);
00246 exit(1);
00247 }
00248
00249 if(ifound < 1)
00250 {
00251 printf
00252 ("Error in check_sink: node %d does not connect to any terminal "
00253 "\n of net %d.\n", inode, inet);
00254 exit(1);
00255 }
00256 }
00257
00258
00259 static void
00260 check_source(int inode,
00261 int inet)
00262 {
00263
00264
00265
00266 t_rr_type rr_type;
00267 t_type_ptr type;
00268 int i, j, ptc_num, bnum, node_block_pin, iclass;
00269
00270 rr_type = rr_node[inode].type;
00271 if(rr_type != SOURCE)
00272 {
00273 printf
00274 ("Error in check_source: net %d begins with a node of type %d.\n",
00275 inet, rr_type);
00276 exit(1);
00277 }
00278
00279 i = rr_node[inode].xlow;
00280 j = rr_node[inode].ylow;
00281 ptc_num = rr_node[inode].ptc_num;
00282 bnum = net[inet].node_block[0];
00283 type = grid[i][j].type;
00284
00285 if(block[bnum].x != i || block[bnum].y != j)
00286 {
00287 printf
00288 ("Error in check_source: net SOURCE is in wrong location (%d,%d)."
00289 "\n", i, j);
00290 exit(1);
00291 }
00292
00293 node_block_pin = net[inet].node_block_pin[0];
00294 iclass = type->pin_class[node_block_pin];
00295
00296 if(ptc_num != iclass)
00297 {
00298 printf
00299 ("Error in check_source: net SOURCE is of wrong class (%d).\n",
00300 ptc_num);
00301 exit(1);
00302 }
00303 }
00304
00305
00306 static void
00307 check_switch(struct s_trace *tptr,
00308 int num_switch)
00309 {
00310
00311
00312
00313
00314 int inode;
00315 short switch_type;
00316
00317 inode = tptr->index;
00318 switch_type = tptr->iswitch;
00319
00320 if(rr_node[inode].type != SINK)
00321 {
00322 if(switch_type < 0 || switch_type >= num_switch)
00323 {
00324 printf
00325 ("Error in check_switch: rr_node %d left via switch type %d.\n",
00326 inode, switch_type);
00327 printf("Switch type is out of range.\n");
00328 exit(1);
00329 }
00330 }
00331
00332 else
00333 {
00334
00335
00336
00337
00338 if(switch_type != OPEN)
00339 {
00340 printf
00341 ("Error in check_switch: rr_node %d is a SINK, but attempts \n"
00342 "to use a switch of type %d.\n", inode, switch_type);
00343 exit(1);
00344 }
00345 }
00346 }
00347
00348
00349 static void
00350 reset_flags(int inet,
00351 boolean * connected_to_route)
00352 {
00353
00354
00355
00356
00357
00358
00359 struct s_trace *tptr;
00360 int inode;
00361
00362 tptr = trace_head[inet];
00363
00364 while(tptr != NULL)
00365 {
00366 inode = tptr->index;
00367 connected_to_route[inode] = FALSE;
00368 tptr = tptr->next;
00369 }
00370 }
00371
00372
00373 static boolean
00374 check_adjacent(int from_node,
00375 int to_node)
00376 {
00377
00378
00379
00380
00381
00382
00383 int from_xlow, from_ylow, to_xlow, to_ylow, from_ptc, to_ptc, iclass;
00384 int num_adj, to_xhigh, to_yhigh, from_xhigh, from_yhigh, iconn;
00385 boolean reached;
00386 t_rr_type from_type, to_type;
00387 t_type_ptr from_grid_type, to_grid_type;
00388
00389 reached = FALSE;
00390
00391 for(iconn = 0; iconn < rr_node[from_node].num_edges; iconn++)
00392 {
00393 if(rr_node[from_node].edges[iconn] == to_node)
00394 {
00395 reached = TRUE;
00396 break;
00397 }
00398 }
00399
00400 if(!reached)
00401 return (FALSE);
00402
00403
00404
00405
00406 num_adj = 0;
00407
00408 from_type = rr_node[from_node].type;
00409 from_xlow = rr_node[from_node].xlow;
00410 from_ylow = rr_node[from_node].ylow;
00411 from_xhigh = rr_node[from_node].xhigh;
00412 from_yhigh = rr_node[from_node].yhigh;
00413 from_ptc = rr_node[from_node].ptc_num;
00414 to_type = rr_node[to_node].type;
00415 to_xlow = rr_node[to_node].xlow;
00416 to_ylow = rr_node[to_node].ylow;
00417 to_xhigh = rr_node[to_node].xhigh;
00418 to_yhigh = rr_node[to_node].yhigh;
00419 to_ptc = rr_node[to_node].ptc_num;
00420
00421 switch (from_type)
00422 {
00423
00424 case SOURCE:
00425 assert(to_type == OPIN);
00426 if(from_xlow == to_xlow && from_ylow == to_ylow
00427 && from_xhigh == to_xhigh && from_yhigh == to_yhigh)
00428 {
00429
00430 from_grid_type = grid[from_xlow][from_ylow].type;
00431 to_grid_type = grid[to_xlow][to_ylow].type;
00432 assert(from_grid_type == to_grid_type);
00433
00434 iclass = to_grid_type->pin_class[to_ptc];
00435 if(iclass == from_ptc)
00436 num_adj++;
00437 }
00438 break;
00439
00440 case SINK:
00441
00442 break;
00443
00444 case OPIN:
00445 assert(to_type == CHANX || to_type == CHANY);
00446 num_adj += pin_and_chan_adjacent(from_node, to_node);
00447
00448 break;
00449
00450 case IPIN:
00451 assert(to_type == SINK);
00452 if(from_xlow == to_xlow && from_ylow == to_ylow
00453 && from_xhigh == to_xhigh && from_yhigh == to_yhigh)
00454 {
00455
00456 from_grid_type = grid[from_xlow][from_ylow].type;
00457 to_grid_type = grid[to_xlow][to_ylow].type;
00458 assert(from_grid_type == to_grid_type);
00459
00460 iclass = from_grid_type->pin_class[from_ptc];
00461 if(iclass == to_ptc)
00462 num_adj++;
00463 }
00464 break;
00465
00466 case CHANX:
00467 if(to_type == IPIN)
00468 {
00469 num_adj += pin_and_chan_adjacent(to_node, from_node);
00470 }
00471 else if(to_type == CHANX)
00472 {
00473 from_xhigh = rr_node[from_node].xhigh;
00474 to_xhigh = rr_node[to_node].xhigh;
00475 if(from_ylow == to_ylow)
00476 {
00477
00478
00479 if(to_xhigh == from_xlow - 1
00480 || from_xhigh == to_xlow - 1)
00481 {
00482 num_adj++;
00483 }
00484
00485 else
00486 {
00487 int i;
00488
00489 for(i = from_xlow; i <= from_xhigh; i++)
00490 {
00491 if(i >= to_xlow && i <= to_xhigh)
00492 {
00493 num_adj++;
00494 break;
00495 }
00496 }
00497 }
00498
00499 }
00500 }
00501 else if(to_type == CHANY)
00502 {
00503 num_adj += chanx_chany_adjacent(from_node, to_node);
00504 }
00505 else
00506 {
00507 assert(0);
00508 }
00509 break;
00510
00511 case CHANY:
00512 if(to_type == IPIN)
00513 {
00514 num_adj += pin_and_chan_adjacent(to_node, from_node);
00515 }
00516 else if(to_type == CHANY)
00517 {
00518 from_yhigh = rr_node[from_node].yhigh;
00519 to_yhigh = rr_node[to_node].yhigh;
00520 if(from_xlow == to_xlow)
00521 {
00522
00523 if(to_yhigh == from_ylow - 1
00524 || from_yhigh == to_ylow - 1)
00525 {
00526 num_adj++;
00527 }
00528
00529 else
00530 {
00531 int j;
00532
00533 for(j = from_ylow; j <= from_yhigh; j++)
00534 {
00535 if(j >= to_ylow && j <= to_yhigh)
00536 {
00537 num_adj++;
00538 break;
00539 }
00540 }
00541 }
00542
00543 }
00544 }
00545 else if(to_type == CHANX)
00546 {
00547 num_adj += chanx_chany_adjacent(to_node, from_node);
00548 }
00549 else
00550 {
00551 assert(0);
00552 }
00553 break;
00554
00555 default:
00556 break;
00557
00558 }
00559
00560 if(num_adj == 1)
00561 return (TRUE);
00562 else if(num_adj == 0)
00563 return (FALSE);
00564
00565 printf("Error in check_adjacent: num_adj = %d. Expected 0 or 1.\n",
00566 num_adj);
00567 exit(1);
00568 }
00569
00570
00571 static int
00572 chanx_chany_adjacent(int chanx_node,
00573 int chany_node)
00574 {
00575
00576
00577
00578
00579 int chanx_y, chanx_xlow, chanx_xhigh;
00580 int chany_x, chany_ylow, chany_yhigh;
00581
00582 chanx_y = rr_node[chanx_node].ylow;
00583 chanx_xlow = rr_node[chanx_node].xlow;
00584 chanx_xhigh = rr_node[chanx_node].xhigh;
00585
00586 chany_x = rr_node[chany_node].xlow;
00587 chany_ylow = rr_node[chany_node].ylow;
00588 chany_yhigh = rr_node[chany_node].yhigh;
00589
00590 if(chany_ylow > chanx_y + 1 || chany_yhigh < chanx_y)
00591 return (0);
00592
00593 if(chanx_xlow > chany_x + 1 || chanx_xhigh < chany_x)
00594 return (0);
00595
00596 return (1);
00597 }
00598
00599
00600 static int
00601 pin_and_chan_adjacent(int pin_node,
00602 int chan_node)
00603 {
00604
00605
00606
00607
00608
00609 int num_adj, pin_xlow, pin_ylow, pin_xhigh, pin_yhigh, chan_xlow,
00610 chan_ylow, chan_xhigh, chan_yhigh;
00611 int pin_ptc, i;
00612 t_rr_type chan_type;
00613 t_type_ptr pin_grid_type;
00614
00615 num_adj = 0;
00616 pin_xlow = rr_node[pin_node].xlow;
00617 pin_ylow = rr_node[pin_node].ylow;
00618 pin_xhigh = rr_node[pin_node].xhigh;
00619 pin_yhigh = rr_node[pin_node].yhigh;
00620 pin_grid_type = grid[pin_xlow][pin_ylow].type;
00621 pin_ptc = rr_node[pin_node].ptc_num;
00622 chan_type = rr_node[chan_node].type;
00623 chan_xlow = rr_node[chan_node].xlow;
00624 chan_ylow = rr_node[chan_node].ylow;
00625 chan_xhigh = rr_node[chan_node].xhigh;
00626 chan_yhigh = rr_node[chan_node].yhigh;
00627
00628 if(chan_type == CHANX)
00629 {
00630 if(chan_ylow == pin_yhigh)
00631 {
00632 if(pin_grid_type->
00633 pinloc[pin_grid_type->height - 1][TOP][pin_ptc] == 1
00634 && pin_xlow <= chan_xhigh && pin_xhigh >= chan_xlow)
00635 num_adj++;
00636 }
00637 else if(chan_ylow == pin_ylow - 1)
00638 {
00639 if(pin_grid_type->pinloc[0][BOTTOM][pin_ptc] == 1
00640 && pin_xlow <= chan_xhigh && pin_xhigh >= chan_xlow)
00641 num_adj++;
00642 }
00643 }
00644 else if(chan_type == CHANY)
00645 {
00646 for(i = 0; i < pin_grid_type->height; i++)
00647 {
00648 if(chan_xlow == pin_xhigh)
00649 {
00650 if(pin_grid_type->pinloc[i][RIGHT][pin_ptc] == 1
00651 && pin_ylow <= chan_yhigh
00652 && pin_yhigh >= chan_ylow)
00653 num_adj++;
00654 }
00655 else if(chan_xlow == pin_xlow - 1)
00656 {
00657 if(pin_grid_type->pinloc[i][LEFT][pin_ptc] == 1
00658 && pin_ylow <= chan_yhigh
00659 && pin_yhigh >= chan_ylow)
00660 num_adj++;
00661 }
00662 }
00663 }
00664 return (num_adj);
00665 }
00666
00667
00668 static void
00669 recompute_occupancy_from_scratch(t_ivec ** fb_opins_used_locally)
00670 {
00671
00672
00673
00674
00675
00676 int inode, inet, iblk, iclass, ipin, num_local_opins;
00677 struct s_trace *tptr;
00678
00679
00680
00681 for(inode = 0; inode < num_rr_nodes; inode++)
00682 rr_node[inode].occ = 0;
00683
00684
00685
00686 for(inet = 0; inet < num_nets; inet++)
00687 {
00688
00689 if(net[inet].is_global)
00690 continue;
00691
00692 tptr = trace_head[inet];
00693 if(tptr == NULL)
00694 continue;
00695
00696 for(;;)
00697 {
00698 inode = tptr->index;
00699 rr_node[inode].occ++;
00700
00701 if(rr_node[inode].type == SINK)
00702 {
00703 tptr = tptr->next;
00704 if(tptr == NULL)
00705 break;
00706 }
00707
00708 tptr = tptr->next;
00709 }
00710 }
00711
00712
00713
00714
00715
00716 for(iblk = 0; iblk < num_blocks; iblk++)
00717 {
00718 for(iclass = 0; iclass < block[iblk].type->num_class; iclass++)
00719 {
00720 num_local_opins =
00721 fb_opins_used_locally[iblk][iclass].nelem;
00722
00723 for(ipin = 0; ipin < num_local_opins; ipin++)
00724 {
00725 inode =
00726 fb_opins_used_locally[iblk][iclass].
00727 list[ipin];
00728 rr_node[inode].occ++;
00729 }
00730 }
00731 }
00732 }
00733
00734
00735 static void
00736 check_locally_used_fb_opins(t_ivec ** fb_opins_used_locally,
00737 enum e_route_type route_type)
00738 {
00739
00740
00741
00742
00743 int iclass, iblk, num_local_opins, inode, ipin;
00744 t_rr_type rr_type;
00745
00746 for(iblk = 0; iblk < num_blocks; iblk++)
00747 {
00748 for(iclass = 0; iclass < block[iblk].type->num_class; iclass++)
00749 {
00750 num_local_opins =
00751 fb_opins_used_locally[iblk][iclass].nelem;
00752
00753
00754 for(ipin = 0; ipin < num_local_opins; ipin++)
00755 {
00756 inode =
00757 fb_opins_used_locally[iblk][iclass].
00758 list[ipin];
00759 check_node_and_range(inode, route_type);
00760
00761
00762
00763 rr_type = rr_node[inode].type;
00764 if(rr_type != OPIN)
00765 {
00766 printf
00767 ("Error in check_locally_used_opins: Block #%d (%s)\n"
00768 "\tclass %d locally used OPIN is of the wrong rr_type --\n"
00769 "\tit is rr_node #%d of type %d.\n",
00770 iblk, block[iblk].name, iclass,
00771 inode, rr_type);
00772 exit(1);
00773 }
00774
00775 ipin = rr_node[inode].ptc_num;
00776 if(block[iblk].type->pin_class[ipin] != iclass)
00777 {
00778 printf
00779 ("Error in check_locally_used_opins: Block #%d (%s):\n"
00780 "\tExpected class %d locally used OPIN, got class %d."
00781 "\trr_node #: %d.\n", iblk,
00782 block[iblk].name, iclass,
00783 block[iblk].type->pin_class[ipin],
00784 inode);
00785 exit(1);
00786 }
00787 }
00788 }
00789 }
00790 }
00791
00792
00793 static void
00794 check_node_and_range(int inode,
00795 enum e_route_type route_type)
00796 {
00797
00798
00799
00800
00801 if(inode < 0 || inode >= num_rr_nodes)
00802 {
00803 printf
00804 ("Error in check_node_and_range: rr_node #%d is out of legal "
00805 "\trange (0 to %d).\n", inode, num_rr_nodes - 1);
00806 exit(1);
00807 }
00808 check_node(inode, route_type);
00809 }