1
+ /* *
2
+ * @file
3
+ * @author Alex Singer
4
+ * @date September 2024
5
+ * @brief The declaration of the Cluster Legalizer class.
6
+ *
7
+ * This file declares a class called the ClusterLegalizer which encapsulates all
8
+ * logic for creating legal clusters from prepacked molecules. This class is
9
+ * designed to be self-contained to the point that it is able to be called
10
+ * externally to the Packer in VPR.
11
+ */
12
+
1
13
#pragma once
2
14
3
- #include < set>
4
15
#include < unordered_map>
16
+ #include < vector>
5
17
#include " atom_netlist_fwd.h"
6
18
#include " noc_data_types.h"
7
19
#include " partition_region.h"
@@ -49,12 +61,15 @@ struct LegalizationCluster {
49
61
// / @brief A list of the molecules in the cluster. By design, a cluster will
50
62
// / only contain molecules which have been previously legalized into
51
63
// / the cluster using a legalization strategy.
52
- std::set <t_pack_molecule*> molecules;
64
+ std::vector <t_pack_molecule*> molecules;
53
65
54
66
// / @brief The logical block of this cluster.
55
67
// / TODO: We should be more careful with how this is allocated. Instead of
56
68
// / pointers, we really should use IDs and store them in a standard
57
- // / container.
69
+ // / container. Currently this is being allocated with the new keyword
70
+ // / and freed when the cluster is destroyed; however this is used
71
+ // / externally to the class and it can be dangerous to pass around
72
+ // / a pointer to this object.
58
73
t_pb* pb;
59
74
60
75
// / @brief The logical block type this cluster represents.
@@ -79,7 +94,7 @@ struct LegalizationCluster {
79
94
};
80
95
81
96
/*
82
- * @brief A manager class which manages the legalization of cluster . As clusters
97
+ * @brief A manager class which manages the legalization of clusters . As clusters
83
98
* are created, this class will legalize for each molecule added. It also
84
99
* provides methods which are helpful for clustering.
85
100
*
@@ -99,13 +114,15 @@ struct LegalizationCluster {
99
114
* look something like this. Note, this example is simplified and the result
100
115
* of the packings should be checked and handled.
101
116
*
102
- * ClusterLegalizer legalizer(...);
117
+ * ClusterLegalizer legalizer(...,
118
+ * ClusterLegalizationStrategy::SKIP_INTRA_LB_ROUTE,
119
+ * ...);
103
120
*
104
121
* std::tie(status, new_cluster_id) = legalizer.start_new_cluster(seed_mol,
105
122
* cluster_type,
106
123
* mode);
107
124
* for mol in molecules_to_add:
108
- * // Cheaper additions, but may pack a molecule that wouldnt route.
125
+ * // Cheaper additions, but may pack a molecule that wouldn't route.
109
126
* status = legalizer.add_mol_to_cluster(mol, new_cluster_id);
110
127
* if (status != e_block_pack_status::BLK_PASSED)
111
128
* break;
@@ -114,16 +131,20 @@ struct LegalizationCluster {
114
131
* if (!legalizer.check_cluster_legality(new_cluster_id))
115
132
* // Destroy the illegal cluster.
116
133
* legalizer.destroy_cluster(new_cluster_id);
134
+ * // Clean-up the internal bookeeping of the class (required after
135
+ * // destroying a cluster).
117
136
* legalizer.compress();
118
137
* // Handle how to try again (maybe use FULL strategy).
119
138
*
120
139
* 2) FULL Legalization Strategy Example:
121
140
* This strategy will fully route the internal connections of the clusters for
122
141
* each molecule added. This is much more expensive to run; however, will ensure
123
142
* that the cluster is fully legalized while it is being created. An example
124
- * of how to sue this strategy would look something like this:
143
+ * of how to use this strategy would look something like this:
125
144
*
126
- * Clusterlegalizer legalizer(...);
145
+ * Clusterlegalizer legalizer(...,
146
+ * ClusterLegalizationStrategy::FULL,
147
+ * ...);
127
148
*
128
149
* std::tie(pack_result, new_cluster_id) = legalizer.start_new_cluster(seed_mol,
129
150
* cluster_type,
@@ -174,6 +195,46 @@ class ClusterLegalizer {
174
195
* @brief Initialize the ClusterLegalizer class.
175
196
*
176
197
* Allocates internal state.
198
+ *
199
+ * @param atom_netlist The complete atom netlist. Used to allocate
200
+ * internal structures to the correct size.
201
+ * @param prepacker The prepacker object used to prepack the atoms
202
+ * into molecules. A reference to this object is
203
+ * stored internally to be used to lookup the
204
+ * molecules of atoms.
205
+ * @param logical_block_types Used to allocate internal objects. Used to
206
+ * get the max number of primitives in any block
207
+ * type.
208
+ * @param lb_type_rr_graphs The routing resource graph internal to the
209
+ * different cluster types. A reference is stored
210
+ * in the class to be used to allocate and load
211
+ * the router data.
212
+ * @param num_models The total number of models in the architecture.
213
+ * This is the sum of the number of the user and
214
+ * library models. Used internally to allocate data
215
+ * structures.
216
+ * @param target_external_pin_util_str A string used to initialize the
217
+ * target external pin utilization of
218
+ * each cluster type.
219
+ * @param high_fanout_thresholds An object that stores the thresholds for
220
+ * a net to be considered high fanout for
221
+ * different block types.
222
+ * @param cluster_legalization_strategy The legalization strategy to be
223
+ * used when creating clusters and
224
+ * adding molecules to clusters.
225
+ * Controls the checks that are performed.
226
+ * @param enable_pin_feasibility_filter A flag to turn on/off the check for
227
+ * pin usage feasibility.
228
+ * @param feasible_block_array_size The largest number of feasible blocks
229
+ * that can be stored in a cluster. Used
230
+ * to allocate an internal structure.
231
+ * @param log_verbosity Controls how verbose the log messages will
232
+ * be within this class.
233
+ *
234
+ * TODO: A lot of these arguments are only used to allocate C-style arrays
235
+ * since the original author was avoiding dynamic allocations. It may
236
+ * be more space efficient (and cleaner) to make these dynamic arrays
237
+ * and not pass these arguments in.
177
238
*/
178
239
ClusterLegalizer (const AtomNetlist& atom_netlist,
179
240
const Prepacker& prepacker,
@@ -211,7 +272,12 @@ class ClusterLegalizer {
211
272
/*
212
273
* @brief Add an unclustered molecule to the given legalization cluster.
213
274
*
214
- * If the addition was unsuccessful, the molecule will remain unclustered.
275
+ * The ClusterLegalizationStrategy (set either in the constructor or by the
276
+ * set_cluster_legalization_strategy method) decides what checks are
277
+ * performed when adding a molecule to the cluster.
278
+ *
279
+ * If the addition was unsuccessful (i.e. a check fails), the molecule will
280
+ * remain unclustered.
215
281
*
216
282
* @param molecule The molecule to add to the cluster.
217
283
* @param cluster_id The ID of the cluster to add the molecule to.
@@ -234,8 +300,8 @@ class ClusterLegalizer {
234
300
void destroy_cluster (LegalizationClusterId cluster_id);
235
301
236
302
/*
237
- * @brief Compress the internal storage of clusters. Should be called after
238
- * a cluster is destroyed.
303
+ * @brief Compress the internal storage of clusters. Should be called
304
+ * eventually after one or more clusters are destroyed.
239
305
*
240
306
* Similar to the Netlist compress method. Will invalidate all Legalization
241
307
* Cluster IDs.
@@ -246,7 +312,7 @@ class ClusterLegalizer {
246
312
void compress ();
247
313
248
314
/*
249
- * @brief A list of all cluster IDs in the legalizer.
315
+ * @brief A range of all cluster IDs in the legalizer.
250
316
*
251
317
* If the legalizer has been compressed (or no clusters have been destroyed)
252
318
* then all cluster IDs in this list will be valid and represent a non-empty
@@ -288,14 +354,15 @@ class ClusterLegalizer {
288
354
void clean_cluster (LegalizationClusterId cluster_id);
289
355
290
356
/*
291
- * @brief Verify that all atoms have been clustered into a cluster.
357
+ * @brief Verify that all atoms have been clustered into some cluster.
292
358
*
293
359
* This will not verify if all the clusters are fully legal.
294
360
*/
295
361
void verify ();
296
362
297
363
/*
298
- * @brief Finalize the clustering.
364
+ * @brief Finalize the clustering. Required for generating a Clustered
365
+ * Netlist.
299
366
*
300
367
* Before generating a Clustered Netlist, each cluster needs to allocate and
301
368
* load a pb_route. This method will generate a pb_route for each cluster
@@ -339,6 +406,14 @@ class ClusterLegalizer {
339
406
}
340
407
341
408
// / @brief Gets the cluster placement stats of the given cluster.
409
+ // /
410
+ // / The cluster placement stats are statistics used to monitor which atoms
411
+ // / have been physically clustered into the pb (more specifically what site
412
+ // / they will go). This can be used externally to the legalizer to detect
413
+ // / if an atom could physically go into a cluster (exists_free_primitive_for_atom_block).
414
+ // /
415
+ // / TODO: Releasing the whole stats can be dangerous. Ideally there should
416
+ // / just be a method to see if an atom could physically go in a cluster.
342
417
inline t_cluster_placement_stats* get_cluster_placement_stats (LegalizationClusterId cluster_id) const {
343
418
VTR_ASSERT_SAFE (cluster_id.is_valid () && (size_t )cluster_id < legalization_clusters_.size ());
344
419
return &(cluster_placement_stats_[get_cluster_type (cluster_id)->index ]);
@@ -358,6 +433,9 @@ class ClusterLegalizer {
358
433
}
359
434
360
435
// / @bried Gets the max size a cluster could physically be.
436
+ // /
437
+ // / This is the maximum number of primitives any cluster could ever have
438
+ // / in the architecture.
361
439
inline size_t get_max_cluster_size () const {
362
440
return max_cluster_size_;
363
441
}
@@ -411,7 +489,10 @@ class ClusterLegalizer {
411
489
412
490
// / @brief Stores the NoC group ID of each atom block. Atom blocks that
413
491
// / belong to different NoC groups can't be clustered with each other
414
- // / into the same clustered block.
492
+ // / into the same clustered block. Under some optimization settings
493
+ // / to improve placement locality / NoC usage. Atoms with different
494
+ // / NoC group IDs belong to logic that is disjoint except through
495
+ // / NoC traffic.
415
496
vtr::vector<AtomBlockId, NocGroupId> atom_noc_grp_id_;
416
497
417
498
// / @brief Stats keeper for placement information during packing/clustering.
@@ -422,17 +503,17 @@ class ClusterLegalizer {
422
503
// / should stored per cluster.
423
504
t_cluster_placement_stats* cluster_placement_stats_ = nullptr ;
424
505
425
- // / @brief The utilization of external input/output pins during packing
426
- // / (between 0 and 1).
506
+ // / @brief The maximum fractional utilization of cluster external
507
+ // / input/output pins during packing (between 0 and 1).
427
508
t_ext_pin_util_targets target_external_pin_util_;
428
509
429
510
// / @brief The max size of any molecule. This is used to allocate a dynamic
430
511
// / array within the legalizer, and in its current form this is a bit
431
512
// / expensive to calculate from the prepacker.
432
513
size_t max_molecule_size_;
433
514
434
- // / @brief The max size a cluster could physically be. This is used to
435
- // / allocate dynamic arrays.
515
+ // / @brief The max number of primitives a cluster could physically have.
516
+ // / This is used to allocate dynamic arrays.
436
517
size_t max_cluster_size_;
437
518
438
519
// / @brief A vector of routing resource nodes within each logical block type
0 commit comments