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

Go to the source code of this file.

Macros

#define ERROR_THRESHOLD   100
 

Functions

static int check_connections_to_global_clb_pins (int inet)
 
static int check_for_duplicated_names (void)
 
static int check_clb_conn (int iblk, int num_conn)
 
static int check_clb_internal_nets (int iblk)
 
static int check_subblock_internal_nets (int iblk, int isub)
 
static int get_num_conn (int bnum)
 
static int check_subblocks (int iblk)
 
static int check_primitives (int iblk, int isub)
 
void check_netlist ()
 

Macro Definition Documentation

#define ERROR_THRESHOLD   100

Definition at line 15 of file check_netlist.c.

Function Documentation

static int check_clb_conn ( int  iblk,
int  num_conn 
)
static

Definition at line 150 of file check_netlist.c.

150  {
151 
152  /* Checks that the connections into and out of the clb make sense. */
153 
154  int iclass, ipin, error;
155  t_type_ptr type;
156 
157  error = 0;
158  type = block[iblk].type;
159 
160  if (type == IO_TYPE) {
161  /*
162  //This triggers incorrectly if other blocks (e.g. I/O buffers) are included in the iopads
163  if (num_conn != 1) {
164  vpr_printf(TIO_MESSAGE_ERROR, "IO blk #%d (%s) has %d pins.\n",
165  iblk, block[iblk].name, num_conn);
166  error++;
167  }
168  */
169  } else if (num_conn < 2) {
170  vpr_printf(TIO_MESSAGE_WARNING, "Logic block #%d (%s) has only %d pin.\n",
171  iblk, block[iblk].name, num_conn);
172 
173  /* Allow the case where we have only one OUTPUT pin connected to continue. *
174  * This is used sometimes as a constant generator for a primary output, *
175  * but I will still warn the user. If the only pin connected is an input, *
176  * abort. */
177 
178  if (num_conn == 1) {
179  for (ipin = 0; ipin < type->num_pins; ipin++) {
180  if (block[iblk].nets[ipin] != OPEN) {
181  iclass = type->pin_class[ipin];
182 
183  if (type->class_inf[iclass].type != DRIVER) {
184  vpr_printf(TIO_MESSAGE_INFO, "Pin is an input -- this whole block is hanging logic that should be swept in logic synthesis.\n");
185  vpr_printf(TIO_MESSAGE_INFO, "\tNon-fatal, but check this.\n");
186  } else {
187  vpr_printf(TIO_MESSAGE_INFO, "Pin is an output -- may be a constant generator.\n");
188  vpr_printf(TIO_MESSAGE_INFO, "\tNon-fatal, but check this.\n");
189  }
190 
191  break;
192  }
193  }
194  }
195  }
196 
197  /* This case should already have been flagged as an error -- this is *
198  * just a redundant double check. */
199 
200  if (num_conn > type->num_pins) {
201  vpr_printf(TIO_MESSAGE_ERROR, "logic block #%d with output %s has %d pins.\n",
202  iblk, block[iblk].name, num_conn);
203  error++;
204  }
205 
206  return (error);
207 }
struct s_class * class_inf
t_type_ptr type
Definition: vpr_types.h:561
struct s_block * block
Definition: globals.c:31
t_type_ptr IO_TYPE
Definition: globals.c:40
Definition: slre.c:50
enum e_pin_type type
messagelogger vpr_printf
Definition: util.c:17

+ Here is the caller graph for this function:

static int check_clb_internal_nets ( int  iblk)
static

TODO: Check if the internal CLB nets makes sense and are connected properly Consists of 3 main loops

  1. a) Check name uniqueness b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
  2. Check all connected CLB pins are connected to valid internal nets
  3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes

Definition at line 209 of file check_netlist.c.

209  {
210  /** TODO:
211  * Check if the internal CLB nets makes sense and are connected properly
212  * Consists of 3 main loops
213  * 1. a) Check name uniqueness
214  b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
215  * 2. Check all connected CLB pins are connected to valid internal nets
216  * 3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes
217  */
218  return 0;
219 }

+ Here is the caller graph for this function:

static int check_connections_to_global_clb_pins ( int  inet)
static

Definition at line 102 of file check_netlist.c.

102  {
103 
104  /* Checks that a global net (inet) connects only to global CLB input pins *
105  * and that non-global nets never connects to a global CLB pin. Either *
106  * global or non-global nets are allowed to connect to pads. */
107 
108  int ipin, num_pins, iblk, node_block_pin, error;
109 
110  num_pins = (clb_net[inet].num_sinks + 1);
111  error = 0;
112 
113  /* For now global signals can be driven by an I/O pad or any CLB output *
114  * although a CLB output generates a warning. I could make a global CLB *
115  * output pin type to allow people to make architectures that didn't have *
116  * this warning. */
117 
118  for (ipin = 0; ipin < num_pins; ipin++) {
119  iblk = clb_net[inet].node_block[ipin];
120 
121  node_block_pin = clb_net[inet].node_block_pin[ipin];
122 
123  if (block[iblk].type->is_global_pin[node_block_pin]
124  != clb_net[inet].is_global && block[iblk].type != IO_TYPE) {
125 
126  /* Allow a CLB output pin to drive a global net (warning only). */
127 
128  if (ipin == 0 && clb_net[inet].is_global) {
129  vpr_printf(TIO_MESSAGE_WARNING, "in check_connections_to_global_clb_pins:\n");
130  vpr_printf(TIO_MESSAGE_WARNING, "\tnet #%d (%s) is driven by CLB output pin (#%d) on block #%d (%s).\n",
131  inet, clb_net[inet].name, node_block_pin, iblk, block[iblk].name);
132  } else { /* Otherwise -> Error */
133  vpr_printf(TIO_MESSAGE_ERROR, "in check_connections_to_global_clb_pins:\n");
134  vpr_printf(TIO_MESSAGE_ERROR, "\tpin %d on net #%d (%s) connects to CLB input pin (#%d) on block #%d (%s).\n",
135  ipin, inet, clb_net[inet].name, node_block_pin, iblk, block[iblk].name);
136  error++;
137  }
138 
139  if (clb_net[inet].is_global)
140  vpr_printf(TIO_MESSAGE_INFO, "Net is global, but CLB pin is not.\n");
141  else
142  vpr_printf(TIO_MESSAGE_INFO, "CLB pin is global, but net is not.\n");
143  vpr_printf(TIO_MESSAGE_INFO, "\n");
144  }
145  } /* End for all pins */
146 
147  return (error);
148 }
int * node_block_pin
Definition: vpr_types.h:509
int * node_block
Definition: vpr_types.h:507
t_type_ptr type
Definition: vpr_types.h:561
boolean * is_global
struct s_block * block
Definition: globals.c:31
struct s_net * clb_net
Definition: globals.c:28
boolean is_global
Definition: vpr_types.h:510
t_type_ptr IO_TYPE
Definition: globals.c:40
messagelogger vpr_printf
Definition: util.c:17
int num_sinks
Definition: vpr_types.h:506

+ Here is the caller graph for this function:

static int check_for_duplicated_names ( void  )
static

Definition at line 250 of file check_netlist.c.

250  {
251 #if 0
252  int iblk, isub, iprim, error;
253  int clb_count, sub_count, prim_count;
254  struct s_hash **clb_hash_table, *clb_h_ptr;
255  struct s_hash **sub_hash_table, *sub_h_ptr;
256  struct s_hash **prim_hash_table, *prim_h_ptr;
257 
258  clb_hash_table = alloc_hash_table();
259  sub_hash_table = alloc_hash_table();
260  prim_hash_table = alloc_hash_table();
261 
262  error = clb_count = sub_count = prim_count = 0;
263 
264  for (iblk = 0; iblk < num_blocks; iblk++)
265  {
266  clb_h_ptr = insert_in_hash_table(clb_hash_table, block[iblk].name, clb_count);
267  if (clb_h_ptr->count > 1) {
268  vpr_printf(TIO_MESSAGE_ERROR, "Block %s has duplicated name.\n",
269  block[iblk].name);
270  error++;
271  } else {
272  clb_count++;
273  }
274  for (isub = 0; isub < block[iblk].num_subblocks; isub++)
275  {
276  sub_h_ptr = insert_in_hash_table(sub_hash_table, block[iblk].subblocks[isub].name, sub_count);
277  if (sub_h_ptr->count > 1) {
278  vpr_printf(TIO_MESSAGE_ERROR, "Subblock %s has duplicated name.\n",
279  block[iblk].subblocks[isub].name);
280  error++;
281  } else {
282  sub_count++;
283  }
284  for (iprim = 0; iprim < block[iblk].subblocks[isub].num_primitives; iprim++)
285  {
286  prim_h_ptr = insert_in_hash_table(prim_hash_table, block[iblk].subblocks[isub].primitives[iprim].name, prim_count);
287  if (prim_h_ptr->count > 1) {
288  vpr_printf(TIO_MESSAGE_ERROR, "Primitive %s has duplicated name.\n",
289  block[iblk].subblocks[isub].primitives[iprim].name);
290  error++;
291  } else {
292  prim_count++;
293  }
294  }
295  }
296  }
297  return error;
298 #endif
299  return 0;
300 }
struct s_hash ** alloc_hash_table(void)
Definition: hash.c:7
int count
Definition: hash.h:6
char * name
Definition: hash.h:4
int num_blocks
Definition: globals.c:30
struct s_block * block
Definition: globals.c:31
messagelogger vpr_printf
Definition: util.c:17
struct s_hash * insert_in_hash_table(struct s_hash **hash_table, char *name, int next_free_index)
Definition: hash.c:76
Definition: hash.h:3

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void check_netlist ( void  )

Definition at line 37 of file check_netlist.c.

37  {
38  int i, error, num_conn;
39  struct s_hash **net_hash_table, *h_net_ptr;
40 
41  /* TODO: Remove the following the function calls after these functions have
42  been fleshed and are legitimately used in the code!!! They are called here so that
43  the compiler will not throw an error for an unused function */
44 
45  int unused_var;
46  unused_var = check_subblock_internal_nets(0, 0);
47  unused_var = check_primitives(0, 0);
48  if (unused_var)
49  vpr_printf(TIO_MESSAGE_INFO, "Please go to the check_netlist() function in check_netlist.c and remove the first section as needed.");
50 
51  /* This routine checks that the netlist makes sense */
52 
53  net_hash_table = alloc_hash_table();
54 
55  error = 0;
56 
57  /* Check that nets fanout and have a driver. */
58  for (i = 0; i < num_nets; i++) {
59  h_net_ptr = insert_in_hash_table(net_hash_table, clb_net[i].name, i);
60  if (h_net_ptr->count != 1) {
61  vpr_printf(TIO_MESSAGE_ERROR, "Net %s has multiple drivers.\n", clb_net[i].name);
62  error++;
63  }
65  if (error >= ERROR_THRESHOLD) {
66  vpr_printf(TIO_MESSAGE_ERROR, "Too many errors in netlist, exiting.\n");
67  }
68  }
69  free_hash_table(net_hash_table);
70 
71  /* Check that each block makes sense. */
72  for (i = 0; i < num_blocks; i++) {
73  num_conn = get_num_conn(i);
74  error += check_clb_conn(i, num_conn);
75  error += check_clb_internal_nets(i);
76  error += check_subblocks(i);
77  if (error >= ERROR_THRESHOLD) {
78  vpr_printf(TIO_MESSAGE_ERROR, "Too many errors in netlist, exiting.\n");
79  exit(1);
80  }
81  }
82 
83  error += check_for_duplicated_names();
84 
85  if (error != 0) {
86  vpr_printf(TIO_MESSAGE_ERROR, "Found %d fatal Errors in the input netlist.\n", error);
87  exit(1);
88  }
89 
90  /* HACK: Jason Luu January 17, 2011 Do not route common constants gnd and vcc
91  Todo: Need to make architecture driven.
92  */
93  for (i = 0; i < num_nets; i++) {
94  if (strcmp(clb_net[i].name, "vcc") == 0) {
95  clb_net[i].is_global = TRUE;
96  } else if (strcmp(clb_net[i].name, "gnd") == 0) {
97  clb_net[i].is_global = TRUE;
98  }
99  }
100 }
struct s_hash ** alloc_hash_table(void)
Definition: hash.c:7
int count
Definition: hash.h:6
static int check_subblock_internal_nets(int iblk, int isub)
char * name
Definition: hash.h:4
int num_nets
Definition: globals.c:27
int num_blocks
Definition: globals.c:30
#define ERROR_THRESHOLD
Definition: check_netlist.c:15
void free_hash_table(struct s_hash **hash_table)
Definition: hash.c:18
struct s_net * clb_net
Definition: globals.c:28
boolean is_global
Definition: vpr_types.h:510
static int check_subblocks(int iblk)
static int check_for_duplicated_names(void)
static int check_connections_to_global_clb_pins(int inet)
static int get_num_conn(int bnum)
static int check_primitives(int iblk, int isub)
messagelogger vpr_printf
Definition: util.c:17
struct s_hash * insert_in_hash_table(struct s_hash **hash_table, char *name, int next_free_index)
Definition: hash.c:76
static int check_clb_internal_nets(int iblk)
Definition: hash.h:3
Definition: util.h:12
static int check_clb_conn(int iblk, int num_conn)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int check_primitives ( int  iblk,
int  isub 
)
static

Definition at line 241 of file check_netlist.c.

241  {
242 
243  /* TODO:
244  This routine checks the subblocks of iblk (which must be a CLB). It *
245  * returns the number of errors found. */
246  return 0;
247 
248 }

+ Here is the caller graph for this function:

static int check_subblock_internal_nets ( int  iblk,
int  isub 
)
static

TODO Check if the internal CLB nets makes sense and are connected properly Consists of 3 main checks

  1. a) Check name uniqueness b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
  2. Check all connected CLB pins are connected to valid internal nets
  3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes

Definition at line 221 of file check_netlist.c.

221  {
222  /**
223  * TODO
224  * Check if the internal CLB nets makes sense and are connected properly
225  * Consists of 3 main checks
226  * 1. a) Check name uniqueness
227  b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
228  * 2. Check all connected CLB pins are connected to valid internal nets
229  * 3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes
230  */
231  return 0;
232 }

+ Here is the caller graph for this function:

static int check_subblocks ( int  iblk)
static

Definition at line 234 of file check_netlist.c.

234  {
235  /* TODO */
236  /* This routine checks the subblocks of iblk (which must be a CLB). It *
237  * returns the number of errors found. */
238  return 0;
239 }

+ Here is the caller graph for this function:

static int get_num_conn ( int  bnum)
static

Definition at line 302 of file check_netlist.c.

302  {
303 
304  /* This routine returns the number of connections to a block. */
305 
306  int i, num_conn;
307  t_type_ptr type;
308 
309  type = block[bnum].type;
310 
311  num_conn = 0;
312 
313  for (i = 0; i < type->num_pins; i++) {
314  if (block[bnum].nets[i] != OPEN)
315  num_conn++;
316  }
317 
318  return (num_conn);
319 }
t_type_ptr type
Definition: vpr_types.h:561
struct s_block * block
Definition: globals.c:31
Definition: slre.c:50

+ Here is the caller graph for this function: