VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
cluster_placement.h File Reference
#include "arch_types.h"
#include "util.h"
+ Include dependency graph for cluster_placement.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

t_cluster_placement_statsalloc_and_load_cluster_placement_stats (void)
 
boolean get_next_primitive_list (INOUTP t_cluster_placement_stats *cluster_placement_stats, INP t_pack_molecule *molecule, INOUTP t_pb_graph_node **primitives_list, INP int clb_index)
 
void commit_primitive (INOUTP t_cluster_placement_stats *cluster_placement_stats, INP t_pb_graph_node *primitive)
 
void set_mode_cluster_placement_stats (INP t_pb_graph_node *complex_block, int mode)
 
void reset_cluster_placement_stats (INOUTP t_cluster_placement_stats *cluster_placement_stats)
 
void free_cluster_placement_stats (INOUTP t_cluster_placement_stats *cluster_placement_stats)
 
int get_array_size_of_molecule (t_pack_molecule *molecule)
 
boolean exists_free_primitive_for_logical_block (INOUTP t_cluster_placement_stats *cluster_placement_stats, INP int ilogical_block)
 
void reset_tried_but_unused_cluster_placements (INOUTP t_cluster_placement_stats *cluster_placement_stats)
 

Function Documentation

t_cluster_placement_stats* alloc_and_load_cluster_placement_stats ( void  )

[0..num_pb_types-1] array of cluster placement stats, one for each type_descriptors

Definition at line 56 of file cluster_placement.c.

56  {
57  t_cluster_placement_stats *cluster_placement_stats_list;
58  int i;
59 
60  cluster_placement_stats_list = (t_cluster_placement_stats *) my_calloc(num_types,
62  for (i = 0; i < num_types; i++) {
63  if (EMPTY_TYPE != &type_descriptors[i]) {
64  cluster_placement_stats_list[i].valid_primitives = (t_cluster_placement_primitive **) my_calloc(
66  + 1, sizeof(t_cluster_placement_primitive*)); /* too much memory allocated but shouldn't be a problem */
67  cluster_placement_stats_list[i].curr_molecule = NULL;
69  &cluster_placement_stats_list[i],
70  type_descriptors[i].pb_graph_head);
71  }
72  }
73  return cluster_placement_stats_list;
74 }
t_type_ptr EMPTY_TYPE
Definition: globals.c:41
int get_max_primitives_in_pb_type(t_pb_type *pb_type)
Definition: vpr_utils.c:173
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
t_pack_molecule * curr_molecule
Definition: vpr_types.h:266
int num_types
Definition: globals.c:37
t_cluster_placement_primitive ** valid_primitives
Definition: vpr_types.h:267
struct s_type_descriptor * type_descriptors
Definition: globals.c:38
static void load_cluster_placement_stats_for_pb_graph_node(INOUTP t_cluster_placement_stats *cluster_placement_stats, INOUTP t_pb_graph_node *pb_graph_node)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void commit_primitive ( INOUTP t_cluster_placement_stats cluster_placement_stats,
INP t_pb_graph_node primitive 
)

Commit primitive, invalidate primitives blocked by mode assignment and update costs for primitives in same cluster as current Costing is done to try to pack blocks closer to existing primitives actual value based on closest common ancestor to committed placement, the farther the ancestor, the less reduction in cost there is Side effects: All cluster_placement_primitives may be invalidated/costed in this algorithm Al intermediate queues are requeued

Definition at line 347 of file cluster_placement.c.

348  {
349  t_pb_graph_node *pb_graph_node, *skip;
350  float incr_cost;
351  int i, j, k;
352  int valid_mode;
354 
355  /* Clear out intermediate queues */
356  flush_intermediate_queues(cluster_placement_stats);
357 
358  /* commit primitive as used, invalidate it */
359  cur = primitive->cluster_placement_primitive;
360  assert(cur->valid == TRUE);
361 
362  cur->valid = FALSE;
363  incr_cost = -0.01; /* cost of using a node drops as its neighbours are used, this drop should be small compared to scarcity values */
364 
365  pb_graph_node = cur->pb_graph_node;
366  /* walk up pb_graph_node and update primitives of children */
367  while (pb_graph_node->parent_pb_graph_node != NULL) {
368  skip = pb_graph_node; /* do not traverse stuff that's already traversed */
369  valid_mode = pb_graph_node->pb_type->parent_mode->index;
370  pb_graph_node = pb_graph_node->parent_pb_graph_node;
371  for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
372  for (j = 0;
373  j < pb_graph_node->pb_type->modes[i].num_pb_type_children;
374  j++) {
375  for (k = 0;
376  k
377  < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb;
378  k++) {
379  if (&pb_graph_node->child_pb_graph_nodes[i][j][k] != skip) {
381  &pb_graph_node->child_pb_graph_nodes[i][j][k],
382  incr_cost, (boolean)(i == valid_mode));
383  }
384  }
385  }
386  }
387  incr_cost /= 10; /* blocks whose ancestor is further away in tree should be affected less than blocks closer in tree */
388  }
389 }
struct s_pb_type * pb_type_children
struct s_pb_graph_node * parent_pb_graph_node
t_mode * modes
static void update_primitive_cost_or_status(INP t_pb_graph_node *pb_graph_node, INP float incremental_cost, INP boolean valid)
Definition: util.h:12
t_mode * parent_mode
static void flush_intermediate_queues(INOUTP t_cluster_placement_stats *cluster_placement_stats)
struct s_pb_graph_node *** child_pb_graph_nodes
int num_pb_type_children
struct s_pb_type * pb_type
t_pb_graph_node * pb_graph_node
Definition: cad_types.h:57
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

boolean exists_free_primitive_for_logical_block ( INOUTP t_cluster_placement_stats cluster_placement_stats,
INP int  ilogical_block 
)

Definition at line 701 of file cluster_placement.c.

703  {
704  int i;
705  t_cluster_placement_primitive *cur, *prev;
706 
707  /* might have a primitive in flight that's still valid */
708  if (cluster_placement_stats->in_flight) {
709  if (primitive_type_feasible(ilogical_block,
710  cluster_placement_stats->in_flight->pb_graph_node->pb_type)) {
711  return TRUE;
712  }
713  }
714 
715  /* Look through list of available primitives to see if any valid */
716  for (i = 0; i < cluster_placement_stats->num_pb_types; i++) {
717  if (cluster_placement_stats->valid_primitives[i]->next_primitive == NULL) {
718  continue; /* no more primitives of this type available */
719  }
720  if (primitive_type_feasible(ilogical_block,
721  cluster_placement_stats->valid_primitives[i]->next_primitive->pb_graph_node->pb_type)) {
722  prev = cluster_placement_stats->valid_primitives[i];
723  cur = cluster_placement_stats->valid_primitives[i]->next_primitive;
724  while (cur) {
725  /* remove invalid nodes lazily when encountered */
726  while (cur && cur->valid == FALSE) {
727  prev->next_primitive = cur->next_primitive;
728  cur->next_primitive = cluster_placement_stats->invalid;
729  cluster_placement_stats->invalid = cur;
730  cur = prev->next_primitive;
731  }
732  if (cur == NULL) {
733  break;
734  }
735  return TRUE;
736  }
737  }
738  }
739 
740  return FALSE;
741 }
boolean primitive_type_feasible(int iblk, const t_pb_type *cur_pb_type)
Definition: vpr_utils.c:241
Definition: util.h:12
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void free_cluster_placement_stats ( INOUTP t_cluster_placement_stats cluster_placement_stats_list)

Free linked lists found in cluster_placement_stats_list

Definition at line 214 of file cluster_placement.c.

215  {
216  t_cluster_placement_primitive *cur, *next;
217  int i, j;
218  for (i = 0; i < num_types; i++) {
219  cur = cluster_placement_stats_list[i].tried;
220  while (cur != NULL) {
221  next = cur->next_primitive;
222  free(cur);
223  cur = next;
224  }
225  cur = cluster_placement_stats_list[i].in_flight;
226  while (cur != NULL) {
227  next = cur->next_primitive;
228  free(cur);
229  cur = next;
230  }
231  cur = cluster_placement_stats_list[i].invalid;
232  while (cur != NULL) {
233  next = cur->next_primitive;
234  free(cur);
235  cur = next;
236  }
237  for (j = 0; j < cluster_placement_stats_list[i].num_pb_types; j++) {
238  cur =
239  cluster_placement_stats_list[i].valid_primitives[j]->next_primitive;
240  while (cur != NULL) {
241  next = cur->next_primitive;
242  free(cur);
243  cur = next;
244  }
245  free(cluster_placement_stats_list[i].valid_primitives[j]);
246  }
247  free(cluster_placement_stats_list[i].valid_primitives);
248  }
249  free(cluster_placement_stats_list);
250 }
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
int num_types
Definition: globals.c:37

+ Here is the caller graph for this function:

int get_array_size_of_molecule ( t_pack_molecule molecule)

Definition at line 692 of file cluster_placement.c.

692  {
693  if (molecule->type == MOLECULE_FORCED_PACK) {
694  return molecule->pack_pattern->num_blocks;
695  } else {
696  return molecule->num_blocks;
697  }
698 }
t_pack_patterns * pack_pattern
Definition: vpr_types.h:246
enum e_pack_pattern_molecule_type type
Definition: vpr_types.h:245

+ Here is the caller graph for this function:

boolean get_next_primitive_list ( INOUTP t_cluster_placement_stats cluster_placement_stats,
INP t_pack_molecule molecule,
INOUTP t_pb_graph_node **  primitives_list,
INP int  clb_index 
)

get next list of primitives for list of logical blocks primitives is the list of ptrs to primitives that matches with the list of logical_blocks (by index), assumes memory is preallocated

  • if this is a new block, requeue tried primitives and return a in-flight primitive list to try
  • if this is an old block, put root primitive to tried queue, requeue rest of primitives. try another set of primitives

return TRUE if can find next primitive, FALSE otherwise

cluster_placement_stats - ptr to the current cluster_placement_stats of open complex block molecule - molecule to pack into open complex block primitives_list - a list of primitives indexed to match logical_block_ptrs of molecule. Expects an allocated array of primitives ptrs as inputs. This function loads the array with the lowest cost primitives that implement molecule

Definition at line 88 of file cluster_placement.c.

90  {
91  t_cluster_placement_primitive *cur, *next, *best, *before_best, *prev;
92  int i;
93  float cost, lowest_cost;
94  best = NULL;
95  before_best = NULL;
96 
97  if (cluster_placement_stats->curr_molecule != molecule) {
98  /* New block, requeue tried primitives and in-flight primitives */
99  flush_intermediate_queues(cluster_placement_stats);
100 
101  cluster_placement_stats->curr_molecule = molecule;
102  } else {
103  /* Hack! Same failed molecule may re-enter if upper stream functions suck, I'm going to make the molecule selector more intelligent, TODO: Remove later */
104  if (cluster_placement_stats->in_flight != NULL) {
105  /* Hack end */
106 
107  /* old block, put root primitive currently inflight to tried queue */
108  cur = cluster_placement_stats->in_flight;
109  next = cur->next_primitive;
110  cur->next_primitive = cluster_placement_stats->tried;
111  cluster_placement_stats->tried = cur;
112  /* should have only one block in flight at any point in time */
113  assert(next == NULL);
114  cluster_placement_stats->in_flight = NULL;
115  }
116  }
117 
118  /* find next set of blocks
119  1. Remove invalid blocks to invalid queue
120  2. Find lowest cost array of primitives that implements blocks
121  3. When found, move current blocks to in-flight, return lowest cost array of primitives
122  4. Return NULL if not found
123  */
124  lowest_cost = HUGE_POSITIVE_FLOAT;
125  for (i = 0; i < cluster_placement_stats->num_pb_types; i++) {
126  if (cluster_placement_stats->valid_primitives[i]->next_primitive == NULL) {
127  continue; /* no more primitives of this type available */
128  }
130  molecule->logical_block_ptrs[molecule->root]->index,
131  cluster_placement_stats->valid_primitives[i]->next_primitive->pb_graph_node->pb_type)) {
132  prev = cluster_placement_stats->valid_primitives[i];
133  cur = cluster_placement_stats->valid_primitives[i]->next_primitive;
134  while (cur) {
135  /* remove invalid nodes lazily when encountered */
136  while (cur && cur->valid == FALSE) {
137  prev->next_primitive = cur->next_primitive;
138  cur->next_primitive = cluster_placement_stats->invalid;
139  cluster_placement_stats->invalid = cur;
140  cur = prev->next_primitive;
141  }
142  if (cur == NULL) {
143  break;
144  }
145  /* try place molecule at root location cur */
146  cost = try_place_molecule(molecule, cur->pb_graph_node,
147  primitives_list, clb_index);
148  if (cost < lowest_cost) {
149  lowest_cost = cost;
150  best = cur;
151  before_best = prev;
152  }
153  prev = cur;
154  cur = cur->next_primitive;
155  }
156  }
157  }
158  if (best == NULL) {
159  /* failed to find a placement */
160  for (i = 0; i < molecule->num_blocks; i++) {
161  primitives_list[i] = NULL;
162  }
163  } else {
164  /* populate primitive list with best */
165  cost = try_place_molecule(molecule, best->pb_graph_node, primitives_list, clb_index);
166  assert(cost == lowest_cost);
167 
168  /* take out best node and put it in flight */
169  cluster_placement_stats->in_flight = best;
170  before_best->next_primitive = best->next_primitive;
171  best->next_primitive = NULL;
172  }
173 
174  if (best == NULL) {
175  return FALSE;
176  }
177  return TRUE;
178 }
boolean primitive_type_feasible(int iblk, const t_pb_type *cur_pb_type)
Definition: vpr_utils.c:241
static float try_place_molecule(INP t_pack_molecule *molecule, INP t_pb_graph_node *root, INOUTP t_pb_graph_node **primitives_list, INP int clb_index)
Definition: util.h:12
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
static void flush_intermediate_queues(INOUTP t_cluster_placement_stats *cluster_placement_stats)
#define HUGE_POSITIVE_FLOAT
Definition: vpr_types.h:79
t_pb_graph_node * pb_graph_node
Definition: cad_types.h:57
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void reset_cluster_placement_stats ( INOUTP t_cluster_placement_stats cluster_placement_stats)

Resets one cluster placement stats by clearing incremental costs and returning all primitives to valid queue

Definition at line 183 of file cluster_placement.c.

184  {
185  t_cluster_placement_primitive *cur, *next;
186  int i;
187 
188  /* Requeue primitives */
189  flush_intermediate_queues(cluster_placement_stats);
190  cur = cluster_placement_stats->invalid;
191  while (cur != NULL) {
192  next = cur->next_primitive;
193  requeue_primitive(cluster_placement_stats, cur);
194  cur = next;
195  }
196  cur = cluster_placement_stats->invalid = NULL;
197  /* reset flags and cost */
198  for (i = 0; i < cluster_placement_stats->num_pb_types; i++) {
199  assert(
200  cluster_placement_stats->valid_primitives[i] != NULL && cluster_placement_stats->valid_primitives[i]->next_primitive != NULL);
201  cur = cluster_placement_stats->valid_primitives[i]->next_primitive;
202  while (cur != NULL) {
203  cur->incremental_cost = 0;
204  cur->valid = TRUE;
205  cur = cur->next_primitive;
206  }
207  }
208  cluster_placement_stats->curr_molecule = NULL;
209 }
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
static void flush_intermediate_queues(INOUTP t_cluster_placement_stats *cluster_placement_stats)
static void requeue_primitive(INOUTP t_cluster_placement_stats *cluster_placement_stats, t_cluster_placement_primitive *cluster_placement_primitive)
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void reset_tried_but_unused_cluster_placements ( INOUTP t_cluster_placement_stats cluster_placement_stats)

Definition at line 744 of file cluster_placement.c.

745  {
746  flush_intermediate_queues(cluster_placement_stats);
747 }
static void flush_intermediate_queues(INOUTP t_cluster_placement_stats *cluster_placement_stats)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void set_mode_cluster_placement_stats ( INP t_pb_graph_node pb_graph_node,
int  mode 
)

Set mode of cluster

Definition at line 394 of file cluster_placement.c.

395  {
396  int i, j, k;
397  for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
398  if (i != mode) {
399  for (j = 0;
400  j < pb_graph_node->pb_type->modes[i].num_pb_type_children;
401  j++) {
402  for (k = 0;
403  k
404  < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb;
405  k++) {
407  &pb_graph_node->child_pb_graph_nodes[i][j][k], 0,
408  FALSE);
409  }
410  }
411  }
412  }
413 }
static void update_primitive_cost_or_status(INP t_pb_graph_node *pb_graph_node, INP float incremental_cost, INP boolean valid)
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function: