VPR-6.0

vpr/SRC/route/rr_graph_sbox.c

Go to the documentation of this file.
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 }