VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
check_route.c File Reference
#include <assert.h>
#include <stdio.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "route_export.h"
#include "check_route.h"
#include "rr_graph.h"
#include "check_rr_graph.h"
#include "read_xml_arch_file.h"
+ Include dependency graph for check_route.c:

Go to the source code of this file.

Functions

static void check_node_and_range (int inode, enum e_route_type route_type)
 
static void check_source (int inode, int inet)
 
static void check_sink (int inode, int inet, boolean *pin_done)
 
static void check_switch (struct s_trace *tptr, int num_switch)
 
static boolean check_adjacent (int from_node, int to_node)
 
static int pin_and_chan_adjacent (int pin_node, int chan_node)
 
static int chanx_chany_adjacent (int chanx_node, int chany_node)
 
static void reset_flags (int inet, boolean *connected_to_route)
 
static void recompute_occupancy_from_scratch (t_ivec **clb_opins_used_locally)
 
static void check_locally_used_clb_opins (t_ivec **clb_opins_used_locally, enum e_route_type route_type)
 
void check_route (enum e_route_type route_type, int num_switch, t_ivec **clb_opins_used_locally)
 

Function Documentation

static int chanx_chany_adjacent ( int  chanx_node,
int  chany_node 
)
static

Definition at line 459 of file check_route.c.

459  {
460 
461  /* Returns 1 if the specified CHANX and CHANY nodes are adjacent, 0 *
462  * otherwise. */
463 
464  int chanx_y, chanx_xlow, chanx_xhigh;
465  int chany_x, chany_ylow, chany_yhigh;
466 
467  chanx_y = rr_node[chanx_node].ylow;
468  chanx_xlow = rr_node[chanx_node].xlow;
469  chanx_xhigh = rr_node[chanx_node].xhigh;
470 
471  chany_x = rr_node[chany_node].xlow;
472  chany_ylow = rr_node[chany_node].ylow;
473  chany_yhigh = rr_node[chany_node].yhigh;
474 
475  if (chany_ylow > chanx_y + 1 || chany_yhigh < chanx_y)
476  return (0);
477 
478  if (chanx_xlow > chany_x + 1 || chanx_xhigh < chany_x)
479  return (0);
480 
481  return (1);
482 }
short xhigh
Definition: vpr_types.h:891
t_rr_node * rr_node
Definition: globals.c:70
short ylow
Definition: vpr_types.h:892
short yhigh
Definition: vpr_types.h:893
short xlow
Definition: vpr_types.h:890

+ Here is the caller graph for this function:

static boolean check_adjacent ( int  from_node,
int  to_node 
)
static

Definition at line 289 of file check_route.c.

289  {
290 
291  /* This routine checks if the rr_node to_node is reachable from from_node. *
292  * It returns TRUE if is reachable and FALSE if it is not. Check_node has *
293  * already been used to verify that both nodes are valid rr_nodes, so only *
294  * adjacency is checked here.
295  * Special case: direct OPIN to IPIN connections need not be adjacent. These
296  * represent specially-crafted connections such as carry-chains or more advanced
297  * blocks where adjacency is overridden by the architect */
298 
299 
300  int from_xlow, from_ylow, to_xlow, to_ylow, from_ptc, to_ptc, iclass;
301  int num_adj, to_xhigh, to_yhigh, from_xhigh, from_yhigh, iconn;
302  boolean reached;
303  t_rr_type from_type, to_type;
304  t_type_ptr from_grid_type, to_grid_type;
305 
306  reached = FALSE;
307 
308  for (iconn = 0; iconn < rr_node[from_node].num_edges; iconn++) {
309  if (rr_node[from_node].edges[iconn] == to_node) {
310  reached = TRUE;
311  break;
312  }
313  }
314 
315  if (!reached)
316  return (FALSE);
317 
318  /* Now we know the rr graph says these two nodes are adjacent. Double *
319  * check that this makes sense, to verify the rr graph. */
320 
321  num_adj = 0;
322 
323  from_type = rr_node[from_node].type;
324  from_xlow = rr_node[from_node].xlow;
325  from_ylow = rr_node[from_node].ylow;
326  from_xhigh = rr_node[from_node].xhigh;
327  from_yhigh = rr_node[from_node].yhigh;
328  from_ptc = rr_node[from_node].ptc_num;
329  to_type = rr_node[to_node].type;
330  to_xlow = rr_node[to_node].xlow;
331  to_ylow = rr_node[to_node].ylow;
332  to_xhigh = rr_node[to_node].xhigh;
333  to_yhigh = rr_node[to_node].yhigh;
334  to_ptc = rr_node[to_node].ptc_num;
335 
336  switch (from_type) {
337 
338  case SOURCE:
339  assert(to_type == OPIN);
340  if (from_xlow == to_xlow && from_ylow == to_ylow
341  && from_xhigh == to_xhigh && from_yhigh == to_yhigh) {
342 
343  from_grid_type = grid[from_xlow][from_ylow].type;
344  to_grid_type = grid[to_xlow][to_ylow].type;
345  assert(from_grid_type == to_grid_type);
346 
347  iclass = to_grid_type->pin_class[to_ptc];
348  if (iclass == from_ptc)
349  num_adj++;
350  }
351  break;
352 
353  case SINK:
354  /* SINKS are adjacent to not connected */
355  break;
356 
357  case OPIN:
358  if(to_type == CHANX || to_type == CHANY) {
359  num_adj += pin_and_chan_adjacent(from_node, to_node);
360  } else {
361  assert(to_type == IPIN); /* direct OPIN to IPIN connections not necessarily adjacent */
362  return TRUE; /* Special case, direct OPIN to IPIN connections need not be adjacent */
363  }
364 
365  break;
366 
367  case IPIN:
368  assert(to_type == SINK);
369  if (from_xlow == to_xlow && from_ylow == to_ylow
370  && from_xhigh == to_xhigh && from_yhigh == to_yhigh) {
371 
372  from_grid_type = grid[from_xlow][from_ylow].type;
373  to_grid_type = grid[to_xlow][to_ylow].type;
374  assert(from_grid_type == to_grid_type);
375 
376  iclass = from_grid_type->pin_class[from_ptc];
377  if (iclass == to_ptc)
378  num_adj++;
379  }
380  break;
381 
382  case CHANX:
383  if (to_type == IPIN) {
384  num_adj += pin_and_chan_adjacent(to_node, from_node);
385  } else if (to_type == CHANX) {
386  from_xhigh = rr_node[from_node].xhigh;
387  to_xhigh = rr_node[to_node].xhigh;
388  if (from_ylow == to_ylow) {
389  /* UDSD Modification by WMF Begin */
390  /*For Fs > 3, can connect to overlapping wire segment */
391  if (to_xhigh == from_xlow - 1 || from_xhigh == to_xlow - 1) {
392  num_adj++;
393  }
394  /* Overlapping */
395  else {
396  int i;
397 
398  for (i = from_xlow; i <= from_xhigh; i++) {
399  if (i >= to_xlow && i <= to_xhigh) {
400  num_adj++;
401  break;
402  }
403  }
404  }
405  /* UDSD Modification by WMF End */
406  }
407  } else if (to_type == CHANY) {
408  num_adj += chanx_chany_adjacent(from_node, to_node);
409  } else {
410  assert(0);
411  }
412  break;
413 
414  case CHANY:
415  if (to_type == IPIN) {
416  num_adj += pin_and_chan_adjacent(to_node, from_node);
417  } else if (to_type == CHANY) {
418  from_yhigh = rr_node[from_node].yhigh;
419  to_yhigh = rr_node[to_node].yhigh;
420  if (from_xlow == to_xlow) {
421  /* UDSD Modification by WMF Begin */
422  if (to_yhigh == from_ylow - 1 || from_yhigh == to_ylow - 1) {
423  num_adj++;
424  }
425  /* Overlapping */
426  else {
427  int j;
428 
429  for (j = from_ylow; j <= from_yhigh; j++) {
430  if (j >= to_ylow && j <= to_yhigh) {
431  num_adj++;
432  break;
433  }
434  }
435  }
436  /* UDSD Modification by WMF End */
437  }
438  } else if (to_type == CHANX) {
439  num_adj += chanx_chany_adjacent(to_node, from_node);
440  } else {
441  assert(0);
442  }
443  break;
444 
445  default:
446  break;
447 
448  }
449 
450  if (num_adj == 1)
451  return (TRUE);
452  else if (num_adj == 0)
453  return (FALSE);
454 
455  vpr_printf(TIO_MESSAGE_ERROR, "in check_adjacent: num_adj = %d. Expected 0 or 1.\n", num_adj);
456  exit(1);
457 }
t_type_ptr type
Definition: vpr_types.h:522
short xhigh
Definition: vpr_types.h:891
short num_edges
Definition: vpr_types.h:901
t_rr_node * rr_node
Definition: globals.c:70
short ptc_num
Definition: vpr_types.h:895
short ylow
Definition: vpr_types.h:892
Definition: util.h:12
struct s_grid_tile ** grid
Definition: globals.c:59
static int chanx_chany_adjacent(int chanx_node, int chany_node)
Definition: check_route.c:459
short yhigh
Definition: vpr_types.h:893
enum e_rr_type t_rr_type
static int pin_and_chan_adjacent(int pin_node, int chan_node)
Definition: check_route.c:484
short xlow
Definition: vpr_types.h:890
messagelogger vpr_printf
Definition: util.c:17
t_rr_type type
Definition: vpr_types.h:902
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void check_locally_used_clb_opins ( t_ivec **  clb_opins_used_locally,
enum e_route_type  route_type 
)
static

Definition at line 590 of file check_route.c.

591  {
592 
593  /* Checks that enough OPINs on CLBs have been set aside (used up) to make a *
594  * legal routing if subblocks connect to OPINs directly. */
595 
596  int iclass, iblk, num_local_opins, inode, ipin;
597  t_rr_type rr_type;
598 
599  for (iblk = 0; iblk < num_blocks; iblk++) {
600  for (iclass = 0; iclass < block[iblk].type->num_class; iclass++) {
601  num_local_opins = clb_opins_used_locally[iblk][iclass].nelem;
602  /* Always 0 for pads and for SINK classes */
603 
604  for (ipin = 0; ipin < num_local_opins; ipin++) {
605  inode = clb_opins_used_locally[iblk][iclass].list[ipin];
606  check_node_and_range(inode, route_type); /* Node makes sense? */
607 
608  /* Now check that node is an OPIN of the right type. */
609 
610  rr_type = rr_node[inode].type;
611  if (rr_type != OPIN) {
612  vpr_printf(TIO_MESSAGE_ERROR, "in check_locally_used_opins: block #%d (%s)\n",
613  iblk, block[iblk].name);
614  vpr_printf(TIO_MESSAGE_ERROR, "\tClass %d local OPIN is wrong rr_type -- rr_node #%d of type %d.\n",
615  iclass, inode, rr_type);
616  exit(1);
617  }
618 
619  ipin = rr_node[inode].ptc_num;
620  if (block[iblk].type->pin_class[ipin] != iclass) {
621  vpr_printf(TIO_MESSAGE_ERROR, "in check_locally_used_opins: block #%d (%s):\n",
622  iblk, block[iblk].name);
623  vpr_printf(TIO_MESSAGE_ERROR, "\tExpected class %d local OPIN has class %d -- rr_node #: %d.\n",
624  iclass, block[iblk].type->pin_class[ipin], inode);
625  exit(1);
626  }
627  }
628  }
629  }
630 }
t_rr_node * rr_node
Definition: globals.c:70
short ptc_num
Definition: vpr_types.h:895
int * list
Definition: util.h:49
static void check_node_and_range(int inode, enum e_route_type route_type)
Definition: check_route.c:632
char * name
Definition: hash.h:4
t_type_ptr type
Definition: vpr_types.h:561
int num_blocks
Definition: globals.c:30
struct s_block * block
Definition: globals.c:31
int nelem
Definition: util.h:48
enum e_rr_type t_rr_type
messagelogger vpr_printf
Definition: util.c:17
t_rr_type type
Definition: vpr_types.h:902

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void check_node_and_range ( int  inode,
enum e_route_type  route_type 
)
static

Definition at line 632 of file check_route.c.

632  {
633 
634  /* Checks that inode is within the legal range, then calls check_node to *
635  * check that everything else about the node is OK. */
636 
637  if (inode < 0 || inode >= num_rr_nodes) {
638  vpr_printf(TIO_MESSAGE_ERROR, "in check_node_and_range: rr_node #%d is out of legal, range (0 to %d).\n",
639  inode, num_rr_nodes - 1);
640  exit(1);
641  }
642  check_node(inode, route_type);
643 }
void check_node(int inode, enum e_route_type route_type)
int num_rr_nodes
Definition: globals.c:69
messagelogger vpr_printf
Definition: util.c:17

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void check_route ( enum e_route_type  route_type,
int  num_switch,
t_ivec **  clb_opins_used_locally 
)

Definition at line 27 of file check_route.c.

28  {
29 
30  /* This routine checks that a routing: (1) Describes a properly *
31  * connected path for each net, (2) this path connects all the *
32  * pins spanned by that net, and (3) that no routing resources are *
33  * oversubscribed (the occupancy of everything is recomputed from *
34  * scratch). */
35 
36  int inet, ipin, max_pins, inode, prev_node;
37  boolean valid, connects;
38  boolean * connected_to_route; /* [0 .. num_rr_nodes-1] */
39  struct s_trace *tptr;
40  boolean * pin_done;
41 
42  vpr_printf(TIO_MESSAGE_INFO, "\n");
43  vpr_printf(TIO_MESSAGE_INFO, "Checking to ensure routing is legal...\n");
44 
45  /* Recompute the occupancy from scratch and check for overuse of routing *
46  * resources. This was already checked in order to determine that this *
47  * is a successful routing, but I want to double check it here. */
48 
49  recompute_occupancy_from_scratch(clb_opins_used_locally);
50  valid = feasible_routing();
51  if (valid == FALSE) {
52  vpr_printf(TIO_MESSAGE_ERROR, "Error in check_route -- routing resources are overused.\n");
53  exit(1);
54  }
55 
56  check_locally_used_clb_opins(clb_opins_used_locally, route_type);
57 
58  connected_to_route = (boolean *) my_calloc(num_rr_nodes, sizeof(boolean));
59 
60  max_pins = 0;
61  for (inet = 0; inet < num_nets; inet++)
62  max_pins = std::max(max_pins, (clb_net[inet].num_sinks + 1));
63 
64  pin_done = (boolean *) my_malloc(max_pins * sizeof(boolean));
65 
66  /* Now check that all nets are indeed connected. */
67 
68  for (inet = 0; inet < num_nets; inet++) {
69 
70  if (clb_net[inet].is_global || clb_net[inet].num_sinks == 0) /* Skip global nets. */
71  continue;
72 
73  for (ipin = 0; ipin < (clb_net[inet].num_sinks + 1); ipin++)
74  pin_done[ipin] = FALSE;
75 
76  /* Check the SOURCE of the net. */
77 
78  tptr = trace_head[inet];
79  if (tptr == NULL) {
80  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d has no routing.\n", inet);
81  exit(1);
82  }
83 
84  inode = tptr->index;
85  check_node_and_range(inode, route_type);
86  check_switch(tptr, num_switch);
87  connected_to_route[inode] = TRUE; /* Mark as in path. */
88 
89  check_source(inode, inet);
90  pin_done[0] = TRUE;
91 
92  prev_node = inode;
93  tptr = tptr->next;
94 
95  /* Check the rest of the net */
96 
97  while (tptr != NULL) {
98  inode = tptr->index;
99  check_node_and_range(inode, route_type);
100  check_switch(tptr, num_switch);
101 
102  if (rr_node[prev_node].type == SINK) {
103  if (connected_to_route[inode] == FALSE) {
104  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: node %d does not link into existing routing for net %d.\n", inode, inet);
105  exit(1);
106  }
107  }
108 
109  else {
110  connects = check_adjacent(prev_node, inode);
111  if (!connects) {
112  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: found non-adjacent segments in traceback while checking net %d.\n", inet);
113  exit(1);
114  }
115 
116  if (connected_to_route[inode] && rr_node[inode].type != SINK) {
117 
118  /* Note: Can get multiple connections to the same logically-equivalent *
119  * SINK in some logic blocks. */
120 
121  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d routing is not a tree.\n", inet);
122  exit(1);
123  }
124 
125  connected_to_route[inode] = TRUE; /* Mark as in path. */
126 
127  if (rr_node[inode].type == SINK)
128  check_sink(inode, inet, pin_done);
129 
130  } /* End of prev_node type != SINK */
131  prev_node = inode;
132  tptr = tptr->next;
133  } /* End while */
134 
135  if (rr_node[prev_node].type != SINK) {
136  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d does not end with a SINK.\n", inet);
137  exit(1);
138  }
139 
140  for (ipin = 0; ipin < (clb_net[inet].num_sinks + 1); ipin++) {
141  if (pin_done[ipin] == FALSE) {
142  vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d does not connect to pin %d.\n", inet, ipin);
143  exit(1);
144  }
145  }
146 
147  reset_flags(inet, connected_to_route);
148 
149  } /* End for each net */
150 
151  free(pin_done);
152  free(connected_to_route);
153  vpr_printf(TIO_MESSAGE_INFO, "Completed routing consistency check successfully.\n");
154  vpr_printf(TIO_MESSAGE_INFO, "\n");
155 }
static void recompute_occupancy_from_scratch(t_ivec **clb_opins_used_locally)
Definition: check_route.c:535
boolean feasible_routing(void)
Definition: route_common.c:298
int index
Definition: vpr_types.h:866
t_rr_node * rr_node
Definition: globals.c:70
static void check_locally_used_clb_opins(t_ivec **clb_opins_used_locally, enum e_route_type route_type)
Definition: check_route.c:590
static void check_node_and_range(int inode, enum e_route_type route_type)
Definition: check_route.c:632
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
int num_nets
Definition: globals.c:27
Definition: util.h:12
struct s_trace * next
Definition: vpr_types.h:870
static void * my_malloc(int ibytes)
Definition: graphics.c:499
boolean * is_global
#define max(a, b)
Definition: graphics.c:171
static void check_source(int inode, int inet)
Definition: check_route.c:204
struct s_net * clb_net
Definition: globals.c:28
int num_rr_nodes
Definition: globals.c:69
static boolean check_adjacent(int from_node, int to_node)
Definition: check_route.c:289
struct s_trace ** trace_head
Definition: globals.c:64
static void reset_flags(int inet, boolean *connected_to_route)
Definition: check_route.c:270
static void check_sink(int inode, int inet, boolean *pin_done)
Definition: check_route.c:157
messagelogger vpr_printf
Definition: util.c:17
static void check_switch(struct s_trace *tptr, int num_switch)
Definition: check_route.c:238
int num_sinks
Definition: vpr_types.h:506
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void check_sink ( int  inode,
int  inet,
boolean pin_done 
)
static

Definition at line 157 of file check_route.c.

157  {
158 
159  /* Checks that this SINK node is one of the terminals of inet, and marks *
160  * the appropriate pin as being reached. */
161 
162  int i, j, ipin, ifound, ptc_num, bnum, iclass, node_block_pin, iblk;
163  t_type_ptr type;
164 
165  assert(rr_node[inode].type == SINK);
166  i = rr_node[inode].xlow;
167  j = rr_node[inode].ylow;
168  type = grid[i][j].type;
169  ptc_num = rr_node[inode].ptc_num; /* For sinks, ptc_num is the class */
170  ifound = 0;
171 
172  for (iblk = 0; iblk < type->capacity; iblk++) {
173  bnum = grid[i][j].blocks[iblk]; /* Hardcoded to one block */
174  for (ipin = 1; ipin < (clb_net[inet].num_sinks + 1); ipin++) { /* All net SINKs */
175  if (clb_net[inet].node_block[ipin] == bnum) {
176  node_block_pin = clb_net[inet].node_block_pin[ipin];
177  iclass = type->pin_class[node_block_pin];
178  if (iclass == ptc_num) {
179  /* Could connect to same pin class on the same clb more than once. Only *
180  * update pin_done for a pin that hasn't been reached yet. */
181 
182  if (pin_done[ipin] == FALSE) {
183  ifound++;
184  pin_done[ipin] = TRUE;
185  }
186  }
187  }
188  }
189  }
190 
191  if (ifound > 1 && type == IO_TYPE) {
192  vpr_printf(TIO_MESSAGE_ERROR, "in check_sink: found %d terminals of net %d of pad %d at location (%d, %d).\n", ifound, inet, ptc_num, i, j);
193  exit(1);
194  }
195 
196  if (ifound < 1) {
197  vpr_printf(TIO_MESSAGE_ERROR, "in check_sink: node %d does not connect to any terminal of net %s #%d.\n"
198  "This error is usually caused by incorrectly specified logical equivalence in your architecture file.\n"
199  "You should try to respecify what pins are equivalent or turn logical equivalence off.\n", inode, clb_net[inet].name, inet);
200  exit(1);
201  }
202 }
int * node_block_pin
Definition: vpr_types.h:509
t_type_ptr type
Definition: vpr_types.h:522
t_rr_node * rr_node
Definition: globals.c:70
short ptc_num
Definition: vpr_types.h:895
short ylow
Definition: vpr_types.h:892
Definition: util.h:12
struct s_net * clb_net
Definition: globals.c:28
struct s_grid_tile ** grid
Definition: globals.c:59
int * blocks
Definition: vpr_types.h:525
t_type_ptr IO_TYPE
Definition: globals.c:40
short xlow
Definition: vpr_types.h:890
messagelogger vpr_printf
Definition: util.c:17
int num_sinks
Definition: vpr_types.h:506
Definition: util.h:12

+ Here is the caller graph for this function:

static void check_source ( int  inode,
int  inet 
)
static

Definition at line 204 of file check_route.c.

204  {
205 
206  /* Checks that the node passed in is a valid source for this net. */
207 
208  t_rr_type rr_type;
209  t_type_ptr type;
210  int i, j, ptc_num, bnum, node_block_pin, iclass;
211 
212  rr_type = rr_node[inode].type;
213  if (rr_type != SOURCE) {
214  vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net %d begins with a node of type %d.\n", inet, rr_type);
215  exit(1);
216  }
217 
218  i = rr_node[inode].xlow;
219  j = rr_node[inode].ylow;
220  ptc_num = rr_node[inode].ptc_num; /* for sinks and sources, ptc_num is class */
221  bnum = clb_net[inet].node_block[0]; /* First node_block for net is the source */
222  type = grid[i][j].type;
223 
224  if (block[bnum].x != i || block[bnum].y != j) {
225  vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net SOURCE is in wrong location (%d,%d).\n", i, j);
226  exit(1);
227  }
228 
229  node_block_pin = clb_net[inet].node_block_pin[0];
230  iclass = type->pin_class[node_block_pin];
231 
232  if (ptc_num != iclass) {
233  vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net SOURCE is of wrong class (%d).\n", ptc_num);
234  exit(1);
235  }
236 }
int * node_block_pin
Definition: vpr_types.h:509
t_type_ptr type
Definition: vpr_types.h:522
t_rr_node * rr_node
Definition: globals.c:70
short ptc_num
Definition: vpr_types.h:895
short ylow
Definition: vpr_types.h:892
int * node_block
Definition: vpr_types.h:507
struct s_block * block
Definition: globals.c:31
struct s_net * clb_net
Definition: globals.c:28
struct s_grid_tile ** grid
Definition: globals.c:59
enum e_rr_type t_rr_type
short xlow
Definition: vpr_types.h:890
messagelogger vpr_printf
Definition: util.c:17
t_rr_type type
Definition: vpr_types.h:902

+ Here is the caller graph for this function:

static void check_switch ( struct s_trace tptr,
int  num_switch 
)
static

Definition at line 238 of file check_route.c.

238  {
239 
240  /* Checks that the switch leading from this traceback element to the next *
241  * one is a legal switch type. */
242 
243  int inode;
244  short switch_type;
245 
246  inode = tptr->index;
247  switch_type = tptr->iswitch;
248 
249  if (rr_node[inode].type != SINK) {
250  if (switch_type < 0 || switch_type >= num_switch) {
251  vpr_printf(TIO_MESSAGE_ERROR, "in check_switch: rr_node %d left via switch type %d.\n", inode, switch_type);
252  vpr_printf(TIO_MESSAGE_ERROR, "\tSwitch type is out of range.\n");
253  exit(1);
254  }
255  }
256 
257  else { /* Is a SINK */
258 
259  /* Without feedthroughs, there should be no switch. If feedthroughs are *
260  * allowed, change to treat a SINK like any other node (as above). */
261 
262  if (switch_type != OPEN) {
263  vpr_printf(TIO_MESSAGE_ERROR, "in check_switch: rr_node %d is a SINK, but attempts to use a switch of type %d.\n",
264  inode, switch_type);
265  exit(1);
266  }
267  }
268 }
int index
Definition: vpr_types.h:866
t_rr_node * rr_node
Definition: globals.c:70
short iswitch
Definition: vpr_types.h:867
Definition: slre.c:50
messagelogger vpr_printf
Definition: util.c:17

+ Here is the caller graph for this function:

static int pin_and_chan_adjacent ( int  pin_node,
int  chan_node 
)
static

Definition at line 484 of file check_route.c.

484  {
485 
486  /* Checks if pin_node is adjacent to chan_node. It returns 1 if the two *
487  * nodes are adjacent and 0 if they are not (any other value means there's *
488  * a bug in this routine). */
489 
490  int num_adj, pin_xlow, pin_ylow, pin_xhigh, pin_yhigh, chan_xlow, chan_ylow,
491  chan_xhigh, chan_yhigh;
492  int pin_ptc, i;
493  t_rr_type chan_type;
494  t_type_ptr pin_grid_type;
495 
496  num_adj = 0;
497  pin_xlow = rr_node[pin_node].xlow;
498  pin_ylow = rr_node[pin_node].ylow;
499  pin_xhigh = rr_node[pin_node].xhigh;
500  pin_yhigh = rr_node[pin_node].yhigh;
501  pin_grid_type = grid[pin_xlow][pin_ylow].type;
502  pin_ptc = rr_node[pin_node].ptc_num;
503  chan_type = rr_node[chan_node].type;
504  chan_xlow = rr_node[chan_node].xlow;
505  chan_ylow = rr_node[chan_node].ylow;
506  chan_xhigh = rr_node[chan_node].xhigh;
507  chan_yhigh = rr_node[chan_node].yhigh;
508 
509  if (chan_type == CHANX) {
510  if (chan_ylow == pin_yhigh) { /* CHANX above CLB */
511  if (pin_grid_type->pinloc[pin_grid_type->height - 1][TOP][pin_ptc]
512  == 1 && pin_xlow <= chan_xhigh && pin_xhigh >= chan_xlow)
513  num_adj++;
514  } else if (chan_ylow == pin_ylow - 1) { /* CHANX below CLB */
515  if (pin_grid_type->pinloc[0][BOTTOM][pin_ptc] == 1
516  && pin_xlow <= chan_xhigh && pin_xhigh >= chan_xlow)
517  num_adj++;
518  }
519  } else if (chan_type == CHANY) {
520  for (i = 0; i < pin_grid_type->height; i++) {
521  if (chan_xlow == pin_xhigh) { /* CHANY to right of CLB */
522  if (pin_grid_type->pinloc[i][RIGHT][pin_ptc] == 1
523  && pin_ylow <= chan_yhigh && pin_yhigh >= chan_ylow)
524  num_adj++;
525  } else if (chan_xlow == pin_xlow - 1) { /* CHANY to left of CLB */
526  if (pin_grid_type->pinloc[i][LEFT][pin_ptc] == 1
527  && pin_ylow <= chan_yhigh && pin_yhigh >= chan_ylow)
528  num_adj++;
529  }
530  }
531  }
532  return (num_adj);
533 }
t_type_ptr type
Definition: vpr_types.h:522
short xhigh
Definition: vpr_types.h:891
t_rr_node * rr_node
Definition: globals.c:70
short ptc_num
Definition: vpr_types.h:895
short ylow
Definition: vpr_types.h:892
struct s_grid_tile ** grid
Definition: globals.c:59
short yhigh
Definition: vpr_types.h:893
enum e_rr_type t_rr_type
short xlow
Definition: vpr_types.h:890
t_rr_type type
Definition: vpr_types.h:902

+ Here is the caller graph for this function:

static void recompute_occupancy_from_scratch ( t_ivec **  clb_opins_used_locally)
static

Definition at line 535 of file check_route.c.

535  {
536 
537  /* This routine updates the occ field in the rr_node structure according to *
538  * the resource usage of the current routing. It does a brute force *
539  * recompute from scratch that is useful for sanity checking. */
540 
541  int inode, inet, iblk, iclass, ipin, num_local_opins;
542  struct s_trace *tptr;
543 
544  /* First set the occupancy of everything to zero. */
545 
546  for (inode = 0; inode < num_rr_nodes; inode++)
547  rr_node[inode].occ = 0;
548 
549  /* Now go through each net and count the tracks and pins used everywhere */
550 
551  for (inet = 0; inet < num_nets; inet++) {
552 
553  if (clb_net[inet].is_global) /* Skip global nets. */
554  continue;
555 
556  tptr = trace_head[inet];
557  if (tptr == NULL)
558  continue;
559 
560  for (;;) {
561  inode = tptr->index;
562  rr_node[inode].occ++;
563 
564  if (rr_node[inode].type == SINK) {
565  tptr = tptr->next; /* Skip next segment. */
566  if (tptr == NULL)
567  break;
568  }
569 
570  tptr = tptr->next;
571  }
572  }
573 
574  /* Now update the occupancy of each of the "locally used" OPINs on each CLB *
575  * (CLB outputs used up by being directly wired to subblocks used only *
576  * locally). */
577 
578  for (iblk = 0; iblk < num_blocks; iblk++) {
579  for (iclass = 0; iclass < block[iblk].type->num_class; iclass++) {
580  num_local_opins = clb_opins_used_locally[iblk][iclass].nelem;
581  /* Will always be 0 for pads or SINK classes. */
582  for (ipin = 0; ipin < num_local_opins; ipin++) {
583  inode = clb_opins_used_locally[iblk][iclass].list[ipin];
584  rr_node[inode].occ++;
585  }
586  }
587  }
588 }
int index
Definition: vpr_types.h:866
t_rr_node * rr_node
Definition: globals.c:70
int * list
Definition: util.h:49
int num_nets
Definition: globals.c:27
t_type_ptr type
Definition: vpr_types.h:561
int num_blocks
Definition: globals.c:30
struct s_trace * next
Definition: vpr_types.h:870
boolean * is_global
struct s_block * block
Definition: globals.c:31
struct s_net * clb_net
Definition: globals.c:28
int nelem
Definition: util.h:48
int num_rr_nodes
Definition: globals.c:69
struct s_trace ** trace_head
Definition: globals.c:64
short occ
Definition: vpr_types.h:898

+ Here is the caller graph for this function:

static void reset_flags ( int  inet,
boolean connected_to_route 
)
static

Definition at line 270 of file check_route.c.

270  {
271 
272  /* This routine resets the flags of all the channel segments contained *
273  * in the traceback of net inet to 0. This allows us to check the *
274  * next net for connectivity (and the default state of the flags *
275  * should always be zero after they have been used). */
276 
277  struct s_trace *tptr;
278  int inode;
279 
280  tptr = trace_head[inet];
281 
282  while (tptr != NULL) {
283  inode = tptr->index;
284  connected_to_route[inode] = FALSE; /* Not in routed path now. */
285  tptr = tptr->next;
286  }
287 }
int index
Definition: vpr_types.h:866
Definition: util.h:12
struct s_trace * next
Definition: vpr_types.h:870
struct s_trace ** trace_head
Definition: globals.c:64

+ Here is the caller graph for this function: