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

Go to the source code of this file.

Functions

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)
 
static void requeue_primitive (INOUTP t_cluster_placement_stats *cluster_placement_stats, t_cluster_placement_primitive *cluster_placement_primitive)
 
static void update_primitive_cost_or_status (INP t_pb_graph_node *pb_graph_node, INP float incremental_cost, INP boolean valid)
 
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)
 
static boolean expand_forced_pack_molecule_placement (INP t_pack_molecule *molecule, INP t_pack_pattern_block *pack_pattern_block, INOUTP t_pb_graph_node **primitives_list, INOUTP float *cost)
 
static t_pb_graph_pinexpand_pack_molecule_pin_edge (INP int pattern_id, INP t_pb_graph_pin *cur_pin, INP boolean forward)
 
static void flush_intermediate_queues (INOUTP t_cluster_placement_stats *cluster_placement_stats)
 
static boolean root_passes_early_filter (INP t_pb_graph_node *root, INP t_pack_molecule *molecule, INP int clb_index)
 
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 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_list)
 
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 *pb_graph_node, int mode)
 
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:

static boolean expand_forced_pack_molecule_placement ( INP t_pack_molecule molecule,
INP t_pack_pattern_block pack_pattern_block,
INOUTP t_pb_graph_node **  primitives_list,
INOUTP float *  cost 
)
static

Expand molecule at pb_graph_node Assumes molecule and pack pattern connections have fan-out 1

Definition at line 492 of file cluster_placement.c.

495  {
496  t_pb_graph_node *pb_graph_node =
497  primitives_list[pack_pattern_block->block_id];
498  t_pb_graph_node *next_primitive;
500  int from_pin, from_port;
501  t_pb_graph_pin *cur_pin, *next_pin;
502  t_pack_pattern_block *next_block;
503 
504  cur = pack_pattern_block->connections;
505  while (cur) {
506  if (cur->from_block == pack_pattern_block) {
507  next_block = cur->to_block;
508  } else {
509  next_block = cur->from_block;
510  }
511  if (primitives_list[next_block->block_id] == NULL && molecule->logical_block_ptrs[next_block->block_id] != NULL) {
512  /* first time visiting location */
513 
514  /* find next primitive based on pattern connections, expand next primitive if not visited */
515  from_pin = cur->from_pin->pin_number;
516  from_port = cur->from_pin->port->port_index_by_type;
517  if (cur->from_block == pack_pattern_block) {
518  /* forward expand to find next block */
519  cur_pin = &pb_graph_node->output_pins[from_port][from_pin];
521  pack_pattern_block->pattern_index, cur_pin, TRUE);
522  } else {
523  /* backward expand to find next block */
524  assert(cur->to_block == pack_pattern_block);
525  if (cur->from_pin->port->is_clock) {
526  cur_pin = &pb_graph_node->clock_pins[from_port][from_pin];
527  } else {
528  cur_pin = &pb_graph_node->input_pins[from_port][from_pin];
529  }
531  pack_pattern_block->pattern_index, cur_pin, FALSE);
532  }
533  /* found next primitive */
534  if (next_pin != NULL) {
535  next_primitive = next_pin->parent_node;
536  /* Check for legality of placement, if legal, expand from legal placement, if not, return FALSE */
537  if (molecule->logical_block_ptrs[next_block->block_id] != NULL
538  && primitives_list[next_block->block_id] == NULL) {
539  if (next_primitive->cluster_placement_primitive->valid
540  == TRUE
542  molecule->logical_block_ptrs[next_block->block_id]->index,
543  next_primitive->pb_type)) {
544  primitives_list[next_block->block_id] = next_primitive;
545  *cost +=
546  next_primitive->cluster_placement_primitive->base_cost
549  next_block, primitives_list, cost)) {
550  return FALSE;
551  }
552  } else {
553  return FALSE;
554  }
555  }
556  } else {
557  return FALSE;
558  }
559  }
560  cur = cur->next;
561  }
562 
563  return TRUE;
564 }
static boolean expand_forced_pack_molecule_placement(INP t_pack_molecule *molecule, INP t_pack_pattern_block *pack_pattern_block, INOUTP t_pb_graph_node **primitives_list, INOUTP float *cost)
boolean is_clock
boolean primitive_type_feasible(int iblk, const t_pb_type *cur_pb_type)
Definition: vpr_utils.c:241
t_pb_graph_pin ** clock_pins
t_pack_pattern_block * from_block
Definition: cad_types.h:21
t_pb_graph_pin ** output_pins
t_pack_pattern_block * to_block
Definition: cad_types.h:24
static t_pb_graph_pin * expand_pack_molecule_pin_edge(INP int pattern_id, INP t_pb_graph_pin *cur_pin, INP boolean forward)
struct s_cluster_placement_primitive * cluster_placement_primitive
Definition: util.h:12
t_pb_graph_pin * from_pin
Definition: cad_types.h:22
struct s_pb_graph_node * parent_node
struct s_pack_pattern_connections * next
Definition: cad_types.h:27
int port_index_by_type
struct s_pb_type * pb_type
t_pb_graph_pin ** input_pins
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static t_pb_graph_pin * expand_pack_molecule_pin_edge ( INP int  pattern_id,
INP t_pb_graph_pin cur_pin,
INP boolean  forward 
)
static

Find next primitive pb_graph_pin

Definition at line 569 of file cluster_placement.c.

570  {
571  int i, j, k;
572  t_pb_graph_pin *temp_pin, *dest_pin;
573  temp_pin = NULL;
574  dest_pin = NULL;
575  if (forward) {
576  for (i = 0; i < cur_pin->num_output_edges; i++) {
577  /* one fanout assumption */
578  if (cur_pin->output_edges[i]->infer_pattern) {
579  for (k = 0; k < cur_pin->output_edges[i]->num_output_pins;
580  k++) {
581  if (cur_pin->output_edges[i]->output_pins[k]->parent_node->pb_type->num_modes
582  == 0) {
583  temp_pin = cur_pin->output_edges[i]->output_pins[k];
584  } else {
585  temp_pin = expand_pack_molecule_pin_edge(pattern_id,
586  cur_pin->output_edges[i]->output_pins[k],
587  forward);
588  }
589  }
590  if (temp_pin != NULL) {
591  assert(dest_pin == NULL || dest_pin == temp_pin);
592  dest_pin = temp_pin;
593  }
594  } else {
595  for (j = 0; j < cur_pin->output_edges[i]->num_pack_patterns;
596  j++) {
597  if (cur_pin->output_edges[i]->pack_pattern_indices[j]
598  == pattern_id) {
599  for (k = 0;
600  k < cur_pin->output_edges[i]->num_output_pins;
601  k++) {
602  if (cur_pin->output_edges[i]->output_pins[k]->parent_node->pb_type->num_modes
603  == 0) {
604  temp_pin =
605  cur_pin->output_edges[i]->output_pins[k];
606  } else {
607  temp_pin =
609  pattern_id,
610  cur_pin->output_edges[i]->output_pins[k],
611  forward);
612  }
613  }
614  if (temp_pin != NULL) {
615  assert(dest_pin == NULL || dest_pin == temp_pin);
616  dest_pin = temp_pin;
617  }
618  }
619  }
620  }
621  }
622  } else {
623  for (i = 0; i < cur_pin->num_input_edges; i++) {
624  /* one fanout assumption */
625  if (cur_pin->input_edges[i]->infer_pattern) {
626  for (k = 0; k < cur_pin->input_edges[i]->num_input_pins; k++) {
627  if (cur_pin->input_edges[i]->input_pins[k]->parent_node->pb_type->num_modes
628  == 0) {
629  temp_pin = cur_pin->input_edges[i]->input_pins[k];
630  } else {
631  temp_pin = expand_pack_molecule_pin_edge(pattern_id,
632  cur_pin->input_edges[i]->input_pins[k],
633  forward);
634  }
635  }
636  if (temp_pin != NULL) {
637  assert(dest_pin == NULL || dest_pin == temp_pin);
638  dest_pin = temp_pin;
639  }
640  } else {
641  for (j = 0; j < cur_pin->input_edges[i]->num_pack_patterns;
642  j++) {
643  if (cur_pin->input_edges[i]->pack_pattern_indices[j]
644  == pattern_id) {
645  for (k = 0; k < cur_pin->input_edges[i]->num_input_pins;
646  k++) {
647  if (cur_pin->input_edges[i]->input_pins[k]->parent_node->pb_type->num_modes
648  == 0) {
649  temp_pin =
650  cur_pin->input_edges[i]->input_pins[k];
651  } else {
653  pattern_id,
654  cur_pin->input_edges[i]->input_pins[k],
655  forward);
656  }
657  }
658  if (temp_pin != NULL) {
659  assert(dest_pin == NULL || dest_pin == temp_pin);
660  dest_pin = temp_pin;
661  }
662  }
663  }
664  }
665  }
666  }
667  return dest_pin;
668 }
t_pb_graph_pin ** output_pins
struct s_pb_graph_edge ** output_edges
static t_pb_graph_pin * expand_pack_molecule_pin_edge(INP int pattern_id, INP t_pb_graph_pin *cur_pin, INP boolean forward)
struct s_pb_graph_edge ** input_edges
t_pb_graph_pin ** input_pins

+ Here is the caller graph for this function:

static void flush_intermediate_queues ( INOUTP t_cluster_placement_stats cluster_placement_stats)
static

Definition at line 670 of file cluster_placement.c.

671  {
672  t_cluster_placement_primitive *cur, *next;
673  cur = cluster_placement_stats->tried;
674  while (cur != NULL) {
675  next = cur->next_primitive;
676  requeue_primitive(cluster_placement_stats, cur);
677  cur = next;
678  }
679  cluster_placement_stats->tried = NULL;
680 
681  cur = cluster_placement_stats->in_flight;
682  if (cur != NULL) {
683  next = cur->next_primitive;
684  requeue_primitive(cluster_placement_stats, cur);
685  /* should have at most one block in flight at any point in time */
686  assert(next == NULL);
687  }
688  cluster_placement_stats->in_flight = NULL;
689 }
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
static void requeue_primitive(INOUTP t_cluster_placement_stats *cluster_placement_stats, t_cluster_placement_primitive *cluster_placement_primitive)

+ 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:

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 
)
static

Add any primitives found in pb_graph_nodes to cluster_placement_stats Adds backward link from pb_graph_node to cluster_placement_primitive

Definition at line 292 of file cluster_placement.c.

294  {
295  int i, j, k;
296  t_cluster_placement_primitive *placement_primitive;
297  const t_pb_type *pb_type = pb_graph_node->pb_type;
298  boolean success;
299  if (pb_type->modes == 0) {
300  placement_primitive = (t_cluster_placement_primitive *) my_calloc(1,
302  placement_primitive->pb_graph_node = pb_graph_node;
303  placement_primitive->valid = TRUE;
304  pb_graph_node->cluster_placement_primitive = placement_primitive;
305  placement_primitive->base_cost = compute_primitive_base_cost(
306  pb_graph_node);
307  success = FALSE;
308  i = 0;
309  while (success == FALSE) {
310  if (cluster_placement_stats->valid_primitives[i] == NULL
311  || cluster_placement_stats->valid_primitives[i]->next_primitive->pb_graph_node->pb_type
312  == pb_graph_node->pb_type) {
313  if (cluster_placement_stats->valid_primitives[i] == NULL) {
314  cluster_placement_stats->valid_primitives[i] = (t_cluster_placement_primitive *) my_calloc(1,
315  sizeof(t_cluster_placement_primitive)); /* head of linked list is empty, makes it easier to remove nodes later */
316  cluster_placement_stats->num_pb_types++;
317  }
318  success = TRUE;
319  placement_primitive->next_primitive =
320  cluster_placement_stats->valid_primitives[i]->next_primitive;
321  cluster_placement_stats->valid_primitives[i]->next_primitive =
322  placement_primitive;
323  }
324  i++;
325  }
326  } else {
327  for (i = 0; i < pb_type->num_modes; i++) {
328  for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
329  for (k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb;
330  k++) {
332  cluster_placement_stats,
333  &pb_graph_node->child_pb_graph_nodes[i][j][k]);
334  }
335  }
336  }
337  }
338 }
struct s_pb_type * pb_type_children
t_mode * modes
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
Definition: util.h:12
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
float compute_primitive_base_cost(INP t_pb_graph_node *primitive)
Definition: vpr_utils.c:452
int num_pb_type_children
t_pb_graph_node * pb_graph_node
Definition: cad_types.h:57
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)
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void requeue_primitive ( INOUTP t_cluster_placement_stats cluster_placement_stats,
t_cluster_placement_primitive cluster_placement_primitive 
)
static

Put primitive back on queue of valid primitives Note that valid status is not changed because if the primitive is not valid, it will get properly collected later

Definition at line 256 of file cluster_placement.c.

258  {
259  int i;
260  int null_index;
261  boolean success;
262  null_index = OPEN;
263 
264  success = FALSE;
265  for (i = 0; i < cluster_placement_stats->num_pb_types; i++) {
266  if (cluster_placement_stats->valid_primitives[i]->next_primitive == NULL) {
267  null_index = i;
268  continue;
269  }
270  if (cluster_placement_primitive->pb_graph_node->pb_type
271  == cluster_placement_stats->valid_primitives[i]->next_primitive->pb_graph_node->pb_type) {
272  success = TRUE;
273  cluster_placement_primitive->next_primitive =
274  cluster_placement_stats->valid_primitives[i]->next_primitive;
275  cluster_placement_stats->valid_primitives[i]->next_primitive =
276  cluster_placement_primitive;
277  }
278  }
279  if (success == FALSE) {
280  assert(null_index != OPEN);
281  cluster_placement_primitive->next_primitive =
282  cluster_placement_stats->valid_primitives[null_index]->next_primitive;
283  cluster_placement_stats->valid_primitives[null_index]->next_primitive =
284  cluster_placement_primitive;
285  }
286 }
Definition: util.h:12
struct s_cluster_placement_primitive * next_primitive
Definition: cad_types.h:58
struct s_pb_type * pb_type
t_pb_graph_node * pb_graph_node
Definition: cad_types.h:57
Definition: slre.c:50
Definition: util.h:12

+ 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:

static boolean root_passes_early_filter ( INP t_pb_graph_node root,
INP t_pack_molecule molecule,
INP int  clb_index 
)
static

Definition at line 760 of file cluster_placement.c.

760  {
761  int i, j;
762  boolean feasible;
763  t_logical_block *root_block;
764  t_model_ports *model_port;
765  int inet;
766  int isink;
767  t_pb_graph_pin *sink_pb_graph_pin;
768 
769  feasible = TRUE;
770  root_block = molecule->logical_block_ptrs[molecule->root];
771  for(i = 0; feasible && i < root->num_output_ports; i++) {
772  for(j = 0; feasible && j < root->num_output_pins[i]; j++) {
773  if(root->output_pins[i][j].is_forced_connection) {
774  model_port = root->output_pins[i][j].port->model_port;
775  inet = root_block->output_nets[model_port->index][j];
776  if(inet != OPEN) {
777  /* This output pin has a dedicated connection to one output, make sure that molecule works */
778  if(molecule->type == MOLECULE_SINGLE_ATOM) {
779  feasible = FALSE; /* There is only one case where an atom can fit in here, so by default, feasibility is false unless proven otherwise */
780  if(vpack_net[inet].num_sinks == 1) {
781  isink = vpack_net[inet].node_block[1];
782  if(logical_block[isink].clb_index == clb_index) {
783  sink_pb_graph_pin = &root->output_pins[i][j];
784  while(sink_pb_graph_pin->num_output_edges != 0) {
785  assert(sink_pb_graph_pin->num_output_edges == 1);
786  assert(sink_pb_graph_pin->output_edges[0]->num_output_pins == 1);
787  sink_pb_graph_pin = sink_pb_graph_pin->output_edges[0]->output_pins[0];
788  }
789  if(sink_pb_graph_pin->parent_node == logical_block[isink].pb->pb_graph_node) {
790  /* There is a logical block mapped to the physical position that pulls in the atom in question */
791  feasible = TRUE;
792  }
793  }
794  }
795  }
796  }
797  }
798  }
799  }
800  return feasible;
801 }
t_pb_graph_pin ** output_pins
struct s_pb_graph_edge ** output_edges
int * node_block
Definition: vpr_types.h:507
Definition: util.h:12
struct s_pb_graph_node * parent_node
Definition: slre.c:50
struct s_net * vpack_net
Definition: globals.c:19
int ** output_nets
Definition: vpr_types.h:212
t_pb_graph_node * pb_graph_node
Definition: vpr_types.h:180
struct s_logical_block * logical_block
Definition: globals.c:20
Definition: util.h:12

+ 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:

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 
)
static

Try place molecule at root location, populate primitives list with locations of placement if successful

Definition at line 454 of file cluster_placement.c.

455  {
456  int list_size, i;
457  float cost = HUGE_POSITIVE_FLOAT;
458  list_size = get_array_size_of_molecule(molecule);
459 
461  molecule->logical_block_ptrs[molecule->root]->index,
462  root->pb_type)) {
463  if (root->cluster_placement_primitive->valid == TRUE) {
464  if(root_passes_early_filter(root, molecule, clb_index)) {
465  for (i = 0; i < list_size; i++) {
466  primitives_list[i] = NULL;
467  }
468  cost = root->cluster_placement_primitive->base_cost
469  + root->cluster_placement_primitive->incremental_cost;
470  primitives_list[molecule->root] = root;
471  if (molecule->type == MOLECULE_FORCED_PACK) {
473  molecule->pack_pattern->root_block, primitives_list,
474  &cost)) {
475  return HUGE_POSITIVE_FLOAT;
476  }
477  }
478  for (i = 0; i < list_size; i++) {
479  assert(
480  (primitives_list[i] == NULL) == (molecule->logical_block_ptrs[i] == NULL));
481  }
482  }
483  }
484  }
485  return cost;
486 }
static boolean expand_forced_pack_molecule_placement(INP t_pack_molecule *molecule, INP t_pack_pattern_block *pack_pattern_block, INOUTP t_pb_graph_node **primitives_list, INOUTP float *cost)
boolean primitive_type_feasible(int iblk, const t_pb_type *cur_pb_type)
Definition: vpr_utils.c:241
static boolean root_passes_early_filter(INP t_pb_graph_node *root, INP t_pack_molecule *molecule, INP int clb_index)
#define HUGE_POSITIVE_FLOAT
Definition: vpr_types.h:79
int get_array_size_of_molecule(t_pack_molecule *molecule)
Definition: util.h:12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void update_primitive_cost_or_status ( INP t_pb_graph_node pb_graph_node,
INP float  incremental_cost,
INP boolean  valid 
)
static

For sibling primitives of pb_graph node, decrease cost For modes invalidated by pb_graph_node, invalidate primitive int distance is the distance of current pb_graph_node from original

Definition at line 420 of file cluster_placement.c.

421  {
422  int i, j, k;
423  t_cluster_placement_primitive *placement_primitive;
424  if (pb_graph_node->pb_type->num_modes == 0) {
425  /* is primitive */
426  placement_primitive =
427  (t_cluster_placement_primitive*) pb_graph_node->cluster_placement_primitive;
428  if (valid) {
429  placement_primitive->incremental_cost += incremental_cost;
430  } else {
431  placement_primitive->valid = FALSE;
432  }
433  } else {
434  for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) {
435  for (j = 0;
436  j < pb_graph_node->pb_type->modes[i].num_pb_type_children;
437  j++) {
438  for (k = 0;
439  k
440  < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb;
441  k++) {
443  &pb_graph_node->child_pb_graph_nodes[i][j][k],
444  incremental_cost, valid);
445  }
446  }
447  }
448  }
449 }
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 caller graph for this function: