VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
cluster.h File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void do_clustering (const t_arch *arch, t_pack_molecule *molecule_head, int num_models, boolean global_clocks, boolean *is_clock, boolean hill_climbing_flag, char *out_fname, boolean timing_driven, enum e_cluster_seed cluster_seed_type, float alpha, float beta, int recompute_timing_after, float block_delay, float intra_cluster_net_delay, float inter_cluster_net_delay, float aspect, boolean allow_unrelated_clustering, boolean allow_early_exit, boolean connection_driven, enum e_packer_algorithm packer_algorithm, t_timing_inf timing_inf)
 
int get_cluster_of_block (int blkidx)
 

Function Documentation

void do_clustering ( const t_arch arch,
t_pack_molecule molecule_head,
int  num_models,
boolean  global_clocks,
boolean is_clock,
boolean  hill_climbing_flag,
char *  out_fname,
boolean  timing_driven,
enum e_cluster_seed  cluster_seed_type,
float  alpha,
float  beta,
int  recompute_timing_after,
float  block_delay,
float  intra_cluster_net_delay,
float  inter_cluster_net_delay,
float  aspect,
boolean  allow_unrelated_clustering,
boolean  allow_early_exit,
boolean  connection_driven,
enum e_packer_algorithm  packer_algorithm,
t_timing_inf  timing_inf 
)

Definition at line 232 of file cluster.c.

240  {
241 
242  /* Does the actual work of clustering multiple netlist blocks *
243  * into clusters. */
244 
245  /* Algorithm employed
246  1. Find type that can legally hold block and create cluster with pb info
247  2. Populate started cluster
248  3. Repeat 1 until no more blocks need to be clustered
249 
250  */
251 
252  int i, iblk, num_molecules, blocks_since_last_analysis, num_clb, max_nets_in_pb_type,
253  cur_nets_in_pb_type, num_blocks_hill_added, max_cluster_size, cur_cluster_size,
254  max_molecule_inputs, max_pb_depth, cur_pb_depth, num_unrelated_clustering_attempts,
255  indexofcrit, savedindexofcrit /* index of next most timing critical block */,
256  detailed_routing_stage, *hill_climbing_inputs_avail;
257 
258  int *num_used_instances_type, *num_instances_type;
259  /* [0..num_types] Holds array for total number of each cluster_type available */
260 
261  boolean early_exit, is_cluster_legal;
262  enum e_block_pack_status block_pack_status;
263  float crit;
264 
265  t_cluster_placement_stats *cluster_placement_stats, *cur_cluster_placement_stats_ptr;
266  t_pb_graph_node **primitives_list;
267  t_block *clb;
268  t_slack * slacks = NULL;
269  t_pack_molecule *istart, *next_molecule, *prev_molecule, *cur_molecule;
270 
271 #ifdef PATH_COUNTING
272  int inet, ipin;
273 #else
274  int inode;
275  float num_paths_scaling, distance_scaling;
276 #endif
277 
278  /* TODO: This is memory inefficient, fix if causes problems */
279  clb = (t_block*)my_calloc(num_logical_blocks, sizeof(t_block));
280  num_clb = 0;
281  istart = NULL;
282 
283  /* determine bound on cluster size and primitive input size */
284  max_cluster_size = 0;
285  max_molecule_inputs = 0;
286  max_pb_depth = 0;
287  max_nets_in_pb_type = 0;
288 
289  indexofcrit = 0;
290 
291  cur_molecule = molecule_head;
292  num_molecules = 0;
293  while (cur_molecule != NULL) {
294  cur_molecule->valid = TRUE;
295  if (cur_molecule->num_ext_inputs > max_molecule_inputs) {
296  max_molecule_inputs = cur_molecule->num_ext_inputs;
297  }
298  num_molecules++;
299  cur_molecule = cur_molecule->next;
300  }
301 
302  for (i = 0; i < num_types; i++) {
303  if (EMPTY_TYPE == &type_descriptors[i])
304  continue;
305  cur_cluster_size = get_max_primitives_in_pb_type(
306  type_descriptors[i].pb_type);
307  cur_pb_depth = get_max_depth_of_pb_type(type_descriptors[i].pb_type);
308  cur_nets_in_pb_type = get_max_nets_in_pb_type(
309  type_descriptors[i].pb_type);
310  if (cur_cluster_size > max_cluster_size) {
311  max_cluster_size = cur_cluster_size;
312  }
313  if (cur_pb_depth > max_pb_depth) {
314  max_pb_depth = cur_pb_depth;
315  }
316  if (cur_nets_in_pb_type > max_nets_in_pb_type) {
317  max_nets_in_pb_type = cur_nets_in_pb_type;
318  }
319  }
320 
321  if (hill_climbing_flag) {
322  hill_climbing_inputs_avail = (int *) my_calloc(max_cluster_size + 1,
323  sizeof(int));
324  } else {
325  hill_climbing_inputs_avail = NULL; /* if used, die hard */
326  }
327 
328  /* TODO: make better estimate for nx and ny */
329  nx = ny = 1;
330 
331  check_clocks(is_clock);
332 #if 0
333  check_for_duplicate_inputs ();
334 #endif
335  alloc_and_init_clustering(global_clocks, alpha, beta, max_cluster_size,
336  max_molecule_inputs, max_pb_depth, num_models,
337  &cluster_placement_stats, &primitives_list, molecule_head,
338  num_molecules);
339 
340  blocks_since_last_analysis = 0;
341  early_exit = FALSE;
342  num_blocks_hill_added = 0;
343  num_used_instances_type = (int*) my_calloc(num_types, sizeof(int));
344  num_instances_type = (int*) my_calloc(num_types, sizeof(int));
345 
346  assert(max_cluster_size < MAX_SHORT);
347  /* Limit maximum number of elements for each cluster */
348 
349  if (timing_driven) {
350  slacks = alloc_and_load_pre_packing_timing_graph(block_delay,
351  inter_cluster_net_delay, arch->models, timing_inf);
352  do_timing_analysis(slacks, TRUE, FALSE, FALSE);
353 
354  if (getEchoEnabled()) {
357 #ifndef PATH_COUNTING
360 #endif
365  }
366 
367  block_criticality = (float*) my_calloc(num_logical_blocks, sizeof(float));
368 
369  critindexarray = (int*) my_malloc(num_logical_blocks * sizeof(int));
370 
371  for (i = 0; i < num_logical_blocks; i++) {
372  assert(logical_block[i].index == i);
373  critindexarray[i] = i;
374  }
375 
376 #ifdef PATH_COUNTING
377  /* Calculate block criticality from a weighted sum of timing and path criticalities. */
378  for (inet = 0; inet < num_logical_nets; inet++) {
379  for (ipin = 1; ipin <= vpack_net[inet].num_sinks; ipin++) {
380 
381  /* Find the logical block iblk which this pin is a sink on. */
382  iblk = vpack_net[inet].node_block[ipin];
383 
384  /* The criticality of this pin is a sum of its timing and path criticalities. */
385  crit = PACK_PATH_WEIGHT * slacks->path_criticality[inet][ipin]
386  + (1 - PACK_PATH_WEIGHT) * slacks->timing_criticality[inet][ipin];
387 
388  /* The criticality of each block is the maximum of the criticalities of all its pins. */
389  if (block_criticality[iblk] < crit) {
390  block_criticality[iblk] = crit;
391  }
392  }
393  }
394 
395 #else
396  /* Calculate criticality based on slacks and tie breakers (# paths, distance from source) */
397  for (inode = 0; inode < num_tnodes; inode++) {
398  /* Only calculate for tnodes which have valid normalized values.
399  Either all values will be accurate or none will, so we only have
400  to check whether one particular value (normalized_T_arr) is valid
401  Tnodes that do not have both times valid were not part of the analysis.
402  Because we calloc-ed the array criticality, such nodes will have criticality 0, the lowest possible value. */
403  if (has_valid_normalized_T_arr(inode)) {
404  iblk = tnode[inode].block;
405  num_paths_scaling = SCALE_NUM_PATHS
406  * (float) tnode[inode].prepacked_data->normalized_total_critical_paths;
407  distance_scaling = SCALE_DISTANCE_VAL
408  * (float) tnode[inode].prepacked_data->normalized_T_arr;
409  crit = (1 - tnode[inode].prepacked_data->normalized_slack) + num_paths_scaling
410  + distance_scaling;
411  if (block_criticality[iblk] < crit) {
412  block_criticality[iblk] = crit;
413  }
414  }
415  }
416 #endif
417  heapsort(critindexarray, block_criticality, num_logical_blocks, 1);
418 
421  }
422 
423 
424  if (cluster_seed_type == VPACK_TIMING) {
425  istart = get_most_critical_seed_molecule(&indexofcrit);
426  } else {/*max input seed*/
428  max_molecule_inputs);
429  }
430 
431  } else /*cluster seed is max input (since there is no timing information)*/ {
433  max_molecule_inputs);
434  }
435 
436 
437  while (istart != NULL) {
438  is_cluster_legal = FALSE;
439  savedindexofcrit = indexofcrit;
440  for (detailed_routing_stage = (int)E_DETAILED_ROUTE_AT_END_ONLY; !is_cluster_legal && detailed_routing_stage != (int)E_DETAILED_ROUTE_END; detailed_routing_stage++) {
441  reset_legalizer_for_cluster(&clb[num_clb]);
442 
443  /* start a new cluster and reset all stats */
444  start_new_cluster(cluster_placement_stats, primitives_list, arch,
445  &clb[num_clb], num_clb, istart, aspect, num_used_instances_type,
446  num_instances_type, num_models, max_cluster_size,
447  max_nets_in_pb_type, detailed_routing_stage);
448  vpr_printf(TIO_MESSAGE_INFO, "Complex block %d: %s, type: %s\n",
449  num_clb, clb[num_clb].name, clb[num_clb].type->name);
450  vpr_printf(TIO_MESSAGE_INFO, "\t");
451  fflush(stdout);
452  update_cluster_stats(istart, num_clb, is_clock, global_clocks, alpha,
453  beta, timing_driven, connection_driven, slacks);
454  num_clb++;
455 
456  if (timing_driven && !early_exit) {
457  blocks_since_last_analysis++;
458  /*it doesn't make sense to do a timing analysis here since there*
459  *is only one logical_block clustered it would not change anything */
460  }
461  cur_cluster_placement_stats_ptr = &cluster_placement_stats[clb[num_clb
462  - 1].type->index];
463  num_unrelated_clustering_attempts = 0;
465  clb[num_clb - 1].pb, allow_unrelated_clustering,
466  &num_unrelated_clustering_attempts,
467  cur_cluster_placement_stats_ptr);
468  prev_molecule = istart;
469  while (next_molecule != NULL && prev_molecule != next_molecule) {
470  block_pack_status = try_pack_molecule(
471  cur_cluster_placement_stats_ptr, next_molecule,
472  primitives_list, clb[num_clb - 1].pb, num_models,
473  max_cluster_size, num_clb - 1, max_nets_in_pb_type, detailed_routing_stage);
474  prev_molecule = next_molecule;
475  if (block_pack_status != BLK_PASSED) {
476  if (next_molecule != NULL) {
477  if (block_pack_status == BLK_FAILED_ROUTE) {
478 #ifdef DEBUG_FAILED_PACKING_CANDIDATES
479  vpr_printf(TIO_MESSAGE_DIRECT, "\tNO_ROUTE:%s type %s/n",
480  next_molecule->logical_block_ptrs[next_molecule->root]->name,
481  next_molecule->logical_block_ptrs[next_molecule->root]->model->name);
482  fflush(stdout);
483  #else
484  vpr_printf(TIO_MESSAGE_DIRECT, ".");
485  #endif
486  } else {
487  #ifdef DEBUG_FAILED_PACKING_CANDIDATES
488  vpr_printf(TIO_MESSAGE_DIRECT, "\tFAILED_CHECK:%s type %s check %d\n",
489  next_molecule->logical_block_ptrs[next_molecule->root]->name,
490  next_molecule->logical_block_ptrs[next_molecule->root]->model->name,
491  block_pack_status);
492  fflush(stdout);
493  #else
494  vpr_printf(TIO_MESSAGE_DIRECT, ".");
495  #endif
496  }
497  }
498 
500  clb[num_clb - 1].pb, allow_unrelated_clustering,
501  &num_unrelated_clustering_attempts,
502  cur_cluster_placement_stats_ptr);
503  continue;
504  } else {
505  /* Continue packing by filling smallest cluster */
506  #ifdef DEBUG_FAILED_PACKING_CANDIDATES
507  vpr_printf(TIO_MESSAGE_DIRECT, "\tPASSED:%s type %s\n",
508  next_molecule->logical_block_ptrs[next_molecule->root]->name,
509  next_molecule->logical_block_ptrs[next_molecule->root]->model->name);
510  fflush(stdout);
511  #else
512  vpr_printf(TIO_MESSAGE_DIRECT, ".");
513  #endif
514  }
515  update_cluster_stats(next_molecule, num_clb - 1, is_clock,
516  global_clocks, alpha, beta, timing_driven,
517  connection_driven, slacks);
518  num_unrelated_clustering_attempts = 0;
519 
520  if (timing_driven && !early_exit) {
521  blocks_since_last_analysis++; /* historically, timing slacks were recomputed after X number of blocks were packed, but this doesn't significantly alter results so I (jluu) did not port the code */
522  }
524  clb[num_clb - 1].pb, allow_unrelated_clustering,
525  &num_unrelated_clustering_attempts,
526  cur_cluster_placement_stats_ptr);
527  }
528  vpr_printf(TIO_MESSAGE_DIRECT, "\n");
529  if (detailed_routing_stage == (int)E_DETAILED_ROUTE_AT_END_ONLY) {
530  is_cluster_legal = try_breadth_first_route_cluster();
531  if (is_cluster_legal == TRUE) {
532  vpr_printf(TIO_MESSAGE_INFO, "Passed route at end.\n");
533  } else {
534  vpr_printf(TIO_MESSAGE_INFO, "Failed route at end, repack cluster trying detailed routing at each stage.\n");
535  }
536  } else {
537  is_cluster_legal = TRUE;
538  }
539  if (is_cluster_legal == TRUE) {
541  if (timing_driven) {
542  if (num_blocks_hill_added > 0 && !early_exit) {
543  blocks_since_last_analysis += num_blocks_hill_added;
544  }
545  if (cluster_seed_type == VPACK_TIMING) {
546  istart = get_most_critical_seed_molecule(&indexofcrit);
547  } else { /*max input seed*/
549  max_molecule_inputs);
550  }
551  } else
552  /*cluster seed is max input (since there is no timing information)*/
554  max_molecule_inputs);
555 
556  free_pb_stats_recursive(clb[num_clb - 1].pb);
557  } else {
558  /* Free up data structures and requeue used molecules */
559  num_used_instances_type[clb[num_clb - 1].type->index]--;
560  free_cb(clb[num_clb - 1].pb);
561  free(clb[num_clb - 1].pb);
562  free(clb[num_clb - 1].name);
563  clb[num_clb - 1].name = NULL;
564  clb[num_clb - 1].pb = NULL;
565  num_clb--;
566  indexofcrit = savedindexofcrit;
567  }
568  }
569  }
570 
572 
573  alloc_and_load_cluster_info(num_clb, clb);
574 
575  check_clustering(num_clb, clb, is_clock);
576 
577  output_clustering(clb, num_clb, global_clocks, is_clock, out_fname, FALSE);
579  output_blif (clb, num_clb, global_clocks, is_clock,
581  }
582 
583  if (hill_climbing_flag) {
584  free(hill_climbing_inputs_avail);
585  }
586  free_cluster_placement_stats(cluster_placement_stats);
587 
588  for (i = 0; i < num_clb; i++) {
589  free_cb(clb[i].pb);
590  free(clb[i].name);
591  free(clb[i].nets);
592  free(clb[i].pb);
593  }
594  free(clb);
595 
596  free(num_used_instances_type);
597  free(num_instances_type);
598  free(unclustered_list_head);
599  free(memory_pool);
601 
602  if (timing_driven) {
603  free(block_criticality);
604  free(critindexarray);
605 
606  block_criticality = NULL;
607  critindexarray = NULL;
608  }
609 
610  if (timing_driven) {
611  free_timing_graph(slacks);
612  }
613 
614  free (primitives_list);
615 
616 }
int get_max_depth_of_pb_type(t_pb_type *pb_type)
Definition: vpr_utils.c:222
static int * critindexarray
Definition: cluster.c:108
void free_cluster_legality_checker(void)
static void check_clustering(int num_clb, t_block *clb, boolean *is_clock)
Definition: cluster.c:2241
void heapsort(int *sort_index, float *sort_values, int nelem, int start_index)
Definition: heapsort.c:13
int get_max_nets_in_pb_type(const t_pb_type *pb_type)
Definition: vpr_utils.c:196
t_type_ptr EMPTY_TYPE
Definition: globals.c:41
int num_tnodes
Definition: path_delay.c:144
t_model * models
#define SCALE_DISTANCE_VAL
Definition: cluster.c:47
static t_pack_molecule * get_molecule_for_cluster(INP enum e_packer_algorithm packer_algorithm, INP t_pb *cur_pb, INP boolean allow_unrelated_clustering, INOUTP int *num_unrelated_clustering_attempts, INP t_cluster_placement_stats *cluster_placement_stats_ptr)
int get_max_primitives_in_pb_type(t_pb_type *pb_type)
Definition: vpr_utils.c:173
static void start_new_cluster(INP t_cluster_placement_stats *cluster_placement_stats, INP t_pb_graph_node **primitives_list, INP const t_arch *arch, INOUTP t_block *new_cluster, INP int clb_index, INP t_pack_molecule *molecule, INP float aspect, INOUTP int *num_used_instances_type, INOUTP int *num_instances_type, INP int num_models, INP int max_cluster_size, INP int max_nets_in_pb_type, INP int detailed_routing_stage)
void free_cluster_placement_stats(INOUTP t_cluster_placement_stats *cluster_placement_stats_list)
static t_pack_molecule * get_seed_logical_molecule_with_most_ext_inputs(int max_molecule_inputs)
Definition: cluster.c:1055
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
void free_cb(t_pb *pb)
Definition: vpr_utils.c:508
static int * net_output_feeds_driving_block_input
Definition: cluster.c:103
int * node_block
Definition: vpr_types.h:507
int num_logical_nets
Definition: globals.c:17
void do_timing_analysis(t_slack *slacks, boolean is_prepacked, boolean do_lut_input_balancing, boolean is_final_analysis)
Definition: path_delay.c:1613
void print_clustering_timing_info(const char *fname)
Definition: path_delay.c:696
float ** slack
Definition: vpr_types.h:405
t_type_ptr type
Definition: vpr_types.h:561
#define MAX_SHORT
Definition: vpr_types.h:75
void reset_legalizer_for_cluster(t_block *clb)
void output_blif(t_block *clb, int num_clusters, boolean global_clocks, boolean *is_clock, const char *out_fname, boolean skip_clustering)
Definition: output_blif.c:489
boolean getEchoEnabled(void)
Definition: ReadOptions.c:67
char * name
Definition: vpr_types.h:560
t_prepacked_tnode_data * prepacked_data
Definition: vpr_types.h:361
Definition: util.h:12
static struct s_molecule_link * unclustered_list_head
Definition: cluster.c:92
static void alloc_and_init_clustering(boolean global_clocks, float alpha, float beta, int max_cluster_size, int max_molecule_inputs, int max_pb_depth, int max_models, t_cluster_placement_stats **cluster_placement_stats, t_pb_graph_node ***primitives_list, t_pack_molecule *molecules_head, int num_molecules)
Definition: cluster.c:715
static float * block_criticality
Definition: cluster.c:107
boolean try_breadth_first_route_cluster(void)
#define SCALE_NUM_PATHS
Definition: cluster.c:38
static void check_clocks(boolean *is_clock)
Definition: cluster.c:619
t_slack * alloc_and_load_pre_packing_timing_graph(float block_delay, float inter_cluster_net_delay, t_model *models, t_timing_inf timing_inf)
Definition: path_delay.c:288
int block
Definition: vpr_types.h:346
static void free_pb_stats_recursive(t_pb *pb)
Definition: cluster.c:805
static void * my_malloc(int ibytes)
Definition: graphics.c:499
t_tnode * tnode
Definition: path_delay.c:143
void output_clustering(t_block *clb, int num_clusters, boolean global_clocks, boolean *is_clock, char *out_fname, boolean skip_clustering)
static t_pack_molecule * get_most_critical_seed_molecule(int *indexofcrit)
Definition: cluster.c:2327
int nx
Definition: globals.c:46
boolean has_valid_normalized_T_arr(int inode)
Definition: path_delay.c:3054
static enum e_block_pack_status try_pack_molecule(INOUTP t_cluster_placement_stats *cluster_placement_stats_ptr, INP t_pack_molecule *molecule, INOUTP t_pb_graph_node **primitives_list, INOUTP t_pb *pb, INP int max_models, INP int max_cluster_size, INP int clb_index, INP int max_nets_in_pb_type, INP int detailed_routing_stage)
Definition: cluster.c:1174
static void print_block_criticalities(const char *fname)
Definition: cluster.c:2908
boolean isEchoFileEnabled(enum e_echo_files echo_option)
Definition: ReadOptions.c:115
e_block_pack_status
Definition: vpr_types.h:116
struct s_pack_molecule * next
Definition: vpr_types.h:257
void print_criticality(t_slack *slacks, boolean criticality_is_normalized, const char *fname)
Definition: path_delay.c:559
static struct s_molecule_link * memory_pool
Definition: cluster.c:94
int num_types
Definition: globals.c:37
char * name
Definition: logic_types.h:34
float ** timing_criticality
Definition: vpr_types.h:406
int num_logical_blocks
Definition: globals.c:17
void print_slack(float **slack, boolean slack_is_normalized, const char *fname)
Definition: path_delay.c:441
void print_timing_graph(const char *fname)
Definition: path_delay.c:1388
struct s_type_descriptor * type_descriptors
Definition: globals.c:38
struct s_net * vpack_net
Definition: globals.c:19
char * getEchoFileName(enum e_echo_files echo_option)
Definition: ReadOptions.c:122
t_logical_block ** logical_block_ptrs
Definition: vpr_types.h:248
static void alloc_and_load_cluster_info(INP int num_clb, INOUTP t_block *clb)
Definition: cluster.c:2176
t_model * model
Definition: vpr_types.h:209
int ny
Definition: globals.c:47
void save_cluster_solution(void)
messagelogger vpr_printf
Definition: util.c:17
void free_timing_graph(t_slack *slacks)
Definition: path_delay.c:390
int num_sinks
Definition: vpr_types.h:506
boolean valid
Definition: vpr_types.h:249
struct s_logical_block * logical_block
Definition: globals.c:20
Definition: util.h:12
static void update_cluster_stats(INP t_pack_molecule *molecule, INP int clb_index, INP boolean *is_clock, INP boolean global_clocks, INP float alpha, INP float beta, INP boolean timing_driven, INP boolean connection_driven, INP t_slack *slacks)
Definition: cluster.c:1774

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int get_cluster_of_block ( int  blkidx)