VPR-6.0
|
00001 #include <assert.h> 00002 #include "util.h" 00003 #include "vpr_types.h" 00004 #include "rr_graph_sbox.h" 00005 #include "rr_graph_util.h" 00006 00007 00008 /* Switch box: * 00009 * TOP (CHANY) * 00010 * | | | | | | * 00011 * +-----------+ * 00012 * --| |-- * 00013 * --| |-- * 00014 * LEFT --| |-- RIGHT * 00015 * (CHANX)--| |--(CHANX) * 00016 * --| |-- * 00017 * --| |-- * 00018 * +-----------+ * 00019 * | | | | | | * 00020 * BOTTOM (CHANY) */ 00021 00022 /* [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: * 00023 * [from_side][to_side][from_track]. That yields an integer vector (ivec) * 00024 * of the tracks to which from_track connects in the proper to_location. * 00025 * For simple switch boxes this is overkill, but it will allow complicated * 00026 * switch boxes with Fs > 3, etc. without trouble. */ 00027 00028 00029 int get_simple_switch_block_track(INP enum e_side from_side, 00030 INP enum e_side to_side, 00031 INP int from_track, 00032 INP enum e_switch_block_type 00033 switch_block_type, 00034 INP int nodes_per_chan); 00035 00036 00037 /** Allocates and loads the switch_block_conn data structure. This structure 00038 * lists which tracks connect to which at each switch block. This is for 00039 * bidir. 00040 */ 00041 struct s_ivec *** 00042 alloc_and_load_switch_block_conn(INP int nodes_per_chan, 00043 INP enum 00044 e_switch_block_type switch_block_type, 00045 INP int Fs) 00046 { 00047 enum e_side from_side, to_side; 00048 int from_track; 00049 struct s_ivec ***switch_block_conn = NULL; 00050 00051 #ifdef CREATE_ECHO_FILES 00052 int i, j, k, l; 00053 FILE *out; 00054 #endif /* CREATE_ECHO_FILES */ 00055 00056 /* Currently Fs must be 3 since each track maps once to each other side */ 00057 assert(3 == Fs); 00058 00059 switch_block_conn = 00060 (struct s_ivec ***)alloc_matrix3(0, 3, 00061 0, 3, 00062 0, (nodes_per_chan - 1), 00063 sizeof(struct s_ivec)); 00064 00065 for(from_side = 0; from_side < 4; from_side++) 00066 { 00067 for(to_side = 0; to_side < 4; to_side++) 00068 { 00069 for(from_track = 0; from_track < nodes_per_chan; 00070 from_track++) 00071 { 00072 if(from_side != to_side) 00073 { 00074 switch_block_conn[from_side][to_side] 00075 [from_track].nelem = 1; 00076 switch_block_conn[from_side][to_side] 00077 [from_track].list = 00078 (int *)my_malloc(sizeof(int)); 00079 00080 switch_block_conn[from_side][to_side] 00081 [from_track].list[0] = 00082 get_simple_switch_block_track 00083 (from_side, to_side, from_track, 00084 switch_block_type, nodes_per_chan); 00085 } 00086 else 00087 { /* from_side == to_side -> no connection. */ 00088 switch_block_conn[from_side][to_side] 00089 [from_track].nelem = 0; 00090 switch_block_conn[from_side][to_side] 00091 [from_track].list = NULL; 00092 } 00093 } 00094 } 00095 } 00096 00097 #ifdef CREATE_ECHO_FILES 00098 out = my_fopen("switch_block_conn.echo", "w", 0); 00099 for(l = 0; l < 4; ++l) 00100 { 00101 for(k = 0; k < 4; ++k) 00102 { 00103 fprintf(out, "Side %d to %d\n", l, k); 00104 for(j = 0; j < nodes_per_chan; ++j) 00105 { 00106 fprintf(out, "%d: ", j); 00107 for(i = 0; i < switch_block_conn[l][k][j].nelem; 00108 ++i) 00109 { 00110 fprintf(out, "%d ", 00111 switch_block_conn[l][k][j]. 00112 list[i]); 00113 } 00114 fprintf(out, "\n"); 00115 } 00116 fprintf(out, "\n"); 00117 } 00118 } 00119 fclose(out); 00120 #endif /* CREATE_ECHO_FILES */ 00121 00122 return switch_block_conn; 00123 } 00124 00125 00126 /** Frees the switch_block_conn data structure. */ 00127 void 00128 free_switch_block_conn(struct s_ivec ***switch_block_conn, 00129 int nodes_per_chan) 00130 { 00131 free_ivec_matrix3(switch_block_conn, 0, 3, 0, 3, 0, nodes_per_chan - 1); 00132 } 00133 00134 00135 #define SBOX_ERROR -1 00136 00137 00138 /** This routine permutes the track number to connect for topologies 00139 * SUBSET, UNIVERSAL, and WILTON. I added FULL (for fully flexible topology) 00140 * but the returned value is simply a dummy, since we don't need to permute 00141 * what connections to make for FULL (connect to EVERYTHING) */ 00142 /** This routine returns the track number to which the from_track should 00143 * connect. It supports three simple, Fs = 3, switch blocks. 00144 */ 00145 int 00146 get_simple_switch_block_track(INP enum e_side from_side, 00147 INP enum e_side to_side, 00148 INP int from_track, 00149 INP enum e_switch_block_type switch_block_type, 00150 INP int nodes_per_chan) 00151 { 00152 00153 int to_track; 00154 00155 to_track = SBOX_ERROR; /* Can check to see if it's not set later. */ 00156 00157 if(switch_block_type == SUBSET) 00158 { /* NB: Global routing uses SUBSET too */ 00159 to_track = from_track; 00160 } 00161 00162 00163 /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ 00164 00165 else if(switch_block_type == WILTON) 00166 { 00167 00168 if(from_side == LEFT) 00169 { 00170 00171 if(to_side == RIGHT) 00172 { /* CHANX to CHANX */ 00173 to_track = from_track; 00174 } 00175 else if(to_side == TOP) 00176 { /* from CHANX to CHANY */ 00177 to_track = 00178 (nodes_per_chan - 00179 from_track) % nodes_per_chan; 00180 } 00181 else if(to_side == BOTTOM) 00182 { 00183 to_track = 00184 (nodes_per_chan + from_track - 00185 1) % nodes_per_chan; 00186 } 00187 } 00188 00189 else if(from_side == RIGHT) 00190 { 00191 if(to_side == LEFT) 00192 { /* CHANX to CHANX */ 00193 to_track = from_track; 00194 } 00195 else if(to_side == TOP) 00196 { /* from CHANX to CHANY */ 00197 to_track = 00198 (nodes_per_chan + from_track - 00199 1) % nodes_per_chan; 00200 } 00201 else if(to_side == BOTTOM) 00202 { 00203 to_track = 00204 (2 * nodes_per_chan - 2 - 00205 from_track) % nodes_per_chan; 00206 } 00207 } 00208 00209 else if(from_side == BOTTOM) 00210 { 00211 if(to_side == TOP) 00212 { /* CHANY to CHANY */ 00213 to_track = from_track; 00214 } 00215 else if(to_side == LEFT) 00216 { /* from CHANY to CHANX */ 00217 to_track = (from_track + 1) % nodes_per_chan; 00218 } 00219 else if(to_side == RIGHT) 00220 { 00221 to_track = 00222 (2 * nodes_per_chan - 2 - 00223 from_track) % nodes_per_chan; 00224 } 00225 } 00226 00227 else if(from_side == TOP) 00228 { 00229 if(to_side == BOTTOM) 00230 { /* CHANY to CHANY */ 00231 to_track = from_track; 00232 } 00233 else if(to_side == LEFT) 00234 { /* from CHANY to CHANX */ 00235 to_track = 00236 (nodes_per_chan - 00237 from_track) % nodes_per_chan; 00238 } 00239 else if(to_side == RIGHT) 00240 { 00241 to_track = (from_track + 1) % nodes_per_chan; 00242 } 00243 } 00244 00245 } 00246 /* End switch_block_type == WILTON case. */ 00247 else if(switch_block_type == UNIVERSAL) 00248 { 00249 00250 if(from_side == LEFT) 00251 { 00252 00253 if(to_side == RIGHT) 00254 { /* CHANX to CHANX */ 00255 to_track = from_track; 00256 } 00257 else if(to_side == TOP) 00258 { /* from CHANX to CHANY */ 00259 to_track = nodes_per_chan - 1 - from_track; 00260 } 00261 else if(to_side == BOTTOM) 00262 { 00263 to_track = from_track; 00264 } 00265 } 00266 00267 else if(from_side == RIGHT) 00268 { 00269 if(to_side == LEFT) 00270 { /* CHANX to CHANX */ 00271 to_track = from_track; 00272 } 00273 else if(to_side == TOP) 00274 { /* from CHANX to CHANY */ 00275 to_track = from_track; 00276 } 00277 else if(to_side == BOTTOM) 00278 { 00279 to_track = nodes_per_chan - 1 - from_track; 00280 } 00281 } 00282 00283 else if(from_side == BOTTOM) 00284 { 00285 if(to_side == TOP) 00286 { /* CHANY to CHANY */ 00287 to_track = from_track; 00288 } 00289 else if(to_side == LEFT) 00290 { /* from CHANY to CHANX */ 00291 to_track = from_track; 00292 } 00293 else if(to_side == RIGHT) 00294 { 00295 to_track = nodes_per_chan - 1 - from_track; 00296 } 00297 } 00298 00299 else if(from_side == TOP) 00300 { 00301 if(to_side == BOTTOM) 00302 { /* CHANY to CHANY */ 00303 to_track = from_track; 00304 } 00305 else if(to_side == LEFT) 00306 { /* from CHANY to CHANX */ 00307 to_track = nodes_per_chan - 1 - from_track; 00308 } 00309 else if(to_side == RIGHT) 00310 { 00311 to_track = from_track; 00312 } 00313 } 00314 } 00315 00316 /* End switch_block_type == UNIVERSAL case. */ 00317 /* UDSD Modification by WMF Begin */ 00318 if(switch_block_type == FULL) 00319 { /* Just a placeholder. No meaning in reality */ 00320 to_track = from_track; 00321 } 00322 /* UDSD Modification by WMF End */ 00323 00324 if(to_track == SBOX_ERROR) 00325 { 00326 printf 00327 ("Error in get_simple_switch_block_track. Unexpected connection.\n" 00328 "from_side: %d to_side: %d switch_block_type: %d.\n", 00329 from_side, to_side, switch_block_type); 00330 exit(1); 00331 } 00332 00333 return (to_track); 00334 }