00001 #include <stdio.h>
00002 #include <assert.h>
00003 #include "util.h"
00004 #include "vpr_types.h"
00005 #include "globals.h"
00006 #include "rr_graph_util.h"
00007 #include "rr_graph2.h"
00008 #include "rr_graph_sbox.h"
00009
00010 #define ALLOW_SWITCH_OFF
00011
00012
00013
00014
00015 #define ENABLE_REVERSE 0
00016
00017
00018 #define SAME_TRACK -5
00019 #define UN_SET -1
00020
00021
00022
00023
00024
00025
00026
00027 boolean *rr_edge_done;
00028
00029
00030
00031
00032 t_linked_edge *free_edge_list_head = NULL;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 static void get_switch_type(boolean is_from_sbox,
00053 boolean is_to_sbox,
00054 short from_node_switch,
00055 short to_node_switch,
00056 short switch_types[2]);
00057
00058 static void load_chan_rr_indices(IN int nodes_per_chan,
00059 IN int chan_len,
00060 IN int num_chans,
00061 IN t_rr_type type,
00062 IN t_seg_details * seg_details,
00063 INOUT int *index,
00064 INOUT t_ivec *** indices);
00065
00066 static int get_bidir_track_to_chan_seg(IN struct s_ivec conn_tracks,
00067 IN t_ivec *** rr_node_indices,
00068 IN int to_chan,
00069 IN int to_seg,
00070 IN int to_sb,
00071 IN t_rr_type to_type,
00072 IN t_seg_details * seg_details,
00073 IN boolean from_is_sbox,
00074 IN int from_switch,
00075 INOUT boolean * rr_edge_done,
00076 IN enum e_directionality
00077 directionality,
00078 INOUT struct s_linked_edge
00079 **edge_list);
00080
00081 static int get_unidir_track_to_chan_seg(IN boolean is_end_sb,
00082 IN int from_track,
00083 IN int to_chan,
00084 IN int to_seg,
00085 IN int to_sb,
00086 IN t_rr_type to_type,
00087 IN int nodes_per_chan,
00088 IN int nx,
00089 IN int ny,
00090 IN enum e_side from_side,
00091 IN enum e_side to_side,
00092 IN int Fs_per_side,
00093 IN int *opin_mux_size,
00094 IN short *****sblock_pattern,
00095 IN t_ivec *** rr_node_indices,
00096 IN t_seg_details * seg_details,
00097 INOUT boolean * rr_edge_done,
00098 OUT boolean * Fs_clipped,
00099 INOUT struct s_linked_edge
00100 **edge_list);
00101
00102 static int vpr_to_phy_track(IN int itrack,
00103 IN int chan_num,
00104 IN int seg_num,
00105 IN t_seg_details * seg_details,
00106 IN enum e_directionality directionality);
00107
00108 static int *get_seg_track_counts(IN int num_sets,
00109 IN int num_seg_types,
00110 IN t_segment_inf * segment_inf,
00111 IN boolean use_full_seg_groups);
00112
00113 static int *label_wire_muxes(IN int chan_num,
00114 IN int seg_num,
00115 IN t_seg_details * seg_details,
00116 IN int max_len,
00117 IN enum e_direction dir,
00118 IN int nodes_per_chan,
00119 OUT int *num_wire_muxes);
00120
00121 static int *label_wire_muxes_for_balance(IN int chan_num,
00122 IN int seg_num,
00123 IN t_seg_details * seg_details,
00124 IN int max_len,
00125 IN enum e_direction direction,
00126 IN int nodes_per_chan,
00127 IN int *num_wire_muxes,
00128 IN t_rr_type chan_type,
00129 IN int *opin_mux_size,
00130 IN t_ivec *** rr_node_indices);
00131
00132 static int *label_incoming_wires(IN int chan_num,
00133 IN int seg_num,
00134 IN int sb_seg,
00135 IN t_seg_details * seg_details,
00136 IN int max_len,
00137 IN enum e_direction dir,
00138 IN int nodes_per_chan,
00139 OUT int *num_incoming_wires,
00140 OUT int *num_ending_wires);
00141
00142 static int find_label_of_track(int *wire_mux_on_track,
00143 int num_wire_muxes,
00144 int from_track);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 static int *
00163 get_seg_track_counts(IN int num_sets,
00164 IN int num_seg_types,
00165 IN t_segment_inf * segment_inf,
00166 IN boolean use_full_seg_groups)
00167 {
00168 int *result;
00169 double *demand;
00170 int i, imax, freq_sum, assigned, size;
00171 double scale, max, reduce;
00172
00173 result = (int *)my_malloc(sizeof(int) * num_seg_types);
00174 demand = (double *)my_malloc(sizeof(double) * num_seg_types);
00175
00176
00177
00178 scale = 1;
00179 freq_sum = 0;
00180 for(i = 0; i < num_seg_types; ++i)
00181 {
00182 scale *= segment_inf[i].length;
00183 freq_sum += segment_inf[i].frequency;
00184 }
00185 reduce = scale * freq_sum;
00186
00187
00188 for(i = 0; i < num_seg_types; ++i)
00189 {
00190 result[i] = 0;
00191 demand[i] = scale * num_sets * segment_inf[i].frequency;
00192 if(use_full_seg_groups)
00193 {
00194 demand[i] /= segment_inf[i].length;
00195 }
00196 }
00197
00198
00199 assigned = 0;
00200 size = 0;
00201 imax = 0;
00202 while(assigned < num_sets)
00203 {
00204
00205 max = 0;
00206 for(i = 0; i < num_seg_types; ++i)
00207 {
00208 if(demand[i] > max)
00209 {
00210 imax = i;
00211 max = demand[i];
00212 }
00213 }
00214
00215
00216 size = (use_full_seg_groups ? segment_inf[imax].length : 1);
00217 demand[imax] -= reduce;
00218 result[imax] += size;
00219 assigned += size;
00220 }
00221
00222
00223 if((assigned - num_sets) > (size / 2))
00224 {
00225 result[imax] -= size;
00226 }
00227
00228
00229 if(demand)
00230 {
00231 free(demand);
00232 demand = NULL;
00233 }
00234
00235
00236 return result;
00237 }
00238
00239
00240 t_seg_details *
00241 alloc_and_load_seg_details(INOUT int *nodes_per_chan,
00242 IN int max_len,
00243 IN int num_seg_types,
00244 IN t_segment_inf * segment_inf,
00245 IN boolean use_full_seg_groups,
00246 IN boolean is_global_graph,
00247 IN enum e_directionality directionality)
00248 {
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 int i, cur_track, ntracks, itrack, length, j, index;
00260 int wire_switch, opin_switch, fac, num_sets, tmp;
00261 int group_start, first_track;
00262 int *sets_per_seg_type = NULL;
00263 t_seg_details *seg_details = NULL;
00264 boolean longline;
00265
00266
00267 if(directionality == BI_DIRECTIONAL)
00268 {
00269 fac = 1;
00270 }
00271 else
00272 {
00273 assert(directionality == UNI_DIRECTIONAL);
00274 fac = 2;
00275 }
00276 assert(*nodes_per_chan % fac == 0);
00277
00278
00279 sets_per_seg_type = get_seg_track_counts((*nodes_per_chan / fac),
00280 num_seg_types,
00281 segment_inf,
00282 use_full_seg_groups);
00283
00284
00285 tmp = 0;
00286 for(i = 0; i < num_seg_types; ++i)
00287 {
00288 tmp += sets_per_seg_type[i] * fac;
00289 }
00290 assert(use_full_seg_groups || (tmp == *nodes_per_chan));
00291 *nodes_per_chan = tmp;
00292
00293 seg_details = (t_seg_details *)
00294 my_malloc(*nodes_per_chan * sizeof(t_seg_details));
00295
00296
00297 cur_track = 0;
00298 for(i = 0; i < num_seg_types; ++i)
00299 {
00300 first_track = cur_track;
00301
00302 num_sets = sets_per_seg_type[i];
00303 ntracks = fac * num_sets;
00304 if(ntracks < 1)
00305 {
00306 continue;
00307 }
00308
00309 longline = segment_inf[i].longline;
00310 length = segment_inf[i].length;
00311 if(longline)
00312 {
00313 length = max_len;
00314 }
00315
00316 wire_switch = segment_inf[i].wire_switch;
00317 opin_switch = segment_inf[i].opin_switch;
00318 assert((wire_switch == opin_switch)
00319 || (directionality != UNI_DIRECTIONAL));
00320
00321
00322 group_start = 0;
00323 for(itrack = 0; itrack < ntracks; itrack++)
00324 {
00325
00326
00327 if((itrack / fac) % length == 0 && (itrack % fac) == 0)
00328 {
00329 group_start = cur_track;
00330 }
00331
00332 seg_details[cur_track].length = length;
00333 seg_details[cur_track].longline = longline;
00334
00335
00336
00337
00338
00339
00340
00341 seg_details[cur_track].start =
00342 (cur_track / fac) % length + 1;
00343
00344
00345
00346 seg_details[cur_track].group_start = group_start;
00347 seg_details[cur_track].group_size =
00348 min(ntracks + first_track - group_start,
00349 length * fac);
00350 assert(0 == seg_details[cur_track].group_size % fac);
00351 if(0 == seg_details[cur_track].group_size)
00352 {
00353 seg_details[cur_track].group_size = length * fac;
00354 }
00355
00356
00357
00358 seg_details[cur_track].cb =
00359 (boolean *) my_malloc(length * sizeof(boolean));
00360 seg_details[cur_track].sb =
00361 (boolean *) my_malloc((length + 1) * sizeof(boolean));
00362 for(j = 0; j < length; ++j)
00363 {
00364 if(is_global_graph)
00365 {
00366 seg_details[cur_track].cb[j] = TRUE;
00367 }
00368 else
00369 {
00370 index = j;
00371
00372
00373 if(longline)
00374 {
00375 index = (index + itrack) % length;
00376 }
00377
00378
00379 if(itrack % fac == 1)
00380 {
00381 index = (length - 1) - j;
00382 }
00383
00384
00385 index = j % segment_inf[i].cb_len;
00386 seg_details[cur_track].cb[j] =
00387 segment_inf[i].cb[index];
00388 }
00389 }
00390 for(j = 0; j < (length + 1); ++j)
00391 {
00392 if(is_global_graph)
00393 {
00394 seg_details[cur_track].sb[j] = TRUE;
00395 }
00396 else
00397 {
00398 index = j;
00399
00400
00401 if(longline)
00402 {
00403 index =
00404 (index + itrack) % (length +
00405 1);
00406 }
00407
00408
00409 if(itrack % fac == 1)
00410 {
00411 index = ((length + 1) - 1) - j;
00412 }
00413
00414
00415 index = j % segment_inf[i].sb_len;
00416 seg_details[cur_track].sb[j] =
00417 segment_inf[i].sb[index];
00418 }
00419 }
00420
00421 seg_details[cur_track].Rmetal = segment_inf[i].Rmetal;
00422 seg_details[cur_track].Cmetal = segment_inf[i].Cmetal;
00423
00424 seg_details[cur_track].wire_switch = wire_switch;
00425 seg_details[cur_track].opin_switch = opin_switch;
00426
00427 if(BI_DIRECTIONAL == directionality)
00428 {
00429 seg_details[cur_track].direction = BI_DIRECTION;
00430 }
00431 else
00432 {
00433 assert(UNI_DIRECTIONAL == directionality);
00434 seg_details[cur_track].direction =
00435 (itrack % 2) ? DEC_DIRECTION : INC_DIRECTION;
00436 }
00437
00438 switch (segment_inf[i].directionality)
00439 {
00440 case UNI_DIRECTIONAL:
00441 seg_details[cur_track].drivers = SINGLE;
00442 break;
00443 case BI_DIRECTIONAL:
00444 seg_details[cur_track].drivers = MULTI_BUFFERED;
00445 break;
00446 }
00447
00448 seg_details[cur_track].index = i;
00449
00450 ++cur_track;
00451 }
00452 }
00453
00454
00455 free(sets_per_seg_type);
00456
00457 return seg_details;
00458 }
00459
00460 void
00461 free_seg_details(t_seg_details * seg_details,
00462 int nodes_per_chan)
00463 {
00464
00465
00466
00467 int i;
00468
00469 for(i = 0; i < nodes_per_chan; i++)
00470 {
00471 free(seg_details[i].cb);
00472 free(seg_details[i].sb);
00473 }
00474 free(seg_details);
00475 }
00476
00477
00478
00479
00480 void
00481 dump_seg_details(t_seg_details * seg_details,
00482 int nodes_per_chan,
00483 char *fname)
00484 {
00485
00486 FILE *fp;
00487 int i, j;
00488 const char *drivers_names[] = { "multi_buffered",
00489 "multi_muxed",
00490 "multi_merged",
00491 "single"
00492 };
00493 const char *direction_names[] = { "inc_direction",
00494 "dec_direction",
00495 "bi_direction"
00496 };
00497
00498 fp = my_fopen(fname, "w");
00499
00500 for(i = 0; i < nodes_per_chan; i++)
00501 {
00502 fprintf(fp, "Track: %d.\n", i);
00503 fprintf(fp, "Length: %d, Start: %d, Long line: %d "
00504 "wire_switch: %d opin_switch: %d.\n",
00505 seg_details[i].length,
00506 seg_details[i].start,
00507 seg_details[i].longline,
00508 seg_details[i].wire_switch, seg_details[i].opin_switch);
00509
00510 fprintf(fp, "Rmetal: %g Cmetal: %g\n",
00511 seg_details[i].Rmetal, seg_details[i].Cmetal);
00512
00513 fprintf(fp, "Direction: %s Drivers: %s\n",
00514 direction_names[seg_details[i].direction],
00515 drivers_names[seg_details[i].drivers]);
00516
00517 fprintf(fp, "Start Track: %d End Track: %d\n",
00518 seg_details[i].start_track, seg_details[i].end_track);
00519
00520 fprintf(fp, "cb list: ");
00521 for(j = 0; j < seg_details[i].length; j++)
00522 fprintf(fp, "%d ", seg_details[i].cb[j]);
00523 fprintf(fp, "\n");
00524
00525 fprintf(fp, "sb list: ");
00526 for(j = 0; j <= seg_details[i].length; j++)
00527 fprintf(fp, "%d ", seg_details[i].sb[j]);
00528 fprintf(fp, "\n");
00529
00530 fprintf(fp, "\n");
00531 }
00532
00533 fclose(fp);
00534 }
00535
00536
00537
00538
00539
00540 int
00541 get_seg_start(IN t_seg_details * seg_details,
00542 IN int itrack,
00543 IN int chan_num,
00544 IN int seg_num)
00545 {
00546
00547 int seg_start, length, start;
00548
00549 seg_start = 1;
00550 if(FALSE == seg_details[itrack].longline)
00551 {
00552
00553 length = seg_details[itrack].length;
00554 start = seg_details[itrack].start;
00555
00556
00557
00558
00559 assert(start > 0);
00560 assert(start <= length);
00561
00562
00563
00564
00565
00566 seg_start =
00567 seg_num - (seg_num + length + chan_num - start) % length;
00568 if(seg_start < 1)
00569 {
00570 seg_start = 1;
00571 }
00572 }
00573
00574 return seg_start;
00575 }
00576
00577 int
00578 get_seg_end(IN t_seg_details * seg_details,
00579 IN int itrack,
00580 IN int istart,
00581 IN int chan_num,
00582 IN int seg_max)
00583 {
00584 int len, ofs, end, first_full;
00585
00586 len = seg_details[itrack].length;
00587 ofs = seg_details[itrack].start;
00588
00589
00590 end = istart + len - 1;
00591
00592
00593 if(1 == istart)
00594 {
00595
00596
00597 first_full = (len - (chan_num % len) + ofs - 1) % len + 1;
00598 if(first_full > 1)
00599 {
00600
00601 end = first_full - 1;
00602 }
00603 }
00604
00605
00606 if(end > seg_max)
00607 {
00608 end = seg_max;
00609 }
00610
00611 return end;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620 int
00621 get_bidir_opin_connections(IN int i,
00622 IN int j,
00623 IN int ipin,
00624 IN struct s_linked_edge **edge_list,
00625 IN int *****opin_to_track_map,
00626 IN int Fc,
00627 IN boolean * rr_edge_done,
00628 IN t_ivec *** rr_node_indices,
00629 IN t_seg_details * seg_details)
00630 {
00631
00632 int iside, num_conn, ofs, tr_i, tr_j, chan, seg;
00633 int to_track, to_switch, to_node, iconn;
00634 int is_connected_track;
00635 t_type_ptr type;
00636 t_rr_type to_type;
00637
00638 type = grid[i][j].type;
00639 ofs = grid[i][j].offset;
00640
00641 num_conn = 0;
00642
00643
00644 for(iside = 0; iside < 4; iside++)
00645 {
00646
00647
00648 tr_i = ((iside == LEFT) ? (i - 1) : i);
00649 tr_j = ((iside == BOTTOM) ? (j - 1) : j);
00650
00651 to_type = ((iside == LEFT) || (iside == RIGHT)) ? CHANY : CHANX;
00652
00653 chan = ((to_type == CHANX) ? tr_j : tr_i);
00654 seg = ((to_type == CHANX) ? tr_i : tr_j);
00655
00656
00657 if((tr_i < 0) || (tr_i > nx))
00658 {
00659 continue;
00660 }
00661 if((tr_j < 0) || (tr_j > ny))
00662 {
00663 continue;
00664 }
00665 if((CHANX == to_type) && (tr_i < 1))
00666 {
00667 continue;
00668 }
00669 if((CHANY == to_type) && (tr_j < 1))
00670 {
00671 continue;
00672 }
00673
00674 is_connected_track = FALSE;
00675
00676
00677 for(iconn = 0; iconn < Fc; ++iconn)
00678 {
00679 to_track =
00680 opin_to_track_map[type->
00681 index][ipin][ofs][iside][iconn];
00682
00683
00684 if(OPEN == to_track || is_connected_track)
00685 {
00686 is_connected_track = TRUE;
00687 assert(OPEN ==
00688 opin_to_track_map[type->
00689 index][ipin][ofs][iside]
00690 [0]);
00691 continue;
00692 }
00693
00694
00695 if(is_cbox
00696 (chan, seg, to_track, seg_details, BI_DIRECTIONAL))
00697 {
00698 to_switch = seg_details[to_track].wire_switch;
00699 to_node =
00700 get_rr_node_index(tr_i, tr_j, to_type,
00701 to_track, rr_node_indices);
00702
00703 *edge_list =
00704 insert_in_edge_list(*edge_list, to_node,
00705 to_switch);
00706 rr_edge_done[to_node] = TRUE;
00707 ++num_conn;
00708 }
00709 }
00710 }
00711
00712 return num_conn;
00713 }
00714
00715
00716
00717 int
00718 get_unidir_opin_connections(IN int chan,
00719 IN int seg,
00720 IN int Fc,
00721 IN t_rr_type chan_type,
00722 IN t_seg_details * seg_details,
00723 INOUT t_linked_edge ** edge_list_ptr,
00724 INOUT int **Fc_ofs,
00725 INOUT boolean * rr_edge_done,
00726 IN int max_len,
00727 IN int nodes_per_chan,
00728 IN t_ivec *** rr_node_indices,
00729 OUT boolean * Fc_clipped)
00730 {
00731
00732
00733
00734
00735 int *inc_muxes = NULL;
00736 int *dec_muxes = NULL;
00737 int num_inc_muxes, num_dec_muxes, iconn;
00738 int inc_inode, dec_inode;
00739 int inc_mux, dec_mux;
00740 int inc_track, dec_track;
00741 int x, y;
00742 int num_edges;
00743
00744 *Fc_clipped = FALSE;
00745
00746
00747 assert(Fc % 2 == 0);
00748
00749
00750 x = ((CHANX == chan_type) ? seg : chan);
00751 y = ((CHANX == chan_type) ? chan : seg);
00752
00753
00754 inc_muxes = label_wire_muxes(chan, seg, seg_details, max_len,
00755 INC_DIRECTION, nodes_per_chan,
00756 &num_inc_muxes);
00757 dec_muxes =
00758 label_wire_muxes(chan, seg, seg_details, max_len, DEC_DIRECTION,
00759 nodes_per_chan, &num_dec_muxes);
00760
00761
00762 if(((Fc / 2) > num_inc_muxes) || ((Fc / 2) > num_dec_muxes))
00763 {
00764 *Fc_clipped = TRUE;
00765 Fc = 2 * min(num_inc_muxes, num_dec_muxes);
00766 }
00767
00768
00769 num_edges = 0;
00770 for(iconn = 0; iconn < (Fc / 2); ++iconn)
00771 {
00772
00773 inc_mux = Fc_ofs[chan][seg] % num_inc_muxes;
00774 dec_mux = Fc_ofs[chan][seg] % num_dec_muxes;
00775 ++Fc_ofs[chan][seg];
00776
00777
00778 inc_track = inc_muxes[inc_mux];
00779 dec_track = dec_muxes[dec_mux];
00780
00781
00782 inc_inode =
00783 get_rr_node_index(x, y, chan_type, inc_track,
00784 rr_node_indices);
00785 dec_inode =
00786 get_rr_node_index(x, y, chan_type, dec_track,
00787 rr_node_indices);
00788
00789
00790 if(FALSE == rr_edge_done[inc_inode])
00791 {
00792 rr_edge_done[inc_inode] = TRUE;
00793 *edge_list_ptr = insert_in_edge_list(*edge_list_ptr,
00794 inc_inode,
00795 seg_details
00796 [inc_track].
00797 opin_switch);
00798 ++num_edges;
00799 }
00800 if(FALSE == rr_edge_done[dec_inode])
00801 {
00802 rr_edge_done[dec_inode] = TRUE;
00803 *edge_list_ptr = insert_in_edge_list(*edge_list_ptr,
00804 dec_inode,
00805 seg_details
00806 [dec_track].
00807 opin_switch);
00808 ++num_edges;
00809 }
00810 }
00811
00812 if(inc_muxes)
00813 {
00814 free(inc_muxes);
00815 inc_muxes = NULL;
00816 }
00817 if(dec_muxes)
00818 {
00819 free(dec_muxes);
00820 dec_muxes = NULL;
00821 }
00822
00823 return num_edges;
00824 }
00825
00826 boolean
00827 is_cbox(IN int chan,
00828 IN int seg,
00829 IN int track,
00830 IN t_seg_details * seg_details,
00831 IN enum e_directionality directionality)
00832 {
00833
00834 int start, length, ofs, fac, start_seg;
00835
00836 fac = 1;
00837 if(UNI_DIRECTIONAL == directionality)
00838 {
00839 fac = 2;
00840 }
00841
00842 start = seg_details[track].start;
00843 length = seg_details[track].length;
00844
00845
00846 start_seg = get_seg_start(seg_details, track, chan, seg);
00847
00848 ofs = seg - start_seg;
00849
00850 assert(ofs >= 0);
00851 assert(ofs < length);
00852
00853
00854 if(DEC_DIRECTION == seg_details[track].direction)
00855 {
00856 ofs = (length - 1) - ofs;
00857 }
00858
00859 return seg_details[track].cb[ofs];
00860 }
00861
00862
00863 static void
00864 load_chan_rr_indices(IN int nodes_per_chan,
00865 IN int chan_len,
00866 IN int num_chans,
00867 IN t_rr_type type,
00868 IN t_seg_details * seg_details,
00869 INOUT int *index,
00870 INOUT t_ivec *** indices)
00871 {
00872 int chan, seg, track, start, inode;
00873
00874 indices[type] = (t_ivec **) my_malloc(sizeof(t_ivec *) * num_chans);
00875 for(chan = 0; chan < num_chans; ++chan)
00876 {
00877 indices[type][chan] =
00878 (t_ivec *) my_malloc(sizeof(t_ivec) * chan_len);
00879
00880 indices[type][chan][0].nelem = 0;
00881 indices[type][chan][0].list = NULL;
00882
00883 for(seg = 1; seg < chan_len; ++seg)
00884 {
00885
00886 indices[type][chan][seg].nelem = nodes_per_chan;
00887 indices[type][chan][seg].list =
00888 (int *)my_malloc(sizeof(int) * nodes_per_chan);
00889 for(track = 0; track < nodes_per_chan; ++track)
00890 {
00891 indices[type][chan][seg].list[track] = OPEN;
00892 }
00893 }
00894 }
00895
00896 for(chan = 0; chan < num_chans; ++chan)
00897 {
00898 for(seg = 1; seg < chan_len; ++seg)
00899 {
00900
00901 for(track = 0; track < indices[type][chan][seg].nelem;
00902 ++track)
00903 {
00904 start =
00905 get_seg_start(seg_details, track, chan, seg);
00906
00907
00908
00909 inode = indices[type][chan][start].list[track];
00910 if(OPEN == inode)
00911 {
00912 inode = *index;
00913 ++(*index);
00914
00915 indices[type][chan][start].list[track] =
00916 inode;
00917 }
00918
00919
00920 indices[type][chan][seg].list[track] = inode;
00921 }
00922 }
00923 }
00924 }
00925
00926
00927 struct s_ivec ***
00928 alloc_and_load_rr_node_indices(IN int nodes_per_chan,
00929 IN int nx,
00930 IN int ny,
00931 INOUT int *index,
00932 IN t_seg_details * seg_details)
00933 {
00934
00935
00936
00937
00938
00939 int i, j, k, ofs;
00940 t_ivec ***indices;
00941 t_ivec tmp;
00942 t_type_ptr type;
00943
00944
00945 indices = (t_ivec ***) my_malloc(sizeof(t_ivec **) * NUM_RR_TYPES);
00946 indices[IPIN] = (t_ivec **) my_malloc(sizeof(t_ivec *) * (nx + 2));
00947 indices[SINK] = (t_ivec **) my_malloc(sizeof(t_ivec *) * (nx + 2));
00948 for(i = 0; i <= (nx + 1); ++i)
00949 {
00950 indices[IPIN][i] =
00951 (t_ivec *) my_malloc(sizeof(t_ivec) * (ny + 2));
00952 indices[SINK][i] =
00953 (t_ivec *) my_malloc(sizeof(t_ivec) * (ny + 2));
00954 for(j = 0; j <= (ny + 1); ++j)
00955 {
00956 indices[IPIN][i][j].nelem = 0;
00957 indices[IPIN][i][j].list = NULL;
00958
00959 indices[SINK][i][j].nelem = 0;
00960 indices[SINK][i][j].list = NULL;
00961 }
00962 }
00963
00964
00965
00966 for(i = 0; i <= (nx + 1); i++)
00967 {
00968 for(j = 0; j <= (ny + 1); j++)
00969 {
00970 ofs = grid[i][j].offset;
00971 if(0 == ofs)
00972 {
00973 type = grid[i][j].type;
00974
00975
00976
00977 tmp.nelem = type->num_class;
00978 tmp.list = NULL;
00979 if(tmp.nelem > 0)
00980 {
00981 tmp.list =
00982 (int *)my_malloc(sizeof(int) *
00983 tmp.nelem);
00984 for(k = 0; k < tmp.nelem; ++k)
00985 {
00986 tmp.list[k] = *index;
00987 ++(*index);
00988 }
00989 }
00990 indices[SINK][i][j] = tmp;
00991
00992
00993
00994 tmp.nelem = type->num_pins;
00995 tmp.list = NULL;
00996 if(tmp.nelem > 0)
00997 {
00998 tmp.list =
00999 (int *)my_malloc(sizeof(int) *
01000 tmp.nelem);
01001 for(k = 0; k < tmp.nelem; ++k)
01002 {
01003 tmp.list[k] = *index;
01004 ++(*index);
01005 }
01006 }
01007 indices[IPIN][i][j] = tmp;
01008 }
01009 }
01010 }
01011
01012
01013 for(i = 0; i <= (nx + 1); i++)
01014 {
01015 for(j = 0; j <= (ny + 1); j++)
01016 {
01017 ofs = grid[i][j].offset;
01018 if(ofs > 0)
01019 {
01020
01021 indices[SINK][i][j] = indices[SINK][i][j - ofs];
01022 indices[IPIN][i][j] = indices[IPIN][i][j - ofs];
01023 }
01024 }
01025 }
01026
01027
01028
01029 indices[SOURCE] = indices[SINK];
01030 indices[OPIN] = indices[IPIN];
01031
01032
01033 load_chan_rr_indices(nodes_per_chan, nx + 1, ny + 1, CHANX,
01034 seg_details, index, indices);
01035 load_chan_rr_indices(nodes_per_chan, ny + 1, nx + 1, CHANY,
01036 seg_details, index, indices);
01037
01038 return indices;
01039 }
01040
01041
01042 void
01043 free_rr_node_indices(IN t_ivec *** rr_node_indices)
01044 {
01045 int i, j, ofs;
01046
01047
01048 for(i = 0; i <= (nx + 1); ++i)
01049 {
01050 for(j = 0; j <= (ny + 1); ++j)
01051 {
01052 ofs = grid[i][j].offset;
01053 if(ofs > 0)
01054 {
01055
01056 rr_node_indices[SINK][i][j].list = NULL;
01057 rr_node_indices[IPIN][i][j].list = NULL;
01058 continue;
01059 }
01060 if(rr_node_indices[SINK][i][j].list != NULL) {
01061 free(rr_node_indices[SINK][i][j].list);
01062 }
01063 if(rr_node_indices[IPIN][i][j].list != NULL) {
01064 free(rr_node_indices[IPIN][i][j].list);
01065 }
01066 }
01067 free(rr_node_indices[SINK][i]);
01068 free(rr_node_indices[IPIN][i]);
01069 }
01070 free(rr_node_indices[SINK]);
01071 free(rr_node_indices[IPIN]);
01072
01073 for(i = 0; i < (nx + 1); ++i)
01074 {
01075 for(j = 0; j < (ny + 1); ++j)
01076 {
01077 if(rr_node_indices[CHANY][i][j].list != NULL) {
01078 free(rr_node_indices[CHANY][i][j].list);
01079 }
01080 }
01081 free(rr_node_indices[CHANY][i]);
01082 }
01083 free(rr_node_indices[CHANY]);
01084
01085 for(i = 0; i < (ny + 1); ++i)
01086 {
01087 for(j = 0; j < (nx + 1); ++j)
01088 {
01089 if(rr_node_indices[CHANX][i][j].list != NULL) {
01090 free(rr_node_indices[CHANX][i][j].list);
01091 }
01092 }
01093 free(rr_node_indices[CHANX][i]);
01094 }
01095 free(rr_node_indices[CHANX]);
01096
01097 free(rr_node_indices);
01098 }
01099
01100
01101 int
01102 get_rr_node_index(int x,
01103 int y,
01104 t_rr_type rr_type,
01105 int ptc,
01106 t_ivec *** rr_node_indices)
01107 {
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 int iclass, tmp;
01128 t_type_ptr type;
01129 t_ivec lookup;
01130
01131 assert(ptc >= 0);
01132 assert(x >= 0 && x <= (nx + 1));
01133 assert(y >= 0 && y <= (ny + 1));
01134
01135 type = grid[x][y].type;
01136
01137
01138 if(CHANX == rr_type)
01139 {
01140 tmp = x;
01141 x = y;
01142 y = tmp;
01143 }
01144
01145
01146 lookup = rr_node_indices[rr_type][x][y];
01147
01148
01149 assert(ptc >= 0);
01150 assert(ptc < lookup.nelem);
01151
01152 #ifdef DEBUG
01153 switch (rr_type)
01154 {
01155 case SOURCE:
01156 assert(ptc < type->num_class);
01157 assert(type->class_inf[ptc].type == DRIVER);
01158 break;
01159
01160 case SINK:
01161 assert(ptc < type->num_class);
01162 assert(type->class_inf[ptc].type == RECEIVER);
01163 break;
01164
01165 case OPIN:
01166 assert(ptc < type->num_pins);
01167 iclass = type->pin_class[ptc];
01168 assert(type->class_inf[iclass].type == DRIVER);
01169 break;
01170
01171 case IPIN:
01172 assert(ptc < type->num_pins);
01173 iclass = type->pin_class[ptc];
01174 assert(type->class_inf[iclass].type == RECEIVER);
01175 break;
01176
01177 case CHANX:
01178 case CHANY:
01179 break;
01180
01181 default:
01182 printf("Error: Bad rr_node passed to get_rr_node_index.\n"
01183 "Request for type=%d ptc=%d at (%d, %d).\n",
01184 rr_type, ptc, x, y);
01185 exit(1);
01186 }
01187 #endif
01188
01189 return lookup.list[ptc];
01190 }
01191
01192
01193 int
01194 get_track_to_ipins(int seg,
01195 int chan,
01196 int track,
01197 t_linked_edge ** edge_list_ptr,
01198 t_ivec *** rr_node_indices,
01199 struct s_ivec ****track_to_ipin_lookup,
01200 t_seg_details * seg_details,
01201 enum e_rr_type chan_type,
01202 int chan_length,
01203 int wire_to_ipin_switch,
01204 enum e_directionality directionality)
01205 {
01206
01207
01208
01209 t_linked_edge *edge_list_head;
01210 int j, pass, iconn, phy_track, end, to_node, max_conn, ipin, side, x,
01211 y, num_conn;
01212 t_type_ptr type;
01213 int off;
01214
01215
01216 end = get_seg_end(seg_details, track, seg, chan, chan_length);
01217
01218 edge_list_head = *edge_list_ptr;
01219 num_conn = 0;
01220
01221 for(j = seg; j <= end; j++)
01222 {
01223 if(is_cbox(chan, j, track, seg_details, directionality))
01224 {
01225 for(pass = 0; pass < 2; ++pass)
01226 {
01227 if(CHANX == chan_type)
01228 {
01229 x = j;
01230 y = chan + pass;
01231 side = (0 == pass ? TOP : BOTTOM);
01232 }
01233 else
01234 {
01235 assert(CHANY == chan_type);
01236 x = chan + pass;
01237 y = j;
01238 side = (0 == pass ? RIGHT : LEFT);
01239 }
01240
01241
01242 if(grid[x][y].type == EMPTY_TYPE)
01243 continue;
01244
01245
01246
01247
01248 phy_track =
01249 vpr_to_phy_track(track, chan, j, seg_details,
01250 directionality);
01251
01252
01253 type = grid[x][y].type;
01254 off = grid[x][y].offset;
01255
01256 max_conn =
01257 track_to_ipin_lookup[type->
01258 index][phy_track][off]
01259 [side].nelem;
01260 for(iconn = 0; iconn < max_conn; iconn++)
01261 {
01262 ipin =
01263 track_to_ipin_lookup[type->
01264 index][phy_track]
01265 [off][side].list[iconn];
01266
01267
01268 assert(type->pinloc[off][side][ipin]);
01269 assert(type->is_global_pin[ipin] ==
01270 FALSE);
01271
01272 to_node =
01273 get_rr_node_index(x, y, IPIN, ipin,
01274 rr_node_indices);
01275 edge_list_head =
01276 insert_in_edge_list(edge_list_head,
01277 to_node,
01278 wire_to_ipin_switch);
01279 }
01280 num_conn += max_conn;
01281 }
01282 }
01283 }
01284
01285 *edge_list_ptr = edge_list_head;
01286 return (num_conn);
01287 }
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306 int
01307 get_track_to_tracks(IN int from_chan,
01308 IN int from_seg,
01309 IN int from_track,
01310 IN t_rr_type from_type,
01311 IN int to_seg,
01312 IN t_rr_type to_type,
01313 IN int chan_len,
01314 IN int nodes_per_chan,
01315 IN int *opin_mux_size,
01316 IN int Fs_per_side,
01317 IN short *****sblock_pattern,
01318 INOUT struct s_linked_edge **edge_list,
01319 IN t_seg_details * seg_details,
01320 IN enum e_directionality directionality,
01321 IN t_ivec *** rr_node_indices,
01322 INOUT boolean * rr_edge_done,
01323 IN struct s_ivec ***switch_block_conn)
01324 {
01325 int num_conn;
01326 int from_switch, from_end, from_sb, from_first;
01327 int to_chan, to_sb;
01328 int start, end;
01329 struct s_ivec conn_tracks;
01330 boolean from_is_sbox, is_behind, Fs_clipped;
01331 enum e_side from_side_a, from_side_b, to_side;
01332
01333 assert(from_seg ==
01334 get_seg_start(seg_details, from_track, from_chan, from_seg));
01335
01336 from_switch = seg_details[from_track].wire_switch;
01337 from_end =
01338 get_seg_end(seg_details, from_track, from_seg, from_chan, chan_len);
01339 from_first = from_seg - 1;
01340
01341
01342 if(CHANX == from_type)
01343 {
01344 from_side_a = RIGHT;
01345 from_side_b = LEFT;
01346 }
01347 else
01348 {
01349 assert(CHANY == from_type);
01350 from_side_a = TOP;
01351 from_side_b = BOTTOM;
01352 }
01353
01354
01355
01356 is_behind = FALSE;
01357 if(to_type == from_type)
01358 {
01359
01360
01361 assert((to_seg == (from_end + 1)) || (to_seg == (from_seg - 1)));
01362 if(to_seg > from_end)
01363 {
01364 is_behind = TRUE;
01365 }
01366 }
01367 else
01368 {
01369
01370
01371 assert((to_seg == from_chan) || (to_seg == (from_chan + 1)));
01372 if(to_seg > from_chan)
01373 {
01374 is_behind = TRUE;
01375 }
01376 }
01377
01378
01379
01380 if(CHANX == to_type)
01381 {
01382 to_side = (is_behind ? RIGHT : LEFT);
01383 }
01384 else
01385 {
01386 assert(CHANY == to_type);
01387 to_side = (is_behind ? TOP : BOTTOM);
01388 }
01389
01390
01391 start = from_first;
01392 end = from_end;
01393
01394
01395
01396
01397 if(to_type == from_type)
01398 {
01399 start = (is_behind ? end : start);
01400 end = start;
01401 }
01402
01403
01404 num_conn = 0;
01405 for(from_sb = start; from_sb <= end; ++from_sb)
01406 {
01407
01408 from_is_sbox = is_sbox(from_chan, from_seg, from_sb, from_track,
01409 seg_details, directionality);
01410
01411 if(from_sb == from_end || from_sb == from_first)
01412 {
01413 from_is_sbox = TRUE;
01414 }
01415
01416
01417
01418 to_chan = from_sb;
01419 to_sb = from_chan;
01420 if(from_type == to_type)
01421 {
01422 to_chan = from_chan;
01423 to_sb = from_sb;
01424 }
01425
01426
01427 if(from_sb < from_end)
01428 {
01429 if(BI_DIRECTIONAL == directionality)
01430 {
01431 conn_tracks =
01432 switch_block_conn[from_side_a][to_side]
01433 [from_track];
01434 num_conn +=
01435 get_bidir_track_to_chan_seg(conn_tracks,
01436 rr_node_indices,
01437 to_chan, to_seg,
01438 to_sb, to_type,
01439 seg_details,
01440 from_is_sbox,
01441 from_switch,
01442 rr_edge_done,
01443 directionality,
01444 edge_list);
01445 }
01446 if(UNI_DIRECTIONAL == directionality)
01447 {
01448
01449
01450
01451 if((from_is_sbox) &&
01452 (DEC_DIRECTION ==
01453 seg_details[from_track].direction))
01454 {
01455 num_conn +=
01456 get_unidir_track_to_chan_seg((from_sb
01457 ==
01458 from_first),
01459 from_track,
01460 to_chan,
01461 to_seg,
01462 to_sb,
01463 to_type,
01464 nodes_per_chan,
01465 nx, ny,
01466 from_side_a,
01467 to_side,
01468 Fs_per_side,
01469 opin_mux_size,
01470 sblock_pattern,
01471 rr_node_indices,
01472 seg_details,
01473 rr_edge_done,
01474 &Fs_clipped,
01475 edge_list);
01476 }
01477 }
01478 }
01479
01480
01481 if(from_sb > from_first)
01482 {
01483 if(BI_DIRECTIONAL == directionality)
01484 {
01485 conn_tracks =
01486 switch_block_conn[from_side_b][to_side]
01487 [from_track];
01488 num_conn +=
01489 get_bidir_track_to_chan_seg(conn_tracks,
01490 rr_node_indices,
01491 to_chan, to_seg,
01492 to_sb, to_type,
01493 seg_details,
01494 from_is_sbox,
01495 from_switch,
01496 rr_edge_done,
01497 directionality,
01498 edge_list);
01499 }
01500 if(UNI_DIRECTIONAL == directionality)
01501 {
01502
01503
01504
01505 if((from_is_sbox) &&
01506 (INC_DIRECTION ==
01507 seg_details[from_track].direction))
01508 {
01509 num_conn +=
01510 get_unidir_track_to_chan_seg((from_sb
01511 ==
01512 from_end),
01513 from_track,
01514 to_chan,
01515 to_seg,
01516 to_sb,
01517 to_type,
01518 nodes_per_chan,
01519 nx, ny,
01520 from_side_b,
01521 to_side,
01522 Fs_per_side,
01523 opin_mux_size,
01524 sblock_pattern,
01525 rr_node_indices,
01526 seg_details,
01527 rr_edge_done,
01528 &Fs_clipped,
01529 edge_list);
01530 }
01531 }
01532 }
01533 }
01534
01535 return num_conn;
01536 }
01537
01538
01539
01540 static int
01541 get_bidir_track_to_chan_seg(IN struct s_ivec conn_tracks,
01542 IN t_ivec *** rr_node_indices,
01543 IN int to_chan,
01544 IN int to_seg,
01545 IN int to_sb,
01546 IN t_rr_type to_type,
01547 IN t_seg_details * seg_details,
01548 IN boolean from_is_sbox,
01549 IN int from_switch,
01550 INOUT boolean * rr_edge_done,
01551 IN enum e_directionality directionality,
01552 INOUT struct s_linked_edge **edge_list)
01553 {
01554 int iconn, to_track, to_node, to_switch, num_conn, to_x, to_y, i;
01555 boolean to_is_sbox;
01556 short switch_types[2];
01557
01558
01559 if(CHANX == to_type)
01560 {
01561 to_x = to_seg;
01562 to_y = to_chan;
01563 }
01564 else
01565 {
01566 assert(CHANY == to_type);
01567 to_x = to_chan;
01568 to_y = to_seg;
01569 }
01570
01571
01572 num_conn = 0;
01573 for(iconn = 0; iconn < conn_tracks.nelem; ++iconn)
01574 {
01575 to_track = conn_tracks.list[iconn];
01576 to_node = get_rr_node_index(to_x, to_y, to_type, to_track,
01577 rr_node_indices);
01578
01579
01580 if(rr_edge_done[to_node])
01581 {
01582 continue;
01583 }
01584
01585
01586 to_switch = seg_details[to_track].wire_switch;
01587
01588 to_is_sbox = is_sbox(to_chan, to_seg, to_sb, to_track,
01589 seg_details, directionality);
01590 get_switch_type(from_is_sbox, to_is_sbox,
01591 from_switch, to_switch, switch_types);
01592
01593
01594 for(i = 0; i < 2; ++i)
01595 {
01596
01597 if(OPEN == switch_types[i])
01598 {
01599 continue;
01600 }
01601
01602
01603 *edge_list = insert_in_edge_list(*edge_list,
01604 to_node,
01605 switch_types[i]);
01606
01607 rr_edge_done[to_node] = TRUE;
01608 ++num_conn;
01609 }
01610 }
01611
01612 return num_conn;
01613 }
01614
01615 static int
01616 get_unidir_track_to_chan_seg(IN boolean is_end_sb,
01617 IN int from_track,
01618 IN int to_chan,
01619 IN int to_seg,
01620 IN int to_sb,
01621 IN t_rr_type to_type,
01622 IN int nodes_per_chan,
01623 IN int nx,
01624 IN int ny,
01625 IN enum e_side from_side,
01626 IN enum e_side to_side,
01627 IN int Fs_per_side,
01628 IN int *opin_mux_size,
01629 IN short *****sblock_pattern,
01630 IN t_ivec *** rr_node_indices,
01631 IN t_seg_details * seg_details,
01632 INOUT boolean * rr_edge_done,
01633 OUT boolean * Fs_clipped,
01634 INOUT struct s_linked_edge **edge_list)
01635 {
01636 int to_track, to_mux, to_node, to_x, to_y, i, max_len, num_labels;
01637 int sb_x, sb_y, count;
01638 int *mux_labels = NULL;
01639 enum e_direction to_dir;
01640 boolean is_fringe, is_core, is_corner, is_straight;
01641
01642
01643 if(CHANX == to_type)
01644 {
01645 to_x = to_seg;
01646 to_y = to_chan;
01647 sb_x = to_sb;
01648 sb_y = to_chan;
01649 max_len = nx;
01650 }
01651 else
01652 {
01653 assert(CHANY == to_type);
01654 to_x = to_chan;
01655 to_y = to_seg;
01656 sb_x = to_chan;
01657 sb_y = to_sb;
01658 max_len = ny;
01659 }
01660
01661
01662 to_dir = DEC_DIRECTION;
01663 if(to_sb < to_seg)
01664 {
01665 to_dir = INC_DIRECTION;
01666 }
01667
01668 *Fs_clipped = FALSE;
01669
01670
01671 is_corner = ((sb_x < 1) || (sb_x >= nx)) && ((sb_y < 1) || (sb_y >= ny));
01672 is_fringe = (FALSE == is_corner) && ((sb_x < 1) || (sb_y < 1)
01673 || (sb_x >= nx) || (sb_y >= ny));
01674 is_core = (FALSE == is_corner) && (FALSE == is_fringe);
01675 is_straight = (from_side == RIGHT && to_side == LEFT) ||
01676 (from_side == LEFT && to_side == RIGHT) ||
01677 (from_side == TOP && to_side == BOTTOM) ||
01678 (from_side == BOTTOM && to_side == TOP);
01679
01680
01681 if(is_end_sb && (is_core || is_corner || is_straight))
01682 {
01683
01684 mux_labels = label_wire_muxes(to_chan, to_seg, seg_details,
01685 max_len, to_dir, nodes_per_chan,
01686 &num_labels);
01687 }
01688 else
01689 {
01690 assert(is_fringe || !is_end_sb);
01691
01692 mux_labels = label_wire_muxes_for_balance(to_chan, to_seg,
01693 seg_details, max_len,
01694 to_dir, nodes_per_chan,
01695 &num_labels, to_type,
01696 opin_mux_size,
01697 rr_node_indices);
01698 }
01699
01700
01701 if(num_labels < 1)
01702 {
01703 if(mux_labels)
01704 {
01705 free(mux_labels);
01706 mux_labels = NULL;
01707 }
01708 return 0;
01709 }
01710
01711
01712 if(Fs_per_side > num_labels)
01713 {
01714 *Fs_clipped = TRUE;
01715 }
01716
01717
01718 to_mux = sblock_pattern[sb_x][sb_y][from_side][to_side][from_track];
01719 assert(to_mux != UN_SET);
01720
01721
01722 count = 0;
01723 for(i = 0; i < Fs_per_side; ++i)
01724 {
01725
01726 to_track = mux_labels[(to_mux + i) % num_labels];
01727 to_node =
01728 get_rr_node_index(to_x, to_y, to_type, to_track,
01729 rr_node_indices);
01730
01731
01732 if(FALSE == rr_edge_done[to_node])
01733 {
01734 rr_edge_done[to_node] = TRUE;
01735 *edge_list =
01736 insert_in_edge_list(*edge_list, to_node,
01737 seg_details[to_track].
01738 wire_switch);
01739 ++count;
01740 }
01741 }
01742
01743 if(mux_labels)
01744 {
01745 free(mux_labels);
01746 mux_labels = NULL;
01747 }
01748
01749 return count;
01750 }
01751
01752 boolean
01753 is_sbox(IN int chan,
01754 IN int wire_seg,
01755 IN int sb_seg,
01756 IN int track,
01757 IN t_seg_details * seg_details,
01758 IN enum e_directionality directionality)
01759 {
01760
01761 int start, length, ofs, fac;
01762
01763 fac = 1;
01764 if(UNI_DIRECTIONAL == directionality)
01765 {
01766 fac = 2;
01767 }
01768
01769 start = seg_details[track].start;
01770 length = seg_details[track].length;
01771
01772
01773 wire_seg = get_seg_start(seg_details, track, chan, wire_seg);
01774
01775 ofs = sb_seg - wire_seg + 1;
01776
01777 assert(ofs >= 0);
01778 assert(ofs < (length + 1));
01779
01780
01781 if((ofs % fac) > 0)
01782 {
01783 ofs = length - ofs;
01784 }
01785
01786 return seg_details[track].sb[ofs];
01787 }
01788
01789
01790
01791 static void
01792 get_switch_type(boolean is_from_sbox,
01793 boolean is_to_sbox,
01794 short from_node_switch,
01795 short to_node_switch,
01796 short switch_types[2])
01797 {
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807 boolean forward_pass_trans;
01808 boolean backward_pass_trans;
01809 int used, min, max;
01810
01811 switch_types[0] = OPEN;
01812 switch_types[1] = OPEN;
01813 used = 0;
01814 forward_pass_trans = FALSE;
01815 backward_pass_trans = FALSE;
01816
01817
01818 if(is_from_sbox)
01819 {
01820 switch_types[used] = to_node_switch;
01821 if(FALSE == switch_inf[to_node_switch].buffered)
01822 {
01823 forward_pass_trans = TRUE;
01824 }
01825 ++used;
01826 }
01827
01828
01829 if(is_to_sbox)
01830 {
01831 if(FALSE == switch_inf[from_node_switch].buffered)
01832 {
01833 switch_types[used] = from_node_switch;
01834 backward_pass_trans = TRUE;
01835 ++used;
01836 }
01837 }
01838
01839
01840 if(forward_pass_trans && backward_pass_trans)
01841 {
01842 min = min(to_node_switch, from_node_switch);
01843 max = max(to_node_switch, from_node_switch);
01844
01845
01846
01847 switch_types[used] = min;
01848 if(switch_inf[max].R < switch_inf[min].R)
01849 {
01850 switch_types[used] = max;
01851 }
01852 ++used;
01853 }
01854 }
01855
01856 static int
01857 vpr_to_phy_track(IN int itrack,
01858 IN int chan_num,
01859 IN int seg_num,
01860 IN t_seg_details * seg_details,
01861 IN enum e_directionality directionality)
01862 {
01863 int group_start, group_size;
01864 int vpr_offset_for_first_phy_track;
01865 int vpr_offset, phy_offset;
01866 int phy_track;
01867 int fac;
01868
01869
01870 fac = 1;
01871 if(UNI_DIRECTIONAL == directionality)
01872 {
01873 fac = 2;
01874 }
01875
01876 group_start = seg_details[itrack].group_start;
01877 group_size = seg_details[itrack].group_size;
01878
01879 vpr_offset_for_first_phy_track =
01880 (chan_num + seg_num - 1) % (group_size / fac);
01881 vpr_offset = (itrack - group_start) / fac;
01882 phy_offset =
01883 (vpr_offset_for_first_phy_track + vpr_offset) % (group_size / fac);
01884 phy_track =
01885 group_start + (fac * phy_offset) + (itrack - group_start) % fac;
01886
01887 return phy_track;
01888 }
01889
01890
01891
01892 short *****
01893 alloc_sblock_pattern_lookup(IN int nx,
01894 IN int ny,
01895 IN int nodes_per_chan)
01896 {
01897 int i, j, from_side, to_side, itrack, items;
01898 short *****result;
01899 short *****i_list;
01900 short ****j_list;
01901 short ***from_list;
01902 short **to_list;
01903 short *track_list;
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915 items = 1;
01916 items *= (nx + 1);
01917 i_list = (short *****)my_malloc(sizeof(short ****) * items);
01918 items *= (ny + 1);
01919 j_list = (short ****)my_malloc(sizeof(short ***) * items);
01920 items *= (4);
01921 from_list = (short ***)my_malloc(sizeof(short **) * items);
01922 items *= (4);
01923 to_list = (short **)my_malloc(sizeof(short *) * items);
01924 items *= (nodes_per_chan);
01925 track_list = (short *)my_malloc(sizeof(short) * items);
01926
01927
01928 result = i_list;
01929 i_list += (nx + 1);
01930 for(i = 0; i < (nx + 1); ++i)
01931 {
01932
01933 result[i] = j_list;
01934 j_list += (ny + 1);
01935 for(j = 0; j < (ny + 1); ++j)
01936 {
01937
01938 result[i][j] = from_list;
01939 from_list += (4);
01940 for(from_side = 0; from_side < 4; ++from_side)
01941 {
01942
01943 result[i][j][from_side] = to_list;
01944 to_list += (4);
01945 for(to_side = 0; to_side < 4; ++to_side)
01946 {
01947
01948 result[i][j][from_side][to_side] =
01949 track_list;
01950 track_list += (nodes_per_chan);
01951 for(itrack = 0; itrack < nodes_per_chan;
01952 itrack++)
01953 {
01954
01955
01956 result[i][j][from_side][to_side]
01957 [itrack] = UN_SET;
01958 }
01959 }
01960 }
01961 }
01962 }
01963
01964
01965 return result;
01966 }
01967
01968
01969 void
01970 free_sblock_pattern_lookup(INOUT short *****sblock_pattern)
01971 {
01972
01973
01974
01975
01976
01977
01978
01979
01980 free(****sblock_pattern);
01981 free(***sblock_pattern);
01982 free(**sblock_pattern);
01983 free(*sblock_pattern);
01984 free(sblock_pattern);
01985 }
01986
01987
01988 void
01989 load_sblock_pattern_lookup(IN int i,
01990 IN int j,
01991 IN int nodes_per_chan,
01992 IN t_seg_details * seg_details,
01993 IN int Fs,
01994 IN enum e_switch_block_type switch_block_type,
01995 INOUT short *****sblock_pattern)
01996 {
01997
01998
01999
02000
02001
02002 int side_cw_incoming_wire_count, side_ccw_incoming_wire_count,
02003 opp_incoming_wire_count;
02004 int to_side, side, side_cw, side_ccw, side_opp, itrack;
02005 int Fs_per_side, chan, seg, chan_len, sb_seg;
02006 boolean is_core_sblock, is_corner_sblock, x_edge, y_edge;
02007 int *incoming_wire_label[4];
02008 int *wire_mux_on_track[4];
02009 int num_incoming_wires[4];
02010 int num_ending_wires[4];
02011 int num_wire_muxes[4];
02012 boolean skip, vert, pos_dir;
02013 enum e_direction dir;
02014
02015 Fs_per_side = 1;
02016 if(Fs != -1)
02017 {
02018 Fs_per_side = Fs / 3;
02019 }
02020
02021
02022 assert(i >= 0);
02023 assert(i <= nx);
02024 assert(j >= 0);
02025 assert(j <= ny);
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068 x_edge = ((i < 1) || (i >= nx));
02069 y_edge = ((j < 1) || (j >= ny));
02070
02071 is_corner_sblock = (x_edge && y_edge);
02072 is_core_sblock = (!x_edge && !y_edge);
02073
02074
02075 for(side = 0; side < 4; ++side)
02076 {
02077
02078 wire_mux_on_track[side] = NULL;
02079 incoming_wire_label[side] = NULL;
02080 num_incoming_wires[side] = 0;
02081 num_ending_wires[side] = 0;
02082 num_wire_muxes[side] = 0;
02083
02084
02085
02086 skip = TRUE;
02087 switch (side)
02088 {
02089 case TOP:
02090 if(j < ny)
02091 {
02092 skip = FALSE;
02093 };
02094 break;
02095 case RIGHT:
02096 if(i < nx)
02097 {
02098 skip = FALSE;
02099 }
02100 break;
02101 case BOTTOM:
02102 if(j > 0)
02103 {
02104 skip = FALSE;
02105 }
02106 break;
02107 case LEFT:
02108 if(i > 0)
02109 {
02110 skip = FALSE;
02111 }
02112 break;
02113 }
02114 if(skip)
02115 {
02116 continue;
02117 }
02118
02119
02120 vert = ((side == TOP) || (side == BOTTOM));
02121 pos_dir = ((side == TOP) || (side == RIGHT));
02122 chan = (vert ? i : j);
02123 sb_seg = (vert ? j : i);
02124 seg = (pos_dir ? (sb_seg + 1) : sb_seg);
02125 chan_len = (vert ? ny : nx);
02126
02127
02128
02129 dir = (pos_dir ? DEC_DIRECTION : INC_DIRECTION);
02130 incoming_wire_label[side] =
02131 label_incoming_wires(chan, seg, sb_seg, seg_details, chan_len,
02132 dir, nodes_per_chan,
02133 &num_incoming_wires[side],
02134 &num_ending_wires[side]);
02135
02136
02137 dir = (pos_dir ? INC_DIRECTION : DEC_DIRECTION);
02138 wire_mux_on_track[side] = label_wire_muxes(chan, seg,
02139 seg_details, chan_len,
02140 dir, nodes_per_chan,
02141 &num_wire_muxes[side]);
02142 }
02143
02144 for(to_side = 0; to_side < 4; to_side++)
02145 {
02146
02147 if(0 == num_wire_muxes[to_side])
02148 {
02149 continue;
02150 }
02151
02152
02153 assert((TOP == 0) && (RIGHT == 1) && (BOTTOM == 2)
02154 && (LEFT == 3));
02155 side_cw = (to_side + 1) % 4;
02156 side_opp = (to_side + 2) % 4;
02157 side_ccw = (to_side + 3) % 4;
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170 side_cw_incoming_wire_count = 0;
02171 if(incoming_wire_label[side_cw])
02172 {
02173 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02174 {
02175
02176 if(incoming_wire_label[side_cw][itrack] != UN_SET)
02177 {
02178
02179 if((is_corner_sblock || is_core_sblock) &&
02180 (incoming_wire_label[side_cw][itrack] <
02181 num_ending_wires[side_cw]))
02182 {
02183
02184
02185
02186
02187 assert(num_ending_wires[side_cw]
02188 ==
02189 num_wire_muxes[to_side]);
02190 sblock_pattern[i][j][side_cw]
02191 [to_side][itrack] =
02192 get_simple_switch_block_track
02193 (side_cw, to_side,
02194 incoming_wire_label[side_cw]
02195 [itrack], switch_block_type,
02196 num_wire_muxes[to_side]);
02197
02198 }
02199 else
02200 {
02201
02202
02203
02204 sblock_pattern[i][j][side_cw]
02205 [to_side][itrack] =
02206 (side_cw_incoming_wire_count *
02207 Fs_per_side) %
02208 num_wire_muxes[to_side];
02209 side_cw_incoming_wire_count++;
02210 }
02211 }
02212 }
02213 }
02214
02215
02216 side_ccw_incoming_wire_count = 0;
02217 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02218 {
02219
02220
02221 if(incoming_wire_label[side_ccw] == NULL)
02222 break;
02223
02224
02225 if(incoming_wire_label[side_ccw][itrack] != UN_SET)
02226 {
02227
02228 if((is_corner_sblock || is_core_sblock) &&
02229 (incoming_wire_label[side_ccw][itrack] <
02230 num_ending_wires[side_ccw]))
02231 {
02232
02233
02234 assert(incoming_wire_label[side_ccw]
02235 [itrack] <
02236 num_wire_muxes[to_side]);
02237 sblock_pattern[i][j][side_ccw][to_side]
02238 [itrack] =
02239 get_simple_switch_block_track
02240 (side_ccw, to_side,
02241 incoming_wire_label[side_ccw]
02242 [itrack], switch_block_type,
02243 num_wire_muxes[to_side]);
02244 }
02245 else
02246 {
02247
02248
02249
02250 sblock_pattern[i][j][side_ccw][to_side]
02251 [itrack] =
02252 ((side_ccw_incoming_wire_count +
02253 side_cw_incoming_wire_count) *
02254 Fs_per_side) %
02255 num_wire_muxes[to_side];
02256 side_ccw_incoming_wire_count++;
02257 }
02258 }
02259 }
02260
02261
02262 opp_incoming_wire_count = 0;
02263 if(incoming_wire_label[side_opp])
02264 {
02265 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02266 {
02267
02268 if(incoming_wire_label[side_opp][itrack] !=
02269 UN_SET)
02270 {
02271
02272
02273 if(is_core_sblock)
02274 {
02275 if(incoming_wire_label[side_opp]
02276 [itrack] <
02277 num_ending_wires[side_opp])
02278 {
02279
02280
02281
02282
02283 sblock_pattern[i][j]
02284 [side_opp][to_side]
02285 [itrack] =
02286 find_label_of_track
02287 (wire_mux_on_track
02288 [to_side],
02289 num_wire_muxes
02290 [to_side], itrack);
02291 }
02292 else
02293 {
02294
02295 sblock_pattern[i][j]
02296 [side_opp][to_side]
02297 [itrack] =
02298 ((side_ccw_incoming_wire_count + side_cw_incoming_wire_count) * Fs_per_side + opp_incoming_wire_count * (Fs_per_side - 1)) % num_wire_muxes[to_side];
02299 opp_incoming_wire_count++;
02300 }
02301 }
02302 else
02303 {
02304 if(incoming_wire_label[side_opp]
02305 [itrack] <
02306 num_ending_wires[side_opp])
02307 {
02308 sblock_pattern[i][j]
02309 [side_opp][to_side]
02310 [itrack] =
02311 find_label_of_track
02312 (wire_mux_on_track
02313 [to_side],
02314 num_wire_muxes
02315 [to_side], itrack);
02316 }
02317 else
02318 {
02319
02320 sblock_pattern[i][j]
02321 [side_opp][to_side]
02322 [itrack] =
02323 ((side_ccw_incoming_wire_count + side_cw_incoming_wire_count) * Fs_per_side + opp_incoming_wire_count * (Fs_per_side - 1)) % num_wire_muxes[to_side];
02324 opp_incoming_wire_count++;
02325 }
02326 }
02327 }
02328 }
02329 }
02330 }
02331
02332 for(side = 0; side < 4; ++side)
02333 {
02334 if(incoming_wire_label[side])
02335 {
02336 free(incoming_wire_label[side]);
02337 }
02338 if(wire_mux_on_track[side])
02339 {
02340 free(wire_mux_on_track[side]);
02341 }
02342 }
02343 }
02344
02345 static int *
02346 label_wire_muxes_for_balance(IN int chan_num,
02347 IN int seg_num,
02348 IN t_seg_details * seg_details,
02349 IN int max_len,
02350 IN enum e_direction direction,
02351 IN int nodes_per_chan,
02352 IN int *num_wire_muxes,
02353 IN t_rr_type chan_type,
02354 IN int *opin_mux_size,
02355 IN t_ivec *** rr_node_indices)
02356 {
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 int num_labels, max_opin_mux_size, min_opin_mux_size;
02383 int inode, i, j, x, y;
02384 int *pre_labels, *final_labels;
02385
02386 if (chan_type == CHANX){
02387 x = seg_num;
02388 y = chan_num;
02389 }
02390 else if (chan_type == CHANY){
02391 x = chan_num;
02392 y = seg_num;
02393 }
02394 else {
02395 printf("Error: Bad channel type (%d).\n", chan_type);
02396 exit(1);
02397 }
02398
02399
02400 pre_labels =
02401 label_wire_muxes(chan_num, seg_num, seg_details, max_len,
02402 direction, nodes_per_chan, &num_labels);
02403
02404
02405 min_opin_mux_size = MAX_SHORT;
02406 max_opin_mux_size = 0;
02407 for(i = 0; i < num_labels; ++i)
02408 {
02409 inode = get_rr_node_index(x, y, chan_type, pre_labels[i],
02410 rr_node_indices);
02411 if(opin_mux_size[inode] < min_opin_mux_size)
02412 {
02413 min_opin_mux_size = opin_mux_size[inode];
02414 }
02415 if(opin_mux_size[inode] > max_opin_mux_size)
02416 {
02417 max_opin_mux_size = opin_mux_size[inode];
02418 }
02419 }
02420 if(max_opin_mux_size > (min_opin_mux_size + 1))
02421 {
02422 printf(ERRTAG "opin muxes are not balanced!\n");
02423 printf("max_opin_mux_size %d min_opin_mux_size %d chan_type %d x %d y %d\n",
02424 max_opin_mux_size, min_opin_mux_size, chan_type, x, y);
02425 exit(1);
02426 }
02427
02428
02429 final_labels = (int *)my_malloc(sizeof(int) * num_labels);
02430 j = 0;
02431 for(i = 0; i < num_labels; ++i)
02432 {
02433 inode = pre_labels[i];
02434 if(opin_mux_size[inode] < max_opin_mux_size)
02435 {
02436 final_labels[j] = inode;
02437 ++j;
02438 }
02439 }
02440 for(i = 0; i < num_labels; ++i)
02441 {
02442 inode = pre_labels[i];
02443 if(opin_mux_size[inode] >= max_opin_mux_size)
02444 {
02445 final_labels[j] = inode;
02446 ++j;
02447 }
02448 }
02449
02450
02451 if(pre_labels)
02452 {
02453 free(pre_labels);
02454 pre_labels = NULL;
02455 }
02456
02457 *num_wire_muxes = num_labels;
02458 return final_labels;
02459 }
02460
02461
02462 static int *
02463 label_wire_muxes(IN int chan_num,
02464 IN int seg_num,
02465 IN t_seg_details * seg_details,
02466 IN int max_len,
02467 IN enum e_direction dir,
02468 IN int nodes_per_chan,
02469 OUT int *num_wire_muxes)
02470 {
02471
02472
02473
02474
02475
02476 int itrack, start, end, num_labels, pass;
02477 int *labels = NULL;
02478 boolean is_endpoint;
02479
02480
02481 num_labels = 0;
02482 for(pass = 0; pass < 2; ++pass)
02483 {
02484
02485 if(pass > 0)
02486 {
02487 labels = (int *)my_malloc(sizeof(int) * num_labels);
02488 num_labels = 0;
02489 }
02490
02491
02492 for(itrack = 0; itrack < nodes_per_chan; ++itrack)
02493 {
02494 start =
02495 get_seg_start(seg_details, itrack, chan_num, seg_num);
02496 end =
02497 get_seg_end(seg_details, itrack, start, chan_num,
02498 max_len);
02499
02500
02501 if(seg_details[itrack].direction != dir)
02502 {
02503 continue;
02504 }
02505
02506
02507 is_endpoint = (seg_num == start);
02508 if(DEC_DIRECTION == seg_details[itrack].direction)
02509 {
02510 is_endpoint = (seg_num == end);
02511 }
02512
02513
02514 if(is_endpoint)
02515 {
02516 if(pass > 0)
02517 {
02518 labels[num_labels] = itrack;
02519 }
02520 ++num_labels;
02521 }
02522 }
02523 }
02524
02525 *num_wire_muxes = num_labels;
02526 return labels;
02527 }
02528
02529
02530
02531 static int *
02532 label_incoming_wires(IN int chan_num,
02533 IN int seg_num,
02534 IN int sb_seg,
02535 IN t_seg_details * seg_details,
02536 IN int max_len,
02537 IN enum e_direction dir,
02538 IN int nodes_per_chan,
02539 OUT int *num_incoming_wires,
02540 OUT int *num_ending_wires)
02541 {
02542
02543
02544
02545
02546
02547 int itrack, start, end, i, num_passing, num_ending, pass;
02548 int *labels;
02549 boolean sbox_exists, is_endpoint;
02550
02551
02552 labels = (int *)my_malloc(nodes_per_chan * sizeof(int));
02553 for(i = 0; i < nodes_per_chan; ++i)
02554 {
02555 labels[i] = UN_SET;
02556 }
02557
02558 num_ending = 0;
02559 num_passing = 0;
02560 for(pass = 0; pass < 2; ++pass)
02561 {
02562 for(itrack = 0; itrack < nodes_per_chan; ++itrack)
02563 {
02564 if(seg_details[itrack].direction == dir)
02565 {
02566 start =
02567 get_seg_start(seg_details, itrack, chan_num,
02568 seg_num);
02569 end =
02570 get_seg_end(seg_details, itrack, start,
02571 chan_num, max_len);
02572
02573
02574 is_endpoint = (seg_num == end);
02575 if(DEC_DIRECTION == seg_details[itrack].direction)
02576 {
02577 is_endpoint = (seg_num == start);
02578 }
02579
02580
02581 sbox_exists = is_sbox(chan_num, seg_num, sb_seg,
02582 itrack, seg_details,
02583 UNI_DIRECTIONAL);
02584
02585 switch (pass)
02586 {
02587
02588 case 0:
02589 if(is_endpoint)
02590 {
02591 labels[itrack] = num_ending;
02592 ++num_ending;
02593 }
02594 break;
02595
02596
02597
02598 case 1:
02599 if((FALSE == is_endpoint) && sbox_exists)
02600 {
02601 labels[itrack] =
02602 num_ending + num_passing;
02603 ++num_passing;
02604 }
02605 break;
02606 }
02607 }
02608 }
02609 }
02610
02611 *num_incoming_wires = num_passing + num_ending;
02612 *num_ending_wires = num_ending;
02613 return labels;
02614 }
02615
02616
02617
02618 static int
02619 find_label_of_track(int *wire_mux_on_track,
02620 int num_wire_muxes,
02621 int from_track)
02622 {
02623 int i, max_label, nearest_label, max_entry, nearest_entry;
02624
02625
02626
02627
02628 max_label = nearest_label = max_entry = nearest_entry = -1;
02629
02630 for(i = 0; i < num_wire_muxes; i++)
02631 {
02632 if(wire_mux_on_track[i] == from_track)
02633 {
02634 return i;
02635 }
02636 }
02637
02638 printf("Error: Expected mux not found.\n");
02639 exit(1);
02640 }