diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index a06a155e038..e7d2fbaace3 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -351,8 +351,10 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a fflush(stdout); - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); + auto& device_ctx = g_vpr_ctx.mutable_device(); helper_ctx.lb_type_rr_graphs = vpr_setup->PackerRRGraph; + device_ctx.pad_loc_type = vpr_setup->PlacerOpts.pad_loc_type; } bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) { @@ -390,7 +392,7 @@ bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) { //clean packing-placement data if (vpr_setup.PackerOpts.doPacking == STAGE_DO) { - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); free_cluster_placement_stats(helper_ctx.cluster_placement_stats); } diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index ca4ed41bdee..eee43e6feaa 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -56,17 +56,33 @@ struct AtomContext : public Context { /******************************************************************** * Atom Netlist ********************************************************************/ + /** + * @brief constructor + * + * In the constructor initialize the list of pack molecules to nullptr and defines a custom deletor for it + */ AtomContext() : list_of_pack_molecules(nullptr, free_pack_molecules) {} + ///@brief Atom netlist AtomNetlist nlist; ///@brief Mappings to/from the Atom Netlist to physically described .blif models AtomLookup lookup; - ///@brief The molecules associated with each atom block + /** + * @brief The molecules associated with each atom block. + * + * This map is loaded in the pre-packing stage and freed at the very end of vpr flow run. + * The pointers in this multimap is shared with list_of_pack_molecules. + */ std::multimap atom_molecules; + /** + * @brief A linked list of all the packing molecules that are loaded in pre-packing stage. + * + * Is is useful in freeing the pack molecules at the destructor of the Atom context using free_pack_molecules. + */ std::unique_ptr list_of_pack_molecules; }; @@ -219,6 +235,11 @@ struct DeviceContext : public Context { * Used to determine when reading rrgraph if file is already loaded. */ std::string read_rr_graph_filename; + + /******************************************************************* + * Place Related + *******************************************************************/ + enum e_pad_loc_type pad_loc_type; }; /** @@ -266,23 +287,40 @@ struct ClusteringContext : public Context { */ std::map> post_routing_clb_pin_nets; std::map> pre_routing_net_pin_mapping; - - std::map num_used_type_instances; }; +/** + * @brief State relating to helper data structure using in the clustering stage + * + * This should contain helper data structures that are useful in the clustering/packing stage. + * They are encapsulated here as they are useful in clustering and reclustering algorithms that may be used + * in packing or placement stages. + */ struct ClusteringHelperContext : public Context { + // A map used to save the number of used instances from each logical block type. std::map num_used_type_instances; + + // Stats keeper for placement information during packing/clustering t_cluster_placement_stats* cluster_placement_stats; + + // total number of models in the architecture int num_models; + int max_cluster_size; t_pb_graph_node** primitives_list; bool enable_pin_feasibility_filter; int feasible_block_array_size; + // total number of CLBs int total_clb_num; + + // A vector of routing resource nodes within each of logic cluster_ctx.blocks types [0 .. num_logical_block_type-1] std::vector* lb_type_rr_graphs; + // the utilization of external input/output pins during packing (between 0 and 1) + t_ext_pin_util_targets target_external_pin_util; + ~ClusteringHelperContext() { free(primitives_list); } @@ -494,8 +532,8 @@ class VprContext : public Context { const ClusteringContext& clustering() const { return clustering_; } ClusteringContext& mutable_clustering() { return clustering_; } - const ClusteringHelperContext& helper() const { return helper_; } - ClusteringHelperContext& mutable_helper() { return helper_; } + const ClusteringHelperContext& cl_helper() const { return helper_; } + ClusteringHelperContext& mutable_cl_helper() { return helper_; } const PlacementContext& placement() const { return placement_; } PlacementContext& mutable_placement() { return placement_; } diff --git a/vpr/src/base/vpr_types.cpp b/vpr/src/base/vpr_types.cpp index 5b74779893e..c92e8966de8 100644 --- a/vpr/src/base/vpr_types.cpp +++ b/vpr/src/base/vpr_types.cpp @@ -263,4 +263,4 @@ void free_cluster_placement_stats(t_cluster_placement_stats* cluster_placement_s free(cluster_placement_stats_list[index].valid_primitives); } free(cluster_placement_stats_list); -} \ No newline at end of file +} diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 1f0db609fa4..2e3c0da6026 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1690,7 +1690,14 @@ typedef vtr::vector>> t_clb_opins_u typedef std::vector> t_arch_switch_fanin; +/** + * @brief Free the linked list that saves all the packing molecules. + */ void free_pack_molecules(t_pack_molecule* list_of_pack_molecules); + +/** + * @brief Free the linked lists to placement locations based on status of primitive inside placement stats data structure. + */ void free_cluster_placement_stats(t_cluster_placement_stats* cluster_placement_stats); #endif diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index b7804c6e2bd..8cac315cdab 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -147,7 +147,7 @@ std::map do_clustering(const t_packer_opts& pa auto& atom_ctx = g_vpr_ctx.atom(); auto& device_ctx = g_vpr_ctx.mutable_device(); auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); helper_ctx.enable_pin_feasibility_filter = packer_opts.enable_pin_feasibility_filter; helper_ctx.feasible_block_array_size = packer_opts.feasible_block_array_size; diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index cdad7f16bf8..b53cc453586 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -14,6 +14,11 @@ #include "tatum/echo_writer.hpp" #include "tatum/TimingReporter.hpp" +/** + * @file + * @brief This file includes useful structs and functions for building and modifying clustering + */ + #define AAPACK_MAX_HIGH_FANOUT_EXPLORE 10 /* For high-fanout nets that are ignored, consider a maximum of this many sinks, must be less than packer_opts.feasible_block_array_size */ #define AAPACK_MAX_TRANSITIVE_EXPLORE 40 /* When investigating transitive fanout connections in packing, consider a maximum of this many molecules, must be less than packer_opts.feasible_block_array_size */ @@ -74,7 +79,7 @@ struct t_cluster_progress_stats { int num_unrelated_clustering_attempts = 0; }; -/* Useful data structures for packing */ +/* Useful data structures for creating or modifying clusters */ struct t_clustering_data { vtr::vector*> intra_lb_routing; int* hill_climbing_inputs_avail; @@ -85,6 +90,7 @@ struct t_clustering_data { * list of blocks with i inputs to be hooked up via external interconnect. */ t_molecule_link* unclustered_list_head = nullptr; + //Maintaining a linked list of free molecule data for speed t_molecule_link* memory_pool = nullptr; /* Does the atom block that drives the output of this atom net also appear as a * diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 6979f8e1fce..d37ea55df25 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -42,7 +42,7 @@ bool try_pack(t_packer_opts* packer_opts, const t_model* library_models, float interc_delay, std::vector* lb_type_rr_graphs) { - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); std::unordered_set is_clock; std::unordered_map expected_lowest_cost_pb_gnode; //The molecules associated with each atom block @@ -113,10 +113,10 @@ bool try_pack(t_packer_opts* packer_opts, VTR_LOG("Using inter-cluster delay: %g\n", packer_opts->inter_cluster_net_delay); } - t_ext_pin_util_targets target_external_pin_util = parse_target_external_pin_util(packer_opts->target_external_pin_util); + helper_ctx.target_external_pin_util = parse_target_external_pin_util(packer_opts->target_external_pin_util); t_pack_high_fanout_thresholds high_fanout_thresholds = parse_high_fanout_thresholds(packer_opts->high_fanout_threshold); - VTR_LOG("Packing with pin utilization targets: %s\n", target_external_pin_util_to_string(target_external_pin_util).c_str()); + VTR_LOG("Packing with pin utilization targets: %s\n", target_external_pin_util_to_string(helper_ctx.target_external_pin_util).c_str()); VTR_LOG("Packing with high fanout thresholds: %s\n", high_fanout_thresholds_to_string(high_fanout_thresholds).c_str()); bool allow_unrelated_clustering = false; @@ -149,7 +149,7 @@ bool try_pack(t_packer_opts* packer_opts, allow_unrelated_clustering, balance_block_type_util, lb_type_rr_graphs, - target_external_pin_util, + helper_ctx.target_external_pin_util, high_fanout_thresholds, attraction_groups, floorplan_regions_overfull, @@ -211,7 +211,7 @@ bool try_pack(t_packer_opts* packer_opts, VTR_LOG("Pack iteration is %d\n", pack_iteration); attraction_groups.set_att_group_pulls(4); t_ext_pin_util pin_util(1.0, 1.0); - target_external_pin_util.set_block_pin_util("clb", pin_util); + helper_ctx.target_external_pin_util.set_block_pin_util("clb", pin_util); } } else { diff --git a/vpr/src/pack/prepack.h b/vpr/src/pack/prepack.h index 83e20e25b40..de29a40436b 100644 --- a/vpr/src/pack/prepack.h +++ b/vpr/src/pack/prepack.h @@ -18,5 +18,4 @@ void free_pack_pattern(t_pack_patterns* pack_pattern); t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_pack_patterns, std::unordered_map& expected_lowest_cost_pb_gnode, const int num_packing_patterns); - #endif diff --git a/vpr/src/pack/re_cluster.cpp b/vpr/src/pack/re_cluster.cpp index 26ad1b04f68..1bf123bcc52 100644 --- a/vpr/src/pack/re_cluster.cpp +++ b/vpr/src/pack/re_cluster.cpp @@ -1,23 +1,26 @@ #include "re_cluster.h" #include "re_cluster_util.h" +#include "initial_placement.h" +#include "cluster_placement.h" +#include "cluster_router.h" -bool move_atom_to_new_cluster(const AtomBlockId& atom_id, - const enum e_pad_loc_type& pad_loc_type, - std::vector* lb_type_rr_graphs, - t_clustering_data& clustering_data, - bool during_packing) { +bool move_mol_to_new_cluster(t_pack_molecule* molecule, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data) { auto& cluster_ctx = g_vpr_ctx.clustering(); - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); auto& device_ctx = g_vpr_ctx.device(); bool is_removed, is_created; - ClusterBlockId old_clb; + ClusterBlockId old_clb = atom_to_cluster(molecule->atom_block_ids[molecule->root]); + int molecule_size = get_array_size_of_molecule(molecule); + PartitionRegion temp_cluster_pr; - int imacro; + t_lb_router_data* old_router_data = nullptr; t_lb_router_data* router_data = nullptr; //Check that there is a place for a new cluster of the same type - old_clb = atom_to_cluster(atom_id); t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(old_clb); int block_mode = cluster_ctx.clb_nlist.block_pb(old_clb)->mode; @@ -27,45 +30,192 @@ bool move_atom_to_new_cluster(const AtomBlockId& atom_id, } if (helper_ctx.num_used_type_instances[block_type] == num_instances) { - VTR_LOG("The utilization of block_type %s is 100%. No space for new clusters\n", block_type->name); - VTR_LOG("Atom %d move aborted\n", atom_id); + VTR_LOGV(verbosity > 4, "The utilization of block_type %s is 100%. No space for new clusters\n", block_type->name); + VTR_LOGV(verbosity > 4, "Atom %d move aborted\n", molecule->atom_block_ids[molecule->root]); return false; } - //remove the atom from its current cluster and check its legality - is_removed = remove_atom_from_cluster(atom_id, lb_type_rr_graphs, old_clb, clustering_data, imacro, during_packing); - if (!is_removed) { - VTR_LOG("Atom: %zu move failed. Can't remove it from the old cluster\n", atom_id); - return (is_removed); + //remove the molecule from its current cluster + std::vector old_clb_atoms = cluster_to_atoms(old_clb); + if (old_clb_atoms.size() == 1) { + VTR_LOGV(verbosity > 4, "Atom: %zu move failed. This is the last atom in its cluster.\n"); + return false; + } + remove_mol_from_cluster(molecule, molecule_size, old_clb, old_clb_atoms, old_router_data); + + //check old cluster legality after removing the molecule + is_removed = is_cluster_legal(old_router_data); + + //if the cluster is legal, commit the molecule removal. Otherwise, abort the move + if (is_removed) { + commit_mol_removal(molecule, molecule_size, old_clb, during_packing, old_router_data, clustering_data); + } else { + VTR_LOGV(verbosity > 4, "Atom: %zu move failed. Can't remove it from the old cluster\n", molecule->atom_block_ids[molecule->root]); + return false; } //Create new cluster of the same type and mode. ClusterBlockId new_clb(helper_ctx.total_clb_num); - is_created = start_new_cluster_for_atom(atom_id, - pad_loc_type, - block_type, - block_mode, - helper_ctx.feasible_block_array_size, - imacro, - helper_ctx.enable_pin_feasibility_filter, - new_clb, - &router_data, - lb_type_rr_graphs, - temp_cluster_pr, - clustering_data, - during_packing); - - //Print the move result - if (is_created) - VTR_LOG("Atom:%zu is moved to a new cluster\n", atom_id); - else - VTR_LOG("Atom:%zu move failed. Can't start a new cluster of the same type and mode\n", atom_id); + is_created = start_new_cluster_for_mol(molecule, + block_type, + block_mode, + helper_ctx.feasible_block_array_size, + helper_ctx.enable_pin_feasibility_filter, + new_clb, + during_packing, + verbosity, + clustering_data, + &router_data, + temp_cluster_pr); + + //Commit or revert the move + if (is_created) { + commit_mol_move(old_clb, new_clb, during_packing, true); + VTR_LOGV(verbosity > 4, "Atom:%zu is moved to a new cluster\n", molecule->atom_block_ids[molecule->root]); + } else { + revert_mol_move(old_clb, molecule, old_router_data, during_packing, clustering_data); + VTR_LOGV(verbosity > 4, "Atom:%zu move failed. Can't start a new cluster of the same type and mode\n", molecule->atom_block_ids[molecule->root]); + } + + free_router_data(old_router_data); + old_router_data = nullptr; //If the move is done after packing not during it, some fixes need to be done on the //clustered netlist if (is_created && !during_packing) { - fix_clustered_netlist(atom_id, old_clb, new_clb); + fix_clustered_netlist(molecule, molecule_size, old_clb, new_clb); } return (is_created); } + +bool move_mol_to_existing_cluster(t_pack_molecule* molecule, + const ClusterBlockId& new_clb, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data) { + //define local variables + bool is_removed, is_added; + AtomBlockId root_atom_id = molecule->atom_block_ids[molecule->root]; + int molecule_size = get_array_size_of_molecule(molecule); + t_lb_router_data* old_router_data = nullptr; + std::vector new_clb_atoms = cluster_to_atoms(new_clb); + ClusterBlockId old_clb = atom_to_cluster(root_atom_id); + + //check old and new clusters compitability + bool is_compitable = check_type_and_mode_compitability(old_clb, new_clb, verbosity); + if (!is_compitable) + return false; + + //remove the molecule from its current cluster + std::vector old_clb_atoms = cluster_to_atoms(old_clb); + if (old_clb_atoms.size() == 1) { + VTR_LOGV(verbosity > 4, "Atom: %zu move failed. This is the last atom in its cluster.\n"); + return false; + } + remove_mol_from_cluster(molecule, molecule_size, old_clb, old_clb_atoms, old_router_data); + + //check old cluster legality after removing the molecule + is_removed = is_cluster_legal(old_router_data); + + //if the cluster is legal, commit the molecule removal. Otherwise, abort the move + if (is_removed) { + commit_mol_removal(molecule, molecule_size, old_clb, during_packing, old_router_data, clustering_data); + } else { + VTR_LOGV(verbosity > 4, "Atom: %zu move failed. Can't remove it from the old cluster\n", root_atom_id); + return false; + } + + //Add the atom to the new cluster + t_lb_router_data* new_router_data = nullptr; + is_added = pack_mol_in_existing_cluster(molecule, new_clb, new_clb_atoms, during_packing, false, clustering_data, new_router_data); + + //Commit or revert the move + if (is_added) { + commit_mol_move(old_clb, new_clb, during_packing, false); + VTR_LOGV(verbosity > 4, "Atom:%zu is moved to a new cluster\n", molecule->atom_block_ids[molecule->root]); + } else { + revert_mol_move(old_clb, molecule, old_router_data, during_packing, clustering_data); + VTR_LOGV(verbosity > 4, "Atom:%zu move failed. Can't start a new cluster of the same type and mode\n", molecule->atom_block_ids[molecule->root]); + } + + free_router_data(old_router_data); + old_router_data = nullptr; + + //If the move is done after packing not during it, some fixes need to be done on the + //clustered netlist + if (is_added && !during_packing) { + fix_clustered_netlist(molecule, molecule_size, old_clb, new_clb); + } + + return (is_added); +} + +#if 1 +bool swap_two_molecules(t_pack_molecule* molecule_1, + t_pack_molecule* molecule_2, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data) { + //define local variables + PartitionRegion temp_cluster_pr_1, temp_cluster_pr_2; + + bool mol_1_success, mol_2_success; + + AtomBlockId root_1_atom_id = molecule_1->atom_block_ids[molecule_1->root]; + AtomBlockId root_2_atom_id = molecule_2->atom_block_ids[molecule_2->root]; + + int molecule_1_size = get_array_size_of_molecule(molecule_1); + int molecule_2_size = get_array_size_of_molecule(molecule_2); + + //Check that the 2 clusters are the same type + ClusterBlockId clb_1 = atom_to_cluster(root_1_atom_id); + ClusterBlockId clb_2 = atom_to_cluster(root_2_atom_id); + + //Check that the old and new clusters are of the same type + bool is_compitable = check_type_and_mode_compitability(clb_1, clb_2, verbosity); + if (!is_compitable) + return false; + + t_lb_router_data* old_1_router_data = nullptr; + t_lb_router_data* old_2_router_data = nullptr; + + //save the atoms of the 2 clusters + std::vector clb_1_atoms = cluster_to_atoms(clb_1); + std::vector clb_2_atoms = cluster_to_atoms(clb_2); + + if (clb_1_atoms.size() == 1 || clb_2_atoms.size() == 1) { + VTR_LOGV(verbosity > 4, "Atom: %zu, %zu swap failed. This is the last atom in its cluster.\n", molecule_1->atom_block_ids[molecule_1->root], molecule_2->atom_block_ids[molecule_2->root]); + return false; + } + + //remove the molecule from its current cluster + remove_mol_from_cluster(molecule_1, molecule_1_size, clb_1, clb_1_atoms, old_1_router_data); + commit_mol_removal(molecule_1, molecule_1_size, clb_1, during_packing, old_1_router_data, clustering_data); + + remove_mol_from_cluster(molecule_2, molecule_2_size, clb_2, clb_2_atoms, old_2_router_data); + commit_mol_removal(molecule_2, molecule_2_size, clb_2, during_packing, old_2_router_data, clustering_data); + + //Add the atom to the new cluster + mol_1_success = pack_mol_in_existing_cluster(molecule_1, clb_2, clb_2_atoms, during_packing, true, clustering_data, old_2_router_data); + mol_2_success = pack_mol_in_existing_cluster(molecule_2, clb_1, clb_1_atoms, during_packing, true, clustering_data, old_1_router_data); + + //commit the move if succeeded or revert if failed + if (mol_1_success && mol_2_success) { + VTR_LOGV(verbosity > 4, "Molecules swap is performed successfully\n"); + } else { + revert_mol_move(clb_1, molecule_1, old_1_router_data, during_packing, clustering_data); + revert_mol_move(clb_2, molecule_2, old_2_router_data, during_packing, clustering_data); + VTR_LOGV(verbosity > 4, "Molecules swap failed\n"); + } + + //If the move is done after packing not during it, some fixes need to be done on the clustered netlist + if (mol_1_success && mol_2_success && !during_packing) { + fix_clustered_netlist(molecule_1, molecule_1_size, clb_1, clb_2); + fix_clustered_netlist(molecule_2, molecule_2_size, clb_2, clb_1); + } + + //return the move result + return (mol_1_success && mol_2_success); +} +#endif diff --git a/vpr/src/pack/re_cluster.h b/vpr/src/pack/re_cluster.h index af6a53703f1..5ca2489aac4 100644 --- a/vpr/src/pack/re_cluster.h +++ b/vpr/src/pack/re_cluster.h @@ -15,16 +15,46 @@ #include "cluster_util.h" /** - * @brief This function moves an atom out of its cluster and create a new cluster for it + * @brief This function moves a molecule out of its cluster and creates a new cluster for it * * This function can be called from 2 spots in the vpr flow. * - First, during packing to optimize the initial clustered netlist * (during_packing variable should be true.) - * - Second, during placement (during_packing variable should be false) + * - Second, during placement (during_packing variable should be false). In this case, the clustered + * netlist is updated. */ -bool move_atom_to_new_cluster(const AtomBlockId& atom_id, - const enum e_pad_loc_type& pad_loc_type, - std::vector* lb_type_rr_graphs, - t_clustering_data& clustering_data, - bool during_packing); -#endif \ No newline at end of file +bool move_mol_to_new_cluster(t_pack_molecule* molecule, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data); + +/** + * @brief This function moves a molecule out of its cluster to another cluster that already exists. + * + * This function can be called from 2 spots in the vpr flow. + * - First, during packing to optimize the initial clustered netlist + * (during_packing variable should be true.) + * - Second, during placement (during_packing variable should be false). In this case, the clustered + * netlist is updated. + */ +bool move_mol_to_existing_cluster(t_pack_molecule* molecule, + const ClusterBlockId& new_clb, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data); + +/** + * @brief This function swap two molecules between two different clusters. + * + * This function can be called from 2 spots in the vpr flow. + * - First, during packing to optimize the initial clustered netlist + * (during_packing variable should be true.) + * - Second, during placement (during_packing variable should be false). In this case, the clustered + * netlist is updated. + */ +bool swap_two_molecules(t_pack_molecule* molecule_1, + t_pack_molecule* molecule_2, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data); +#endif diff --git a/vpr/src/pack/re_cluster_util.cpp b/vpr/src/pack/re_cluster_util.cpp index 102030bedd1..a71779dc433 100644 --- a/vpr/src/pack/re_cluster_util.cpp +++ b/vpr/src/pack/re_cluster_util.cpp @@ -17,7 +17,7 @@ const char* name_suffix = "_m"; //static void set_atom_pin_mapping(const ClusteredNetlist& clb_nlist, const AtomBlockId atom_blk, const AtomPortId atom_port, const t_pb_graph_pin* gpin); static void load_atom_index_for_pb_pin(t_pb_routes& pb_route, int ipin); static void load_internal_to_block_net_nums(const t_logical_block_type_ptr type, t_pb_routes& pb_route); -static bool count_children_pbs(const t_pb* pb); +//static bool count_children_pbs(const t_pb* pb); static void fix_atom_pin_mapping(const AtomBlockId blk); static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index); @@ -30,10 +30,17 @@ static void check_net_absorbtion(const AtomNetId atom_net_id, static void fix_cluster_port_after_moving(const ClusterBlockId clb_index); -static void fix_cluster_net_after_moving(const AtomBlockId& atom_id, +static void fix_cluster_net_after_moving(const t_pack_molecule* molecule, + int molecule_size, const ClusterBlockId& old_clb, const ClusterBlockId& new_clb); +static void rebuild_cluster_placemet_stats(const ClusterBlockId& clb_index, + const std::vector& clb_atoms, + int type_idx, + int mode); + +/***************** API functions ***********************/ ClusterBlockId atom_to_cluster(const AtomBlockId& atom) { auto& atom_ctx = g_vpr_ctx.atom(); return (atom_ctx.lookup.atom_clb(atom)); @@ -44,113 +51,71 @@ std::vector cluster_to_atoms(const ClusterBlockId& cluster) { return (cluster_lookup.atoms_in_cluster(cluster)); } -bool remove_atom_from_cluster(const AtomBlockId& atom_id, - std::vector* lb_type_rr_graphs, - ClusterBlockId& old_clb, - t_clustering_data& clustering_data, - int& imacro, - bool during_packing) { - auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); - auto& atom_ctx = g_vpr_ctx.mutable_atom(); - - //Determine the cluster ID - old_clb = atom_to_cluster(atom_id); +void remove_mol_from_cluster(const t_pack_molecule* molecule, + int molecule_size, + ClusterBlockId& old_clb, + std::vector& old_clb_atoms, + t_lb_router_data*& router_data) { + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); //re-build router_data structure for this cluster - t_lb_router_data* router_data = lb_load_router_data(lb_type_rr_graphs, old_clb); + router_data = lb_load_router_data(helper_ctx.lb_type_rr_graphs, old_clb, old_clb_atoms); //remove atom from router_data - remove_atom_from_target(router_data, atom_id); - - //check cluster legality - bool is_cluster_legal = check_cluster_legality(0, E_DETAILED_ROUTE_AT_END_ONLY, router_data); - - if (is_cluster_legal) { - t_pb* temp = const_cast(atom_ctx.lookup.atom_pb(atom_id)); - t_pb* next = temp->parent_pb; - //char* atom_name = vtr::strdup(temp->name); - bool has_more_children; - - revert_place_atom_block(atom_id, router_data); - //delete atom pb - cleanup_pb(temp); - - has_more_children = count_children_pbs(next); - //keep deleting the parent pbs if they were created only for the removed atom - while (!has_more_children) { - temp = next; - next = next->parent_pb; - cleanup_pb(temp); - has_more_children = count_children_pbs(next); - } - - //if the parents' names are the same as the removed atom names, - //update the name to prevent double the name when creating a new cluster for - // the removed atom - /* - * while(next != nullptr && *(next->name) == *atom_name) { - * next->name = vtr::strdup(child_name); - * if(next->parent_pb == nullptr) - * next = next->parent_pb; - * } - */ - - cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route.clear(); - cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route = alloc_and_load_pb_route(router_data->saved_lb_nets, cluster_ctx.clb_nlist.block_pb(old_clb)->pb_graph_node); - - if (during_packing) { - clustering_data.intra_lb_routing[old_clb] = router_data->saved_lb_nets; - router_data->saved_lb_nets = nullptr; + for (int i_atom = 0; i_atom < molecule_size; i_atom++) { + if (molecule->atom_block_ids[i_atom]) { + remove_atom_from_target(router_data, molecule->atom_block_ids[i_atom]); + old_clb_atoms.erase(std::remove(old_clb_atoms.begin(), old_clb_atoms.end(), molecule->atom_block_ids[i_atom])); } - - else - get_imacro_from_iblk(&imacro, old_clb, g_vpr_ctx.placement().pl_macros); - } else { - VTR_LOG("re-cluster: Cluster is illegal after removing an atom\n"); } +} - free_router_data(router_data); - router_data = nullptr; - - //return true if succeeded - return (is_cluster_legal); +void commit_mol_move(const ClusterBlockId& old_clb, + const ClusterBlockId& new_clb, + bool during_packing, + bool new_clb_created) { + auto& device_ctx = g_vpr_ctx.device(); + + //Place the new cluster if this function called during placement (after the initial placement is done) + if (!during_packing && new_clb_created) { + int imacro; + g_vpr_ctx.mutable_placement().block_locs.resize(g_vpr_ctx.placement().block_locs.size() + 1); + get_imacro_from_iblk(&imacro, old_clb, g_vpr_ctx.placement().pl_macros); + set_imacro_for_iblk(&imacro, new_clb); + place_one_block(new_clb, device_ctx.pad_loc_type); + } } -t_lb_router_data* lb_load_router_data(std::vector* lb_type_rr_graphs, const ClusterBlockId& clb_index) { +t_lb_router_data* lb_load_router_data(std::vector* lb_type_rr_graphs, const ClusterBlockId& clb_index, const std::vector& clb_atoms) { //build data structures used by intra-logic block router auto& cluster_ctx = g_vpr_ctx.clustering(); auto block_type = cluster_ctx.clb_nlist.block_type(clb_index); t_lb_router_data* router_data = alloc_and_load_router_data(&lb_type_rr_graphs[block_type->index], block_type); //iterate over atoms of the current cluster and add them to router data - for (auto atom_id : cluster_to_atoms(clb_index)) { + for (auto atom_id : clb_atoms) { add_atom_as_target(router_data, atom_id); } return (router_data); } -bool start_new_cluster_for_atom(const AtomBlockId atom_id, - const enum e_pad_loc_type& pad_loc_type, - const t_logical_block_type_ptr& type, - const int mode, - const int feasible_block_array_size, - int& imacro, - bool enable_pin_feasibility_filter, - ClusterBlockId clb_index, - t_lb_router_data** router_data, - std::vector* lb_type_rr_graphs, - PartitionRegion& temp_cluster_pr, - t_clustering_data& clustering_data, - bool during_packing) { +bool start_new_cluster_for_mol(t_pack_molecule* molecule, + const t_logical_block_type_ptr& type, + const int mode, + const int feasible_block_array_size, + bool enable_pin_feasibility_filter, + ClusterBlockId clb_index, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data, + t_lb_router_data** router_data, + PartitionRegion& temp_cluster_pr) { auto& atom_ctx = g_vpr_ctx.atom(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - auto& helper_ctx = g_vpr_ctx.mutable_helper(); + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); - t_pack_molecule* molecule = atom_ctx.atom_molecules.find(atom_id)->second; - int verbosity = 0; - - /*Cluster's PartitionRegion is empty initially, meaning it has no floorplanning constraints*/ + /* Cluster's PartitionRegion is empty initially, meaning it has no floorplanning constraints */ PartitionRegion empty_pr; floorplanning_ctx.cluster_constraints.push_back(empty_pr); @@ -164,7 +129,7 @@ bool start_new_cluster_for_atom(const AtomBlockId atom_id, alloc_and_load_pb_stats(pb, feasible_block_array_size); pb->parent_pb = nullptr; - *router_data = alloc_and_load_router_data(&lb_type_rr_graphs[type->index], type); + *router_data = alloc_and_load_router_data(&(helper_ctx.lb_type_rr_graphs[type->index]), type); e_block_pack_status pack_result = BLK_STATUS_UNDEFINED; pb->mode = mode; @@ -188,7 +153,7 @@ bool start_new_cluster_for_atom(const AtomBlockId atom_id, // If clustering succeeds, add it to the clb netlist if (pack_result == BLK_PASSED) { - VTR_LOGV(verbosity > 2, "\tPASSED_SEED: Block Type %s\n", type->name); + VTR_LOGV(verbosity > 4, "\tPASSED_SEED: Block Type %s\n", type->name); //Once clustering succeeds, add it to the clb netlist if (pb->name != nullptr) { free(pb->name); @@ -198,14 +163,12 @@ bool start_new_cluster_for_atom(const AtomBlockId atom_id, clb_index = cluster_ctx.clb_nlist.create_block(new_name.c_str(), pb, type); helper_ctx.total_clb_num++; + //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. if (during_packing) { clustering_data.intra_lb_routing.push_back((*router_data)->saved_lb_nets); (*router_data)->saved_lb_nets = nullptr; } else { cluster_ctx.clb_nlist.block_pb(clb_index)->pb_route = alloc_and_load_pb_route((*router_data)->saved_lb_nets, cluster_ctx.clb_nlist.block_pb(clb_index)->pb_graph_node); - g_vpr_ctx.mutable_placement().block_locs.resize(g_vpr_ctx.placement().block_locs.size() + 1); - set_imacro_for_iblk(&imacro, clb_index); - place_one_block(clb_index, pad_loc_type); } } else { free_pb(pb); @@ -219,18 +182,119 @@ bool start_new_cluster_for_atom(const AtomBlockId atom_id, return (pack_result == BLK_PASSED); } -void fix_clustered_netlist(const AtomBlockId& atom_id, +bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, + const ClusterBlockId new_clb, + const std::vector& new_clb_atoms, + bool during_packing, + bool is_swap, + t_clustering_data& clustering_data, + t_lb_router_data*& router_data) { + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); + auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + + PartitionRegion temp_cluster_pr; + e_block_pack_status pack_result = BLK_STATUS_UNDEFINED; + t_ext_pin_util target_ext_pin_util = helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(new_clb)->name); + t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(new_clb); + t_pb* temp_pb = cluster_ctx.clb_nlist.block_pb(new_clb); + + //re-build cluster placement stats + rebuild_cluster_placemet_stats(new_clb, new_clb_atoms, cluster_ctx.clb_nlist.block_type(new_clb)->index, cluster_ctx.clb_nlist.block_pb(new_clb)->mode); + + //re-build router_data structure for this cluster + if (!is_swap) + router_data = lb_load_router_data(helper_ctx.lb_type_rr_graphs, new_clb, new_clb_atoms); + + pack_result = try_pack_molecule(&(helper_ctx.cluster_placement_stats[block_type->index]), + molecule, + helper_ctx.primitives_list, + temp_pb, + helper_ctx.num_models, + helper_ctx.max_cluster_size, + new_clb, + E_DETAILED_ROUTE_FOR_EACH_ATOM, + router_data, + 0, + //helper_ctx.enable_pin_feasibility_filter, + false, + helper_ctx.feasible_block_array_size, + target_ext_pin_util, + temp_cluster_pr); + + // If clustering succeeds, add it to the clb netlist + if (pack_result == BLK_PASSED) { + //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. + if (during_packing) { + free_intra_lb_nets(clustering_data.intra_lb_routing[new_clb]); + clustering_data.intra_lb_routing[new_clb] = router_data->saved_lb_nets; + router_data->saved_lb_nets = nullptr; + } else { + cluster_ctx.clb_nlist.block_pb(new_clb)->pb_route.clear(); + cluster_ctx.clb_nlist.block_pb(new_clb)->pb_route = alloc_and_load_pb_route(router_data->saved_lb_nets, cluster_ctx.clb_nlist.block_pb(new_clb)->pb_graph_node); + } + } + + if (pack_result == BLK_PASSED || !is_swap) { + //Free clustering router data + free_router_data(router_data); + router_data = nullptr; + } + + return (pack_result == BLK_PASSED); +} + +void fix_clustered_netlist(t_pack_molecule* molecule, + int molecule_size, const ClusterBlockId& old_clb, const ClusterBlockId& new_clb) { fix_cluster_port_after_moving(new_clb); - fix_cluster_net_after_moving(atom_id, old_clb, new_clb); + fix_cluster_net_after_moving(molecule, molecule_size, old_clb, new_clb); } +void revert_mol_move(const ClusterBlockId& old_clb, + t_pack_molecule* molecule, + t_lb_router_data*& old_router_data, + bool during_packing, + t_clustering_data& clustering_data) { + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); + auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + + PartitionRegion temp_cluster_pr_original; + e_block_pack_status pack_result = try_pack_molecule(&(helper_ctx.cluster_placement_stats[cluster_ctx.clb_nlist.block_type(old_clb)->index]), + molecule, + helper_ctx.primitives_list, + cluster_ctx.clb_nlist.block_pb(old_clb), + helper_ctx.num_models, + helper_ctx.max_cluster_size, + old_clb, + E_DETAILED_ROUTE_FOR_EACH_ATOM, + old_router_data, + 0, + helper_ctx.enable_pin_feasibility_filter, + helper_ctx.feasible_block_array_size, + helper_ctx.target_external_pin_util.get_pin_util(cluster_ctx.clb_nlist.block_type(old_clb)->name), + temp_cluster_pr_original); + + VTR_ASSERT(pack_result == BLK_PASSED); + //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. + if (during_packing) { + free_intra_lb_nets(clustering_data.intra_lb_routing[old_clb]); + clustering_data.intra_lb_routing[old_clb] = old_router_data->saved_lb_nets; + old_router_data->saved_lb_nets = nullptr; + } else { + cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route.clear(); + cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route = alloc_and_load_pb_route(old_router_data->saved_lb_nets, cluster_ctx.clb_nlist.block_pb(old_clb)->pb_graph_node); + } + + free_router_data(old_router_data); + old_router_data = nullptr; +} /*******************************************/ /************ static functions *************/ /*******************************************/ -static void fix_cluster_net_after_moving(const AtomBlockId& atom_id, +static void fix_cluster_net_after_moving(const t_pack_molecule* molecule, + int molecule_size, const ClusterBlockId& old_clb, const ClusterBlockId& new_clb) { auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); @@ -248,13 +312,17 @@ static void fix_cluster_net_after_moving(const AtomBlockId& atom_id, } //delete cluster nets that are no longer used - for (auto atom_pin : atom_ctx.nlist.block_pins(atom_id)) { - atom_net_id = atom_ctx.nlist.pin_net(atom_pin); - check_net_absorbtion(atom_net_id, new_clb, old_clb, cluster_pin, previously_absorbed, now_abosrbed); - - if (!previously_absorbed && now_abosrbed) { - cur_clb_net = cluster_ctx.clb_nlist.pin_net(cluster_pin); - cluster_ctx.clb_nlist.remove_net(cur_clb_net); + for (int i_atom = 0; i_atom < molecule_size; i_atom++) { + if (molecule->atom_block_ids[i_atom]) { + for (auto atom_pin : atom_ctx.nlist.block_pins(molecule->atom_block_ids[i_atom])) { + atom_net_id = atom_ctx.nlist.pin_net(atom_pin); + check_net_absorbtion(atom_net_id, new_clb, old_clb, cluster_pin, previously_absorbed, now_abosrbed); + + if (!previously_absorbed && now_abosrbed) { + cur_clb_net = cluster_ctx.clb_nlist.pin_net(cluster_pin); + cluster_ctx.clb_nlist.remove_net(cur_clb_net); + } + } } } @@ -313,13 +381,15 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { int num_output_ports = pb->pb_graph_node->num_output_ports; int num_clock_ports = pb->pb_graph_node->num_clock_ports; - int j, k, ipin, rr_node_index; + int iport, ipb_pin, ipin, rr_node_index; ipin = 0; - for (j = 0; j < num_input_ports; j++) { - ClusterPortId input_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[j].name); - for (k = 0; k < pb->pb_graph_node->num_input_pins[j]; k++) { - pb_graph_pin = &pb->pb_graph_node->input_pins[j][k]; + // iterating over input ports + for (iport = 0; iport < num_input_ports; iport++) { + ClusterPortId input_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[iport].name); + // iterating over physical block pins of each input port + for (ipb_pin = 0; ipb_pin < pb->pb_graph_node->num_input_pins[iport]; ipb_pin++) { + pb_graph_pin = &pb->pb_graph_node->input_pins[iport][ipb_pin]; rr_node_index = pb_graph_pin->pin_count_in_cluster; VTR_ASSERT(pb_graph_pin->pin_count_in_cluster == ipin); @@ -328,9 +398,9 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); - ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(input_port_id, (BitIndex)k); + ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(input_port_id, (BitIndex)ipb_pin); if (!cur_pin_id) - cluster_ctx.clb_nlist.create_pin(input_port_id, (BitIndex)k, clb_net_id, PinType::SINK, ipin); + cluster_ctx.clb_nlist.create_pin(input_port_id, (BitIndex)ipb_pin, clb_net_id, PinType::SINK, ipin); else cluster_ctx.clb_nlist.set_pin_net(cur_pin_id, PinType::SINK, clb_net_id); } @@ -340,10 +410,12 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { } } - for (j = 0; j < num_output_ports; j++) { - ClusterPortId output_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[num_input_ports + j].name); - for (k = 0; k < pb->pb_graph_node->num_output_pins[j]; k++) { - pb_graph_pin = &pb->pb_graph_node->output_pins[j][k]; + // iterating over output ports + for (iport = 0; iport < num_output_ports; iport++) { + ClusterPortId output_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[num_input_ports + iport].name); + // iterating over physical block pins of each output port + for (ipb_pin = 0; ipb_pin < pb->pb_graph_node->num_output_pins[iport]; ipb_pin++) { + pb_graph_pin = &pb->pb_graph_node->output_pins[iport][ipb_pin]; rr_node_index = pb_graph_pin->pin_count_in_cluster; VTR_ASSERT(pb_graph_pin->pin_count_in_cluster == ipin); @@ -352,11 +424,11 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); - ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(output_port_id, (BitIndex)k); + ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(output_port_id, (BitIndex)ipb_pin); AtomPinId atom_net_driver = atom_ctx.nlist.net_driver(atom_net_id); bool driver_is_constant = atom_ctx.nlist.pin_is_constant(atom_net_driver); if (!cur_pin_id) - cluster_ctx.clb_nlist.create_pin(output_port_id, (BitIndex)k, clb_net_id, PinType::DRIVER, ipin, driver_is_constant); + cluster_ctx.clb_nlist.create_pin(output_port_id, (BitIndex)ipb_pin, clb_net_id, PinType::DRIVER, ipin, driver_is_constant); else { cluster_ctx.clb_nlist.set_pin_net(cur_pin_id, PinType::DRIVER, clb_net_id); cluster_ctx.clb_nlist.set_pin_is_constant(cur_pin_id, driver_is_constant); @@ -369,10 +441,12 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { } } - for (j = 0; j < num_clock_ports; j++) { - ClusterPortId clock_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[num_input_ports + num_output_ports + j].name); - for (k = 0; k < pb->pb_graph_node->num_clock_pins[j]; k++) { - pb_graph_pin = &pb->pb_graph_node->clock_pins[j][k]; + // iterating over clock ports + for (iport = 0; iport < num_clock_ports; iport++) { + ClusterPortId clock_port_id = cluster_ctx.clb_nlist.find_port(clb_index, block_type->pb_type->ports[num_input_ports + num_output_ports + iport].name); + // iterating over physical block pins of each clock port + for (ipb_pin = 0; ipb_pin < pb->pb_graph_node->num_clock_pins[iport]; ipb_pin++) { + pb_graph_pin = &pb->pb_graph_node->clock_pins[iport][ipb_pin]; rr_node_index = pb_graph_pin->pin_count_in_cluster; VTR_ASSERT(pb_graph_pin->pin_count_in_cluster == ipin); @@ -381,9 +455,9 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); - ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(clock_port_id, (BitIndex)k); + ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(clock_port_id, (BitIndex)ipb_pin); if (!cur_pin_id) - cluster_ctx.clb_nlist.create_pin(clock_port_id, (BitIndex)k, clb_net_id, PinType::SINK, ipin); + cluster_ctx.clb_nlist.create_pin(clock_port_id, (BitIndex)ipb_pin, clb_net_id, PinType::SINK, ipin); else cluster_ctx.clb_nlist.set_pin_net(cur_pin_id, PinType::SINK, clb_net_id); } @@ -490,12 +564,11 @@ static void fix_atom_pin_mapping(const AtomBlockId blk) { static void load_internal_to_block_net_nums(const t_logical_block_type_ptr type, t_pb_routes& pb_route) { int num_pins = type->pb_graph_head->total_pb_pins; - for (int i = 0; i < num_pins; i++) { - if (!pb_route.count(i)) continue; + for (int ipb_pin = 0; ipb_pin < num_pins; ipb_pin++) { + if (!pb_route.count(ipb_pin)) continue; - //if (pb_route[i].driver_pb_pin_id != OPEN && !pb_route[i].atom_net_id) { - if (pb_route[i].driver_pb_pin_id != OPEN) { - load_atom_index_for_pb_pin(pb_route, i); + if (pb_route[ipb_pin].driver_pb_pin_id != OPEN) { + load_atom_index_for_pb_pin(pb_route, ipb_pin); } } } @@ -517,6 +590,7 @@ static void load_atom_index_for_pb_pin(t_pb_routes& pb_route, int ipin) { pb_route[driver].sink_pb_pin_ids.push_back(ipin); } +#if 0 static bool count_children_pbs(const t_pb* pb) { if (pb == nullptr) return 0; @@ -529,4 +603,87 @@ static bool count_children_pbs(const t_pb* pb) { } } return false; -} \ No newline at end of file +} +#endif + +static void rebuild_cluster_placemet_stats(const ClusterBlockId& clb_index, + const std::vector& clb_atoms, + int type_idx, + int mode) { + auto& helper_ctx = g_vpr_ctx.mutable_cl_helper(); + auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& atom_ctx = g_vpr_ctx.atom(); + + t_cluster_placement_stats* cluster_placement_stats = &(helper_ctx.cluster_placement_stats[type_idx]); + + reset_cluster_placement_stats(cluster_placement_stats); + set_mode_cluster_placement_stats(cluster_ctx.clb_nlist.block_pb(clb_index)->pb_graph_node, mode); + + std::set list_of_pb_atom_nodes; + t_cluster_placement_primitive* cur_cluster_placement_primitive; + + for (auto& atom_blk : clb_atoms) { + list_of_pb_atom_nodes.insert(atom_ctx.lookup.atom_pb(atom_blk)->pb_graph_node); + } + + for (int i = 0; i < cluster_placement_stats->num_pb_types; i++) { + cur_cluster_placement_primitive = cluster_placement_stats->valid_primitives[i]->next_primitive; + while (cur_cluster_placement_primitive != nullptr) { + if (list_of_pb_atom_nodes.find(cur_cluster_placement_primitive->pb_graph_node) != list_of_pb_atom_nodes.end()) { + cur_cluster_placement_primitive->valid = false; + } + cur_cluster_placement_primitive = cur_cluster_placement_primitive->next_primitive; + } + } +} + +bool is_cluster_legal(t_lb_router_data*& router_data) { + return (check_cluster_legality(0, E_DETAILED_ROUTE_AT_END_ONLY, router_data)); +} + +void commit_mol_removal(const t_pack_molecule* molecule, + const int& molecule_size, + const ClusterBlockId& old_clb, + bool during_packing, + t_lb_router_data*& router_data, + t_clustering_data& clustering_data) { + auto& cluster_ctx = g_vpr_ctx.mutable_clustering(); + + for (int i_atom = 0; i_atom < molecule_size; i_atom++) { + if (molecule->atom_block_ids[i_atom]) { + revert_place_atom_block(molecule->atom_block_ids[i_atom], router_data); + } + } + + cleanup_pb(cluster_ctx.clb_nlist.block_pb(old_clb)); + + //If you are still in packing, update the clustering data. Otherwise, update the clustered netlist. + if (during_packing) { + free_intra_lb_nets(clustering_data.intra_lb_routing[old_clb]); + clustering_data.intra_lb_routing[old_clb] = router_data->saved_lb_nets; + router_data->saved_lb_nets = nullptr; + } else { + cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route.clear(); + cluster_ctx.clb_nlist.block_pb(old_clb)->pb_route = alloc_and_load_pb_route(router_data->saved_lb_nets, cluster_ctx.clb_nlist.block_pb(old_clb)->pb_graph_node); + } +} + +bool check_type_and_mode_compitability(const ClusterBlockId& old_clb, + const ClusterBlockId& new_clb, + int verbosity) { + auto& cluster_ctx = g_vpr_ctx.clustering(); + + //Check that the old and new clusters are the same type + if (cluster_ctx.clb_nlist.block_type(old_clb) != cluster_ctx.clb_nlist.block_type(new_clb)) { + VTR_LOGV(verbosity > 4, "Move aborted. New and old cluster blocks are not of the same type"); + return false; + } + + //Check that the old and new clusters are the mode + if (cluster_ctx.clb_nlist.block_pb(old_clb)->mode != cluster_ctx.clb_nlist.block_pb(new_clb)->mode) { + VTR_LOGV(verbosity > 4, "Move aborted. New and old cluster blocks are not of the same mode"); + return false; + } + + return true; +} diff --git a/vpr/src/pack/re_cluster_util.h b/vpr/src/pack/re_cluster_util.h index 06c71be1f9b..89f12d960ab 100644 --- a/vpr/src/pack/re_cluster_util.h +++ b/vpr/src/pack/re_cluster_util.h @@ -20,7 +20,8 @@ */ /** - * @brief A function that returns the cluster ID of an atom ID + * @brief A function that returns the block ID in the clustered netlist + * from its ID in the atom netlist. */ ClusterBlockId atom_to_cluster(const AtomBlockId& atom); @@ -32,52 +33,121 @@ ClusterBlockId atom_to_cluster(const AtomBlockId& atom); std::vector cluster_to_atoms(const ClusterBlockId& cluster); /** - * @brief A function that loads the router data for a cluster + * @brief A function that loads the intra-cluster router data of one cluster */ t_lb_router_data* lb_load_router_data(std::vector* lb_type_rr_graphs, - const ClusterBlockId& clb_index); + const ClusterBlockId& clb_index, + const std::vector& clb_atoms); /** - * @brief A function that removes an atom from a cluster and check legality of + * @brief A function that removes a molecule from a cluster and checks legality of * the old cluster. * * It returns true if the removal is done and the old cluster is legal. * It aborts the removal and returns false if the removal will make the old cluster - * illegal + * illegal. + * + * This function updates the intra-logic block router data structure (router_data) and + * remove all the atoms of the moecule from old_clb_atoms vector. + * + * @param old_clb: The original cluster of this molecule + * @param old_clb_atoms: A vector containing the list of atoms in the old cluster of the molecule. + * It will be updated in the function to remove the atoms of molecule from it. + * @param router_data: returns the intra logic block router data. */ -bool remove_atom_from_cluster(const AtomBlockId& atom_id, - std::vector* lb_type_rr_graphs, - ClusterBlockId& old_clb, - t_clustering_data& clustering_data, - int& imacro, - bool during_packing); +void remove_mol_from_cluster(const t_pack_molecule* molecule, + int molecule_size, + ClusterBlockId& old_clb, + std::vector& old_clb_atoms, + t_lb_router_data*& router_data); /** * @brief A function that starts a new cluster for one specific molecule * - * It place the molecule in a specific type and mode that should be passed by + * It places the molecule in a specific type and mode that should be passed by * the higher level routine. + * + * @param type: the cluster block type needed + * @param mode: the mode of the new cluster + * @param clb_index: the cluster block Id of the newly created cluster block + * @param during_packing: true if this function is called during packing, false if it is called during placement + * @param clustering_data: A data structure containing helper data for the clustering process + * (is updated if this function is called during packing, especially intra_lb_routing data member). + * @param router_data: returns the intra logic block router data. + * @param temp_cluster_pr: returns the partition region of the new cluster. + */ +bool start_new_cluster_for_mol(t_pack_molecule* molecule, + const t_logical_block_type_ptr& type, + const int mode, + const int feasible_block_array_size, + bool enable_pin_feasibility_filter, + ClusterBlockId clb_index, + bool during_packing, + int verbosity, + t_clustering_data& clustering_data, + t_lb_router_data** router_data, + PartitionRegion& temp_cluster_pr); + +/** + * @brief A function that packs a molecule into an existing cluster + * + * @param clb_index: the cluster block Id of the new cluster that we need to pack the molecule in. + * @param: clb_atoms: A vector containing the list of atoms in the new cluster block before adding the molecule. + * @param during_packing: true if this function is called during packing, false if it is called during placement + * @param is_swap: true if this function is called during swapping two molecules. False if the called during a single molecule move + * @param clustering_data: A data structure containing helper data for the clustering process + * (is updated if this function is called during packing, especially intra_lb_routing data member). + * @param router_data: returns the intra logic block router data. */ -bool start_new_cluster_for_atom(const AtomBlockId atom_id, - const enum e_pad_loc_type& pad_loc_type, - const t_logical_block_type_ptr& type, - const int mode, - const int feasible_block_array_size, - int& imacro, - bool enable_pin_feasibility_filter, - ClusterBlockId clb_index, - t_lb_router_data** router_data, - std::vector* lb_type_rr_graphs, - PartitionRegion& temp_cluster_pr, - t_clustering_data& clustering_data, - bool during_packing); +bool pack_mol_in_existing_cluster(t_pack_molecule* molecule, + const ClusterBlockId clb_index, + const std::vector& clb_atoms, + bool during_packing, + bool is_swap, + t_clustering_data& clustering_data, + t_lb_router_data*& router_data); /** * @brief A function that fix the clustered netlist if the move is performed * after the packing is done and clustered netlist is built + * + * If you are changing clustering after packing is done, you need to update the clustered netlist by + * deleting the newly absorbed nets and creating nets for the atom nets that become unabsorbed. It also + * fixes the cluster ports for both the old and new clusters. */ -void fix_clustered_netlist(const AtomBlockId& atom_id, +void fix_clustered_netlist(t_pack_molecule* molecule, + int molecule_size, const ClusterBlockId& old_clb, const ClusterBlockId& new_clb); +/** + * @brief A function that commits the molecule move if it is legal + * + * @during_packing: true if this function is called during packing, false if it is called during placement + * @new_clb_created: true if the move is creating a new cluster (e.g. move_mol_to_new_cluster) + */ +void commit_mol_move(const ClusterBlockId& old_clb, + const ClusterBlockId& new_clb, + bool during_packing, + bool new_clb_created); + +void revert_mol_move(const ClusterBlockId& old_clb, + t_pack_molecule* molecule, + t_lb_router_data*& old_router_data, + bool during_packing, + t_clustering_data& clustering_data); + +bool is_cluster_legal(t_lb_router_data*& router_data); + +void commit_mol_removal(const t_pack_molecule* molecule, + const int& molecule_size, + const ClusterBlockId& old_clb, + bool during_packing, + t_lb_router_data*& router_data, + t_clustering_data& clustering_data); + +bool check_type_and_mode_compitability(const ClusterBlockId& old_clb, + const ClusterBlockId& new_clb, + int verbosity); + #endif