Skip to content

Commit e956917

Browse files
[Packer] Created GreedySeedSelector Class
Cleaned up the way that new seed molecules were picked in the greedy clusterer by abstracting it into a class. This will make it simpler to build upon this or change how seeds are selected in the future.
1 parent 33c131a commit e956917

File tree

5 files changed

+349
-214
lines changed

5 files changed

+349
-214
lines changed

vpr/src/pack/cluster_util.cpp

Lines changed: 0 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,156 +1523,6 @@ t_molecule_stats calc_molecule_stats(const t_pack_molecule* molecule, const Atom
15231523
return molecule_stats;
15241524
}
15251525

1526-
std::vector<AtomBlockId> initialize_seed_atoms(const e_cluster_seed seed_type,
1527-
const t_molecule_stats& max_molecule_stats,
1528-
const Prepacker& prepacker,
1529-
const vtr::vector<AtomBlockId, float>& atom_criticality) {
1530-
const AtomNetlist& atom_nlist = g_vpr_ctx.atom().nlist;
1531-
1532-
//Put all atoms in seed list
1533-
std::vector<AtomBlockId> seed_atoms(atom_nlist.blocks().begin(), atom_nlist.blocks().end());
1534-
1535-
//Initially all gains are zero
1536-
vtr::vector<AtomBlockId, float> atom_gains(atom_nlist.blocks().size(), 0.);
1537-
1538-
if (seed_type == e_cluster_seed::TIMING) {
1539-
VTR_ASSERT(atom_gains.size() == atom_criticality.size());
1540-
1541-
//By criticality
1542-
atom_gains = atom_criticality;
1543-
1544-
} else if (seed_type == e_cluster_seed::MAX_INPUTS) {
1545-
//By number of used molecule input pins
1546-
for (auto blk : atom_nlist.blocks()) {
1547-
const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk);
1548-
const t_molecule_stats molecule_stats = calc_molecule_stats(blk_mol, atom_nlist);
1549-
atom_gains[blk] = molecule_stats.num_used_ext_inputs;
1550-
}
1551-
1552-
} else if (seed_type == e_cluster_seed::BLEND) {
1553-
//By blended gain (criticality and inputs used)
1554-
for (auto blk : atom_nlist.blocks()) {
1555-
/* Score seed gain of each block as a weighted sum of timing criticality,
1556-
* number of tightly coupled blocks connected to it, and number of external inputs */
1557-
float seed_blend_fac = 0.5;
1558-
1559-
const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk);
1560-
const t_molecule_stats molecule_stats = calc_molecule_stats(blk_mol, atom_nlist);
1561-
VTR_ASSERT(max_molecule_stats.num_used_ext_inputs > 0);
1562-
1563-
float blend_gain = (seed_blend_fac * atom_criticality[blk]
1564-
+ (1 - seed_blend_fac) * (molecule_stats.num_used_ext_inputs / max_molecule_stats.num_used_ext_inputs));
1565-
blend_gain *= (1 + 0.2 * (molecule_stats.num_blocks - 1));
1566-
atom_gains[blk] = blend_gain;
1567-
}
1568-
1569-
} else if (seed_type == e_cluster_seed::MAX_PINS || seed_type == e_cluster_seed::MAX_INPUT_PINS) {
1570-
//By pins per molecule (i.e. available pins on primitives, not pins in use)
1571-
1572-
for (auto blk : atom_nlist.blocks()) {
1573-
const t_pack_molecule* mol = prepacker.get_atom_molecule(blk);
1574-
const t_molecule_stats molecule_stats = calc_molecule_stats(mol, atom_nlist);
1575-
1576-
int molecule_pins = 0;
1577-
if (seed_type == e_cluster_seed::MAX_PINS) {
1578-
//All pins
1579-
molecule_pins = molecule_stats.num_pins;
1580-
} else {
1581-
VTR_ASSERT(seed_type == e_cluster_seed::MAX_INPUT_PINS);
1582-
//Input pins only
1583-
molecule_pins = molecule_stats.num_input_pins;
1584-
}
1585-
1586-
atom_gains[blk] = molecule_pins;
1587-
}
1588-
1589-
} else if (seed_type == e_cluster_seed::BLEND2) {
1590-
for (auto blk : atom_nlist.blocks()) {
1591-
const t_pack_molecule* mol = prepacker.get_atom_molecule(blk);
1592-
const t_molecule_stats molecule_stats = calc_molecule_stats(mol, atom_nlist);
1593-
1594-
float pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_pins, max_molecule_stats.num_pins);
1595-
float input_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_input_pins, max_molecule_stats.num_input_pins);
1596-
float output_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_output_pins, max_molecule_stats.num_output_pins);
1597-
float used_ext_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_pins, max_molecule_stats.num_used_ext_pins);
1598-
float used_ext_input_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_inputs, max_molecule_stats.num_used_ext_inputs);
1599-
float used_ext_output_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_outputs, max_molecule_stats.num_used_ext_outputs);
1600-
float num_blocks_ratio = vtr::safe_ratio<float>(molecule_stats.num_blocks, max_molecule_stats.num_blocks);
1601-
float criticality = atom_criticality[blk];
1602-
1603-
constexpr float PIN_WEIGHT = 0.;
1604-
constexpr float INPUT_PIN_WEIGHT = 0.5;
1605-
constexpr float OUTPUT_PIN_WEIGHT = 0.;
1606-
constexpr float USED_PIN_WEIGHT = 0.;
1607-
constexpr float USED_INPUT_PIN_WEIGHT = 0.2;
1608-
constexpr float USED_OUTPUT_PIN_WEIGHT = 0.;
1609-
constexpr float BLOCKS_WEIGHT = 0.2;
1610-
constexpr float CRITICALITY_WEIGHT = 0.1;
1611-
1612-
float gain = PIN_WEIGHT * pin_ratio
1613-
+ INPUT_PIN_WEIGHT * input_pin_ratio
1614-
+ OUTPUT_PIN_WEIGHT * output_pin_ratio
1615-
1616-
+ USED_PIN_WEIGHT * used_ext_pin_ratio
1617-
+ USED_INPUT_PIN_WEIGHT * used_ext_input_pin_ratio
1618-
+ USED_OUTPUT_PIN_WEIGHT * used_ext_output_pin_ratio
1619-
1620-
+ BLOCKS_WEIGHT * num_blocks_ratio
1621-
+ CRITICALITY_WEIGHT * criticality;
1622-
1623-
atom_gains[blk] = gain;
1624-
}
1625-
1626-
} else {
1627-
VPR_FATAL_ERROR(VPR_ERROR_PACK, "Unrecognized cluster seed type");
1628-
}
1629-
1630-
//Sort seeds in descending order of gain (i.e. highest gain first)
1631-
//
1632-
// Note that we use a *stable* sort here. It has been observed that different
1633-
// standard library implementations (e.g. gcc-4.9 vs gcc-5) use sorting algorithms
1634-
// which produce different orderings for seeds of equal gain (which is allowed with
1635-
// std::sort which does not specify how equal values are handled). Using a stable
1636-
// sort ensures that regardless of the underlying sorting algorithm the same seed
1637-
// order is produced regardless of compiler.
1638-
auto by_descending_gain = [&](const AtomBlockId lhs, const AtomBlockId rhs) {
1639-
return atom_gains[lhs] > atom_gains[rhs];
1640-
};
1641-
std::stable_sort(seed_atoms.begin(), seed_atoms.end(), by_descending_gain);
1642-
1643-
if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_CLUSTERING_BLOCK_CRITICALITIES)) {
1644-
print_seed_gains(getEchoFileName(E_ECHO_CLUSTERING_BLOCK_CRITICALITIES), seed_atoms, atom_gains, atom_criticality);
1645-
}
1646-
1647-
return seed_atoms;
1648-
}
1649-
1650-
t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
1651-
const std::vector<AtomBlockId>& seed_atoms,
1652-
const Prepacker& prepacker,
1653-
const ClusterLegalizer& cluster_legalizer) {
1654-
while (seed_index < static_cast<int>(seed_atoms.size())) {
1655-
AtomBlockId blk_id = seed_atoms[seed_index++];
1656-
1657-
// Check if the atom has already been assigned to a cluster
1658-
if (!cluster_legalizer.is_atom_clustered(blk_id)) {
1659-
t_pack_molecule* best = nullptr;
1660-
1661-
t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id);
1662-
if (!cluster_legalizer.is_mol_clustered(molecule)) {
1663-
if (best == nullptr || (best->base_gain) < (molecule->base_gain)) {
1664-
best = molecule;
1665-
}
1666-
}
1667-
VTR_ASSERT(best != nullptr);
1668-
return best;
1669-
}
1670-
}
1671-
1672-
/*if it makes it to here , there are no more blocks available*/
1673-
return nullptr;
1674-
}
1675-
16761526
float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain, AttractGroupId cluster_attraction_group_id, AttractionInfo& attraction_groups, int num_molecule_failures) {
16771527
float gain;
16781528
int i;
@@ -1804,38 +1654,6 @@ std::map<const t_model*, std::vector<t_logical_block_type_ptr>> identify_primiti
18041654
return model_candidates;
18051655
}
18061656

1807-
void print_seed_gains(const char* fname, const std::vector<AtomBlockId>& seed_atoms, const vtr::vector<AtomBlockId, float>& atom_gain, const vtr::vector<AtomBlockId, float>& atom_criticality) {
1808-
FILE* fp = vtr::fopen(fname, "w");
1809-
1810-
const AtomContext& atom_ctx = g_vpr_ctx.atom();
1811-
1812-
//For prett formatting determine the maximum name length
1813-
int max_name_len = strlen("atom_block_name");
1814-
int max_type_len = strlen("atom_block_type");
1815-
for (auto blk_id : atom_ctx.nlist.blocks()) {
1816-
max_name_len = std::max(max_name_len, (int)atom_ctx.nlist.block_name(blk_id).size());
1817-
1818-
const t_model* model = atom_ctx.nlist.block_model(blk_id);
1819-
max_type_len = std::max(max_type_len, (int)strlen(model->name));
1820-
}
1821-
1822-
fprintf(fp, "%-*s %-*s %8s %8s\n", max_name_len, "atom_block_name", max_type_len, "atom_block_type", "gain", "criticality");
1823-
fprintf(fp, "\n");
1824-
for (auto blk_id : seed_atoms) {
1825-
std::string name = atom_ctx.nlist.block_name(blk_id);
1826-
fprintf(fp, "%-*s ", max_name_len, name.c_str());
1827-
1828-
const t_model* model = atom_ctx.nlist.block_model(blk_id);
1829-
fprintf(fp, "%-*s ", max_type_len, model->name);
1830-
1831-
fprintf(fp, "%*f ", std::max((int)strlen("gain"), 8), atom_gain[blk_id]);
1832-
fprintf(fp, "%*f ", std::max((int)strlen("criticality"), 8), atom_criticality[blk_id]);
1833-
fprintf(fp, "\n");
1834-
}
1835-
1836-
fclose(fp);
1837-
}
1838-
18391657
size_t update_pb_type_count(const t_pb* pb, std::map<t_pb_type*, int>& pb_type_count, size_t depth) {
18401658
size_t max_depth = depth;
18411659

vpr/src/pack/cluster_util.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -428,16 +428,6 @@ t_pack_molecule* get_molecule_for_cluster(t_pb* cur_pb,
428428
*/
429429
t_molecule_stats calc_molecule_stats(const t_pack_molecule* molecule, const AtomNetlist& atom_nlist);
430430

431-
std::vector<AtomBlockId> initialize_seed_atoms(const e_cluster_seed seed_type,
432-
const t_molecule_stats& max_molecule_stats,
433-
const Prepacker& prepacker,
434-
const vtr::vector<AtomBlockId, float>& atom_criticality);
435-
436-
t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
437-
const std::vector<AtomBlockId>& seed_atoms,
438-
const Prepacker& prepacker,
439-
const ClusterLegalizer& cluster_legalizer);
440-
441431
/*
442432
* @brief Get gain of packing molecule into current cluster.
443433
*
@@ -448,8 +438,6 @@ t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
448438
*/
449439
float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain, AttractGroupId cluster_attraction_group_id, AttractionInfo& attraction_groups, int num_molecule_failures);
450440

451-
void print_seed_gains(const char* fname, const std::vector<AtomBlockId>& seed_atoms, const vtr::vector<AtomBlockId, float>& atom_gain, const vtr::vector<AtomBlockId, float>& atom_criticality);
452-
453441
/**
454442
* @brief Score unclustered atoms that are two hops away from current cluster
455443
*

vpr/src/pack/greedy_clusterer.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,16 @@
3838

3939
#include "greedy_clusterer.h"
4040
#include <map>
41+
#include <vector>
4142
#include "atom_netlist.h"
4243
#include "attraction_groups.h"
4344
#include "cluster_legalizer.h"
4445
#include "cluster_util.h"
4546
#include "constraints_report.h"
47+
#include "greedy_seed_selector.h"
4648
#include "physical_types.h"
4749
#include "prepack.h"
50+
#include "vtr_vector.h"
4851

4952
GreedyClusterer::GreedyClusterer(const t_packer_opts& packer_opts,
5053
const t_analysis_opts& analysis_opts,
@@ -106,7 +109,7 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
106109

107110
enum e_block_pack_status block_pack_status;
108111

109-
t_pack_molecule *istart, *next_molecule, *prev_molecule;
112+
t_pack_molecule *next_molecule, *prev_molecule;
110113

111114
auto& device_ctx = g_vpr_ctx.mutable_device();
112115

@@ -130,8 +133,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
130133
* (eg. [A1, A2, ..]->[B1, B2, ..]->C implies cluster [A1, A2, ...] and C have a weak link) */
131134
vtr::vector<LegalizationClusterId, std::vector<AtomNetId>> clb_inter_blk_nets(atom_netlist_.blocks().size());
132135

133-
istart = nullptr;
134-
135136
const t_molecule_stats max_molecule_stats = prepacker.calc_max_molecule_stats(atom_netlist_);
136137

137138
cluster_stats.num_molecules = prepacker.get_num_molecules();
@@ -170,18 +171,16 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
170171
clustering_delay_calc, timing_info, atom_criticality);
171172
}
172173

173-
// Assign gain scores to atoms and sort them based on the scores.
174-
auto seed_atoms = initialize_seed_atoms(packer_opts_.cluster_seed_type,
175-
max_molecule_stats,
176-
prepacker,
177-
atom_criticality);
174+
// Create the greedy seed selector.
175+
GreedySeedSelector seed_selector(atom_netlist_,
176+
prepacker,
177+
packer_opts_.cluster_seed_type,
178+
max_molecule_stats,
179+
atom_criticality);
178180

179-
/* index of next most timing critical block */
180-
int seed_index = 0;
181-
istart = get_highest_gain_seed_molecule(seed_index,
182-
seed_atoms,
183-
prepacker,
184-
cluster_legalizer);
181+
// Pick the first seed molecule.
182+
t_pack_molecule* istart = seed_selector.get_next_seed(prepacker,
183+
cluster_legalizer);
185184

186185
print_pack_status_header();
187186

@@ -191,7 +190,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
191190

192191
while (istart != nullptr) {
193192
bool is_cluster_legal = false;
194-
int saved_seed_index = seed_index;
195193
// The basic algorithm:
196194
// 1) Try to put all the molecules in that you can without doing the
197195
// full intra-lb route. Then do full legalization at the end.
@@ -333,10 +331,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
333331

334332
if (is_cluster_legal) {
335333
// Pick new seed.
336-
istart = get_highest_gain_seed_molecule(seed_index,
337-
seed_atoms,
338-
prepacker,
339-
cluster_legalizer);
334+
istart = seed_selector.get_next_seed(prepacker,
335+
cluster_legalizer);
340336
// Update cluster stats.
341337
if (packer_opts_.timing_driven && num_blocks_hill_added > 0)
342338
cluster_stats.blocks_since_last_analysis += num_blocks_hill_added;
@@ -350,7 +346,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
350346
// If the cluster is not legal, requeue used mols.
351347
num_used_type_instances[cluster_legalizer.get_cluster_type(legalization_cluster_id)]--;
352348
total_clb_num--;
353-
seed_index = saved_seed_index;
354349
// Destroy the illegal cluster.
355350
cluster_legalizer.destroy_cluster(legalization_cluster_id);
356351
cluster_legalizer.compress();

0 commit comments

Comments
 (0)