From 918219f2b9cacc4f52a8f55cd6eb64be4c871a0b Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 16 Dec 2020 14:26:01 -0500 Subject: [PATCH 01/25] Added a vpr floorplanning constraints context --- vpr/src/base/vpr_constraints.cpp | 8 ++++++++ vpr/src/base/vpr_constraints.h | 18 ++++++++++++++++++ vpr/src/base/vpr_constraints_reader.cpp | 12 +++++++++--- vpr/src/base/vpr_constraints_serializer.h | 3 +++ vpr/src/base/vpr_context.h | 16 ++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 87fdf0211e1..4baaccea72b 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -47,3 +47,11 @@ std::vector VprConstraints::get_part_atoms(PartitionId part_id) { return part_atoms; } + +int VprConstraints::get_num_partitions() { + return num_partitions; +} + +void VprConstraints::set_num_partitions(int num_parts) { + num_partitions = num_parts; +} diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 8a60122c165..79773feffb0 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -60,6 +60,18 @@ class VprConstraints { */ std::vector get_part_atoms(PartitionId part_id); + /** + * @brief Returns the number of partitions in the object + */ + int get_num_partitions(); + + /** + * @brief Sets the number of partitions in the object + * + * @param num_parts The number of partitions in the partitions vector + */ + void set_num_partitions(int num_parts); + private: /** * Store all constrained atoms @@ -70,6 +82,12 @@ class VprConstraints { * Store all partitions */ vtr::vector partitions; + + /** + * Store number of partitions - the number of partitions in the partitions vector. + * Used when echoing VprConstraints objects. + */ + int num_partitions; }; #endif /* VPR_CONSTRAINTS_H */ diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index 1b5f2e985fd..a2704f2846b 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -31,10 +31,16 @@ void load_vpr_constraints_file(const char* read_vpr_constraints_name) { read_vpr_constraints_name); } - VprConstraints constraints = reader.constraints_; - int num_parts = reader.num_partitions_; + //VprConstraints constraints = reader.constraints_; + //int num_parts = reader.num_partitions_; + + //Update the floorplanning constraints in the floorplanning constraints context + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + floorplanning_ctx.constraints = reader.constraints_; + + VprConstraints ctx_constraints = floorplanning_ctx.constraints; if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_VPR_CONSTRAINTS)) { - echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), constraints, num_parts); + echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), ctx_constraints, ctx_constraints.get_num_partitions()); } } diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index c87449f4db7..644a2c95028 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -295,6 +295,9 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase Date: Mon, 18 Jan 2021 13:46:19 -0500 Subject: [PATCH 02/25] Wrote code to set the PartitionRegion of the new cluster in start_new_cluster --- vpr/src/base/vpr_constraints.cpp | 6 ++++++ vpr/src/base/vpr_constraints.h | 9 ++++++++- vpr/src/base/vpr_context.h | 2 +- vpr/src/pack/cluster.cpp | 22 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 4baaccea72b..9dd71b45120 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -55,3 +55,9 @@ int VprConstraints::get_num_partitions() { void VprConstraints::set_num_partitions(int num_parts) { num_partitions = num_parts; } + +PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { + PartitionRegion pr; + pr = partitions[part_id].get_part_region(); + return pr; +} diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 79773feffb0..940856fcd84 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -33,7 +33,7 @@ class VprConstraints { /** * @brief Return id of the partition the atom belongs to * - * If an atom is not in a partition (unconstrained), PartitionId::Invalid() is returned. + * If an atom is not in a partition (unconstrained), PartitionId::INVALID() is returned. * * @param blk_id The atom for which the partition id is needed */ @@ -72,6 +72,13 @@ class VprConstraints { */ void set_num_partitions(int num_parts); + /** + * @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); + private: /** * Store all constrained atoms diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 92d5265ba99..d4bbc5aaf6d 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -377,8 +377,8 @@ struct RoutingContext : public Context { * to certain regions on the chip. */ struct FloorplanningContext : public Context { - ///@brief Atom netlist VprConstraints constraints; + std::unordered_map clb_constraints; }; /** diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index de4487212f0..fa3d7f38fa1 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -70,6 +70,8 @@ #include "tatum/report/graphviz_dot_writer.hpp" #include "tatum/TimingReporter.hpp" +#include "constraints_load.h" + #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 */ @@ -2065,6 +2067,26 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto block_type = clb_nlist->block_type(clb_index); num_used_type_instances[block_type]++; + /*Access the constraints info from context*/ + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + + VprConstraints ctx_constraints = floorplanning_ctx.constraints; + + /*determine whether seed atom belongs to a partition*/ + PartitionId partid; + partid = ctx_constraints.get_atom_partition(root_atom); + + /*if the seed atom does not belong to a partition, it is unconstrained, so the cluster will have an empty PartitionRegion + *if there is a constraint,set cluster PartitionRegion to same in the vector map of the clusters in the constraints context + */ + if (partid == PartitionId::INVALID()) { + PartitionRegion empty_pr; + floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); + } else { + PartitionRegion pr = ctx_constraints.get_partition_pr(partid); + floorplanning_ctx.clb_constraints.insert({clb_index, pr}); + } + /* Expand FPGA size if needed */ // Check used type instances against the possible equivalent physical locations unsigned int num_instances = 0; From ca7b577588cca18b76a55f1b7b992330b4d53fcb Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 20 Jan 2021 19:34:25 -0500 Subject: [PATCH 03/25] Added code to check for an empty PartitionRegion and code to check intersections in the clusterer --- vpr/src/base/partition_region.cpp | 8 +++++ vpr/src/base/partition_region.h | 5 +++ vpr/src/base/vpr_types.h | 1 + vpr/src/pack/cluster.cpp | 55 +++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index d40b9ee8e58..45277ef82df 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -8,6 +8,14 @@ std::vector PartitionRegion::get_partition_region() { return partition_region; } +bool PartitionRegion::empty() { + if (partition_region.size() == 0) { + return true; + } else { + return false; + } +} + PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { /**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 diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 97e352efe8e..020cd3b8fda 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -24,6 +24,11 @@ class PartitionRegion { */ std::vector get_partition_region(); + /** + * @brief Check if the PartitionRegion is empty (ie. holds no regions in its vector) + */ + bool empty(); + /** * @brief Global friend function that returns the intersection of two PartitionRegions * diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index e9e1f63d25f..ddfc6678585 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -164,6 +164,7 @@ enum e_block_pack_status { BLK_PASSED, BLK_FAILED_FEASIBLE, BLK_FAILED_ROUTE, + BLK_FAILED_FLOORPLANNING, BLK_STATUS_UNDEFINED }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index fa3d7f38fa1..f1bf14219cc 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -218,6 +218,10 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* int verbosity, const int feasible_block_array_size); +static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, + const ClusterBlockId clb_index, + int verbosity); + static void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data, const std::multimap& atom_molecules); static 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); @@ -635,6 +639,9 @@ std::map do_clustering(const t_packer_opts& pa next_molecule->pack_pattern->name, next_molecule->atom_block_ids.size()); VTR_LOG("\n"); fflush(stdout); + } else if (block_pack_status == BLK_FAILED_FLOORPLANNING){ + VTR_LOG("\tFloorplanning constraints not met: '%s' (%s)", blk_name.c_str(), blk_model->name); + VTR_LOG("\n"); } else { VTR_LOG("\tFAILED_FEASIBILITY_CHECK: '%s' (%s)", blk_name.c_str(), blk_model->name, block_pack_status); VTR_LOGV(next_molecule->pack_pattern, " molecule %s molecule_size %zu", @@ -1200,6 +1207,7 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu t_ext_pin_util max_external_pin_util) { int molecule_size, failed_location; int i; + int j; enum e_block_pack_status block_pack_status; t_pb* parent; t_pb* cur_pb; @@ -1252,6 +1260,17 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu verbosity, feasible_block_array_size); } } + + //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion + /*for(j = 0; j < molecule_size && block_pack_status == BLK_PASSED; j++) { + //VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); + //failed_location = i + 1; + //try to intersect with atom PartitionRegion if atom exists + if (molecule->atom_block_ids[j]) { + block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); + } + }*/ + if (enable_pin_feasibility_filter && block_pack_status == BLK_PASSED) { /* Check if pin usage is feasible for the current packing assignment */ reset_lookahead_pins_used(pb); @@ -1505,6 +1524,42 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* return block_pack_status; } +/*try and see if floorplanning constraints match*/ +static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, + const ClusterBlockId clb_index, + int verbosity) { + + auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); + VprConstraints ctx_constraints = floorplanning_ctx.constraints; + + /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ + + //get partition that atom belongs to + PartitionId partid; + partid = ctx_constraints.get_atom_partition(blk_id); + + //get pr of that partition + PartitionRegion atom_pr; + atom_pr = ctx_constraints.get_partition_pr(partid); + + //intersect it with the pr of the current cluster + PartitionRegion cluster_pr; + auto got = floorplanning_ctx.clb_constraints.find(clb_index); + cluster_pr = got->second; + PartitionRegion intersect_pr; + intersect_pr = intersection(atom_pr, cluster_pr); + + if (intersect_pr.empty() == true){ + return BLK_FAILED_FLOORPLANNING; + if (verbosity > 3){ + VTR_LOG("\t\t\tAtom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); + } + } + else { + return BLK_PASSED; + } +} + /* Revert trial atom block iblock and free up memory space accordingly */ static void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data, const std::multimap& atom_molecules) { From ed6e7a88465daa36f2822f66cf9a1756ecdd2f5d Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Thu, 21 Jan 2021 10:07:01 -0500 Subject: [PATCH 04/25] Modified function for intersecting atom and cluster PartitionRegions --- vpr/src/pack/cluster.cpp | 68 ++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index f1bf14219cc..c0c66d70cca 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1243,6 +1243,21 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu return BLK_FAILED_FEASIBLE; } + //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion + for (j = 0; j < molecule_size; j++) { + //try to intersect with atom PartitionRegion if atom exists + if (molecule->atom_block_ids[j]) { + VTR_LOG("\t\t\t Testing outside for loop, molecule size is %d \n", molecule_size); + block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); + } + if (block_pack_status == BLK_FAILED_FLOORPLANNING) { + return block_pack_status; + } + } + + //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; + while (block_pack_status != BLK_PASSED) { if (get_next_primitive_list(cluster_placement_stats_ptr, molecule, primitives_list)) { @@ -1253,6 +1268,7 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu failed_location = i + 1; // try place atom block if it exists if (molecule->atom_block_ids[i]) { + //VTR_LOG("\t\t\t Inner for loop, molecule size is %d, i is %d \n", molecule_size, i); block_pack_status = try_place_atom_block_rec(primitives_list[i], molecule->atom_block_ids[i], pb, &parent, max_models, max_cluster_size, clb_index, @@ -1262,11 +1278,12 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu } //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion - /*for(j = 0; j < molecule_size && block_pack_status == BLK_PASSED; j++) { + /*for (j = 0; j < molecule_size && block_pack_status == BLK_PASSED; j++) { //VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); //failed_location = i + 1; //try to intersect with atom PartitionRegion if atom exists if (molecule->atom_block_ids[j]) { + VTR_LOG("\t\t\t In the second for loop in try_pack_molecule, j is %d \n", j); block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); } }*/ @@ -1529,7 +1546,7 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl const ClusterBlockId clb_index, int verbosity) { - auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); VprConstraints ctx_constraints = floorplanning_ctx.constraints; /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ @@ -1538,26 +1555,43 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl PartitionId partid; partid = ctx_constraints.get_atom_partition(blk_id); - //get pr of that partition PartitionRegion atom_pr; - atom_pr = ctx_constraints.get_partition_pr(partid); - - //intersect it with the pr of the current cluster PartitionRegion cluster_pr; - auto got = floorplanning_ctx.clb_constraints.find(clb_index); - cluster_pr = got->second; PartitionRegion intersect_pr; - intersect_pr = intersection(atom_pr, cluster_pr); - if (intersect_pr.empty() == true){ - return BLK_FAILED_FLOORPLANNING; - if (verbosity > 3){ - VTR_LOG("\t\t\tAtom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); - } - } - else { + //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()) { return BLK_PASSED; - } + } else { + + //get pr of that partition + atom_pr = ctx_constraints.get_partition_pr(partid); + + //intersect it with the pr of the current cluster + auto got = floorplanning_ctx.clb_constraints.find(clb_index); + //cluster_pr = got->second; + + if (got == floorplanning_ctx.clb_constraints.end()) { + VTR_LOG("\t\t\t Did not find PR of cluster"); + } else { + cluster_pr = got->second; + intersect_pr = intersection(atom_pr, cluster_pr); + } + + + if (intersect_pr.empty() == true){ + if (verbosity > 3){ + VTR_LOG("\t\t\tAtom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); + } + return BLK_FAILED_FLOORPLANNING; + } + else { + //update the cluster's PartitionRegion + got->second = intersect_pr; + return BLK_PASSED; + } + } } /* Revert trial atom block iblock and free up memory space accordingly From 532a143ccf1bbab0ab78958e73d28a240e1a5fc4 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 25 Jan 2021 18:05:42 -0500 Subject: [PATCH 05/25] Fixed bug where cluster PartitionRegion was not updated soon enough in start_new_cluster --- vpr/src/pack/cluster.cpp | 61 ++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index c0c66d70cca..f6e5d497fb0 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1247,12 +1247,15 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu for (j = 0; j < molecule_size; j++) { //try to intersect with atom PartitionRegion if atom exists if (molecule->atom_block_ids[j]) { - VTR_LOG("\t\t\t Testing outside for loop, molecule size is %d \n", molecule_size); block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); + + if (block_pack_status == BLK_FAILED_FLOORPLANNING) { + VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); + return block_pack_status; + } else if (block_pack_status == BLK_PASSED) { + VTR_LOG("\t\t\t From intersect: block passed \n"); + } } - if (block_pack_status == BLK_FAILED_FLOORPLANNING) { - return block_pack_status; - } } //change status back to undefined before the while loop in case in was changed to BLK_PASSED in the above for loop @@ -1562,6 +1565,9 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl //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 passed cluster %d \n", blk_id, clb_index); + } return BLK_PASSED; } else { @@ -1576,19 +1582,35 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl VTR_LOG("\t\t\t Did not find PR of cluster"); } else { cluster_pr = got->second; - intersect_pr = intersection(atom_pr, cluster_pr); + //intersect_pr = intersection(atom_pr, cluster_pr); } + if (cluster_pr.empty() == true) { + //what if the atom passes here but then doesn't pass somewhere else + //the cluster PR will have been updated for no reason + //probably better to have another function at the end of the try_pack_molecule function that + //takes care of updating cluster PR + got->second = atom_pr; + if (verbosity > 3){ + VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + } + return BLK_PASSED; + } else { + intersect_pr = intersection(cluster_pr, atom_pr); + } if (intersect_pr.empty() == true){ if (verbosity > 3){ - VTR_LOG("\t\t\tAtom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); + VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); } return BLK_FAILED_FLOORPLANNING; } else { //update the cluster's PartitionRegion got->second = intersect_pr; + if (verbosity > 3){ + VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + } return BLK_PASSED; } } @@ -2039,6 +2061,19 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto& atom_ctx = g_vpr_ctx.atom(); auto& device_ctx = g_vpr_ctx.mutable_device(); + /* + * Get floorplanning information + */ + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + + VprConstraints ctx_constraints = floorplanning_ctx.constraints; + + /* + * Set an empty PR for the cluster + */ + PartitionRegion empty_pr; + floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); + /* Allocate a dummy initial cluster and load a atom block as a seed and check if it is legal */ AtomBlockId root_atom = molecule->atom_block_ids[molecule->root]; const std::string& root_atom_name = atom_ctx.nlist.block_name(root_atom); @@ -2156,11 +2191,6 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto block_type = clb_nlist->block_type(clb_index); num_used_type_instances[block_type]++; - /*Access the constraints info from context*/ - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - - VprConstraints ctx_constraints = floorplanning_ctx.constraints; - /*determine whether seed atom belongs to a partition*/ PartitionId partid; partid = ctx_constraints.get_atom_partition(root_atom); @@ -2168,12 +2198,19 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats /*if the seed atom does not belong to a partition, it is unconstrained, so the cluster will have an empty PartitionRegion *if there is a constraint,set cluster PartitionRegion to same in the vector map of the clusters in the constraints context */ - if (partid == PartitionId::INVALID()) { + /*if (partid == PartitionId::INVALID()) { PartitionRegion empty_pr; floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); } else { PartitionRegion pr = ctx_constraints.get_partition_pr(partid); floorplanning_ctx.clb_constraints.insert({clb_index, pr}); + }*/ + + //if seed atom belongs to a partition, update cluster_pr + if (partid != PartitionId::INVALID()) { + PartitionRegion pr = ctx_constraints.get_partition_pr(partid); + floorplanning_ctx.clb_constraints[clb_index] = pr; + VTR_LOG("Cluster's partition region was updated to match seed atom\n"); } /* Expand FPGA size if needed */ From 511a9941e36430e6c02147bc90a173fafe383853 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Tue, 26 Jan 2021 12:59:32 -0500 Subject: [PATCH 06/25] Ran make format --- vpr/src/base/partition_region.cpp | 10 +- vpr/src/base/vpr_constraints.cpp | 6 +- vpr/src/base/vpr_types.h | 2 +- vpr/src/pack/cluster.cpp | 213 +++++++++++++++--------------- 4 files changed, 114 insertions(+), 117 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 45277ef82df..0ca8c510be3 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -9,11 +9,11 @@ std::vector PartitionRegion::get_partition_region() { } bool PartitionRegion::empty() { - if (partition_region.size() == 0) { - return true; - } else { - return false; - } + if (partition_region.size() == 0) { + return true; + } else { + return false; + } } PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 9dd71b45120..4a60428ccb2 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -57,7 +57,7 @@ void VprConstraints::set_num_partitions(int num_parts) { } PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { - PartitionRegion pr; - pr = partitions[part_id].get_part_region(); - return pr; + PartitionRegion pr; + pr = partitions[part_id].get_part_region(); + return pr; } diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index ddfc6678585..966cc00e126 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -164,7 +164,7 @@ enum e_block_pack_status { BLK_PASSED, BLK_FAILED_FEASIBLE, BLK_FAILED_ROUTE, - BLK_FAILED_FLOORPLANNING, + BLK_FAILED_FLOORPLANNING, BLK_STATUS_UNDEFINED }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index f6e5d497fb0..f8221276d09 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -219,8 +219,8 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* const int feasible_block_array_size); static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - int verbosity); + const ClusterBlockId clb_index, + int verbosity); static void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data, const std::multimap& atom_molecules); @@ -639,9 +639,9 @@ std::map do_clustering(const t_packer_opts& pa next_molecule->pack_pattern->name, next_molecule->atom_block_ids.size()); VTR_LOG("\n"); fflush(stdout); - } else if (block_pack_status == BLK_FAILED_FLOORPLANNING){ - VTR_LOG("\tFloorplanning constraints not met: '%s' (%s)", blk_name.c_str(), blk_model->name); - VTR_LOG("\n"); + } else if (block_pack_status == BLK_FAILED_FLOORPLANNING) { + VTR_LOG("\tFloorplanning constraints not met: '%s' (%s)", blk_name.c_str(), blk_model->name); + VTR_LOG("\n"); } else { VTR_LOG("\tFAILED_FEASIBILITY_CHECK: '%s' (%s)", blk_name.c_str(), blk_model->name, block_pack_status); VTR_LOGV(next_molecule->pack_pattern, " molecule %s molecule_size %zu", @@ -1245,17 +1245,17 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion for (j = 0; j < molecule_size; j++) { - //try to intersect with atom PartitionRegion if atom exists - if (molecule->atom_block_ids[j]) { - block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); + //try to intersect with atom PartitionRegion if atom exists + if (molecule->atom_block_ids[j]) { + block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); if (block_pack_status == BLK_FAILED_FLOORPLANNING) { - VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); - return block_pack_status; + VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); + return block_pack_status; } else if (block_pack_status == BLK_PASSED) { - VTR_LOG("\t\t\t From intersect: block passed \n"); + VTR_LOG("\t\t\t From intersect: block passed \n"); } - } + } } //change status back to undefined before the while loop in case in was changed to BLK_PASSED in the above for loop @@ -1271,7 +1271,7 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu failed_location = i + 1; // try place atom block if it exists if (molecule->atom_block_ids[i]) { - //VTR_LOG("\t\t\t Inner for loop, molecule size is %d, i is %d \n", molecule_size, i); + //VTR_LOG("\t\t\t Inner for loop, molecule size is %d, i is %d \n", molecule_size, i); block_pack_status = try_place_atom_block_rec(primitives_list[i], molecule->atom_block_ids[i], pb, &parent, max_models, max_cluster_size, clb_index, @@ -1282,14 +1282,14 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion /*for (j = 0; j < molecule_size && block_pack_status == BLK_PASSED; j++) { - //VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); - //failed_location = i + 1; - //try to intersect with atom PartitionRegion if atom exists - if (molecule->atom_block_ids[j]) { - VTR_LOG("\t\t\t In the second for loop in try_pack_molecule, j is %d \n", j); - block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); - } - }*/ + * //VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); + * //failed_location = i + 1; + * //try to intersect with atom PartitionRegion if atom exists + * if (molecule->atom_block_ids[j]) { + * VTR_LOG("\t\t\t In the second for loop in try_pack_molecule, j is %d \n", j); + * block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); + * } + * }*/ if (enable_pin_feasibility_filter && block_pack_status == BLK_PASSED) { /* Check if pin usage is feasible for the current packing assignment */ @@ -1546,73 +1546,70 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* /*try and see if floorplanning constraints match*/ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - int verbosity) { - - auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - VprConstraints ctx_constraints = floorplanning_ctx.constraints; - - /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ - - //get partition that atom belongs to - PartitionId partid; - partid = ctx_constraints.get_atom_partition(blk_id); - - PartitionRegion atom_pr; - PartitionRegion cluster_pr; - PartitionRegion intersect_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()) { - if (verbosity > 3){ - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); - } - return BLK_PASSED; - } else { - - //get pr of that partition - atom_pr = ctx_constraints.get_partition_pr(partid); - - //intersect it with the pr of the current cluster - auto got = floorplanning_ctx.clb_constraints.find(clb_index); - //cluster_pr = got->second; - - if (got == floorplanning_ctx.clb_constraints.end()) { - VTR_LOG("\t\t\t Did not find PR of cluster"); - } else { - cluster_pr = got->second; - //intersect_pr = intersection(atom_pr, cluster_pr); - } - - if (cluster_pr.empty() == true) { - //what if the atom passes here but then doesn't pass somewhere else - //the cluster PR will have been updated for no reason - //probably better to have another function at the end of the try_pack_molecule function that - //takes care of updating cluster PR - got->second = atom_pr; - if (verbosity > 3){ - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); - } - return BLK_PASSED; - } else { - intersect_pr = intersection(cluster_pr, atom_pr); - } - - if (intersect_pr.empty() == true){ - if (verbosity > 3){ - VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); - } - return BLK_FAILED_FLOORPLANNING; - } - else { - //update the cluster's PartitionRegion - got->second = intersect_pr; - if (verbosity > 3){ - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); - } - return BLK_PASSED; - } + const ClusterBlockId clb_index, + int verbosity) { + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + VprConstraints ctx_constraints = floorplanning_ctx.constraints; + + /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ + + //get partition that atom belongs to + PartitionId partid; + partid = ctx_constraints.get_atom_partition(blk_id); + + PartitionRegion atom_pr; + PartitionRegion cluster_pr; + PartitionRegion intersect_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()) { + if (verbosity > 3) { + VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + } + return BLK_PASSED; + } else { + //get pr of that partition + atom_pr = ctx_constraints.get_partition_pr(partid); + + //intersect it with the pr of the current cluster + auto got = floorplanning_ctx.clb_constraints.find(clb_index); + //cluster_pr = got->second; + + if (got == floorplanning_ctx.clb_constraints.end()) { + VTR_LOG("\t\t\t Did not find PR of cluster"); + } else { + cluster_pr = got->second; + //intersect_pr = intersection(atom_pr, cluster_pr); + } + + if (cluster_pr.empty() == true) { + //what if the atom passes here but then doesn't pass somewhere else + //the cluster PR will have been updated for no reason + //probably better to have another function at the end of the try_pack_molecule function that + //takes care of updating cluster PR + got->second = atom_pr; + if (verbosity > 3) { + VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + } + return BLK_PASSED; + } else { + intersect_pr = intersection(cluster_pr, atom_pr); + } + + if (intersect_pr.empty() == true) { + if (verbosity > 3) { + VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); + } + return BLK_FAILED_FLOORPLANNING; + } else { + //update the cluster's PartitionRegion + got->second = intersect_pr; + if (verbosity > 3) { + VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + } + return BLK_PASSED; + } } } @@ -2192,26 +2189,26 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats num_used_type_instances[block_type]++; /*determine whether seed atom belongs to a partition*/ - PartitionId partid; - partid = ctx_constraints.get_atom_partition(root_atom); - - /*if the seed atom does not belong to a partition, it is unconstrained, so the cluster will have an empty PartitionRegion - *if there is a constraint,set cluster PartitionRegion to same in the vector map of the clusters in the constraints context - */ - /*if (partid == PartitionId::INVALID()) { - PartitionRegion empty_pr; - floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); - } else { - PartitionRegion pr = ctx_constraints.get_partition_pr(partid); - floorplanning_ctx.clb_constraints.insert({clb_index, pr}); - }*/ - - //if seed atom belongs to a partition, update cluster_pr - if (partid != PartitionId::INVALID()) { - PartitionRegion pr = ctx_constraints.get_partition_pr(partid); - floorplanning_ctx.clb_constraints[clb_index] = pr; - VTR_LOG("Cluster's partition region was updated to match seed atom\n"); - } + PartitionId partid; + partid = ctx_constraints.get_atom_partition(root_atom); + + /*if the seed atom does not belong to a partition, it is unconstrained, so the cluster will have an empty PartitionRegion + *if there is a constraint,set cluster PartitionRegion to same in the vector map of the clusters in the constraints context + */ + /*if (partid == PartitionId::INVALID()) { + * PartitionRegion empty_pr; + * floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); + * } else { + * PartitionRegion pr = ctx_constraints.get_partition_pr(partid); + * floorplanning_ctx.clb_constraints.insert({clb_index, pr}); + * }*/ + + //if seed atom belongs to a partition, update cluster_pr + if (partid != PartitionId::INVALID()) { + PartitionRegion pr = ctx_constraints.get_partition_pr(partid); + floorplanning_ctx.clb_constraints[clb_index] = pr; + VTR_LOG("Cluster's partition region was updated to match seed atom\n"); + } /* Expand FPGA size if needed */ // Check used type instances against the possible equivalent physical locations From 8008b2e75053e55b565d6e280ce57df27ff9c32f Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Tue, 26 Jan 2021 23:57:40 -0500 Subject: [PATCH 07/25] Added function to echo cluster contents --- vpr/src/base/echo_files.cpp | 3 +++ vpr/src/base/echo_files.h | 3 +++ vpr/src/pack/cluster.cpp | 51 ++++++++++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/vpr/src/base/echo_files.cpp b/vpr/src/base/echo_files.cpp index b294af97874..b73d8349267 100644 --- a/vpr/src/base/echo_files.cpp +++ b/vpr/src/base/echo_files.cpp @@ -74,6 +74,9 @@ void alloc_and_load_echo_file_info() { //Vpr constraints setEchoFileName(E_ECHO_VPR_CONSTRAINTS, "vpr_constraints.echo"); + //Packing + setEchoFileName(E_ECHO_CLUSTERS, "clusters.echo"); + //Intra-block routing setEchoFileName(E_ECHO_INTRA_LB_FAILED_ROUTE, "intra_lb_failed_route.echo"); diff --git a/vpr/src/base/echo_files.h b/vpr/src/base/echo_files.h index 6c4e548ab76..16739daec0c 100644 --- a/vpr/src/base/echo_files.h +++ b/vpr/src/base/echo_files.h @@ -12,6 +12,9 @@ enum e_echo_files { E_ECHO_PRE_PACKING_MOLECULES_AND_PATTERNS, E_ECHO_VPR_CONSTRAINTS, + //Packing + E_ECHO_CLUSTERS, + // Intra-block routing E_ECHO_INTRA_LB_FAILED_ROUTE, diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index f8221276d09..eaab6f112af 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -311,6 +311,8 @@ static t_pack_molecule* get_molecule_for_cluster(t_pb* cur_pb, static void check_clustering(); +static void echo_clusters(char* filename); + static void check_cluster_atom_blocks(t_pb* pb, std::unordered_set& blocks_checked); static void mark_all_molecules_valid(t_pack_molecule* molecule_head); @@ -771,6 +773,10 @@ std::map do_clustering(const t_packer_opts& pa VTR_ASSERT(num_clb == (int)cluster_ctx.clb_nlist.blocks().size()); check_clustering(); + if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_CLUSTERS)) { + echo_clusters(getEchoFileName(E_ECHO_CLUSTERS)); + } + output_clustering(intra_lb_routing, packer_opts.global_clocks, is_clock, arch->architecture_id, packer_opts.output_file.c_str(), false); VTR_ASSERT(cluster_ctx.clb_nlist.blocks().size() == intra_lb_routing.size()); @@ -1250,11 +1256,11 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); if (block_pack_status == BLK_FAILED_FLOORPLANNING) { - VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); + //VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); return block_pack_status; - } else if (block_pack_status == BLK_PASSED) { - VTR_LOG("\t\t\t From intersect: block passed \n"); - } + } /*else if (block_pack_status == BLK_PASSED) { + * VTR_LOG("\t\t\t From intersect: block passed \n"); + * }*/ } } @@ -2542,6 +2548,43 @@ static void check_clustering() { } } +static void echo_clusters(char* filename) { + FILE* fp; + fp = vtr::fopen(filename, "w"); + + fprintf(fp, "--------------------------------------------------------------\n"); + fprintf(fp, "Clusters\n"); + fprintf(fp, "--------------------------------------------------------------\n"); + fprintf(fp, "\n"); + + auto& atom_ctx = g_vpr_ctx.atom(); + auto& cluster_ctx = g_vpr_ctx.clustering(); + + std::map> cluster_atoms; + + for (auto blk_id : cluster_ctx.clb_nlist.blocks()) { + cluster_atoms.insert({blk_id, std::vector()}); + } + + for (auto atom_blk_id : atom_ctx.nlist.blocks()) { + ClusterBlockId clb_index = atom_ctx.lookup.atom_clb(atom_blk_id); + + cluster_atoms[clb_index].push_back(atom_blk_id); + } + + for (auto i = cluster_atoms.begin(); i != cluster_atoms.end(); i++) { + fprintf(fp, "\tCluster Id: %d \n", i->first); + fprintf(fp, "\tAtoms in cluster: \n"); + + for (auto j = 0; j < i->second.size(); j++) { + AtomBlockId atom_id = i->second[j]; + fprintf(fp, "\t %s \n", atom_ctx.nlist.block_name(atom_id).c_str()); + } + } + + fclose(fp); +} + /* TODO: May want to check that all atom blocks are actually reached */ static void check_cluster_atom_blocks(t_pb* pb, std::unordered_set& blocks_checked) { int i, j; From 5845338a1fe2b70b215a6a7eccb4a23fb4f6b4b5 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 27 Jan 2021 17:06:22 -0500 Subject: [PATCH 08/25] Added routine print_pack_status to print some cluster stats incrementally during clustering --- vpr/src/pack/cluster.cpp | 56 ++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index eaab6f112af..dce781c7906 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -190,6 +190,11 @@ static t_pack_molecule* get_molecule_by_num_ext_inputs(const int ext_inps, static t_pack_molecule* get_free_molecule_with_most_ext_inputs_for_cluster(t_pb* cur_pb, t_cluster_placement_stats* cluster_placement_stats_ptr); +static void print_pack_status(int num_clb, + int tot_num_molecules, + int num_molecules_processed, + std::map clb_types); + static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, const std::multimap& atom_molecules, t_pack_molecule* molecule, @@ -396,7 +401,7 @@ std::map do_clustering(const t_packer_opts& pa *****************************************************************/ VTR_ASSERT(packer_opts.packer_algorithm == PACK_GREEDY); - int num_molecules, blocks_since_last_analysis, num_clb, + int num_molecules, num_molecules_processed, blocks_since_last_analysis, num_clb, num_blocks_hill_added, max_cluster_size, cur_cluster_size, max_pb_depth, cur_pb_depth, num_unrelated_clustering_attempts, seedindex, savedseedindex /* index of next most timing critical block */, @@ -572,11 +577,15 @@ std::map do_clustering(const t_packer_opts& pa balance_block_type_utilization, packer_opts.feasible_block_array_size); - VTR_LOGV(verbosity == 2, - "Complex block %d: '%s' (%s) ", num_clb, - cluster_ctx.clb_nlist.block_name(clb_index).c_str(), - cluster_ctx.clb_nlist.block_type(clb_index)->name); - VTR_LOGV(verbosity == 2, "."); //Progress dot for seed-block + //initial molecule in cluster has been processed + num_molecules_processed++; + + /*VTR_LOGV(verbosity == 2, + * "Complex block %d: '%s' (%s) ", num_clb, + * cluster_ctx.clb_nlist.block_name(clb_index).c_str(), + * cluster_ctx.clb_nlist.block_type(clb_index)->name); + * VTR_LOGV(verbosity == 2, ".");*/ + //Progress dot for seed-block fflush(stdout); t_ext_pin_util target_ext_pin_util = ext_pin_util_targets.get_pin_util(cluster_ctx.clb_nlist.block_type(clb_index)->name); @@ -673,9 +682,12 @@ std::map do_clustering(const t_packer_opts& pa next_molecule->pack_pattern->name, next_molecule->atom_block_ids.size()); VTR_LOG("\n"); } - VTR_LOGV(verbosity == 2, "."); + //VTR_LOGV(verbosity == 2, "."); fflush(stdout); + //Since molecule passed, update num_molecules_processed + num_molecules_processed++; + update_cluster_stats(next_molecule, clb_index, is_clock, //Set of all clocks is_clock, //Set of all global signals (currently clocks) @@ -701,7 +713,7 @@ std::map do_clustering(const t_packer_opts& pa packer_opts.pack_verbosity); } - VTR_LOGV(verbosity == 2, "\n"); + //VTR_LOGV(verbosity == 2, "\n"); if (detailed_routing_stage == (int)E_DETAILED_ROUTE_AT_END_ONLY) { /* is_mode_conflict does not affect this stage. It is needed when trying to route the packed clusters. @@ -745,8 +757,10 @@ std::map do_clustering(const t_packer_opts& pa } } auto cur_pb = cluster_ctx.clb_nlist.block_pb(clb_index); + // update the data structure holding the LE counts update_le_count(cur_pb, logic_block_type, le_pb_type, le_count); + print_pack_status(num_clb, num_molecules, num_molecules_processed, num_used_type_instances); free_pb_stats_recursive(cur_pb); } else { /* Free up data structures and requeue used molecules */ @@ -803,6 +817,22 @@ std::map do_clustering(const t_packer_opts& pa return num_used_type_instances; } +static void print_pack_status(int num_clb, + int tot_num_molecules, + int num_molecules_processed, + std::map clb_types) { + //print an update every 10 clusters + if (num_clb % 10 == 0) { + VTR_LOG("\nCreated %d clusters\n", num_clb); + VTR_LOG("Processed %d out of %d molecules\n", num_molecules_processed, tot_num_molecules); + VTR_LOG("Cluster types:\n"); + + for (auto i = clb_types.begin(); i != clb_types.end(); i++) { + VTR_LOG("\t %s: # blocks %zu \n", i->first->name, size_t(i->second)); + } + } +} + /* Determine if atom block is in pb */ static bool is_atom_blk_in_pb(const AtomBlockId blk_id, const t_pb* pb) { auto& atom_ctx = g_vpr_ctx.atom(); @@ -2213,7 +2243,9 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats if (partid != PartitionId::INVALID()) { PartitionRegion pr = ctx_constraints.get_partition_pr(partid); floorplanning_ctx.clb_constraints[clb_index] = pr; - VTR_LOG("Cluster's partition region was updated to match seed atom\n"); + if (verbosity > 2) { + VTR_LOG("Cluster's partition region was updated to match seed atom\n"); + } } /* Expand FPGA size if needed */ @@ -2573,10 +2605,12 @@ static void echo_clusters(char* filename) { } for (auto i = cluster_atoms.begin(); i != cluster_atoms.end(); i++) { - fprintf(fp, "\tCluster Id: %d \n", i->first); + fprintf(fp, "\tCluster Id: %zu \n", size_t(i->first)); fprintf(fp, "\tAtoms in cluster: \n"); - for (auto j = 0; j < i->second.size(); j++) { + int num_atoms = i->second.size(); + + for (auto j = 0; j < num_atoms; j++) { AtomBlockId atom_id = i->second[j]; fprintf(fp, "\t %s \n", atom_ctx.nlist.block_name(atom_id).c_str()); } From 7b465fe117058d1d0709e990885e8ec768322df9 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 27 Jan 2021 20:18:12 -0500 Subject: [PATCH 09/25] Printed end of clustering stats in table format --- vpr/src/pack/cluster.cpp | 3 +++ vpr/src/pack/output_clustering.cpp | 37 +++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index dce781c7906..4d27e076f06 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -409,6 +409,8 @@ std::map do_clustering(const t_packer_opts& pa const int verbosity = packer_opts.pack_verbosity; + num_molecules_processed = 0; + std::map num_used_type_instances; bool is_cluster_legal; @@ -830,6 +832,7 @@ static void print_pack_status(int num_clb, for (auto i = clb_types.begin(); i != clb_types.end(); i++) { VTR_LOG("\t %s: # blocks %zu \n", i->first->name, size_t(i->second)); } + VTR_LOG("\n"); } } diff --git a/vpr/src/pack/output_clustering.cpp b/vpr/src/pack/output_clustering.cpp index 51758041f9b..b8768b0881b 100644 --- a/vpr/src/pack/output_clustering.cpp +++ b/vpr/src/pack/output_clustering.cpp @@ -31,6 +31,9 @@ #define LINELENGTH 1024 #define TAB_LENGTH 4 +static void print_clustering_stats_header(); +static void print_clustering_stats(char* block_name, int num_block_type, float num_inputs_clocks, float num_outputs); + /**************** Subroutine definitions ************************************/ /* Prints out one cluster (clb). Both the external pins and the * @@ -101,15 +104,15 @@ static void print_stats() { num_clb_types[logical_block->index]++; } + print_clustering_stats_header(); + for (itype = 0; itype < device_ctx.logical_block_types.size(); itype++) { if (num_clb_types[itype] == 0) { - VTR_LOG("\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n", - device_ctx.logical_block_types[itype].name, num_clb_types[itype], 0.0, 0.0); + print_clustering_stats(device_ctx.logical_block_types[itype].name, num_clb_types[itype], 0.0, 0.0); } else { - VTR_LOG("\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n", - device_ctx.logical_block_types[itype].name, num_clb_types[itype], - (float)num_clb_inputs_used[itype] / (float)num_clb_types[itype], - (float)num_clb_outputs_used[itype] / (float)num_clb_types[itype]); + print_clustering_stats(device_ctx.logical_block_types[itype].name, num_clb_types[itype], + (float)num_clb_inputs_used[itype] / (float)num_clb_types[itype], + (float)num_clb_outputs_used[itype] / (float)num_clb_types[itype]); } } @@ -127,6 +130,28 @@ static void print_stats() { /* TODO: print more stats */ } +static void print_clustering_stats_header() { + VTR_LOG("---------- -------- ------------------------------------ --------------------------\n"); + VTR_LOG("Block Type # Blocks Avg. # of input clocks and pins used Avg. # of output pins used\n"); + VTR_LOG("---------- -------- ------------------------------------ --------------------------\n"); +} + +static void print_clustering_stats(char* block_name, int num_block_type, float num_inputs_clocks, float num_outputs) { + VTR_LOG( + "%10s " + "%8d " + "%36g " + "%26g ", + block_name, + num_block_type, + num_inputs_clocks, + num_outputs); + + VTR_LOG("\n"); + + fflush(stdout); +} + static const char* clustering_xml_net_text(AtomNetId net_id) { /* This routine prints out the atom_ctx.nlist net name (or open). * net_num is the index of the atom_ctx.nlist net to be printed From 6fb45ff4e6d42c004f0eb63c935c3eb4a3985d29 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 27 Jan 2021 21:10:18 -0500 Subject: [PATCH 10/25] Shortened and clarified some comments --- vpr/src/pack/cluster.cpp | 98 ++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 63 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 4d27e076f06..718f1572251 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -223,9 +223,9 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* int verbosity, const int feasible_block_array_size); -static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - int verbosity); +static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, + const ClusterBlockId clb_index, + int verbosity); static void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data, const std::multimap& atom_molecules); @@ -582,11 +582,11 @@ std::map do_clustering(const t_packer_opts& pa //initial molecule in cluster has been processed num_molecules_processed++; - /*VTR_LOGV(verbosity == 2, - * "Complex block %d: '%s' (%s) ", num_clb, - * cluster_ctx.clb_nlist.block_name(clb_index).c_str(), - * cluster_ctx.clb_nlist.block_type(clb_index)->name); - * VTR_LOGV(verbosity == 2, ".");*/ + VTR_LOGV(verbosity > 2, + "Complex block %d: '%s' (%s) ", num_clb, + cluster_ctx.clb_nlist.block_name(clb_index).c_str(), + cluster_ctx.clb_nlist.block_type(clb_index)->name); + VTR_LOGV(verbosity > 2, "."); //Progress dot for seed-block fflush(stdout); @@ -653,7 +653,7 @@ std::map do_clustering(const t_packer_opts& pa VTR_LOG("\n"); fflush(stdout); } else if (block_pack_status == BLK_FAILED_FLOORPLANNING) { - VTR_LOG("\tFloorplanning constraints not met: '%s' (%s)", blk_name.c_str(), blk_model->name); + VTR_LOG("\tFAILED_FLOORPLANNING_CONSTRAINTS_CHECK: '%s' (%s)", blk_name.c_str(), blk_model->name); VTR_LOG("\n"); } else { VTR_LOG("\tFAILED_FEASIBILITY_CHECK: '%s' (%s)", blk_name.c_str(), blk_model->name, block_pack_status); @@ -684,7 +684,7 @@ std::map do_clustering(const t_packer_opts& pa next_molecule->pack_pattern->name, next_molecule->atom_block_ids.size()); VTR_LOG("\n"); } - //VTR_LOGV(verbosity == 2, "."); + fflush(stdout); //Since molecule passed, update num_molecules_processed @@ -715,8 +715,6 @@ std::map do_clustering(const t_packer_opts& pa packer_opts.pack_verbosity); } - //VTR_LOGV(verbosity == 2, "\n"); - if (detailed_routing_stage == (int)E_DETAILED_ROUTE_AT_END_ONLY) { /* is_mode_conflict does not affect this stage. It is needed when trying to route the packed clusters. * @@ -762,7 +760,10 @@ std::map do_clustering(const t_packer_opts& pa // update the data structure holding the LE counts update_le_count(cur_pb, logic_block_type, le_pb_type, le_count); + + //print clustering progress incrementally print_pack_status(num_clb, num_molecules, num_molecules_processed, num_used_type_instances); + free_pb_stats_recursive(cur_pb); } else { /* Free up data structures and requeue used molecules */ @@ -1286,14 +1287,10 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu for (j = 0; j < molecule_size; j++) { //try to intersect with atom PartitionRegion if atom exists if (molecule->atom_block_ids[j]) { - block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); - + block_pack_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[j], clb_index, verbosity); if (block_pack_status == BLK_FAILED_FLOORPLANNING) { - //VTR_LOG("\t\t\t From intersect: block failed floorplanning check \n"); return block_pack_status; - } /*else if (block_pack_status == BLK_PASSED) { - * VTR_LOG("\t\t\t From intersect: block passed \n"); - * }*/ + } } } @@ -1310,7 +1307,6 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu failed_location = i + 1; // try place atom block if it exists if (molecule->atom_block_ids[i]) { - //VTR_LOG("\t\t\t Inner for loop, molecule size is %d, i is %d \n", molecule_size, i); block_pack_status = try_place_atom_block_rec(primitives_list[i], molecule->atom_block_ids[i], pb, &parent, max_models, max_cluster_size, clb_index, @@ -1319,17 +1315,6 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu } } - //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion - /*for (j = 0; j < molecule_size && block_pack_status == BLK_PASSED; j++) { - * //VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); - * //failed_location = i + 1; - * //try to intersect with atom PartitionRegion if atom exists - * if (molecule->atom_block_ids[j]) { - * VTR_LOG("\t\t\t In the second for loop in try_pack_molecule, j is %d \n", j); - * block_pack_status = intersect_atom_cluster_part_regions(molecule->atom_block_ids[j], clb_index, verbosity); - * } - * }*/ - if (enable_pin_feasibility_filter && block_pack_status == BLK_PASSED) { /* Check if pin usage is feasible for the current packing assignment */ reset_lookahead_pins_used(pb); @@ -1583,10 +1568,14 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* return block_pack_status; } -/*try and see if floorplanning constraints match*/ -static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBlockId blk_id, - const ClusterBlockId clb_index, - int verbosity) { +/* + * Checks if the atom and cluster have compatible floorplanning constraints + * 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. + */ +static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, + const ClusterBlockId clb_index, + int verbosity) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); VprConstraints ctx_constraints = floorplanning_ctx.constraints; @@ -1604,7 +1593,7 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl //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 passed cluster %d \n", blk_id, clb_index); + VTR_LOG("\t\t\t Intersect: Atom block %d has no floorplanning constraints, passed for cluster %d \n", blk_id, clb_index); } return BLK_PASSED; } else { @@ -1613,23 +1602,23 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl //intersect it with the pr of the current cluster auto got = floorplanning_ctx.clb_constraints.find(clb_index); - //cluster_pr = got->second; if (got == floorplanning_ctx.clb_constraints.end()) { VTR_LOG("\t\t\t Did not find PR of cluster"); } else { cluster_pr = got->second; - //intersect_pr = intersection(atom_pr, cluster_pr); } if (cluster_pr.empty() == true) { - //what if the atom passes here but then doesn't pass somewhere else - //the cluster PR will have been updated for no reason - //probably better to have another function at the end of the try_pack_molecule function that - //takes care of updating cluster PR + /* + * TO-DO: If a constrained atom passes here but then fails somewhere later in try_pack_molecule, + * the cluster's PartitionRegion will have been updated needlessly. + * Probably better to have another function at the end of try_pack_molecule that takes care of + * updating the cluster PartitionRegion once the atom passes all the checks + */ got->second = atom_pr; if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + VTR_LOG("\t\t\t Intersect: Atom block %d has floorplanning constraints, passed cluster %d \n", blk_id, clb_index); } return BLK_PASSED; } else { @@ -1642,7 +1631,7 @@ static enum e_block_pack_status intersect_atom_cluster_part_regions(const AtomBl } return BLK_FAILED_FLOORPLANNING; } else { - //update the cluster's PartitionRegion + //update the cluster's PartitionRegion with the intersecting PartitionRegion got->second = intersect_pr; if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); @@ -2096,17 +2085,11 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto& atom_ctx = g_vpr_ctx.atom(); auto& device_ctx = g_vpr_ctx.mutable_device(); - - /* - * Get floorplanning information - */ auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); VprConstraints ctx_constraints = floorplanning_ctx.constraints; - /* - * Set an empty PR for the cluster - */ + /*Cluster's PartitionRegion is empty initially, meaning it has no floorplanning constraints*/ PartitionRegion empty_pr; floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); @@ -2227,22 +2210,11 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto block_type = clb_nlist->block_type(clb_index); num_used_type_instances[block_type]++; - /*determine whether seed atom belongs to a partition*/ + /*determine whether seed atom belongs to a partition, meaning it has a floorplanning constraint*/ PartitionId partid; partid = ctx_constraints.get_atom_partition(root_atom); - /*if the seed atom does not belong to a partition, it is unconstrained, so the cluster will have an empty PartitionRegion - *if there is a constraint,set cluster PartitionRegion to same in the vector map of the clusters in the constraints context - */ - /*if (partid == PartitionId::INVALID()) { - * PartitionRegion empty_pr; - * floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); - * } else { - * PartitionRegion pr = ctx_constraints.get_partition_pr(partid); - * floorplanning_ctx.clb_constraints.insert({clb_index, pr}); - * }*/ - - //if seed atom belongs to a partition, update cluster_pr + //if seed atom belongs to a partition, update cluster PartitionRegion if (partid != PartitionId::INVALID()) { PartitionRegion pr = ctx_constraints.get_partition_pr(partid); floorplanning_ctx.clb_constraints[clb_index] = pr; From 3a606e88b639ae7991c4de9fb1dd598688263f0e Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Thu, 28 Jan 2021 10:07:47 -0500 Subject: [PATCH 11/25] Made formatting changes to cluster echo file --- vpr/src/pack/cluster.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 718f1572251..dcc36a4d5af 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1618,7 +1618,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock */ got->second = atom_pr; if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d has floorplanning constraints, passed cluster %d \n", blk_id, clb_index); + 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; } else { @@ -1634,7 +1634,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock //update the cluster's PartitionRegion with the intersecting PartitionRegion got->second = intersect_pr; if (verbosity > 3) { - VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d \n", blk_id, clb_index); + 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; } @@ -2580,7 +2580,9 @@ static void echo_clusters(char* filename) { } for (auto i = cluster_atoms.begin(); i != cluster_atoms.end(); i++) { - fprintf(fp, "\tCluster Id: %zu \n", size_t(i->first)); + 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)); fprintf(fp, "\tAtoms in cluster: \n"); int num_atoms = i->second.size(); From 4fceb1ef9b25987fcc6ef140af8004b0df2fdf82 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 1 Feb 2021 09:54:49 -0500 Subject: [PATCH 12/25] Changed frequency of cluster progress messages --- vpr/src/pack/cluster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index dcc36a4d5af..af2dd635c51 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -825,7 +825,7 @@ static void print_pack_status(int num_clb, int num_molecules_processed, std::map clb_types) { //print an update every 10 clusters - if (num_clb % 10 == 0) { + if (num_clb % 50 == 0) { VTR_LOG("\nCreated %d clusters\n", num_clb); VTR_LOG("Processed %d out of %d molecules\n", num_molecules_processed, tot_num_molecules); VTR_LOG("Cluster types:\n"); From f34a1d632af60ecec3d2ba3d740036a92c3d67e3 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Tue, 2 Feb 2021 22:10:32 -0500 Subject: [PATCH 13/25] Changed data structure for holding cluster constraints from unordered_map to vtr vector --- vpr/src/base/vpr_context.h | 2 +- vpr/src/pack/cluster.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index d4bbc5aaf6d..5004442b91a 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -378,7 +378,7 @@ struct RoutingContext : public Context { */ struct FloorplanningContext : public Context { VprConstraints constraints; - std::unordered_map clb_constraints; + vtr::vector cluster_constraints; }; /** diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index af2dd635c51..54bd313d450 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1601,13 +1601,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock atom_pr = ctx_constraints.get_partition_pr(partid); //intersect it with the pr of the current cluster - auto got = floorplanning_ctx.clb_constraints.find(clb_index); - - if (got == floorplanning_ctx.clb_constraints.end()) { - VTR_LOG("\t\t\t Did not find PR of cluster"); - } else { - cluster_pr = got->second; - } + cluster_pr = floorplanning_ctx.cluster_constraints[clb_index]; if (cluster_pr.empty() == true) { /* @@ -1616,7 +1610,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock * Probably better to have another function at the end of try_pack_molecule that takes care of * updating the cluster PartitionRegion once the atom passes all the checks */ - got->second = atom_pr; + floorplanning_ctx.cluster_constraints[clb_index] = atom_pr; 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); } @@ -1632,7 +1626,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_FAILED_FLOORPLANNING; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion - got->second = intersect_pr; + floorplanning_ctx.cluster_constraints[clb_index] = intersect_pr; 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); } @@ -2091,7 +2085,7 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats /*Cluster's PartitionRegion is empty initially, meaning it has no floorplanning constraints*/ PartitionRegion empty_pr; - floorplanning_ctx.clb_constraints.insert({clb_index, empty_pr}); + floorplanning_ctx.cluster_constraints.push_back(empty_pr); /* Allocate a dummy initial cluster and load a atom block as a seed and check if it is legal */ AtomBlockId root_atom = molecule->atom_block_ids[molecule->root]; @@ -2217,7 +2211,7 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats //if seed atom belongs to a partition, update cluster PartitionRegion if (partid != PartitionId::INVALID()) { PartitionRegion pr = ctx_constraints.get_partition_pr(partid); - floorplanning_ctx.clb_constraints[clb_index] = pr; + floorplanning_ctx.cluster_constraints[clb_index] = pr; if (verbosity > 2) { VTR_LOG("Cluster's partition region was updated to match seed atom\n"); } From e4b8257e829342a2aa445400fd6072ccab38062b Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 3 Feb 2021 17:25:33 -0500 Subject: [PATCH 14/25] Changed place where cluster's PartitionRegion is updated so that it doesn't get updated unnecessarily --- vpr/src/pack/cluster.cpp | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 54bd313d450..a6c8fb99a06 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -225,7 +225,9 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, const ClusterBlockId clb_index, - int verbosity); + int verbosity, + PartitionRegion& temp_cluster_pr, + bool& cluster_pr_needs_update); static void revert_place_atom_block(const AtomBlockId blk_id, t_lb_router_data* router_data, const std::multimap& atom_molecules); @@ -1253,6 +1255,7 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu t_pb* cur_pb; auto& atom_ctx = g_vpr_ctx.atom(); + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); parent = nullptr; @@ -1283,11 +1286,17 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu return BLK_FAILED_FEASIBLE; } + PartitionRegion temp_cluster_pr; + bool cluster_pr_needs_update = false; + //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion for (j = 0; j < molecule_size; j++) { //try to intersect with atom PartitionRegion if atom exists if (molecule->atom_block_ids[j]) { - block_pack_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[j], clb_index, verbosity); + block_pack_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[j], + clb_index, verbosity, + temp_cluster_pr, + cluster_pr_needs_update); if (block_pack_status == BLK_FAILED_FLOORPLANNING) { return block_pack_status; } @@ -1396,6 +1405,12 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu } } + //update cluster PartitionRegion if atom with floorplanning constraints was added + if (cluster_pr_needs_update) { + floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; + VTR_LOG("\nUpdated PartitionRegion of cluster %d\n", clb_index); + } + for (i = 0; i < molecule_size; i++) { if (molecule->atom_block_ids[i]) { /* invalidate all molecules that share atom block with current molecule */ @@ -1575,7 +1590,9 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* */ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, const ClusterBlockId clb_index, - int verbosity) { + int verbosity, + PartitionRegion& temp_cluster_pr, + bool& cluster_pr_needs_update) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); VprConstraints ctx_constraints = floorplanning_ctx.constraints; @@ -1595,6 +1612,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock 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); } + cluster_pr_needs_update = false; return BLK_PASSED; } else { //get pr of that partition @@ -1610,7 +1628,9 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock * Probably better to have another function at the end of try_pack_molecule that takes care of * updating the cluster PartitionRegion once the atom passes all the checks */ - floorplanning_ctx.cluster_constraints[clb_index] = atom_pr; + //floorplanning_ctx.cluster_constraints[clb_index] = atom_pr; + 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); } @@ -1623,10 +1643,13 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock 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; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion - floorplanning_ctx.cluster_constraints[clb_index] = intersect_pr; + //floorplanning_ctx.cluster_constraints[clb_index] = intersect_pr; + temp_cluster_pr = intersect_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); } @@ -2204,19 +2227,6 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto block_type = clb_nlist->block_type(clb_index); num_used_type_instances[block_type]++; - /*determine whether seed atom belongs to a partition, meaning it has a floorplanning constraint*/ - PartitionId partid; - partid = ctx_constraints.get_atom_partition(root_atom); - - //if seed atom belongs to a partition, update cluster PartitionRegion - if (partid != PartitionId::INVALID()) { - PartitionRegion pr = ctx_constraints.get_partition_pr(partid); - floorplanning_ctx.cluster_constraints[clb_index] = pr; - if (verbosity > 2) { - VTR_LOG("Cluster's partition region was updated to match seed atom\n"); - } - } - /* Expand FPGA size if needed */ // Check used type instances against the possible equivalent physical locations unsigned int num_instances = 0; From 6e59e429e93bf81956c643934616b0d4bb818842 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 3 Feb 2021 21:22:44 -0500 Subject: [PATCH 15/25] Added comments and removed unnecessary variables --- vpr/src/base/partition_region.cpp | 6 +---- vpr/src/base/partition_region.h | 2 +- vpr/src/base/vpr_constraints.cpp | 6 +---- vpr/src/base/vpr_constraints.h | 28 ++++++++++++----------- vpr/src/base/vpr_constraints_reader.cpp | 3 --- vpr/src/base/vpr_constraints_serializer.h | 3 --- vpr/src/base/vpr_context.h | 14 ++++++++++++ vpr/src/pack/cluster.cpp | 23 +++++-------------- 8 files changed, 38 insertions(+), 47 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 0ca8c510be3..698b1dc2cc5 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -9,11 +9,7 @@ std::vector PartitionRegion::get_partition_region() { } bool PartitionRegion::empty() { - if (partition_region.size() == 0) { - return true; - } else { - return false; - } + return partition_region.size() == 0; } PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 020cd3b8fda..26ab1dba228 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -25,7 +25,7 @@ class PartitionRegion { std::vector get_partition_region(); /** - * @brief Check if the PartitionRegion is empty (ie. holds no regions in its vector) + * @brief Check if the PartitionRegion is empty (meaning there is no constraint on the object the PartitionRegion belongs to) */ bool empty(); diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 4a60428ccb2..cbf2c4af06b 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -49,11 +49,7 @@ std::vector VprConstraints::get_part_atoms(PartitionId part_id) { } int VprConstraints::get_num_partitions() { - return num_partitions; -} - -void VprConstraints::set_num_partitions(int num_parts) { - num_partitions = num_parts; + return partitions.size(); } PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 940856fcd84..1a079dd857a 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -18,6 +18,21 @@ * It also specifies which regions the partitions should be placed in. Atoms cannot be placed in more than one partition. * If an atom is assigned to more than one partition, the last partition is was assigned to will be the partition it is placed in. * + * Related Classes + * =============== + * The following definitions are useful to understanding this class: + * + * Partition: a grouping of atoms that are constrained to a portion of an FPGA + * See vpr/base/partition.h for more detail + * + * Region: the x and y bounds of a rectangular region, optionally including a subtile value, + * that atoms in a partition are constrained to + * See vpr/base/region.h for more detail + * + * PartitionRegion: the union of regions that a partition can be placed in + * See vpr/base/partition_region.h for more detail + * + * */ class VprConstraints { @@ -65,13 +80,6 @@ class VprConstraints { */ int get_num_partitions(); - /** - * @brief Sets the number of partitions in the object - * - * @param num_parts The number of partitions in the partitions vector - */ - void set_num_partitions(int num_parts); - /** * @brief Returns the PartitionRegion belonging to the specified Partition * @@ -89,12 +97,6 @@ class VprConstraints { * Store all partitions */ vtr::vector partitions; - - /** - * Store number of partitions - the number of partitions in the partitions vector. - * Used when echoing VprConstraints objects. - */ - int num_partitions; }; #endif /* VPR_CONSTRAINTS_H */ diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index a2704f2846b..db2f5260dac 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -31,9 +31,6 @@ void load_vpr_constraints_file(const char* read_vpr_constraints_name) { read_vpr_constraints_name); } - //VprConstraints constraints = reader.constraints_; - //int num_parts = reader.num_partitions_; - //Update the floorplanning constraints in the floorplanning constraints context auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); floorplanning_ctx.constraints = reader.constraints_; diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index 644a2c95028..c87449f4db7 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -295,9 +295,6 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase cluster_constraints; }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index a6c8fb99a06..6e304c9fa15 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -70,8 +70,6 @@ #include "tatum/report/graphviz_dot_writer.hpp" #include "tatum/TimingReporter.hpp" -#include "constraints_load.h" - #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 */ @@ -225,7 +223,7 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, const ClusterBlockId clb_index, - int verbosity, + const int verbosity, PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update); @@ -1249,7 +1247,6 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu t_ext_pin_util max_external_pin_util) { int molecule_size, failed_location; int i; - int j; enum e_block_pack_status block_pack_status; t_pb* parent; t_pb* cur_pb; @@ -1289,11 +1286,11 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu PartitionRegion temp_cluster_pr; bool cluster_pr_needs_update = false; - //for loop to check if cluster PartitionRegion intersects with atom PartitionRegion - for (j = 0; j < molecule_size; j++) { + //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[j]) { - block_pack_status = atom_cluster_floorplanning_check(molecule->atom_block_ids[j], + 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); @@ -1590,7 +1587,7 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* */ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlockId blk_id, const ClusterBlockId clb_index, - int verbosity, + const int verbosity, PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); @@ -1622,13 +1619,6 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock cluster_pr = floorplanning_ctx.cluster_constraints[clb_index]; if (cluster_pr.empty() == true) { - /* - * TO-DO: If a constrained atom passes here but then fails somewhere later in try_pack_molecule, - * the cluster's PartitionRegion will have been updated needlessly. - * Probably better to have another function at the end of try_pack_molecule that takes care of - * updating the cluster PartitionRegion once the atom passes all the checks - */ - //floorplanning_ctx.cluster_constraints[clb_index] = atom_pr; temp_cluster_pr = atom_pr; cluster_pr_needs_update = true; if (verbosity > 3) { @@ -1647,7 +1637,6 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_FAILED_FLOORPLANNING; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion - //floorplanning_ctx.cluster_constraints[clb_index] = intersect_pr; temp_cluster_pr = intersect_pr; cluster_pr_needs_update = true; if (verbosity > 3) { From 83cfe2b1a5a1b5e75b3547e9d121749a78d14616 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Sun, 7 Feb 2021 22:29:59 -0500 Subject: [PATCH 16/25] Made packing progress print every 4% --- vpr/src/base/SetupGrid.cpp | 2 ++ vpr/src/pack/cluster.cpp | 50 ++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/vpr/src/base/SetupGrid.cpp b/vpr/src/base/SetupGrid.cpp index e246fb6d564..0d08cfc470f 100644 --- a/vpr/src/base/SetupGrid.cpp +++ b/vpr/src/base/SetupGrid.cpp @@ -406,6 +406,8 @@ static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t grid_widt size_t incry = p.parse_formula(yspec.incr_expr, vars); size_t repeaty = p.parse_formula(yspec.repeat_expr, vars); + warn_out_of_range = false; + //Check start against the device dimensions // Start locations outside the device will never create block instances if (startx > grid_width - 1) { diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 6e304c9fa15..3555c1b38eb 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -191,7 +191,9 @@ static t_pack_molecule* get_free_molecule_with_most_ext_inputs_for_cluster(t_pb* static void print_pack_status(int num_clb, int tot_num_molecules, int num_molecules_processed, - std::map clb_types); + int& mols_since_last_print, + int device_width, + int device_height); static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* cluster_placement_stats_ptr, const std::multimap& atom_molecules, @@ -401,8 +403,8 @@ std::map do_clustering(const t_packer_opts& pa *****************************************************************/ VTR_ASSERT(packer_opts.packer_algorithm == PACK_GREEDY); - int num_molecules, num_molecules_processed, blocks_since_last_analysis, num_clb, - num_blocks_hill_added, max_cluster_size, cur_cluster_size, + int num_molecules, num_molecules_processed, mols_since_last_print, blocks_since_last_analysis, + num_clb, num_blocks_hill_added, max_cluster_size, cur_cluster_size, max_pb_depth, cur_pb_depth, num_unrelated_clustering_attempts, seedindex, savedseedindex /* index of next most timing critical block */, detailed_routing_stage, *hill_climbing_inputs_avail; @@ -410,6 +412,7 @@ std::map do_clustering(const t_packer_opts& pa const int verbosity = packer_opts.pack_verbosity; num_molecules_processed = 0; + mols_since_last_print = 0; std::map num_used_type_instances; @@ -581,6 +584,13 @@ std::map do_clustering(const t_packer_opts& pa //initial molecule in cluster has been processed num_molecules_processed++; + mols_since_last_print++; + print_pack_status(num_clb, + num_molecules, + num_molecules_processed, + mols_since_last_print, + device_ctx.grid.width(), + device_ctx.grid.height()); VTR_LOGV(verbosity > 2, "Complex block %d: '%s' (%s) ", num_clb, @@ -689,6 +699,12 @@ std::map do_clustering(const t_packer_opts& pa //Since molecule passed, update num_molecules_processed num_molecules_processed++; + mols_since_last_print++; + print_pack_status(num_clb, num_molecules, + num_molecules_processed, + mols_since_last_print, + device_ctx.grid.width(), + device_ctx.grid.height()); update_cluster_stats(next_molecule, clb_index, is_clock, //Set of all clocks @@ -762,7 +778,7 @@ std::map do_clustering(const t_packer_opts& pa update_le_count(cur_pb, logic_block_type, le_pb_type, le_count); //print clustering progress incrementally - print_pack_status(num_clb, num_molecules, num_molecules_processed, num_used_type_instances); + //print_pack_status(num_clb, num_molecules, num_molecules_processed, mols_since_last_print, device_ctx.grid.width(), device_ctx.grid.height()); free_pb_stats_recursive(cur_pb); } else { @@ -823,17 +839,23 @@ std::map do_clustering(const t_packer_opts& pa static void print_pack_status(int num_clb, int tot_num_molecules, int num_molecules_processed, - std::map clb_types) { - //print an update every 10 clusters - if (num_clb % 50 == 0) { + int& mols_since_last_print, + int device_width, + int device_height) { + const float print_frequency = 0.04; + + double percentage = (num_molecules_processed / (double)tot_num_molecules) * 100; + + int int_molecule_increment = (int)(print_frequency * tot_num_molecules); + + //print update every 4% of molecules processed + if (mols_since_last_print == int_molecule_increment) { + VTR_LOG("\nMols since last print is %d", mols_since_last_print); VTR_LOG("\nCreated %d clusters\n", num_clb); VTR_LOG("Processed %d out of %d molecules\n", num_molecules_processed, tot_num_molecules); - VTR_LOG("Cluster types:\n"); - - for (auto i = clb_types.begin(); i != clb_types.end(); i++) { - VTR_LOG("\t %s: # blocks %zu \n", i->first->name, size_t(i->second)); - } - VTR_LOG("\n"); + VTR_LOG("%f percent of molecules processed\n", percentage); + VTR_LOG("FPGA size %d x %d\n", device_width, device_height); + mols_since_last_print = 0; } } @@ -1406,6 +1428,8 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu if (cluster_pr_needs_update) { floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; VTR_LOG("\nUpdated PartitionRegion of cluster %d\n", clb_index); + std::vector pr = floorplanning_ctx.cluster_constraints[clb_index].get_partition_region(); + VTR_LOG("Cluster's partition region size is %d\n", pr.size()); } for (i = 0; i < molecule_size; i++) { From 7e8f9d595f08408384491cfe77b8c38fdc7698b0 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 8 Feb 2021 11:17:42 -0500 Subject: [PATCH 17/25] Print clustering progress in a table --- vpr/src/pack/cluster.cpp | 41 +++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 3555c1b38eb..eedb16d9e6a 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -188,6 +188,8 @@ static t_pack_molecule* get_molecule_by_num_ext_inputs(const int ext_inps, static t_pack_molecule* get_free_molecule_with_most_ext_inputs_for_cluster(t_pb* cur_pb, t_cluster_placement_stats* cluster_placement_stats_ptr); +static void print_pack_status_header(); + static void print_pack_status(int num_clb, int tot_num_molecules, int num_molecules_processed, @@ -556,6 +558,8 @@ std::map do_clustering(const t_packer_opts& pa istart = get_highest_gain_seed_molecule(&seedindex, atom_molecules, seed_atoms); + print_pack_status_header(); + /**************************************************************** * Clustering *****************************************************************/ @@ -836,6 +840,12 @@ std::map do_clustering(const t_packer_opts& pa return num_used_type_instances; } +static void print_pack_status_header() { + VTR_LOG("------------------- -------------------------- ---------\n"); + VTR_LOG("Molecules processed Number of clusters created FPGA size\n"); + VTR_LOG("------------------- -------------------------- ---------\n"); +} + static void print_pack_status(int num_clb, int tot_num_molecules, int num_molecules_processed, @@ -846,15 +856,24 @@ static void print_pack_status(int num_clb, double percentage = (num_molecules_processed / (double)tot_num_molecules) * 100; + int int_percentage = int(percentage); + int int_molecule_increment = (int)(print_frequency * tot_num_molecules); - //print update every 4% of molecules processed if (mols_since_last_print == int_molecule_increment) { - VTR_LOG("\nMols since last print is %d", mols_since_last_print); - VTR_LOG("\nCreated %d clusters\n", num_clb); - VTR_LOG("Processed %d out of %d molecules\n", num_molecules_processed, tot_num_molecules); - VTR_LOG("%f percent of molecules processed\n", percentage); - VTR_LOG("FPGA size %d x %d\n", device_width, device_height); + VTR_LOG( + "%6d/%-6d %3d%% " + "%26d " + "%3d x %-3d ", + num_molecules_processed, + tot_num_molecules, + int_percentage, + num_clb, + device_width, + device_height); + + VTR_LOG("\n"); + fflush(stdout); mols_since_last_print = 0; } } @@ -1427,9 +1446,9 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu //update cluster PartitionRegion if atom with floorplanning constraints was added if (cluster_pr_needs_update) { floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; - VTR_LOG("\nUpdated PartitionRegion of cluster %d\n", clb_index); - std::vector pr = floorplanning_ctx.cluster_constraints[clb_index].get_partition_region(); - VTR_LOG("Cluster's partition region size is %d\n", pr.size()); + if (verbosity > 2) { + VTR_LOG("\nUpdated PartitionRegion of cluster %d\n", clb_index); + } } for (i = 0; i < molecule_size; i++) { @@ -2249,8 +2268,8 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats if (num_used_type_instances[block_type] > num_instances) { device_ctx.grid = create_device_grid(device_layout_name, arch->grid_layouts, num_used_type_instances, target_device_utilization); - VTR_LOGV(verbosity > 0, "Not enough resources expand FPGA size to (%d x %d)\n", - device_ctx.grid.width(), device_ctx.grid.height()); + /*VTR_LOGV(verbosity > 0, "Not enough resources expand FPGA size to (%d x %d)\n", + * device_ctx.grid.width(), device_ctx.grid.height());*/ } } From c8b58b88f9c4ba92bb8bb59a036732d73aa59179 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 8 Feb 2021 12:06:26 -0500 Subject: [PATCH 18/25] Added function level comments and table headers --- vpr/src/base/constraints_load.cpp | 8 +++++--- vpr/src/base/constraints_load.h | 2 +- vpr/src/base/vpr_constraints_reader.cpp | 2 +- vpr/src/base/vpr_context.h | 4 ++++ vpr/src/pack/cluster.cpp | 8 ++++++-- vpr/src/pack/output_clustering.cpp | 1 + 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/vpr/src/base/constraints_load.cpp b/vpr/src/base/constraints_load.cpp index 52e1cecbfe4..788396eeffc 100644 --- a/vpr/src/base/constraints_load.cpp +++ b/vpr/src/base/constraints_load.cpp @@ -67,16 +67,18 @@ void print_constraints(FILE* fp, VprConstraints constraints, int num_parts) { } } -void echo_constraints(char* filename, VprConstraints constraints, int num_parts) { +void echo_constraints(char* filename, VprConstraints constraints) { FILE* fp; fp = vtr::fopen(filename, "w"); + int num_of_parts = constraints.get_num_partitions(); + fprintf(fp, "--------------------------------------------------------------\n"); fprintf(fp, "Constraints\n"); fprintf(fp, "--------------------------------------------------------------\n"); fprintf(fp, "\n"); - fprintf(fp, "\n Number of partitions is %d \n", num_parts); - print_constraints(fp, constraints, num_parts); + fprintf(fp, "\n Number of partitions is %d \n", num_of_parts); + print_constraints(fp, constraints, num_of_parts); fclose(fp); } diff --git a/vpr/src/base/constraints_load.h b/vpr/src/base/constraints_load.h index f95fbe40c0d..6c2d53feda7 100644 --- a/vpr/src/base/constraints_load.h +++ b/vpr/src/base/constraints_load.h @@ -7,6 +7,6 @@ #include "vpr_constraints.h" #include "vtr_vector.h" -void echo_constraints(char* filename, VprConstraints constraints, int num_parts); +void echo_constraints(char* filename, VprConstraints constraints); #endif diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index db2f5260dac..8e69b7b42b4 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -38,6 +38,6 @@ void load_vpr_constraints_file(const char* read_vpr_constraints_name) { VprConstraints ctx_constraints = floorplanning_ctx.constraints; if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_VPR_CONSTRAINTS)) { - echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), ctx_constraints, ctx_constraints.get_num_partitions()); + echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), ctx_constraints); } } diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index ffc34ebfcc1..8128b6244a3 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -382,6 +382,8 @@ struct FloorplanningContext : public Context { * * Provides all information needed about floorplanning constraints, including * which atoms are constrained and the regions they are constrained to. + * + * The constraints are input into vpr and do not change. */ VprConstraints constraints; @@ -391,6 +393,8 @@ struct FloorplanningContext : public Context { * Each cluster will have a PartitionRegion specifying its regions constraints * according to the constrained atoms packed into it. This structure allows the floorplanning * constraints for a given cluster to be found easily given its ClusterBlockId. + * + * The constraints on each cluster are computed during the clustering process and can change. */ vtr::vector cluster_constraints; }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index eedb16d9e6a..b3963b9780b 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -840,12 +840,15 @@ std::map do_clustering(const t_packer_opts& pa return num_used_type_instances; } +/*print the header for the clustering progress table*/ static void print_pack_status_header() { + VTR_LOG("Starting Clustering - Clustering Progress: \n"); VTR_LOG("------------------- -------------------------- ---------\n"); VTR_LOG("Molecules processed Number of clusters created FPGA size\n"); VTR_LOG("------------------- -------------------------- ---------\n"); } +/*incrementally print progress updates during clustering*/ static void print_pack_status(int num_clb, int tot_num_molecules, int num_molecules_processed, @@ -1444,6 +1447,8 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu } //update cluster PartitionRegion if atom with floorplanning constraints was added + /* TODO: Create temp_cluster_pr in start_new_cluster and pass to this function + * by reference so that this check is not needed */ if (cluster_pr_needs_update) { floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; if (verbosity > 2) { @@ -2268,8 +2273,6 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats if (num_used_type_instances[block_type] > num_instances) { device_ctx.grid = create_device_grid(device_layout_name, arch->grid_layouts, num_used_type_instances, target_device_utilization); - /*VTR_LOGV(verbosity > 0, "Not enough resources expand FPGA size to (%d x %d)\n", - * device_ctx.grid.width(), device_ctx.grid.height());*/ } } @@ -2591,6 +2594,7 @@ static void check_clustering() { } } +/*Print the contents of each cluster to an echo file*/ static void echo_clusters(char* filename) { FILE* fp; fp = vtr::fopen(filename, "w"); diff --git a/vpr/src/pack/output_clustering.cpp b/vpr/src/pack/output_clustering.cpp index f53cb41e209..233bbb7ecac 100644 --- a/vpr/src/pack/output_clustering.cpp +++ b/vpr/src/pack/output_clustering.cpp @@ -131,6 +131,7 @@ static void print_stats() { } static void print_clustering_stats_header() { + VTR_LOG("Final Clustering Statistics: \n"); VTR_LOG("---------- -------- ------------------------------------ --------------------------\n"); VTR_LOG("Block Type # Blocks Avg. # of input clocks and pins used Avg. # of output pins used\n"); VTR_LOG("---------- -------- ------------------------------------ --------------------------\n"); From f11da6700e229c51314a6f55a73f9ac1ab8b6c2f Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 10 Feb 2021 11:29:48 -0500 Subject: [PATCH 19/25] Modified build_device_grid function call in SetupGrid.cpp to get rid of unnecessary warning messages during clustering --- vpr/src/base/SetupGrid.cpp | 6 +----- vpr/src/base/constraints_load.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/vpr/src/base/SetupGrid.cpp b/vpr/src/base/SetupGrid.cpp index 0d08cfc470f..7c4df13e98b 100644 --- a/vpr/src/base/SetupGrid.cpp +++ b/vpr/src/base/SetupGrid.cpp @@ -191,9 +191,7 @@ static DeviceGrid auto_size_device_grid(const std::vector& grid_layo //Check if it satisfies the block counts if (grid_satisfies_instance_counts(grid, minimum_instance_counts, maximum_device_utilization)) { //Re-build the grid at the final size with out-of-range - //warnings turned on (so users are aware of out-of-range issues - //at the final device sizes) - grid = build_device_grid(grid_def, width, height, true, limiting_resources); + grid = build_device_grid(grid_def, width, height, false, limiting_resources); return grid; } @@ -406,8 +404,6 @@ static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t grid_widt size_t incry = p.parse_formula(yspec.incr_expr, vars); size_t repeaty = p.parse_formula(yspec.repeat_expr, vars); - warn_out_of_range = false; - //Check start against the device dimensions // Start locations outside the device will never create block instances if (startx > grid_width - 1) { diff --git a/vpr/src/base/constraints_load.cpp b/vpr/src/base/constraints_load.cpp index 788396eeffc..7ab94f547cc 100644 --- a/vpr/src/base/constraints_load.cpp +++ b/vpr/src/base/constraints_load.cpp @@ -3,7 +3,7 @@ static void print_region(FILE* fp, Region region); static void print_partition(FILE* fp, Partition part); static void print_partition_region(FILE* fp, PartitionRegion pr); -static void print_constraints(FILE* fp, VprConstraints constraints, int num_parts); +static void print_constraints(FILE* fp, VprConstraints constraints); void print_region(FILE* fp, Region region) { vtr::Rect rect = region.get_region_rect(); @@ -42,10 +42,14 @@ void print_partition_region(FILE* fp, PartitionRegion pr) { } } -void print_constraints(FILE* fp, VprConstraints constraints, int num_parts) { +void print_constraints(FILE* fp, VprConstraints constraints) { Partition temp_part; std::vector atoms; + int num_parts = constraints.get_num_partitions(); + + fprintf(fp, "\n Number of partitions is %d \n", num_parts); + for (int i = 0; i < num_parts; i++) { PartitionId part_id(i); @@ -71,14 +75,11 @@ void echo_constraints(char* filename, VprConstraints constraints) { FILE* fp; fp = vtr::fopen(filename, "w"); - int num_of_parts = constraints.get_num_partitions(); - fprintf(fp, "--------------------------------------------------------------\n"); fprintf(fp, "Constraints\n"); fprintf(fp, "--------------------------------------------------------------\n"); fprintf(fp, "\n"); - fprintf(fp, "\n Number of partitions is %d \n", num_of_parts); - print_constraints(fp, constraints, num_of_parts); + print_constraints(fp, constraints); fclose(fp); } From 899a3da10f424ca6ca317a03d4acaaadd5a85226 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 10 Feb 2021 16:31:11 -0500 Subject: [PATCH 20/25] Create the temporary cluster PartitionRegion earlier in the flow when creating a cluster --- vpr/src/pack/cluster.cpp | 53 ++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index b3963b9780b..ded837408b4 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -210,7 +210,8 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu int verbosity, bool enable_pin_feasibility_filter, const int feasible_block_array_size, - t_ext_pin_util max_external_pin_util); + t_ext_pin_util max_external_pin_util, + PartitionRegion& temp_cluster_pr); static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* pb_graph_node, const AtomBlockId blk_id, @@ -276,7 +277,8 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats int verbosity, bool enable_pin_feasibility_filter, bool balance_block_type_utilization, - const int feasible_block_array_size); + const int feasible_block_array_size, + PartitionRegion& temp_cluster_pr); static t_pack_molecule* get_highest_gain_molecule(t_pb* cur_pb, const std::multimap& atom_molecules, @@ -572,6 +574,10 @@ std::map do_clustering(const t_packer_opts& pa VTR_LOGV(verbosity > 2, "Complex block %d:\n", num_clb); + /*this temp structure is used to store updates to the cluster's + * floorplanning constraints before they are stored long-term*/ + PartitionRegion temp_cluster_pr; + start_new_cluster(cluster_placement_stats, primitives_list, atom_molecules, clb_index, istart, num_used_type_instances, @@ -584,7 +590,8 @@ std::map do_clustering(const t_packer_opts& pa packer_opts.pack_verbosity, packer_opts.enable_pin_feasibility_filter, balance_block_type_utilization, - packer_opts.feasible_block_array_size); + packer_opts.feasible_block_array_size, + temp_cluster_pr); //initial molecule in cluster has been processed num_molecules_processed++; @@ -649,7 +656,8 @@ std::map do_clustering(const t_packer_opts& pa packer_opts.pack_verbosity, packer_opts.enable_pin_feasibility_filter, packer_opts.feasible_block_array_size, - target_ext_pin_util); + target_ext_pin_util, + temp_cluster_pr); prev_molecule = next_molecule; auto blk_id = next_molecule->atom_block_ids[next_molecule->root]; @@ -1288,7 +1296,8 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu int verbosity, bool enable_pin_feasibility_filter, const int feasible_block_array_size, - t_ext_pin_util max_external_pin_util) { + 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; @@ -1327,7 +1336,6 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu return BLK_FAILED_FEASIBLE; } - PartitionRegion temp_cluster_pr; bool cluster_pr_needs_update = false; //check if every atom in the molecule is legal in the cluster from a floorplanning perspective @@ -1447,8 +1455,6 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu } //update cluster PartitionRegion if atom with floorplanning constraints was added - /* TODO: Create temp_cluster_pr in start_new_cluster and pass to this function - * by reference so that this check is not needed */ if (cluster_pr_needs_update) { floorplanning_ctx.cluster_constraints[clb_index] = temp_cluster_pr; if (verbosity > 2) { @@ -2132,7 +2138,8 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats int verbosity, bool enable_pin_feasibility_filter, bool balance_block_type_utilization, - const int feasible_block_array_size) { + const int feasible_block_array_size, + PartitionRegion& temp_cluster_pr) { /* 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 */ @@ -2218,7 +2225,8 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats verbosity, enable_pin_feasibility_filter, feasible_block_array_size, - FULL_EXTERNAL_PIN_UTIL); + FULL_EXTERNAL_PIN_UTIL, + temp_cluster_pr); success = (pack_result == BLK_PASSED); } @@ -2633,6 +2641,31 @@ static void echo_clusters(char* filename) { } } + fprintf(fp, "\nCLUSTER CONSTRAINTS:\n"); + 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) { + fprintf(fp, "\nRegions in Cluster %zu:\n", size_t(clb_id)); + for (unsigned int i = 0; i < reg.size(); i++) { + vtr::Rect rect = reg[i].get_region_rect(); + int xmin = rect.xmin(); + int xmax = rect.xmax(); + int ymin = rect.ymin(); + int ymax = rect.ymax(); + int subtile = reg[i].get_sub_tile(); + + fprintf(fp, "\tRegion: \n"); + fprintf(fp, "\txmin: %d\n", xmin); + fprintf(fp, "\tymin: %d\n", ymin); + fprintf(fp, "\txmax: %d\n", xmax); + fprintf(fp, "\tymax: %d\n", ymax); + fprintf(fp, "\tsubtile: %d\n\n", subtile); + } + } + } + fclose(fp); } From ee4bf86ed4622daa87c443d171ec17e455938f64 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Fri, 12 Feb 2021 00:45:08 -0500 Subject: [PATCH 21/25] Moved print functions to be within their respective class. ex - print_region is now in region class. Added a print function for vtr::Rect --- libs/libvtrutil/src/vtr_geometry.h | 4 ++ libs/libvtrutil/src/vtr_geometry.tpp | 7 +++ vpr/src/base/constraints_load.cpp | 71 ---------------------------- vpr/src/base/partition.cpp | 10 ++++ vpr/src/base/partition.h | 3 ++ vpr/src/base/partition_region.cpp | 13 +++++ vpr/src/base/partition_region.h | 3 ++ vpr/src/base/region.cpp | 6 +++ vpr/src/base/region.h | 3 ++ vpr/src/base/vpr_constraints.cpp | 30 ++++++++++++ vpr/src/base/vpr_constraints.h | 3 ++ vpr/src/pack/cluster.cpp | 21 ++------ 12 files changed, 87 insertions(+), 87 deletions(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 73d774b09d6..a12e87aabe8 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -145,6 +145,10 @@ Rect bounding_box(const Rect& lhs, const Rect& rhs); template Rect intersection(const Rect& lhs, const Rect& rhs); +//Prints a rectangle +template +static void print_rect(FILE* fp, const Rect rect); + //Sample on a uniformly spaced grid within a rectangle // sample(vtr::Rect(l, h), 0, 0, M) == l // sample(vtr::Rect(l, h), M, M, M) == h diff --git a/libs/libvtrutil/src/vtr_geometry.tpp b/libs/libvtrutil/src/vtr_geometry.tpp index 5a4c3d8ea01..2010700fc50 100644 --- a/libs/libvtrutil/src/vtr_geometry.tpp +++ b/libs/libvtrutil/src/vtr_geometry.tpp @@ -189,6 +189,13 @@ Rect intersection(const Rect& lhs, const Rect& rhs) { std::min(lhs.xmax(), rhs.xmax()), std::min(lhs.ymax(), rhs.ymax())); } +template +static void print_rect(FILE* fp, const Rect rect) { + fprintf(fp, "\txmin: %d\n", rect.xmin()); + fprintf(fp, "\tymin: %d\n", rect.ymin()); + fprintf(fp, "\txmax: %d\n", rect.xmax()); + fprintf(fp, "\tymax: %d\n", rect.ymax()); +} //Only defined for integral types template::value>::type...> Point sample(const vtr::Rect& r, T x, T y, T d) { diff --git a/vpr/src/base/constraints_load.cpp b/vpr/src/base/constraints_load.cpp index 7ab94f547cc..7d12547bf3b 100644 --- a/vpr/src/base/constraints_load.cpp +++ b/vpr/src/base/constraints_load.cpp @@ -1,76 +1,5 @@ #include "constraints_load.h" -static void print_region(FILE* fp, Region region); -static void print_partition(FILE* fp, Partition part); -static void print_partition_region(FILE* fp, PartitionRegion pr); -static void print_constraints(FILE* fp, VprConstraints constraints); - -void print_region(FILE* fp, Region region) { - vtr::Rect rect = region.get_region_rect(); - int xmin = rect.xmin(); - int xmax = rect.xmax(); - int ymin = rect.ymin(); - int ymax = rect.ymax(); - int subtile = region.get_sub_tile(); - - fprintf(fp, "\tRegion: \n"); - fprintf(fp, "\txmin: %d\n", xmin); - fprintf(fp, "\txmax: %d\n", xmax); - fprintf(fp, "\tymin: %d\n", ymin); - fprintf(fp, "\tymax: %d\n", ymax); - fprintf(fp, "\tsubtile: %d\n\n", subtile); -} - -void print_partition(FILE* fp, Partition part) { - std::string name = part.get_name(); - fprintf(fp, "partition_name: %s\n", name.c_str()); - - PartitionRegion pr = part.get_part_region(); - - print_partition_region(fp, pr); -} - -void print_partition_region(FILE* fp, PartitionRegion pr) { - std::vector part_region = pr.get_partition_region(); - - int pr_size = part_region.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]); - } -} - -void print_constraints(FILE* fp, VprConstraints constraints) { - Partition temp_part; - std::vector atoms; - - int num_parts = constraints.get_num_partitions(); - - fprintf(fp, "\n Number of partitions is %d \n", num_parts); - - for (int i = 0; i < num_parts; i++) { - PartitionId part_id(i); - - temp_part = constraints.get_partition(part_id); - - fprintf(fp, "\npartition_id: %zu\n", size_t(part_id)); - print_partition(fp, temp_part); - - atoms = constraints.get_part_atoms(part_id); - - int atoms_size = atoms.size(); - - 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]; - fprintf(fp, "\t#%zu\n", size_t(atom_id)); - } - } -} - void echo_constraints(char* filename, VprConstraints constraints) { FILE* fp; fp = vtr::fopen(filename, "w"); diff --git a/vpr/src/base/partition.cpp b/vpr/src/base/partition.cpp index 51f208d7b36..107a8ec2d3a 100644 --- a/vpr/src/base/partition.cpp +++ b/vpr/src/base/partition.cpp @@ -1,4 +1,5 @@ #include "partition.h" +#include "partition_region.h" #include #include @@ -17,3 +18,12 @@ const PartitionRegion Partition::get_part_region() { void Partition::set_part_region(PartitionRegion pr) { part_region = pr; } + +void print_partition(FILE* fp, Partition part) { + std::string name = part.get_name(); + fprintf(fp, "partition_name: %s\n", name.c_str()); + + 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 9c3206b6967..7ef144e22a7 100644 --- a/vpr/src/base/partition.h +++ b/vpr/src/base/partition.h @@ -53,4 +53,7 @@ class Partition { PartitionRegion part_region; ///< the union of regions that the partition can be placed in }; +///@brief used to print data from a Partition +void print_partition(FILE* fp, Partition part); + #endif /* PARTITION_H */ diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 698b1dc2cc5..88823b0f6e4 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -1,4 +1,5 @@ #include "partition_region.h" +#include "region.h" void PartitionRegion::add_to_part_region(Region region) { partition_region.push_back(region); @@ -33,3 +34,15 @@ PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { return pr; } + +void print_partition_region(FILE* fp, PartitionRegion pr) { + std::vector part_region = pr.get_partition_region(); + + int pr_size = part_region.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]); + } +} diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 26ab1dba228..b7fd9720ee4 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -41,4 +41,7 @@ class PartitionRegion { std::vector partition_region; ///< 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); + #endif /* PARTITION_REGIONS_H */ diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index 4480244a41f..a94823c9ae9 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -82,3 +82,9 @@ Region intersection(Region r1, Region r2) { return intersect; } + +void print_region(FILE* fp, Region region) { + fprintf(fp, "\tRegion: \n"); + print_rect(fp, region.get_region_rect()); + fprintf(fp, "\tsubtile: %d\n\n", region.get_sub_tile()); +} diff --git a/vpr/src/base/region.h b/vpr/src/base/region.h index d8032f86130..42a57caaa6f 100644 --- a/vpr/src/base/region.h +++ b/vpr/src/base/region.h @@ -76,4 +76,7 @@ bool do_regions_intersect(Region r1, Region r2); */ Region intersection(Region r1, Region r2); +///@brief Used to print data from a Region +void print_region(FILE* fp, Region region); + #endif /* REGION_H */ diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index cbf2c4af06b..9d14bb29afb 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,4 +1,5 @@ #include "vpr_constraints.h" +#include "partition.h" void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { constrained_atoms.insert({blk_id, part_id}); @@ -57,3 +58,32 @@ PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { pr = partitions[part_id].get_part_region(); return pr; } + +void print_constraints(FILE* fp, VprConstraints constraints) { + Partition temp_part; + std::vector atoms; + + int num_parts = constraints.get_num_partitions(); + + fprintf(fp, "\n Number of partitions is %d \n", num_parts); + + for (int i = 0; i < num_parts; i++) { + PartitionId part_id(i); + + temp_part = constraints.get_partition(part_id); + + fprintf(fp, "\npartition_id: %zu\n", size_t(part_id)); + print_partition(fp, temp_part); + + atoms = constraints.get_part_atoms(part_id); + + int atoms_size = atoms.size(); + + 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]; + 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 1a079dd857a..14ebfee7552 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -99,4 +99,7 @@ class VprConstraints { vtr::vector partitions; }; +///@brief used to print data from a VprConstraints object +void print_constraints(FILE* fp, VprConstraints constraints); + #endif /* VPR_CONSTRAINTS_H */ diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index ded837408b4..e42ef567811 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -574,8 +574,9 @@ std::map do_clustering(const t_packer_opts& pa VTR_LOGV(verbosity > 2, "Complex block %d:\n", num_clb); - /*this temp structure is used to store updates to the cluster's - * floorplanning constraints before they are stored long-term*/ + /*Used to store cluster's PartitionRegion as primitives are added to it. + * Since some of the primitives might fail legality, this structure temporarily + * stores PartitionRegion information while the cluster is packed*/ PartitionRegion temp_cluster_pr; start_new_cluster(cluster_placement_stats, primitives_list, @@ -2641,7 +2642,7 @@ static void echo_clusters(char* filename) { } } - fprintf(fp, "\nCLUSTER CONSTRAINTS:\n"); + fprintf(fp, "\nCluster Floorplanning Constraints:\n"); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); for (ClusterBlockId clb_id : cluster_ctx.clb_nlist.blocks()) { @@ -2649,19 +2650,7 @@ static void echo_clusters(char* filename) { if (reg.size() != 0) { fprintf(fp, "\nRegions in Cluster %zu:\n", size_t(clb_id)); for (unsigned int i = 0; i < reg.size(); i++) { - vtr::Rect rect = reg[i].get_region_rect(); - int xmin = rect.xmin(); - int xmax = rect.xmax(); - int ymin = rect.ymin(); - int ymax = rect.ymax(); - int subtile = reg[i].get_sub_tile(); - - fprintf(fp, "\tRegion: \n"); - fprintf(fp, "\txmin: %d\n", xmin); - fprintf(fp, "\tymin: %d\n", ymin); - fprintf(fp, "\txmax: %d\n", xmax); - fprintf(fp, "\tymax: %d\n", ymax); - fprintf(fp, "\tsubtile: %d\n\n", subtile); + print_region(fp, reg[i]); } } } From cfb812fc8582017986ed13e7b604a436757b09b9 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Fri, 12 Feb 2021 12:38:12 -0500 Subject: [PATCH 22/25] Comment update for print_constraints function --- vpr/src/base/vpr_constraints.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 14ebfee7552..689fcdca1c2 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -99,7 +99,8 @@ class VprConstraints { vtr::vector partitions; }; -///@brief used to print data from a VprConstraints object +///@brief used to print floorplanning constraints data from a VprConstraints object void print_constraints(FILE* fp, VprConstraints constraints); + #endif /* VPR_CONSTRAINTS_H */ From e2a7bfc949b2f15fcaa384bce4f4023eb55fec65 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Fri, 12 Feb 2021 12:44:13 -0500 Subject: [PATCH 23/25] Updated comment for echo_constraints function --- vpr/src/base/constraints_load.h | 1 + vpr/src/base/vpr_constraints.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/constraints_load.h b/vpr/src/base/constraints_load.h index 6c2d53feda7..d7a79308e55 100644 --- a/vpr/src/base/constraints_load.h +++ b/vpr/src/base/constraints_load.h @@ -7,6 +7,7 @@ #include "vpr_constraints.h" #include "vtr_vector.h" +///@brief Used to print vpr's floorplanning constraints to an echo file "vpr_constraints.echo" void echo_constraints(char* filename, VprConstraints constraints); #endif diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 689fcdca1c2..062a7c9e689 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -102,5 +102,4 @@ class VprConstraints { ///@brief used to print floorplanning constraints data from a VprConstraints object void print_constraints(FILE* fp, VprConstraints constraints); - #endif /* VPR_CONSTRAINTS_H */ From d2d6fcb563a3a7200daa0004fd2afb21b955e961 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Fri, 26 Feb 2021 10:23:10 -0500 Subject: [PATCH 24/25] Updated PartitionRegion class comment --- vpr/src/base/partition_region.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index b7fd9720ee4..e3b59d1e2b3 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -6,7 +6,7 @@ /** * @file - * @brief This file defines the PartitionRegions class. The PartitionRegions class is used to store the union + * @brief This file defines the PartitionRegion class. The PartitionRegion class is used to store the union * of regions that a partition can be placed in. */ From 8c5bc25b1e579e7b8951ffb5951e9ed61d71efe3 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Fri, 26 Feb 2021 10:30:53 -0500 Subject: [PATCH 25/25] Ran make format to fix formatting in vtr geometry file --- libs/libvtrutil/src/vtr_geometry.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 7e01a4943c2..ed500eb325f 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -208,7 +208,6 @@ Rect bounding_box(const Rect& lhs, const Rect& rhs); template Rect intersection(const Rect& lhs, const Rect& rhs); - //Prints a rectangle template static void print_rect(FILE* fp, const Rect rect);