From 66fa02dd2ccdc40edb71bf759f300150a4b96d1d Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Thu, 15 Feb 2024 12:00:31 -0500 Subject: [PATCH 01/37] avoid copying Region and PartitionRegion unnecessarily --- vpr/src/base/partition.cpp | 20 +++++---- vpr/src/base/partition.h | 11 +++-- vpr/src/base/partition_region.cpp | 53 ++++++++++++----------- vpr/src/base/partition_region.h | 50 +++++++++++---------- vpr/src/base/region.cpp | 4 +- vpr/src/base/region.h | 7 ++- vpr/src/base/vpr_constraints.cpp | 38 ++++++++-------- vpr/src/base/vpr_constraints.h | 30 +++++++++---- vpr/src/base/vpr_constraints_serializer.h | 12 ++--- vpr/src/base/vpr_constraints_writer.cpp | 8 ++-- vpr/src/base/vpr_constraints_writer.h | 2 +- vpr/src/draw/draw_floorplanning.cpp | 26 +++++------ vpr/src/pack/attraction_groups.cpp | 4 +- vpr/src/pack/cluster_util.cpp | 8 ++-- vpr/src/pack/constraints_report.cpp | 8 ++-- vpr/src/place/initial_placement.cpp | 6 +-- vpr/src/place/move_utils.cpp | 9 ++-- vpr/src/place/place_constraints.cpp | 50 ++++++++++----------- vpr/test/test_vpr_constraints.cpp | 25 +++++------ 19 files changed, 197 insertions(+), 174 deletions(-) diff --git a/vpr/src/base/partition.cpp b/vpr/src/base/partition.cpp index 107a8ec2d3a..6e004b86d46 100644 --- a/vpr/src/base/partition.cpp +++ b/vpr/src/base/partition.cpp @@ -1,29 +1,33 @@ #include "partition.h" #include "partition_region.h" #include -#include +#include -const std::string Partition::get_name() { +const std::string& Partition::get_name() const{ return name; } void Partition::set_name(std::string _part_name) { - name = _part_name; + name = std::move(_part_name); } -const PartitionRegion Partition::get_part_region() { +const PartitionRegion& Partition::get_part_region() const { + return part_region; +} + +PartitionRegion& Partition::get_mutable_part_region() { return part_region; } void Partition::set_part_region(PartitionRegion pr) { - part_region = pr; + part_region = std::move(pr); } -void print_partition(FILE* fp, Partition part) { - std::string name = part.get_name(); +void print_partition(FILE* fp, const Partition& part) { + const std::string& name = part.get_name(); fprintf(fp, "partition_name: %s\n", name.c_str()); - PartitionRegion pr = part.get_part_region(); + const PartitionRegion& pr = part.get_part_region(); print_partition_region(fp, pr); } diff --git a/vpr/src/base/partition.h b/vpr/src/base/partition.h index 7ef144e22a7..9c8984b8c86 100644 --- a/vpr/src/base/partition.h +++ b/vpr/src/base/partition.h @@ -28,7 +28,7 @@ class Partition { /** * @brief Get the unique name of the partition */ - const std::string get_name(); + const std::string& get_name() const; /** * @brief Set the name of the partition @@ -46,7 +46,12 @@ class Partition { /** * @brief Get the PartitionRegion (union of rectangular regions) for this partition */ - const PartitionRegion get_part_region(); + const PartitionRegion& get_part_region() const; + + /** + * @brief Get the mutable PartitionRegion (union of rectangular regions) for this partition + */ + PartitionRegion& get_mutable_part_region(); private: std::string name; ///< name of the partition, name will be unique across partitions @@ -54,6 +59,6 @@ class Partition { }; ///@brief used to print data from a Partition -void print_partition(FILE* fp, Partition part); +void print_partition(FILE* fp, const Partition& part); #endif /* PARTITION_H */ diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 4e08d58f79c..2676b6d1035 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -1,32 +1,34 @@ #include "partition_region.h" #include "region.h" +#include + void PartitionRegion::add_to_part_region(Region region) { - partition_region.push_back(region); + regions.push_back(region); } -std::vector PartitionRegion::get_partition_region() { - return partition_region; +const std::vector& PartitionRegion::get_regions() const { + return regions; } -std::vector PartitionRegion::get_partition_region() const { - return partition_region; +std::vector& PartitionRegion::get_mutable_regions() { + return regions; } void PartitionRegion::set_partition_region(std::vector pr) { - partition_region = pr; + regions = std::move(pr); } -bool PartitionRegion::empty() { - return partition_region.size() == 0; +bool PartitionRegion::empty() const { + return regions.empty(); } -bool PartitionRegion::is_loc_in_part_reg(t_pl_loc loc) { +bool PartitionRegion::is_loc_in_part_reg(const t_pl_loc& loc) const { bool is_in_pr = false; - for (unsigned int i = 0; i < partition_region.size(); i++) { - is_in_pr = partition_region[i].is_loc_in_reg(loc); - if (is_in_pr == true) { + for (const auto & region : regions) { + is_in_pr = region.is_loc_in_reg(loc); + if (is_in_pr) { break; } } @@ -41,12 +43,13 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR * Rectangles are not merged even if it would be possible */ PartitionRegion pr; + auto& pr_regions = pr.get_mutable_regions(); Region intersect_region; - for (unsigned int i = 0; i < cluster_pr.partition_region.size(); i++) { - for (unsigned int j = 0; j < new_pr.partition_region.size(); j++) { - intersect_region = intersection(cluster_pr.partition_region[i], new_pr.partition_region[j]); + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + intersect_region = intersection(cluster_region, new_region); if (!intersect_region.empty()) { - pr.partition_region.push_back(intersect_region); + pr_regions.push_back(intersect_region); } } } @@ -55,11 +58,11 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR } void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { - Region intersect_region; std::vector int_regions; - for (unsigned int i = 0; i < cluster_pr.partition_region.size(); i++) { - for (unsigned int j = 0; j < new_pr.partition_region.size(); j++) { - intersect_region = intersection(cluster_pr.partition_region[i], new_pr.partition_region[j]); + + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + Region intersect_region = intersection(cluster_region, new_region); if (!intersect_region.empty()) { int_regions.push_back(intersect_region); } @@ -68,14 +71,14 @@ void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& cluster_pr.set_partition_region(int_regions); } -void print_partition_region(FILE* fp, PartitionRegion pr) { - std::vector part_region = pr.get_partition_region(); +void print_partition_region(FILE* fp, const PartitionRegion& pr) { + const std::vector& regions = pr.get_regions(); - int pr_size = part_region.size(); + int pr_size = regions.size(); fprintf(fp, "\tNumber of regions in partition is: %d\n", pr_size); - for (unsigned int i = 0; i < part_region.size(); i++) { - print_region(fp, part_region[i]); + for (const auto & region : regions) { + print_region(fp, region); } } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index eb89399191c..2ea9796091b 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -25,8 +25,12 @@ class PartitionRegion { /** * @brief Return the union of regions */ - std::vector get_partition_region(); - std::vector get_partition_region() const; + std::vector& get_mutable_regions(); + + /** + * @brief Return the union of regions + */ + const std::vector& get_regions() const; /** * @brief Set the union of regions @@ -36,7 +40,7 @@ class PartitionRegion { /** * @brief Check if the PartitionRegion is empty (meaning there is no constraint on the object the PartitionRegion belongs to) */ - bool empty(); + bool empty() const; /** * @brief Check if the given location is within the legal bounds of the PartitionRegion. @@ -44,30 +48,30 @@ class PartitionRegion { * * @param loc The location to be checked */ - bool is_loc_in_part_reg(t_pl_loc loc); - - /** - * @brief Global friend function that returns the intersection of two PartitionRegions - * - * @param cluster_pr One of the PartitionRegions to be intersected - * @param new_pr One of the PartitionRegions to be intersected - */ - friend PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr); - - /** - * @brief Global friend function that updates the PartitionRegion of a cluster with the intersection - * of the cluster PartitionRegion and a new PartitionRegion - * - * @param cluster_pr The cluster PartitionRegion that is to be updated - * @param new_pr The new PartitionRegion that the cluster PartitionRegion will be intersected with - */ - friend void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr); + bool is_loc_in_part_reg(const t_pl_loc& loc) const; private: - std::vector partition_region; ///< union of rectangular regions that a partition can be placed in + std::vector regions; ///< union of rectangular regions that a partition can be placed in }; ///@brief used to print data from a PartitionRegion -void print_partition_region(FILE* fp, PartitionRegion pr); +void print_partition_region(FILE* fp, const PartitionRegion& pr); + +/** +* @brief Global friend function that returns the intersection of two PartitionRegions +* +* @param cluster_pr One of the PartitionRegions to be intersected +* @param new_pr One of the PartitionRegions to be intersected +*/ +PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr); + +/** +* @brief Global friend function that updates the PartitionRegion of a cluster with the intersection +* of the cluster PartitionRegion and a new PartitionRegion +* +* @param cluster_pr The cluster PartitionRegion that is to be updated +* @param new_pr The new PartitionRegion that the cluster PartitionRegion will be intersected with +*/ +void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr); #endif /* PARTITION_REGIONS_H */ diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index 5c38f9ace86..e45266c723c 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -42,7 +42,7 @@ bool Region::empty() { || layer_num < 0); } -bool Region::is_loc_in_reg(t_pl_loc loc) { +bool Region::is_loc_in_reg(t_pl_loc loc) const { bool is_loc_in_reg = false; int loc_layer_num = loc.layer; @@ -149,7 +149,7 @@ Region intersection(const Region& r1, const Region& r2) { return intersect; } -void print_region(FILE* fp, Region region) { +void print_region(FILE* fp, const Region& region) { const auto region_coord = region.get_region_rect(); const auto region_rect = vtr::Rect(region_coord.xmin, region_coord.ymin, region_coord.xmax, region_coord.ymax); fprintf(fp, "\tRegion: \n"); diff --git a/vpr/src/base/region.h b/vpr/src/base/region.h index 7b1ceec6dda..dfdfd26d20c 100644 --- a/vpr/src/base/region.h +++ b/vpr/src/base/region.h @@ -43,8 +43,7 @@ struct RegionRectCoord { bool operator==(const RegionRectCoord& rhs) const { vtr::Rect lhs_rect(xmin, ymin, xmax, ymax); vtr::Rect rhs_rect(rhs.xmin, rhs.ymin, rhs.xmax, rhs.ymax); - return lhs_rect == rhs_rect - && layer_num == rhs.layer_num; + return (lhs_rect == rhs_rect) && (layer_num == rhs.layer_num); } }; @@ -105,7 +104,7 @@ class Region { * * @param loc The location to be checked */ - bool is_loc_in_reg(t_pl_loc loc); + bool is_loc_in_reg(t_pl_loc loc) const; bool operator==(const Region& reg) const { return (reg.get_region_rect() == this->get_region_rect() @@ -142,7 +141,7 @@ bool do_regions_intersect(Region r1, Region r2); Region intersection(const Region& r1, const Region& r2); ///@brief Used to print data from a Region -void print_region(FILE* fp, Region region); +void print_region(FILE* fp, const Region& region); namespace std { template<> diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 95c7e7b7358..8580c9419ca 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,7 +1,7 @@ #include "vpr_constraints.h" #include "partition.h" -void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { +void VprConstraints::add_constrained_atom(AtomBlockId blk_id, PartitionId part_id) { auto got = constrained_atoms.find(blk_id); /** @@ -16,27 +16,29 @@ void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const Partit } } -PartitionId VprConstraints::get_atom_partition(AtomBlockId blk_id) { - PartitionId part_id; - +PartitionId VprConstraints::get_atom_partition(AtomBlockId blk_id) const { auto got = constrained_atoms.find(blk_id); if (got == constrained_atoms.end()) { - return part_id = PartitionId::INVALID(); ///< atom is not in a partition, i.e. unconstrained + return PartitionId::INVALID(); ///< atom is not in a partition, i.e. unconstrained } else { return got->second; } } -void VprConstraints::add_partition(Partition part) { +void VprConstraints::add_partition(const Partition& part) { partitions.push_back(part); } -Partition VprConstraints::get_partition(PartitionId part_id) { +const Partition& VprConstraints::get_partition(PartitionId part_id) const { + return partitions[part_id]; +} + +Partition& VprConstraints::get_mutable_partition(PartitionId part_id) { return partitions[part_id]; } -std::vector VprConstraints::get_part_atoms(PartitionId part_id) { +std::vector VprConstraints::get_part_atoms(PartitionId part_id) const { std::vector part_atoms; for (auto& it : constrained_atoms) { @@ -48,18 +50,19 @@ std::vector VprConstraints::get_part_atoms(PartitionId part_id) { return part_atoms; } -int VprConstraints::get_num_partitions() { +int VprConstraints::get_num_partitions() const { return partitions.size(); } -PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { - PartitionRegion pr; - pr = partitions[part_id].get_part_region(); - return pr; +const PartitionRegion& VprConstraints::get_partition_pr(PartitionId part_id) const { + return partitions[part_id].get_part_region(); +} + +PartitionRegion& VprConstraints::get_mutable_partition_pr(PartitionId part_id) { + return partitions[part_id].get_mutable_part_region(); } -void print_constraints(FILE* fp, VprConstraints constraints) { - Partition temp_part; +void print_constraints(FILE* fp, const VprConstraints& constraints) { std::vector atoms; int num_parts = constraints.get_num_partitions(); @@ -69,7 +72,7 @@ void print_constraints(FILE* fp, VprConstraints constraints) { for (int i = 0; i < num_parts; i++) { PartitionId part_id(i); - temp_part = constraints.get_partition(part_id); + const Partition& temp_part = constraints.get_partition(part_id); fprintf(fp, "\npartition_id: %zu\n", size_t(part_id)); print_partition(fp, temp_part); @@ -80,8 +83,7 @@ void print_constraints(FILE* fp, VprConstraints constraints) { fprintf(fp, "\tAtom vector size is %d\n", atoms_size); fprintf(fp, "\tIds of atoms in partition: \n"); - for (unsigned int j = 0; j < atoms.size(); j++) { - AtomBlockId atom_id = atoms[j]; + for (auto atom_id : atoms) { fprintf(fp, "\t#%zu\n", size_t(atom_id)); } } diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index fd3f64842a4..9dd09f47b82 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -43,7 +43,7 @@ class VprConstraints { * @param blk_id The atom being stored * @param part_id The partition the atom is being constrained to */ - void add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id); + void add_constrained_atom(AtomBlockId blk_id, PartitionId part_id); /** * @brief Return id of the partition the atom belongs to @@ -52,40 +52,54 @@ class VprConstraints { * * @param blk_id The atom for which the partition id is needed */ - PartitionId get_atom_partition(AtomBlockId blk_id); + PartitionId get_atom_partition(AtomBlockId blk_id) const; /** * @brief Store a partition * * @param part The partition being stored */ - void add_partition(Partition part); + void add_partition(const Partition& part); /** * @brief Return a partition * * @param part_id The id of the partition that is wanted */ - Partition get_partition(PartitionId part_id); + const Partition& get_partition(PartitionId part_id) const; + + /** + * @brief Returns a mutable partition + * + * @param part_id The id of the partition that is wanted + */ + Partition& get_mutable_partition(PartitionId part_id); /** * @brief Return all the atoms that belong to a partition * * @param part_id The id of the partition whose atoms are needed */ - std::vector get_part_atoms(PartitionId part_id); + std::vector get_part_atoms(PartitionId part_id) const; /** * @brief Returns the number of partitions in the object */ - int get_num_partitions(); + int get_num_partitions() const; /** * @brief Returns the PartitionRegion belonging to the specified Partition * * @param part_id The id of the partition whose PartitionRegion is needed */ - PartitionRegion get_partition_pr(PartitionId part_id); + const PartitionRegion& get_partition_pr(PartitionId part_id) const; + + /** + * @brief Returns the mutable PartitionRegion belonging to the specified Partition + * + * @param part_id The id of the partition whose PartitionRegion is needed + */ + PartitionRegion& get_mutable_partition_pr(PartitionId part_id); private: /** @@ -100,6 +114,6 @@ class VprConstraints { }; ///@brief used to print floorplanning constraints data from a VprConstraints object -void print_constraints(FILE* fp, VprConstraints constraints); +void print_constraints(FILE* fp, const VprConstraints& constraints); #endif /* VPR_CONSTRAINTS_H */ diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index 5405eb0e21a..902d3977a80 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -222,8 +222,8 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase regions = pr.get_partition_region(); + const PartitionRegion& pr = part_info.part.get_part_region(); + const std::vector& regions = pr.get_regions(); return regions.size(); } virtual inline Region get_partition_add_region(int n, partition_info& part_info) final { - PartitionRegion pr = part_info.part.get_part_region(); - std::vector regions = pr.get_partition_region(); + const PartitionRegion& pr = part_info.part.get_part_region(); + const std::vector& regions = pr.get_regions(); return regions[n]; } diff --git a/vpr/src/base/vpr_constraints_writer.cpp b/vpr/src/base/vpr_constraints_writer.cpp index de8c91dedbb..056d0fd7151 100644 --- a/vpr/src/base/vpr_constraints_writer.cpp +++ b/vpr/src/base/vpr_constraints_writer.cpp @@ -196,7 +196,7 @@ void setup_vpr_floorplan_constraints_cutpoints(VprConstraints& constraints, int } int num_partitions = 0; - for (auto region : region_atoms) { + for (const auto& region : region_atoms) { Partition part; PartitionId partid(num_partitions); std::string part_name = "Part" + std::to_string(num_partitions); @@ -205,15 +205,15 @@ void setup_vpr_floorplan_constraints_cutpoints(VprConstraints& constraints, int {reg_coord.xmin, reg_coord.ymin, reg_coord.xmax, reg_coord.ymax, reg_coord.layer_num}); constraints.add_partition(part); - for (unsigned int k = 0; k < region.second.size(); k++) { - constraints.add_constrained_atom(region.second[k], partid); + for (auto blk_id : region.second) { + constraints.add_constrained_atom(blk_id, partid); } num_partitions++; } } -void create_partition(Partition& part, std::string part_name, const RegionRectCoord& region_cord) { +void create_partition(Partition& part, const std::string& part_name, const RegionRectCoord& region_cord) { part.set_name(part_name); PartitionRegion part_pr; Region part_region; diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index 955542be637..9db00bb4612 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -45,6 +45,6 @@ void setup_vpr_floorplan_constraints_one_loc(VprConstraints& constraints, int ex */ void setup_vpr_floorplan_constraints_cutpoints(VprConstraints& constraints, int horizontal_cutpoints, int vertical_cutpoints); -void create_partition(Partition& part, std::string part_name, const RegionRectCoord& region_cord); +void create_partition(Partition& part, const std::string& part_name, const RegionRectCoord& region_cord); #endif /* VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ */ diff --git a/vpr/src/draw/draw_floorplanning.cpp b/vpr/src/draw/draw_floorplanning.cpp index 126bbd63212..8cb32442774 100644 --- a/vpr/src/draw/draw_floorplanning.cpp +++ b/vpr/src/draw/draw_floorplanning.cpp @@ -84,9 +84,9 @@ static void highlight_partition(ezgl::renderer* g, int partitionID, int alpha) { auto constraints = floorplanning_ctx.constraints; t_draw_coords* draw_coords = get_draw_coords_vars(); - auto partition = constraints.get_partition((PartitionId)partitionID); - auto& partition_region = partition.get_part_region(); - auto regions = partition_region.get_partition_region(); + const auto& partition = constraints.get_partition((PartitionId)partitionID); + const auto& partition_region = partition.get_part_region(); + const auto& regions = partition_region.get_regions(); bool name_drawn = false; ezgl::color partition_color = kelly_max_contrast_colors_no_black[partitionID % (kelly_max_contrast_colors_no_black.size())]; @@ -116,13 +116,13 @@ static void highlight_partition(ezgl::renderer* g, int partitionID, int alpha) { if (!name_drawn) { g->set_font_size(10); - std::string partition_name = partition.get_name(); + const std::string& partition_name = partition.get_name(); g->set_color(partition_color, 230); g->draw_text( on_screen_rect.center(), - partition_name.c_str(), + partition_name, on_screen_rect.width() - 10, on_screen_rect.height() - 10); @@ -165,12 +165,11 @@ void draw_constrained_atoms(ezgl::renderer* g) { for (int partitionID = 0; partitionID < num_partitions; partitionID++) { auto atoms = constraints.get_part_atoms((PartitionId)partitionID); - for (size_t j = 0; j < atoms.size(); j++) { - AtomBlockId const& const_atom = atoms[j]; - if (atom_ctx.lookup.atom_pb(const_atom) != nullptr) { - const t_pb* pb = atom_ctx.lookup.atom_pb(const_atom); + for (const auto atom_id : atoms) { + if (atom_ctx.lookup.atom_pb(atom_id) != nullptr) { + const t_pb* pb = atom_ctx.lookup.atom_pb(atom_id); auto color = kelly_max_contrast_colors_no_black[partitionID % (kelly_max_contrast_colors_no_black.size())]; - ClusterBlockId clb_index = atom_ctx.lookup.atom_clb(atoms[j]); + ClusterBlockId clb_index = atom_ctx.lookup.atom_clb(atom_id); auto type = cluster_ctx.clb_nlist.block_type(clb_index); draw_internal_pb(clb_index, cluster_ctx.clb_nlist.block_pb(clb_index), pb, ezgl::rectangle({0, 0}, 0, 0), type, color, g); @@ -232,7 +231,7 @@ static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* current_pb, c g->draw_text( abs_bbox.center(), - blk_tag.c_str(), + blk_tag, abs_bbox.width() + 10, abs_bbox.height() + 10); @@ -307,7 +306,7 @@ static GtkTreeModel* create_and_fill_model(void) { for (int partitionID = 0; partitionID < num_partitions; partitionID++) { auto atoms = constraints.get_part_atoms((PartitionId)partitionID); - auto partition = constraints.get_partition((PartitionId)partitionID); + const auto& partition = constraints.get_partition((PartitionId)partitionID); std::string partition_name(partition.get_name() + " (" + std::to_string(atoms.size()) + " primitives)"); @@ -318,8 +317,7 @@ static GtkTreeModel* create_and_fill_model(void) { COL_NAME, partition_name.c_str(), -1); - for (size_t j = 0; j < atoms.size(); j++) { - AtomBlockId const& const_atom = atoms[j]; + for (auto const_atom : atoms) { std::string atom_name = (atom_ctx.lookup.atom_pb(const_atom))->name; gtk_tree_store_append(store, &child_iter, &iter); gtk_tree_store_set(store, &child_iter, diff --git a/vpr/src/pack/attraction_groups.cpp b/vpr/src/pack/attraction_groups.cpp index 2c70d9d11cd..e4bd17620e4 100644 --- a/vpr/src/pack/attraction_groups.cpp +++ b/vpr/src/pack/attraction_groups.cpp @@ -64,8 +64,8 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { for (int ipart = 0; ipart < num_parts; ipart++) { PartitionId partid(ipart); - Partition part = floorplanning_ctx.constraints.get_partition(partid); - auto& pr_regions = part.get_part_region(); + const Partition& part = floorplanning_ctx.constraints.get_partition(partid); + const auto& pr_regions = part.get_part_region(); PartitionRegion intersect_pr; diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index c1170afba63..48fe7a9dd71 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -94,11 +94,11 @@ static void echo_clusters(char* filename) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); for (ClusterBlockId clb_id : cluster_ctx.clb_nlist.blocks()) { - std::vector reg = floorplanning_ctx.cluster_constraints[clb_id].get_partition_region(); - if (reg.size() != 0) { + const std::vector& regions = floorplanning_ctx.cluster_constraints[clb_id].get_regions(); + if (!regions.empty()) { fprintf(fp, "\nRegions in Cluster %zu:\n", size_t(clb_id)); - for (unsigned int i = 0; i < reg.size(); i++) { - print_region(fp, reg[i]); + for (const auto & region : regions) { + print_region(fp, region); } } } diff --git a/vpr/src/pack/constraints_report.cpp b/vpr/src/pack/constraints_report.cpp index f75823aefab..2c58ef341a4 100644 --- a/vpr/src/pack/constraints_report.cpp +++ b/vpr/src/pack/constraints_report.cpp @@ -18,12 +18,10 @@ bool floorplan_constraints_regions_overfull() { } t_logical_block_type_ptr bt = cluster_ctx.clb_nlist.block_type(blk_id); - PartitionRegion pr = floorplanning_ctx.cluster_constraints[blk_id]; - std::vector regions = pr.get_partition_region(); - - for (unsigned int i_reg = 0; i_reg < regions.size(); i_reg++) { - Region current_reg = regions[i_reg]; + const PartitionRegion& pr = floorplanning_ctx.cluster_constraints[blk_id]; + const std::vector& regions = pr.get_regions(); + for (const auto& current_reg : regions) { auto got = regions_count_info.find(current_reg); if (got == regions_count_info.end()) { diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 7e67f169ef2..b9b97b1998f 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -236,7 +236,7 @@ static bool is_loc_legal(t_pl_loc& loc, PartitionRegion& pr, t_logical_block_typ bool legal = false; //Check if the location is within its constraint region - for (auto reg : pr.get_partition_region()) { + for (const auto& reg : pr.get_regions()) { const auto reg_coord = reg.get_region_rect(); vtr::Rect reg_rect(reg_coord.xmin, reg_coord.ymin, reg_coord.xmax, reg_coord.ymax); if (reg_coord.layer_num != loc.layer) continue; @@ -580,7 +580,7 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, const PartitionRegion& //If the block has more than one floorplan region, pick a random region to get the min/max x and y values int region_index; - std::vector regions = pr.get_partition_region(); + const std::vector& regions = pr.get_regions(); if (regions.size() > 1) { region_index = vtr::irand(regions.size() - 1); } else { @@ -637,7 +637,7 @@ bool try_place_macro_exhaustively(const t_pl_macro& pl_macro, const PartitionReg const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[block_type->index]; auto& place_ctx = g_vpr_ctx.mutable_placement(); - std::vector regions = pr.get_partition_region(); + const std::vector& regions = pr.get_regions(); bool placed = false; diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 2c62d6ec371..b7692581a61 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -1276,13 +1276,10 @@ bool intersect_range_limit_with_floorplan_constraints(t_logical_block_type_ptr t max_grid_loc.y, layer_num}); - auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); + const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); - PartitionRegion pr = floorplanning_ctx.cluster_constraints[b_from]; - std::vector regions; - if (!pr.empty()) { - regions = pr.get_partition_region(); - } + const PartitionRegion& pr = floorplanning_ctx.cluster_constraints[b_from]; + const std::vector& regions = pr.get_regions(); Region intersect_reg; /* * If region size is greater than 1, the block is constrained to more than one rectangular region. diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index f1c5045251b..e1b153d9d71 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -42,8 +42,8 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) { bool is_macro_constrained = false; bool is_member_constrained = false; - for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { - ClusterBlockId iblk = pl_macro.members[imember].blk_index; + for (const auto & member : pl_macro.members) { + ClusterBlockId iblk = member.blk_index; is_member_constrained = is_cluster_constrained(iblk); if (is_member_constrained) { @@ -62,25 +62,25 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition int num_constrained_members = 0; auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); - for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { - ClusterBlockId iblk = pl_macro.members[imember].blk_index; + for (const auto & member : pl_macro.members) { + ClusterBlockId iblk = member.blk_index; is_member_constrained = is_cluster_constrained(iblk); if (is_member_constrained) { num_constrained_members++; - //PartitionRegion of the constrained block - PartitionRegion block_pr; + //PartitionRegion of the constrained block modified for the head according to the offset PartitionRegion modified_pr; - block_pr = floorplanning_ctx.cluster_constraints[iblk]; - std::vector block_regions = block_pr.get_partition_region(); + //PartitionRegion of the constrained block + const PartitionRegion& block_pr = floorplanning_ctx.cluster_constraints[iblk]; + const std::vector& block_regions = block_pr.get_regions(); - for (unsigned int i = 0; i < block_regions.size(); i++) { + for (const auto & block_region : block_regions) { Region modified_reg; - auto offset = pl_macro.members[imember].offset; + auto offset = member.offset; - const auto block_reg_coord = block_regions[i].get_region_rect(); + const auto block_reg_coord = block_region.get_region_rect(); modified_reg.set_region_rect({block_reg_coord.xmin - offset.x, block_reg_coord.ymin - offset.y, @@ -89,8 +89,8 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition block_reg_coord.layer_num}); //check that subtile is not an invalid value before changing, otherwise it just stays -1 - if (block_regions[i].get_sub_tile() != NO_SUBTILE) { - modified_reg.set_sub_tile(block_regions[i].get_sub_tile() - offset.sub_tile); + if (block_region.get_sub_tile() != NO_SUBTILE) { + modified_reg.set_sub_tile(block_region.get_sub_tile() - offset.sub_tile); } modified_pr.add_to_part_region(modified_reg); @@ -116,13 +116,13 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition } PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr, const t_pl_macro& pl_macro) { - std::vector block_regions = head_pr.get_partition_region(); + const std::vector& block_regions = head_pr.get_regions(); PartitionRegion macro_pr; - for (unsigned int i = 0; i < block_regions.size(); i++) { + for (const auto & block_region : block_regions) { Region modified_reg; - const auto block_reg_coord = block_regions[i].get_region_rect(); + const auto block_reg_coord = block_region.get_region_rect(); modified_reg.set_region_rect({block_reg_coord.xmin + offset.x, block_reg_coord.ymin + offset.y, @@ -131,8 +131,8 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs block_reg_coord.layer_num}); //check that subtile is not an invalid value before changing, otherwise it just stays -1 - if (block_regions[i].get_sub_tile() != NO_SUBTILE) { - modified_reg.set_sub_tile(block_regions[i].get_sub_tile() + offset.sub_tile); + if (block_region.get_sub_tile() != NO_SUBTILE) { + modified_reg.set_sub_tile(block_region.get_sub_tile() + offset.sub_tile); } macro_pr.add_to_part_region(modified_reg); @@ -154,9 +154,9 @@ void print_macro_constraint_error(const t_pl_macro& pl_macro) { VTR_LOG( "Feasible floorplanning constraints could not be calculated for the placement macro. \n" "The placement macro contains the following blocks: \n"); - for (unsigned int i = 0; i < pl_macro.members.size(); i++) { - std::string blk_name = cluster_ctx.clb_nlist.block_name((pl_macro.members[i].blk_index)); - VTR_LOG("Block %s (#%zu) ", blk_name.c_str(), size_t(pl_macro.members[i].blk_index)); + for (const auto & member : pl_macro.members) { + std::string blk_name = cluster_ctx.clb_nlist.block_name((member.blk_index)); + VTR_LOG("Block %s (#%zu) ", blk_name.c_str(), size_t(member.blk_index)); } VTR_LOG("\n"); VPR_ERROR(VPR_ERROR_PLACE, " \n Check that the above-mentioned placement macro blocks have compatible floorplan constraints.\n"); @@ -380,7 +380,7 @@ int region_tile_cover(const Region& reg, t_logical_block_type_ptr block_type, t_ */ bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_pl_loc& loc) { auto& device_ctx = g_vpr_ctx.device(); - std::vector regions = pr.get_partition_region(); + const std::vector& regions = pr.get_regions(); bool pr_size_one; int pr_size = 0; int reg_size; @@ -439,11 +439,11 @@ bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_ } int get_part_reg_size(PartitionRegion& pr, t_logical_block_type_ptr block_type, GridTileLookup& grid_tiles) { - std::vector part_reg = pr.get_partition_region(); + const std::vector& regions = pr.get_regions(); int num_tiles = 0; - for (unsigned int i_reg = 0; i_reg < part_reg.size(); i_reg++) { - num_tiles += grid_tiles.region_tile_count(part_reg[i_reg], block_type); + for (const auto & region : regions) { + num_tiles += grid_tiles.region_tile_count(region, block_type); } return num_tiles; diff --git a/vpr/test/test_vpr_constraints.cpp b/vpr/test/test_vpr_constraints.cpp index f9a5d7e5bd4..f0fb486d76a 100644 --- a/vpr/test/test_vpr_constraints.cpp +++ b/vpr/test/test_vpr_constraints.cpp @@ -53,7 +53,7 @@ TEST_CASE("PartitionRegion", "[vpr]") { pr1.add_to_part_region(r1); - std::vector pr_regions = pr1.get_partition_region(); + const std::vector& pr_regions = pr1.get_regions(); REQUIRE(pr_regions[0].get_sub_tile() == 3); const auto pr_reg_coord = pr_regions[0].get_region_rect(); @@ -80,8 +80,8 @@ TEST_CASE("Partition", "[vpr]") { part_reg.add_to_part_region(r1); part.set_part_region(part_reg); - PartitionRegion part_reg_2 = part.get_part_region(); - std::vector regions = part_reg_2.get_partition_region(); + const PartitionRegion& part_reg_2 = part.get_part_region(); + const std::vector& regions = part_reg_2.get_regions(); REQUIRE(regions[0].get_sub_tile() == 3); @@ -121,8 +121,7 @@ TEST_CASE("VprConstraints", "[vpr]") { vprcon.add_partition(part); - Partition got_part; - got_part = vprcon.get_partition(part_id); + const Partition& got_part = vprcon.get_partition(part_id); REQUIRE(got_part.get_name() == "part_name"); std::vector partition_atoms; @@ -235,7 +234,7 @@ TEST_CASE("PartRegionIntersect", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); vtr::Rect int_rect(0, 0, 1, 1); vtr::Rect int_rect_2(1, 1, 2, 2); @@ -268,7 +267,7 @@ TEST_CASE("PartRegionIntersect2", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); vtr::Rect int_rect(0, 0, 2, 2); REQUIRE(regions.size() == 1); const auto first_reg_coord = regions[0].get_region_rect(); @@ -304,9 +303,9 @@ TEST_CASE("PartRegionIntersect3", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); - REQUIRE(regions.size() == 0); + REQUIRE(regions.empty()); } //2x2 regions, 1 overlap @@ -337,7 +336,7 @@ TEST_CASE("PartRegionIntersect4", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); vtr::Rect intersect(1, 2, 3, 4); @@ -374,7 +373,7 @@ TEST_CASE("PartRegionIntersect5", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); vtr::Rect int_r1r3(2, 6, 4, 7); vtr::Rect int_r2r4(6, 4, 8, 5); @@ -415,7 +414,7 @@ TEST_CASE("PartRegionIntersect6", "[vpr]") { PartitionRegion int_pr; int_pr = intersection(pr1, pr2); - std::vector regions = int_pr.get_partition_region(); + const std::vector& regions = int_pr.get_regions(); vtr::Rect int_r1r3(2, 3, 4, 4); vtr::Rect int_r1r4(2, 6, 4, 7); @@ -455,7 +454,7 @@ TEST_CASE("MacroConstraints", "[vpr]") { PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset, grid_pr, pl_macro); - std::vector mac_regions = macro_pr.get_partition_region(); + const std::vector& mac_regions = macro_pr.get_regions(); const auto mac_first_reg_coord = mac_regions[0].get_region_rect(); From cbe5665e46ae094e633e490a5e7b92038844f3ec Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Thu, 15 Feb 2024 19:55:12 -0500 Subject: [PATCH 02/37] pass by ref and range based loops --- libs/libvtrutil/src/vtr_util.cpp | 10 ++--- libs/libvtrutil/src/vtr_util.h | 8 ++-- vpr/src/base/SetupGrid.cpp | 19 ++++----- vpr/src/base/SetupGrid.h | 9 +++-- vpr/src/base/atom_netlist.cpp | 10 ++--- vpr/src/base/atom_netlist.h | 10 ++--- vpr/src/base/constraints_load.cpp | 2 +- vpr/src/base/constraints_load.h | 2 +- vpr/src/base/setup_noc.cpp | 18 ++++----- vpr/src/base/setup_noc.h | 2 +- vpr/src/base/vpr_constraints.cpp | 2 +- vpr/src/base/vpr_constraints_reader.cpp | 2 +- vpr/src/base/vpr_constraints_writer.cpp | 5 +-- vpr/src/base/vpr_constraints_writer.h | 14 ++++++- vpr/src/noc/noc_traffic_flows.cpp | 16 +++++++- vpr/src/noc/noc_traffic_flows.h | 8 +++- .../noc/read_xml_noc_traffic_flows_file.cpp | 39 +++++++++++++------ vpr/src/noc/read_xml_noc_traffic_flows_file.h | 12 ++++-- vpr/src/pack/attraction_groups.cpp | 16 ++++---- vpr/src/pack/attraction_groups.h | 4 +- vpr/src/pack/cluster_util.cpp | 32 +++++++-------- vpr/src/pack/cluster_util.h | 4 +- vpr/src/pack/pack.cpp | 12 ++++-- vpr/src/place/move_utils.cpp | 2 +- 24 files changed, 156 insertions(+), 102 deletions(-) diff --git a/libs/libvtrutil/src/vtr_util.cpp b/libs/libvtrutil/src/vtr_util.cpp index 2a7a247bde1..e73cee1d1a4 100644 --- a/libs/libvtrutil/src/vtr_util.cpp +++ b/libs/libvtrutil/src/vtr_util.cpp @@ -26,7 +26,7 @@ static int cont; /* line continued? (used by strtok)*/ * * The split strings (excluding the delimiters) are returned */ -std::vector split(const char* text, const std::string delims) { +std::vector split(const char* text, const std::string& delims) { if (text) { std::string text_str(text); return split(text_str, delims); @@ -39,7 +39,7 @@ std::vector split(const char* text, const std::string delims) { * * The split strings (excluding the delimiters) are returned */ -std::vector split(const std::string& text, const std::string delims) { +std::vector split(const std::string& text, const std::string& delims) { std::vector tokens; std::string curr_tok; @@ -102,7 +102,7 @@ std::string replace_all(const std::string& input, const std::string& search, con } ///@brief Retruns true if str starts with prefix -bool starts_with(std::string str, std::string prefix) { +bool starts_with(const std::string& str, const std::string& prefix) { return str.find(prefix) == 0; } @@ -461,8 +461,8 @@ bool file_exists(const char* filename) { * * Returns true if the extension is correct, and false otherwise. */ -bool check_file_name_extension(std::string file_name, - std::string file_extension) { +bool check_file_name_extension(const std::string& file_name, + const std::string& file_extension) { auto ext = std::filesystem::path(file_name).extension(); return ext == file_extension; } diff --git a/libs/libvtrutil/src/vtr_util.h b/libs/libvtrutil/src/vtr_util.h index edcb7ba8598..114de793751 100644 --- a/libs/libvtrutil/src/vtr_util.h +++ b/libs/libvtrutil/src/vtr_util.h @@ -14,8 +14,8 @@ namespace vtr { * * The split strings (excluding the delimiters) are returned */ -std::vector split(const char* text, const std::string delims = " \t\n"); -std::vector split(const std::string& text, const std::string delims = " \t\n"); +std::vector split(const char* text, const std::string& delims = " \t\n"); +std::vector split(const std::string& text, const std::string& delims = " \t\n"); ///@brief Returns 'input' with the first instance of 'search' replaced with 'replace' std::string replace_first(const std::string& input, const std::string& search, const std::string& replace); @@ -24,7 +24,7 @@ std::string replace_first(const std::string& input, const std::string& search, c std::string replace_all(const std::string& input, const std::string& search, const std::string& replace); ///@brief Retruns true if str starts with prefix -bool starts_with(std::string str, std::string prefix); +bool starts_with(const std::string& str, const std::string& prefix); ///@brief Returns a std::string formatted using a printf-style format string std::string string_fmt(const char* fmt, ...); @@ -69,7 +69,7 @@ double atod(const std::string& value); */ int get_file_line_number_of_last_opened_file(); bool file_exists(const char* filename); -bool check_file_name_extension(std::string file_name, std::string file_extension); +bool check_file_name_extension(const std::string& file_name, const std::string& file_extension); extern std::string out_file_prefix; diff --git a/vpr/src/base/SetupGrid.cpp b/vpr/src/base/SetupGrid.cpp index 3569f5bff1f..626d3027259 100644 --- a/vpr/src/base/SetupGrid.cpp +++ b/vpr/src/base/SetupGrid.cpp @@ -31,8 +31,8 @@ using vtr::t_formula_data; static DeviceGrid auto_size_device_grid(const std::vector& grid_layouts, const std::map& minimum_instance_counts, float maximum_device_utilization); static std::vector grid_overused_resources(const DeviceGrid& grid, std::map instance_counts); -static bool grid_satisfies_instance_counts(const DeviceGrid& grid, std::map instance_counts, float maximum_utilization); -static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t width, size_t height, bool warn_out_of_range = true, std::vector limiting_resources = std::vector()); +static bool grid_satisfies_instance_counts(const DeviceGrid& grid, const std::map& instance_counts, float maximum_utilization); +static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t width, size_t height, bool warn_out_of_range = true, const std::vector& limiting_resources = std::vector()); static void CheckGrid(const DeviceGrid& grid); @@ -46,7 +46,7 @@ static void set_grid_block_type(int priority, const t_metadata_dict* meta); ///@brief Create the device grid based on resource requirements -DeviceGrid create_device_grid(std::string layout_name, const std::vector& grid_layouts, const std::map& minimum_instance_counts, float target_device_utilization) { +DeviceGrid create_device_grid(const std::string& layout_name, const std::vector& grid_layouts, const std::map& minimum_instance_counts, float target_device_utilization) { if (layout_name == "auto") { //Auto-size the device // @@ -78,9 +78,9 @@ DeviceGrid create_device_grid(std::string layout_name, const std::vector& grid_layouts, size_t width, size_t height) { +DeviceGrid create_device_grid(const std::string& layout_name, const std::vector& grid_layouts, size_t width, size_t height) { if (layout_name == "auto") { - VTR_ASSERT(grid_layouts.size() > 0); + VTR_ASSERT(!grid_layouts.empty()); //Auto-size if (grid_layouts[0].grid_type == GridDefType::AUTO) { //Auto layout of the specified dimensions @@ -145,7 +145,7 @@ DeviceGrid create_device_grid(std::string layout_name, const std::vector& grid_layouts, const std::map& minimum_instance_counts, float maximum_device_utilization) { - VTR_ASSERT(grid_layouts.size() > 0); + VTR_ASSERT(!grid_layouts.empty()); DeviceGrid grid; @@ -281,6 +281,7 @@ static std::vector grid_overused_resources(const Devic //Sort so we allocate logical blocks with the fewest equivalent sites first (least flexible) std::vector logical_block_types; + logical_block_types.reserve(device_ctx.logical_block_types.size()); for (auto& block_type : device_ctx.logical_block_types) { logical_block_types.push_back(&block_type); } @@ -316,7 +317,7 @@ static std::vector grid_overused_resources(const Devic return overused_resources; } -static bool grid_satisfies_instance_counts(const DeviceGrid& grid, std::map instance_counts, float maximum_utilization) { +static bool grid_satisfies_instance_counts(const DeviceGrid& grid, const std::map& instance_counts, float maximum_utilization) { //Are the resources satisified? auto overused_resources = grid_overused_resources(grid, instance_counts); @@ -335,7 +336,7 @@ static bool grid_satisfies_instance_counts(const DeviceGrid& grid, std::map limiting_resources) { +static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t grid_width, size_t grid_height, bool warn_out_of_range, const std::vector& limiting_resources) { if (grid_def.grid_type == GridDefType::FIXED) { if (grid_def.width != int(grid_width) || grid_def.height != int(grid_height)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, @@ -754,7 +755,7 @@ static void CheckGrid(const DeviceGrid& grid) { } } -float calculate_device_utilization(const DeviceGrid& grid, std::map instance_counts) { +float calculate_device_utilization(const DeviceGrid& grid, const std::map& instance_counts) { //Record the resources of the grid std::map grid_resources; for (int layer_num = 0; layer_num < grid.get_num_layers(); ++layer_num) { diff --git a/vpr/src/base/SetupGrid.h b/vpr/src/base/SetupGrid.h index 4dd80c28539..977ce2f51e2 100644 --- a/vpr/src/base/SetupGrid.h +++ b/vpr/src/base/SetupGrid.h @@ -13,13 +13,16 @@ #include "physical_types.h" ///@brief Find the device satisfying the specified minimum resources -DeviceGrid create_device_grid(std::string layout_name, +DeviceGrid create_device_grid(const std::string& layout_name, const std::vector& grid_layouts, const std::map& minimum_instance_counts, float target_device_utilization); ///@brief Find the device close in size to the specified dimensions -DeviceGrid create_device_grid(std::string layout_name, const std::vector& grid_layouts, size_t min_width, size_t min_height); +DeviceGrid create_device_grid(const std::string& layout_name, + const std::vector& grid_layouts, + size_t min_width, + size_t min_height); /** * @brief Calculate the device utilization @@ -27,7 +30,7 @@ DeviceGrid create_device_grid(std::string layout_name, const std::vector instance_counts); +float calculate_device_utilization(const DeviceGrid& grid, const std::map& instance_counts); /** * @brief Returns the effective size of the device diff --git a/vpr/src/base/atom_netlist.cpp b/vpr/src/base/atom_netlist.cpp index 39af4d23e1c..1cbd2232f1f 100644 --- a/vpr/src/base/atom_netlist.cpp +++ b/vpr/src/base/atom_netlist.cpp @@ -115,7 +115,7 @@ AtomBlockId AtomNetlist::find_atom_pin_driver(const AtomBlockId blk_id, const t_ return AtomBlockId::INVALID(); } -std::unordered_set AtomNetlist::net_aliases(const std::string net_name) const { +std::unordered_set AtomNetlist::net_aliases(const std::string& net_name) const { auto net_id = find_net(net_name); VTR_ASSERT(net_id != AtomNetId::INVALID()); @@ -137,7 +137,7 @@ std::unordered_set AtomNetlist::net_aliases(const std::string net_n * Mutators * */ -AtomBlockId AtomNetlist::create_block(const std::string name, const t_model* model, const TruthTable truth_table) { +AtomBlockId AtomNetlist::create_block(const std::string& name, const t_model* model, const TruthTable& truth_table) { AtomBlockId blk_id = Netlist::create_block(name); //Initialize the data @@ -205,7 +205,7 @@ AtomPinId AtomNetlist::create_pin(const AtomPortId port_id, BitIndex port_bit, c return pin_id; } -AtomNetId AtomNetlist::create_net(const std::string name) { +AtomNetId AtomNetlist::create_net(const std::string& name) { AtomNetId net_id = Netlist::create_net(name); //Check post-conditions: size @@ -214,11 +214,11 @@ AtomNetId AtomNetlist::create_net(const std::string name) { return net_id; } -AtomNetId AtomNetlist::add_net(const std::string name, AtomPinId driver, std::vector sinks) { +AtomNetId AtomNetlist::add_net(const std::string& name, AtomPinId driver, std::vector sinks) { return Netlist::add_net(name, driver, sinks); } -void AtomNetlist::add_net_alias(const std::string net_name, const std::string alias_net_name) { +void AtomNetlist::add_net_alias(const std::string& net_name, const std::string& alias_net_name) { auto net_id = find_net(net_name); VTR_ASSERT(net_id != AtomNetId::INVALID()); diff --git a/vpr/src/base/atom_netlist.h b/vpr/src/base/atom_netlist.h index d639b2d5d57..de1bb4f53bf 100644 --- a/vpr/src/base/atom_netlist.h +++ b/vpr/src/base/atom_netlist.h @@ -157,7 +157,7 @@ class AtomNetlist : public Netlist net_aliases(const std::string net_name) const; + std::unordered_set net_aliases(const std::string& net_name) const; public: //Public Mutators /* @@ -173,7 +173,7 @@ class AtomNetlist : public Netlist sinks); + AtomNetId add_net(const std::string& name, AtomPinId driver, std::vector sinks); /** * @brief Adds a value to the net aliases set for a given net name in the net_aliases_map. @@ -218,7 +218,7 @@ class AtomNetlist : public Netlist arch.noc->router_list.size()) // check whether the noc topology information provided is using all the routers in the FPGA { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "The Provided NoC topology information in the architecture file uses less number of routers than what is available in the FPGA device."); - } else if (noc_router_tiles.size() == 0) // case where no physical router tiles were found + } else if (noc_router_tiles.empty()) // case where no physical router tiles were found { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "No physical NoC routers were found on the FPGA device. Either the provided name for the physical router tile was incorrect or the FPGA device has no routers."); } @@ -58,7 +58,7 @@ void setup_noc(const t_arch& arch) { return; } -void identify_and_store_noc_router_tile_positions(const DeviceGrid& device_grid, std::vector& noc_router_tiles, std::string noc_router_tile_name) { +void identify_and_store_noc_router_tile_positions(const DeviceGrid& device_grid, std::vector& noc_router_tiles, const std::string& noc_router_tile_name) { const int num_layers = device_grid.get_num_layers(); int curr_tile_width; int curr_tile_height; @@ -173,10 +173,10 @@ void create_noc_routers(const t_noc_inf& noc_info, NocStorage* noc_model, std::v error_case_physical_router_index_2 = INVALID_PHYSICAL_ROUTER_INDEX; // determine the physical router tile that is closest to the current user described router in the arch file - for (auto physical_router = noc_router_tiles.begin(); physical_router != noc_router_tiles.end(); physical_router++) { + for (auto & physical_router : noc_router_tiles) { // get the position of the current physical router tile on the FPGA device - curr_physical_router_pos_x = physical_router->tile_centroid_x; - curr_physical_router_pos_y = physical_router->tile_centroid_y; + curr_physical_router_pos_x = physical_router.tile_centroid_x; + curr_physical_router_pos_y = physical_router.tile_centroid_y; // use euclidean distance to calculate the length between the current user described router and the physical router curr_calculated_distance = sqrt(pow(abs(curr_physical_router_pos_x - curr_logical_router_position_x), 2.0) + pow(abs(curr_physical_router_pos_y - curr_logical_router_position_y), 2.0)); @@ -237,14 +237,14 @@ void create_noc_links(const t_noc_inf* noc_info, NocStorage* noc_model) { noc_model->make_room_for_noc_router_link_list(); // go through each router and add its outgoing links to the NoC - for (auto router = noc_info->router_list.begin(); router != noc_info->router_list.end(); router++) { + for (const auto & router : noc_info->router_list) { // get the converted id of the current source router - source_router = noc_model->convert_router_id(router->id); + source_router = noc_model->convert_router_id(router.id); // go through all the routers connected to the current one and add links to the noc - for (auto conn_router_id = router->connection_list.begin(); conn_router_id != router->connection_list.end(); conn_router_id++) { + for (int conn_router_id : router.connection_list) { // get the converted id of the currently connected sink router - sink_router = noc_model->convert_router_id(*conn_router_id); + sink_router = noc_model->convert_router_id(conn_router_id); // add the link to the Noc noc_model->add_link(source_router, sink_router); diff --git a/vpr/src/base/setup_noc.h b/vpr/src/base/setup_noc.h index 23737d1c5b1..62b3ae4d543 100644 --- a/vpr/src/base/setup_noc.h +++ b/vpr/src/base/setup_noc.h @@ -89,7 +89,7 @@ void setup_noc(const t_arch& arch); * tile in the FPGA architecture description * file. */ -void identify_and_store_noc_router_tile_positions(const DeviceGrid& device_grid, std::vector& list_of_noc_router_tiles, std::string noc_router_tile_name); +void identify_and_store_noc_router_tile_positions(const DeviceGrid& device_grid, std::vector& list_of_noc_router_tiles, const std::string& noc_router_tile_name); /** * @brief Creates NoC routers and adds them to the NoC model based diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 8580c9419ca..c44fc490ab3 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -41,7 +41,7 @@ Partition& VprConstraints::get_mutable_partition(PartitionId part_id) { std::vector VprConstraints::get_part_atoms(PartitionId part_id) const { std::vector part_atoms; - for (auto& it : constrained_atoms) { + for (const auto& it : constrained_atoms) { if (it.second == part_id) { part_atoms.push_back(it.first); } diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index 8e69b7b42b4..c1d3f33389b 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -35,7 +35,7 @@ void load_vpr_constraints_file(const char* read_vpr_constraints_name) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); floorplanning_ctx.constraints = reader.constraints_; - VprConstraints ctx_constraints = floorplanning_ctx.constraints; + const auto& ctx_constraints = floorplanning_ctx.constraints; if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_VPR_CONSTRAINTS)) { echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), ctx_constraints); diff --git a/vpr/src/base/vpr_constraints_writer.cpp b/vpr/src/base/vpr_constraints_writer.cpp index 056d0fd7151..073b02dc1f3 100644 --- a/vpr/src/base/vpr_constraints_writer.cpp +++ b/vpr/src/base/vpr_constraints_writer.cpp @@ -55,8 +55,7 @@ void setup_vpr_floorplan_constraints_one_loc(VprConstraints& constraints, int ex * The subtile can also optionally be set in the PartitionRegion, based on the value passed in by the user. */ for (auto blk_id : cluster_ctx.clb_nlist.blocks()) { - std::string part_name; - part_name = cluster_ctx.clb_nlist.block_name(blk_id); + const std::string& part_name = cluster_ctx.clb_nlist.block_name(blk_id); PartitionId partid(part_id); Partition part; @@ -65,7 +64,7 @@ void setup_vpr_floorplan_constraints_one_loc(VprConstraints& constraints, int ex PartitionRegion pr; Region reg; - auto loc = place_ctx.block_locs[blk_id].loc; + const auto& loc = place_ctx.block_locs[blk_id].loc; reg.set_region_rect({loc.x - expand, loc.y - expand, diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index 9db00bb4612..f99335c7c42 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -37,7 +37,19 @@ */ void write_vpr_floorplan_constraints(const char* file_name, int expand, bool subtile, int horizontal_partitions, int vertical_partitions); -//Generate constraints which lock all blocks to one location. +/** + * @brief Populates VprConstraints by creating a partition for each clustered block. + * All atoms in the clustered block are assigned to the same partition. The created partition + * for each clustered block would include the current location of the clustered block. The + * partition is expanded from four sides by "expand" blocks. + * + * @param constraints The VprConstraints to be populated. + * @param expand The amount the floorplan region will be expanded around the current + * x, y location of the block. Ex. if location is (1, 1) and expand = 1, + * the floorplan region will be from (0, 0) to (2, 2). + * @param subtile Specifies whether to write out the constraint regions with or without + * subtile values. + */ void setup_vpr_floorplan_constraints_one_loc(VprConstraints& constraints, int expand, bool subtile); /* Generate constraints which divide the grid into partition according to the horizontal and vertical partition values passed in diff --git a/vpr/src/noc/noc_traffic_flows.cpp b/vpr/src/noc/noc_traffic_flows.cpp index 426597bd71c..18b03444c91 100644 --- a/vpr/src/noc/noc_traffic_flows.cpp +++ b/vpr/src/noc/noc_traffic_flows.cpp @@ -54,11 +54,23 @@ const std::vector& NocTrafficFlows::get_all_traffic_flow_id(vo // setters for the traffic flows -void NocTrafficFlows::create_noc_traffic_flow(const std::string& source_router_module_name, const std::string& sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority) { +void NocTrafficFlows::create_noc_traffic_flow(const std::string& source_router_module_name, + const std::string& sink_router_module_name, + ClusterBlockId source_router_cluster_id, + ClusterBlockId sink_router_cluster_id, + double traffic_flow_bandwidth, + double traffic_flow_latency, + int traffic_flow_priority) { VTR_ASSERT_MSG(!built_traffic_flows, "NoC traffic flows have already been added, cannot modify further."); // create and add the new traffic flow to the vector - noc_traffic_flows.emplace_back(source_router_module_name, sink_router_module_name, source_router_cluster_id, sink_router_cluster_id, traffic_flow_bandwidth, traffic_flow_latency, traffic_flow_priority); + noc_traffic_flows.emplace_back(source_router_module_name, + sink_router_module_name, + source_router_cluster_id, + sink_router_cluster_id, + traffic_flow_bandwidth, + traffic_flow_latency, + traffic_flow_priority); //since the new traffic flow was added to the back of the vector, its id will be the index of the last element NocTrafficFlowId curr_traffic_flow_id = (NocTrafficFlowId)(noc_traffic_flows.size() - 1); diff --git a/vpr/src/noc/noc_traffic_flows.h b/vpr/src/noc/noc_traffic_flows.h index 8b433ef3599..c1c73f8884f 100644 --- a/vpr/src/noc/noc_traffic_flows.h +++ b/vpr/src/noc/noc_traffic_flows.h @@ -255,7 +255,13 @@ class NocTrafficFlows { * at the sink router. * @param traffic_flow_priority The importance of a given traffic flow. */ - void create_noc_traffic_flow(const std::string& source_router_module_name, const std::string& sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority); + void create_noc_traffic_flow(const std::string& source_router_module_name, + const std::string& sink_router_module_name, + ClusterBlockId source_router_cluster_id, + ClusterBlockId sink_router_cluster_id, + double traffic_flow_bandwidth, + double traffic_flow_latency, + int traffic_flow_priority); /** * @brief Copies the passed in router_cluster_id_in_netlist vector to the diff --git a/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp b/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp index b785d2c4da6..07bd53be7ce 100644 --- a/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp +++ b/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp @@ -76,7 +76,12 @@ void read_xml_noc_traffic_flows_file(const char* noc_flows_file) { return; } -void process_single_flow(pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const ClusteringContext& cluster_ctx, NocContext& noc_ctx, t_physical_tile_type_ptr noc_router_tile_type, const std::vector& cluster_blocks_compatible_with_noc_router_tiles) { +void process_single_flow(pugi::xml_node single_flow_tag, + const pugiutil::loc_data& loc_data, + const ClusteringContext& cluster_ctx, + NocContext& noc_ctx, + t_physical_tile_type_ptr noc_router_tile_type, + const std::vector& cluster_blocks_compatible_with_noc_router_tiles) { // contains all traffic flows NocTrafficFlows* noc_traffic_flow_storage = &noc_ctx.noc_traffic_flows_storage; @@ -113,7 +118,13 @@ void process_single_flow(pugi::xml_node single_flow_tag, const pugiutil::loc_dat verify_traffic_flow_properties(traffic_flow_bandwidth, max_traffic_flow_latency, traffic_flow_priority, single_flow_tag, loc_data); // The current flow information is legal, so store it - noc_traffic_flow_storage->create_noc_traffic_flow(source_router_module_name, sink_router_module_name, source_router_id, sink_router_id, traffic_flow_bandwidth, max_traffic_flow_latency, traffic_flow_priority); + noc_traffic_flow_storage->create_noc_traffic_flow(source_router_module_name, + sink_router_module_name, + source_router_id, + sink_router_id, + traffic_flow_bandwidth, + max_traffic_flow_latency, + traffic_flow_priority); return; } @@ -169,7 +180,7 @@ int get_traffic_flow_priority(pugi::xml_node single_flow_tag, const pugiutil::lo return traffic_flow_priority; } -void verify_traffic_flow_router_modules(std::string source_router_name, std::string sink_router_name, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data) { +void verify_traffic_flow_router_modules(const std::string& source_router_name, const std::string& sink_router_name, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data) { // check that the source router module name is not empty if (source_router_name == "") { vpr_throw(VPR_ERROR_OTHER, loc_data.filename_c_str(), loc_data.line(single_flow_tag), "Invalid name for the source NoC router module."); @@ -206,7 +217,11 @@ void verify_traffic_flow_properties(double traffic_flow_bandwidth, double max_tr return; } -ClusterBlockId get_router_module_cluster_id(std::string router_module_name, const ClusteringContext& cluster_ctx, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const std::vector& cluster_blocks_compatible_with_noc_router_tiles) { +ClusterBlockId get_router_module_cluster_id(const std::string& router_module_name, + const ClusteringContext& cluster_ctx, + pugi::xml_node single_flow_tag, + const pugiutil::loc_data& loc_data, + const std::vector& cluster_blocks_compatible_with_noc_router_tiles) { ClusterBlockId router_module_id = ClusterBlockId::INVALID(); // Given a regex pattern, use it to match a name of a cluster router block within the clustered netlist. If a matching cluster block is found, then return its cluster block id. @@ -226,7 +241,7 @@ ClusterBlockId get_router_module_cluster_id(std::string router_module_name, cons return router_module_id; } -void check_traffic_flow_router_module_type(std::string router_module_name, ClusterBlockId router_module_id, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const ClusteringContext& cluster_ctx, t_physical_tile_type_ptr noc_router_tile_type) { +void check_traffic_flow_router_module_type(const std::string& router_module_name, ClusterBlockId router_module_id, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const ClusteringContext& cluster_ctx, t_physical_tile_type_ptr noc_router_tile_type) { // get the logical type of the provided router module t_logical_block_type_ptr router_module_logical_type = cluster_ctx.clb_nlist.block_type(router_module_id); @@ -257,7 +272,7 @@ t_physical_tile_type_ptr get_physical_type_of_noc_router_tile(const DeviceContex physical_noc_router->get_router_layer_position()}); } -bool check_that_all_router_blocks_have_an_associated_traffic_flow(NocContext& noc_ctx, t_physical_tile_type_ptr noc_router_tile_type, std::string noc_flows_file) { +bool check_that_all_router_blocks_have_an_associated_traffic_flow(NocContext& noc_ctx, t_physical_tile_type_ptr noc_router_tile_type, const std::string& noc_flows_file) { bool result = true; // contains the number of all the noc router blocks in the design @@ -269,10 +284,10 @@ bool check_that_all_router_blocks_have_an_associated_traffic_flow(NocContext& no /* * Go through the router subtiles and get the router logical block types the subtiles support. Then determine how many of each router logical block types there are in the clustered netlist. The accumulated sum of all these clusters is the total number of router blocks in the design. */ - for (auto subtile = noc_router_subtiles->begin(); subtile != noc_router_subtiles->end(); subtile++) { - for (auto router_logical_block = subtile->equivalent_sites.begin(); router_logical_block != subtile->equivalent_sites.end(); router_logical_block++) { + for (const auto & noc_router_subtile : *noc_router_subtiles) { + for (auto router_logical_block : noc_router_subtile.equivalent_sites) { // get the number of logical blocks in the design of the current logical block type - number_of_router_blocks_in_design += clustered_netlist_stats.num_blocks_type[(*router_logical_block)->index]; + number_of_router_blocks_in_design += clustered_netlist_stats.num_blocks_type[router_logical_block->index]; } } @@ -299,14 +314,14 @@ std::vector get_cluster_blocks_compatible_with_noc_router_tiles( // vector to store all the cluster blocks ids that can be placed within a physical NoC router tile on the FPGA std::vector cluster_blocks_compatible_with_noc_router_tiles; - for (auto cluster_block_id = cluster_netlist_blocks.begin(); cluster_block_id != cluster_netlist_blocks.end(); cluster_block_id++) { + for (auto cluster_blk_id : cluster_netlist_blocks) { // get the logical type of the block - t_logical_block_type_ptr cluster_block_type = cluster_ctx.clb_nlist.block_type(*cluster_block_id); + t_logical_block_type_ptr cluster_block_type = cluster_ctx.clb_nlist.block_type(cluster_blk_id); // check if the current block is compatible with a NoC router tile // if it is, then this block is a NoC outer instantiated by the user in the design, so add it to the vector compatible blocks if (is_tile_compatible(noc_router_tile_type, cluster_block_type)) { - cluster_blocks_compatible_with_noc_router_tiles.push_back(*cluster_block_id); + cluster_blocks_compatible_with_noc_router_tiles.push_back(cluster_blk_id); } } diff --git a/vpr/src/noc/read_xml_noc_traffic_flows_file.h b/vpr/src/noc/read_xml_noc_traffic_flows_file.h index e8005665b3c..55cecc38bc1 100644 --- a/vpr/src/noc/read_xml_noc_traffic_flows_file.h +++ b/vpr/src/noc/read_xml_noc_traffic_flows_file.h @@ -142,7 +142,7 @@ int get_traffic_flow_priority(pugi::xml_node single_flow_tag, const pugiutil::lo * @param loc_data Contains location data about the current line in the xml * file. Passed in for error logging. */ -void verify_traffic_flow_router_modules(std::string source_router_name, std::string sink_router_name, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data); +void verify_traffic_flow_router_modules(const std::string& source_router_name, const std::string& sink_router_name, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data); /** * @brief Ensures the traffic flow's bandwidth, latency constraint and @@ -181,7 +181,11 @@ void verify_traffic_flow_properties(double traffic_flow_bandwidth, double max_tr * @return ClusterBlockId The corresponding router block id of the provided * router module name. */ -ClusterBlockId get_router_module_cluster_id(std::string router_module_name, const ClusteringContext& cluster_ctx, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const std::vector& cluster_blocks_compatible_with_noc_router_tiles); +ClusterBlockId get_router_module_cluster_id(const std::string& router_module_name, + const ClusteringContext& cluster_ctx, + pugi::xml_node single_flow_tag, + const pugiutil::loc_data& loc_data, + const std::vector& cluster_blocks_compatible_with_noc_router_tiles); /** * @brief Checks to see whether a given router block is compatible with a NoC @@ -204,7 +208,7 @@ ClusterBlockId get_router_module_cluster_id(std::string router_module_name, cons * FPGA. Used to check if the router block is * compatible with a router tile. */ -void check_traffic_flow_router_module_type(std::string router_module_name, ClusterBlockId router_module_id, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const ClusteringContext& cluster_ctx, t_physical_tile_type_ptr noc_router_tile_type); +void check_traffic_flow_router_module_type(const std::string& router_module_name, ClusterBlockId router_module_id, pugi::xml_node single_flow_tag, const pugiutil::loc_data& loc_data, const ClusteringContext& cluster_ctx, t_physical_tile_type_ptr noc_router_tile_type); /** * @brief Retrieves the physical type of a noc router tile. @@ -237,7 +241,7 @@ t_physical_tile_type_ptr get_physical_type_of_noc_router_tile(const DeviceContex * associated traffic flow. False means there are some router * blocks that do not have a an associated traffic flow. */ -bool check_that_all_router_blocks_have_an_associated_traffic_flow(NocContext& noc_ctx, t_physical_tile_type_ptr noc_router_tile_type, std::string noc_flows_file); +bool check_that_all_router_blocks_have_an_associated_traffic_flow(NocContext& noc_ctx, t_physical_tile_type_ptr noc_router_tile_type, const std::string& noc_flows_file); /** * @brief Goes through the blocks within the clustered netlist and identifies diff --git a/vpr/src/pack/attraction_groups.cpp b/vpr/src/pack/attraction_groups.cpp index e4bd17620e4..60e72546e51 100644 --- a/vpr/src/pack/attraction_groups.cpp +++ b/vpr/src/pack/attraction_groups.cpp @@ -1,7 +1,7 @@ #include "attraction_groups.h" AttractionInfo::AttractionInfo(bool attraction_groups_on) { - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); auto& atom_ctx = g_vpr_ctx.atom(); int num_parts = floorplanning_ctx.constraints.get_num_partitions(); @@ -33,7 +33,7 @@ AttractionInfo::AttractionInfo(bool attraction_groups_on) { } void AttractionInfo::create_att_groups_for_overfull_regions() { - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); auto& atom_ctx = g_vpr_ctx.atom(); int num_parts = floorplanning_ctx.constraints.get_num_partitions(); @@ -47,10 +47,10 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { atom_attraction_group.resize(num_atoms); fill(atom_attraction_group.begin(), atom_attraction_group.end(), AttractGroupId::INVALID()); - auto& overfull_regions = floorplanning_ctx.overfull_regions; + const auto& overfull_regions = floorplanning_ctx.overfull_regions; PartitionRegion overfull_regions_pr; - for (unsigned int i = 0; i < overfull_regions.size(); i++) { - overfull_regions_pr.add_to_part_region(overfull_regions[i]); + for (const auto & overfull_region : overfull_regions) { + overfull_regions_pr.add_to_part_region(overfull_region); } /* * Create a PartitionRegion that contains all the overfull regions so that you can @@ -88,7 +88,7 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { } void AttractionInfo::create_att_groups_for_all_regions() { - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); auto& atom_ctx = g_vpr_ctx.atom(); int num_parts = floorplanning_ctx.constraints.get_num_partitions(); @@ -137,8 +137,8 @@ void AttractionInfo::assign_atom_attraction_ids() { AttractionGroup att_group = attraction_groups[group_id]; - for (unsigned int iatom = 0; iatom < att_group.group_atoms.size(); iatom++) { - atom_attraction_group[att_group.group_atoms[iatom]] = group_id; + for (auto group_atom : att_group.group_atoms) { + atom_attraction_group[group_atom] = group_id; } } } diff --git a/vpr/src/pack/attraction_groups.h b/vpr/src/pack/attraction_groups.h index 109afa667cc..813d6e0fb1b 100644 --- a/vpr/src/pack/attraction_groups.h +++ b/vpr/src/pack/attraction_groups.h @@ -80,7 +80,7 @@ class AttractionInfo { int num_attraction_groups(); - int get_att_group_pulls(); + int get_att_group_pulls() const; void set_att_group_pulls(int num_pulls); @@ -101,7 +101,7 @@ class AttractionInfo { int att_group_pulls = 1; }; -inline int AttractionInfo::get_att_group_pulls() { +inline int AttractionInfo::get_att_group_pulls() const { return att_group_pulls; } diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 48fe7a9dd71..0c1891c7927 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -76,22 +76,21 @@ static void echo_clusters(char* filename) { cluster_atoms[clb_index].push_back(atom_blk_id); } - for (auto i = cluster_atoms.begin(); i != cluster_atoms.end(); i++) { - std::string cluster_name; - cluster_name = cluster_ctx.clb_nlist.block_name(i->first); - fprintf(fp, "Cluster %s Id: %zu \n", cluster_name.c_str(), size_t(i->first)); + for (auto & cluster_atom : cluster_atoms) { + const std::string& cluster_name = cluster_ctx.clb_nlist.block_name(cluster_atom.first); + fprintf(fp, "Cluster %s Id: %zu \n", cluster_name.c_str(), size_t(cluster_atom.first)); fprintf(fp, "\tAtoms in cluster: \n"); - int num_atoms = i->second.size(); + int num_atoms = cluster_atom.second.size(); for (auto j = 0; j < num_atoms; j++) { - AtomBlockId atom_id = i->second[j]; + AtomBlockId atom_id = cluster_atom.second[j]; fprintf(fp, "\t %s \n", atom_ctx.nlist.block_name(atom_id).c_str()); } } fprintf(fp, "\nCluster Floorplanning Constraints:\n"); - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); for (ClusterBlockId clb_id : cluster_ctx.clb_nlist.blocks()) { const std::vector& regions = floorplanning_ctx.cluster_constraints[clb_id].get_regions(); @@ -1318,9 +1317,6 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ PartitionId partid; partid = floorplanning_ctx.constraints.get_atom_partition(blk_id); - PartitionRegion atom_pr; - PartitionRegion cluster_pr; - //if the atom does not belong to a partition, it can be put in the cluster //regardless of what the cluster's PartitionRegion is because it has no constraints if (partid == PartitionId::INVALID()) { @@ -1331,12 +1327,12 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ return BLK_PASSED; } else { //get pr of that partition - atom_pr = floorplanning_ctx.constraints.get_partition_pr(partid); + const PartitionRegion& atom_pr = floorplanning_ctx.constraints.get_partition_pr(partid); //intersect it with the pr of the current cluster - cluster_pr = floorplanning_ctx.cluster_constraints[clb_index]; + PartitionRegion cluster_pr = floorplanning_ctx.cluster_constraints[clb_index]; - if (cluster_pr.empty() == true) { + if (cluster_pr.empty()) { temp_cluster_pr = atom_pr; cluster_pr_needs_update = true; if (verbosity > 3) { @@ -1349,7 +1345,7 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ update_cluster_part_reg(cluster_pr, atom_pr); } - if (cluster_pr.empty() == true) { + if (cluster_pr.empty()) { if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); } @@ -2036,7 +2032,7 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, const int num_models, const int max_cluster_size, const t_arch* arch, - std::string device_layout_name, + const std::string& device_layout_name, std::vector* lb_type_rr_graphs, t_lb_router_data** router_data, const int detailed_routing_stage, @@ -3466,10 +3462,10 @@ enum e_block_pack_status check_chain_root_placement_feasibility(const t_pb_graph } else { block_pack_status = BLK_FAILED_FEASIBLE; for (const auto& chain : chain_root_pins) { - for (size_t tieOff = 0; tieOff < chain.size(); tieOff++) { + for (auto tieOff : chain) { // check if this chosen primitive is one of the possible // starting points for this chain. - if (pb_graph_node == chain[tieOff]->parent_node) { + if (pb_graph_node == tieOff->parent_node) { // this location matches with the one of the dedicated chain // input from outside logic block, therefore it is feasible block_pack_status = BLK_PASSED; @@ -3624,7 +3620,7 @@ void update_le_count(const t_pb* pb, const t_logical_block_type_ptr logic_block_ * This function returns true if the given physical block has * a primitive matching the given blif model and is used */ -bool pb_used_for_blif_model(const t_pb* pb, std::string blif_model_name) { +bool pb_used_for_blif_model(const t_pb* pb, const std::string& blif_model_name) { auto pb_graph_node = pb->pb_graph_node; auto pb_type = pb_graph_node->pb_type; auto mode = &pb_type->modes[pb->mode]; diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index 6c05272e1e7..2f01e38b1e5 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -331,7 +331,7 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, const int num_models, const int max_cluster_size, const t_arch* arch, - std::string device_layout_name, + const std::string& device_layout_name, std::vector* lb_type_rr_graphs, t_lb_router_data** router_data, const int detailed_routing_stage, @@ -442,7 +442,7 @@ t_logical_block_type_ptr identify_logic_block_type(std::map& le_count, const t_pb_type* le_pb_type); diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 9fd61587cde..e561ca59365 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -27,7 +27,10 @@ /* #define DUMP_PB_GRAPH 1 */ /* #define DUMP_BLIF_INPUT 1 */ -static bool try_size_device_grid(const t_arch& arch, const std::map& num_type_instances, float target_device_utilization, std::string device_layout_name); +static bool try_size_device_grid(const t_arch& arch, + const std::map& num_type_instances, + float target_device_utilization, + const std::string& device_layout_name); /** * @brief Counts the total number of logic models that the architecture can implement. @@ -153,7 +156,7 @@ bool try_pack(t_packer_opts* packer_opts, * is not dense enough and there are floorplan constraints, it is presumed that the constraints are the cause * of the floorplan not fitting, so attraction groups are turned on for later iterations. */ - bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.mutable_floorplanning().constraints.get_num_partitions() > 0); + bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning().constraints.get_num_partitions() > 0); if (fits_on_device && !floorplan_regions_overfull) { break; //Done @@ -331,7 +334,10 @@ std::unordered_set alloc_and_load_is_clock(bool global_clocks) { return (is_clock); } -static bool try_size_device_grid(const t_arch& arch, const std::map& num_type_instances, float target_device_utilization, std::string device_layout_name) { +static bool try_size_device_grid(const t_arch& arch, + const std::map& num_type_instances, + float target_device_utilization, + const std::string& device_layout_name) { auto& device_ctx = g_vpr_ctx.mutable_device(); //Build the device diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index b7692581a61..7dec20a1d01 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -28,7 +28,7 @@ void report_aborted_moves() { if (f_move_abort_reasons.empty()) { VTR_LOG(" No moves aborted\n"); } - for (auto kv : f_move_abort_reasons) { + for (const auto& kv : f_move_abort_reasons) { VTR_LOG(" %s: %zu\n", kv.first.c_str(), kv.second); } } From 3777e5f420e3895237b3169415ec245caad00f4f Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 10:36:39 -0500 Subject: [PATCH 03/37] find noc router atoms --- vpr/src/pack/pack.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index e561ca59365..bd740b7821c 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -40,6 +40,26 @@ static bool try_size_device_grid(const t_arch& arch, */ static int count_models(const t_model* user_models); +static std::vector find_noc_router_atoms() { + const auto& atom_ctx = g_vpr_ctx.atom(); + + // NoC router atoms are expected to have a specific blif model + const std::string noc_router_blif_model_name = "noc_router_adapter_block"; + + // stores found NoC router atoms + std::vector noc_router_atoms; + + // iterate over all atoms and find those whose blif model matches + for (auto atom_id : atom_ctx.nlist.blocks()) { + const t_model* model = atom_ctx.nlist.block_model(atom_id); + if (noc_router_blif_model_name == model->name) { + noc_router_atoms.push_back(atom_id); + } + } + + return noc_router_atoms; +} + bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, const t_arch* arch, @@ -131,6 +151,11 @@ bool try_pack(t_packer_opts* packer_opts, int pack_iteration = 1; bool floorplan_regions_overfull = false; + auto noc_atoms = find_noc_router_atoms(); + for (auto noc_atom : noc_atoms) { + std::cout << "NoC Atom: " << atom_ctx.nlist.block_name(noc_atom) << std::endl; + } + while (true) { free_clustering_data(*packer_opts, clustering_data); From 71f85c5d980694f4f7003476eea885a0e5ef2cfe Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 13:06:05 -0500 Subject: [PATCH 04/37] add exclusivity index to PartitionRegion --- vpr/src/base/partition_region.cpp | 48 ++++++++++++++++++++++++++----- vpr/src/base/partition_region.h | 9 ++++-- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 2676b6d1035..77afc4fa5e7 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -36,6 +36,22 @@ bool PartitionRegion::is_loc_in_part_reg(const t_pl_loc& loc) const { return is_in_pr; } +int PartitionRegion::get_exclusivity_index() const { + return exclusivity_index; +} + +void PartitionRegion::set_exclusivity_index(int index) { + /* negative exclusivity index means this PartitionRegion is compatible + * with other PartitionsRegions as long as the intersection of their + * regions is not empty. + */ + if (index < 0) { + index = -1; + } + + exclusivity_index = index; +} + PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { /**for N regions in part_region and M in the calling object you can get anywhere from * 0 to M*N regions in the resulting vector. Only intersection regions with non-zero area rectangles and @@ -43,11 +59,20 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR * Rectangles are not merged even if it would be possible */ PartitionRegion pr; + + const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); + const int new_exclusivity = new_pr.get_exclusivity_index(); + + // PartitionRegion are not compatible even if their regions overlap + if (cluster_exclusivity != new_exclusivity) { + return pr; + } + auto& pr_regions = pr.get_mutable_regions(); - Region intersect_region; + for (const auto& cluster_region : cluster_pr.get_regions()) { for (const auto& new_region : new_pr.get_regions()) { - intersect_region = intersection(cluster_region, new_region); + Region intersect_region = intersection(cluster_region, new_region); if (!intersect_region.empty()) { pr_regions.push_back(intersect_region); } @@ -60,14 +85,23 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { std::vector int_regions; - for (const auto& cluster_region : cluster_pr.get_regions()) { - for (const auto& new_region : new_pr.get_regions()) { - Region intersect_region = intersection(cluster_region, new_region); - if (!intersect_region.empty()) { - int_regions.push_back(intersect_region); + const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); + const int new_exclusivity = new_pr.get_exclusivity_index(); + + // check whether PartitionRegions are compatible in the first place + if (cluster_exclusivity == new_exclusivity) { + + // now that we know PartitionRegions are compatible, look for overlapping regions + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + Region intersect_region = intersection(cluster_region, new_region); + if (!intersect_region.empty()) { + int_regions.push_back(intersect_region); + } } } } + cluster_pr.set_partition_region(int_regions); } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 2ea9796091b..ec4d24a065f 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -50,15 +50,20 @@ class PartitionRegion { */ bool is_loc_in_part_reg(const t_pl_loc& loc) const; + int get_exclusivity_index() const; + + void set_exclusivity_index(int index); + private: std::vector regions; ///< union of rectangular regions that a partition can be placed in + int exclusivity_index = -1; ///< PartitionRegions with different exclusivity_index values are not compatible }; ///@brief used to print data from a PartitionRegion void print_partition_region(FILE* fp, const PartitionRegion& pr); /** -* @brief Global friend function that returns the intersection of two PartitionRegions +* @brief Global function that returns the intersection of two PartitionRegions * * @param cluster_pr One of the PartitionRegions to be intersected * @param new_pr One of the PartitionRegions to be intersected @@ -66,7 +71,7 @@ void print_partition_region(FILE* fp, const PartitionRegion& pr); PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr); /** -* @brief Global friend function that updates the PartitionRegion of a cluster with the intersection +* @brief Global function that updates the PartitionRegion of a cluster with the intersection * of the cluster PartitionRegion and a new PartitionRegion * * @param cluster_pr The cluster PartitionRegion that is to be updated From 2917fca40ccc55423900c2174c5b551671e7d56f Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 14:12:34 -0500 Subject: [PATCH 05/37] add update_noc_reachability_partitions() --- vpr/src/pack/pack.cpp | 105 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index bd740b7821c..b491fe0d362 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "vtr_assert.h" #include "vtr_log.h" @@ -60,6 +62,104 @@ static std::vector find_noc_router_atoms() { return noc_router_atoms; } +static void update_noc_reachability_partitions(const std::vector& noc_atoms) { + const auto& atom_ctx = g_vpr_ctx.atom(); + auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; + const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + + const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); + + // get the total number of atoms + const size_t n_atoms = atom_ctx.nlist.blocks().size(); + + vtr::vector atom_visited(n_atoms, false); + + int exclusivity_cnt = 0; + + RegionRectCoord unconstrained_rect{std::numeric_limits::min(), + std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::max(), + -1}; + Region unconstrained_region; + unconstrained_region.set_region_rect(unconstrained_rect); + + for (auto noc_atom_id : noc_atoms) { + // check if this NoC router has already been visited + if (atom_visited[noc_atom_id]) { + continue; + } + + exclusivity_cnt++; + + PartitionRegion associated_noc_partition_region; + associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); + associated_noc_partition_region.add_to_part_region(unconstrained_region); + + Partition associated_noc_partition; + associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); + associated_noc_partition.set_part_region(associated_noc_partition_region); + auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); + constraints.add_partition(associated_noc_partition); + + const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); + + if (noc_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); + } else { // noc atom is already in a partition + auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); + auto& noc_partition_region = noc_partition.get_mutable_part_region(); + VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); + noc_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + std::queue q; + q.push(noc_atom_id); + atom_visited[noc_atom_id] = true; + + while (!q.empty()) { + AtomBlockId current_atom = q.front(); + q.pop(); + + PartitionId atom_partition_id = constraints.get_atom_partition(noc_atom_id); + if (atom_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(current_atom, associated_noc_partition_id); + } else { + auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); + auto& atom_partition_region = atom_partition.get_mutable_part_region(); + VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0); + atom_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { + AtomNetId net_id = atom_ctx.nlist.pin_net(pin); + size_t net_fanout = atom_ctx.nlist.net_sinks(net_id).size(); + + if (net_fanout >= high_fanout_threshold) { + continue; + } + + AtomBlockId driver_atom_id = atom_ctx.nlist.net_driver_block(net_id); + if (!atom_visited[driver_atom_id]) { + q.push(driver_atom_id); + atom_visited[driver_atom_id] = true; + } + + for (auto sink_pin : atom_ctx.nlist.net_sinks(net_id)) { + AtomBlockId sink_atom_id = atom_ctx.nlist.pin_block(sink_pin); + if (!atom_visited[sink_atom_id]) { + q.push(sink_atom_id); + atom_visited[sink_atom_id] = true; + } + } + + } + } + + } +} + + bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, const t_arch* arch, @@ -151,10 +251,9 @@ bool try_pack(t_packer_opts* packer_opts, int pack_iteration = 1; bool floorplan_regions_overfull = false; + // find all NoC router atoms auto noc_atoms = find_noc_router_atoms(); - for (auto noc_atom : noc_atoms) { - std::cout << "NoC Atom: " << atom_ctx.nlist.block_name(noc_atom) << std::endl; - } + update_noc_reachability_partitions(noc_atoms); while (true) { free_clustering_data(*packer_opts, clustering_data); From ca55771a81b54616af3949e8d2c2c30757d34a5e Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 14:24:20 -0500 Subject: [PATCH 06/37] changed unconstrained region coordinates --- vpr/src/pack/pack.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index b491fe0d362..67ab28d8bbc 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -66,6 +66,7 @@ static void update_noc_reachability_partitions(const std::vector& n const auto& atom_ctx = g_vpr_ctx.atom(); auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + const auto& device_ctx = g_vpr_ctx.device(); const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); @@ -76,10 +77,10 @@ static void update_noc_reachability_partitions(const std::vector& n int exclusivity_cnt = 0; - RegionRectCoord unconstrained_rect{std::numeric_limits::min(), - std::numeric_limits::min(), - std::numeric_limits::max(), - std::numeric_limits::max(), + RegionRectCoord unconstrained_rect{0, + 0, + (int)device_ctx.grid.width() - 1, + (int)device_ctx.grid.height() - 1, -1}; Region unconstrained_region; unconstrained_region.set_region_rect(unconstrained_rect); @@ -121,13 +122,14 @@ static void update_noc_reachability_partitions(const std::vector& n AtomBlockId current_atom = q.front(); q.pop(); - PartitionId atom_partition_id = constraints.get_atom_partition(noc_atom_id); + PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); if (atom_partition_id == PartitionId::INVALID()) { constraints.add_constrained_atom(current_atom, associated_noc_partition_id); } else { auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); auto& atom_partition_region = atom_partition.get_mutable_part_region(); - VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0); +// std::cout << "ss" << atom_partition_region.get_exclusivity_index() << std::endl; + VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); atom_partition_region.set_exclusivity_index(exclusivity_cnt); } From d5a98a4d25cca831df7805b0700cfa72efb718d0 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 15:56:08 -0500 Subject: [PATCH 07/37] bugfix: check if there is any unfixed Noc routers If all routers are constrained, place_noc_routers_randomly crashes. --- vpr/src/place/initial_noc_placement.cpp | 5 +++++ vpr/src/place/initial_placement.cpp | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index 9294f3b291b..a8c619f8dbd 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -103,6 +103,11 @@ static void place_noc_routers_randomly(std::vector& unfixed_rout * only once. */ + // check if all NoC routers have already been placed + if (unfixed_routers.empty()) { + return; + } + // Make a copy of NoC physical routers because we want to change its order vtr::vector noc_phy_routers = noc_ctx.noc_model.get_noc_routers(); diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index b9b97b1998f..30e3cc190ae 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -67,7 +67,11 @@ static void clear_all_grid_locs(); * * @return true if macro was placed, false if not. */ -static bool place_macro(int macros_max_num_tries, const t_pl_macro& pl_macro, enum e_pad_loc_type pad_loc_type, std::vector* blk_types_empty_locs_in_grid, vtr::vector& block_scores); +static bool place_macro(int macros_max_num_tries, + const t_pl_macro& pl_macro, + enum e_pad_loc_type pad_loc_type, + std::vector* blk_types_empty_locs_in_grid, + vtr::vector& block_scores); /* * Assign scores to each block based on macro size and floorplanning constraints. @@ -107,7 +111,10 @@ static int get_blk_type_first_loc(t_pl_loc& loc, const t_pl_macro& pl_macro, std * @param blk_types_empty_locs_in_grid first location (lowest y) and number of remaining blocks in each column for the blk_id type * */ -static void update_blk_type_first_loc(int blk_type_column_index, t_logical_block_type_ptr block_type, const t_pl_macro& pl_macro, std::vector* blk_types_empty_locs_in_grid); +static void update_blk_type_first_loc(int blk_type_column_index, + t_logical_block_type_ptr block_type, + const t_pl_macro& pl_macro, + std::vector* blk_types_empty_locs_in_grid); /** * @brief Initializes empty locations of the grid with a specific block type into vector for dense initial placement @@ -212,7 +219,8 @@ static void check_initial_placement_legality() { for (auto blk_id : cluster_ctx.clb_nlist.blocks()) { if (place_ctx.block_locs[blk_id].loc.x == INVALID_X) { - VTR_LOG("Block %s (# %d) of type %s could not be placed during initial placement iteration %d\n", cluster_ctx.clb_nlist.block_name(blk_id).c_str(), blk_id, cluster_ctx.clb_nlist.block_type(blk_id)->name, MAX_INIT_PLACE_ATTEMPTS - 1); + VTR_LOG("Block %s (# %d) of type %s could not be placed during initial placement iteration %d\n", + cluster_ctx.clb_nlist.block_name(blk_id).c_str(), blk_id, cluster_ctx.clb_nlist.block_type(blk_id)->name, MAX_INIT_PLACE_ATTEMPTS - 1); unplaced_blocks++; } } From 5eb7a07b2a4f39cff390d49019ada68309d67636 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 16 Feb 2024 16:44:41 -0500 Subject: [PATCH 08/37] clean modified cluster_constraints elements --- vpr/src/pack/pack.cpp | 24 +++++++++++++++++++----- vpr/src/place/place_constraints.cpp | 5 ++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 67ab28d8bbc..013edc51b77 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -66,7 +66,6 @@ static void update_noc_reachability_partitions(const std::vector& n const auto& atom_ctx = g_vpr_ctx.atom(); auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; - const auto& device_ctx = g_vpr_ctx.device(); const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); @@ -79,9 +78,9 @@ static void update_noc_reachability_partitions(const std::vector& n RegionRectCoord unconstrained_rect{0, 0, - (int)device_ctx.grid.width() - 1, - (int)device_ctx.grid.height() - 1, - -1}; + std::numeric_limits::max(), + std::numeric_limits::max(), + 0}; Region unconstrained_region; unconstrained_region.set_region_rect(unconstrained_rect); @@ -128,7 +127,6 @@ static void update_noc_reachability_partitions(const std::vector& n } else { auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); auto& atom_partition_region = atom_partition.get_mutable_part_region(); -// std::cout << "ss" << atom_partition_region.get_exclusivity_index() << std::endl; VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); atom_partition_region.set_exclusivity_index(exclusivity_cnt); } @@ -253,6 +251,7 @@ bool try_pack(t_packer_opts* packer_opts, int pack_iteration = 1; bool floorplan_regions_overfull = false; + auto constraints_backup = g_vpr_ctx.floorplanning().constraints; // find all NoC router atoms auto noc_atoms = find_noc_router_atoms(); update_noc_reachability_partitions(noc_atoms); @@ -398,6 +397,21 @@ bool try_pack(t_packer_opts* packer_opts, //check clustering and output it check_and_output_clustering(*packer_opts, is_clock, arch, helper_ctx.total_clb_num, clustering_data.intra_lb_routing); + + g_vpr_ctx.mutable_floorplanning().constraints = constraints_backup; + const int max_y = (int)g_vpr_ctx.device().grid.height(); + const int max_x = (int)g_vpr_ctx.device().grid.width(); + for (auto& cluster_partition_region : g_vpr_ctx.mutable_floorplanning().cluster_constraints) { + const auto& regions = cluster_partition_region.get_regions(); + if (regions.size() == 1) { + const auto rect = regions[0].get_region_rect(); + + if (rect.xmin <= 0 && rect.ymin <= 0 && rect.xmax >= max_x && rect.ymax >= max_y) { + cluster_partition_region = PartitionRegion(); + } + } + } + // Free Data Structures free_clustering_data(*packer_opts, clustering_data); diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index e1b153d9d71..6a425401718 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -33,8 +33,7 @@ int check_placement_floorplanning() { /*returns true if cluster has floorplanning constraints, false if it doesn't*/ bool is_cluster_constrained(ClusterBlockId blk_id) { auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); - PartitionRegion pr; - pr = floorplanning_ctx.cluster_constraints[blk_id]; + const PartitionRegion& pr = floorplanning_ctx.cluster_constraints[blk_id]; return (!pr.empty()); } @@ -250,7 +249,7 @@ void load_cluster_constraints() { PartitionRegion empty_pr; floorplanning_ctx.cluster_constraints[cluster_id] = empty_pr; - //if there are any constrainted atoms in the cluster, + //if there are any constrained atoms in the cluster, //we update the cluster's PartitionRegion for (auto atom : *atoms) { PartitionId partid = floorplanning_ctx.constraints.get_atom_partition(atom); From 895e34f2957b068f41a21e4d4abdb59c25929a0d Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 23 Feb 2024 15:40:51 -0500 Subject: [PATCH 09/37] revert noc-aware clustering --- vpr/src/pack/pack.cpp | 138 ------------------------------------------ 1 file changed, 138 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 013edc51b77..62558798ad5 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include "vtr_assert.h" #include "vtr_log.h" @@ -42,124 +40,6 @@ static bool try_size_device_grid(const t_arch& arch, */ static int count_models(const t_model* user_models); -static std::vector find_noc_router_atoms() { - const auto& atom_ctx = g_vpr_ctx.atom(); - - // NoC router atoms are expected to have a specific blif model - const std::string noc_router_blif_model_name = "noc_router_adapter_block"; - - // stores found NoC router atoms - std::vector noc_router_atoms; - - // iterate over all atoms and find those whose blif model matches - for (auto atom_id : atom_ctx.nlist.blocks()) { - const t_model* model = atom_ctx.nlist.block_model(atom_id); - if (noc_router_blif_model_name == model->name) { - noc_router_atoms.push_back(atom_id); - } - } - - return noc_router_atoms; -} - -static void update_noc_reachability_partitions(const std::vector& noc_atoms) { - const auto& atom_ctx = g_vpr_ctx.atom(); - auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; - const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; - - const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); - - // get the total number of atoms - const size_t n_atoms = atom_ctx.nlist.blocks().size(); - - vtr::vector atom_visited(n_atoms, false); - - int exclusivity_cnt = 0; - - RegionRectCoord unconstrained_rect{0, - 0, - std::numeric_limits::max(), - std::numeric_limits::max(), - 0}; - Region unconstrained_region; - unconstrained_region.set_region_rect(unconstrained_rect); - - for (auto noc_atom_id : noc_atoms) { - // check if this NoC router has already been visited - if (atom_visited[noc_atom_id]) { - continue; - } - - exclusivity_cnt++; - - PartitionRegion associated_noc_partition_region; - associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); - associated_noc_partition_region.add_to_part_region(unconstrained_region); - - Partition associated_noc_partition; - associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); - associated_noc_partition.set_part_region(associated_noc_partition_region); - auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); - constraints.add_partition(associated_noc_partition); - - const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); - - if (noc_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); - } else { // noc atom is already in a partition - auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); - auto& noc_partition_region = noc_partition.get_mutable_part_region(); - VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); - noc_partition_region.set_exclusivity_index(exclusivity_cnt); - } - - std::queue q; - q.push(noc_atom_id); - atom_visited[noc_atom_id] = true; - - while (!q.empty()) { - AtomBlockId current_atom = q.front(); - q.pop(); - - PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); - if (atom_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(current_atom, associated_noc_partition_id); - } else { - auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); - auto& atom_partition_region = atom_partition.get_mutable_part_region(); - VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); - atom_partition_region.set_exclusivity_index(exclusivity_cnt); - } - - for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { - AtomNetId net_id = atom_ctx.nlist.pin_net(pin); - size_t net_fanout = atom_ctx.nlist.net_sinks(net_id).size(); - - if (net_fanout >= high_fanout_threshold) { - continue; - } - - AtomBlockId driver_atom_id = atom_ctx.nlist.net_driver_block(net_id); - if (!atom_visited[driver_atom_id]) { - q.push(driver_atom_id); - atom_visited[driver_atom_id] = true; - } - - for (auto sink_pin : atom_ctx.nlist.net_sinks(net_id)) { - AtomBlockId sink_atom_id = atom_ctx.nlist.pin_block(sink_pin); - if (!atom_visited[sink_atom_id]) { - q.push(sink_atom_id); - atom_visited[sink_atom_id] = true; - } - } - - } - } - - } -} - - bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, const t_arch* arch, @@ -252,9 +132,6 @@ bool try_pack(t_packer_opts* packer_opts, bool floorplan_regions_overfull = false; auto constraints_backup = g_vpr_ctx.floorplanning().constraints; - // find all NoC router atoms - auto noc_atoms = find_noc_router_atoms(); - update_noc_reachability_partitions(noc_atoms); while (true) { free_clustering_data(*packer_opts, clustering_data); @@ -397,21 +274,6 @@ bool try_pack(t_packer_opts* packer_opts, //check clustering and output it check_and_output_clustering(*packer_opts, is_clock, arch, helper_ctx.total_clb_num, clustering_data.intra_lb_routing); - - g_vpr_ctx.mutable_floorplanning().constraints = constraints_backup; - const int max_y = (int)g_vpr_ctx.device().grid.height(); - const int max_x = (int)g_vpr_ctx.device().grid.width(); - for (auto& cluster_partition_region : g_vpr_ctx.mutable_floorplanning().cluster_constraints) { - const auto& regions = cluster_partition_region.get_regions(); - if (regions.size() == 1) { - const auto rect = regions[0].get_region_rect(); - - if (rect.xmin <= 0 && rect.ymin <= 0 && rect.xmax >= max_x && rect.ymax >= max_y) { - cluster_partition_region = PartitionRegion(); - } - } - } - // Free Data Structures free_clustering_data(*packer_opts, clustering_data); From f778c8723399b4b1480c23d91bb1ffa6749a3a3c Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Fri, 23 Feb 2024 15:49:52 -0500 Subject: [PATCH 10/37] remove exclusivity_index and fix some typos --- vpr/src/base/partition_region.cpp | 43 ++++------------------------- vpr/src/base/partition_region.h | 5 ---- vpr/src/base/setup_noc.cpp | 8 +++--- vpr/src/pack/attraction_groups.cpp | 2 +- vpr/src/pack/cluster_util.cpp | 4 +-- vpr/src/place/place_constraints.cpp | 14 +++++----- 6 files changed, 20 insertions(+), 56 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 77afc4fa5e7..1f0c9dbd62c 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -36,22 +36,6 @@ bool PartitionRegion::is_loc_in_part_reg(const t_pl_loc& loc) const { return is_in_pr; } -int PartitionRegion::get_exclusivity_index() const { - return exclusivity_index; -} - -void PartitionRegion::set_exclusivity_index(int index) { - /* negative exclusivity index means this PartitionRegion is compatible - * with other PartitionsRegions as long as the intersection of their - * regions is not empty. - */ - if (index < 0) { - index = -1; - } - - exclusivity_index = index; -} - PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { /**for N regions in part_region and M in the calling object you can get anywhere from * 0 to M*N regions in the resulting vector. Only intersection regions with non-zero area rectangles and @@ -60,14 +44,6 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR */ PartitionRegion pr; - const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); - const int new_exclusivity = new_pr.get_exclusivity_index(); - - // PartitionRegion are not compatible even if their regions overlap - if (cluster_exclusivity != new_exclusivity) { - return pr; - } - auto& pr_regions = pr.get_mutable_regions(); for (const auto& cluster_region : cluster_pr.get_regions()) { @@ -85,19 +61,12 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { std::vector int_regions; - const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); - const int new_exclusivity = new_pr.get_exclusivity_index(); - - // check whether PartitionRegions are compatible in the first place - if (cluster_exclusivity == new_exclusivity) { - - // now that we know PartitionRegions are compatible, look for overlapping regions - for (const auto& cluster_region : cluster_pr.get_regions()) { - for (const auto& new_region : new_pr.get_regions()) { - Region intersect_region = intersection(cluster_region, new_region); - if (!intersect_region.empty()) { - int_regions.push_back(intersect_region); - } + // now that we know PartitionRegions are compatible, look for overlapping regions + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + Region intersect_region = intersection(cluster_region, new_region); + if (!intersect_region.empty()) { + int_regions.push_back(intersect_region); } } } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index ec4d24a065f..db73d2d7f09 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -50,13 +50,8 @@ class PartitionRegion { */ bool is_loc_in_part_reg(const t_pl_loc& loc) const; - int get_exclusivity_index() const; - - void set_exclusivity_index(int index); - private: std::vector regions; ///< union of rectangular regions that a partition can be placed in - int exclusivity_index = -1; ///< PartitionRegions with different exclusivity_index values are not compatible }; ///@brief used to print data from a PartitionRegion diff --git a/vpr/src/base/setup_noc.cpp b/vpr/src/base/setup_noc.cpp index de3bbb6840c..a2975b9683c 100644 --- a/vpr/src/base/setup_noc.cpp +++ b/vpr/src/base/setup_noc.cpp @@ -139,7 +139,7 @@ void create_noc_routers(const t_noc_inf& noc_info, NocStorage* noc_model, std::v double curr_logical_router_position_x; double curr_logical_router_position_y; - // keep track of the index of each physical router (this helps uniqely identify them) + // keep track of the index of each physical router (this helps uniquely identify them) int curr_physical_router_index = 0; // keep track of the ids of the routers that create the case where multiple routers have the same distance to a physical router tile @@ -153,7 +153,7 @@ void create_noc_routers(const t_noc_inf& noc_info, NocStorage* noc_model, std::v // Below we create all the routers within the NoC // - // go through each user desctibed router in the arch file and assign it to a physical router on the FPGA + // go through each user described router in the arch file and assign it to a physical router on the FPGA for (auto logical_router = noc_info.router_list.begin(); logical_router != noc_info.router_list.end(); logical_router++) { // assign the shortest distance to a large value (this is done so that the first distance calculated and we can replace this) shortest_distance = LLONG_MAX; @@ -173,7 +173,7 @@ void create_noc_routers(const t_noc_inf& noc_info, NocStorage* noc_model, std::v error_case_physical_router_index_2 = INVALID_PHYSICAL_ROUTER_INDEX; // determine the physical router tile that is closest to the current user described router in the arch file - for (auto & physical_router : noc_router_tiles) { + for (auto& physical_router : noc_router_tiles) { // get the position of the current physical router tile on the FPGA device curr_physical_router_pos_x = physical_router.tile_centroid_x; curr_physical_router_pos_y = physical_router.tile_centroid_y; @@ -237,7 +237,7 @@ void create_noc_links(const t_noc_inf* noc_info, NocStorage* noc_model) { noc_model->make_room_for_noc_router_link_list(); // go through each router and add its outgoing links to the NoC - for (const auto & router : noc_info->router_list) { + for (const auto& router : noc_info->router_list) { // get the converted id of the current source router source_router = noc_model->convert_router_id(router.id); diff --git a/vpr/src/pack/attraction_groups.cpp b/vpr/src/pack/attraction_groups.cpp index 60e72546e51..b8f0351d6a7 100644 --- a/vpr/src/pack/attraction_groups.cpp +++ b/vpr/src/pack/attraction_groups.cpp @@ -49,7 +49,7 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { const auto& overfull_regions = floorplanning_ctx.overfull_regions; PartitionRegion overfull_regions_pr; - for (const auto & overfull_region : overfull_regions) { + for (const auto& overfull_region : overfull_regions) { overfull_regions_pr.add_to_part_region(overfull_region); } /* diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 0c1891c7927..84dd08f3a0e 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -76,7 +76,7 @@ static void echo_clusters(char* filename) { cluster_atoms[clb_index].push_back(atom_blk_id); } - for (auto & cluster_atom : cluster_atoms) { + for (auto& cluster_atom : cluster_atoms) { const std::string& cluster_name = cluster_ctx.clb_nlist.block_name(cluster_atom.first); fprintf(fp, "Cluster %s Id: %zu \n", cluster_name.c_str(), size_t(cluster_atom.first)); fprintf(fp, "\tAtoms in cluster: \n"); @@ -96,7 +96,7 @@ static void echo_clusters(char* filename) { const std::vector& regions = floorplanning_ctx.cluster_constraints[clb_id].get_regions(); if (!regions.empty()) { fprintf(fp, "\nRegions in Cluster %zu:\n", size_t(clb_id)); - for (const auto & region : regions) { + for (const auto& region : regions) { print_region(fp, region); } } diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 6a425401718..72f7925ff28 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -41,7 +41,7 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) { bool is_macro_constrained = false; bool is_member_constrained = false; - for (const auto & member : pl_macro.members) { + for (const auto& member : pl_macro.members) { ClusterBlockId iblk = member.blk_index; is_member_constrained = is_cluster_constrained(iblk); @@ -61,7 +61,7 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition int num_constrained_members = 0; auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); - for (const auto & member : pl_macro.members) { + for (const auto& member : pl_macro.members) { ClusterBlockId iblk = member.blk_index; is_member_constrained = is_cluster_constrained(iblk); @@ -75,7 +75,7 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition const PartitionRegion& block_pr = floorplanning_ctx.cluster_constraints[iblk]; const std::vector& block_regions = block_pr.get_regions(); - for (const auto & block_region : block_regions) { + for (const auto& block_region : block_regions) { Region modified_reg; auto offset = member.offset; @@ -118,7 +118,7 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs const std::vector& block_regions = head_pr.get_regions(); PartitionRegion macro_pr; - for (const auto & block_region : block_regions) { + for (const auto& block_region : block_regions) { Region modified_reg; const auto block_reg_coord = block_region.get_region_rect(); @@ -153,7 +153,7 @@ void print_macro_constraint_error(const t_pl_macro& pl_macro) { VTR_LOG( "Feasible floorplanning constraints could not be calculated for the placement macro. \n" "The placement macro contains the following blocks: \n"); - for (const auto & member : pl_macro.members) { + for (const auto& member : pl_macro.members) { std::string blk_name = cluster_ctx.clb_nlist.block_name((member.blk_index)); VTR_LOG("Block %s (#%zu) ", blk_name.c_str(), size_t(member.blk_index)); } @@ -371,7 +371,7 @@ int region_tile_cover(const Region& reg, t_logical_block_type_ptr block_type, t_ } /* - * Used when marking fixed blocks to check whether the ParitionRegion associated with a block + * Used when marking fixed blocks to check whether the PartitionRegion associated with a block * covers one tile. If it covers one tile, it is marked as fixed. If it covers 0 tiles or * more than one tile, it will not be marked as fixed. As soon as it is known that the * PartitionRegion covers more than one tile, there is no need to check further regions @@ -441,7 +441,7 @@ int get_part_reg_size(PartitionRegion& pr, t_logical_block_type_ptr block_type, const std::vector& regions = pr.get_regions(); int num_tiles = 0; - for (const auto & region : regions) { + for (const auto& region : regions) { num_tiles += grid_tiles.region_tile_count(region, block_type); } From f23d7b5457365ed8d75caf73106ffdf0ffccb372 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 26 Feb 2024 10:08:52 -0500 Subject: [PATCH 11/37] Revert "remove exclusivity_index and fix some typos" This reverts commit f778c8723399b4b1480c23d91bb1ffa6749a3a3c. --- vpr/src/base/partition_region.cpp | 43 ++++++++++++++++++++++++++----- vpr/src/base/partition_region.h | 5 ++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 1f0c9dbd62c..77afc4fa5e7 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -36,6 +36,22 @@ bool PartitionRegion::is_loc_in_part_reg(const t_pl_loc& loc) const { return is_in_pr; } +int PartitionRegion::get_exclusivity_index() const { + return exclusivity_index; +} + +void PartitionRegion::set_exclusivity_index(int index) { + /* negative exclusivity index means this PartitionRegion is compatible + * with other PartitionsRegions as long as the intersection of their + * regions is not empty. + */ + if (index < 0) { + index = -1; + } + + exclusivity_index = index; +} + PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { /**for N regions in part_region and M in the calling object you can get anywhere from * 0 to M*N regions in the resulting vector. Only intersection regions with non-zero area rectangles and @@ -44,6 +60,14 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR */ PartitionRegion pr; + const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); + const int new_exclusivity = new_pr.get_exclusivity_index(); + + // PartitionRegion are not compatible even if their regions overlap + if (cluster_exclusivity != new_exclusivity) { + return pr; + } + auto& pr_regions = pr.get_mutable_regions(); for (const auto& cluster_region : cluster_pr.get_regions()) { @@ -61,12 +85,19 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { std::vector int_regions; - // now that we know PartitionRegions are compatible, look for overlapping regions - for (const auto& cluster_region : cluster_pr.get_regions()) { - for (const auto& new_region : new_pr.get_regions()) { - Region intersect_region = intersection(cluster_region, new_region); - if (!intersect_region.empty()) { - int_regions.push_back(intersect_region); + const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); + const int new_exclusivity = new_pr.get_exclusivity_index(); + + // check whether PartitionRegions are compatible in the first place + if (cluster_exclusivity == new_exclusivity) { + + // now that we know PartitionRegions are compatible, look for overlapping regions + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + Region intersect_region = intersection(cluster_region, new_region); + if (!intersect_region.empty()) { + int_regions.push_back(intersect_region); + } } } } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index db73d2d7f09..ec4d24a065f 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -50,8 +50,13 @@ class PartitionRegion { */ bool is_loc_in_part_reg(const t_pl_loc& loc) const; + int get_exclusivity_index() const; + + void set_exclusivity_index(int index); + private: std::vector regions; ///< union of rectangular regions that a partition can be placed in + int exclusivity_index = -1; ///< PartitionRegions with different exclusivity_index values are not compatible }; ///@brief used to print data from a PartitionRegion From 5dd2025f02f32edcfc37f516c299dbb262e27310 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 26 Feb 2024 10:09:12 -0500 Subject: [PATCH 12/37] Revert "revert noc-aware clustering" This reverts commit 895e34f2957b068f41a21e4d4abdb59c25929a0d. --- vpr/src/pack/pack.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 62558798ad5..013edc51b77 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "vtr_assert.h" #include "vtr_log.h" @@ -40,6 +42,124 @@ static bool try_size_device_grid(const t_arch& arch, */ static int count_models(const t_model* user_models); +static std::vector find_noc_router_atoms() { + const auto& atom_ctx = g_vpr_ctx.atom(); + + // NoC router atoms are expected to have a specific blif model + const std::string noc_router_blif_model_name = "noc_router_adapter_block"; + + // stores found NoC router atoms + std::vector noc_router_atoms; + + // iterate over all atoms and find those whose blif model matches + for (auto atom_id : atom_ctx.nlist.blocks()) { + const t_model* model = atom_ctx.nlist.block_model(atom_id); + if (noc_router_blif_model_name == model->name) { + noc_router_atoms.push_back(atom_id); + } + } + + return noc_router_atoms; +} + +static void update_noc_reachability_partitions(const std::vector& noc_atoms) { + const auto& atom_ctx = g_vpr_ctx.atom(); + auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; + const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + + const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); + + // get the total number of atoms + const size_t n_atoms = atom_ctx.nlist.blocks().size(); + + vtr::vector atom_visited(n_atoms, false); + + int exclusivity_cnt = 0; + + RegionRectCoord unconstrained_rect{0, + 0, + std::numeric_limits::max(), + std::numeric_limits::max(), + 0}; + Region unconstrained_region; + unconstrained_region.set_region_rect(unconstrained_rect); + + for (auto noc_atom_id : noc_atoms) { + // check if this NoC router has already been visited + if (atom_visited[noc_atom_id]) { + continue; + } + + exclusivity_cnt++; + + PartitionRegion associated_noc_partition_region; + associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); + associated_noc_partition_region.add_to_part_region(unconstrained_region); + + Partition associated_noc_partition; + associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); + associated_noc_partition.set_part_region(associated_noc_partition_region); + auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); + constraints.add_partition(associated_noc_partition); + + const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); + + if (noc_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); + } else { // noc atom is already in a partition + auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); + auto& noc_partition_region = noc_partition.get_mutable_part_region(); + VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); + noc_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + std::queue q; + q.push(noc_atom_id); + atom_visited[noc_atom_id] = true; + + while (!q.empty()) { + AtomBlockId current_atom = q.front(); + q.pop(); + + PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); + if (atom_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(current_atom, associated_noc_partition_id); + } else { + auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); + auto& atom_partition_region = atom_partition.get_mutable_part_region(); + VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); + atom_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { + AtomNetId net_id = atom_ctx.nlist.pin_net(pin); + size_t net_fanout = atom_ctx.nlist.net_sinks(net_id).size(); + + if (net_fanout >= high_fanout_threshold) { + continue; + } + + AtomBlockId driver_atom_id = atom_ctx.nlist.net_driver_block(net_id); + if (!atom_visited[driver_atom_id]) { + q.push(driver_atom_id); + atom_visited[driver_atom_id] = true; + } + + for (auto sink_pin : atom_ctx.nlist.net_sinks(net_id)) { + AtomBlockId sink_atom_id = atom_ctx.nlist.pin_block(sink_pin); + if (!atom_visited[sink_atom_id]) { + q.push(sink_atom_id); + atom_visited[sink_atom_id] = true; + } + } + + } + } + + } +} + + bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, const t_arch* arch, @@ -132,6 +252,9 @@ bool try_pack(t_packer_opts* packer_opts, bool floorplan_regions_overfull = false; auto constraints_backup = g_vpr_ctx.floorplanning().constraints; + // find all NoC router atoms + auto noc_atoms = find_noc_router_atoms(); + update_noc_reachability_partitions(noc_atoms); while (true) { free_clustering_data(*packer_opts, clustering_data); @@ -274,6 +397,21 @@ bool try_pack(t_packer_opts* packer_opts, //check clustering and output it check_and_output_clustering(*packer_opts, is_clock, arch, helper_ctx.total_clb_num, clustering_data.intra_lb_routing); + + g_vpr_ctx.mutable_floorplanning().constraints = constraints_backup; + const int max_y = (int)g_vpr_ctx.device().grid.height(); + const int max_x = (int)g_vpr_ctx.device().grid.width(); + for (auto& cluster_partition_region : g_vpr_ctx.mutable_floorplanning().cluster_constraints) { + const auto& regions = cluster_partition_region.get_regions(); + if (regions.size() == 1) { + const auto rect = regions[0].get_region_rect(); + + if (rect.xmin <= 0 && rect.ymin <= 0 && rect.xmax >= max_x && rect.ymax >= max_y) { + cluster_partition_region = PartitionRegion(); + } + } + } + // Free Data Structures free_clustering_data(*packer_opts, clustering_data); From 0d0d311f5f2f3692149ddd35b6156c0444718051 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 26 Feb 2024 10:13:50 -0500 Subject: [PATCH 13/37] reduced fanout threshold in update_noc_reachability_partitions() --- vpr/src/pack/pack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 013edc51b77..36b911f393d 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -65,9 +65,9 @@ static std::vector find_noc_router_atoms() { static void update_noc_reachability_partitions(const std::vector& noc_atoms) { const auto& atom_ctx = g_vpr_ctx.atom(); auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; - const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; +// const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; - const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(""); + const size_t high_fanout_threshold = 32; //;high_fanout_thresholds.get_threshold(""); // get the total number of atoms const size_t n_atoms = atom_ctx.nlist.blocks().size(); From e4168ee3de4cae8f61945d4e9cec46294fa5d4e7 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Tue, 27 Feb 2024 15:55:35 -0500 Subject: [PATCH 14/37] ignore reset --- vpr/src/place/place.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 2e30d2f3c43..e60f2c3a153 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -618,6 +618,13 @@ void try_place(const Netlist<>& net_list, num_swap_aborted = 0; num_ts_called = 0; + for (auto net_id : cluster_ctx.clb_nlist.nets()) { + if (cluster_ctx.clb_nlist.net_name(net_id) == "reset") { + g_vpr_ctx.mutable_clustering().clb_nlist.set_net_is_global(net_id, true); + g_vpr_ctx.mutable_clustering().clb_nlist.set_net_is_ignored(net_id, true); + } + } + if (placer_opts.place_algorithm.is_timing_driven()) { /*do this before the initial placement to avoid messing up the initial placement */ place_delay_model = alloc_lookups_and_delay_model(net_list, From 04e2f2aaec985ff24d96ad3487cae7dcd28d2409 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 28 Feb 2024 12:37:16 -0500 Subject: [PATCH 15/37] lock NoC routers and constrain other blocks --- vpr/src/place/initial_noc_placement.cpp | 71 +++++++++++++++++++++++++ vpr/src/place/initial_placement.cpp | 1 + 2 files changed, 72 insertions(+) diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index a8c619f8dbd..ba09c456ca5 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -5,6 +5,9 @@ #include "noc_place_checkpoint.h" #include "vtr_math.h" +#include +#include + /** * @brief Evaluates whether a NoC router swap should be accepted or not. * If delta cost is non-positive, the move is always accepted. If the cost @@ -251,6 +254,7 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts) { void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { auto& noc_ctx = g_vpr_ctx.noc(); + auto& cluster_ctx = g_vpr_ctx.clustering(); // Get all the router clusters const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); @@ -280,4 +284,71 @@ void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { // Run the simulated annealing optimizer for NoC routers noc_routers_anneal(noc_opts); + + auto& device_ctx = g_vpr_ctx.device(); + + for (auto router_blk_id : router_blk_ids) { + g_vpr_ctx.mutable_placement().block_locs[router_blk_id].is_fixed = true; + + vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); + + std::queue q; + q.push(router_blk_id); + block_visited[router_blk_id] = true; + + const auto& noc_loc = g_vpr_ctx.placement().block_locs[router_blk_id].loc; + + const int height = device_ctx.grid.height(); + const int width = device_ctx.grid.width(); + + RegionRectCoord rect_coord{std::max(0, noc_loc.x - 20), + std::max(0, noc_loc.y - 20), + std::min(width-1, noc_loc.x + 20), + std::min(height-1, noc_loc.y + 20), 0}; + Region region; + region.set_region_rect(rect_coord); + + while (!q.empty()) { + ClusterBlockId current_block_id = q.front(); + q.pop(); + + auto block_type = cluster_ctx.clb_nlist.block_type(current_block_id); + if (std::strcmp(block_type->name, "io") != 0) { + auto& constraint = g_vpr_ctx.mutable_floorplanning().cluster_constraints[current_block_id]; + constraint.add_to_part_region(region); + } + + for (ClusterPinId pin_id : cluster_ctx.clb_nlist.block_pins(current_block_id)) { + ClusterNetId net_id = cluster_ctx.clb_nlist.pin_net(pin_id); + + if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) { + continue; + } + + if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= 32) { + continue; + } + + if (cluster_ctx.clb_nlist.pin_type(pin_id) == PinType::DRIVER) { + //ignore nets that are globally routed + + for (auto sink_pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) { + auto sink_block_id = cluster_ctx.clb_nlist.pin_block(sink_pin_id); + if (!block_visited[sink_block_id]) { + block_visited[sink_block_id] = true; + q.push(sink_block_id); + } + } + } else { //else the pin is sink --> only care about its driver + ClusterPinId source_pin = cluster_ctx.clb_nlist.net_driver(net_id); + auto source_blk_id = cluster_ctx.clb_nlist.pin_block(source_pin); + if (!block_visited[source_blk_id]) { + block_visited[source_blk_id] = true; + q.push(source_blk_id); + } + } + } + } + + } } \ No newline at end of file diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 30e3cc190ae..8c75deb0713 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -1123,6 +1123,7 @@ void initial_placement(const t_placer_opts& placer_opts, if (noc_opts.noc) { // NoC routers are placed before other blocks initial_noc_placement(noc_opts, placer_opts.seed); + propagate_place_constraints(); } //Assign scores to blocks and placement macros according to how difficult they are to place From 5a541046247b17b42b3d078980729545ba61a834 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sat, 16 Mar 2024 13:25:14 -0400 Subject: [PATCH 16/37] replace constant 32 with high fanout threshold for logic blocks --- vpr/src/pack/pack.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 36b911f393d..25ef26f996c 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -65,9 +65,12 @@ static std::vector find_noc_router_atoms() { static void update_noc_reachability_partitions(const std::vector& noc_atoms) { const auto& atom_ctx = g_vpr_ctx.atom(); auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; -// const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + const auto& device_ctx = g_vpr_ctx.device(); + const auto& grid = device_ctx.grid; - const size_t high_fanout_threshold = 32; //;high_fanout_thresholds.get_threshold(""); + t_logical_block_type_ptr logic_block_type = infer_logic_block_type(grid); + const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logic_block_type->name); // get the total number of atoms const size_t n_atoms = atom_ctx.nlist.blocks().size(); From c379041626e8e2cda045b0c7e4723627241e6c02 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sat, 16 Mar 2024 13:25:51 -0400 Subject: [PATCH 17/37] add NoC groups --- vpr/src/base/vpr_context.h | 8 +++++ vpr/src/noc/noc_data_types.h | 3 ++ vpr/src/place/initial_noc_placement.cpp | 41 ++++++++++++------------- vpr/src/place/initial_noc_placment.h | 2 +- vpr/src/place/initial_placement.cpp | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 18420590f2e..a1d3c8e446f 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -413,6 +413,14 @@ struct PlacementContext : public Context { * it would mean that per-layer bounding box is used. For the 2D architecture, the cube bounding box would be used. */ bool cube_bb = false; + + + vtr::vector> noc_group_clusters; + + vtr::vector> noc_group_routers; + + std::map noc_router_to_noc_group; + }; /** diff --git a/vpr/src/noc/noc_data_types.h b/vpr/src/noc/noc_data_types.h index 86135ca77cb..5478048e59b 100644 --- a/vpr/src/noc/noc_data_types.h +++ b/vpr/src/noc/noc_data_types.h @@ -24,4 +24,7 @@ struct noc_traffic_flow_id_tag; /** Datatype to index traffic flows within the application */ typedef vtr::StrongId NocTrafficFlowId; +struct noc_group_id_tag; +typedef vtr::StrongId NocGroupId; + #endif \ No newline at end of file diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index ba09c456ca5..d8f2f42f820 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -252,12 +252,13 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts) { } } -void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { +void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& placer_opts) { auto& noc_ctx = g_vpr_ctx.noc(); auto& cluster_ctx = g_vpr_ctx.clustering(); // Get all the router clusters const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); + const auto router_block_type = cluster_ctx.clb_nlist.block_type(router_blk_ids[0]); // Holds all the routers that are not fixed into a specific location by constraints std::vector unfixed_routers; @@ -277,7 +278,7 @@ void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { } // Place unconstrained NoC routers randomly - place_noc_routers_randomly(unfixed_routers, seed); + place_noc_routers_randomly(unfixed_routers, placer_opts.seed); // populate internal data structures to maintain route, bandwidth usage, and latencies initial_noc_routing(); @@ -285,37 +286,35 @@ void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { // Run the simulated annealing optimizer for NoC routers noc_routers_anneal(noc_opts); - auto& device_ctx = g_vpr_ctx.device(); + vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); + auto& place_ctx = g_vpr_ctx.mutable_placement(); + int noc_group_cnt = 0; for (auto router_blk_id : router_blk_ids) { - g_vpr_ctx.mutable_placement().block_locs[router_blk_id].is_fixed = true; - vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); + if (block_visited[router_blk_id]) { + continue; + } + + NocGroupId noc_group_id(noc_group_cnt); + noc_group_cnt++; + place_ctx.noc_group_routers.emplace_back(); + place_ctx.noc_group_clusters.emplace_back(); std::queue q; q.push(router_blk_id); block_visited[router_blk_id] = true; - const auto& noc_loc = g_vpr_ctx.placement().block_locs[router_blk_id].loc; - - const int height = device_ctx.grid.height(); - const int width = device_ctx.grid.width(); - - RegionRectCoord rect_coord{std::max(0, noc_loc.x - 20), - std::max(0, noc_loc.y - 20), - std::min(width-1, noc_loc.x + 20), - std::min(height-1, noc_loc.y + 20), 0}; - Region region; - region.set_region_rect(rect_coord); - while (!q.empty()) { ClusterBlockId current_block_id = q.front(); q.pop(); auto block_type = cluster_ctx.clb_nlist.block_type(current_block_id); - if (std::strcmp(block_type->name, "io") != 0) { - auto& constraint = g_vpr_ctx.mutable_floorplanning().cluster_constraints[current_block_id]; - constraint.add_to_part_region(region); + if (block_type->index == router_block_type->index) { + place_ctx.noc_group_routers[noc_group_id].push_back(current_block_id); + place_ctx.noc_router_to_noc_group[current_block_id] = noc_group_id; + } else { + place_ctx.noc_group_clusters[noc_group_id].push_back(current_block_id); } for (ClusterPinId pin_id : cluster_ctx.clb_nlist.block_pins(current_block_id)) { @@ -325,7 +324,7 @@ void initial_noc_placement(const t_noc_opts& noc_opts, int seed) { continue; } - if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= 32) { + if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= placer_opts.place_high_fanout_net) { continue; } diff --git a/vpr/src/place/initial_noc_placment.h b/vpr/src/place/initial_noc_placment.h index 4f060a14277..7727f15f6aa 100644 --- a/vpr/src/place/initial_noc_placment.h +++ b/vpr/src/place/initial_noc_placment.h @@ -10,6 +10,6 @@ * * @param noc_opts NoC-related options. Used to calculate NoC-related costs. */ -void initial_noc_placement(const t_noc_opts& noc_opts, int seed); +void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& placer_opts); #endif //VTR_INITIAL_NOC_PLACMENT_H diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 8c75deb0713..752136ca65c 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -1122,7 +1122,7 @@ void initial_placement(const t_placer_opts& placer_opts, if (noc_opts.noc) { // NoC routers are placed before other blocks - initial_noc_placement(noc_opts, placer_opts.seed); + initial_noc_placement(noc_opts, placer_opts); propagate_place_constraints(); } From d76e92e18e8681a1b0bb321bf8061789b0221774 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 17 Mar 2024 17:24:02 -0400 Subject: [PATCH 18/37] add noc group move --- vpr/src/place/noc_group_move_generator.cpp | 84 ++++++++++++++++++++++ vpr/src/place/noc_group_move_generator.h | 16 +++++ vpr/src/place/place.cpp | 8 ++- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 vpr/src/place/noc_group_move_generator.cpp create mode 100644 vpr/src/place/noc_group_move_generator.h diff --git a/vpr/src/place/noc_group_move_generator.cpp b/vpr/src/place/noc_group_move_generator.cpp new file mode 100644 index 00000000000..77fc528b82d --- /dev/null +++ b/vpr/src/place/noc_group_move_generator.cpp @@ -0,0 +1,84 @@ + +#include "noc_group_move_generator.h" + +#include "move_utils.h" +#include "place_constraints.h" + +e_create_move NocGroupMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* criticalities) { + const auto& noc_ctx = g_vpr_ctx.noc(); + auto& place_ctx = g_vpr_ctx.placement(); + const auto& cluster_ctx = g_vpr_ctx.clustering(); + + e_create_move create_move; + + const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); + + const ClusterBlockId selected_noc_router_blk_id = router_blk_ids[vtr::irand(router_blk_ids.size()-1)]; + const NocGroupId noc_group_id = place_ctx.noc_router_to_noc_group.find(selected_noc_router_blk_id)->second; + + const auto& group_routers = place_ctx.noc_group_routers[noc_group_id]; + const auto& group_clusters = place_ctx.noc_group_clusters[noc_group_id]; + + std::cout << "Group routers: " << group_routers.size() << ", group clusters: " << group_clusters.size() << std::endl; + + for (auto block_id : group_clusters) { + ClusterBlockId router_blk_id = group_routers[vtr::irand(group_routers.size()-1)]; + t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; + t_block_loc block_loc = place_ctx.block_locs[block_id]; + + t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(block_id); + const auto& compressed_block_grid = place_ctx.compressed_block_grids[block_type->index]; + + std::vector router_compressed_loc = get_compressed_loc_approx(compressed_block_grid, + router_loc.loc, + 1); + + //Determine the coordinates in the compressed grid space of the current block + std::vector block_compressed_loc = get_compressed_loc_approx(compressed_block_grid, + block_loc.loc, + 1); + + auto search_range = get_compressed_grid_target_search_range(compressed_block_grid, + router_compressed_loc[0], + 20); + + int delta_cx = search_range.xmax - search_range.xmin; + + bool legal = find_compatible_compressed_loc_in_range(block_type, + delta_cx, + block_compressed_loc[0], + search_range, + router_compressed_loc[0], + false, + 0, + true); + + if (!legal) { + continue; + } + + t_pl_loc to_loc; + compressed_grid_to_loc(block_type, router_compressed_loc[0], to_loc); + + create_move = ::create_move(blocks_affected, block_id, to_loc); + std::cout << "number of affected blocks: " << blocks_affected.num_moved_blocks << std::endl; + if (create_move == e_create_move::ABORT) { + std::cout << "clear" << std::endl; + clear_move_blocks(blocks_affected); + return e_create_move::ABORT; + } + } + + //Check that all the blocks affected by the move would still be in a legal floorplan region after the swap + if (!floorplan_legal(blocks_affected)) { + return e_create_move::ABORT; + } + + + std::cout << "number of affected blocks: " << blocks_affected.num_moved_blocks << std::endl; + return create_move; +} \ No newline at end of file diff --git a/vpr/src/place/noc_group_move_generator.h b/vpr/src/place/noc_group_move_generator.h new file mode 100644 index 00000000000..7ae6041f0a3 --- /dev/null +++ b/vpr/src/place/noc_group_move_generator.h @@ -0,0 +1,16 @@ +#ifndef VTR_NOC_GROUP_MOVE_GENERATOR_H +#define VTR_NOC_GROUP_MOVE_GENERATOR_H + +#include "move_generator.h" + + +class NocGroupMoveGenerator : public MoveGenerator { + public: + e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* criticalities) override; +}; + +#endif //VTR_NOC_GROUP_MOVE_GENERATOR_H \ No newline at end of file diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index e60f2c3a153..468f9b997aa 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -70,6 +70,8 @@ #include "noc_place_utils.h" +#include "noc_group_move_generator.h" + /* define the RL agent's reward function factor constant. This factor controls the weight of bb cost * * compared to the timing cost in the agent's reward function. The reward is calculated as * * -1*(1.5-REWARD_BB_TIMING_RELATIVE_WEIGHT)*timing_cost + (1+REWARD_BB_TIMING_RELATIVE_WEIGHT)*bb_cost) @@ -1721,7 +1723,9 @@ static e_move_result try_swap(const t_annealing_state* state, #endif //NO_GRAPHICS } else if (router_block_move) { // generate a move where two random router blocks are swapped - create_move_outcome = propose_router_swap(blocks_affected, rlim); +// create_move_outcome = propose_router_swap(blocks_affected, rlim); + NocGroupMoveGenerator noc_group_move_gen; + noc_group_move_gen.propose_move(blocks_affected, proposed_action, 20, placer_opts, criticalities); proposed_action.move_type = e_move_type::UNIFORM; } else { //Generate a new move (perturbation) used to explore the space of possible placements @@ -1960,6 +1964,8 @@ static e_move_result try_swap(const t_annealing_state* state, if (!router_block_move) { calculate_reward_and_process_outcome(placer_opts, move_outcome_stats, delta_c, timing_bb_factor, move_generator); + } else { + std::cout << "Group move delta cost: " << delta_c << std::endl; } #ifdef VTR_ENABLE_DEBUG_LOGGING From eeac6c55f8cb96d2609b7373f9d2497475c1b492 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 17 Mar 2024 21:31:48 -0400 Subject: [PATCH 19/37] fix repetitive locs in NocGroupMoveGenerator --- vpr/src/place/move_utils.cpp | 10 +- vpr/src/place/move_utils.h | 6 +- vpr/src/place/noc_group_move_generator.cpp | 114 ++++++++++++++------- 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 7dec20a1d01..cd10f26320a 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -1035,12 +1035,12 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, to_loc = t_pl_loc(grid_loc.x, grid_loc.y, sub_tile, grid_loc.layer_num); } -bool has_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physical_tile_loc& to_loc) { +int has_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physical_tile_loc& to_loc) { auto& device_ctx = g_vpr_ctx.device(); auto& place_ctx = g_vpr_ctx.placement(); const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; - bool legal = false; + int return_sub_tile = -1; t_pl_loc to_uncompressed_loc; compressed_grid_to_loc(type, to_loc, to_uncompressed_loc); @@ -1049,12 +1049,12 @@ bool has_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physica const auto& compatible_sub_tiles = compressed_block_grid.compatible_sub_tiles_for_tile.at(phy_type->index); for (const auto& sub_tile : compatible_sub_tiles) { if (place_ctx.grid_blocks.is_sub_tile_empty(to_phy_uncompressed_loc, sub_tile)) { - legal = true; + return_sub_tile = sub_tile; break; } } - return legal; + return return_sub_tile; } bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, @@ -1147,7 +1147,7 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, if (from_loc.x == to_loc.x && from_loc.y == to_loc.y && from_loc.layer_num == to_layer_num) { continue; //Same from/to location -- try again for new y-position } else if (search_for_empty) { // Check if the location has at least one empty sub-tile - legal = has_empty_compatible_subtile(type, to_loc); + legal = has_empty_compatible_subtile(type, to_loc) >= 0; } else { legal = true; } diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index 3ff8e729833..9d7e98b1e24 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -232,8 +232,8 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, * * @return bool True if the given location has at least one empty compatible subtile. */ -bool has_empty_compatible_subtile(t_logical_block_type_ptr type, - const t_physical_tile_loc& to_loc); +int has_empty_compatible_subtile(t_logical_block_type_ptr type, + const t_physical_tile_loc& to_loc); /** * @brief find compressed location in a compressed range for a specific type in the given layer (to_layer_num) @@ -247,7 +247,7 @@ bool has_empty_compatible_subtile(t_logical_block_type_ptr type, * search_for_empty: indicates that the returned location must be empty */ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, - const int delta_cx, + int delta_cx, const t_physical_tile_loc& from_loc, t_bb search_range, t_physical_tile_loc& to_loc, diff --git a/vpr/src/place/noc_group_move_generator.cpp b/vpr/src/place/noc_group_move_generator.cpp index 77fc528b82d..7b0ee1c0e1b 100644 --- a/vpr/src/place/noc_group_move_generator.cpp +++ b/vpr/src/place/noc_group_move_generator.cpp @@ -13,59 +13,102 @@ e_create_move NocGroupMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block auto& place_ctx = g_vpr_ctx.placement(); const auto& cluster_ctx = g_vpr_ctx.clustering(); - e_create_move create_move; + e_create_move create_move = e_create_move::ABORT; const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); - const ClusterBlockId selected_noc_router_blk_id = router_blk_ids[vtr::irand(router_blk_ids.size()-1)]; + const ClusterBlockId selected_noc_router_blk_id = router_blk_ids[vtr::irand(router_blk_ids.size() - 1)]; const NocGroupId noc_group_id = place_ctx.noc_router_to_noc_group.find(selected_noc_router_blk_id)->second; const auto& group_routers = place_ctx.noc_group_routers[noc_group_id]; const auto& group_clusters = place_ctx.noc_group_clusters[noc_group_id]; - std::cout << "Group routers: " << group_routers.size() << ", group clusters: " << group_clusters.size() << std::endl; + auto& device_ctx = g_vpr_ctx.device(); + auto& grid = device_ctx.grid; + const int num_layers = grid.get_num_layers(); - for (auto block_id : group_clusters) { - ClusterBlockId router_blk_id = group_routers[vtr::irand(group_routers.size()-1)]; - t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; - t_block_loc block_loc = place_ctx.block_locs[block_id]; + //Collect the set of x/y locations for each instance of a block type + //[group_noc_router_idx][logical_block_type][layer_num][0...num_instance_on_layer] -> (x, y), sub-tile + std::vector, int>>>>> block_locations; + block_locations.resize(group_routers.size()); - t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(block_id); - const auto& compressed_block_grid = place_ctx.compressed_block_grids[block_type->index]; + for (size_t group_noc_router_idx = 0; group_noc_router_idx < group_routers.size(); group_noc_router_idx++) { + block_locations[group_noc_router_idx].resize(device_ctx.logical_block_types.size()); + for (int block_type_num = 0; block_type_num < (int)device_ctx.logical_block_types.size(); block_type_num++) { + block_locations[group_noc_router_idx][block_type_num].resize(num_layers); + } + } - std::vector router_compressed_loc = get_compressed_loc_approx(compressed_block_grid, - router_loc.loc, - 1); - //Determine the coordinates in the compressed grid space of the current block - std::vector block_compressed_loc = get_compressed_loc_approx(compressed_block_grid, - block_loc.loc, - 1); + for (size_t group_noc_router_idx = 0; group_noc_router_idx < group_routers.size(); group_noc_router_idx++) { + ClusterBlockId router_blk_id = group_routers[group_noc_router_idx]; + t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; + const int half_length = 10; + int min_x = std::max(router_loc.loc.x - half_length, 0); + int max_x = std::min(router_loc.loc.x + half_length, device_ctx.grid.width() - 1); + int min_y = std::max(router_loc.loc.y - half_length, 0); + int max_y = std::min(router_loc.loc.y + half_length, device_ctx.grid.height() - 1); + int layer_num = router_loc.loc.layer; + + for (int x = min_x; x < max_x; ++x) { + for (int y = min_y; y < max_y; ++y) { + int width_offset = grid.get_width_offset({x, y, layer_num}); + int height_offset = grid.get_height_offset(t_physical_tile_loc(x, y, layer_num)); + if (width_offset == 0 && height_offset == 0) { + const auto& type = grid.get_physical_type({x, y, layer_num}); + auto equivalent_sites = get_equivalent_sites_set(type); + + for (auto& block : equivalent_sites) { + + const auto& compressed_block_grid = place_ctx.compressed_block_grids[block->index]; + std::vector router_compressed_loc = get_compressed_loc_approx(compressed_block_grid, + {x, y, 0, layer_num}, + num_layers); + + int sub_tile = has_empty_compatible_subtile(block, router_compressed_loc[layer_num]); + if (sub_tile >= 0) { + block_locations[group_noc_router_idx][block->index][layer_num].push_back({{x, y}, sub_tile}); + } + + } + } + } + } + } - auto search_range = get_compressed_grid_target_search_range(compressed_block_grid, - router_compressed_loc[0], - 20); + std::set tried_locs; - int delta_cx = search_range.xmax - search_range.xmin; + for (auto block_id : group_clusters) { + int i_macro; + get_imacro_from_iblk(&i_macro, block_id, place_ctx.pl_macros); + if (i_macro != -1) { + continue; + } - bool legal = find_compatible_compressed_loc_in_range(block_type, - delta_cx, - block_compressed_loc[0], - search_range, - router_compressed_loc[0], - false, - 0, - true); + int group_noc_router_idx = vtr::irand(group_routers.size()-1); + ClusterBlockId router_blk_id = group_routers[group_noc_router_idx]; + t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; + + int layer_num = router_loc.loc.layer; - if (!legal) { + t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(block_id); + + size_t n_points = block_locations[group_noc_router_idx][block_type->index][layer_num].size(); + if (n_points == 0) { +// std::cout << "No empty blocks around the selected NoC router" << std::endl; continue; } + int point_idx = vtr::irand(n_points - 1); + auto selected_empty_point = block_locations[group_noc_router_idx][block_type->index][layer_num][point_idx]; - t_pl_loc to_loc; - compressed_grid_to_loc(block_type, router_compressed_loc[0], to_loc); - + t_pl_loc to_loc{selected_empty_point.first.x(), selected_empty_point.first.y(), selected_empty_point.second, layer_num}; + block_locations[group_noc_router_idx][block_type->index][layer_num].erase(block_locations[group_noc_router_idx][block_type->index][layer_num].begin() + point_idx); create_move = ::create_move(blocks_affected, block_id, to_loc); - std::cout << "number of affected blocks: " << blocks_affected.num_moved_blocks << std::endl; + + bool added = tried_locs.insert(to_loc).second; + if (!added) { + std::cout << "repetitive" << std::endl; + } if (create_move == e_create_move::ABORT) { std::cout << "clear" << std::endl; clear_move_blocks(blocks_affected); @@ -73,12 +116,13 @@ e_create_move NocGroupMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block } } + + //Check that all the blocks affected by the move would still be in a legal floorplan region after the swap if (!floorplan_legal(blocks_affected)) { + std::cout << "illegal floorplan" << std::endl; return e_create_move::ABORT; } - - std::cout << "number of affected blocks: " << blocks_affected.num_moved_blocks << std::endl; return create_move; } \ No newline at end of file From 9dd89eb8194753a171a75c23edeb1cf51322c5f7 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 17 Mar 2024 21:36:04 -0400 Subject: [PATCH 20/37] centroid moves consider noc routers --- vpr/src/base/vpr_context.h | 2 ++ vpr/src/place/directed_moves_util.cpp | 11 +++++++++++ vpr/src/place/initial_noc_placement.cpp | 3 +++ vpr/src/place/place.cpp | 11 ++--------- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index a1d3c8e446f..68bb3f8ec80 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -419,6 +419,8 @@ struct PlacementContext : public Context { vtr::vector> noc_group_routers; + vtr::vector cluster_to_noc_grp; + std::map noc_router_to_noc_group; }; diff --git a/vpr/src/place/directed_moves_util.cpp b/vpr/src/place/directed_moves_util.cpp index 330f1904368..b501291ad69 100644 --- a/vpr/src/place/directed_moves_util.cpp +++ b/vpr/src/place/directed_moves_util.cpp @@ -19,6 +19,7 @@ void get_coordinate_of_pin(ClusterPinId pin, t_physical_tile_loc& tile_loc) { void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc& centroid, const PlacerCriticalities* criticalities) { auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& place_ctx = g_vpr_ctx.placement(); t_physical_tile_loc tile_loc; int ipin; @@ -28,6 +29,16 @@ void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc float acc_layer = 0; float weight = 1; + if (place_ctx.cluster_to_noc_grp[b_from] != NocGroupId::INVALID()) { + NocGroupId noc_grp_id = place_ctx.cluster_to_noc_grp[b_from]; + for (ClusterBlockId router_blk_id : place_ctx.noc_group_routers[noc_grp_id]) { + t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; + acc_x += router_loc.loc.x; + acc_y += router_loc.loc.y; + acc_weight += 1.0f; + } + } + int from_block_layer_num = g_vpr_ctx.placement().block_locs[b_from].loc.layer; VTR_ASSERT(from_block_layer_num != OPEN); diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index d8f2f42f820..ae2e1d4d202 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -289,6 +289,7 @@ void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& plac vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); auto& place_ctx = g_vpr_ctx.mutable_placement(); int noc_group_cnt = 0; + place_ctx.cluster_to_noc_grp.resize(cluster_ctx.clb_nlist.blocks().size(), NocGroupId ::INVALID()); for (auto router_blk_id : router_blk_ids) { @@ -315,8 +316,10 @@ void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& plac place_ctx.noc_router_to_noc_group[current_block_id] = noc_group_id; } else { place_ctx.noc_group_clusters[noc_group_id].push_back(current_block_id); + place_ctx.cluster_to_noc_grp[current_block_id] = noc_group_id; } + for (ClusterPinId pin_id : cluster_ctx.clb_nlist.block_pins(current_block_id)) { ClusterNetId net_id = cluster_ctx.clb_nlist.pin_net(pin_id); diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 468f9b997aa..e7114e420bb 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -620,13 +620,6 @@ void try_place(const Netlist<>& net_list, num_swap_aborted = 0; num_ts_called = 0; - for (auto net_id : cluster_ctx.clb_nlist.nets()) { - if (cluster_ctx.clb_nlist.net_name(net_id) == "reset") { - g_vpr_ctx.mutable_clustering().clb_nlist.set_net_is_global(net_id, true); - g_vpr_ctx.mutable_clustering().clb_nlist.set_net_is_ignored(net_id, true); - } - } - if (placer_opts.place_algorithm.is_timing_driven()) { /*do this before the initial placement to avoid messing up the initial placement */ place_delay_model = alloc_lookups_and_delay_model(net_list, @@ -1725,7 +1718,7 @@ static e_move_result try_swap(const t_annealing_state* state, // generate a move where two random router blocks are swapped // create_move_outcome = propose_router_swap(blocks_affected, rlim); NocGroupMoveGenerator noc_group_move_gen; - noc_group_move_gen.propose_move(blocks_affected, proposed_action, 20, placer_opts, criticalities); + create_move_outcome = noc_group_move_gen.propose_move(blocks_affected, proposed_action, 20, placer_opts, criticalities); proposed_action.move_type = e_move_type::UNIFORM; } else { //Generate a new move (perturbation) used to explore the space of possible placements @@ -1965,7 +1958,7 @@ static e_move_result try_swap(const t_annealing_state* state, calculate_reward_and_process_outcome(placer_opts, move_outcome_stats, delta_c, timing_bb_factor, move_generator); } else { - std::cout << "Group move delta cost: " << delta_c << std::endl; +// std::cout << "Group move delta cost: " << delta_c << std::endl; } #ifdef VTR_ENABLE_DEBUG_LOGGING From 09bcc42b23534d3b167384dbd9b19f4e8cc39db5 Mon Sep 17 00:00:00 2001 From: soheil Date: Mon, 18 Mar 2024 00:37:09 -0400 Subject: [PATCH 21/37] add noc_centroid_weight --- vpr/src/base/SetupVPR.cpp | 1 + vpr/src/base/read_options.cpp | 7 ++++++ vpr/src/base/read_options.h | 1 + vpr/src/base/vpr_context.h | 2 ++ vpr/src/base/vpr_types.h | 1 + vpr/src/place/directed_moves_util.cpp | 30 ++++++++++++++++--------- vpr/src/place/initial_noc_placement.cpp | 1 + 7 files changed, 33 insertions(+), 10 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index a93b648f87b..a685a3ba828 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -739,6 +739,7 @@ static void SetupNocOpts(const t_options& Options, t_noc_opts* NocOpts) { NocOpts->noc_latency_weighting = Options.noc_latency_weighting; NocOpts->noc_congestion_weighting = Options.noc_congestion_weighting; NocOpts->noc_swap_percentage = Options.noc_swap_percentage; + NocOpts->noc_centroid_weight = Options.noc_centroid_weight; NocOpts->noc_placement_file_name = Options.noc_placement_file_name; return; diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index fc01cd4bb96..87d1b08c87d 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -2859,6 +2859,13 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .default_value("0") .show_in(argparse::ShowIn::HELP_ONLY); + noc_grp.add_argument(args.noc_centroid_weight, "--noc_centroid_weight") + .help( + "Sets the minimum fraction of swaps attempted by the placer that are NoC blocks." + "This value is an integer ranging from 0-100. 0 means NoC blocks will be moved at the same rate as other blocks. 100 means all swaps attempted by the placer are NoC router blocks.") + .default_value("0") + .show_in(argparse::ShowIn::HELP_ONLY); + noc_grp.add_argument(args.noc_placement_file_name, "--noc_placement_file_name") .help( "Name of the output file that contains the NoC placement information." diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index e6476ba151e..b7ea1e5acc8 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -157,6 +157,7 @@ struct t_options { argparse::ArgValue noc_latency_weighting; argparse::ArgValue noc_congestion_weighting; argparse::ArgValue noc_swap_percentage; + argparse::ArgValue noc_centroid_weight; argparse::ArgValue noc_placement_file_name; /* Timing-driven placement options only */ diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 68bb3f8ec80..1fbffc0a835 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -423,6 +423,8 @@ struct PlacementContext : public Context { std::map noc_router_to_noc_group; + float noc_centroid_weight; + }; /** diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index d36c0cf887d..e64c80214bd 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1504,6 +1504,7 @@ struct t_noc_opts { double noc_latency_weighting; /// Date: Mon, 18 Mar 2024 01:38:05 -0400 Subject: [PATCH 22/37] fix noc weight in centroid calculation --- vpr/src/place/directed_moves_util.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/place/directed_moves_util.cpp b/vpr/src/place/directed_moves_util.cpp index 7086007ace2..4193b9be859 100644 --- a/vpr/src/place/directed_moves_util.cpp +++ b/vpr/src/place/directed_moves_util.cpp @@ -105,9 +105,9 @@ void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc for (ClusterBlockId router_blk_id : place_ctx.noc_group_routers[noc_grp_id]) { t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; - acc_x += router_loc.loc.x; - acc_y += router_loc.loc.y; - acc_weight += 1.0f; + acc_x += router_loc.loc.x * single_noc_weight; + acc_y += router_loc.loc.y * single_noc_weight; + acc_weight += single_noc_weight; } } } From d7ad61240a11cfdf771cbb9dc06f791f7afe0e59 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 18 Mar 2024 13:19:49 -0400 Subject: [PATCH 23/37] const ref --- libs/libvtrutil/src/vtr_error.h | 5 +++-- libs/libvtrutil/src/vtr_expr_eval.cpp | 29 +++++++++++---------------- libs/libvtrutil/src/vtr_expr_eval.h | 2 +- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/libs/libvtrutil/src/vtr_error.h b/libs/libvtrutil/src/vtr_error.h index d710c66305d..f13d46bcdb7 100644 --- a/libs/libvtrutil/src/vtr_error.h +++ b/libs/libvtrutil/src/vtr_error.h @@ -3,6 +3,7 @@ #include #include +#include /** * @file @@ -34,9 +35,9 @@ namespace vtr { class VtrError : public std::runtime_error { public: ///@brief VtrError constructor - VtrError(std::string msg = "", std::string new_filename = "", size_t new_linenumber = -1) + VtrError(const std::string& msg = "", std::string new_filename = "", size_t new_linenumber = -1) : std::runtime_error(msg) - , filename_(new_filename) + , filename_(std::move(new_filename)) , linenumber_(new_linenumber) {} /** diff --git a/libs/libvtrutil/src/vtr_expr_eval.cpp b/libs/libvtrutil/src/vtr_expr_eval.cpp index 165b9caa51a..791319f4367 100644 --- a/libs/libvtrutil/src/vtr_expr_eval.cpp +++ b/libs/libvtrutil/src/vtr_expr_eval.cpp @@ -58,13 +58,13 @@ static bool is_char_number(const char ch); static bool is_operator(const char ch); // returns true if the specified name is a known function operator -static bool is_function(std::string name); +static bool is_function(const std::string& name); // returns true if the specified name is a known compound operator t_compound_operator is_compound_op(const char* ch); // returns true if the specified name is a known variable -static bool is_variable(std::string var); +static bool is_variable(const std::string& var); // returns the length of any identifier (e.g. name, function) starting at the beginning of str static int identifier_length(const char* str); @@ -76,14 +76,14 @@ static bool goto_next_char(int* str_ind, const string& pw_formula, char ch); bool same_string(std::string str1, std::string str2); //checks if the block indicated by the user was one of the moved blocks in the last perturbation -int in_blocks_affected(std::string expression_left); +int in_blocks_affected(const std::string& expression_left); //the function of += operator bool additional_assignment_op(int arg1, int arg2); /**** Function Implementations ****/ /* returns integer result according to specified non-piece-wise formula and data */ -int FormulaParser::parse_formula(std::string formula, const t_formula_data& mydata, bool is_breakpoint) { +int FormulaParser::parse_formula(const std::string& formula, const t_formula_data& mydata, bool is_breakpoint) { int result = -1; /* output in reverse-polish notation */ @@ -150,7 +150,7 @@ int FormulaParser::parse_piecewise_formula(const char* formula, const t_formula_ } tmp_ind_count = str_ind - tmp_ind_start; /* range start is between { and : */ substr = pw_formula.substr(tmp_ind_start, tmp_ind_count); - range_start = parse_formula(substr.c_str(), mydata); + range_start = parse_formula(substr, mydata); /* get the end of the range */ tmp_ind_start = str_ind + 1; @@ -160,7 +160,7 @@ int FormulaParser::parse_piecewise_formula(const char* formula, const t_formula_ } tmp_ind_count = str_ind - tmp_ind_start; /* range end is between : and } */ substr = pw_formula.substr(tmp_ind_start, tmp_ind_count); - range_end = parse_formula(substr.c_str(), mydata); + range_end = parse_formula(substr, mydata); if (range_start > range_end) { throw vtr::VtrError(vtr::string_fmt("parse_piecewise_formula: range_start, %d, is bigger than range end, %d\n", range_start, range_end), __FILE__, __LINE__); @@ -287,8 +287,6 @@ static void formula_to_rpn(const char* formula, const t_formula_data& mydata, ve rpn_output.push_back(fobj_dummy); op_stack.pop(); } - - return; } /* Fills the formula object fobj according to specified character and mydata, @@ -352,7 +350,7 @@ static void get_formula_object(const char* ch, int& ichar, const t_formula_data& } ichar--; fobj->type = E_FML_NUMBER; - fobj->data.num = vtr::atoi(ss.str().c_str()); + fobj->data.num = vtr::atoi(ss.str()); } else if (is_compound_op(ch) != E_COM_OP_UNDEFINED) { fobj->type = E_FML_OPERATOR; t_compound_operator comp_op_code = is_compound_op(ch); @@ -415,8 +413,6 @@ static void get_formula_object(const char* ch, int& ichar, const t_formula_data& break; } } - - return; } /* returns integer specifying precedence of passed-in operator. higher integer @@ -562,7 +558,6 @@ static void handle_bracket(const Formula_Object& fobj, vector& r } } while (keep_going); } - return; } /* used by the shunting-yard formula parser to deal with commas, ie ','. These occur in function calls*/ @@ -770,7 +765,7 @@ static bool is_operator(const char ch) { } //returns true if string signifies a function e.g max, min -static bool is_function(std::string name) { +static bool is_function(const std::string& name) { if (name == "min" || name == "max" || name == "gcd" @@ -801,7 +796,7 @@ t_compound_operator is_compound_op(const char* ch) { } //checks if the entered string is a known variable name -static bool is_variable(std::string var_name) { +static bool is_variable(const std::string& var_name) { if (same_string(var_name, "from_block") || same_string(var_name, "temp_count") || same_string(var_name, "move_num") || same_string(var_name, "route_net_id") || same_string(var_name, "in_blocks_affected") || same_string(var_name, "router_iter")) { return true; } @@ -849,11 +844,11 @@ bool same_string(std::string str1, std::string str2) { str1.erase(remove(str1.begin(), str1.end(), ' '), str1.end()); str2.erase(remove(str2.begin(), str2.end(), ' '), str2.end()); - //converting both strings to lower case to eliminate case sensivity + //converting both strings to lower case to eliminate case sensitivity std::transform(str1.begin(), str1.end(), str1.begin(), ::tolower); std::transform(str2.begin(), str2.end(), str2.begin(), ::tolower); - return (str1.compare(str2) == 0); + return (str1 == str2); } //the += operator @@ -870,7 +865,7 @@ bool additional_assignment_op(int arg1, int arg2) { //recognizes the block_id to look for (entered by the user) //then looks for that block_id in all the blocks moved in the last perturbation. //returns the block id if found, else just -1 -int in_blocks_affected(std::string expression_left) { +int in_blocks_affected(const std::string& expression_left) { int wanted_block = -1; int found_block; std::stringstream ss; diff --git a/libs/libvtrutil/src/vtr_expr_eval.h b/libs/libvtrutil/src/vtr_expr_eval.h index 0671bf92f7e..3c528cccd37 100644 --- a/libs/libvtrutil/src/vtr_expr_eval.h +++ b/libs/libvtrutil/src/vtr_expr_eval.h @@ -214,7 +214,7 @@ class FormulaParser { FormulaParser& operator=(const FormulaParser&) = delete; ///@brief returns integer result according to specified formula and data - int parse_formula(std::string formula, const t_formula_data& mydata, bool is_breakpoint = false); + int parse_formula(const std::string& formula, const t_formula_data& mydata, bool is_breakpoint = false); ///@brief returns integer result according to specified piece-wise formula and data int parse_piecewise_formula(const char* formula, const t_formula_data& mydata); From 7b1339c6ef2bc838692f3e3dec903366f8644560 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 18 Mar 2024 14:58:20 -0400 Subject: [PATCH 24/37] noc attracted centroid move --- vpr/src/base/CheckSetup.cpp | 8 ++-- vpr/src/base/CheckSetup.h | 2 +- vpr/src/base/SetupVPR.cpp | 2 +- vpr/src/base/read_options.cpp | 2 +- vpr/src/base/vpr_context.h | 3 -- vpr/src/base/vpr_types.h | 12 ++--- vpr/src/place/RL_agent_util.cpp | 57 ++++++++++++++--------- vpr/src/place/RL_agent_util.h | 20 ++++++-- vpr/src/place/centroid_move_generator.cpp | 35 ++++++++++---- vpr/src/place/centroid_move_generator.h | 15 +++++- vpr/src/place/directed_moves_util.cpp | 18 ++++--- vpr/src/place/directed_moves_util.h | 14 +++++- vpr/src/place/initial_noc_placement.cpp | 1 - vpr/src/place/median_move_generator.cpp | 2 +- vpr/src/place/move_utils.h | 1 + vpr/src/place/place.cpp | 2 +- vpr/src/place/simpleRL_move_generator.cpp | 6 ++- vpr/src/place/simpleRL_move_generator.h | 21 +++++++-- 18 files changed, 154 insertions(+), 67 deletions(-) diff --git a/vpr/src/base/CheckSetup.cpp b/vpr/src/base/CheckSetup.cpp index 44d382938a3..e35efcf1513 100644 --- a/vpr/src/base/CheckSetup.cpp +++ b/vpr/src/base/CheckSetup.cpp @@ -12,7 +12,7 @@ void CheckSetup(const t_packer_opts& PackerOpts, const t_router_opts& RouterOpts, const t_det_routing_arch& RoutingArch, const std::vector& Segments, - const t_timing_inf Timing, + const t_timing_inf& Timing, const t_chan_width_dist Chans) { int i; int Tmp; @@ -31,7 +31,7 @@ void CheckSetup(const t_packer_opts& PackerOpts, "This is allowed, but strange, and circuit speed will suffer.\n"); } - if ((false == Timing.timing_analysis_enabled) + if (!Timing.timing_analysis_enabled && (PlacerOpts.place_algorithm.is_timing_driven())) { /* May work, not tested */ VPR_FATAL_ERROR(VPR_ERROR_OTHER, @@ -57,7 +57,7 @@ void CheckSetup(const t_packer_opts& PackerOpts, if (!Timing.timing_analysis_enabled && (DEMAND_ONLY != RouterOpts.base_cost_type && DEMAND_ONLY_NORMALIZED_LENGTH != RouterOpts.base_cost_type)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, - "base_cost_type must be demand_only or demand_only_normailzed_length when timing analysis is disabled.\n"); + "base_cost_type must be demand_only or demand_only_normalized_length when timing analysis is disabled.\n"); } } @@ -72,7 +72,7 @@ void CheckSetup(const t_packer_opts& PackerOpts, for (i = 0; i < (int)Segments.size(); ++i) { Tmp = Segments[i].arch_opin_switch; auto& device_ctx = g_vpr_ctx.device(); - if (false == device_ctx.arch_switch_inf[Tmp].buffered()) { + if (!device_ctx.arch_switch_inf[Tmp].buffered()) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "arch_opin_switch (#%d) of segment type #%d is not buffered.\n", Tmp, i); } diff --git a/vpr/src/base/CheckSetup.h b/vpr/src/base/CheckSetup.h index d1e18764d9a..7f513467849 100644 --- a/vpr/src/base/CheckSetup.h +++ b/vpr/src/base/CheckSetup.h @@ -7,7 +7,7 @@ void CheckSetup(const t_packer_opts& PackerOpts, const t_router_opts& RouterOpts, const t_det_routing_arch& RoutingArch, const std::vector& Segments, - const t_timing_inf Timing, + const t_timing_inf& Timing, const t_chan_width_dist Chans); #endif diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index a685a3ba828..7ad717f550b 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -399,7 +399,7 @@ static void SetupRoutingArch(const t_arch& Arch, RoutingArch->R_minW_pmos = Arch.R_minW_pmos; RoutingArch->Fs = Arch.Fs; RoutingArch->directionality = BI_DIRECTIONAL; - if (Arch.Segments.size()) { + if (!Arch.Segments.empty()) { RoutingArch->directionality = Arch.Segments[0].directionality; } diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 87d1b08c87d..7ee3a269588 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -2035,7 +2035,7 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .help( "The percentage probabilities of different moves in Simulated Annealing placement." "This option is only effective for timing-driven placement." - "The numbers listed are interpreted as the percentage probabilities of {uniformMove, MedianMove, CentroidMove, WeightedCentroid, WeightedMedian, Timing feasible Region(TFR), Critical UniformMove}, in that order.") + "The numbers listed are interpreted as the percentage probabilities of {uniformMove, MedianMove, CentroidMove, WeightedCentroid, WeightedMedian, Critical UniformMove, Timing feasible Region(TFR)}, in that order.") .nargs('+') .default_value({"100", "0", "0", "0", "0", "0", "0"}) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 1fbffc0a835..d87536fc66e 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -422,9 +422,6 @@ struct PlacementContext : public Context { vtr::vector cluster_to_noc_grp; std::map noc_router_to_noc_group; - - float noc_centroid_weight; - }; /** diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index e64c80214bd..d4a4cb7aeb1 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -112,10 +112,10 @@ constexpr auto INVALID_BLOCK_ID = ClusterBlockId(-2); #define NO_CLUSTER -1 #define NEVER_CLUSTER -2 -#define NOT_VALID -10000 /* Marks gains that aren't valid */ +#define NOT_VALID (-10000) /* Marks gains that aren't valid */ /* Ensure no gain can ever be this negative! */ #ifndef UNDEFINED -# define UNDEFINED -1 +# define UNDEFINED (-1) #endif enum class e_router_lookahead { @@ -550,9 +550,9 @@ enum class e_timing_update_type { ****************************************************************************/ /* Values of number of placement available move types */ -#define NUM_PL_MOVE_TYPES 7 -#define NUM_PL_NONTIMING_MOVE_TYPES 3 -#define NUM_PL_1ST_STATE_MOVE_TYPES 4 +constexpr int NUM_PL_MOVE_TYPES = 7; +constexpr int NUM_PL_NONTIMING_MOVE_TYPES = 3; +constexpr int NUM_PL_1ST_STATE_MOVE_TYPES = 4; /* Timing data structures end */ enum sched_type { @@ -1503,8 +1503,8 @@ struct t_noc_opts { double noc_latency_constraints_weighting; ///& move_generator, std::unique_ptr& move_generator2, const t_placer_opts& placer_opts, int move_lim) { - if (placer_opts.RL_agent_placement == false) { +void create_move_generators(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + const t_placer_opts& placer_opts, + int move_lim, + float noc_attraction_weight) { + if (!placer_opts.RL_agent_placement) { if (placer_opts.place_algorithm.is_timing_driven()) { VTR_LOG("Using static probabilities for choosing each move type\n"); - VTR_LOG("Probability of Uniform_move : %f \n", placer_opts.place_static_move_prob[0]); - VTR_LOG("Probability of Median_move : %f \n", placer_opts.place_static_move_prob[1]); - VTR_LOG("Probability of Centroid_move : %f \n", placer_opts.place_static_move_prob[2]); - VTR_LOG("Probability of Weighted_centroid_move : %f \n", placer_opts.place_static_move_prob[3]); - VTR_LOG("Probability of Weighted_median_move : %f \n", placer_opts.place_static_move_prob[4]); - VTR_LOG("Probability of Timing_feasible_region_move : %f \n", placer_opts.place_static_move_prob[5]); - VTR_LOG("Probability of Critical_uniform_move : %f \n", placer_opts.place_static_move_prob[6]); + VTR_LOG("Probability of Uniform_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::UNIFORM]); + VTR_LOG("Probability of Median_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::MEDIAN]); + VTR_LOG("Probability of Centroid_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::CENTROID]); + VTR_LOG("Probability of Weighted_centroid_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::W_CENTROID]); + VTR_LOG("Probability of Weighted_median_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::W_MEDIAN]); + VTR_LOG("Probability of Critical_uniform_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::CRIT_UNIFORM]); + VTR_LOG("Probability of Timing_feasible_region_move : %f \n", placer_opts.place_static_move_prob[(int)e_move_type::FEASIBLE_REGION]); move_generator = std::make_unique(placer_opts.place_static_move_prob); move_generator2 = std::make_unique(placer_opts.place_static_move_prob); } else { //Non-timing driven placement VTR_LOG("Using static probabilities for choosing each move type\n"); - VTR_LOG("Probability of Uniform_move : %f \n", placer_opts.place_static_notiming_move_prob[0]); - VTR_LOG("Probability of Median_move : %f \n", placer_opts.place_static_notiming_move_prob[1]); - VTR_LOG("Probability of Centroid_move : %f \n", placer_opts.place_static_notiming_move_prob[2]); + VTR_LOG("Probability of Uniform_move : %f \n", placer_opts.place_static_notiming_move_prob[(int)e_move_type::UNIFORM]); + VTR_LOG("Probability of Median_move : %f \n", placer_opts.place_static_notiming_move_prob[(int)e_move_type::MEDIAN]); + VTR_LOG("Probability of Centroid_move : %f \n", placer_opts.place_static_notiming_move_prob[(int)e_move_type::CENTROID]); move_generator = std::make_unique(placer_opts.place_static_notiming_move_prob); move_generator2 = std::make_unique(placer_opts.place_static_notiming_move_prob); } @@ -60,13 +64,13 @@ void create_move_generators(std::unique_ptr& move_generator, std: placer_opts.place_agent_epsilon); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator = std::make_unique(karmed_bandit_agent1); + move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(num_2nd_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2); + move_generator2 = std::make_unique(karmed_bandit_agent2, 0.0f); } else { std::unique_ptr karmed_bandit_agent1, karmed_bandit_agent2; //agent's 1st state @@ -80,38 +84,47 @@ void create_move_generators(std::unique_ptr& move_generator, std: e_agent_space::MOVE_TYPE); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator = std::make_unique(karmed_bandit_agent1); + move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(num_2nd_state_avail_moves, e_agent_space::MOVE_TYPE); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2); + move_generator2 = std::make_unique(karmed_bandit_agent2,0.0f); } } } -void assign_current_move_generator(std::unique_ptr& move_generator, std::unique_ptr& move_generator2, e_agent_state agent_state, const t_placer_opts& placer_opts, bool in_quench, std::unique_ptr& current_move_generator) { +void assign_current_move_generator(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + e_agent_state agent_state, + const t_placer_opts& placer_opts, + bool in_quench, std::unique_ptr& current_move_generator) { if (in_quench) { - if (placer_opts.place_quench_algorithm.is_timing_driven() && placer_opts.place_agent_multistate == true) + if (placer_opts.place_quench_algorithm.is_timing_driven() && placer_opts.place_agent_multistate) current_move_generator = std::move(move_generator2); else current_move_generator = std::move(move_generator); } else { - if (agent_state == EARLY_IN_THE_ANNEAL || placer_opts.place_agent_multistate == false) + if (agent_state == EARLY_IN_THE_ANNEAL || !placer_opts.place_agent_multistate) current_move_generator = std::move(move_generator); else current_move_generator = std::move(move_generator2); } } -void update_move_generator(std::unique_ptr& move_generator, std::unique_ptr& move_generator2, e_agent_state agent_state, const t_placer_opts& placer_opts, bool in_quench, std::unique_ptr& current_move_generator) { +void update_move_generator(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + e_agent_state agent_state, + const t_placer_opts& placer_opts, + bool in_quench, + std::unique_ptr& current_move_generator) { if (in_quench) { - if (placer_opts.place_quench_algorithm.is_timing_driven() && placer_opts.place_agent_multistate == true) + if (placer_opts.place_quench_algorithm.is_timing_driven() && placer_opts.place_agent_multistate) move_generator2 = std::move(current_move_generator); else move_generator = std::move(current_move_generator); } else { - if (agent_state == EARLY_IN_THE_ANNEAL || placer_opts.place_agent_multistate == false) + if (agent_state == EARLY_IN_THE_ANNEAL || !placer_opts.place_agent_multistate) move_generator = std::move(current_move_generator); else move_generator2 = std::move(current_move_generator); diff --git a/vpr/src/place/RL_agent_util.h b/vpr/src/place/RL_agent_util.h index ebfee697850..f5edc5b83fa 100644 --- a/vpr/src/place/RL_agent_util.h +++ b/vpr/src/place/RL_agent_util.h @@ -19,15 +19,29 @@ enum e_agent_state { * It returns a unique pointer for each move generator in move_generator and move_generator2 * move_lim: represents the num of moves per temp. */ -void create_move_generators(std::unique_ptr& move_generator, std::unique_ptr& move_generator2, const t_placer_opts& placer_opts, int move_lim); +void create_move_generators(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + const t_placer_opts& placer_opts, + int move_lim, + float noc_attraction_weight); /** * @brief copy one of the available move_generators to be the current move_generator that would be used in the placement based on the placer_options and the agent state */ -void assign_current_move_generator(std::unique_ptr& move_generator, std::unique_ptr& move_generator2, e_agent_state agent_state, const t_placer_opts& placer_opts, bool in_quench, std::unique_ptr& current_move_generator); +void assign_current_move_generator(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + e_agent_state agent_state, + const t_placer_opts& placer_opts, + bool in_quench, + std::unique_ptr& current_move_generator); /** * @ brief move the updated current_move_generator to its original move_Generator structure based on he placer_options and the agent state */ -void update_move_generator(std::unique_ptr& move_generator, std::unique_ptr& move_generator2, e_agent_state agent_state, const t_placer_opts& placer_opts, bool in_quench, std::unique_ptr& current_move_generator); +void update_move_generator(std::unique_ptr& move_generator, + std::unique_ptr& move_generator2, + e_agent_state agent_state, + const t_placer_opts& placer_opts, + bool in_quench, + std::unique_ptr& current_move_generator); #endif diff --git a/vpr/src/place/centroid_move_generator.cpp b/vpr/src/place/centroid_move_generator.cpp index f1316701998..07828e19cab 100644 --- a/vpr/src/place/centroid_move_generator.cpp +++ b/vpr/src/place/centroid_move_generator.cpp @@ -5,23 +5,42 @@ #include "place_constraints.h" #include "move_utils.h" -e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, float rlim, const t_placer_opts& placer_opts, const PlacerCriticalities* /*criticalities*/) { - //Find a movable block based on blk_type +CentroidMoveGenerator::CentroidMoveGenerator() + : noc_attraction_w_(0.0f) + , noc_attraction_enabled_(false) {} + +CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight) + : noc_attraction_w_(noc_attraction_weight) + , noc_attraction_enabled_(true) { + VTR_ASSERT(noc_attraction_weight > 0.0 && noc_attraction_weight <= 1.0); +} + +e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* /*criticalities*/) { + // Find a movable block based on blk_type ClusterBlockId b_from = propose_block_to_move(placer_opts, proposed_action.logical_blk_type_index, false, nullptr, nullptr); - VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Centroid Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); + + VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, + "Centroid Move Choose Block %d - rlim %f\n", + size_t(b_from), + rlim); if (!b_from) { //No movable block found - VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\tNo movable block found\n"); + VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, + "\tNo movable block found\n"); return e_create_move::ABORT; } - auto& device_ctx = g_vpr_ctx.device(); - auto& place_ctx = g_vpr_ctx.placement(); - auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& device_ctx = g_vpr_ctx.device(); + const auto& place_ctx = g_vpr_ctx.placement(); + const auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = g_placer_ctx.mutable_move(); t_pl_loc from = place_ctx.block_locs[b_from].loc; @@ -36,7 +55,7 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block t_pl_loc to, centroid; /* Calculate the centroid location*/ - calculate_centroid_loc(b_from, false, centroid, nullptr); + calculate_centroid_loc(b_from, false, centroid, nullptr, noc_attraction_enabled_, noc_attraction_w_); // Centroid location is not necessarily a valid location, and the downstream location expect a valid // layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc. diff --git a/vpr/src/place/centroid_move_generator.h b/vpr/src/place/centroid_move_generator.h index cbcbb883aea..bd17a16113c 100644 --- a/vpr/src/place/centroid_move_generator.h +++ b/vpr/src/place/centroid_move_generator.h @@ -13,7 +13,20 @@ * Returns its choices by filling in affected_blocks. */ class CentroidMoveGenerator : public MoveGenerator { - e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, float rlim, const t_placer_opts& placer_opts, const PlacerCriticalities* /*criticalities*/) override; + public: + CentroidMoveGenerator(); + CentroidMoveGenerator(float noc_attraction_weight); + + private: + e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* /*criticalities*/) override; + + private: + float noc_attraction_w_; + bool noc_attraction_enabled_; }; #endif diff --git a/vpr/src/place/directed_moves_util.cpp b/vpr/src/place/directed_moves_util.cpp index 4193b9be859..dd739de985b 100644 --- a/vpr/src/place/directed_moves_util.cpp +++ b/vpr/src/place/directed_moves_util.cpp @@ -17,7 +17,12 @@ void get_coordinate_of_pin(ClusterPinId pin, t_physical_tile_loc& tile_loc) { tile_loc.y = std::max(std::min(tile_loc.y, (int)grid.height() - 2), 1); //-2 for no perim channels } -void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc& centroid, const PlacerCriticalities* criticalities) { +void calculate_centroid_loc(ClusterBlockId b_from, + bool timing_weights, + t_pl_loc& centroid, + const PlacerCriticalities* criticalities, + bool noc_attraction_enabled, + float noc_attraction_weight) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_ctx = g_vpr_ctx.placement(); @@ -92,16 +97,15 @@ void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc } } - if (!place_ctx.cluster_to_noc_grp.empty()) { + if (noc_attraction_enabled) { if (place_ctx.cluster_to_noc_grp[b_from] != NocGroupId::INVALID()) { NocGroupId noc_grp_id = place_ctx.cluster_to_noc_grp[b_from]; - float noc_weight = place_ctx.noc_centroid_weight; - float single_noc_weight = (acc_weight * noc_weight) / place_ctx.noc_group_routers[noc_grp_id].size(); + float single_noc_weight = (acc_weight * noc_attraction_weight) / place_ctx.noc_group_routers[noc_grp_id].size(); - acc_x *= (1.0f - noc_weight); - acc_y *= (1.0f - noc_weight); - acc_weight *= (1.0f - noc_weight); + acc_x *= (1.0f - noc_attraction_weight); + acc_y *= (1.0f - noc_attraction_weight); + acc_weight *= (1.0f - noc_attraction_weight); for (ClusterBlockId router_blk_id : place_ctx.noc_group_routers[noc_grp_id]) { t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; diff --git a/vpr/src/place/directed_moves_util.h b/vpr/src/place/directed_moves_util.h index 11ef3df71c3..fdb941226ee 100644 --- a/vpr/src/place/directed_moves_util.h +++ b/vpr/src/place/directed_moves_util.h @@ -31,6 +31,18 @@ void get_coordinate_of_pin(ClusterPinId pin, t_physical_tile_loc& tile_loc); * * @return The calculated location is returned in centroid parameter that is sent by reference */ -void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc& centroid, const PlacerCriticalities* criticalities); +void calculate_centroid_loc(ClusterBlockId b_from, + bool timing_weights, + t_pl_loc& centroid, + const PlacerCriticalities* criticalities, + bool noc_attraction_enabled, + float noc_attraction_weight); + +inline void calculate_centroid_loc(ClusterBlockId b_from, + bool timing_weights, + t_pl_loc& centroid, + const PlacerCriticalities* criticalities) { + calculate_centroid_loc(b_from, timing_weights,centroid, criticalities,false, 0.0f); +} #endif diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index 1e727b6da4b..ae2e1d4d202 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -290,7 +290,6 @@ void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& plac auto& place_ctx = g_vpr_ctx.mutable_placement(); int noc_group_cnt = 0; place_ctx.cluster_to_noc_grp.resize(cluster_ctx.clb_nlist.blocks().size(), NocGroupId ::INVALID()); - place_ctx.noc_centroid_weight = (float)noc_opts.noc_centroid_weight; for (auto router_blk_id : router_blk_ids) { diff --git a/vpr/src/place/median_move_generator.cpp b/vpr/src/place/median_move_generator.cpp index 324d0cd3e44..2decd1ff22f 100644 --- a/vpr/src/place/median_move_generator.cpp +++ b/vpr/src/place/median_move_generator.cpp @@ -61,7 +61,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_ continue; /* To speed up the calculation, we found it is useful to ignore high fanout nets. * Especially that in most cases, these high fanout nets are scattered in many locations of - * the device and don't guide to a specific location. We also assuered these assumpitions experimentally. + * the device and don't guide to a specific location. We also assured these assumptions experimentally. */ if (int(cluster_ctx.clb_nlist.net_pins(net_id).size()) > placer_opts.place_high_fanout_net) continue; diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index 9d7e98b1e24..c22c3cec7a6 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -27,6 +27,7 @@ enum class e_move_type { W_MEDIAN, CRIT_UNIFORM, FEASIBLE_REGION, + NOC_ATTRACTION_CENTROID, NUMBER_OF_AUTO_MOVES, MANUAL_MOVE = NUMBER_OF_AUTO_MOVES, INVALID_MOVE diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index e7114e420bb..19765622d0f 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -651,7 +651,7 @@ void try_place(const Netlist<>& net_list, * pow(net_list.blocks().size(), 1.3333)); //create the move generator based on the chosen strategy - create_move_generators(move_generator, move_generator2, placer_opts, move_lim); + create_move_generators(move_generator, move_generator2, placer_opts, move_lim, noc_opts.noc_centroid_weight); alloc_and_load_placement_structs(placer_opts.place_cost_exp, placer_opts, noc_opts, directs, num_directs); diff --git a/vpr/src/place/simpleRL_move_generator.cpp b/vpr/src/place/simpleRL_move_generator.cpp index 17753d66a88..e29f7773676 100644 --- a/vpr/src/place/simpleRL_move_generator.cpp +++ b/vpr/src/place/simpleRL_move_generator.cpp @@ -14,7 +14,11 @@ static float scaled_clipped_exp(float x) { return std::exp(std::min(1000 * x, fl * RL move generator implementation * * * * */ -e_create_move SimpleRLMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, float rlim, const t_placer_opts& placer_opts, const PlacerCriticalities* criticalities) { +e_create_move SimpleRLMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* criticalities) { proposed_action = karmed_bandit_agent->propose_action(); return avail_moves[(int)proposed_action.move_type]->propose_move(blocks_affected, proposed_action, rlim, placer_opts, criticalities); } diff --git a/vpr/src/place/simpleRL_move_generator.h b/vpr/src/place/simpleRL_move_generator.h index de108313023..31dd2518689 100644 --- a/vpr/src/place/simpleRL_move_generator.h +++ b/vpr/src/place/simpleRL_move_generator.h @@ -86,7 +86,7 @@ class KArmedBanditAgent { protected: float exp_alpha_ = -1; //Step size for q_ updates (< 0 implies use incremental average) size_t num_available_moves_; //Number of move types that agent can choose from to perform - size_t num_available_types_; //Number of block types that exist in the netlest. Agent may not choose the block type. + size_t num_available_types_; //Number of block types that exist in the netlist. Agent may not choose the block type. size_t num_available_actions_; //Total number of available actions bool propose_blk_type_ = false; //Check if agent should propose both move and block type or only move type std::vector num_action_chosen_; //Number of times each arm has been pulled (n) @@ -216,18 +216,26 @@ class SimpleRLMoveGenerator : public MoveGenerator { */ template::value || std::is_same::value>::type> - explicit SimpleRLMoveGenerator(std::unique_ptr& agent); + explicit SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight); // Updates affected_blocks with the proposed move, while respecting the current rlim - e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, float rlim, const t_placer_opts& placer_opts, const PlacerCriticalities* criticalities) override; + e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* criticalities) override; // Receives feedback about the outcome of the previously proposed move void process_outcome(double reward, e_reward_function reward_fun) override; }; template -SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent) { - avail_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES); +SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight) { + if (noc_attraction_weight > 0.0f) { + avail_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES); + } else { + avail_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES - 1); + } avail_moves[(int)e_move_type::UNIFORM] = std::make_unique(); avail_moves[(int)e_move_type::MEDIAN] = std::make_unique(); @@ -236,6 +244,9 @@ SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent) { avail_moves[(int)e_move_type::W_MEDIAN] = std::make_unique(); avail_moves[(int)e_move_type::CRIT_UNIFORM] = std::make_unique(); avail_moves[(int)e_move_type::FEASIBLE_REGION] = std::make_unique(); + if (noc_attraction_weight > 0.0f) { + avail_moves[(int)e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(noc_attraction_weight); + } karmed_bandit_agent = std::move(agent); } From b0211ab0bde441da85924da88c4367794b978155 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 18 Mar 2024 16:19:28 -0400 Subject: [PATCH 25/37] pass move types to KArmedBanditAgent constructor --- vpr/src/base/SetupVPR.cpp | 2 -- vpr/src/place/RL_agent_util.cpp | 29 ++++++++++----- vpr/src/place/simpleRL_move_generator.cpp | 44 ++++++++++++----------- vpr/src/place/simpleRL_move_generator.h | 30 ++++++++-------- 4 files changed, 60 insertions(+), 45 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 7ad717f550b..e1ace118abc 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -741,8 +741,6 @@ static void SetupNocOpts(const t_options& Options, t_noc_opts* NocOpts) { NocOpts->noc_swap_percentage = Options.noc_swap_percentage; NocOpts->noc_centroid_weight = Options.noc_centroid_weight; NocOpts->noc_placement_file_name = Options.noc_placement_file_name; - - return; } static void find_ipin_cblock_switch_index(const t_arch& Arch, int& wire_to_arch_ipin_switch, int& wire_to_arch_ipin_switch_between_dice) { diff --git a/vpr/src/place/RL_agent_util.cpp b/vpr/src/place/RL_agent_util.cpp index 4bf27e9215e..307a3c15d2e 100644 --- a/vpr/src/place/RL_agent_util.cpp +++ b/vpr/src/place/RL_agent_util.cpp @@ -46,27 +46,40 @@ void create_move_generators(std::unique_ptr& move_generator, * only move type. * * This state is activated late in the anneal and in the Quench */ - int num_1st_state_avail_moves = placer_opts.place_algorithm.is_timing_driven() ? NUM_PL_1ST_STATE_MOVE_TYPES : NUM_PL_NONTIMING_MOVE_TYPES; - int num_2nd_state_avail_moves = placer_opts.place_algorithm.is_timing_driven() ? NUM_PL_MOVE_TYPES : NUM_PL_NONTIMING_MOVE_TYPES; + std::vector first_state_avail_moves {e_move_type::UNIFORM, e_move_type::MEDIAN, e_move_type::CENTROID}; + if (placer_opts.place_algorithm.is_timing_driven()) { + first_state_avail_moves.push_back(e_move_type::W_CENTROID); + } + + std::vector second_state_avail_moves {e_move_type::UNIFORM, e_move_type::MEDIAN, e_move_type::CENTROID}; + if (placer_opts.place_algorithm.is_timing_driven()) { + second_state_avail_moves.insert(second_state_avail_moves.end(), + {e_move_type::W_CENTROID, e_move_type::W_MEDIAN, e_move_type::CRIT_UNIFORM, e_move_type::FEASIBLE_REGION}); + } + + if (noc_attraction_weight > 0.0f) { + first_state_avail_moves.push_back(e_move_type::NOC_ATTRACTION_CENTROID); + second_state_avail_moves.push_back(e_move_type::NOC_ATTRACTION_CENTROID); + } if (placer_opts.place_agent_algorithm == E_GREEDY) { std::unique_ptr karmed_bandit_agent1, karmed_bandit_agent2; //agent's 1st state if (placer_opts.place_agent_space == e_agent_space::MOVE_BLOCK_TYPE) { VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move and block types\n"); - karmed_bandit_agent1 = std::make_unique(num_1st_state_avail_moves, + karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_BLOCK_TYPE, placer_opts.place_agent_epsilon); } else { VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move types\n"); - karmed_bandit_agent1 = std::make_unique(num_1st_state_avail_moves, + karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); //agent's 2nd state - karmed_bandit_agent2 = std::make_unique(num_2nd_state_avail_moves, + karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); @@ -76,17 +89,17 @@ void create_move_generators(std::unique_ptr& move_generator, //agent's 1st state if (placer_opts.place_agent_space == e_agent_space::MOVE_BLOCK_TYPE) { VTR_LOG("Using simple RL 'Softmax agent' for choosing move and block types\n"); - karmed_bandit_agent1 = std::make_unique(num_1st_state_avail_moves, + karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_BLOCK_TYPE); } else { VTR_LOG("Using simple RL 'Softmax agent' for choosing move types\n"); - karmed_bandit_agent1 = std::make_unique(num_1st_state_avail_moves, + karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_TYPE); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); //agent's 2nd state - karmed_bandit_agent2 = std::make_unique(num_2nd_state_avail_moves, + karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); move_generator2 = std::make_unique(karmed_bandit_agent2,0.0f); diff --git a/vpr/src/place/simpleRL_move_generator.cpp b/vpr/src/place/simpleRL_move_generator.cpp index e29f7773676..2ba720aa6a0 100644 --- a/vpr/src/place/simpleRL_move_generator.cpp +++ b/vpr/src/place/simpleRL_move_generator.cpp @@ -2,6 +2,7 @@ #include "globals.h" #include #include +#include #include "vtr_random.h" #include "vtr_time.h" @@ -20,7 +21,7 @@ e_create_move SimpleRLMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block const t_placer_opts& placer_opts, const PlacerCriticalities* criticalities) { proposed_action = karmed_bandit_agent->propose_action(); - return avail_moves[(int)proposed_action.move_type]->propose_move(blocks_affected, proposed_action, rlim, placer_opts, criticalities); + return avail_moves[proposed_action.move_type]->propose_move(blocks_affected, proposed_action, rlim, placer_opts, criticalities); } void SimpleRLMoveGenerator::process_outcome(double reward, e_reward_function reward_fun) { @@ -32,13 +33,14 @@ void SimpleRLMoveGenerator::process_outcome(double reward, e_reward_function rew * K-Armed bandit agent implementation * * * * */ -KArmedBanditAgent::KArmedBanditAgent(size_t num_moves, e_agent_space agent_space) - : num_available_moves_(num_moves) +KArmedBanditAgent::KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space) + : available_moves_(std::move(available_moves)) , propose_blk_type_(agent_space == e_agent_space::MOVE_BLOCK_TYPE) { std::vector available_logical_block_types = get_available_logical_blk_types_(); num_available_types_ = available_logical_block_types.size(); - num_available_actions_ = propose_blk_type_ ? (num_available_moves_ * num_available_types_) : num_available_moves_; + size_t num_available_moves = available_moves_.size(); + num_available_actions_ = propose_blk_type_ ? (num_available_moves * num_available_types_) : num_available_moves; action_logical_blk_type_.clear(); @@ -68,7 +70,7 @@ e_move_type KArmedBanditAgent::action_to_move_type_(const size_t action_idx) { e_move_type move_type = e_move_type::INVALID_MOVE; if (action_idx < num_available_actions_) { - move_type = (e_move_type)(action_idx % num_available_moves_); + move_type = available_moves_[action_idx % available_moves_.size()]; } return move_type; @@ -76,7 +78,7 @@ e_move_type KArmedBanditAgent::action_to_move_type_(const size_t action_idx) { int KArmedBanditAgent::action_to_blk_type_(const size_t action_idx) { if (propose_blk_type_) { - return action_logical_blk_type_.at(action_idx / num_available_moves_); + return action_logical_blk_type_.at(action_idx / available_moves_.size()); } else { // the agent doesn't select the move type return -1; } @@ -105,8 +107,10 @@ std::vector KArmedBanditAgent::get_available_logical_blk_types_() { void KArmedBanditAgent::process_outcome(double reward, e_reward_function reward_fun) { ++num_action_chosen_[last_action_]; - if (reward_fun == RUNTIME_AWARE || reward_fun == WL_BIASED_RUNTIME_AWARE) - reward /= time_elapsed_[last_action_ % num_available_moves_]; + if (reward_fun == RUNTIME_AWARE || reward_fun == WL_BIASED_RUNTIME_AWARE) { + e_move_type move_type = action_to_move_type_(last_action_); + reward /= time_elapsed_[move_type]; + } //Determine step size float step = 0.; @@ -154,13 +158,13 @@ void KArmedBanditAgent::set_step(float gamma, int move_lim) { } else { // // For an exponentially weighted average the fraction of total weight applied - // to moves which occured > K moves ago is: + // to moves which occurred > K moves ago is: // // gamma = (1 - alpha)^K // // If we treat K as the number of moves per temperature (move_lim) then gamma - // is the fraction of weight applied to moves which occured > move_lim moves ago, - // and given a target gamma we can explicitly calcualte the alpha step-size + // is the fraction of weight applied to moves which occurred > move_lim moves ago, + // and given a target gamma we can explicitly calculate the alpha step-size // required by the agent: // // alpha = 1 - e^(log(gamma) / K) @@ -178,8 +182,8 @@ int KArmedBanditAgent::agent_to_phy_blk_type(const int idx) { * E-greedy agent implementation * * * * */ -EpsilonGreedyAgent::EpsilonGreedyAgent(size_t num_moves, e_agent_space agent_space, float epsilon) - : KArmedBanditAgent(num_moves, agent_space) { +EpsilonGreedyAgent::EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon) + : KArmedBanditAgent(std::move(available_moves), agent_space) { set_epsilon(epsilon); init_q_scores_(); } @@ -227,7 +231,7 @@ t_propose_action EpsilonGreedyAgent::propose_action() { action_to_blk_type_(last_action_)}; //Check the move type to be a valid move - VTR_ASSERT((size_t)proposed_action.move_type < num_available_moves_); + VTR_ASSERT_SAFE(std::find(available_moves_.begin(), available_moves_.end(), proposed_action.move_type) != available_moves_.end()); return proposed_action; } @@ -253,8 +257,8 @@ void EpsilonGreedyAgent::set_epsilon_action_prob() { * Softmax agent implementation * * * * */ -SoftmaxAgent::SoftmaxAgent(size_t num_moves, e_agent_space agent_space) - : KArmedBanditAgent(num_moves, agent_space) { +SoftmaxAgent::SoftmaxAgent(std::vector available_moves, e_agent_space agent_space) + : KArmedBanditAgent(std::move(available_moves), agent_space) { init_q_scores_(); } @@ -301,7 +305,7 @@ t_propose_action SoftmaxAgent::propose_action() { action_to_blk_type_(last_action_)}; //Check the move type to be a valid move - VTR_ASSERT((size_t)proposed_action.move_type < num_available_moves_); + VTR_ASSERT_SAFE(std::find(available_moves_.begin(), available_moves_.end(), proposed_action.move_type) != available_moves_.end()); return proposed_action; } @@ -322,7 +326,7 @@ void SoftmaxAgent::set_block_ratio_() { blk_type.index = agent_to_phy_blk_type(itype); auto num_blocks = cluster_ctx.clb_nlist.blocks_per_type(blk_type).size(); block_type_ratio_[itype] = (float)num_blocks / num_total_blocks; - block_type_ratio_[itype] /= num_available_moves_; + block_type_ratio_[itype] /= available_moves_.size(); } } @@ -337,7 +341,7 @@ void SoftmaxAgent::set_action_prob_() { for (size_t i = 0; i < num_available_actions_; ++i) { if (propose_blk_type_) { //calculate block type index based on its location on q_table - int blk_ratio_index = (int)i / num_available_moves_; + int blk_ratio_index = (int)i / available_moves_.size(); action_prob_[i] = (exp_q_[i] / sum_q) * block_type_ratio_[blk_ratio_index]; } else { action_prob_[i] = (exp_q_[i] / sum_q); @@ -351,7 +355,7 @@ void SoftmaxAgent::set_action_prob_() { [sum_prob](float x) { return x * (1 / sum_prob); }); } else { std::transform(action_prob_.begin(), action_prob_.end(), action_prob_.begin(), - [sum_prob, this](float x) { return x + ((1.0 - sum_prob) / this->num_available_moves_); }); + [sum_prob, this](float x) { return x + ((1.0 - sum_prob) / this->available_moves_.size()); }); } // calculate the accumulative action probability of each action diff --git a/vpr/src/place/simpleRL_move_generator.h b/vpr/src/place/simpleRL_move_generator.h index 31dd2518689..3d3f66789d5 100644 --- a/vpr/src/place/simpleRL_move_generator.h +++ b/vpr/src/place/simpleRL_move_generator.h @@ -14,7 +14,7 @@ */ class KArmedBanditAgent { public: - KArmedBanditAgent(size_t num_moves, e_agent_space agent_space); + KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space); virtual ~KArmedBanditAgent() = default; /** @@ -85,7 +85,7 @@ class KArmedBanditAgent { protected: float exp_alpha_ = -1; //Step size for q_ updates (< 0 implies use incremental average) - size_t num_available_moves_; //Number of move types that agent can choose from to perform + std::vector available_moves_; size_t num_available_types_; //Number of block types that exist in the netlist. Agent may not choose the block type. size_t num_available_actions_; //Total number of available actions bool propose_blk_type_ = false; //Check if agent should propose both move and block type or only move type @@ -95,7 +95,8 @@ class KArmedBanditAgent { /* Ratios of the average runtime to calculate each move type */ /* These ratios are useful for different reward functions * * The vector is calculated by averaging many runs on different circuits */ - std::vector time_elapsed_{1.0, 3.6, 5.4, 2.5, 2.1, 0.8, 2.2}; +// std::vector time_elapsed_ + const vtr::vector time_elapsed_{1.0, 3.6, 5.4, 2.5, 2.1, 0.8, 2.2, 5.4}; FILE* agent_info_file_ = nullptr; @@ -121,7 +122,7 @@ class KArmedBanditAgent { */ class EpsilonGreedyAgent : public KArmedBanditAgent { public: - EpsilonGreedyAgent(size_t num_moves, e_agent_space agent_space, float epsilon); + EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon); ~EpsilonGreedyAgent() override; t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform @@ -160,10 +161,9 @@ class EpsilonGreedyAgent : public KArmedBanditAgent { */ class SoftmaxAgent : public KArmedBanditAgent { public: - SoftmaxAgent(size_t num_moves, e_agent_space agent_space); + SoftmaxAgent(std::vector available_moves, e_agent_space agent_space); ~SoftmaxAgent() override; - //void process_outcome(double reward, std::string reward_fun) override; //Updates the agent based on the reward of the last proposed action t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform private: @@ -200,7 +200,7 @@ class SoftmaxAgent : public KArmedBanditAgent { */ class SimpleRLMoveGenerator : public MoveGenerator { private: - std::vector> avail_moves; // list of pointers to the available move generators (the different move types) + vtr::vector> avail_moves; // list of pointers to the available move generators (the different move types) std::unique_ptr karmed_bandit_agent; // a pointer to the specific agent used (e.g. Softmax) public: @@ -237,15 +237,15 @@ SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent, float no avail_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES - 1); } - avail_moves[(int)e_move_type::UNIFORM] = std::make_unique(); - avail_moves[(int)e_move_type::MEDIAN] = std::make_unique(); - avail_moves[(int)e_move_type::CENTROID] = std::make_unique(); - avail_moves[(int)e_move_type::W_CENTROID] = std::make_unique(); - avail_moves[(int)e_move_type::W_MEDIAN] = std::make_unique(); - avail_moves[(int)e_move_type::CRIT_UNIFORM] = std::make_unique(); - avail_moves[(int)e_move_type::FEASIBLE_REGION] = std::make_unique(); + avail_moves[e_move_type::UNIFORM] = std::make_unique(); + avail_moves[e_move_type::MEDIAN] = std::make_unique(); + avail_moves[e_move_type::CENTROID] = std::make_unique(); + avail_moves[e_move_type::W_CENTROID] = std::make_unique(); + avail_moves[e_move_type::W_MEDIAN] = std::make_unique(); + avail_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(); + avail_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(); if (noc_attraction_weight > 0.0f) { - avail_moves[(int)e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(noc_attraction_weight); + avail_moves[e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(noc_attraction_weight); } karmed_bandit_agent = std::move(agent); From c74ed3bbbc0c5f12454d3a8cb909d647f3164fe5 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 18 Mar 2024 19:12:24 -0400 Subject: [PATCH 26/37] fix segault in SimpleRLMoveGenerator::propose_move() when noc centroid move is enabled --- vpr/src/place/RL_agent_util.cpp | 4 ++-- vpr/src/place/move_generator.h | 4 ++-- vpr/src/place/move_utils.cpp | 3 ++- vpr/src/place/place.cpp | 16 ++++++++-------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/vpr/src/place/RL_agent_util.cpp b/vpr/src/place/RL_agent_util.cpp index 307a3c15d2e..d9e9f092545 100644 --- a/vpr/src/place/RL_agent_util.cpp +++ b/vpr/src/place/RL_agent_util.cpp @@ -83,7 +83,7 @@ void create_move_generators(std::unique_ptr& move_generator, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2, 0.0f); + move_generator2 = std::make_unique(karmed_bandit_agent2, noc_attraction_weight); } else { std::unique_ptr karmed_bandit_agent1, karmed_bandit_agent2; //agent's 1st state @@ -102,7 +102,7 @@ void create_move_generators(std::unique_ptr& move_generator, karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2,0.0f); + move_generator2 = std::make_unique(karmed_bandit_agent2, noc_attraction_weight); } } } diff --git a/vpr/src/place/move_generator.h b/vpr/src/place/move_generator.h index 83791bbcf9b..962b92b1023 100644 --- a/vpr/src/place/move_generator.h +++ b/vpr/src/place/move_generator.h @@ -47,10 +47,10 @@ class MoveGenerator { /** * @brief Updates affected_blocks with the proposed move, while respecting the current rlim * - * This function proposes a new move and updates blocks affected and move_type accorrdingly. The function interface is general + * This function proposes a new move and updates blocks affected and move_type accordingly. The function interface is general * to match the parameters needed by all move generators * - * @param blocks_affectedt: the output of the move + * @param blocks_affected: the output of the move * @param proposed_action: Contains the move type and block type. If the block type is specified, * the proposed move swaps instances of the given block type. Otherwise, the selected block type * by the move generator is written to proposed_action.logical_blk_type_index. diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index cd10f26320a..b49c753fa1f 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -1003,7 +1003,7 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, } //Array of move type strings -static const std::array move_type_strings = { +static const std::array move_type_strings = { "Uniform", "Median", "Centroid", @@ -1011,6 +1011,7 @@ static const std::array move_type_strings = "W. Median", "Crit. Uniform", "Feasible Region", + "NoC Centroid", "Manual Move"}; //To convert enum move type to string diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 19765622d0f..4fa65e47d0d 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -938,9 +938,9 @@ void try_place(const Netlist<>& net_list, //allocate move type statistics vectors MoveTypeStat move_type_stat; - move_type_stat.blk_type_moves.resize(device_ctx.logical_block_types.size() * placer_opts.place_static_move_prob.size(), 0); - move_type_stat.accepted_moves.resize(device_ctx.logical_block_types.size() * placer_opts.place_static_move_prob.size(), 0); - move_type_stat.rejected_moves.resize(device_ctx.logical_block_types.size() * placer_opts.place_static_move_prob.size(), 0); + move_type_stat.blk_type_moves.resize(device_ctx.logical_block_types.size() * (int)e_move_type::NUMBER_OF_AUTO_MOVES, 0); + move_type_stat.accepted_moves.resize(device_ctx.logical_block_types.size() * (int)e_move_type::NUMBER_OF_AUTO_MOVES, 0); + move_type_stat.rejected_moves.resize(device_ctx.logical_block_types.size() * (int)e_move_type::NUMBER_OF_AUTO_MOVES, 0); /* Get the first range limiter */ first_rlim = (float)max(device_ctx.grid.width() - 1, @@ -1067,7 +1067,7 @@ void try_place(const Netlist<>& net_list, //#endif } while (state.outer_loop_update(stats.success_rate, costs, placer_opts, annealing_sched)); - /* Outer loop of the simmulated annealing ends */ + /* Outer loop of the simulated annealing ends */ } //skip_anneal ends /* Start Quench */ @@ -1085,7 +1085,7 @@ void try_place(const Netlist<>& net_list, placer_setup_slacks.get(), pin_timing_invalidator.get(), timing_info.get()); - //move the appropoiate move_generator to be the current used move generator + //move the appropriate move_generator to be the current used move generator assign_current_move_generator(move_generator, move_generator2, agent_state, placer_opts, true, current_move_generator); @@ -1726,7 +1726,7 @@ static e_move_result try_swap(const t_annealing_state* state, } if (proposed_action.logical_blk_type_index != -1) { //if the agent proposed the block type, then collect the block type stat - ++move_type_stat.blk_type_moves[(proposed_action.logical_blk_type_index * (placer_opts.place_static_move_prob.size())) + (int)proposed_action.move_type]; + ++move_type_stat.blk_type_moves[(proposed_action.logical_blk_type_index * (int)e_move_type::NUMBER_OF_AUTO_MOVES) + (int)proposed_action.move_type]; } LOG_MOVE_STATS_PROPOSED(t, blocks_affected); @@ -1877,7 +1877,7 @@ static e_move_result try_swap(const t_annealing_state* state, commit_move_blocks(blocks_affected); if (proposed_action.logical_blk_type_index != -1) { //if the agent proposed the block type, then collect the block type stat - ++move_type_stat.accepted_moves[(proposed_action.logical_blk_type_index * (placer_opts.place_static_move_prob.size())) + (int)proposed_action.move_type]; + ++move_type_stat.accepted_moves[(proposed_action.logical_blk_type_index * (int)e_move_type::NUMBER_OF_AUTO_MOVES) + (int)proposed_action.move_type]; } if (noc_opts.noc) { commit_noc_costs(); @@ -1928,7 +1928,7 @@ static e_move_result try_swap(const t_annealing_state* state, } if (proposed_action.logical_blk_type_index != -1) { //if the agent proposed the block type, then collect the block type stat - ++move_type_stat.rejected_moves[(proposed_action.logical_blk_type_index * (placer_opts.place_static_move_prob.size())) + (int)proposed_action.move_type]; + ++move_type_stat.rejected_moves[(proposed_action.logical_blk_type_index * (int)e_move_type::NUMBER_OF_AUTO_MOVES) + (int)proposed_action.move_type]; } /* Revert the traffic flow routes within the NoC*/ if (noc_opts.noc) { From 790b6527b2262aeb473a7e5d66b6459b28c95ebe Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 28 Apr 2024 17:47:47 -0400 Subject: [PATCH 27/37] move NoC-biased member vars from PlacementContext to CentroidMoveGenerator --- vpr/src/base/vpr_context.h | 9 -- vpr/src/place/RL_agent_util.cpp | 16 ++- vpr/src/place/centroid_move_generator.cpp | 123 +++++++++++++++++++- vpr/src/place/centroid_move_generator.h | 33 +++++- vpr/src/place/directed_moves_util.cpp | 13 ++- vpr/src/place/initial_noc_placement.cpp | 70 ----------- vpr/src/place/noc_group_move_generator.cpp | 128 --------------------- vpr/src/place/noc_group_move_generator.h | 16 --- vpr/src/place/place.cpp | 16 +-- vpr/src/place/simpleRL_move_generator.h | 6 +- 10 files changed, 184 insertions(+), 246 deletions(-) delete mode 100644 vpr/src/place/noc_group_move_generator.cpp delete mode 100644 vpr/src/place/noc_group_move_generator.h diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index d87536fc66e..18420590f2e 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -413,15 +413,6 @@ struct PlacementContext : public Context { * it would mean that per-layer bounding box is used. For the 2D architecture, the cube bounding box would be used. */ bool cube_bb = false; - - - vtr::vector> noc_group_clusters; - - vtr::vector> noc_group_routers; - - vtr::vector cluster_to_noc_grp; - - std::map noc_router_to_noc_group; }; /** diff --git a/vpr/src/place/RL_agent_util.cpp b/vpr/src/place/RL_agent_util.cpp index d9e9f092545..9ed3e55283a 100644 --- a/vpr/src/place/RL_agent_util.cpp +++ b/vpr/src/place/RL_agent_util.cpp @@ -77,13 +77,17 @@ void create_move_generators(std::unique_ptr& move_generator, placer_opts.place_agent_epsilon); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); + move_generator = std::make_unique(karmed_bandit_agent1, + noc_attraction_weight, + placer_opts.place_high_fanout_net); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2, noc_attraction_weight); + move_generator2 = std::make_unique(karmed_bandit_agent2, + noc_attraction_weight, + placer_opts.place_high_fanout_net); } else { std::unique_ptr karmed_bandit_agent1, karmed_bandit_agent2; //agent's 1st state @@ -97,12 +101,16 @@ void create_move_generators(std::unique_ptr& move_generator, e_agent_space::MOVE_TYPE); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator = std::make_unique(karmed_bandit_agent1, noc_attraction_weight); + move_generator = std::make_unique(karmed_bandit_agent1, + noc_attraction_weight, + placer_opts.place_high_fanout_net); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); - move_generator2 = std::make_unique(karmed_bandit_agent2, noc_attraction_weight); + move_generator2 = std::make_unique(karmed_bandit_agent2, + noc_attraction_weight, + placer_opts.place_high_fanout_net); } } } diff --git a/vpr/src/place/centroid_move_generator.cpp b/vpr/src/place/centroid_move_generator.cpp index 07828e19cab..e4e44c1d64c 100644 --- a/vpr/src/place/centroid_move_generator.cpp +++ b/vpr/src/place/centroid_move_generator.cpp @@ -5,14 +5,127 @@ #include "place_constraints.h" #include "move_utils.h" +#include + + +// Static member variable definitions +vtr::vector> CentroidMoveGenerator::noc_group_clusters_; +vtr::vector> CentroidMoveGenerator::noc_group_routers_; +vtr::vector CentroidMoveGenerator::cluster_to_noc_grp_; +std::map CentroidMoveGenerator::noc_router_to_noc_group_; + + CentroidMoveGenerator::CentroidMoveGenerator() : noc_attraction_w_(0.0f) , noc_attraction_enabled_(false) {} -CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight) +CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight, size_t high_fanout_net) : noc_attraction_w_(noc_attraction_weight) , noc_attraction_enabled_(true) { VTR_ASSERT(noc_attraction_weight > 0.0 && noc_attraction_weight <= 1.0); + + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& noc_ctx = g_vpr_ctx.noc(); + + // check if static member variables are already initialized + if (!noc_group_clusters_.empty() && !noc_group_routers_.empty() && + !cluster_to_noc_grp_.empty() && !noc_router_to_noc_group_.empty()) { + return; + } + + noc_group_clusters_.clear(); + noc_group_routers_.clear(); + cluster_to_noc_grp_.clear(); + noc_router_to_noc_group_.clear(); + + /* + * Assume the clustered netlist is an undirected graph where nodes + * represent clustered blocks, and edges are low fanout connections. + * To determine NoC groups, we need to find components that include + * at least one NoC router. To do this, we start a BFS traversal from + * unvisited NoC routers and assign the starting NoC router and all the + * blocks that are visited during the traversal to a NoC group. + */ + + // determines whether a block is visited + vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); + + // NoCGroupIDs are sequential and start from zero. This counter specifies the value to be assigned to a new NoCGroupID + int noc_group_cnt = 0; + + // Initialize the associated NoC group for all blocks to INVALID. If a block is not visited during traversal, + // it does not belong to any NoC groups. For other blocks, the associated NoC group is updated once they are visited. + cluster_to_noc_grp_.resize(cluster_ctx.clb_nlist.blocks().size(), NocGroupId ::INVALID()); + + // Get all the router clusters and the NoC router logical block type + const auto& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); + const auto router_block_type = cluster_ctx.clb_nlist.block_type(router_blk_ids[0]); + + // iterate over logical NoC routers and start a BFS + for (auto router_blk_id : router_blk_ids) { + + if (block_visited[router_blk_id]) { + continue; + } + + NocGroupId noc_group_id(noc_group_cnt); + noc_group_cnt++; + noc_group_routers_.emplace_back(); + noc_group_clusters_.emplace_back(); + + // BFS frontier + std::queue q; + + // initialize the frontier with the NoC router + q.push(router_blk_id); + block_visited[router_blk_id] = true; + + while (!q.empty()) { + ClusterBlockId current_block_id = q.front(); + q.pop(); + + // get the logical block type for the block extracted from the frontier queue + auto block_type = cluster_ctx.clb_nlist.block_type(current_block_id); + + if (block_type->index == router_block_type->index) { + noc_group_routers_[noc_group_id].push_back(current_block_id); + noc_router_to_noc_group_[current_block_id] = noc_group_id; + } else { + noc_group_clusters_[noc_group_id].push_back(current_block_id); + cluster_to_noc_grp_[current_block_id] = noc_group_id; + } + + // iterate over all low fanout nets of the current block to find its unvisited neighbors + for (ClusterPinId pin_id : cluster_ctx.clb_nlist.block_pins(current_block_id)) { + ClusterNetId net_id = cluster_ctx.clb_nlist.pin_net(pin_id); + + if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) { + continue; + } + + if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= high_fanout_net) { + continue; + } + + if (cluster_ctx.clb_nlist.pin_type(pin_id) == PinType::DRIVER) { + for (auto sink_pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) { + ClusterBlockId sink_block_id = cluster_ctx.clb_nlist.pin_block(sink_pin_id); + if (!block_visited[sink_block_id]) { + block_visited[sink_block_id] = true; + q.push(sink_block_id); + } + } + } else { //else the pin is sink --> only care about its driver + ClusterPinId source_pin = cluster_ctx.clb_nlist.net_driver(net_id); + ClusterBlockId source_blk_id = cluster_ctx.clb_nlist.pin_block(source_pin); + if (!block_visited[source_blk_id]) { + block_visited[source_blk_id] = true; + q.push(source_blk_id); + } + } + } + } + } } e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, @@ -74,3 +187,11 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block return create_move; } + +const std::vector& CentroidMoveGenerator::get_noc_group_routers(NocGroupId noc_grp_id) { + return CentroidMoveGenerator::noc_group_routers_[noc_grp_id]; +} + +NocGroupId CentroidMoveGenerator::get_cluster_noc_group(ClusterBlockId blk_id) { + return CentroidMoveGenerator::cluster_to_noc_grp_[blk_id]; +} diff --git a/vpr/src/place/centroid_move_generator.h b/vpr/src/place/centroid_move_generator.h index bd17a16113c..b10fb29c286 100644 --- a/vpr/src/place/centroid_move_generator.h +++ b/vpr/src/place/centroid_move_generator.h @@ -1,5 +1,6 @@ #ifndef VPR_CENTROID_MOVE_GEN_H #define VPR_CENTROID_MOVE_GEN_H + #include "move_generator.h" /** @@ -10,12 +11,22 @@ * This move picks a random block and moves it (swapping with what's there if necessary) to the zero force location * It calculates forces/weighs acting on the block based on its connections to other blocks. * + * The computed centroid location can be optionally biased towards the location of NoC routers + * that are reachable from the selected block. A NoC router is reachable from a block if one can + * start from the block and reach the NoC router only by traversing low fanout nets. All the blocks + * (including NoC routers) that can reach a NoC router form a NoC group. + * * Returns its choices by filling in affected_blocks. */ class CentroidMoveGenerator : public MoveGenerator { public: CentroidMoveGenerator(); - CentroidMoveGenerator(float noc_attraction_weight); + CentroidMoveGenerator(float noc_attraction_weight, size_t high_fanout_net); + + + static const std::vector& get_noc_group_routers(NocGroupId noc_grp_id); + + static NocGroupId get_cluster_noc_group(ClusterBlockId blk_id); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, @@ -25,8 +36,28 @@ class CentroidMoveGenerator : public MoveGenerator { const PlacerCriticalities* /*criticalities*/) override; private: + /** A value in range [0, 1] that specifies how much the centroid location + * computation is biased towards the associated NoC routers*/ float noc_attraction_w_; + + /** Indicates whether the centroid calculation is NoC-biased.*/ bool noc_attraction_enabled_; + + /** Stores all non-router blocks for each NoC group*/ + static vtr::vector> noc_group_clusters_; + + /** Stores NoC routers in each NoC group*/ + static vtr::vector> noc_group_routers_; + + /** Specifies the NoC group that each block belongs to. A block cannot belong to more + * than one NoC because this means those NoC groups can reach each other and form + * a single NoC group. We use NocGroupId::INVALID to show that a block does not belong + * to any NoC groups. This happens when a block is not reachable from any NoC router. + * */ + static vtr::vector cluster_to_noc_grp_; + + /** Specifies the NoC group for each NoC router*/ + static std::map noc_router_to_noc_group_; }; #endif diff --git a/vpr/src/place/directed_moves_util.cpp b/vpr/src/place/directed_moves_util.cpp index dd739de985b..18d56973e3b 100644 --- a/vpr/src/place/directed_moves_util.cpp +++ b/vpr/src/place/directed_moves_util.cpp @@ -1,4 +1,6 @@ + #include "directed_moves_util.h" +#include "centroid_move_generator.h" void get_coordinate_of_pin(ClusterPinId pin, t_physical_tile_loc& tile_loc) { auto& device_ctx = g_vpr_ctx.device(); @@ -98,16 +100,19 @@ void calculate_centroid_loc(ClusterBlockId b_from, } if (noc_attraction_enabled) { - if (place_ctx.cluster_to_noc_grp[b_from] != NocGroupId::INVALID()) { + NocGroupId noc_grp_id = CentroidMoveGenerator::get_cluster_noc_group(b_from); - NocGroupId noc_grp_id = place_ctx.cluster_to_noc_grp[b_from]; - float single_noc_weight = (acc_weight * noc_attraction_weight) / place_ctx.noc_group_routers[noc_grp_id].size(); + // check if the block belongs to a NoC group + if (noc_grp_id != NocGroupId::INVALID()) { + // get the routers in the associated NoC group + const auto& noc_routers = CentroidMoveGenerator::get_noc_group_routers(noc_grp_id); + float single_noc_weight = (acc_weight * noc_attraction_weight) / (float)noc_routers.size(); acc_x *= (1.0f - noc_attraction_weight); acc_y *= (1.0f - noc_attraction_weight); acc_weight *= (1.0f - noc_attraction_weight); - for (ClusterBlockId router_blk_id : place_ctx.noc_group_routers[noc_grp_id]) { + for (ClusterBlockId router_blk_id : noc_routers) { t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; acc_x += router_loc.loc.x * single_noc_weight; acc_y += router_loc.loc.y * single_noc_weight; diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index 5ade7c6b060..0b1454b67c2 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -255,11 +255,9 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts) { void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& placer_opts) { auto& noc_ctx = g_vpr_ctx.noc(); - auto& cluster_ctx = g_vpr_ctx.clustering(); // Get all the router clusters const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); - const auto router_block_type = cluster_ctx.clb_nlist.block_type(router_blk_ids[0]); // Holds all the routers that are not fixed into a specific location by constraints std::vector unfixed_routers; @@ -294,72 +292,4 @@ void initial_noc_placement(const t_noc_opts& noc_opts, const t_placer_opts& plac "At least one cycle was found in NoC channel dependency graph. This may cause a deadlock " "when packets wait on each other in a cycle.\n"); } - - vtr::vector block_visited(cluster_ctx.clb_nlist.blocks().size(), false); - auto& place_ctx = g_vpr_ctx.mutable_placement(); - int noc_group_cnt = 0; - place_ctx.cluster_to_noc_grp.resize(cluster_ctx.clb_nlist.blocks().size(), NocGroupId ::INVALID()); - - for (auto router_blk_id : router_blk_ids) { - - if (block_visited[router_blk_id]) { - continue; - } - - NocGroupId noc_group_id(noc_group_cnt); - noc_group_cnt++; - place_ctx.noc_group_routers.emplace_back(); - place_ctx.noc_group_clusters.emplace_back(); - - std::queue q; - q.push(router_blk_id); - block_visited[router_blk_id] = true; - - while (!q.empty()) { - ClusterBlockId current_block_id = q.front(); - q.pop(); - - auto block_type = cluster_ctx.clb_nlist.block_type(current_block_id); - if (block_type->index == router_block_type->index) { - place_ctx.noc_group_routers[noc_group_id].push_back(current_block_id); - place_ctx.noc_router_to_noc_group[current_block_id] = noc_group_id; - } else { - place_ctx.noc_group_clusters[noc_group_id].push_back(current_block_id); - place_ctx.cluster_to_noc_grp[current_block_id] = noc_group_id; - } - - - for (ClusterPinId pin_id : cluster_ctx.clb_nlist.block_pins(current_block_id)) { - ClusterNetId net_id = cluster_ctx.clb_nlist.pin_net(pin_id); - - if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) { - continue; - } - - if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= placer_opts.place_high_fanout_net) { - continue; - } - - if (cluster_ctx.clb_nlist.pin_type(pin_id) == PinType::DRIVER) { - //ignore nets that are globally routed - - for (auto sink_pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) { - auto sink_block_id = cluster_ctx.clb_nlist.pin_block(sink_pin_id); - if (!block_visited[sink_block_id]) { - block_visited[sink_block_id] = true; - q.push(sink_block_id); - } - } - } else { //else the pin is sink --> only care about its driver - ClusterPinId source_pin = cluster_ctx.clb_nlist.net_driver(net_id); - auto source_blk_id = cluster_ctx.clb_nlist.pin_block(source_pin); - if (!block_visited[source_blk_id]) { - block_visited[source_blk_id] = true; - q.push(source_blk_id); - } - } - } - } - - } } \ No newline at end of file diff --git a/vpr/src/place/noc_group_move_generator.cpp b/vpr/src/place/noc_group_move_generator.cpp deleted file mode 100644 index 7b0ee1c0e1b..00000000000 --- a/vpr/src/place/noc_group_move_generator.cpp +++ /dev/null @@ -1,128 +0,0 @@ - -#include "noc_group_move_generator.h" - -#include "move_utils.h" -#include "place_constraints.h" - -e_create_move NocGroupMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, - t_propose_action& proposed_action, - float rlim, - const t_placer_opts& placer_opts, - const PlacerCriticalities* criticalities) { - const auto& noc_ctx = g_vpr_ctx.noc(); - auto& place_ctx = g_vpr_ctx.placement(); - const auto& cluster_ctx = g_vpr_ctx.clustering(); - - e_create_move create_move = e_create_move::ABORT; - - const std::vector& router_blk_ids = noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist(); - - const ClusterBlockId selected_noc_router_blk_id = router_blk_ids[vtr::irand(router_blk_ids.size() - 1)]; - const NocGroupId noc_group_id = place_ctx.noc_router_to_noc_group.find(selected_noc_router_blk_id)->second; - - const auto& group_routers = place_ctx.noc_group_routers[noc_group_id]; - const auto& group_clusters = place_ctx.noc_group_clusters[noc_group_id]; - - auto& device_ctx = g_vpr_ctx.device(); - auto& grid = device_ctx.grid; - const int num_layers = grid.get_num_layers(); - - //Collect the set of x/y locations for each instance of a block type - //[group_noc_router_idx][logical_block_type][layer_num][0...num_instance_on_layer] -> (x, y), sub-tile - std::vector, int>>>>> block_locations; - block_locations.resize(group_routers.size()); - - for (size_t group_noc_router_idx = 0; group_noc_router_idx < group_routers.size(); group_noc_router_idx++) { - block_locations[group_noc_router_idx].resize(device_ctx.logical_block_types.size()); - for (int block_type_num = 0; block_type_num < (int)device_ctx.logical_block_types.size(); block_type_num++) { - block_locations[group_noc_router_idx][block_type_num].resize(num_layers); - } - } - - - for (size_t group_noc_router_idx = 0; group_noc_router_idx < group_routers.size(); group_noc_router_idx++) { - ClusterBlockId router_blk_id = group_routers[group_noc_router_idx]; - t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; - const int half_length = 10; - int min_x = std::max(router_loc.loc.x - half_length, 0); - int max_x = std::min(router_loc.loc.x + half_length, device_ctx.grid.width() - 1); - int min_y = std::max(router_loc.loc.y - half_length, 0); - int max_y = std::min(router_loc.loc.y + half_length, device_ctx.grid.height() - 1); - int layer_num = router_loc.loc.layer; - - for (int x = min_x; x < max_x; ++x) { - for (int y = min_y; y < max_y; ++y) { - int width_offset = grid.get_width_offset({x, y, layer_num}); - int height_offset = grid.get_height_offset(t_physical_tile_loc(x, y, layer_num)); - if (width_offset == 0 && height_offset == 0) { - const auto& type = grid.get_physical_type({x, y, layer_num}); - auto equivalent_sites = get_equivalent_sites_set(type); - - for (auto& block : equivalent_sites) { - - const auto& compressed_block_grid = place_ctx.compressed_block_grids[block->index]; - std::vector router_compressed_loc = get_compressed_loc_approx(compressed_block_grid, - {x, y, 0, layer_num}, - num_layers); - - int sub_tile = has_empty_compatible_subtile(block, router_compressed_loc[layer_num]); - if (sub_tile >= 0) { - block_locations[group_noc_router_idx][block->index][layer_num].push_back({{x, y}, sub_tile}); - } - - } - } - } - } - } - - std::set tried_locs; - - for (auto block_id : group_clusters) { - int i_macro; - get_imacro_from_iblk(&i_macro, block_id, place_ctx.pl_macros); - if (i_macro != -1) { - continue; - } - - int group_noc_router_idx = vtr::irand(group_routers.size()-1); - ClusterBlockId router_blk_id = group_routers[group_noc_router_idx]; - t_block_loc router_loc = place_ctx.block_locs[router_blk_id]; - - int layer_num = router_loc.loc.layer; - - t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(block_id); - - size_t n_points = block_locations[group_noc_router_idx][block_type->index][layer_num].size(); - if (n_points == 0) { -// std::cout << "No empty blocks around the selected NoC router" << std::endl; - continue; - } - int point_idx = vtr::irand(n_points - 1); - auto selected_empty_point = block_locations[group_noc_router_idx][block_type->index][layer_num][point_idx]; - - t_pl_loc to_loc{selected_empty_point.first.x(), selected_empty_point.first.y(), selected_empty_point.second, layer_num}; - block_locations[group_noc_router_idx][block_type->index][layer_num].erase(block_locations[group_noc_router_idx][block_type->index][layer_num].begin() + point_idx); - create_move = ::create_move(blocks_affected, block_id, to_loc); - - bool added = tried_locs.insert(to_loc).second; - if (!added) { - std::cout << "repetitive" << std::endl; - } - if (create_move == e_create_move::ABORT) { - std::cout << "clear" << std::endl; - clear_move_blocks(blocks_affected); - return e_create_move::ABORT; - } - } - - - - //Check that all the blocks affected by the move would still be in a legal floorplan region after the swap - if (!floorplan_legal(blocks_affected)) { - std::cout << "illegal floorplan" << std::endl; - return e_create_move::ABORT; - } - - return create_move; -} \ No newline at end of file diff --git a/vpr/src/place/noc_group_move_generator.h b/vpr/src/place/noc_group_move_generator.h deleted file mode 100644 index 7ae6041f0a3..00000000000 --- a/vpr/src/place/noc_group_move_generator.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef VTR_NOC_GROUP_MOVE_GENERATOR_H -#define VTR_NOC_GROUP_MOVE_GENERATOR_H - -#include "move_generator.h" - - -class NocGroupMoveGenerator : public MoveGenerator { - public: - e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, - t_propose_action& proposed_action, - float rlim, - const t_placer_opts& placer_opts, - const PlacerCriticalities* criticalities) override; -}; - -#endif //VTR_NOC_GROUP_MOVE_GENERATOR_H \ No newline at end of file diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index e45d8a0a27c..94fd0120838 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "NetPinTimingInvalidator.h" @@ -16,6 +15,7 @@ #include "vtr_geometry.h" #include "vtr_time.h" #include "vtr_math.h" +#include "vtr_ndmatrix.h" #include "vpr_types.h" #include "vpr_error.h" @@ -70,14 +70,12 @@ #include "noc_place_utils.h" -#include "noc_group_move_generator.h" - /* define the RL agent's reward function factor constant. This factor controls the weight of bb cost * * compared to the timing cost in the agent's reward function. The reward is calculated as * * -1*(1.5-REWARD_BB_TIMING_RELATIVE_WEIGHT)*timing_cost + (1+REWARD_BB_TIMING_RELATIVE_WEIGHT)*bb_cost) */ -#define REWARD_BB_TIMING_RELATIVE_WEIGHT 0.4 +static constexpr float REWARD_BB_TIMING_RELATIVE_WEIGHT = 0.4; #ifdef VTR_ENABLE_DEBUG_LOGGING # include "draw_types.h" @@ -92,12 +90,12 @@ using std::min; /* This defines the error tolerance for floating points variables used in * * cost computation. 0.01 means that there is a 1% error tolerance. */ -#define ERROR_TOL .01 +static constexpr double ERROR_TOL = .01; /* This defines the maximum number of swap attempts before invoking the * * once-in-a-while placement legality check as well as floating point * * variables round-offs check. */ -#define MAX_MOVES_BEFORE_RECOMPUTE 500000 +static constexpr int MAX_MOVES_BEFORE_RECOMPUTE = 500000; /* Flags for the states of the bounding box. * * Stored as char for memory efficiency. */ @@ -105,7 +103,7 @@ using std::min; #define UPDATED_ONCE 'U' #define GOT_FROM_SCRATCH 'S' -/* For comp_cost. NORMAL means use the method that generates updateable * +/* For comp_cost. NORMAL means use the method that generates updatable * * bounding boxes for speed. CHECK means compute all bounding boxes from * * scratch using a very simple routine to allow checks of the other * * costs. @@ -1719,9 +1717,7 @@ static e_move_result try_swap(const t_annealing_state* state, #endif //NO_GRAPHICS } else if (router_block_move) { // generate a move where two random router blocks are swapped -// create_move_outcome = propose_router_swap(blocks_affected, rlim); - NocGroupMoveGenerator noc_group_move_gen; - create_move_outcome = noc_group_move_gen.propose_move(blocks_affected, proposed_action, 20, placer_opts, criticalities); + create_move_outcome = propose_router_swap(blocks_affected, rlim); proposed_action.move_type = e_move_type::UNIFORM; } else { //Generate a new move (perturbation) used to explore the space of possible placements diff --git a/vpr/src/place/simpleRL_move_generator.h b/vpr/src/place/simpleRL_move_generator.h index 3d3f66789d5..db74e30ef24 100644 --- a/vpr/src/place/simpleRL_move_generator.h +++ b/vpr/src/place/simpleRL_move_generator.h @@ -216,7 +216,7 @@ class SimpleRLMoveGenerator : public MoveGenerator { */ template::value || std::is_same::value>::type> - explicit SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight); + explicit SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight, size_t high_fanout_thresh); // Updates affected_blocks with the proposed move, while respecting the current rlim e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, @@ -230,7 +230,7 @@ class SimpleRLMoveGenerator : public MoveGenerator { }; template -SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight) { +SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent, float noc_attraction_weight, size_t high_fanout_thresh) { if (noc_attraction_weight > 0.0f) { avail_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES); } else { @@ -245,7 +245,7 @@ SimpleRLMoveGenerator::SimpleRLMoveGenerator(std::unique_ptr& agent, float no avail_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(); avail_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(); if (noc_attraction_weight > 0.0f) { - avail_moves[e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(noc_attraction_weight); + avail_moves[e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(noc_attraction_weight, high_fanout_thresh); } karmed_bandit_agent = std::move(agent); From 82ffe3ffd610446cb64467801db3fe2af63f68d4 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 28 Apr 2024 19:13:35 -0400 Subject: [PATCH 28/37] enum class for e_block_pack_status --- vpr/src/base/vpr_types.h | 2 +- vpr/src/pack/cluster_util.cpp | 151 +++++++++++++++---------------- vpr/src/pack/cluster_util.h | 42 ++++----- vpr/src/pack/re_cluster_util.cpp | 18 ++-- 4 files changed, 105 insertions(+), 108 deletions(-) diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index c007e37bddb..e4d05a8c65f 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -170,7 +170,7 @@ enum class e_cluster_seed { BLEND2 }; -enum e_block_pack_status { +enum class e_block_pack_status { BLK_PASSED, BLK_FAILED_FEASIBLE, BLK_FAILED_ROUTE, diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 84dd08f3a0e..1a41849bf47 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -918,34 +918,28 @@ bool cleanup_pb(t_pb* pb) { * Otherwise, it returns the appropriate failed pack status based on which * legality check the molecule failed. */ -enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, - t_pack_molecule* molecule, - t_pb_graph_node** primitives_list, - t_pb* pb, - const int max_models, - const int max_cluster_size, - const ClusterBlockId clb_index, - const int detailed_routing_stage, - t_lb_router_data* router_data, - int verbosity, - bool enable_pin_feasibility_filter, - const int feasible_block_array_size, - t_ext_pin_util max_external_pin_util, - PartitionRegion& temp_cluster_pr) { - int molecule_size, failed_location; - int i; - enum e_block_pack_status block_pack_status; +e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, + t_pack_molecule* molecule, + t_pb_graph_node** primitives_list, + t_pb* pb, + int max_models, + int max_cluster_size, + ClusterBlockId clb_index, + int detailed_routing_stage, + t_lb_router_data* router_data, + int verbosity, + bool enable_pin_feasibility_filter, + int feasible_block_array_size, + t_ext_pin_util max_external_pin_util, + PartitionRegion& temp_cluster_pr) { t_pb* parent; t_pb* cur_pb; - auto& atom_ctx = g_vpr_ctx.atom(); + const auto& atom_ctx = g_vpr_ctx.atom(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); parent = nullptr; - block_pack_status = BLK_STATUS_UNDEFINED; - - molecule_size = get_array_size_of_molecule(molecule); - failed_location = 0; + const int molecule_size = get_array_size_of_molecule(molecule); if (verbosity > 3) { AtomBlockId root_atom = molecule->atom_block_ids[molecule->root]; @@ -968,62 +962,66 @@ enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_pl VTR_LOGV(verbosity > 4, "\t\t\tFAILED Placement Feasibility Filter: Only one long chain per cluster is allowed\n"); //Record the failure of this molecule in the current pb stats record_molecule_failure(molecule, pb); - return BLK_FAILED_FEASIBLE; + return e_block_pack_status::BLK_FAILED_FEASIBLE; } - bool cluster_pr_needs_update = false; bool cluster_pr_update_check = false; //check if every atom in the molecule is legal in the cluster from a floorplanning perspective for (int i_mol = 0; i_mol < molecule_size; i_mol++) { //try to intersect with atom PartitionRegion if atom exists if (molecule->atom_block_ids[i_mol]) { - block_pack_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[i_mol], - clb_index, verbosity, - temp_cluster_pr, - cluster_pr_needs_update); - if (block_pack_status == BLK_FAILED_FLOORPLANNING) { + bool cluster_pr_needs_update = false; + bool block_pack_floorplan_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[i_mol], + clb_index, verbosity, + temp_cluster_pr, + cluster_pr_needs_update); + + if (!block_pack_floorplan_status) { //Record the failure of this molecule in the current pb stats record_molecule_failure(molecule, pb); - return block_pack_status; + return e_block_pack_status::BLK_FAILED_FLOORPLANNING; } - if (cluster_pr_needs_update == true) { + + if (cluster_pr_needs_update) { cluster_pr_update_check = true; } } } - //change status back to undefined before the while loop in case in was changed to BLK_PASSED in the above for loop - block_pack_status = BLK_STATUS_UNDEFINED; + e_block_pack_status block_pack_status = e_block_pack_status::BLK_STATUS_UNDEFINED; - while (block_pack_status != BLK_PASSED) { + while (block_pack_status != e_block_pack_status::BLK_PASSED) { if (get_next_primitive_list(cluster_placement_stats_ptr, molecule, primitives_list)) { - block_pack_status = BLK_PASSED; + block_pack_status = e_block_pack_status::BLK_PASSED; + + int failed_location = 0; - for (i = 0; i < molecule_size && block_pack_status == BLK_PASSED; i++) { - VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); - failed_location = i + 1; + for (int i_mol = 0; i_mol < molecule_size && block_pack_status == e_block_pack_status::BLK_PASSED; i_mol++) { + VTR_ASSERT((primitives_list[i_mol] == nullptr) == (!molecule->atom_block_ids[i_mol])); + failed_location = i_mol + 1; // try place atom block if it exists - if (molecule->atom_block_ids[i]) { - block_pack_status = try_place_atom_block_rec(primitives_list[i], - molecule->atom_block_ids[i], pb, &parent, + if (molecule->atom_block_ids[i_mol]) { + block_pack_status = try_place_atom_block_rec(primitives_list[i_mol], + molecule->atom_block_ids[i_mol], pb, &parent, max_models, max_cluster_size, clb_index, cluster_placement_stats_ptr, molecule, router_data, verbosity, feasible_block_array_size); } } - if (enable_pin_feasibility_filter && block_pack_status == BLK_PASSED) { + if (enable_pin_feasibility_filter && block_pack_status == e_block_pack_status::BLK_PASSED) { /* Check if pin usage is feasible for the current packing assignment */ reset_lookahead_pins_used(pb); try_update_lookahead_pins_used(pb); if (!check_lookahead_pins_used(pb, max_external_pin_util)) { VTR_LOGV(verbosity > 4, "\t\t\tFAILED Pin Feasibility Filter\n"); - block_pack_status = BLK_FAILED_FEASIBLE; + block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; } } - if (block_pack_status == BLK_PASSED) { + + if (block_pack_status == e_block_pack_status::BLK_PASSED) { /* * during the clustering step of `do_clustering`, `detailed_routing_stage` is incremented at each iteration until it a cluster * is correctly generated or `detailed_routing_stage` assumes an invalid value (E_DETAILED_ROUTE_INVALID). @@ -1063,15 +1061,15 @@ enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_pl } while (do_detailed_routing_stage && mode_status.is_mode_issue()); } - if (do_detailed_routing_stage && is_routed == false) { + if (do_detailed_routing_stage && !is_routed) { /* Cannot pack */ VTR_LOGV(verbosity > 4, "\t\t\tFAILED Detailed Routing Legality\n"); - block_pack_status = BLK_FAILED_ROUTE; + block_pack_status = e_block_pack_status::BLK_FAILED_ROUTE; } else { /* Pack successful, commit * TODO: SW Engineering note - may want to update cluster stats here too instead of doing it outside */ - VTR_ASSERT(block_pack_status == BLK_PASSED); + VTR_ASSERT(block_pack_status == e_block_pack_status::BLK_PASSED); if (molecule->is_chain()) { /* Chained molecules often take up lots of area and are important, * if a chain is packed in, want to rename logic block to match chain name */ @@ -1103,7 +1101,7 @@ enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_pl } } - for (i = 0; i < molecule_size; i++) { + for (int i = 0; i < molecule_size; i++) { if (molecule->atom_block_ids[i]) { /* invalidate all molecules that share atom block with current molecule */ @@ -1119,13 +1117,13 @@ enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_pl } } - if (block_pack_status != BLK_PASSED) { - for (i = 0; i < failed_location; i++) { + if (block_pack_status != e_block_pack_status::BLK_PASSED) { + for (int i = 0; i < failed_location; i++) { if (molecule->atom_block_ids[i]) { remove_atom_from_target(router_data, molecule->atom_block_ids[i]); } } - for (i = 0; i < failed_location; i++) { + for (int i = 0; i < failed_location; i++) { if (molecule->atom_block_ids[i]) { revert_place_atom_block(molecule->atom_block_ids[i], router_data); } @@ -1144,7 +1142,7 @@ enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_pl } } else { VTR_LOGV(verbosity > 3, "\t\tFAILED No candidate primitives available\n"); - block_pack_status = BLK_FAILED_FEASIBLE; + block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; break; /* no more candidate primitives available, this molecule will not pack, return fail */ } } @@ -1195,7 +1193,7 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap my_parent = nullptr; - block_pack_status = BLK_PASSED; + block_pack_status = e_block_pack_status::BLK_PASSED; /* Discover parent */ if (pb_graph_node->parent_pb_graph_node != cb->pb_graph_node) { @@ -1253,7 +1251,7 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap * Early exit to flag failure */ if (true == pb_type->parent_mode->disable_packing) { - return BLK_FAILED_FEASIBLE; + return e_block_pack_status::BLK_FAILED_FEASIBLE; } is_primitive = (pb_type->num_modes == 0); @@ -1273,11 +1271,11 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap add_atom_as_target(router_data, blk_id); if (!primitive_feasible(blk_id, pb)) { /* failed location feasibility check, revert pack */ - block_pack_status = BLK_FAILED_FEASIBLE; + block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; } // if this block passed and is part of a chained molecule - if (block_pack_status == BLK_PASSED && molecule->is_chain()) { + if (block_pack_status == e_block_pack_status::BLK_PASSED && molecule->is_chain()) { auto molecule_root_block = molecule->atom_block_ids[molecule->root]; // if this is the root block of the chain molecule check its placmeent feasibility if (blk_id == molecule_root_block) { @@ -1285,14 +1283,14 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap } } - VTR_LOGV(verbosity > 4 && block_pack_status == BLK_PASSED, + VTR_LOGV(verbosity > 4 && block_pack_status == e_block_pack_status::BLK_PASSED, "\t\t\tPlaced atom '%s' (%s) at %s\n", atom_ctx.nlist.block_name(blk_id).c_str(), atom_ctx.nlist.block_model(blk_id)->name, pb->hierarchical_type_name().c_str()); } - if (block_pack_status != BLK_PASSED) { + if (block_pack_status != e_block_pack_status::BLK_PASSED) { free(pb->name); pb->name = nullptr; } @@ -1304,11 +1302,11 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap * If the atom and cluster both have non-empty PartitionRegions, and the intersection * of the PartitionRegions is empty, the atom cannot be packed in the cluster. */ -enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - const int verbosity, - PartitionRegion& temp_cluster_pr, - bool& cluster_pr_needs_update) { +bool atom_cluster_floorplanning_check(AtomBlockId blk_id, + ClusterBlockId clb_index, + int verbosity, + PartitionRegion& temp_cluster_pr, + bool& cluster_pr_needs_update) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ @@ -1324,7 +1322,7 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ VTR_LOG("\t\t\t Intersect: Atom block %d has no floorplanning constraints, passed for cluster %d \n", blk_id, clb_index); } cluster_pr_needs_update = false; - return BLK_PASSED; + return true; } else { //get pr of that partition const PartitionRegion& atom_pr = floorplanning_ctx.constraints.get_partition_pr(partid); @@ -1338,19 +1336,20 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d has floorplanning constraints, passed cluster %d which has empty PR\n", blk_id, clb_index); } - return BLK_PASSED; + return true; } else { //update cluster_pr with the intersection of the cluster's PartitionRegion //and the atom's PartitionRegion update_cluster_part_reg(cluster_pr, atom_pr); } + // At this point, cluster_pr is the intersection of atom_pr and the clusters current pr if (cluster_pr.empty()) { if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); } cluster_pr_needs_update = false; - return BLK_FAILED_FLOORPLANNING; + return false; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion temp_cluster_pr = cluster_pr; @@ -1358,7 +1357,7 @@ enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_ if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d, cluster PR was updated with intersection result \n", blk_id, clb_index); } - return BLK_PASSED; + return false; } } } @@ -1528,15 +1527,15 @@ void try_fill_cluster(const t_packer_opts& packer_opts, std::string blk_name = atom_ctx.nlist.block_name(blk_id); const t_model* blk_model = atom_ctx.nlist.block_model(blk_id); - if (block_pack_status != BLK_PASSED) { + if (block_pack_status != e_block_pack_status::BLK_PASSED) { if (packer_opts.pack_verbosity > 2) { - if (block_pack_status == BLK_FAILED_ROUTE) { + if (block_pack_status == e_block_pack_status::BLK_FAILED_ROUTE) { VTR_LOG("\tNO_ROUTE: '%s' (%s)", blk_name.c_str(), blk_model->name); VTR_LOGV(next_molecule->pack_pattern, " molecule %s molecule_size %zu", next_molecule->pack_pattern->name, next_molecule->atom_block_ids.size()); VTR_LOG("\n"); fflush(stdout); - } else if (block_pack_status == BLK_FAILED_FLOORPLANNING) { + } else if (block_pack_status == e_block_pack_status::BLK_FAILED_FLOORPLANNING) { VTR_LOG("\tFAILED_FLOORPLANNING_CONSTRAINTS_CHECK: '%s' (%s)", blk_name.c_str(), blk_model->name); VTR_LOG("\n"); } else { @@ -2104,7 +2103,7 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, *router_data = alloc_and_load_router_data(&lb_type_rr_graphs[type->index], type); //Try packing into each mode - e_block_pack_status pack_result = BLK_STATUS_UNDEFINED; + e_block_pack_status pack_result = e_block_pack_status::BLK_STATUS_UNDEFINED; for (int j = 0; j < type->pb_graph_head->pb_type->num_modes && !success; j++) { pb->mode = j; @@ -2126,7 +2125,7 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, FULL_EXTERNAL_PIN_UTIL, temp_cluster_pr); - success = (pack_result == BLK_PASSED); + success = (pack_result == e_block_pack_status::BLK_PASSED); } if (success) { @@ -3428,7 +3427,7 @@ void update_molecule_chain_info(t_pack_molecule* chain_molecule, const t_pb_grap enum e_block_pack_status check_chain_root_placement_feasibility(const t_pb_graph_node* pb_graph_node, const t_pack_molecule* molecule, const AtomBlockId blk_id) { - enum e_block_pack_status block_pack_status = BLK_PASSED; + enum e_block_pack_status block_pack_status = e_block_pack_status::BLK_PASSED; auto& atom_ctx = g_vpr_ctx.atom(); bool is_long_chain = molecule->chain_info->is_long_chain; @@ -3456,11 +3455,11 @@ enum e_block_pack_status check_chain_root_placement_feasibility(const t_pb_graph // the chosen primitive should be a valid starting point for the chain // long chains should only be placed at the top of the chain tieOff = 0 if (pb_graph_node != chain_root_pins[chain_id][0]->parent_node) { - block_pack_status = BLK_FAILED_FEASIBLE; + block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; } // the chain doesn't have an assigned chain_id yet } else { - block_pack_status = BLK_FAILED_FEASIBLE; + block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; for (const auto& chain : chain_root_pins) { for (auto tieOff : chain) { // check if this chosen primitive is one of the possible @@ -3468,7 +3467,7 @@ enum e_block_pack_status check_chain_root_placement_feasibility(const t_pb_graph if (pb_graph_node == tieOff->parent_node) { // this location matches with the one of the dedicated chain // input from outside logic block, therefore it is feasible - block_pack_status = BLK_PASSED; + block_pack_status = e_block_pack_status::BLK_PASSED; break; } // long chains should only be placed at the top of the chain tieOff = 0 diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index 2f01e38b1e5..3e6e83dec27 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -19,8 +19,8 @@ * @brief This file includes useful structs and functions for building and modifying clustering */ -#define AAPACK_MAX_HIGH_FANOUT_EXPLORE 10 /* For high-fanout nets that are ignored, consider a maximum of this many sinks, must be less than packer_opts.feasible_block_array_size */ -#define AAPACK_MAX_TRANSITIVE_EXPLORE 40 /* When investigating transitive fanout connections in packing, consider a maximum of this many molecules, must be less than packer_opts.feasible_block_array_size */ +constexpr int AAPACK_MAX_HIGH_FANOUT_EXPLORE = 10; /* For high-fanout nets that are ignored, consider a maximum of this many sinks, must be less than packer_opts.feasible_block_array_size */ +constexpr int AAPACK_MAX_TRANSITIVE_EXPLORE = 40; /* When investigating transitive fanout connections in packing, consider a maximum of this many molecules, must be less than packer_opts.feasible_block_array_size */ //Constant allowing all cluster pins to be used const t_ext_pin_util FULL_EXTERNAL_PIN_UTIL(1., 1.); @@ -200,20 +200,20 @@ void rebuild_attraction_groups(AttractionInfo& attraction_groups); void record_molecule_failure(t_pack_molecule* molecule, t_pb* pb); -enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, - t_pack_molecule* molecule, - t_pb_graph_node** primitives_list, - t_pb* pb, - const int max_models, - const int max_cluster_size, - const ClusterBlockId clb_index, - const int detailed_routing_stage, - t_lb_router_data* router_data, - int verbosity, - bool enable_pin_feasibility_filter, - const int feasible_block_array_size, - t_ext_pin_util max_external_pin_util, - PartitionRegion& temp_cluster_pr); +e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, + t_pack_molecule* molecule, + t_pb_graph_node** primitives_list, + t_pb* pb, + int max_models, + int max_cluster_size, + ClusterBlockId clb_index, + int detailed_routing_stage, + t_lb_router_data* router_data, + int verbosity, + bool enable_pin_feasibility_filter, + int feasible_block_array_size, + t_ext_pin_util max_external_pin_util, + PartitionRegion& temp_cluster_pr); void try_fill_cluster(const t_packer_opts& packer_opts, t_cluster_placement_stats* cur_cluster_placement_stats_ptr, @@ -278,11 +278,11 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap int verbosity, const int feasible_block_array_size); -enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - const int verbosity, - PartitionRegion& temp_cluster_pr, - bool& cluster_pr_needs_update); +bool atom_cluster_floorplanning_check(AtomBlockId blk_id, + ClusterBlockId clb_index, + int verbosity, + PartitionRegion& temp_cluster_pr, + bool& cluster_pr_needs_update); void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data); diff --git a/vpr/src/pack/re_cluster_util.cpp b/vpr/src/pack/re_cluster_util.cpp index b3c1d2c2fa9..5e1c2f7e142 100644 --- a/vpr/src/pack/re_cluster_util.cpp +++ b/vpr/src/pack/re_cluster_util.cpp @@ -1,6 +1,5 @@ #include "re_cluster_util.h" -#include "vpr_context.h" #include "clustered_netlist_utils.h" #include "cluster_util.h" #include "cluster_router.h" @@ -8,7 +7,6 @@ #include "place_macro.h" #include "initial_placement.h" #include "read_netlist.h" -#include //The name suffix of the new block (if exists) const char* name_suffix = "_m"; @@ -94,7 +92,7 @@ void commit_mol_move(const ClusterBlockId& old_clb, g_vpr_ctx.mutable_placement().block_locs.resize(g_vpr_ctx.placement().block_locs.size() + 1); get_imacro_from_iblk(&imacro, old_clb, g_vpr_ctx.placement().pl_macros); set_imacro_for_iblk(&imacro, new_clb); - place_one_block(new_clb, device_ctx.pad_loc_type, NULL, NULL); + place_one_block(new_clb, device_ctx.pad_loc_type, nullptr, nullptr); } } @@ -146,7 +144,7 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, *router_data = alloc_and_load_router_data(&(helper_ctx.lb_type_rr_graphs[type->index]), type); - e_block_pack_status pack_result = BLK_STATUS_UNDEFINED; + e_block_pack_status pack_result = e_block_pack_status::BLK_STATUS_UNDEFINED; pb->mode = mode; reset_cluster_placement_stats(&(helper_ctx.cluster_placement_stats[type->index])); set_mode_cluster_placement_stats(pb->pb_graph_node, mode); @@ -167,7 +165,7 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, temp_cluster_pr); // If clustering succeeds, add it to the clb netlist - if (pack_result == BLK_PASSED) { + if (pack_result == e_block_pack_status::BLK_PASSED) { VTR_LOGV(verbosity > 4, "\tPASSED_SEED: Block Type %s\n", type->name); //Once clustering succeeds, add it to the clb netlist if (pb->name != nullptr) { @@ -194,7 +192,7 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, free_router_data(*router_data); *router_data = nullptr; - return (pack_result == BLK_PASSED); + return (pack_result == e_block_pack_status::BLK_PASSED); } bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, @@ -209,7 +207,7 @@ bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); PartitionRegion temp_cluster_pr; - e_block_pack_status pack_result = BLK_STATUS_UNDEFINED; + e_block_pack_status pack_result = e_block_pack_status::BLK_STATUS_UNDEFINED; t_ext_pin_util target_ext_pin_util = helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(new_clb)->name); t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(new_clb); t_pb* temp_pb = cluster_ctx.clb_nlist.block_pb(new_clb); @@ -240,7 +238,7 @@ bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, temp_cluster_pr); // If clustering succeeds, add it to the clb netlist - if (pack_result == BLK_PASSED) { + if (pack_result == e_block_pack_status::BLK_PASSED) { //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. if (during_packing) { free_intra_lb_nets(clustering_data.intra_lb_routing[new_clb]); @@ -265,7 +263,7 @@ bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, router_data = nullptr; } - return (pack_result == BLK_PASSED); + return (pack_result == e_block_pack_status::BLK_PASSED); } void fix_clustered_netlist(t_pack_molecule* molecule, @@ -300,7 +298,7 @@ void revert_mol_move(const ClusterBlockId& old_clb, helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(old_clb)->name), temp_cluster_pr_original); - VTR_ASSERT(pack_result == BLK_PASSED); + VTR_ASSERT(pack_result == e_block_pack_status::BLK_PASSED); //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. if (during_packing) { free_intra_lb_nets(clustering_data.intra_lb_routing[old_clb]); From 922246a71eb5814cc2245255da7df041120b0613 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 28 Apr 2024 19:28:53 -0400 Subject: [PATCH 29/37] add noc_aware_cluster_util files --- vpr/src/pack/noc_aware_cluster_util.cpp | 125 +++++++++++++++++++++++ vpr/src/pack/noc_aware_cluster_util.h | 13 +++ vpr/src/pack/pack.cpp | 130 +----------------------- 3 files changed, 139 insertions(+), 129 deletions(-) create mode 100644 vpr/src/pack/noc_aware_cluster_util.cpp create mode 100644 vpr/src/pack/noc_aware_cluster_util.h diff --git a/vpr/src/pack/noc_aware_cluster_util.cpp b/vpr/src/pack/noc_aware_cluster_util.cpp new file mode 100644 index 00000000000..0689b848446 --- /dev/null +++ b/vpr/src/pack/noc_aware_cluster_util.cpp @@ -0,0 +1,125 @@ + +#include "noc_aware_cluster_util.h" +#include "globals.h" + +#include + +std::vector find_noc_router_atoms() { + const auto& atom_ctx = g_vpr_ctx.atom(); + + // NoC router atoms are expected to have a specific blif model + const std::string noc_router_blif_model_name = "noc_router_adapter_block"; + + // stores found NoC router atoms + std::vector noc_router_atoms; + + // iterate over all atoms and find those whose blif model matches + for (auto atom_id : atom_ctx.nlist.blocks()) { + const t_model* model = atom_ctx.nlist.block_model(atom_id); + if (noc_router_blif_model_name == model->name) { + noc_router_atoms.push_back(atom_id); + } + } + + return noc_router_atoms; +} + +void update_noc_reachability_partitions(const std::vector& noc_atoms) { + const auto& atom_ctx = g_vpr_ctx.atom(); + auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; + const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; + const auto& device_ctx = g_vpr_ctx.device(); + const auto& grid = device_ctx.grid; + + t_logical_block_type_ptr logic_block_type = infer_logic_block_type(grid); + const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logic_block_type->name); + + // get the total number of atoms + const size_t n_atoms = atom_ctx.nlist.blocks().size(); + + vtr::vector atom_visited(n_atoms, false); + + int exclusivity_cnt = 0; + + RegionRectCoord unconstrained_rect{0, + 0, + std::numeric_limits::max(), + std::numeric_limits::max(), + 0}; + Region unconstrained_region; + unconstrained_region.set_region_rect(unconstrained_rect); + + for (auto noc_atom_id : noc_atoms) { + // check if this NoC router has already been visited + if (atom_visited[noc_atom_id]) { + continue; + } + + exclusivity_cnt++; + + PartitionRegion associated_noc_partition_region; + associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); + associated_noc_partition_region.add_to_part_region(unconstrained_region); + + Partition associated_noc_partition; + associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); + associated_noc_partition.set_part_region(associated_noc_partition_region); + auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); + constraints.add_partition(associated_noc_partition); + + const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); + + if (noc_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); + } else { // noc atom is already in a partition + auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); + auto& noc_partition_region = noc_partition.get_mutable_part_region(); + VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); + noc_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + std::queue q; + q.push(noc_atom_id); + atom_visited[noc_atom_id] = true; + + while (!q.empty()) { + AtomBlockId current_atom = q.front(); + q.pop(); + + PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); + if (atom_partition_id == PartitionId::INVALID()) { + constraints.add_constrained_atom(current_atom, associated_noc_partition_id); + } else { + auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); + auto& atom_partition_region = atom_partition.get_mutable_part_region(); + VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); + atom_partition_region.set_exclusivity_index(exclusivity_cnt); + } + + for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { + AtomNetId net_id = atom_ctx.nlist.pin_net(pin); + size_t net_fanout = atom_ctx.nlist.net_sinks(net_id).size(); + + if (net_fanout >= high_fanout_threshold) { + continue; + } + + AtomBlockId driver_atom_id = atom_ctx.nlist.net_driver_block(net_id); + if (!atom_visited[driver_atom_id]) { + q.push(driver_atom_id); + atom_visited[driver_atom_id] = true; + } + + for (auto sink_pin : atom_ctx.nlist.net_sinks(net_id)) { + AtomBlockId sink_atom_id = atom_ctx.nlist.pin_block(sink_pin); + if (!atom_visited[sink_atom_id]) { + q.push(sink_atom_id); + atom_visited[sink_atom_id] = true; + } + } + + } + } + + } +} \ No newline at end of file diff --git a/vpr/src/pack/noc_aware_cluster_util.h b/vpr/src/pack/noc_aware_cluster_util.h new file mode 100644 index 00000000000..0b2f092bca9 --- /dev/null +++ b/vpr/src/pack/noc_aware_cluster_util.h @@ -0,0 +1,13 @@ + +#ifndef VTR_NOC_AWARE_CLUSTER_UTIL_H +#define VTR_NOC_AWARE_CLUSTER_UTIL_H + +#include + +#include "vpr_types.h" + +std::vector find_noc_router_atoms(); + +void update_noc_reachability_partitions(const std::vector& noc_atoms); + +#endif diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 25ef26f996c..46883d72d2c 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -1,11 +1,5 @@ -#include -#include #include #include -#include -#include -#include -#include #include #include "vtr_assert.h" @@ -17,14 +11,13 @@ #include "read_xml_arch_file.h" #include "globals.h" -#include "atom_netlist.h" #include "prepack.h" #include "pack_types.h" #include "pack.h" -#include "read_blif.h" #include "cluster.h" #include "SetupGrid.h" #include "re_cluster.h" +#include "noc_aware_cluster_util.h" /* #define DUMP_PB_GRAPH 1 */ /* #define DUMP_BLIF_INPUT 1 */ @@ -42,127 +35,6 @@ static bool try_size_device_grid(const t_arch& arch, */ static int count_models(const t_model* user_models); -static std::vector find_noc_router_atoms() { - const auto& atom_ctx = g_vpr_ctx.atom(); - - // NoC router atoms are expected to have a specific blif model - const std::string noc_router_blif_model_name = "noc_router_adapter_block"; - - // stores found NoC router atoms - std::vector noc_router_atoms; - - // iterate over all atoms and find those whose blif model matches - for (auto atom_id : atom_ctx.nlist.blocks()) { - const t_model* model = atom_ctx.nlist.block_model(atom_id); - if (noc_router_blif_model_name == model->name) { - noc_router_atoms.push_back(atom_id); - } - } - - return noc_router_atoms; -} - -static void update_noc_reachability_partitions(const std::vector& noc_atoms) { - const auto& atom_ctx = g_vpr_ctx.atom(); - auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; - const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; - const auto& device_ctx = g_vpr_ctx.device(); - const auto& grid = device_ctx.grid; - - t_logical_block_type_ptr logic_block_type = infer_logic_block_type(grid); - const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logic_block_type->name); - - // get the total number of atoms - const size_t n_atoms = atom_ctx.nlist.blocks().size(); - - vtr::vector atom_visited(n_atoms, false); - - int exclusivity_cnt = 0; - - RegionRectCoord unconstrained_rect{0, - 0, - std::numeric_limits::max(), - std::numeric_limits::max(), - 0}; - Region unconstrained_region; - unconstrained_region.set_region_rect(unconstrained_rect); - - for (auto noc_atom_id : noc_atoms) { - // check if this NoC router has already been visited - if (atom_visited[noc_atom_id]) { - continue; - } - - exclusivity_cnt++; - - PartitionRegion associated_noc_partition_region; - associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); - associated_noc_partition_region.add_to_part_region(unconstrained_region); - - Partition associated_noc_partition; - associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); - associated_noc_partition.set_part_region(associated_noc_partition_region); - auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); - constraints.add_partition(associated_noc_partition); - - const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); - - if (noc_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); - } else { // noc atom is already in a partition - auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); - auto& noc_partition_region = noc_partition.get_mutable_part_region(); - VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); - noc_partition_region.set_exclusivity_index(exclusivity_cnt); - } - - std::queue q; - q.push(noc_atom_id); - atom_visited[noc_atom_id] = true; - - while (!q.empty()) { - AtomBlockId current_atom = q.front(); - q.pop(); - - PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); - if (atom_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(current_atom, associated_noc_partition_id); - } else { - auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); - auto& atom_partition_region = atom_partition.get_mutable_part_region(); - VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); - atom_partition_region.set_exclusivity_index(exclusivity_cnt); - } - - for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { - AtomNetId net_id = atom_ctx.nlist.pin_net(pin); - size_t net_fanout = atom_ctx.nlist.net_sinks(net_id).size(); - - if (net_fanout >= high_fanout_threshold) { - continue; - } - - AtomBlockId driver_atom_id = atom_ctx.nlist.net_driver_block(net_id); - if (!atom_visited[driver_atom_id]) { - q.push(driver_atom_id); - atom_visited[driver_atom_id] = true; - } - - for (auto sink_pin : atom_ctx.nlist.net_sinks(net_id)) { - AtomBlockId sink_atom_id = atom_ctx.nlist.pin_block(sink_pin); - if (!atom_visited[sink_atom_id]) { - q.push(sink_atom_id); - atom_visited[sink_atom_id] = true; - } - } - - } - } - - } -} - - bool try_pack(t_packer_opts* packer_opts, const t_analysis_opts* analysis_opts, const t_arch* arch, From 6e20704dc6d6b1e138cda29e1e853cb3ae94c7ba Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 28 Apr 2024 20:15:54 -0400 Subject: [PATCH 30/37] check NoC group compatibility during packing --- vpr/src/base/vpr_context.h | 5 ++- vpr/src/base/vpr_types.h | 1 + vpr/src/pack/cluster.cpp | 5 ++- vpr/src/pack/cluster_util.cpp | 49 +++++++++++++++++++++++-- vpr/src/pack/cluster_util.h | 11 +++++- vpr/src/pack/noc_aware_cluster_util.cpp | 48 ++++-------------------- vpr/src/pack/pack.cpp | 15 -------- vpr/src/pack/re_cluster.cpp | 4 +- vpr/src/pack/re_cluster_util.cpp | 15 ++++++-- vpr/src/pack/re_cluster_util.h | 3 +- 10 files changed, 86 insertions(+), 70 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 18420590f2e..e36f48323d2 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -352,6 +352,9 @@ struct ClusteringHelperContext : public Context { // A vector of unordered_sets of AtomBlockIds that are inside each clustered block [0 .. num_clustered_blocks-1] // unordered_set for faster insertion/deletion during the iterative improvement process of packing vtr::vector> atoms_lookup; + + vtr::vector atom_noc_grp_id; + ~ClusteringHelperContext() { delete[] primitives_list; } @@ -512,7 +515,7 @@ struct FloorplanningContext : public Context { /** * @brief State of the Network on Chip (NoC) * - * This should only contain data structures related to descrbing the + * This should only contain data structures related to describing the * NoC within the device. */ struct NocContext : public Context { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index e4d05a8c65f..44b79e2e5fe 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -175,6 +175,7 @@ enum class e_block_pack_status { BLK_FAILED_FEASIBLE, BLK_FAILED_ROUTE, BLK_FAILED_FLOORPLANNING, + BLK_FAILED_NOC_GROUP, BLK_STATUS_UNDEFINED }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index b19aa4e7f99..10026b22aa3 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -243,6 +243,7 @@ std::map do_clustering(const t_packer_opts& pa * Since some of the primitives might fail legality, this structure temporarily * stores PartitionRegion information while the cluster is packed*/ PartitionRegion temp_cluster_pr; + NocGroupId temp_cluster_noc_grp_id = NocGroupId::INVALID(); start_new_cluster(helper_ctx.cluster_placement_stats, helper_ctx.primitives_list, clb_index, istart, @@ -257,7 +258,8 @@ std::map do_clustering(const t_packer_opts& pa packer_opts.enable_pin_feasibility_filter, balance_block_type_utilization, packer_opts.feasible_block_array_size, - temp_cluster_pr); + temp_cluster_pr, + temp_cluster_noc_grp_id); //initial molecule in cluster has been processed cluster_stats.num_molecules_processed++; @@ -356,6 +358,7 @@ std::map do_clustering(const t_packer_opts& pa router_data, target_ext_pin_util, temp_cluster_pr, + temp_cluster_noc_grp_id, block_pack_status, clustering_data.unclustered_list_head, unclustered_list_head_size, diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 1a41849bf47..9be8810af07 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -931,7 +931,8 @@ e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placeme bool enable_pin_feasibility_filter, int feasible_block_array_size, t_ext_pin_util max_external_pin_util, - PartitionRegion& temp_cluster_pr) { + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id) { t_pb* parent; t_pb* cur_pb; @@ -989,6 +990,20 @@ e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placeme } } + // check if all atoms in the molecule can be added to the cluster without NoC group conflicts + for (int i_mol = 0; i_mol < molecule_size; i_mol++) { + if (molecule->atom_block_ids[i_mol]) { + bool block_pack_noc_grp_status = atom_cluster_noc_group_check(molecule->atom_block_ids[i_mol], + verbosity, temp_noc_grp_id); + + if (!block_pack_noc_grp_status) { + //Record the failure of this molecule in the current pb stats + record_molecule_failure(molecule, pb); + return e_block_pack_status::BLK_FAILED_NOC_GROUP; + } + } + } + e_block_pack_status block_pack_status = e_block_pack_status::BLK_STATUS_UNDEFINED; while (block_pack_status != e_block_pack_status::BLK_PASSED) { @@ -1362,6 +1377,28 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, } } +bool atom_cluster_noc_group_check(AtomBlockId blk_id, + int verbosity, + NocGroupId& temp_cluster_noc_grp_id) { + const NocGroupId atom_noc_grp_id = g_vpr_ctx.cl_helper().atom_noc_grp_id[blk_id]; + + + if (temp_cluster_noc_grp_id == NocGroupId::INVALID()) { + // the cluster does not have a NoC group + // assign the atom's NoC group to cluster + temp_cluster_noc_grp_id = atom_noc_grp_id; + return true; + } else if (temp_cluster_noc_grp_id == atom_noc_grp_id) { + // the cluster has the same NoC group ID as the atom, + // so they are compatible + return true; + } else { + // the cluster belongs to a different NoC group than the atom's group, + // so they are incompatible + return false; + } +} + /* Revert trial atom block iblock and free up memory space accordingly */ void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data) { @@ -1497,6 +1534,7 @@ void try_fill_cluster(const t_packer_opts& packer_opts, t_lb_router_data* router_data, t_ext_pin_util target_ext_pin_util, PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id, e_block_pack_status& block_pack_status, t_molecule_link* unclustered_list_head, const int& unclustered_list_head_size, @@ -1519,7 +1557,8 @@ void try_fill_cluster(const t_packer_opts& packer_opts, packer_opts.enable_pin_feasibility_filter, packer_opts.feasible_block_array_size, target_ext_pin_util, - temp_cluster_pr); + temp_cluster_pr, + temp_noc_grp_id); auto blk_id = next_molecule->atom_block_ids[next_molecule->root]; VTR_ASSERT(blk_id); @@ -2041,7 +2080,8 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, bool enable_pin_feasibility_filter, bool balance_block_type_utilization, const int feasible_block_array_size, - PartitionRegion& temp_cluster_pr) { + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id) { /* Given a starting seed block, start_new_cluster determines the next cluster type to use * It expands the FPGA if it cannot find a legal cluster for the atom block */ @@ -2123,7 +2163,8 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, enable_pin_feasibility_filter, feasible_block_array_size, FULL_EXTERNAL_PIN_UTIL, - temp_cluster_pr); + temp_cluster_pr, + temp_noc_grp_id); success = (pack_result == e_block_pack_status::BLK_PASSED); } diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index 3e6e83dec27..4de3de53e3a 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -213,7 +213,8 @@ e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placeme bool enable_pin_feasibility_filter, int feasible_block_array_size, t_ext_pin_util max_external_pin_util, - PartitionRegion& temp_cluster_pr); + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id); void try_fill_cluster(const t_packer_opts& packer_opts, t_cluster_placement_stats* cur_cluster_placement_stats_ptr, @@ -237,6 +238,7 @@ void try_fill_cluster(const t_packer_opts& packer_opts, t_lb_router_data* router_data, t_ext_pin_util target_ext_pin_util, PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id, e_block_pack_status& block_pack_status, t_molecule_link* unclustered_list_head, const int& unclustered_list_head_size, @@ -284,6 +286,10 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update); +bool atom_cluster_noc_group_check(AtomBlockId blk_id, + int verbosity, + NocGroupId& temp_cluster_noc_grp_id); + void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data); void update_connection_gain_values(const AtomNetId net_id, const AtomBlockId clustered_blk_id, t_pb* cur_pb, enum e_net_relation_to_clustered_block net_relation_to_clustered_block); @@ -341,7 +347,8 @@ void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats, bool enable_pin_feasibility_filter, bool balance_block_type_utilization, const int feasible_block_array_size, - PartitionRegion& temp_cluster_pr); + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_noc_grp_id); t_pack_molecule* get_highest_gain_molecule(t_pb* cur_pb, AttractionInfo& attraction_groups, diff --git a/vpr/src/pack/noc_aware_cluster_util.cpp b/vpr/src/pack/noc_aware_cluster_util.cpp index 0689b848446..8fa1293e0fc 100644 --- a/vpr/src/pack/noc_aware_cluster_util.cpp +++ b/vpr/src/pack/noc_aware_cluster_util.cpp @@ -26,10 +26,9 @@ std::vector find_noc_router_atoms() { void update_noc_reachability_partitions(const std::vector& noc_atoms) { const auto& atom_ctx = g_vpr_ctx.atom(); - auto& constraints = g_vpr_ctx.mutable_floorplanning().constraints; + auto& cl_helper_ctx = g_vpr_ctx.mutable_cl_helper(); const auto& high_fanout_thresholds = g_vpr_ctx.cl_helper().high_fanout_thresholds; - const auto& device_ctx = g_vpr_ctx.device(); - const auto& grid = device_ctx.grid; + const auto& grid = g_vpr_ctx.device().grid; t_logical_block_type_ptr logic_block_type = infer_logic_block_type(grid); const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logic_block_type->name); @@ -39,15 +38,9 @@ void update_noc_reachability_partitions(const std::vector& noc_atom vtr::vector atom_visited(n_atoms, false); - int exclusivity_cnt = 0; + cl_helper_ctx.atom_noc_grp_id.resize(n_atoms, NocGroupId::INVALID()); - RegionRectCoord unconstrained_rect{0, - 0, - std::numeric_limits::max(), - std::numeric_limits::max(), - 0}; - Region unconstrained_region; - unconstrained_region.set_region_rect(unconstrained_rect); + int noc_grp_id_cnt = 0; for (auto noc_atom_id : noc_atoms) { // check if this NoC router has already been visited @@ -55,28 +48,9 @@ void update_noc_reachability_partitions(const std::vector& noc_atom continue; } - exclusivity_cnt++; + auto noc_grp_id = (NocGroupId)noc_grp_id_cnt; + noc_grp_id_cnt++; - PartitionRegion associated_noc_partition_region; - associated_noc_partition_region.set_exclusivity_index(exclusivity_cnt); - associated_noc_partition_region.add_to_part_region(unconstrained_region); - - Partition associated_noc_partition; - associated_noc_partition.set_name(atom_ctx.nlist.block_name(noc_atom_id)); - associated_noc_partition.set_part_region(associated_noc_partition_region); - auto associated_noc_partition_id = (PartitionId)constraints.get_num_partitions(); - constraints.add_partition(associated_noc_partition); - - const PartitionId noc_partition_id = constraints.get_atom_partition(noc_atom_id); - - if (noc_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(noc_atom_id, associated_noc_partition_id); - } else { // noc atom is already in a partition - auto& noc_partition = constraints.get_mutable_partition(noc_partition_id); - auto& noc_partition_region = noc_partition.get_mutable_part_region(); - VTR_ASSERT(noc_partition_region.get_exclusivity_index() < 0); - noc_partition_region.set_exclusivity_index(exclusivity_cnt); - } std::queue q; q.push(noc_atom_id); @@ -86,15 +60,7 @@ void update_noc_reachability_partitions(const std::vector& noc_atom AtomBlockId current_atom = q.front(); q.pop(); - PartitionId atom_partition_id = constraints.get_atom_partition(current_atom); - if (atom_partition_id == PartitionId::INVALID()) { - constraints.add_constrained_atom(current_atom, associated_noc_partition_id); - } else { - auto& atom_partition = constraints.get_mutable_partition(atom_partition_id); - auto& atom_partition_region = atom_partition.get_mutable_part_region(); - VTR_ASSERT(atom_partition_region.get_exclusivity_index() < 0 || current_atom == noc_atom_id); - atom_partition_region.set_exclusivity_index(exclusivity_cnt); - } + cl_helper_ctx.atom_noc_grp_id[current_atom] = noc_grp_id; for(auto pin : atom_ctx.nlist.block_pins(current_atom)) { AtomNetId net_id = atom_ctx.nlist.pin_net(pin); diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 46883d72d2c..e3c49554627 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -272,21 +272,6 @@ bool try_pack(t_packer_opts* packer_opts, //check clustering and output it check_and_output_clustering(*packer_opts, is_clock, arch, helper_ctx.total_clb_num, clustering_data.intra_lb_routing); - - g_vpr_ctx.mutable_floorplanning().constraints = constraints_backup; - const int max_y = (int)g_vpr_ctx.device().grid.height(); - const int max_x = (int)g_vpr_ctx.device().grid.width(); - for (auto& cluster_partition_region : g_vpr_ctx.mutable_floorplanning().cluster_constraints) { - const auto& regions = cluster_partition_region.get_regions(); - if (regions.size() == 1) { - const auto rect = regions[0].get_region_rect(); - - if (rect.xmin <= 0 && rect.ymin <= 0 && rect.xmax >= max_x && rect.ymax >= max_y) { - cluster_partition_region = PartitionRegion(); - } - } - } - // Free Data Structures free_clustering_data(*packer_opts, clustering_data); diff --git a/vpr/src/pack/re_cluster.cpp b/vpr/src/pack/re_cluster.cpp index 34e0ada9669..8ef8bcd3133 100644 --- a/vpr/src/pack/re_cluster.cpp +++ b/vpr/src/pack/re_cluster.cpp @@ -16,6 +16,7 @@ bool move_mol_to_new_cluster(t_pack_molecule* molecule, ClusterBlockId old_clb = atom_to_cluster(molecule->atom_block_ids[molecule->root]); int molecule_size = get_array_size_of_molecule(molecule); + NocGroupId temp_noc_grp_id = NocGroupId::INVALID(); PartitionRegion temp_cluster_pr; t_lb_router_data* old_router_data = nullptr; t_lb_router_data* router_data = nullptr; @@ -66,7 +67,8 @@ bool move_mol_to_new_cluster(t_pack_molecule* molecule, verbosity, clustering_data, &router_data, - temp_cluster_pr); + temp_cluster_pr, + temp_noc_grp_id); //Commit or revert the move if (is_created) { diff --git a/vpr/src/pack/re_cluster_util.cpp b/vpr/src/pack/re_cluster_util.cpp index 5e1c2f7e142..53f8098a18d 100644 --- a/vpr/src/pack/re_cluster_util.cpp +++ b/vpr/src/pack/re_cluster_util.cpp @@ -8,6 +8,7 @@ #include "initial_placement.h" #include "read_netlist.h" + //The name suffix of the new block (if exists) const char* name_suffix = "_m"; @@ -122,7 +123,8 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, int verbosity, t_clustering_data& clustering_data, t_lb_router_data** router_data, - PartitionRegion& temp_cluster_pr) { + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_cluster_noc_grp_id) { auto& atom_ctx = g_vpr_ctx.atom(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); @@ -162,7 +164,8 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, enable_pin_feasibility_filter, 0, FULL_EXTERNAL_PIN_UTIL, - temp_cluster_pr); + temp_cluster_pr, + temp_cluster_noc_grp_id); // If clustering succeeds, add it to the clb netlist if (pack_result == e_block_pack_status::BLK_PASSED) { @@ -206,6 +209,7 @@ bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + NocGroupId temp_cluster_noc_grp_id; PartitionRegion temp_cluster_pr; e_block_pack_status pack_result = e_block_pack_status::BLK_STATUS_UNDEFINED; t_ext_pin_util target_ext_pin_util = helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(new_clb)->name); @@ -235,7 +239,8 @@ bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, //false, helper_ctx.feasible_block_array_size, target_ext_pin_util, - temp_cluster_pr); + temp_cluster_pr, + temp_cluster_noc_grp_id); // If clustering succeeds, add it to the clb netlist if (pack_result == e_block_pack_status::BLK_PASSED) { @@ -282,6 +287,7 @@ void revert_mol_move(const ClusterBlockId& old_clb, auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + NocGroupId temp_cluster_noc_grp_id_original; PartitionRegion temp_cluster_pr_original; e_block_pack_status pack_result = try_pack_molecule(&(helper_ctx.cluster_placement_stats[cluster_ctx.clb_nlist.block_type(old_clb)->index]), molecule, @@ -296,7 +302,8 @@ void revert_mol_move(const ClusterBlockId& old_clb, helper_ctx.enable_pin_feasibility_filter, helper_ctx.feasible_block_array_size, helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(old_clb)->name), - temp_cluster_pr_original); + temp_cluster_pr_original, + temp_cluster_noc_grp_id_original); VTR_ASSERT(pack_result == e_block_pack_status::BLK_PASSED); //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. diff --git a/vpr/src/pack/re_cluster_util.h b/vpr/src/pack/re_cluster_util.h index 201321f741a..66e24614b2f 100644 --- a/vpr/src/pack/re_cluster_util.h +++ b/vpr/src/pack/re_cluster_util.h @@ -87,7 +87,8 @@ bool start_new_cluster_for_mol(t_pack_molecule* molecule, int verbosity, t_clustering_data& clustering_data, t_lb_router_data** router_data, - PartitionRegion& temp_cluster_pr); + PartitionRegion& temp_cluster_pr, + NocGroupId& temp_cluster_noc_grp_id); /** * @brief A function that packs a molecule into an existing cluster From 00269050827401720e0a63a35172ad83202785fa Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Sun, 28 Apr 2024 21:03:06 -0400 Subject: [PATCH 31/37] remove exclusivity_index from PartitionRegion --- vpr/src/base/partition_region.cpp | 44 +++++-------------------------- vpr/src/base/partition_region.h | 5 ---- 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 77afc4fa5e7..14961efc919 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -36,22 +36,6 @@ bool PartitionRegion::is_loc_in_part_reg(const t_pl_loc& loc) const { return is_in_pr; } -int PartitionRegion::get_exclusivity_index() const { - return exclusivity_index; -} - -void PartitionRegion::set_exclusivity_index(int index) { - /* negative exclusivity index means this PartitionRegion is compatible - * with other PartitionsRegions as long as the intersection of their - * regions is not empty. - */ - if (index < 0) { - index = -1; - } - - exclusivity_index = index; -} - PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { /**for N regions in part_region and M in the calling object you can get anywhere from * 0 to M*N regions in the resulting vector. Only intersection regions with non-zero area rectangles and @@ -59,15 +43,6 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR * Rectangles are not merged even if it would be possible */ PartitionRegion pr; - - const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); - const int new_exclusivity = new_pr.get_exclusivity_index(); - - // PartitionRegion are not compatible even if their regions overlap - if (cluster_exclusivity != new_exclusivity) { - return pr; - } - auto& pr_regions = pr.get_mutable_regions(); for (const auto& cluster_region : cluster_pr.get_regions()) { @@ -85,19 +60,12 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { std::vector int_regions; - const int cluster_exclusivity = cluster_pr.get_exclusivity_index(); - const int new_exclusivity = new_pr.get_exclusivity_index(); - - // check whether PartitionRegions are compatible in the first place - if (cluster_exclusivity == new_exclusivity) { - - // now that we know PartitionRegions are compatible, look for overlapping regions - for (const auto& cluster_region : cluster_pr.get_regions()) { - for (const auto& new_region : new_pr.get_regions()) { - Region intersect_region = intersection(cluster_region, new_region); - if (!intersect_region.empty()) { - int_regions.push_back(intersect_region); - } + // now that we know PartitionRegions are compatible, look for overlapping regions + for (const auto& cluster_region : cluster_pr.get_regions()) { + for (const auto& new_region : new_pr.get_regions()) { + Region intersect_region = intersection(cluster_region, new_region); + if (!intersect_region.empty()) { + int_regions.push_back(intersect_region); } } } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index ec4d24a065f..db73d2d7f09 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -50,13 +50,8 @@ class PartitionRegion { */ bool is_loc_in_part_reg(const t_pl_loc& loc) const; - int get_exclusivity_index() const; - - void set_exclusivity_index(int index); - private: std::vector regions; ///< union of rectangular regions that a partition can be placed in - int exclusivity_index = -1; ///< PartitionRegions with different exclusivity_index values are not compatible }; ///@brief used to print data from a PartitionRegion From ecb08bff121681e94ebec25c8fcdf84ef4f06f99 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 29 Apr 2024 15:15:57 -0400 Subject: [PATCH 32/37] fix segfault when logic block type can't be inferred --- vpr/src/base/vpr_types.cpp | 4 ++-- vpr/src/base/vpr_types.h | 9 +++++---- vpr/src/pack/cluster_util.cpp | 1 - vpr/src/pack/noc_aware_cluster_util.cpp | 3 ++- vpr/src/pack/pack.cpp | 1 - 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vpr/src/base/vpr_types.cpp b/vpr/src/base/vpr_types.cpp index ed3fc40f9d0..475a9a30d19 100644 --- a/vpr/src/base/vpr_types.cpp +++ b/vpr/src/base/vpr_types.cpp @@ -123,7 +123,7 @@ t_ext_pin_util_targets& t_ext_pin_util_targets::operator=(t_ext_pin_util_targets return *this; } -t_ext_pin_util t_ext_pin_util_targets::get_pin_util(const std::string& block_type_name) const { +t_ext_pin_util t_ext_pin_util_targets::get_pin_util(std::string_view block_type_name) const { auto itr = overrides_.find(block_type_name); if (itr != overrides_.end()) { return itr->second; @@ -248,7 +248,7 @@ void t_pack_high_fanout_thresholds::set(const std::string& block_type_name, int overrides_[block_type_name] = threshold; } -int t_pack_high_fanout_thresholds::get_threshold(const std::string& block_type_name) const { +int t_pack_high_fanout_thresholds::get_threshold(std::string_view block_type_name) const { auto itr = overrides_.find(block_type_name); if (itr != overrides_.end()) { return itr->second; diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 3fd9f95ad11..5333a9d3ae3 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "arch_types.h" #include "atom_netlist_fwd.h" #include "clustered_netlist_fwd.h" @@ -196,7 +197,7 @@ class t_ext_pin_util_targets { t_ext_pin_util_targets& operator=(t_ext_pin_util_targets&& other) noexcept; ///@brief Returns the input pin util of the specified block (or default if unspecified) - t_ext_pin_util get_pin_util(const std::string& block_type_name) const; + t_ext_pin_util get_pin_util(std::string_view block_type_name) const; ///@brief Returns a string describing input/output pin utilization targets std::string to_string() const; @@ -216,7 +217,7 @@ class t_ext_pin_util_targets { private: t_ext_pin_util defaults_; - std::map overrides_; + std::map> overrides_; }; class t_pack_high_fanout_thresholds { @@ -227,7 +228,7 @@ class t_pack_high_fanout_thresholds { t_pack_high_fanout_thresholds& operator=(t_pack_high_fanout_thresholds&& other) noexcept; ///@brief Returns the high fanout threshold of the specifi ed block - int get_threshold(const std::string& block_type_name) const; + int get_threshold(std::string_view block_type_name) const; ///@brief Returns a string describing high fanout thresholds for different block types std::string to_string() const; @@ -247,7 +248,7 @@ class t_pack_high_fanout_thresholds { private: int default_; - std::map overrides_; + std::map> overrides_; }; /* these are defined later, but need to declare here because it is used */ diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 9be8810af07..c80950ae4e6 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -1382,7 +1382,6 @@ bool atom_cluster_noc_group_check(AtomBlockId blk_id, NocGroupId& temp_cluster_noc_grp_id) { const NocGroupId atom_noc_grp_id = g_vpr_ctx.cl_helper().atom_noc_grp_id[blk_id]; - if (temp_cluster_noc_grp_id == NocGroupId::INVALID()) { // the cluster does not have a NoC group // assign the atom's NoC group to cluster diff --git a/vpr/src/pack/noc_aware_cluster_util.cpp b/vpr/src/pack/noc_aware_cluster_util.cpp index 8fa1293e0fc..d09b6ec3d91 100644 --- a/vpr/src/pack/noc_aware_cluster_util.cpp +++ b/vpr/src/pack/noc_aware_cluster_util.cpp @@ -31,7 +31,8 @@ void update_noc_reachability_partitions(const std::vector& noc_atom const auto& grid = g_vpr_ctx.device().grid; t_logical_block_type_ptr logic_block_type = infer_logic_block_type(grid); - const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logic_block_type->name); + const char* logical_block_name = logic_block_type != nullptr ? logic_block_type->name : ""; + const size_t high_fanout_threshold = high_fanout_thresholds.get_threshold(logical_block_name); // get the total number of atoms const size_t n_atoms = atom_ctx.nlist.blocks().size(); diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index e3c49554627..041d48eb879 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -126,7 +126,6 @@ bool try_pack(t_packer_opts* packer_opts, int pack_iteration = 1; bool floorplan_regions_overfull = false; - auto constraints_backup = g_vpr_ctx.floorplanning().constraints; // find all NoC router atoms auto noc_atoms = find_noc_router_atoms(); update_noc_reachability_partitions(noc_atoms); From 9bfa10f82cb962b752f2e4c4faab28b1a2590135 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 29 Apr 2024 15:52:40 -0400 Subject: [PATCH 33/37] fix atom_cluster_floorplanning_check returning wrong value --- vpr/src/pack/cluster_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index c80950ae4e6..2da69305294 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -1372,7 +1372,7 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d, cluster PR was updated with intersection result \n", blk_id, clb_index); } - return false; + return true; } } } From d5aef9ab1716be5440c0375e1a1bc725c0140e39 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Mon, 29 Apr 2024 16:04:48 -0400 Subject: [PATCH 34/37] add log messages for atom_cluster_noc_group_check() --- vpr/src/pack/cluster_util.cpp | 41 +++++++++++++++---------- vpr/src/pack/cluster_util.h | 1 + vpr/src/pack/noc_aware_cluster_util.cpp | 1 - vpr/src/util/vpr_utils.cpp | 9 ++---- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index 2da69305294..c1983197209 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -994,7 +994,8 @@ e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placeme for (int i_mol = 0; i_mol < molecule_size; i_mol++) { if (molecule->atom_block_ids[i_mol]) { bool block_pack_noc_grp_status = atom_cluster_noc_group_check(molecule->atom_block_ids[i_mol], - verbosity, temp_noc_grp_id); + clb_index, verbosity, + temp_noc_grp_id); if (!block_pack_noc_grp_status) { //Record the failure of this molecule in the current pb stats @@ -1111,9 +1112,7 @@ e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placeme //update cluster PartitionRegion if atom with floorplanning constraints was added if (cluster_pr_update_check) { floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; - if (verbosity > 2) { - VTR_LOG("\nUpdated PartitionRegion of cluster %d\n", clb_index); - } + VTR_LOGV(verbosity > 2, "\nUpdated PartitionRegion of cluster %d\n", clb_index); } for (int i = 0; i < molecule_size; i++) { @@ -1333,9 +1332,9 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, //if the atom does not belong to a partition, it can be put in the cluster //regardless of what the cluster's PartitionRegion is because it has no constraints if (partid == PartitionId::INVALID()) { - if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d has no floorplanning constraints, passed for cluster %d \n", blk_id, clb_index); - } + VTR_LOGV(verbosity > 3, + "\t\t\t Intersect: Atom block %d has no floorplanning constraints, passed for cluster %d \n", + blk_id, clb_index); cluster_pr_needs_update = false; return true; } else { @@ -1348,9 +1347,9 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, if (cluster_pr.empty()) { temp_cluster_pr = atom_pr; cluster_pr_needs_update = true; - if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d has floorplanning constraints, passed cluster %d which has empty PR\n", blk_id, clb_index); - } + VTR_LOGV(verbosity > 3, + "\t\t\t Intersect: Atom block %d has floorplanning constraints, passed cluster %d which has empty PR\n", + blk_id, clb_index); return true; } else { //update cluster_pr with the intersection of the cluster's PartitionRegion @@ -1360,24 +1359,25 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, // At this point, cluster_pr is the intersection of atom_pr and the clusters current pr if (cluster_pr.empty()) { - if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); - } + VTR_LOGV(verbosity > 3, + "\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", + blk_id, clb_index); cluster_pr_needs_update = false; return false; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion temp_cluster_pr = cluster_pr; cluster_pr_needs_update = true; - if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d, cluster PR was updated with intersection result \n", blk_id, clb_index); - } + VTR_LOGV(verbosity > 3, + "\t\t\t Intersect: Atom block %d passed cluster %d, cluster PR was updated with intersection result \n", + blk_id, clb_index); return true; } } } bool atom_cluster_noc_group_check(AtomBlockId blk_id, + ClusterBlockId clb_index, int verbosity, NocGroupId& temp_cluster_noc_grp_id) { const NocGroupId atom_noc_grp_id = g_vpr_ctx.cl_helper().atom_noc_grp_id[blk_id]; @@ -1385,15 +1385,24 @@ bool atom_cluster_noc_group_check(AtomBlockId blk_id, if (temp_cluster_noc_grp_id == NocGroupId::INVALID()) { // the cluster does not have a NoC group // assign the atom's NoC group to cluster + VTR_LOGV(verbosity > 3, + "\t\t\t NoC Group: Atom block %d passed cluster %d, cluster's NoC group was updated with the atom's group %d\n", + blk_id, clb_index, (size_t)atom_noc_grp_id); temp_cluster_noc_grp_id = atom_noc_grp_id; return true; } else if (temp_cluster_noc_grp_id == atom_noc_grp_id) { // the cluster has the same NoC group ID as the atom, // so they are compatible + VTR_LOGV(verbosity > 3, + "\t\t\t NoC Group: Atom block %d passed cluster %d, cluster's NoC group was compatible with the atom's group %d\n", + blk_id, clb_index, (size_t)atom_noc_grp_id); return true; } else { // the cluster belongs to a different NoC group than the atom's group, // so they are incompatible + VTR_LOGV(verbosity > 3, + "\t\t\t NoC Group: Atom block %d failed NoC group check for cluster %d. Cluster's NoC group: %d, atom's NoC group: %d\n", + blk_id, clb_index, (size_t)temp_cluster_noc_grp_id, size_t(atom_noc_grp_id)); return false; } } diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index 4de3de53e3a..22bcb709b44 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -287,6 +287,7 @@ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, bool& cluster_pr_needs_update); bool atom_cluster_noc_group_check(AtomBlockId blk_id, + ClusterBlockId clb_index, int verbosity, NocGroupId& temp_cluster_noc_grp_id); diff --git a/vpr/src/pack/noc_aware_cluster_util.cpp b/vpr/src/pack/noc_aware_cluster_util.cpp index d09b6ec3d91..4fe47c1c570 100644 --- a/vpr/src/pack/noc_aware_cluster_util.cpp +++ b/vpr/src/pack/noc_aware_cluster_util.cpp @@ -52,7 +52,6 @@ void update_noc_reachability_partitions(const std::vector& noc_atom auto noc_grp_id = (NocGroupId)noc_grp_id_cnt; noc_grp_id_cnt++; - std::queue q; q.push(noc_atom_id); atom_visited[noc_atom_id] = true; diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index db422bea509..77a4dd700ea 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -1,14 +1,12 @@ -#include #include #include #include #include -#include +#include #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_memory.h" -#include "vtr_random.h" #include "vpr_types.h" #include "vpr_error.h" @@ -17,10 +15,7 @@ #include "globals.h" #include "vpr_utils.h" #include "cluster_placement.h" -#include "place_macro.h" -#include "pack_types.h" #include "device_grid.h" -#include "timing_fail_error.h" #include "re_cluster_util.h" /* This module contains subroutines that are used in several unrelated parts * @@ -28,7 +23,7 @@ /* This defines the maximum string length that could be parsed by functions * * in vpr_utils. */ -#define MAX_STRING_LEN 128 +static constexpr size_t MAX_STRING_LEN = 128; /******************** File-scope variables declarations **********************/ From 023ba474605d2fb76b5da2647c8a7d65161c2dcd Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Tue, 14 May 2024 16:20:45 -0400 Subject: [PATCH 35/37] add comments --- vpr/src/pack/cluster_util.h | 34 ++++++++++++++++++++++++- vpr/src/place/centroid_move_generator.h | 31 +++++++++++++++++++++- vpr/src/place/directed_moves_util.h | 20 +++++++++++---- vpr/src/place/move_utils.cpp | 11 ++++---- vpr/src/place/move_utils.h | 13 ++++++---- vpr/src/util/vpr_utils.cpp | 2 +- 6 files changed, 93 insertions(+), 18 deletions(-) diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index 22bcb709b44..910bb69c932 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -280,12 +280,44 @@ enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_grap int verbosity, const int feasible_block_array_size); + +/** + * @brief Checks whether an atom block can be added to a clustered block + * without violating floorplanning constraints. It also updates the + * clustered block's floorplanning region by taking the intersection of + * its current region and the floorplanning region of the given atom block. + * + * @param blk_id A unique ID for the candidate atom block to be added to the growing cluster. + * @param clb_index A unique ID for the clustered block that the atom block wants to be added to. + * @param verbosity Controls the detail level of log information printed by this function. + * @param temp_cluster_pr The floorplanning regions of the clustered block. This function may + * update the given region. + * @param cluster_pr_needs_update Indicates whether the floorplanning region of the clustered block + * have updated. + * @return True if adding the given atom block to the clustered block does not violated any + * floorplanning constraints. + */ bool atom_cluster_floorplanning_check(AtomBlockId blk_id, ClusterBlockId clb_index, int verbosity, PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update); - +/** + * @brief Checks if an atom block can be added to a clustered block without + * violating NoC group constraints. For passing this check, either both clustered + * and atom blocks must belong to the same NoC group, or at least one of them should + * not belong to any NoC group. If the atom block is associated with a NoC group while + * the clustered block does not belong to any NoC groups, the NoC group ID of the atom block + * is assigned to the clustered block when the atom is added to it. + * block + * + * @param blk_id A unique ID for the candidate atom block to be added to the growing cluster. + * @param clb_index A unique ID for the clustered block that the atom block wants to be added to. + * @param verbosity Controls the detail level of log information printed by this function. + * @param temp_cluster_noc_grp_id The NoC group ID of the clustered block. This function may update + * this ID. + * @return True if adding the atom block the cluster does not violate NoC group constraints. + */ bool atom_cluster_noc_group_check(AtomBlockId blk_id, ClusterBlockId clb_index, int verbosity, diff --git a/vpr/src/place/centroid_move_generator.h b/vpr/src/place/centroid_move_generator.h index b10fb29c286..2dc95033e35 100644 --- a/vpr/src/place/centroid_move_generator.h +++ b/vpr/src/place/centroid_move_generator.h @@ -20,12 +20,41 @@ */ class CentroidMoveGenerator : public MoveGenerator { public: + /** + * The move generator created by calling this constructor only consider + * netlist connectivity for computing the centroid location. + */ CentroidMoveGenerator(); + + /** + * The move generator created by calling this constructor considers both + * netlist connectivity and NoC reachability for computing the centroid. + * The constructor also forms NoC groups by finding connected components + * in the graph representing the clustered netlist. When finding connected + * components, none of the nets whose fanout is larger than high_fanout_net + * are traversed. + * @param noc_attraction_weight Specifies how much the computed centroid + * is adjusted towards the location of NoC routers in the same NoC group as + * the clustered block to be moved. + * @param high_fanout_net All nets with a fanout larger than this number are + * ignored when forming NoC groups. + */ CentroidMoveGenerator(float noc_attraction_weight, size_t high_fanout_net); + /** + * Returns all NoC routers that are in the NoC group with a given ID. + * @param noc_grp_id The NoC group ID whose NoC routers are requested. + * @return The clustered block ID of all NoC routers in the given NoC group. + */ static const std::vector& get_noc_group_routers(NocGroupId noc_grp_id); + /** + * Returns the NoC group ID of clustered block. + * @param blk_id The clustered block whose NoC group ID is requested. + * @return The NoC group ID of the given clustered block or INVALID if + * the given clustered block does not belong to any NoC groups. + */ static NocGroupId get_cluster_noc_group(ClusterBlockId blk_id); private: @@ -43,7 +72,7 @@ class CentroidMoveGenerator : public MoveGenerator { /** Indicates whether the centroid calculation is NoC-biased.*/ bool noc_attraction_enabled_; - /** Stores all non-router blocks for each NoC group*/ + /** Stores the ids of all non-router clustered blocks for each NoC group*/ static vtr::vector> noc_group_clusters_; /** Stores NoC routers in each NoC group*/ diff --git a/vpr/src/place/directed_moves_util.h b/vpr/src/place/directed_moves_util.h index fdb941226ee..dc2f07c4643 100644 --- a/vpr/src/place/directed_moves_util.h +++ b/vpr/src/place/directed_moves_util.h @@ -25,11 +25,21 @@ void get_coordinate_of_pin(ClusterPinId pin, t_physical_tile_loc& tile_loc); * This function is very useful in centroid and weightedCentroid moves as it calculates * the centroid location. It returns the calculated location in centroid. * - * @param b_from: The block Id of the moving block - * @param timing_weights: Determines whether to calculate centroid or weighted centroid location. If true, use the timing weights (weighted centroid) - * @param criticalities: A pointer to the placer criticalities which is used when calculating weighted centroid (send a NULL pointer in case of centroid) + * When NoC attraction is enabled, the computed centroid is slightly adjusted towards the location + * of NoC routers that are in the same NoC group b_from. + * + * @param b_from The block Id of the moving block + * @param timing_weights Determines whether to calculate centroid or + * weighted centroid location. If true, use the timing weights (weighted centroid). + * @param criticalities A pointer to the placer criticalities which is used when + * calculating weighted centroid (send a NULL pointer in case of centroid) + * @param noc_attraction_enabled Indicates whether the computed centroid location + * should be adjusted towards NoC routers in the NoC group of the given block. + * @param noc_attraction_weight When NoC attraction is enabled, this weight + * specifies to which extent the computed centroid should be adjusted. A value + * in range [0, 1] is expected. * - * @return The calculated location is returned in centroid parameter that is sent by reference + * @return The calculated location is returned in centroid parameter that is sent by reference */ void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, @@ -42,7 +52,7 @@ inline void calculate_centroid_loc(ClusterBlockId b_from, bool timing_weights, t_pl_loc& centroid, const PlacerCriticalities* criticalities) { - calculate_centroid_loc(b_from, timing_weights,centroid, criticalities,false, 0.0f); + calculate_centroid_loc(b_from, timing_weights, centroid, criticalities, false, 0.0f); } #endif diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 07f3c35a838..2266b942469 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -254,13 +254,13 @@ e_block_move_result record_macro_macro_swaps(t_pl_blocks_to_be_moved& blocks_aff //Continue walking along the overlapping parts of the from and to macros, recording //each block swap. // - //At the momemnt we only support swapping the two macros if they have the same shape. + //At the moment we only support swapping the two macros if they have the same shape. //This will be the case with the common cases we care about (i.e. carry-chains), so //we just abort in any other cases (if these types of macros become more common in //the future this could be updated). // - //Unless the two macros have thier root blocks aligned (i.e. the mutual overlap starts - //at imember_from == 0), then theree will be a fixed offset between the macros' relative + //Unless the two macros have their root blocks aligned (i.e. the mutual overlap starts + //at imember_from == 0), then there will be a fixed offset between the macros' relative //position. We record this as from_to_macro_*_offset which is used to verify the shape //of the macros is consistent. // @@ -1036,7 +1036,8 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, to_loc = t_pl_loc(grid_loc.x, grid_loc.y, sub_tile, grid_loc.layer_num); } -int has_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physical_tile_loc& to_loc) { +int find_empty_compatible_subtile(t_logical_block_type_ptr type, + const t_physical_tile_loc& to_loc) { auto& device_ctx = g_vpr_ctx.device(); auto& place_ctx = g_vpr_ctx.placement(); @@ -1148,7 +1149,7 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, if (from_loc.x == to_loc.x && from_loc.y == to_loc.y && from_loc.layer_num == to_layer_num) { continue; //Same from/to location -- try again for new y-position } else if (search_for_empty) { // Check if the location has at least one empty sub-tile - legal = has_empty_compatible_subtile(type, to_loc) >= 0; + legal = find_empty_compatible_subtile(type, to_loc) >= 0; } else { legal = true; } diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index c22c3cec7a6..7c13d225f22 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -225,16 +225,19 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, t_pl_loc& to_loc); /** - * @brief Checks whether the given location has a compatible empty subtile with - * the given type. + * @brief Tries to find an compatible empty subtile with the given type at + * the given location. If such a subtile could be found, the subtile number + * is returned. Otherwise, -1 is returned to indicate that there are no + * compatible subtiles at the given location. * * @param type logical block type * @param to_loc The location to be checked * - * @return bool True if the given location has at least one empty compatible subtile. + * @return int The subtile number if there is an empty compatible subtile, otherwise -1 + * is returned to indicate that there are no empty subtiles compatible with the given type.. */ -int has_empty_compatible_subtile(t_logical_block_type_ptr type, - const t_physical_tile_loc& to_loc); +int find_empty_compatible_subtile(t_logical_block_type_ptr type, + const t_physical_tile_loc& to_loc); /** * @brief find compressed location in a compressed range for a specific type in the given layer (to_layer_num) diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 77a4dd700ea..9e7b4f12435 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -23,7 +23,7 @@ /* This defines the maximum string length that could be parsed by functions * * in vpr_utils. */ -static constexpr size_t MAX_STRING_LEN = 128; +static constexpr size_t MAX_STRING_LEN = 512; /******************** File-scope variables declarations **********************/ From 1f2ac0b8e0beb8b3aeebbd2a37dfd1f076f67c29 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Tue, 14 May 2024 16:33:41 -0400 Subject: [PATCH 36/37] avoid creating std::string every time log_move_abort is called --- vpr/src/draw/manual_moves.cpp | 2 +- vpr/src/place/move_utils.cpp | 11 ++++++++--- vpr/src/place/move_utils.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/vpr/src/draw/manual_moves.cpp b/vpr/src/draw/manual_moves.cpp index 77551dbe505..3d907550396 100644 --- a/vpr/src/draw/manual_moves.cpp +++ b/vpr/src/draw/manual_moves.cpp @@ -212,7 +212,7 @@ void manual_move_cost_summary_dialog() { gtk_window_set_transient_for((GtkWindow*)dialog, (GtkWindow*)draw_state->manual_moves_state.manual_move_window); //Create elements for the dialog and printing costs to the user. - GtkWidget* title_label = gtk_label_new(NULL); + GtkWidget* title_label = gtk_label_new(nullptr); gtk_label_set_markup((GtkLabel*)title_label, "Move Costs and Outcomes"); std::string delta_cost = "Delta Cost: " + std::to_string(draw_state->manual_moves_state.manual_move_info.delta_cost) + " "; GtkWidget* delta_cost_label = gtk_label_new(delta_cost.c_str()); diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 2266b942469..431f05014dc 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -16,10 +16,15 @@ bool f_placer_breakpoint_reached = false; //Records counts of reasons for aborted moves -static std::map f_move_abort_reasons; +static std::map> f_move_abort_reasons; -void log_move_abort(const std::string& reason) { - ++f_move_abort_reasons[reason]; +void log_move_abort(std::string_view reason) { + auto it = f_move_abort_reasons.find(reason); + if (it != f_move_abort_reasons.end()) { + it->second++; + } else { + f_move_abort_reasons.emplace(reason, 1); + } } void report_aborted_moves() { diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index 7c13d225f22..965dc55f53d 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -86,7 +86,7 @@ struct t_range_limiters { }; //Records a reasons for an aborted move -void log_move_abort(const std::string& reason); +void log_move_abort(std::string_view reason); //Prints a breif report about aborted move reasons and counts void report_aborted_moves(); From 80dcdeb75f872a375f4bc33093c9f2a0e35cc2ba Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 22 May 2024 19:24:58 -0400 Subject: [PATCH 37/37] add comments and subroutines --- vpr/src/base/vpr_context.h | 3 + vpr/src/base/vpr_types.h | 2 +- vpr/src/noc/noc_data_types.h | 1 + vpr/src/pack/cluster.cpp | 9 +- vpr/src/pack/noc_aware_cluster_util.cpp | 8 ++ vpr/src/pack/noc_aware_cluster_util.h | 31 ++++- vpr/src/place/centroid_move_generator.cpp | 145 +++++++++++----------- vpr/src/place/centroid_move_generator.h | 10 ++ 8 files changed, 135 insertions(+), 74 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index e36f48323d2..453b0c8bac1 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -353,6 +353,9 @@ struct ClusteringHelperContext : public Context { // unordered_set for faster insertion/deletion during the iterative improvement process of packing vtr::vector> atoms_lookup; + /** Stores the NoC group ID of each atom block. Atom blocks that belong + * to different NoC groups can't be clustered with each other into the + * same clustered block.*/ vtr::vector atom_noc_grp_id; ~ClusteringHelperContext() { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index f4343577a11..7f289171c69 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1501,7 +1501,7 @@ struct t_noc_opts { double noc_latency_constraints_weighting; /// NocTrafficFlowId; +/** Data type to index NoC groups. */ struct noc_group_id_tag; typedef vtr::StrongId NocGroupId; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 10026b22aa3..47b277f2872 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -19,7 +19,7 @@ * t_pb: * Represents a clustered instance of a t_pb_graph_node containing netlist primitives * - * t_pb_type and t_pb_graph_node (and related types) describe the targetted FPGA architecture, while t_pb represents + * t_pb_type and t_pb_graph_node (and related types) describe the targeted FPGA architecture, while t_pb represents * the actual clustering of the user netlist. * * For example: @@ -82,7 +82,7 @@ * cluster until a nullptr is returned. So, the number of repeated molecules is changed from 1 to 500, * effectively making the clusterer pack a cluster until a nullptr is returned. */ -#define ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES 500 +static constexpr int ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES = 500; std::map do_clustering(const t_packer_opts& packer_opts, const t_analysis_opts& analysis_opts, @@ -243,6 +243,11 @@ std::map do_clustering(const t_packer_opts& pa * Since some of the primitives might fail legality, this structure temporarily * stores PartitionRegion information while the cluster is packed*/ PartitionRegion temp_cluster_pr; + /* + * Stores the cluster's NoC group ID as more primitives are added to it. + * This is used to check if a candidate primitive is in the same NoC group + * as the atom blocks that have already been added to the primitive. + */ NocGroupId temp_cluster_noc_grp_id = NocGroupId::INVALID(); start_new_cluster(helper_ctx.cluster_placement_stats, helper_ctx.primitives_list, diff --git a/vpr/src/pack/noc_aware_cluster_util.cpp b/vpr/src/pack/noc_aware_cluster_util.cpp index 4fe47c1c570..51319175c12 100644 --- a/vpr/src/pack/noc_aware_cluster_util.cpp +++ b/vpr/src/pack/noc_aware_cluster_util.cpp @@ -43,6 +43,14 @@ void update_noc_reachability_partitions(const std::vector& noc_atom int noc_grp_id_cnt = 0; + /* + * Assume that the atom netlist is represented as an undirected graph + * with all high fanout nets removed. In this graph, we want to find all + * connected components that include at least one NoC router. We start a + * BFS from each NoC router and traverse all nets below the high_fanout_threshold, + * and mark each atom block with a NoC group ID. + */ + for (auto noc_atom_id : noc_atoms) { // check if this NoC router has already been visited if (atom_visited[noc_atom_id]) { diff --git a/vpr/src/pack/noc_aware_cluster_util.h b/vpr/src/pack/noc_aware_cluster_util.h index 0b2f092bca9..abeb8d8ba95 100644 --- a/vpr/src/pack/noc_aware_cluster_util.h +++ b/vpr/src/pack/noc_aware_cluster_util.h @@ -1,13 +1,42 @@ - #ifndef VTR_NOC_AWARE_CLUSTER_UTIL_H #define VTR_NOC_AWARE_CLUSTER_UTIL_H +/** + * @file This file includes helper functions used to find NoC groups + * in the atom netlist and assign NoC group IDs to atom blocks. + * + * A NoC group is a set of atom blocks that are reachable from a NoC router + * through low fanout nets. During packing, atom blocks that belong to two different + * NoC group IDs cannot be packed with each other into the same clustered block. + * This prevents atom blocks that belong to two separate NoC-attached modules from + * being packed with each other, and helps with more localized placement of NoC-attached + * modules around their corresponding NoC routers. + * + * For more details refer to the following paper: + * The Road Less Traveled: Congestion-Aware NoC Placement and Packet Routing for FPGAs + */ + #include #include "vpr_types.h" +/** + * @brief Iterates over all atom blocks and check whether + * their blif model is the same as a NoC routers. + * + * @return The atom block IDs of the NoC router blocks in the netlist. + */ std::vector find_noc_router_atoms(); + +/** + * @brief Runs BFS starting from NoC routers to find all connected + * components that include a NoC router. Each connected component + * containing a NoC router is marked as a NoC group. The NoC group ID + * for each atom block is updated in the global state. + * + * @param noc_atoms The atom block IDs of the NoC router blocks in the netlist. + */ void update_noc_reachability_partitions(const std::vector& noc_atoms); #endif diff --git a/vpr/src/place/centroid_move_generator.cpp b/vpr/src/place/centroid_move_generator.cpp index e4e44c1d64c..b10d93a661f 100644 --- a/vpr/src/place/centroid_move_generator.cpp +++ b/vpr/src/place/centroid_move_generator.cpp @@ -24,15 +24,88 @@ CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight, size_t , noc_attraction_enabled_(true) { VTR_ASSERT(noc_attraction_weight > 0.0 && noc_attraction_weight <= 1.0); - const auto& cluster_ctx = g_vpr_ctx.clustering(); - const auto& noc_ctx = g_vpr_ctx.noc(); // check if static member variables are already initialized if (!noc_group_clusters_.empty() && !noc_group_routers_.empty() && !cluster_to_noc_grp_.empty() && !noc_router_to_noc_group_.empty()) { return; + } else { + initialize_noc_groups(high_fanout_net); + } +} + +e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, + t_propose_action& proposed_action, + float rlim, + const t_placer_opts& placer_opts, + const PlacerCriticalities* /*criticalities*/) { + // Find a movable block based on blk_type + ClusterBlockId b_from = propose_block_to_move(placer_opts, + proposed_action.logical_blk_type_index, + false, + nullptr, + nullptr); + + VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, + "Centroid Move Choose Block %d - rlim %f\n", + size_t(b_from), + rlim); + + if (!b_from) { //No movable block found + VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, + "\tNo movable block found\n"); + return e_create_move::ABORT; } + const auto& device_ctx = g_vpr_ctx.device(); + const auto& place_ctx = g_vpr_ctx.placement(); + const auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& place_move_ctx = g_placer_ctx.mutable_move(); + + t_pl_loc from = place_ctx.block_locs[b_from].loc; + auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from); + auto grid_from_type = device_ctx.grid.get_physical_type({from.x, from.y, from.layer}); + VTR_ASSERT(is_tile_compatible(grid_from_type, cluster_from_type)); + + t_range_limiters range_limiters{rlim, + place_move_ctx.first_rlim, + placer_opts.place_dm_rlim}; + + t_pl_loc to, centroid; + + /* Calculate the centroid location*/ + calculate_centroid_loc(b_from, false, centroid, nullptr, noc_attraction_enabled_, noc_attraction_w_); + + // Centroid location is not necessarily a valid location, and the downstream location expect a valid + // layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc. + to.layer = (centroid.layer < 0) ? from.layer : centroid.layer; + /* Find a location near the weighted centroid_loc */ + if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) { + return e_create_move::ABORT; + } + + e_create_move create_move = ::create_move(blocks_affected, b_from, to); + + //Check that all the blocks affected by the move would still be in a legal floorplan region after the swap + if (!floorplan_legal(blocks_affected)) { + return e_create_move::ABORT; + } + + return create_move; +} + +const std::vector& CentroidMoveGenerator::get_noc_group_routers(NocGroupId noc_grp_id) { + return CentroidMoveGenerator::noc_group_routers_[noc_grp_id]; +} + +NocGroupId CentroidMoveGenerator::get_cluster_noc_group(ClusterBlockId blk_id) { + return CentroidMoveGenerator::cluster_to_noc_grp_[blk_id]; +} + +void CentroidMoveGenerator::initialize_noc_groups(size_t high_fanout_net) { + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& noc_ctx = g_vpr_ctx.noc(); + noc_group_clusters_.clear(); noc_group_routers_.clear(); cluster_to_noc_grp_.clear(); @@ -127,71 +200,3 @@ CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight, size_t } } } - -e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, - t_propose_action& proposed_action, - float rlim, - const t_placer_opts& placer_opts, - const PlacerCriticalities* /*criticalities*/) { - // Find a movable block based on blk_type - ClusterBlockId b_from = propose_block_to_move(placer_opts, - proposed_action.logical_blk_type_index, - false, - nullptr, - nullptr); - - VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, - "Centroid Move Choose Block %d - rlim %f\n", - size_t(b_from), - rlim); - - if (!b_from) { //No movable block found - VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, - "\tNo movable block found\n"); - return e_create_move::ABORT; - } - - const auto& device_ctx = g_vpr_ctx.device(); - const auto& place_ctx = g_vpr_ctx.placement(); - const auto& cluster_ctx = g_vpr_ctx.clustering(); - auto& place_move_ctx = g_placer_ctx.mutable_move(); - - t_pl_loc from = place_ctx.block_locs[b_from].loc; - auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from); - auto grid_from_type = device_ctx.grid.get_physical_type({from.x, from.y, from.layer}); - VTR_ASSERT(is_tile_compatible(grid_from_type, cluster_from_type)); - - t_range_limiters range_limiters{rlim, - place_move_ctx.first_rlim, - placer_opts.place_dm_rlim}; - - t_pl_loc to, centroid; - - /* Calculate the centroid location*/ - calculate_centroid_loc(b_from, false, centroid, nullptr, noc_attraction_enabled_, noc_attraction_w_); - - // Centroid location is not necessarily a valid location, and the downstream location expect a valid - // layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc. - to.layer = (centroid.layer < 0) ? from.layer : centroid.layer; - /* Find a location near the weighted centroid_loc */ - if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) { - return e_create_move::ABORT; - } - - e_create_move create_move = ::create_move(blocks_affected, b_from, to); - - //Check that all the blocks affected by the move would still be in a legal floorplan region after the swap - if (!floorplan_legal(blocks_affected)) { - return e_create_move::ABORT; - } - - return create_move; -} - -const std::vector& CentroidMoveGenerator::get_noc_group_routers(NocGroupId noc_grp_id) { - return CentroidMoveGenerator::noc_group_routers_[noc_grp_id]; -} - -NocGroupId CentroidMoveGenerator::get_cluster_noc_group(ClusterBlockId blk_id) { - return CentroidMoveGenerator::cluster_to_noc_grp_[blk_id]; -} diff --git a/vpr/src/place/centroid_move_generator.h b/vpr/src/place/centroid_move_generator.h index 2dc95033e35..2a0b99234c5 100644 --- a/vpr/src/place/centroid_move_generator.h +++ b/vpr/src/place/centroid_move_generator.h @@ -87,6 +87,16 @@ class CentroidMoveGenerator : public MoveGenerator { /** Specifies the NoC group for each NoC router*/ static std::map noc_router_to_noc_group_; + + /** + * @brief This function forms NoC groups by finding connected components + * in the graph representing the clustered netlist. When finding connected + * components, none of the nets whose fanout is larger than high_fanout_net + * are traversed. + * @param high_fanout_net All nets with a fanout larger than this number are + * ignored when forming NoC groups. + */ + static void initialize_noc_groups(size_t high_fanout_net); }; #endif