VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
rr_graph_sbox.c
Go to the documentation of this file.
1 #include <assert.h>
2 #include "util.h"
3 #include "vpr_types.h"
4 #include "rr_graph_sbox.h"
5 #include "rr_graph_util.h"
6 #include "ReadOptions.h"
7 
8 /* Switch box: *
9  * TOP (CHANY) *
10  * | | | | | | *
11  * +-----------+ *
12  * --| |-- *
13  * --| |-- *
14  * LEFT --| |-- RIGHT *
15  * (CHANX)--| |--(CHANX) *
16  * --| |-- *
17  * --| |-- *
18  * +-----------+ *
19  * | | | | | | *
20  * BOTTOM (CHANY) */
21 
22 /* [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: *
23  * [from_side][to_side][from_track]. That yields an integer vector (ivec) *
24  * of the tracks to which from_track connects in the proper to_location. *
25  * For simple switch boxes this is overkill, but it will allow complicated *
26  * switch boxes with Fs > 3, etc. without trouble. */
27 
28 int get_simple_switch_block_track(INP enum e_side from_side,
29  INP enum e_side to_side, INP int from_track,
30  INP enum e_switch_block_type switch_block_type, INP int nodes_per_chan);
31 
32 /* Allocates and loads the switch_block_conn data structure. This structure *
33  * lists which tracks connect to which at each switch block. This is for
34  * bidir. */
35 struct s_ivec ***
37  INP enum e_switch_block_type switch_block_type, INP int Fs) {
38  enum e_side from_side, to_side;
39  int from_track;
40  struct s_ivec ***switch_block_conn = NULL;
41 
42  /* Currently Fs must be 3 since each track maps once to each other side */
43  assert(3 == Fs);
44 
45  switch_block_conn = (struct s_ivec ***) alloc_matrix3(0, 3, 0, 3, 0,
46  (nodes_per_chan - 1), sizeof(struct s_ivec));
47 
48  for (from_side = (enum e_side)0; from_side < 4; from_side = (enum e_side)(from_side + 1)) {
49  for (to_side = (enum e_side)0; to_side < 4; to_side = (enum e_side)(to_side + 1)) {
50  for (from_track = 0; from_track < nodes_per_chan; from_track++) {
51  if (from_side != to_side) {
52  switch_block_conn[from_side][to_side][from_track].nelem = 1;
53  switch_block_conn[from_side][to_side][from_track].list =
54  (int *) my_malloc(sizeof(int));
55 
56  switch_block_conn[from_side][to_side][from_track].list[0] =
57  get_simple_switch_block_track(from_side, to_side,
58  from_track, switch_block_type,
59  nodes_per_chan);
60  } else { /* from_side == to_side -> no connection. */
61  switch_block_conn[from_side][to_side][from_track].nelem = 0;
62  switch_block_conn[from_side][to_side][from_track].list =
63  NULL;
64  }
65  }
66  }
67  }
68 
69  if (getEchoEnabled()) {
70  int i, j, k, l;
71  FILE *out;
72 
73  out = my_fopen("switch_block_conn.echo", "w", 0);
74  for (l = 0; l < 4; ++l) {
75  for (k = 0; k < 4; ++k) {
76  fprintf(out, "Side %d to %d\n", l, k);
77  for (j = 0; j < nodes_per_chan; ++j) {
78  fprintf(out, "%d: ", j);
79  for (i = 0; i < switch_block_conn[l][k][j].nelem; ++i) {
80  fprintf(out, "%d ", switch_block_conn[l][k][j].list[i]);
81  }
82  fprintf(out, "\n");
83  }
84  fprintf(out, "\n");
85  }
86  }
87  fclose(out);
88  }
89  return switch_block_conn;
90 }
91 
92 void free_switch_block_conn(struct s_ivec ***switch_block_conn,
93  int nodes_per_chan) {
94  /* Frees the switch_block_conn data structure. */
95 
96  free_ivec_matrix3(switch_block_conn, 0, 3, 0, 3, 0, nodes_per_chan - 1);
97 }
98 
99 #define SBOX_ERROR -1
100 
101 /* This routine permutes the track number to connect for topologies
102  * SUBSET, UNIVERSAL, and WILTON. I added FULL (for fully flexible topology)
103  * but the returned value is simply a dummy, since we don't need to permute
104  * what connections to make for FULL (connect to EVERYTHING) */
106  INP enum e_side to_side, INP int from_track,
107  INP enum e_switch_block_type switch_block_type, INP int nodes_per_chan) {
108 
109  /* This routine returns the track number to which the from_track should *
110  * connect. It supports three simple, Fs = 3, switch blocks. */
111 
112  int to_track;
113 
114  to_track = SBOX_ERROR; /* Can check to see if it's not set later. */
115 
116  if (switch_block_type == SUBSET) { /* NB: Global routing uses SUBSET too */
117  to_track = from_track;
118  }
119 
120  /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */
121 
122  else if (switch_block_type == WILTON) {
123 
124  if (from_side == LEFT) {
125 
126  if (to_side == RIGHT) { /* CHANX to CHANX */
127  to_track = from_track;
128  } else if (to_side == TOP) { /* from CHANX to CHANY */
129  to_track = (nodes_per_chan - from_track) % nodes_per_chan;
130  } else if (to_side == BOTTOM) {
131  to_track = (nodes_per_chan + from_track - 1) % nodes_per_chan;
132  }
133  }
134 
135  else if (from_side == RIGHT) {
136  if (to_side == LEFT) { /* CHANX to CHANX */
137  to_track = from_track;
138  } else if (to_side == TOP) { /* from CHANX to CHANY */
139  to_track = (nodes_per_chan + from_track - 1) % nodes_per_chan;
140  } else if (to_side == BOTTOM) {
141  to_track = (2 * nodes_per_chan - 2 - from_track)
142  % nodes_per_chan;
143  }
144  }
145 
146  else if (from_side == BOTTOM) {
147  if (to_side == TOP) { /* CHANY to CHANY */
148  to_track = from_track;
149  } else if (to_side == LEFT) { /* from CHANY to CHANX */
150  to_track = (from_track + 1) % nodes_per_chan;
151  } else if (to_side == RIGHT) {
152  to_track = (2 * nodes_per_chan - 2 - from_track)
153  % nodes_per_chan;
154  }
155  }
156 
157  else if (from_side == TOP) {
158  if (to_side == BOTTOM) { /* CHANY to CHANY */
159  to_track = from_track;
160  } else if (to_side == LEFT) { /* from CHANY to CHANX */
161  to_track = (nodes_per_chan - from_track) % nodes_per_chan;
162  } else if (to_side == RIGHT) {
163  to_track = (from_track + 1) % nodes_per_chan;
164  }
165  }
166 
167  }
168  /* End switch_block_type == WILTON case. */
169  else if (switch_block_type == UNIVERSAL) {
170 
171  if (from_side == LEFT) {
172 
173  if (to_side == RIGHT) { /* CHANX to CHANX */
174  to_track = from_track;
175  } else if (to_side == TOP) { /* from CHANX to CHANY */
176  to_track = nodes_per_chan - 1 - from_track;
177  } else if (to_side == BOTTOM) {
178  to_track = from_track;
179  }
180  }
181 
182  else if (from_side == RIGHT) {
183  if (to_side == LEFT) { /* CHANX to CHANX */
184  to_track = from_track;
185  } else if (to_side == TOP) { /* from CHANX to CHANY */
186  to_track = from_track;
187  } else if (to_side == BOTTOM) {
188  to_track = nodes_per_chan - 1 - from_track;
189  }
190  }
191 
192  else if (from_side == BOTTOM) {
193  if (to_side == TOP) { /* CHANY to CHANY */
194  to_track = from_track;
195  } else if (to_side == LEFT) { /* from CHANY to CHANX */
196  to_track = from_track;
197  } else if (to_side == RIGHT) {
198  to_track = nodes_per_chan - 1 - from_track;
199  }
200  }
201 
202  else if (from_side == TOP) {
203  if (to_side == BOTTOM) { /* CHANY to CHANY */
204  to_track = from_track;
205  } else if (to_side == LEFT) { /* from CHANY to CHANX */
206  to_track = nodes_per_chan - 1 - from_track;
207  } else if (to_side == RIGHT) {
208  to_track = from_track;
209  }
210  }
211  }
212 
213  /* End switch_block_type == UNIVERSAL case. */
214  /* UDSD Modification by WMF Begin */
215  if (switch_block_type == FULL) { /* Just a placeholder. No meaning in reality */
216  to_track = from_track;
217  }
218  /* UDSD Modification by WMF End */
219 
220  if (to_track == SBOX_ERROR) {
221  vpr_printf(TIO_MESSAGE_ERROR, "in get_simple_switch_block_track.\n");
222  vpr_printf(TIO_MESSAGE_ERROR, "\tUnexpected connection from_side: %d to_side: %d switch_block_type: %d.\n",
223  from_side, to_side, switch_block_type);
224  exit(1);
225  }
226 
227  return (to_track);
228 }
FILE * my_fopen(const char *fname, const char *flag, int prompt)
Definition: util.c:54
int * list
Definition: util.h:49
int get_simple_switch_block_track(INP enum e_side from_side, INP enum e_side to_side, INP int from_track, INP enum e_switch_block_type switch_block_type, INP int nodes_per_chan)
e_switch_block_type
e_side
boolean getEchoEnabled(void)
Definition: ReadOptions.c:67
#define SBOX_ERROR
Definition: rr_graph_sbox.c:99
struct s_ivec *** alloc_and_load_switch_block_conn(INP int nodes_per_chan, INP enum e_switch_block_type switch_block_type, INP int Fs)
Definition: rr_graph_sbox.c:36
static void * my_malloc(int ibytes)
Definition: graphics.c:499
int nelem
Definition: util.h:48
#define INP
Definition: util.h:19
Definition: util.h:47
void free_switch_block_conn(struct s_ivec ***switch_block_conn, int nodes_per_chan)
Definition: rr_graph_sbox.c:92
void *** alloc_matrix3(int nrmin, int nrmax, int ncmin, int ncmax, int ndmin, int ndmax, size_t elsize)
Definition: util.c:585
messagelogger vpr_printf
Definition: util.c:17
void free_ivec_matrix3(struct s_ivec ***ivec_matrix3, int nrmin, int nrmax, int ncmin, int ncmax, int ndmin, int ndmax)
Definition: util.c:529