diff --git a/vpr/src/analytical_place/analytical_placement_flow.cpp b/vpr/src/analytical_place/analytical_placement_flow.cpp index 9b334402114..8ad001c4dc2 100644 --- a/vpr/src/analytical_place/analytical_placement_flow.cpp +++ b/vpr/src/analytical_place/analytical_placement_flow.cpp @@ -68,8 +68,7 @@ void run_analytical_placement_flow(t_vpr_setup& vpr_setup) { const UserPlaceConstraints& constraints = g_vpr_ctx.floorplanning().constraints; // Run the prepacker - Prepacker prepacker; - prepacker.init(atom_nlist, device_ctx.logical_block_types); + const Prepacker prepacker(atom_nlist, device_ctx.logical_block_types); // Create the ap netlist from the atom netlist using the result from the // prepacker. @@ -80,7 +79,8 @@ void run_analytical_placement_flow(t_vpr_setup& vpr_setup) { // Run the Global Placer std::unique_ptr global_placer = make_global_placer(e_global_placer::SimPL, - ap_netlist); + ap_netlist, + prepacker); PartialPlacement p_placement = global_placer->place(); // Verify that the partial placement is valid before running the full diff --git a/vpr/src/analytical_place/ap_netlist.cpp b/vpr/src/analytical_place/ap_netlist.cpp index 6ae59e596b4..6a2d55e546e 100644 --- a/vpr/src/analytical_place/ap_netlist.cpp +++ b/vpr/src/analytical_place/ap_netlist.cpp @@ -9,13 +9,13 @@ #include #include "netlist_fwd.h" #include "netlist_utils.h" -#include "vpr_types.h" +#include "prepack.h" #include "vtr_assert.h" /* * Blocks */ -const t_pack_molecule* APNetlist::block_molecule(const APBlockId id) const { +PackMoleculeId APNetlist::block_molecule(const APBlockId id) const { VTR_ASSERT_SAFE(valid_block_id(id)); return block_molecules_[id]; @@ -37,11 +37,11 @@ const APFixedBlockLoc& APNetlist::block_loc(const APBlockId id) const { /* * Mutators */ -APBlockId APNetlist::create_block(const std::string& name, const t_pack_molecule* mol) { +APBlockId APNetlist::create_block(const std::string& name, PackMoleculeId molecule_id) { APBlockId blk_id = Netlist::create_block(name); // Initialize the data - block_molecules_.insert(blk_id, mol); + block_molecules_.insert(blk_id, molecule_id); block_mobilities_.insert(blk_id, APBlockMobility::MOVEABLE); block_locs_.insert(blk_id, APFixedBlockLoc()); @@ -49,7 +49,7 @@ APBlockId APNetlist::create_block(const std::string& name, const t_pack_molecule VTR_ASSERT(validate_block_sizes()); // Check post-conditions: values - VTR_ASSERT(block_molecule(blk_id) == mol); + VTR_ASSERT(block_molecule(blk_id) == molecule_id); VTR_ASSERT(block_mobility(blk_id) == APBlockMobility::MOVEABLE); return blk_id; diff --git a/vpr/src/analytical_place/ap_netlist.h b/vpr/src/analytical_place/ap_netlist.h index ec64ae38a9b..cd2844de6e3 100644 --- a/vpr/src/analytical_place/ap_netlist.h +++ b/vpr/src/analytical_place/ap_netlist.h @@ -23,9 +23,7 @@ #include #include "netlist.h" #include "ap_netlist_fwd.h" - -// Forward declarations -class t_pack_molecule; +#include "prepack.h" /** * @brief Struct to store fixed block location information @@ -83,7 +81,7 @@ class APNetlist : public Netlist { */ /// @brief Returns the molecule that this block represents. - const t_pack_molecule* block_molecule(const APBlockId id) const; + PackMoleculeId block_molecule(const APBlockId id) const; /// @brief Returns the mobility of this block. APBlockMobility block_mobility(const APBlockId id) const; @@ -104,7 +102,7 @@ class APNetlist : public Netlist { * @param name The unique name of the block * @param mol The molecule the block represents */ - APBlockId create_block(const std::string& name, const t_pack_molecule* mol); + APBlockId create_block(const std::string& name, PackMoleculeId molecule_id); /** * @brief Fixes a block at the given location @@ -182,7 +180,7 @@ class APNetlist : public Netlist { private: // Private Data /// @brief Molecule of each block - vtr::vector_map block_molecules_; + vtr::vector_map block_molecules_; /// @brief Type of each block vtr::vector_map block_mobilities_; /// @brief Location of each block (if fixed). diff --git a/vpr/src/analytical_place/full_legalizer.cpp b/vpr/src/analytical_place/full_legalizer.cpp index e0850479118..9302e7d7cca 100644 --- a/vpr/src/analytical_place/full_legalizer.cpp +++ b/vpr/src/analytical_place/full_legalizer.cpp @@ -28,6 +28,7 @@ #include "place_and_route.h" #include "place_constraints.h" #include "place_macro.h" +#include "prepack.h" #include "verify_clustering.h" #include "verify_placement.h" #include "vpr_api.h" @@ -202,7 +203,8 @@ class APClusterPlacer { * @param primitive_candidate_block_types A list of candidate block types for * the given molecule. */ -static LegalizationClusterId create_new_cluster(t_pack_molecule* seed_molecule, +static LegalizationClusterId create_new_cluster(PackMoleculeId seed_molecule_id, + const Prepacker& prepacker, ClusterLegalizer& cluster_legalizer, const std::map>& primitive_candidate_block_types) { const AtomContext& atom_ctx = g_vpr_ctx.atom(); @@ -212,7 +214,9 @@ static LegalizationClusterId create_new_cluster(t_pack_molecule* seed_molecule, // placed into. // TODO: The original implementation sorted based on balance. Perhaps this // should do the same. - AtomBlockId root_atom = seed_molecule->atom_block_ids[seed_molecule->root]; + VTR_ASSERT(seed_molecule_id.is_valid()); + const t_pack_molecule& seed_molecule = prepacker.get_molecule(seed_molecule_id); + AtomBlockId root_atom = seed_molecule.atom_block_ids[seed_molecule.root]; const t_model* root_model = atom_ctx.nlist.block_model(root_atom); auto itr = primitive_candidate_block_types.find(root_model); @@ -224,7 +228,7 @@ static LegalizationClusterId create_new_cluster(t_pack_molecule* seed_molecule, for (int mode = 0; mode < num_modes; mode++) { e_block_pack_status pack_status = e_block_pack_status::BLK_STATUS_UNDEFINED; LegalizationClusterId new_cluster_id; - std::tie(pack_status, new_cluster_id) = cluster_legalizer.start_new_cluster(seed_molecule, type, mode); + std::tie(pack_status, new_cluster_id) = cluster_legalizer.start_new_cluster(seed_molecule_id, type, mode); if (pack_status == e_block_pack_status::BLK_PASSED) return new_cluster_id; } @@ -290,33 +294,29 @@ void FullLegalizer::create_clusters(const PartialPlacement& p_placement) { for (size_t tile_id_idx = 0; tile_id_idx < num_device_tiles; tile_id_idx++) { DeviceTileId tile_id = DeviceTileId(tile_id_idx); // Create the molecule list - std::list mol_list; + std::list mol_list; for (APBlockId ap_blk_id : blocks_in_tiles[tile_id]) { - // FIXME: The netlist stores a const pointer to mol; but the cluster - // legalizer does not accept this. Need to fix one or the other. - // For now, using const_cast. - t_pack_molecule* mol = const_cast(ap_netlist_.block_molecule(ap_blk_id)); - mol_list.push_back(mol); + mol_list.push_back(ap_netlist_.block_molecule(ap_blk_id)); } // Clustering algorithm: Create clusters one at a time. while (!mol_list.empty()) { // Arbitrarily choose the first molecule as a seed molecule. - t_pack_molecule* seed_mol = mol_list.front(); + PackMoleculeId seed_mol_id = mol_list.front(); mol_list.pop_front(); // Use the seed molecule to create a cluster for this tile. - LegalizationClusterId new_cluster_id = create_new_cluster(seed_mol, cluster_legalizer, primitive_candidate_block_types); + LegalizationClusterId new_cluster_id = create_new_cluster(seed_mol_id, prepacker_, cluster_legalizer, primitive_candidate_block_types); // Insert all molecules that you can into the cluster. // NOTE: If the mol_list was somehow sorted, we can just stop at // first failure! auto it = mol_list.begin(); while (it != mol_list.end()) { - t_pack_molecule* mol = *it; - if (!cluster_legalizer.is_molecule_compatible(mol, new_cluster_id)) { + PackMoleculeId mol_id = *it; + if (!cluster_legalizer.is_molecule_compatible(mol_id, new_cluster_id)) { ++it; continue; } // Try to insert it. If successful, remove from list. - e_block_pack_status pack_status = cluster_legalizer.add_mol_to_cluster(mol, new_cluster_id); + e_block_pack_status pack_status = cluster_legalizer.add_mol_to_cluster(mol_id, new_cluster_id); if (pack_status == e_block_pack_status::BLK_PASSED) { it = mol_list.erase(it); } else { @@ -352,8 +352,9 @@ void FullLegalizer::place_clusters(const ClusteredNetlist& clb_nlist, // Create a lookup from the AtomBlockId to the APBlockId vtr::vector atom_to_ap_block(atom_netlist_.blocks().size()); for (APBlockId ap_blk_id : ap_netlist_.blocks()) { - const t_pack_molecule* blk_mol = ap_netlist_.block_molecule(ap_blk_id); - for (AtomBlockId atom_blk_id : blk_mol->atom_block_ids) { + PackMoleculeId blk_mol_id = ap_netlist_.block_molecule(ap_blk_id); + const t_pack_molecule& blk_mol = prepacker_.get_molecule(blk_mol_id); + for (AtomBlockId atom_blk_id : blk_mol.atom_block_ids) { // See issue #2791, some of the atom_block_ids may be invalid. They // can safely be ignored. if (!atom_blk_id.is_valid()) diff --git a/vpr/src/analytical_place/gen_ap_netlist_from_atoms.cpp b/vpr/src/analytical_place/gen_ap_netlist_from_atoms.cpp index 34207e88145..60ac4afe311 100644 --- a/vpr/src/analytical_place/gen_ap_netlist_from_atoms.cpp +++ b/vpr/src/analytical_place/gen_ap_netlist_from_atoms.cpp @@ -16,7 +16,6 @@ #include "prepack.h" #include "region.h" #include "user_place_constraints.h" -#include "vpr_types.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_time.h" @@ -40,10 +39,11 @@ APNetlist gen_ap_netlist_from_atoms(const AtomNetlist& atom_netlist, // Each net has the exact same name as in the atom netlist for (AtomBlockId atom_blk_id : atom_netlist.blocks()) { // Get the molecule of this block - t_pack_molecule* mol = prepacker.get_atom_molecule(atom_blk_id); + PackMoleculeId molecule_id = prepacker.get_atom_molecule(atom_blk_id); + const t_pack_molecule& mol = prepacker.get_molecule(molecule_id); // Create the AP block (if not already done) - const std::string& first_blk_name = atom_netlist.block_name(mol->atom_block_ids[0]); - APBlockId ap_blk_id = ap_netlist.create_block(first_blk_name, mol); + const std::string& first_blk_name = atom_netlist.block_name(mol.atom_block_ids[0]); + APBlockId ap_blk_id = ap_netlist.create_block(first_blk_name, molecule_id); // Add the ports and pins of this block to the supernode for (AtomPortId atom_port_id : atom_netlist.block_ports(atom_blk_id)) { BitIndex port_width = atom_netlist.port_width(atom_port_id); @@ -68,8 +68,9 @@ APNetlist gen_ap_netlist_from_atoms(const AtomNetlist& atom_netlist, // Fix the block locations given by the VPR constraints for (APBlockId ap_blk_id : ap_netlist.blocks()) { - const t_pack_molecule* mol = ap_netlist.block_molecule(ap_blk_id); - for (AtomBlockId mol_atom_blk_id : mol->atom_block_ids) { + PackMoleculeId molecule_id = ap_netlist.block_molecule(ap_blk_id); + const t_pack_molecule& mol = prepacker.get_molecule(molecule_id); + for (AtomBlockId mol_atom_blk_id : mol.atom_block_ids) { PartitionId part_id = constraints.get_atom_partition(mol_atom_blk_id); if (!part_id.is_valid()) continue; diff --git a/vpr/src/analytical_place/global_placer.cpp b/vpr/src/analytical_place/global_placer.cpp index d2fbfe42d11..dc72c792635 100644 --- a/vpr/src/analytical_place/global_placer.cpp +++ b/vpr/src/analytical_place/global_placer.cpp @@ -18,11 +18,12 @@ #include "vtr_time.h" std::unique_ptr make_global_placer(e_global_placer placer_type, - const APNetlist& netlist) { + const APNetlist& netlist, + const Prepacker& prepacker) { // Based on the placer type passed in, build the global placer. switch (placer_type) { case e_global_placer::SimPL: - return std::make_unique(netlist); + return std::make_unique(netlist, prepacker); default: VPR_FATAL_ERROR(VPR_ERROR_AP, "Unrecognized global placer type"); @@ -30,7 +31,9 @@ std::unique_ptr make_global_placer(e_global_placer placer_type, } } -SimPLGlobalPlacer::SimPLGlobalPlacer(const APNetlist& netlist) : GlobalPlacer(netlist) { +SimPLGlobalPlacer::SimPLGlobalPlacer(const APNetlist& netlist, + const Prepacker& prepacker) + : GlobalPlacer(netlist) { // This can be a long method. Good to time this to see how long it takes to // construct the global placer. vtr::ScopedStartFinishTimer global_placer_building_timer("Constructing Global Placer"); @@ -39,7 +42,8 @@ SimPLGlobalPlacer::SimPLGlobalPlacer(const APNetlist& netlist) : GlobalPlacer(ne netlist); // Build the partial legalizer partial_legalizer_ = make_partial_legalizer(e_partial_legalizer::FLOW_BASED, - netlist); + netlist, + prepacker); } /** diff --git a/vpr/src/analytical_place/global_placer.h b/vpr/src/analytical_place/global_placer.h index 0628b9b0d50..aa382d39d95 100644 --- a/vpr/src/analytical_place/global_placer.h +++ b/vpr/src/analytical_place/global_placer.h @@ -19,8 +19,9 @@ // Forward declarations class APNetlist; class AnalyticalSolver; -class PartialPlacement; class PartialLegalizer; +class PartialPlacement; +class Prepacker; /** * @brief Enumeration of all of the global placers currently implemented in VPR. @@ -77,7 +78,8 @@ class GlobalPlacer { * @brief A factory method which creates a Global Placer of the given type. */ std::unique_ptr make_global_placer(e_global_placer placer_type, - const APNetlist& netlist); + const APNetlist& netlist, + const Prepacker& prepacker); /** * @brief A Global Placer based on the SimPL work for analytical ASIC placement. @@ -130,7 +132,7 @@ class SimPLGlobalPlacer : public GlobalPlacer { * * Constructs the solver and partial legalizer. */ - SimPLGlobalPlacer(const APNetlist& netlist); + SimPLGlobalPlacer(const APNetlist& netlist, const Prepacker& prepacker); /** * @brief Run a SimPL-like global placement algorithm diff --git a/vpr/src/analytical_place/partial_legalizer.cpp b/vpr/src/analytical_place/partial_legalizer.cpp index e782c85b073..6da6afc6493 100644 --- a/vpr/src/analytical_place/partial_legalizer.cpp +++ b/vpr/src/analytical_place/partial_legalizer.cpp @@ -23,10 +23,10 @@ #include "globals.h" #include "partial_placement.h" #include "physical_types.h" +#include "prepack.h" #include "primitive_vector.h" #include "vpr_context.h" #include "vpr_error.h" -#include "vpr_types.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -36,11 +36,12 @@ #include "vtr_vector_map.h" std::unique_ptr make_partial_legalizer(e_partial_legalizer legalizer_type, - const APNetlist& netlist) { + const APNetlist& netlist, + const Prepacker& prepacker) { // Based on the partial legalizer type passed in, build the partial legalizer. switch (legalizer_type) { case e_partial_legalizer::FLOW_BASED: - return std::make_unique(netlist); + return std::make_unique(netlist, prepacker); default: VPR_FATAL_ERROR(VPR_ERROR_AP, "Unrecognized partial legalizer type"); @@ -72,10 +73,12 @@ static inline float get_model_mass(const t_model* model) { * (primitive types) in the architecture. */ static inline PrimitiveVector get_primitive_mass(APBlockId blk_id, - const APNetlist& netlist) { + const APNetlist& netlist, + const Prepacker& prepacker) { PrimitiveVector mass; - const t_pack_molecule* mol = netlist.block_molecule(blk_id); - for (AtomBlockId atom_blk_id : mol->atom_block_ids) { + PackMoleculeId mol_id = netlist.block_molecule(blk_id); + const t_pack_molecule& mol = prepacker.get_molecule(mol_id); + for (AtomBlockId atom_blk_id : mol.atom_block_ids) { // See issue #2791, some of the atom_block_ids may be invalid. They can // safely be ignored. if (!atom_blk_id.is_valid()) @@ -459,8 +462,8 @@ void FlowBasedLegalizer::compute_neighbors_of_bin(LegalizerBinId src_bin_id, siz bins_[src_bin_id].neighbors.assign(neighbors.begin(), neighbors.end()); } -FlowBasedLegalizer::FlowBasedLegalizer(const APNetlist& netlist) - : PartialLegalizer(netlist), +FlowBasedLegalizer::FlowBasedLegalizer(const APNetlist& netlist, const Prepacker& prepacker) + : PartialLegalizer(netlist, prepacker), // TODO: Pass the device grid in. tile_bin_({g_vpr_ctx.device().grid.width(), g_vpr_ctx.device().grid.height()}) { const DeviceGrid& grid = g_vpr_ctx.device().grid; @@ -542,7 +545,7 @@ FlowBasedLegalizer::FlowBasedLegalizer(const APNetlist& netlist) // Pre-compute the masses of the APBlocks VTR_LOGV(log_verbosity_ >= 10, "Pre-computing the block masses...\n"); for (APBlockId blk_id : netlist.blocks()) { - block_masses_.insert(blk_id, get_primitive_mass(blk_id, netlist)); + block_masses_.insert(blk_id, get_primitive_mass(blk_id, netlist, prepacker)); } VTR_LOGV(log_verbosity_ >= 10, "Finished pre-computing the block masses.\n"); diff --git a/vpr/src/analytical_place/partial_legalizer.h b/vpr/src/analytical_place/partial_legalizer.h index 96171e5fdb5..dc464dd40d7 100644 --- a/vpr/src/analytical_place/partial_legalizer.h +++ b/vpr/src/analytical_place/partial_legalizer.h @@ -26,6 +26,7 @@ // Forward declarations class APNetlist; +class Prepacker; struct PartialPlacement; /** @@ -54,8 +55,11 @@ class PartialLegalizer { * * Currently just copies the parameters into the class as member varaibles. */ - PartialLegalizer(const APNetlist& netlist, int log_verbosity = 1) + PartialLegalizer(const APNetlist& netlist, + const Prepacker& prepacker, + int log_verbosity = 1) : netlist_(netlist), + prepacker_(prepacker), log_verbosity_(log_verbosity) {} /** @@ -80,6 +84,10 @@ class PartialLegalizer { /// global placement. const APNetlist& netlist_; + /// @brief The prepacker used to create the packed molecules used within + /// the AP Netlist. + const Prepacker& prepacker_; + /// @brief The verbosity of the log statements within the partial legalizer. /// 0 would be no log messages, 10 would print per-iteration status, /// 20 would print logs messages within each iteration. @@ -90,7 +98,8 @@ class PartialLegalizer { * @brief A factory method which creates a Partial Legalizer of the given type. */ std::unique_ptr make_partial_legalizer(e_partial_legalizer legalizer_type, - const APNetlist& netlist); + const APNetlist& netlist, + const Prepacker& prepacker); /** * @brief A strong ID for the bins used in the partial legalizer. @@ -400,7 +409,7 @@ class FlowBasedLegalizer : public PartialLegalizer { * description. Builds the connectivity of bins. Computes the mass of all * blocks in the netlist. */ - FlowBasedLegalizer(const APNetlist& netlist); + FlowBasedLegalizer(const APNetlist& netlist, const Prepacker& prepacker); /** * @brief Performs flow-based spreading on the given partial placement. diff --git a/vpr/src/base/SetupGrid.cpp b/vpr/src/base/SetupGrid.cpp index 08e23567877..a9c91cf3ef0 100644 --- a/vpr/src/base/SetupGrid.cpp +++ b/vpr/src/base/SetupGrid.cpp @@ -9,9 +9,9 @@ #include #include #include -#include #include +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_math.h" #include "vtr_log.h" diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 9c0fb69ba98..0896e3e8207 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -1,6 +1,7 @@ #include #include +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_util.h" #include "vtr_log.h" diff --git a/vpr/src/base/ShowSetup.cpp b/vpr/src/base/ShowSetup.cpp index b89c21ca4e2..6e9c1026b96 100644 --- a/vpr/src/base/ShowSetup.cpp +++ b/vpr/src/base/ShowSetup.cpp @@ -1,17 +1,14 @@ -#include -#include - -#include "vtr_assert.h" -#include "vtr_log.h" -#include "vpr_types.h" -#include "vpr_error.h" +#include "ShowSetup.h" #include "globals.h" -#include "echo_files.h" -#include "read_options.h" -#include "read_xml_arch_file.h" -#include "ShowSetup.h" +#include "physical_types_util.h" +#include "vpr_error.h" +#include "vpr_types.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include +#include /******** Function Prototypes ********/ static void ShowPackerOpts(const t_packer_opts& PackerOpts); diff --git a/vpr/src/base/blk_loc_registry.cpp b/vpr/src/base/blk_loc_registry.cpp index 70f809cdcd9..bb2866e3546 100644 --- a/vpr/src/base/blk_loc_registry.cpp +++ b/vpr/src/base/blk_loc_registry.cpp @@ -3,6 +3,7 @@ #include "move_transactions.h" #include "globals.h" +#include "physical_types_util.h" BlkLocRegistry::BlkLocRegistry() : expected_transaction_(e_expected_transaction::APPLY) {} diff --git a/vpr/src/base/check_netlist.cpp b/vpr/src/base/check_netlist.cpp index cd800003a5f..a80e3d7d76c 100644 --- a/vpr/src/base/check_netlist.cpp +++ b/vpr/src/base/check_netlist.cpp @@ -7,6 +7,7 @@ #include #include +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -16,7 +17,6 @@ #include "hash.h" #include "vpr_utils.h" #include "check_netlist.h" -#include "read_xml_arch_file.h" #define ERROR_THRESHOLD 100 diff --git a/vpr/src/base/clustered_netlist.cpp b/vpr/src/base/clustered_netlist.cpp index 180b60e35bd..ce9e44dd422 100644 --- a/vpr/src/base/clustered_netlist.cpp +++ b/vpr/src/base/clustered_netlist.cpp @@ -1,7 +1,7 @@ #include "clustered_netlist.h" +#include "physical_types_util.h" #include "vtr_assert.h" -#include "vpr_error.h" #include diff --git a/vpr/src/base/read_netlist.cpp b/vpr/src/base/read_netlist.cpp index 2f0d1ff8716..34c1aa726f3 100644 --- a/vpr/src/base/read_netlist.cpp +++ b/vpr/src/base/read_netlist.cpp @@ -11,6 +11,7 @@ #include #include +#include "physical_types_util.h" #include "pugixml.hpp" #include "pugixml_loc.hpp" #include "pugixml_util.hpp" @@ -19,7 +20,6 @@ #include "vtr_util.h" #include "vtr_log.h" #include "vtr_digest.h" -#include "vtr_memory.h" #include "vtr_token.h" #include "vpr_types.h" @@ -29,7 +29,6 @@ #include "hash.h" #include "globals.h" #include "atom_netlist.h" -#include "read_xml_util.h" #include "read_netlist.h" #include "pb_type_graph.h" diff --git a/vpr/src/base/read_route.cpp b/vpr/src/base/read_route.cpp index 6ac9d099c4b..c62f3761559 100644 --- a/vpr/src/base/read_route.cpp +++ b/vpr/src/base/read_route.cpp @@ -21,26 +21,19 @@ #include #include -#include "atom_netlist.h" -#include "atom_netlist_utils.h" -#include "rr_graph.h" +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_digest.h" #include "vtr_util.h" -#include "tatum/echo_writer.hpp" #include "vtr_log.h" #include "check_route.h" #include "route_common.h" #include "vpr_types.h" #include "globals.h" -#include "vpr_api.h" #include "read_place.h" #include "vpr_types.h" #include "vpr_utils.h" #include "vpr_error.h" -#include "place_and_route.h" -#include "route_export.h" -#include "echo_files.h" #include "route_common.h" #include "route_tree.h" #include "read_route.h" diff --git a/vpr/src/base/stats.cpp b/vpr/src/base/stats.cpp index bda53d16a56..e8bc00c58e5 100644 --- a/vpr/src/base/stats.cpp +++ b/vpr/src/base/stats.cpp @@ -1,6 +1,7 @@ #include #include +#include "physical_types_util.h" #include "route_tree.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -15,15 +16,6 @@ #include "segment_stats.h" #include "channel_stats.h" #include "stats.h" -#include "net_delay.h" -#include "read_xml_arch_file.h" -#include "echo_files.h" - -#include "timing_info.h" -#include "RoutingDelayCalculator.h" - -#include "timing_util.h" -#include "tatum/TimingReporter.hpp" /********************** Subroutines local to this module *********************/ diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 50fd339b66b..296240410f8 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -17,10 +17,10 @@ #include "FlatPlacementInfo.h" #include "cluster_util.h" +#include "physical_types_util.h" #include "verify_placement.h" #include "vpr_context.h" #include "vtr_assert.h" -#include "vtr_math.h" #include "vtr_log.h" #include "vtr_version.h" #include "vtr_time.h" @@ -31,7 +31,6 @@ #include "atom_netlist.h" #include "read_netlist.h" #include "check_netlist.h" -#include "read_blif.h" #include "draw.h" #include "place_and_route.h" #include "pack.h" diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 0c297f93ac1..de78ce0f122 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -6,7 +6,6 @@ #include #include "FlatPlacementInfo.h" -#include "prepack.h" #include "vpr_types.h" #include "vtr_ndmatrix.h" #include "vtr_optional.h" diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index abea66f8d6b..3974e9a0a3e 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -251,10 +251,8 @@ class t_pack_high_fanout_thresholds { /* these are defined later, but need to declare here because it is used */ class t_rr_node; -class t_pack_molecule; struct t_pb_stats; struct t_pb_route; -struct t_chain_info; typedef vtr::flat_map2 t_pb_routes; @@ -366,73 +364,6 @@ struct t_pb_route { const t_pb_graph_pin* pb_graph_pin = nullptr; ///block_id - * chain_info : if this is a molecule representing a chained pack pattern, this data structure will - * hold the data shared between all molecules forming a chain together. - * num_blocks : maximum number of atom blocks that can fit in this molecule - * root : index of the pack_pattern->root_block in the atom_blocks_ids. root_block_id = atom_block_ids[root] - * base_gain : intrinsic "goodness" score for molecule independent of rest of netlist - * next : next molecule in the linked list - */ -class t_pack_molecule { - public: - /* general molecule info */ - float base_gain; - enum e_pack_pattern_molecule_type type; - - /* large molecules info */ - t_pack_patterns* pack_pattern; - int root; - int num_blocks; - std::vector atom_block_ids; - std::shared_ptr chain_info; - - t_pack_molecule* next; - // a molecule is chain is it is a forced pack and its pack pattern is chain - bool is_chain() const { return type == MOLECULE_FORCED_PACK && pack_pattern->is_chain; } -}; - -/** - * @brief Holds information to be shared between molecules that represent the same chained pack pattern. - * - * For example, molecules that are representing a long carry chain that spans multiple logic blocks. - * - * Data members: - * is_long_chain : is this a long that is divided on multiple clusters (divided on multiple molecules). - * chain_id : is used to access the chain_root_pins vector in the t_pack_patterns of the molecule. To get - * the starting point of this chain in the cluster. This id is useful when we have multiple - * (architectural) carry chains in a logic block, for example. It lets us see which of the chains - * is being used for this long (netlist) chain, so we continue to use that chain in the packing - * of other molecules of this long chain. - * first_packed_molecule : first molecule to be packed out of the molecules forming this chain. This is the molecule - * setting the value of the chain_id. - */ -struct t_chain_info { - bool is_long_chain = false; - int chain_id = -1; - t_pack_molecule* first_packed_molecule = nullptr; -}; /****************************************************************** * Timing data types diff --git a/vpr/src/draw/draw_basic.cpp b/vpr/src/draw/draw_basic.cpp index 482fbf178e3..c0e3896c9c8 100644 --- a/vpr/src/draw/draw_basic.cpp +++ b/vpr/src/draw/draw_basic.cpp @@ -7,9 +7,9 @@ #include #include +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_ndoffsetmatrix.h" -#include "vtr_log.h" #include "vtr_color_map.h" #include "vpr_utils.h" @@ -22,7 +22,6 @@ #include "draw_rr_edges.h" #include "draw_basic.h" #include "draw_triangle.h" -#include "read_xml_arch_file.h" #include "draw_global.h" #include "move_utils.h" #include "route_export.h" diff --git a/vpr/src/draw/draw_noc.cpp b/vpr/src/draw/draw_noc.cpp index d112cb7cae5..a91866caa70 100644 --- a/vpr/src/draw/draw_noc.cpp +++ b/vpr/src/draw/draw_noc.cpp @@ -1,12 +1,12 @@ #ifndef NO_GRAPHICS +# include "draw_basic.h" # include "draw_noc.h" # include "globals.h" # include "noc_storage.h" -# include "vpr_error.h" +# include "physical_types_util.h" # include "vtr_math.h" -# include "draw_basic.h" void draw_noc(ezgl::renderer* g) { t_draw_state* draw_state = get_draw_state_vars(); @@ -475,4 +475,4 @@ void shift_noc_link(noc_link_draw_coords& link_coords, NocLinkShift link_shift_d } } -#endif \ No newline at end of file +#endif diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index 0815be661a6..272148fa25d 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -1,20 +1,17 @@ /*draw_rr_edges.cpp contains all functions that draw lines between RR nodes.*/ #include +#include "physical_types_util.h" #include "vtr_assert.h" -#include "vtr_color_map.h" #include "vpr_utils.h" #include "vpr_error.h" #include "globals.h" -#include "draw_color.h" -#include "draw.h" #include "draw_rr.h" #include "draw_rr_edges.h" #include "draw_triangle.h" #include "draw_searchbar.h" -#include "read_xml_arch_file.h" #include "draw_global.h" #include "draw_basic.h" diff --git a/vpr/src/draw/draw_searchbar.cpp b/vpr/src/draw/draw_searchbar.cpp index a90583f42ce..195f27a792d 100644 --- a/vpr/src/draw/draw_searchbar.cpp +++ b/vpr/src/draw/draw_searchbar.cpp @@ -1,18 +1,16 @@ /*draw_searchbar.cpp contains all functions related to searchbar actions.*/ #include -#include #include "netlist_fwd.h" +#include "physical_types_util.h" #include "vpr_utils.h" #include "globals.h" -#include "draw_color.h" #include "draw.h" #include "draw_rr.h" #include "draw_basic.h" #include "draw_searchbar.h" -#include "read_xml_arch_file.h" #include "draw_global.h" #include "intra_logic_block.h" diff --git a/vpr/src/draw/draw_types.cpp b/vpr/src/draw/draw_types.cpp index b3909c5fd7c..c3aea7d005a 100644 --- a/vpr/src/draw/draw_types.cpp +++ b/vpr/src/draw/draw_types.cpp @@ -1,12 +1,11 @@ #ifndef NO_GRAPHICS +# include "draw.h" # include "draw_global.h" # include "draw_types.h" -# include "draw_toggle_functions.h" # include "globals.h" +# include "physical_types_util.h" # include "vpr_utils.h" -# include "draw.h" -# include /******************************************* * begin t_draw_state function definitions * diff --git a/vpr/src/draw/manual_moves.cpp b/vpr/src/draw/manual_moves.cpp index 6a98d6ee419..972b2a36bd7 100644 --- a/vpr/src/draw/manual_moves.cpp +++ b/vpr/src/draw/manual_moves.cpp @@ -17,6 +17,7 @@ #include "draw.h" #include "draw_searchbar.h" #include "buttons.h" +#include "physical_types_util.h" #ifndef NO_GRAPHICS diff --git a/vpr/src/draw/save_graphics.cpp b/vpr/src/draw/save_graphics.cpp index 84b1599f30f..c21ba82a321 100644 --- a/vpr/src/draw/save_graphics.cpp +++ b/vpr/src/draw/save_graphics.cpp @@ -1,13 +1,9 @@ #ifndef NO_GRAPHICS # include -# include -# include "globals.h" # include "draw.h" -# include "draw_global.h" # include "save_graphics.h" -# include "vtr_path.h" # include "search_bar.h" extern ezgl::rectangle initial_world; diff --git a/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp b/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp index 3f12c02ed2d..b7d633b20c6 100644 --- a/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp +++ b/vpr/src/noc/read_xml_noc_traffic_flows_file.cpp @@ -1,5 +1,6 @@ #include "read_xml_noc_traffic_flows_file.h" +#include "physical_types_util.h" void read_xml_noc_traffic_flows_file(const char* noc_flows_file) { // start by checking that the provided file is a ".flows" file @@ -316,4 +317,4 @@ std::vector get_cluster_blocks_compatible_with_noc_router_tiles( } return cluster_blocks_compatible_with_noc_router_tiles; -} \ No newline at end of file +} diff --git a/vpr/src/pack/cluster_legalizer.cpp b/vpr/src/pack/cluster_legalizer.cpp index 399b0e271cc..d59ca39a699 100644 --- a/vpr/src/pack/cluster_legalizer.cpp +++ b/vpr/src/pack/cluster_legalizer.cpp @@ -17,6 +17,7 @@ #include #include "atom_lookup.h" #include "atom_netlist.h" +#include "cad_types.h" #include "cluster_placement.h" #include "cluster_router.h" #include "globals.h" @@ -289,16 +290,19 @@ static bool check_cluster_noc_group(AtomBlockId atom_blk_id, * chain root block has a placement constraint (such as being driven from * outside the cluster) and returns the status of the placement accordingly. */ -static enum e_block_pack_status check_chain_root_placement_feasibility(const t_pb_graph_node* pb_graph_node, - const t_pack_molecule* molecule, - const AtomBlockId blk_id) { +static enum e_block_pack_status check_chain_root_placement_feasibility( + const t_pb_graph_node* pb_graph_node, + const t_chain_info& prepack_chain_info, + const t_clustering_chain_info& clustering_chain_info, + t_pack_patterns* mol_pack_patterns, + const AtomBlockId blk_id) { const AtomContext& atom_ctx = g_vpr_ctx.atom(); enum e_block_pack_status block_pack_status = e_block_pack_status::BLK_PASSED; - bool is_long_chain = molecule->chain_info->is_long_chain; + bool is_long_chain = prepack_chain_info.is_long_chain; - const auto& chain_root_pins = molecule->pack_pattern->chain_root_pins; + const auto& chain_root_pins = mol_pack_patterns->chain_root_pins; t_model_ports* root_port = chain_root_pins[0][0]->port->model_port; AtomNetId chain_net_id; @@ -315,7 +319,7 @@ static enum e_block_pack_status check_chain_root_placement_feasibility(const t_p // driven by a global gnd or vdd. Therefore even if this is not a long chain // but its input pin is driven by a net, the placement legality is checked. if (is_long_chain || chain_net_id) { - auto chain_id = molecule->chain_info->chain_id; + auto chain_id = clustering_chain_info.chain_id; // if this chain has a chain id assigned to it (implies is_long_chain too) if (chain_id != -1) { // the chosen primitive should be a valid starting point for the chain @@ -472,10 +476,12 @@ try_place_atom_block_rec(const t_pb_graph_node* pb_graph_node, const LegalizationClusterId cluster_id, vtr::vector_map& atom_cluster, const t_intra_cluster_placement_stats* cluster_placement_stats_ptr, - const t_pack_molecule* molecule, + const PackMoleculeId molecule_id, t_lb_router_data* router_data, int verbosity, - const int feasible_block_array_size) { + const int feasible_block_array_size, + const Prepacker& prepacker, + const vtr::vector_map& clustering_chain_info) { const AtomContext& atom_ctx = g_vpr_ctx.atom(); AtomContext& mutable_atom_ctx = g_vpr_ctx.mutable_atom(); @@ -489,8 +495,9 @@ try_place_atom_block_rec(const t_pb_graph_node* pb_graph_node, block_pack_status = try_place_atom_block_rec(pb_graph_node->parent_pb_graph_node, blk_id, cb, &my_parent, max_models, max_cluster_size, cluster_id, atom_cluster, - cluster_placement_stats_ptr, molecule, router_data, - verbosity, feasible_block_array_size); + cluster_placement_stats_ptr, molecule_id, router_data, + verbosity, feasible_block_array_size, + prepacker, clustering_chain_info); parent_pb = my_parent; } else { parent_pb = cb; @@ -571,11 +578,18 @@ try_place_atom_block_rec(const t_pb_graph_node* pb_graph_node, } // if this block passed and is part of a chained molecule - if (block_pack_status == e_block_pack_status::BLK_PASSED && molecule->is_chain()) { - auto molecule_root_block = molecule->atom_block_ids[molecule->root]; + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + if (block_pack_status == e_block_pack_status::BLK_PASSED && molecule.is_chain()) { + auto molecule_root_block = molecule.atom_block_ids[molecule.root]; // if this is the root block of the chain molecule check its placmeent feasibility if (blk_id == molecule_root_block) { - block_pack_status = check_chain_root_placement_feasibility(pb_graph_node, molecule, blk_id); + VTR_ASSERT(molecule.chain_id.is_valid()); + const t_chain_info& prepack_chain_info = prepacker.get_molecule_chain_info(molecule.chain_id); + block_pack_status = check_chain_root_placement_feasibility(pb_graph_node, + prepack_chain_info, + clustering_chain_info[molecule.chain_id], + molecule.pack_pattern, + blk_id); } } @@ -932,26 +946,31 @@ static bool check_lookahead_pins_used(t_pb* cur_pb, t_ext_pin_util max_external_ return true; } -/** - * @brief This function takes a chain molecule, and the pb_graph_node that is - * chosen for packing the molecule's root block. Using the given - * root_primitive, this function will identify which chain id this - * molecule is being mapped to and will update the chain id value inside - * the chain info data structure of this molecule. - */ -static void update_molecule_chain_info(t_pack_molecule* chain_molecule, const t_pb_graph_node* root_primitive) { - VTR_ASSERT(chain_molecule->chain_info->chain_id == -1 && chain_molecule->chain_info->is_long_chain); +void ClusterLegalizer::update_clustering_chain_info(PackMoleculeId chain_molecule_id, + const t_pb_graph_node* root_primitive) { + // Get the molecule + VTR_ASSERT(chain_molecule_id.is_valid()); + const t_pack_molecule& chain_molecule = prepacker_.get_molecule(chain_molecule_id); + + // Get the ID of the chain it is a part of + MoleculeChainId chain_id = chain_molecule.chain_id; + VTR_ASSERT(chain_id.is_valid()); - auto chain_root_pins = chain_molecule->pack_pattern->chain_root_pins; + // Get the prepacking and clustering information on this chain. + const t_chain_info& prepack_chain_info = prepacker_.get_molecule_chain_info(chain_id); + t_clustering_chain_info& clustering_chain_info = clustering_chain_info_[chain_id]; + VTR_ASSERT(clustering_chain_info.chain_id == -1 && prepack_chain_info.is_long_chain); + // Update the clustering chain information. // long chains should only be placed at the beginning of the chain // Since for long chains the molecule size is already equal to the // total number of adders in the cluster. Therefore, it should // always be placed at the very first adder in this cluster. + auto chain_root_pins = chain_molecule.pack_pattern->chain_root_pins; for (size_t chainId = 0; chainId < chain_root_pins.size(); chainId++) { if (chain_root_pins[chainId][0]->parent_node == root_primitive) { - chain_molecule->chain_info->chain_id = chainId; - chain_molecule->chain_info->first_packed_molecule = chain_molecule; + clustering_chain_info.chain_id = chainId; + clustering_chain_info.first_packed_molecule = chain_molecule_id; return; } } @@ -959,28 +978,27 @@ static void update_molecule_chain_info(t_pack_molecule* chain_molecule, const t_ VTR_ASSERT(false); } -/* - * @brief Reset molecule information created while trying to cluster it. - * - * This code only resets information that has to do with long chains. - * - * TODO: This information should not be stored in the molecule, but should be - * stored in the ClusterLegalizer class instead. - * - * TODO: This code may be removable. Tried turning it off and found no test - * failures or QoR degredations. Should be investigated in more detail. - */ -static void reset_molecule_info(t_pack_molecule* mol) { +void ClusterLegalizer::reset_molecule_info(PackMoleculeId mol_id) { + VTR_ASSERT(mol_id.is_valid()); + // when invalidating a molecule check if it's a chain molecule // that is part of a long chain. If so, check if this molecule // has modified the chain_id value based on the stale packing // then reset the chain id and the first packed molecule pointer // this is packing is being reset - if (mol->is_chain() - && mol->chain_info->is_long_chain - && mol->chain_info->first_packed_molecule == mol) { - mol->chain_info->first_packed_molecule = nullptr; - mol->chain_info->chain_id = -1; + const t_pack_molecule& mol = prepacker_.get_molecule(mol_id); + if (!mol.is_chain()) + return; + + VTR_ASSERT(mol.chain_id.is_valid()); + const t_chain_info& prepack_chain_info = prepacker_.get_molecule_chain_info(mol.chain_id); + if (!prepack_chain_info.is_long_chain) + return; + + t_clustering_chain_info& clustering_chain_info = clustering_chain_info_[mol.chain_id]; + if (clustering_chain_info.first_packed_molecule == mol_id) { + clustering_chain_info.first_packed_molecule = PackMoleculeId::INVALID(); + clustering_chain_info.chain_id = -1; } } @@ -1139,14 +1157,14 @@ static bool cleanup_pb(t_pb* pb) { return can_free; } -e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecule, +e_block_pack_status ClusterLegalizer::try_pack_molecule(PackMoleculeId molecule_id, LegalizationCluster& cluster, LegalizationClusterId cluster_id, const t_ext_pin_util& max_external_pin_util) { // Try to pack the molecule into a cluster with this pb type. // Safety debugs. - VTR_ASSERT_DEBUG(molecule != nullptr); + VTR_ASSERT_DEBUG(molecule_id.is_valid()); VTR_ASSERT_DEBUG(cluster.pb != nullptr); VTR_ASSERT_DEBUG(cluster.type != nullptr); @@ -1159,15 +1177,19 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul // - Checking if the atom can be placed in the cluster for floorplanning // constraints. const FloorplanningContext& floorplanning_ctx = g_vpr_ctx.floorplanning(); + + // Get the molecule object. + const t_pack_molecule& molecule = prepacker_.get_molecule(molecule_id); + if (log_verbosity_ > 3) { - AtomBlockId root_atom = molecule->atom_block_ids[molecule->root]; + AtomBlockId root_atom = molecule.atom_block_ids[molecule.root]; VTR_LOG("\t\tTry pack molecule: '%s' (%s)", atom_ctx.nlist.block_name(root_atom).c_str(), atom_ctx.nlist.block_model(root_atom)->name); - VTR_LOGV(molecule->pack_pattern, + VTR_LOGV(molecule.pack_pattern, " molecule_type %s molecule_size %zu", - molecule->pack_pattern->name, - molecule->atom_block_ids.size()); + molecule.pack_pattern->name, + molecule.atom_block_ids.size()); VTR_LOG("\n"); } @@ -1176,7 +1198,7 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul // molecules to be placed in this cluster. To avoid possibly creating cluster level // blocks that have incompatible placement constraints or form very long placement // macros that limit placement flexibility. - if (cluster.placement_stats->has_long_chain && molecule->is_chain() && molecule->chain_info->is_long_chain) { + if (cluster.placement_stats->has_long_chain && molecule.is_chain() && prepacker_.get_molecule_chain_info(molecule.chain_id).is_long_chain) { VTR_LOGV(log_verbosity_ > 4, "\t\t\tFAILED Placement Feasibility Filter: Only one long chain per cluster is allowed\n"); return e_block_pack_status::BLK_FAILED_FEASIBLE; } @@ -1187,40 +1209,39 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul PartitionRegion new_cluster_pr = cluster.pr; // TODO: This can be made more efficient by pre-computing the intersection // of all the atoms' PRs in the molecule. - int molecule_size = get_array_size_of_molecule(molecule); - for (int i_mol = 0; i_mol < molecule_size; i_mol++) { + for (AtomBlockId atom_blk_id : molecule.atom_block_ids) { + if (!atom_blk_id.is_valid()) + continue; + // Try to intersect with atom PartitionRegion if atom exists - AtomBlockId atom_blk_id = molecule->atom_block_ids[i_mol]; - if (atom_blk_id) { - bool cluster_pr_needs_update = false; - bool block_pack_floorplan_status = check_cluster_floorplanning(atom_blk_id, - new_cluster_pr, - floorplanning_ctx.constraints, - log_verbosity_, - cluster_pr_needs_update); - if (!block_pack_floorplan_status) { - return e_block_pack_status::BLK_FAILED_FLOORPLANNING; - } + bool cluster_pr_needs_update = false; + bool block_pack_floorplan_status = check_cluster_floorplanning(atom_blk_id, + new_cluster_pr, + floorplanning_ctx.constraints, + log_verbosity_, + cluster_pr_needs_update); + if (!block_pack_floorplan_status) { + return e_block_pack_status::BLK_FAILED_FLOORPLANNING; + } - if (cluster_pr_needs_update) { - cluster_pr_update_check = true; - } + if (cluster_pr_needs_update) { + cluster_pr_update_check = true; } } // Check if all atoms in the molecule can be added to the cluster without // NoC group conflicts NocGroupId new_cluster_noc_grp_id = cluster.noc_grp_id; - for (int i_mol = 0; i_mol < molecule_size; i_mol++) { - AtomBlockId atom_blk_id = molecule->atom_block_ids[i_mol]; - if (atom_blk_id) { - bool block_pack_noc_grp_status = check_cluster_noc_group(atom_blk_id, - new_cluster_noc_grp_id, - atom_noc_grp_id_, - log_verbosity_); - if (!block_pack_noc_grp_status) { - return e_block_pack_status::BLK_FAILED_NOC_GROUP; - } + for (AtomBlockId atom_blk_id : molecule.atom_block_ids) { + if (!atom_blk_id.is_valid()) + continue; + + bool block_pack_noc_grp_status = check_cluster_noc_group(atom_blk_id, + new_cluster_noc_grp_id, + atom_noc_grp_id_, + log_verbosity_); + if (!block_pack_noc_grp_status) { + return e_block_pack_status::BLK_FAILED_NOC_GROUP; } } @@ -1228,19 +1249,20 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul e_block_pack_status block_pack_status = e_block_pack_status::BLK_STATUS_UNDEFINED; while (block_pack_status != e_block_pack_status::BLK_PASSED) { if (!get_next_primitive_list(cluster.placement_stats, - molecule, - primitives_list.data())) { + molecule_id, + primitives_list.data(), + prepacker_)) { VTR_LOGV(log_verbosity_ > 3, "\t\tFAILED No candidate primitives available\n"); block_pack_status = e_block_pack_status::BLK_FAILED_FEASIBLE; break; /* no more candidate primitives available, this molecule will not pack, return fail */ } block_pack_status = e_block_pack_status::BLK_PASSED; - int failed_location = 0; - for (int i_mol = 0; i_mol < molecule_size && block_pack_status == e_block_pack_status::BLK_PASSED; i_mol++) { - VTR_ASSERT((primitives_list[i_mol] == nullptr) == (!molecule->atom_block_ids[i_mol])); + size_t failed_location = 0; + for (size_t i_mol = 0; i_mol < molecule.atom_block_ids.size() && block_pack_status == e_block_pack_status::BLK_PASSED; i_mol++) { + VTR_ASSERT((primitives_list[i_mol] == nullptr) == (!molecule.atom_block_ids[i_mol])); failed_location = i_mol + 1; - AtomBlockId atom_blk_id = molecule->atom_block_ids[i_mol]; + AtomBlockId atom_blk_id = molecule.atom_block_ids[i_mol]; if (!atom_blk_id.is_valid()) continue; // NOTE: This parent variable is only used in the recursion of this @@ -1255,10 +1277,12 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul cluster_id, atom_cluster_, cluster.placement_stats, - molecule, + molecule_id, cluster.router_data, log_verbosity_, - feasible_block_array_size_); + feasible_block_array_size_, + prepacker_, + clustering_chain_info_); } if (enable_pin_feasibility_filter_ && block_pack_status == e_block_pack_status::BLK_PASSED) { @@ -1322,10 +1346,10 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul * TODO: SW Engineering note - may want to update cluster stats here too instead of doing it outside */ VTR_ASSERT(block_pack_status == e_block_pack_status::BLK_PASSED); - if (molecule->is_chain()) { + if (molecule.is_chain()) { /* Chained molecules often take up lots of area and are important, * if a chain is packed in, want to rename logic block to match chain name */ - AtomBlockId chain_root_blk_id = molecule->atom_block_ids[molecule->pack_pattern->root_block->block_id]; + AtomBlockId chain_root_blk_id = molecule.atom_block_ids[molecule.pack_pattern->root_block->block_id]; t_pb* cur_pb = atom_ctx.lookup.atom_pb(chain_root_blk_id)->parent_pb; while (cur_pb != nullptr) { free(cur_pb->name); @@ -1337,10 +1361,13 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul // If so, update the chain id for this chain of molecules to make sure all // molecules will be packed to the same chain id and can reach each other using // the chain direct links between clusters - if (molecule->chain_info->is_long_chain) { + VTR_ASSERT(molecule.chain_id.is_valid()); + const t_chain_info& prepack_chain_info = prepacker_.get_molecule_chain_info(molecule.chain_id); + if (prepack_chain_info.is_long_chain) { cluster.placement_stats->has_long_chain = true; - if (molecule->chain_info->chain_id == -1) { - update_molecule_chain_info(molecule, primitives_list[molecule->root]); + const t_clustering_chain_info& clustering_chain_info = clustering_chain_info_[molecule.chain_id]; + if (clustering_chain_info.chain_id == -1) { + update_clustering_chain_info(molecule_id, primitives_list[molecule.root]); } } } @@ -1356,10 +1383,10 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul cluster.noc_grp_id = new_cluster_noc_grp_id; // Insert the molecule into the cluster for bookkeeping. - cluster.molecules.push_back(molecule); + cluster.molecules.push_back(molecule_id); - for (int i = 0; i < molecule_size; i++) { - AtomBlockId atom_blk_id = molecule->atom_block_ids[i]; + for (size_t i = 0; i < molecule.atom_block_ids.size(); i++) { + AtomBlockId atom_blk_id = molecule.atom_block_ids[i]; if (!atom_blk_id.is_valid()) continue; @@ -1384,19 +1411,19 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul if (block_pack_status != e_block_pack_status::BLK_PASSED) { /* Pack unsuccessful, undo inserting molecule into cluster */ - for (int i = 0; i < failed_location; i++) { - AtomBlockId atom_blk_id = molecule->atom_block_ids[i]; + for (size_t i = 0; i < failed_location; i++) { + AtomBlockId atom_blk_id = molecule.atom_block_ids[i]; if (atom_blk_id) { remove_atom_from_target(cluster.router_data, atom_blk_id); } } - for (int i = 0; i < failed_location; i++) { - AtomBlockId atom_blk_id = molecule->atom_block_ids[i]; + for (size_t i = 0; i < failed_location; i++) { + AtomBlockId atom_blk_id = molecule.atom_block_ids[i]; if (atom_blk_id) { revert_place_atom_block(atom_blk_id, cluster.router_data, atom_cluster_); } } - reset_molecule_info(molecule); + reset_molecule_info(molecule_id); /* Packing failed, but a part of the pb tree is still allocated and pbs have their modes set. * Before trying to pack next molecule the unused pbs need to be freed and, the most important, @@ -1415,16 +1442,15 @@ e_block_pack_status ClusterLegalizer::try_pack_molecule(t_pack_molecule* molecul } std::tuple -ClusterLegalizer::start_new_cluster(t_pack_molecule* molecule, +ClusterLegalizer::start_new_cluster(PackMoleculeId molecule_id, t_logical_block_type_ptr cluster_type, int cluster_mode) { // Safety asserts to ensure the API is being called with valid arguments. - VTR_ASSERT_DEBUG(molecule != nullptr); + VTR_ASSERT_DEBUG(molecule_id.is_valid()); VTR_ASSERT_DEBUG(cluster_type != nullptr); VTR_ASSERT_DEBUG(cluster_mode < cluster_type->pb_graph_head->pb_type->num_modes); // Ensure that the molecule has not already been placed. - VTR_ASSERT_SAFE(molecule_cluster_.find(molecule) == molecule_cluster_.end() || - !molecule_cluster_[molecule].is_valid()); + VTR_ASSERT_SAFE(!molecule_cluster_[molecule_id].is_valid()); // Safety asserts to ensure that the API was initialized properly. VTR_ASSERT_DEBUG(lb_type_rr_graphs_ != nullptr); @@ -1458,7 +1484,7 @@ ClusterLegalizer::start_new_cluster(t_pack_molecule* molecule, // (meaning all cluster pins are allowed to be used). const t_ext_pin_util FULL_EXTERNAL_PIN_UTIL(1., 1.); LegalizationClusterId new_cluster_id = LegalizationClusterId(legalization_cluster_ids_.size()); - e_block_pack_status pack_status = try_pack_molecule(molecule, + e_block_pack_status pack_status = try_pack_molecule(molecule_id, new_cluster, new_cluster_id, FULL_EXTERNAL_PIN_UTIL); @@ -1466,7 +1492,8 @@ ClusterLegalizer::start_new_cluster(t_pack_molecule* molecule, if (pack_status == e_block_pack_status::BLK_PASSED) { // Give the new cluster pb a name. The current convention is to name the // cluster after the root atom of the first molecule packed into it. - AtomBlockId root_atom = molecule->atom_block_ids[molecule->root]; + const t_pack_molecule& molecule = prepacker_.get_molecule(molecule_id); + AtomBlockId root_atom = molecule.atom_block_ids[molecule.root]; const std::string& root_atom_name = atom_nlist.block_name(root_atom); if (new_cluster.pb->name != nullptr) free(new_cluster.pb->name); @@ -1475,7 +1502,7 @@ ClusterLegalizer::start_new_cluster(t_pack_molecule* molecule, legalization_cluster_ids_.push_back(new_cluster_id); legalization_clusters_.push_back(std::move(new_cluster)); // Update the molecule to cluster map. - molecule_cluster_[molecule] = new_cluster_id; + molecule_cluster_[molecule_id] = new_cluster_id; } else { // Delete the new_cluster. free_pb(new_cluster.pb); @@ -1488,14 +1515,13 @@ ClusterLegalizer::start_new_cluster(t_pack_molecule* molecule, return {pack_status, new_cluster_id}; } -e_block_pack_status ClusterLegalizer::add_mol_to_cluster(t_pack_molecule* molecule, +e_block_pack_status ClusterLegalizer::add_mol_to_cluster(PackMoleculeId molecule_id, LegalizationClusterId cluster_id) { // Safety asserts to make sure the inputs are valid. VTR_ASSERT_SAFE(cluster_id.is_valid() && (size_t)cluster_id < legalization_clusters_.size()); VTR_ASSERT(legalization_cluster_ids_[cluster_id].is_valid() && "Cannot add to a destroyed cluster"); // Ensure that the molecule has not already been placed. - VTR_ASSERT(molecule_cluster_.find(molecule) == molecule_cluster_.end() || - !molecule_cluster_[molecule].is_valid()); + VTR_ASSERT(!molecule_cluster_[molecule_id].is_valid()); // Safety asserts to ensure that the API was initialized properly. VTR_ASSERT_DEBUG(lb_type_rr_graphs_ != nullptr); @@ -1506,14 +1532,14 @@ e_block_pack_status ClusterLegalizer::add_mol_to_cluster(t_pack_molecule* molecu // Set the target_external_pin_util. t_ext_pin_util target_ext_pin_util = target_external_pin_util_.get_pin_util(cluster.type->name); // Try to pack the molecule into the cluster. - e_block_pack_status pack_status = try_pack_molecule(molecule, + e_block_pack_status pack_status = try_pack_molecule(molecule_id, cluster, cluster_id, target_ext_pin_util); // If the packing was successful, set the molecules' cluster to this one. if (pack_status == e_block_pack_status::BLK_PASSED) - molecule_cluster_[molecule] = cluster_id; + molecule_cluster_[molecule_id] = cluster_id; return pack_status; } @@ -1525,19 +1551,18 @@ void ClusterLegalizer::destroy_cluster(LegalizationClusterId cluster_id) { // Get the cluster. LegalizationCluster& cluster = legalization_clusters_[cluster_id]; // Remove all molecules from the cluster. - for (t_pack_molecule* mol : cluster.molecules) { - VTR_ASSERT_SAFE(molecule_cluster_.find(mol) != molecule_cluster_.end() && - molecule_cluster_[mol] == cluster_id); - molecule_cluster_[mol] = LegalizationClusterId::INVALID(); + for (PackMoleculeId mol_id : cluster.molecules) { + VTR_ASSERT_SAFE(molecule_cluster_[mol_id] == cluster_id); + molecule_cluster_[mol_id] = LegalizationClusterId::INVALID(); // Revert the placement of all blocks in the molecule. - int molecule_size = get_array_size_of_molecule(mol); - for (int i = 0; i < molecule_size; i++) { - AtomBlockId atom_blk_id = mol->atom_block_ids[i]; + const t_pack_molecule& mol = prepacker_.get_molecule(mol_id); + for (AtomBlockId atom_blk_id : mol.atom_block_ids) { if (atom_blk_id) { revert_place_atom_block(atom_blk_id, cluster.router_data, atom_cluster_); } } - reset_molecule_info(mol); + reset_molecule_info(mol_id); + molecule_cluster_[mol_id] = LegalizationClusterId::INVALID(); } cluster.molecules.clear(); // Free the rest of the cluster data. @@ -1563,10 +1588,11 @@ void ClusterLegalizer::compress() { legalization_cluster_ids_ = clean_and_reorder_ids(cluster_id_map); legalization_clusters_ = clean_and_reorder_values(legalization_clusters_, cluster_id_map); // Update the reverse lookups. - for (auto& it : molecule_cluster_) { - if (!it.second.is_valid()) + for (PackMoleculeId mol_id : prepacker_.molecules()) { + LegalizationClusterId old_cluster_id = molecule_cluster_[mol_id]; + if (!old_cluster_id.is_valid()) continue; - molecule_cluster_[it.first] = cluster_id_map[it.second]; + molecule_cluster_[mol_id] = cluster_id_map[old_cluster_id]; } for (size_t i = 0; i < atom_cluster_.size(); i++) { AtomBlockId atom_blk_id = AtomBlockId(i); @@ -1635,8 +1661,12 @@ ClusterLegalizer::ClusterLegalizer(const AtomNetlist& atom_netlist, // NOTE: Be careful with this constructor, it may throw a VPR_FATAL_ERROR. target_external_pin_util_ = t_ext_pin_util_targets(target_external_pin_util_str); + // Resize the molecule_cluster lookup to make the accesses much cheaper. + molecule_cluster_.resize(prepacker_.molecules().size(), LegalizationClusterId::INVALID()); // Resize the atom_cluster lookup to make the accesses much cheaper. atom_cluster_.resize(atom_netlist.blocks().size(), LegalizationClusterId::INVALID()); + // Default the clustering chain info for each chain. + clustering_chain_info_.resize(prepacker_.get_num_molecule_chains()); // Pre-compute the max size of any molecule. max_molecule_size_ = prepacker.get_max_molecule_size(); // Calculate the max cluster size @@ -1668,8 +1698,6 @@ void ClusterLegalizer::reset() { destroy_cluster(cluster_id); } compress(); - // Reset the molecule_cluster map - molecule_cluster_.clear(); } void ClusterLegalizer::verify() { @@ -1740,9 +1768,9 @@ void ClusterLegalizer::verify() { } } -bool ClusterLegalizer::is_molecule_compatible(t_pack_molecule* molecule, +bool ClusterLegalizer::is_molecule_compatible(PackMoleculeId molecule_id, LegalizationClusterId cluster_id) const { - VTR_ASSERT_SAFE(molecule != nullptr); + VTR_ASSERT_SAFE(molecule_id.is_valid()); VTR_ASSERT_SAFE(cluster_id.is_valid() && (size_t)cluster_id < legalization_clusters_.size()); // Go through each atom in the molecule and check if there exists a free // primitive for that atom block. @@ -1753,7 +1781,8 @@ bool ClusterLegalizer::is_molecule_compatible(t_pack_molecule* molecule, // would be more robust, but checking individual atoms is faster. const LegalizationCluster& cluster = legalization_clusters_[cluster_id]; - for (AtomBlockId atom_blk_id : molecule->atom_block_ids) { + const t_pack_molecule& molecule = prepacker_.get_molecule(molecule_id); + for (AtomBlockId atom_blk_id : molecule.atom_block_ids) { // FIXME: Why is it possible that molecules contain invalid block IDs? // This should be fixed! if (!atom_blk_id.is_valid()) diff --git a/vpr/src/pack/cluster_legalizer.h b/vpr/src/pack/cluster_legalizer.h index ef3ec64f7b2..e2f57486581 100644 --- a/vpr/src/pack/cluster_legalizer.h +++ b/vpr/src/pack/cluster_legalizer.h @@ -12,17 +12,18 @@ #pragma once -#include #include #include "atom_netlist_fwd.h" #include "noc_data_types.h" #include "partition_region.h" +#include "prepack.h" #include "vpr_types.h" #include "vtr_range.h" #include "vtr_strong_id.h" #include "vtr_vector.h" #include "vtr_vector_map.h" +// Forward declarations class Prepacker; class t_intra_cluster_placement_stats; class t_pb_graph_node; @@ -34,6 +35,32 @@ struct t_lb_router_data; struct legalization_cluster_id_tag; typedef vtr::StrongId LegalizationClusterId; +/** + * @brief Holds information to be shared between molecules that represent the + * same chained pack pattern, specifically for packing. + * + * For example, molecules that are representing a long carry chain that spans + * multiple logic blocks. + * + * This is holding clustering-specific information on the chains. General + * information on chains is found in the t_chain_info type. + */ +struct t_clustering_chain_info { + /// @brief An ID into the chain_root_pins vector in the t_pack_patterns of + /// the molecule. + /// + /// Used to get the starting point of this chain in the cluster. This ID is + /// useful when we have multiple (architectural) carry chains in a logic + /// block, for example. It lets us see which of the chains is being used for + /// this long (netlist) chain, so we continue to use that chain in the + /// packing of other molecules of this long chain. + int chain_id = -1; + + /// @brief First molecule to be packed out of the molecules forming this + /// chain. This is the molecule setting the value of the chain_id. + PackMoleculeId first_packed_molecule; +}; + /// @brief The different legalization strategies the cluster legalizer can perform. /// /// Allows the user of the API to select how thorough the legalizer should be @@ -62,7 +89,7 @@ struct LegalizationCluster { /// @brief A list of the molecules in the cluster. By design, a cluster will /// only contain molecules which have been previously legalized into /// the cluster using a legalization strategy. - std::vector molecules; + std::vector molecules; /// @brief The logical block of this cluster. /// TODO: We should be more careful with how this is allocated. Instead of @@ -186,11 +213,28 @@ class ClusterLegalizer { * @param max_external_pin_util The max external pin utilization for a * cluster of this type. */ - e_block_pack_status try_pack_molecule(t_pack_molecule* molecule, + e_block_pack_status try_pack_molecule(PackMoleculeId molecule_id, LegalizationCluster& cluster, LegalizationClusterId cluster_id, const t_ext_pin_util& max_external_pin_util); + /** + * @brief This function takes a chain molecule, and the pb_graph_node that is + * chosen for packing the molecule's root block. Using the given + * root_primitive, this function will identify which chain id this + * molecule is being mapped to and will update the chain id value inside + * the chain info data structure of this molecule. + */ + void update_clustering_chain_info(PackMoleculeId chain_molecule_id, + const t_pb_graph_node* root_primitive); + + /* + * @brief Reset molecule information created while trying to cluster it. + * + * This code only resets information that has to do with long chains. + */ + void reset_molecule_info(PackMoleculeId mol_id); + public: // Explicitly deleted default constructor. Need to use other constructor to @@ -272,7 +316,7 @@ class ClusterLegalizer { * status will return the reason and the ID would be invalid. */ std::tuple - start_new_cluster(t_pack_molecule* molecule, + start_new_cluster(PackMoleculeId molecule_id, t_logical_block_type_ptr cluster_type, int cluster_mode); @@ -292,7 +336,7 @@ class ClusterLegalizer { * @return The status of the pack (if the addition was successful and * if not why). */ - e_block_pack_status add_mol_to_cluster(t_pack_molecule* molecule, + e_block_pack_status add_mol_to_cluster(PackMoleculeId molecule_id, LegalizationClusterId cluster_id); /* @@ -396,7 +440,7 @@ class ClusterLegalizer { * go in a cluster. By calling it you can save runtime for impossible cases * vs. calling the full checks. */ - bool is_molecule_compatible(t_pack_molecule* molecule, + bool is_molecule_compatible(PackMoleculeId molecule_id, LegalizationClusterId cluster_id) const; /// @brief Gets the top-level pb of the given cluster. @@ -446,17 +490,11 @@ class ClusterLegalizer { /// @brief Returns true if the given molecule has been packed into a /// cluster, false otherwise. - inline bool is_mol_clustered(t_pack_molecule* mol) const { - VTR_ASSERT_SAFE(mol != nullptr); + inline bool is_mol_clustered(PackMoleculeId mol_id) const { + VTR_ASSERT_SAFE(mol_id.is_valid()); // Check if the molecule has been assigned a cluster. It has not been - // assigned a cluster if it does not have an entry in the map or if the - // ID of the cluster it is assigned to is invalid. - const auto iter = molecule_cluster_.find(mol); - if (iter == molecule_cluster_.end()) - return false; - if (!iter->second.is_valid()) - return false; - return true; + // assigned a cluster if it is assigned to a valid cluster. + return molecule_cluster_[mol_id].is_valid(); } /// @brief Returns a reference to the target_external_pin_util object. This @@ -512,7 +550,10 @@ class ClusterLegalizer { vtr::vector_map legalization_cluster_ids_; /// @brief Lookup table for which cluster each molecule is in. - std::unordered_map molecule_cluster_; + vtr::vector_map molecule_cluster_; + + /// @brief Clustering chain information for each of the chains in the prepacker. + vtr::vector_map clustering_chain_info_; /// @brief List of all legalization clusters. vtr::vector_map legalization_clusters_; diff --git a/vpr/src/pack/cluster_placement.cpp b/vpr/src/pack/cluster_placement.cpp index 917545cd3ba..2241a9ba9a2 100644 --- a/vpr/src/pack/cluster_placement.cpp +++ b/vpr/src/pack/cluster_placement.cpp @@ -20,6 +20,7 @@ #include "cluster_placement.h" #include "hash.h" #include "physical_types.h" +#include "prepack.h" #include "vpr_types.h" #include "vpr_utils.h" #include "vtr_assert.h" @@ -43,14 +44,16 @@ static void update_primitive_cost_or_status(t_intra_cluster_placement_stats* clu bool valid); static float try_place_molecule(t_intra_cluster_placement_stats* cluster_placement_stats, - const t_pack_molecule* molecule, + PackMoleculeId molecule_id, t_pb_graph_node* root, - t_pb_graph_node** primitives_list); + t_pb_graph_node** primitives_list, + const Prepacker& prepacker); static bool expand_forced_pack_molecule_placement(t_intra_cluster_placement_stats* cluster_placement_stats, - const t_pack_molecule* molecule, + PackMoleculeId molecule_id, const t_pack_pattern_block* pack_pattern_block, t_pb_graph_node** primitives_list, + const Prepacker& prepacker, float* cost); static t_pb_graph_pin* expand_pack_molecule_pin_edge(int pattern_id, @@ -154,7 +157,7 @@ t_intra_cluster_placement_stats* alloc_and_load_cluster_placement_stats(t_logica // The reset and setting the mode can be done while loading the placement // stats. if (!is_empty_type(cluster_type)) { - cluster_placement_stats->curr_molecule = nullptr; + cluster_placement_stats->curr_molecule = PackMoleculeId::INVALID(); load_cluster_placement_stats_for_pb_graph_node(cluster_placement_stats, cluster_type->pb_graph_head); } @@ -173,19 +176,19 @@ void free_cluster_placement_stats(t_intra_cluster_placement_stats* cluster_place } bool get_next_primitive_list(t_intra_cluster_placement_stats* cluster_placement_stats, - const t_pack_molecule* molecule, + PackMoleculeId molecule_id, t_pb_graph_node** primitives_list, + const Prepacker& prepacker, int force_site) { std::unordered_multimap::iterator best; - int i; float cost, lowest_cost; int best_pb_type_index = -1; - if (cluster_placement_stats->curr_molecule != molecule) { + if (cluster_placement_stats->curr_molecule != molecule_id) { /* New block, requeue tried primitives and in-flight primitives */ cluster_placement_stats->flush_intermediate_queues(); - cluster_placement_stats->curr_molecule = molecule; + cluster_placement_stats->curr_molecule = molecule_id; } else { /* Hack! Same failed molecule may re-enter if upper stream functions suck, * I'm going to make the molecule selector more intelligent. @@ -210,10 +213,11 @@ bool get_next_primitive_list(t_intra_cluster_placement_stats* cluster_placement_ lowest_cost = HUGE_POSITIVE_FLOAT; // Iterate over each primitive block type in the current cluster_placement_stats - for (i = 0; i < cluster_placement_stats->num_pb_types; i++) { + for (int i = 0; i < cluster_placement_stats->num_pb_types; i++) { if (!cluster_placement_stats->valid_primitives[i].empty()) { t_cluster_placement_primitive* cur_cluster_placement_primitive = cluster_placement_stats->valid_primitives[i].begin()->second; - if (primitive_type_feasible(molecule->atom_block_ids[molecule->root], cur_cluster_placement_primitive->pb_graph_node->pb_type)) { + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + if (primitive_type_feasible(molecule.atom_block_ids[molecule.root], cur_cluster_placement_primitive->pb_graph_node->pb_type)) { // Iterate over the unordered_multimap of the valid primitives of a specific pb primitive type for (auto it = cluster_placement_stats->valid_primitives[i].begin(); it != cluster_placement_stats->valid_primitives[i].end(); /*loop increment is done inside the loop*/) { //Lazily remove invalid primitives @@ -233,9 +237,10 @@ bool get_next_primitive_list(t_intra_cluster_placement_stats* cluster_placement_ } if (force_site == it->second->pb_graph_node->flat_site_index) { cost = try_place_molecule(cluster_placement_stats, - molecule, + molecule_id, it->second->pb_graph_node, - primitives_list); + primitives_list, + prepacker); if (cost < HUGE_POSITIVE_FLOAT) { cluster_placement_stats->move_primitive_to_inflight(i, it); return true; @@ -250,9 +255,10 @@ bool get_next_primitive_list(t_intra_cluster_placement_stats* cluster_placement_ /* try place molecule at root location cur */ cost = try_place_molecule(cluster_placement_stats, - molecule, + molecule_id, it->second->pb_graph_node, - primitives_list); + primitives_list, + prepacker); // if the cost is lower than the best, or is equal to the best but this // primitive is more available in the cluster mark it as the best primitive @@ -275,15 +281,17 @@ bool get_next_primitive_list(t_intra_cluster_placement_stats* cluster_placement_ if (!found_best) { /* failed to find a placement */ - for (i = 0; i < molecule->num_blocks; i++) { + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + for (size_t i = 0; i < molecule.atom_block_ids.size(); i++) { primitives_list[i] = nullptr; } } else { /* populate primitive list with best */ cost = try_place_molecule(cluster_placement_stats, - molecule, + molecule_id, best->second->pb_graph_node, - primitives_list); + primitives_list, + prepacker); VTR_ASSERT(cost == lowest_cost); /* take out best node and put it in flight */ @@ -313,7 +321,7 @@ static void reset_cluster_placement_stats(t_intra_cluster_placement_stats* clust primitive.second->valid = true; } } - cluster_placement_stats->curr_molecule = nullptr; + cluster_placement_stats->curr_molecule = PackMoleculeId::INVALID(); cluster_placement_stats->has_long_chain = false; } @@ -444,20 +452,18 @@ static void update_primitive_cost_or_status(t_intra_cluster_placement_stats* clu const t_pb_graph_node* pb_graph_node, const float incremental_cost, const bool valid) { - int i, j, k; - t_cluster_placement_primitive* placement_primitive; if (pb_graph_node->is_primitive()) { /* is primitive */ - placement_primitive = cluster_placement_stats->get_pb_graph_node_placement_primitive(pb_graph_node); + t_cluster_placement_primitive* placement_primitive = cluster_placement_stats->get_pb_graph_node_placement_primitive(pb_graph_node); if (valid) { placement_primitive->incremental_cost += incremental_cost; } else { placement_primitive->valid = false; } } else { - for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) { - for (j = 0; j < pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) { - for (k = 0; k < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb; k++) { + for (int i = 0; i < pb_graph_node->pb_type->num_modes; i++) { + for (int j = 0; j < pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) { + for (int k = 0; k < pb_graph_node->pb_type->modes[i].pb_type_children[j].num_pb; k++) { update_primitive_cost_or_status(cluster_placement_stats, &pb_graph_node->child_pb_graph_nodes[i][j][k], incremental_cost, valid); @@ -471,35 +477,37 @@ static void update_primitive_cost_or_status(t_intra_cluster_placement_stats* clu * Try place molecule at root location, populate primitives list with locations of placement if successful */ static float try_place_molecule(t_intra_cluster_placement_stats* cluster_placement_stats, - const t_pack_molecule* molecule, + PackMoleculeId molecule_id, t_pb_graph_node* root, - t_pb_graph_node** primitives_list) { - int list_size, i; + t_pb_graph_node** primitives_list, + const Prepacker& prepacker) { float cost = HUGE_POSITIVE_FLOAT; - list_size = get_array_size_of_molecule(molecule); + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + size_t list_size = molecule.atom_block_ids.size(); - if (primitive_type_feasible(molecule->atom_block_ids[molecule->root], + if (primitive_type_feasible(molecule.atom_block_ids[molecule.root], root->pb_type)) { t_cluster_placement_primitive* root_placement_primitive = cluster_placement_stats->get_pb_graph_node_placement_primitive(root); if (root_placement_primitive->valid) { - for (i = 0; i < list_size; i++) { + for (size_t i = 0; i < list_size; i++) { primitives_list[i] = nullptr; } cost = root_placement_primitive->base_cost + root_placement_primitive->incremental_cost; - primitives_list[molecule->root] = root; - if (molecule->type == MOLECULE_FORCED_PACK) { + primitives_list[molecule.root] = root; + if (molecule.type == e_pack_pattern_molecule_type::MOLECULE_FORCED_PACK) { if (!expand_forced_pack_molecule_placement(cluster_placement_stats, - molecule, - molecule->pack_pattern->root_block, + molecule_id, + molecule.pack_pattern->root_block, primitives_list, + prepacker, &cost)) { return HUGE_POSITIVE_FLOAT; } } - for (i = 0; i < list_size; i++) { - VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule->atom_block_ids[i])); - for (int j = 0; j < list_size; j++) { + for (size_t i = 0; i < list_size; i++) { + VTR_ASSERT((primitives_list[i] == nullptr) == (!molecule.atom_block_ids[i])); + for (size_t j = 0; j < list_size; j++) { if (i != j) { if (primitives_list[i] != nullptr && primitives_list[i] == primitives_list[j]) { return HUGE_POSITIVE_FLOAT; @@ -517,9 +525,10 @@ static float try_place_molecule(t_intra_cluster_placement_stats* cluster_placeme * Assumes molecule and pack pattern connections have fan-out 1 */ static bool expand_forced_pack_molecule_placement(t_intra_cluster_placement_stats* cluster_placement_stats, - const t_pack_molecule* molecule, + PackMoleculeId molecule_id, const t_pack_pattern_block* pack_pattern_block, t_pb_graph_node** primitives_list, + const Prepacker& prepacker, float* cost) { t_pb_graph_node* pb_graph_node = primitives_list[pack_pattern_block->block_id]; t_pb_graph_node* next_primitive; @@ -534,7 +543,8 @@ static bool expand_forced_pack_molecule_placement(t_intra_cluster_placement_stat } else { next_block = cur->from_block; } - if (primitives_list[next_block->block_id] == nullptr && molecule->atom_block_ids[next_block->block_id]) { + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + if (primitives_list[next_block->block_id] == nullptr && molecule.atom_block_ids[next_block->block_id]) { /* first time visiting location */ /* find next primitive based on pattern connections, expand next primitive if not visited */ @@ -563,12 +573,12 @@ static bool expand_forced_pack_molecule_placement(t_intra_cluster_placement_stat if (next_pin != nullptr) { next_primitive = next_pin->parent_node; /* Check for legality of placement, if legal, expand from legal placement, if not, return false */ - if (molecule->atom_block_ids[next_block->block_id] && primitives_list[next_block->block_id] == nullptr) { + if (molecule.atom_block_ids[next_block->block_id] && primitives_list[next_block->block_id] == nullptr) { t_cluster_placement_primitive* next_placement_primitive = cluster_placement_stats->get_pb_graph_node_placement_primitive(next_primitive); - if (next_placement_primitive->valid && primitive_type_feasible(molecule->atom_block_ids[next_block->block_id], next_primitive->pb_type)) { + if (next_placement_primitive->valid && primitive_type_feasible(molecule.atom_block_ids[next_block->block_id], next_primitive->pb_type)) { primitives_list[next_block->block_id] = next_primitive; *cost += next_placement_primitive->base_cost + next_placement_primitive->incremental_cost; - if (!expand_forced_pack_molecule_placement(cluster_placement_stats, molecule, next_block, primitives_list, cost)) { + if (!expand_forced_pack_molecule_placement(cluster_placement_stats, molecule_id, next_block, primitives_list, prepacker, cost)) { return false; } } else { @@ -685,15 +695,6 @@ static t_pb_graph_pin* expand_pack_molecule_pin_edge(const int pattern_id, return dest_pin; } -/* Determine max index + 1 of molecule */ -int get_array_size_of_molecule(const t_pack_molecule* molecule) { - if (molecule->type == MOLECULE_FORCED_PACK) { - return molecule->pack_pattern->num_blocks; - } else { - return molecule->num_blocks; - } -} - /* Given atom block, determines if a free primitive exists for it */ bool exists_free_primitive_for_atom_block(t_intra_cluster_placement_stats* cluster_placement_stats, const AtomBlockId blk_id) { @@ -727,3 +728,4 @@ bool exists_free_primitive_for_atom_block(t_intra_cluster_placement_stats* clust void reset_tried_but_unused_cluster_placements(t_intra_cluster_placement_stats* cluster_placement_stats) { cluster_placement_stats->flush_intermediate_queues(); } + diff --git a/vpr/src/pack/cluster_placement.h b/vpr/src/pack/cluster_placement.h index f3d840457ca..40632e3b949 100644 --- a/vpr/src/pack/cluster_placement.h +++ b/vpr/src/pack/cluster_placement.h @@ -9,7 +9,10 @@ #include #include #include "physical_types.h" -#include "vpr_types.h" +#include "prepack.h" + +// Forward declarations +class AtomBlockId; /** * @brief Stats keeper for placement within the cluster during packing @@ -20,7 +23,7 @@ class t_intra_cluster_placement_stats { public: int num_pb_types; /// molecules_vector = prepacker.get_molecules_vector(); + std::vector molecules_vector; + molecules_vector.assign(prepacker.molecules().begin(), prepacker.molecules().end()); std::stable_sort(molecules_vector.begin(), molecules_vector.end(), - [](t_pack_molecule* a, t_pack_molecule* b) { - return a->base_gain > b->base_gain; + [&](PackMoleculeId a_id, PackMoleculeId b_id) { + const t_pack_molecule& a = prepacker.get_molecule(a_id); + const t_pack_molecule& b = prepacker.get_molecule(b_id); + + return a.base_gain > b.base_gain; }); // Push back the each molecule into the unrelated clustering data vector // for their external inputs. This creates individual sorted lists of // molecules for each number of used external inputs. - for (t_pack_molecule* mol : molecules_vector) { + for (PackMoleculeId mol_id : molecules_vector) { //Figure out how many external inputs are used by this molecule - t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(mol, atom_netlist); + t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(mol_id, atom_netlist); int ext_inps = molecule_stats.num_used_ext_inputs; //Insert the molecule into the unclustered lists by number of external inputs - unrelated_clustering_data_[ext_inps].push_back(mol); + unrelated_clustering_data_[ext_inps].push_back(mol_id); } } @@ -138,15 +145,15 @@ GreedyCandidateSelector::GreedyCandidateSelector( size_t num_layers = std::floor(max_layer) + 1; flat_tile_placement_.resize({x_dim, y_dim, num_layers}); // Populate the ND-Matrix with each of the molecules. - std::unordered_set seen_molecules; + std::unordered_set seen_molecules; for (AtomBlockId blk_id : atom_netlist_.blocks()) { VTR_ASSERT(flat_placement_info.blk_x_pos[blk_id] != -1.f && flat_placement_info.blk_y_pos[blk_id] != -1.f && flat_placement_info.blk_layer[blk_id] != -1.f); // Get the molecule for this atom block. - t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk_id); + PackMoleculeId blk_mol_id = prepacker.get_atom_molecule(blk_id); // Skip if we have already seen this molecule. - if (seen_molecules.count(blk_mol) != 0) + if (seen_molecules.count(blk_mol_id) != 0) continue; // Insert the molecule into the appropriate list size_t tile_x = std::floor(flat_placement_info.blk_x_pos[blk_id]); @@ -154,12 +161,12 @@ GreedyCandidateSelector::GreedyCandidateSelector( size_t tile_layer = std::floor(flat_placement_info.blk_layer[blk_id]); FlatTileMoleculeList& tile_mol_list = flat_tile_placement_[tile_x][tile_y][tile_layer]; if (flat_placement_info.blk_sub_tile[blk_id] == -1) { - tile_mol_list.undefined_sub_tile_mols.push_back(blk_mol); + tile_mol_list.undefined_sub_tile_mols.push_back(blk_mol_id); } else { size_t sub_tile = flat_placement_info.blk_sub_tile[blk_id]; if (sub_tile >= tile_mol_list.sub_tile_mols.size()) tile_mol_list.sub_tile_mols.resize(sub_tile + 1); - tile_mol_list.sub_tile_mols[sub_tile].push_back(blk_mol); + tile_mol_list.sub_tile_mols[sub_tile].push_back(blk_mol_id); } } } @@ -169,20 +176,20 @@ GreedyCandidateSelector::~GreedyCandidateSelector() { } ClusterGainStats GreedyCandidateSelector::create_cluster_gain_stats( - t_pack_molecule* cluster_seed_mol, + PackMoleculeId cluster_seed_mol_id, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { // Initialize the cluster gain stats. ClusterGainStats cluster_gain_stats; - cluster_gain_stats.seed_molecule = cluster_seed_mol; + cluster_gain_stats.seed_molecule_id = cluster_seed_mol_id; cluster_gain_stats.num_feasible_blocks = NOT_VALID; cluster_gain_stats.has_done_connectivity_and_timing = false; // TODO: The reason this is being resized and not reserved is due to legacy // code which should be updated. cluster_gain_stats.feasible_blocks.resize(packer_opts_.feasible_block_array_size); for (int i = 0; i < packer_opts_.feasible_block_array_size; i++) - cluster_gain_stats.feasible_blocks[i] = nullptr; + cluster_gain_stats.feasible_blocks[i] = PackMoleculeId::INVALID(); cluster_gain_stats.tie_break_high_fanout_net = AtomNetId::INVALID(); cluster_gain_stats.explore_transitive_fanout = true; @@ -191,7 +198,7 @@ ClusterGainStats GreedyCandidateSelector::create_cluster_gain_stats( // TODO: We may want to update the cluster gain stats different, knowing // that this candidate was the seed molecule. update_cluster_gain_stats_candidate_success(cluster_gain_stats, - cluster_seed_mol, + cluster_seed_mol_id, cluster_id, cluster_legalizer, attraction_groups); @@ -202,10 +209,11 @@ ClusterGainStats GreedyCandidateSelector::create_cluster_gain_stats( void GreedyCandidateSelector::update_cluster_gain_stats_candidate_success( ClusterGainStats& cluster_gain_stats, - t_pack_molecule* successful_mol, + PackMoleculeId successful_mol_id, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { + VTR_ASSERT(successful_mol_id.is_valid()); // TODO: If this threshold lookup gets expensive, move outside. int high_fanout_net_threshold = high_fanout_thresholds_.get_threshold(cluster_legalizer.get_cluster_type(cluster_id)->name); @@ -215,9 +223,8 @@ void GreedyCandidateSelector::update_cluster_gain_stats_candidate_success( // pins, and clock structures, in order to reflect the new content of the // cluster. Also keeps track of which attraction group the cluster belongs // to. - int molecule_size = get_array_size_of_molecule(successful_mol); - for (int iblock = 0; iblock < molecule_size; iblock++) { - AtomBlockId blk_id = successful_mol->atom_block_ids[iblock]; + const t_pack_molecule& successful_mol = prepacker_.get_molecule(successful_mol_id); + for (AtomBlockId blk_id : successful_mol.atom_block_ids) { if (!blk_id) { continue; } @@ -285,7 +292,7 @@ void GreedyCandidateSelector::update_cluster_gain_stats_candidate_success( } // if this molecule came from the transitive fanout candidates remove it - cluster_gain_stats.transitive_fanout_candidates.erase(successful_mol->atom_block_ids[successful_mol->root]); + cluster_gain_stats.transitive_fanout_candidates.erase(successful_mol.atom_block_ids[successful_mol.root]); cluster_gain_stats.explore_transitive_fanout = true; // Whenever a new molecule has been clustered, reset the number of @@ -563,21 +570,22 @@ void GreedyCandidateSelector::update_total_gain(ClusterGainStats& cluster_gain_s } } -void GreedyCandidateSelector::update_cluster_gain_stats_candidate_failed(ClusterGainStats& cluster_gain_stats, - t_pack_molecule* failed_mol) { - auto got = cluster_gain_stats.atom_failures.find(failed_mol->atom_block_ids[0]); - if (got == cluster_gain_stats.atom_failures.end()) { - cluster_gain_stats.atom_failures.insert({failed_mol->atom_block_ids[0], 1}); +void GreedyCandidateSelector::update_cluster_gain_stats_candidate_failed( + ClusterGainStats& cluster_gain_stats, + PackMoleculeId failed_mol_id) { + VTR_ASSERT(failed_mol_id.is_valid()); + auto got = cluster_gain_stats.mol_failures.find(failed_mol_id); + if (got == cluster_gain_stats.mol_failures.end()) { + cluster_gain_stats.mol_failures.insert({failed_mol_id, 1}); } else { got->second++; } } -t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( +PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster( ClusterGainStats& cluster_gain_stats, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, - const Prepacker& prepacker, AttractionInfo& attraction_groups) { /* Finds the block with the greatest gain that satisfies the * input, clock and capacity constraints of a cluster that are @@ -621,7 +629,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( !cluster_gain_stats.has_done_connectivity_and_timing) { add_cluster_molecule_candidates_by_connectivity_and_timing(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); cluster_gain_stats.has_done_connectivity_and_timing = true; @@ -632,7 +639,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( cluster_gain_stats.num_feasible_blocks = 0; add_cluster_molecule_candidates_by_connectivity_and_timing(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); cluster_gain_stats.has_done_connectivity_and_timing = true; @@ -644,7 +650,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) { add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); } @@ -653,7 +658,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) { add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); } @@ -662,7 +666,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) { add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); } @@ -671,7 +674,6 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) { add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); } @@ -681,13 +683,12 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( if (cluster_gain_stats.num_feasible_blocks == 0) { add_cluster_molecule_candidates_by_attraction_group(cluster_gain_stats, cluster_id, - prepacker, cluster_legalizer, attraction_groups); } /* Grab highest gain molecule */ // If this was a vector, this would just be a pop_back. - t_pack_molecule* best_molecule = nullptr; + PackMoleculeId best_molecule = PackMoleculeId::INVALID(); if (cluster_gain_stats.num_feasible_blocks > 0) { cluster_gain_stats.num_feasible_blocks--; int index = cluster_gain_stats.num_feasible_blocks; @@ -697,7 +698,7 @@ t_pack_molecule* GreedyCandidateSelector::get_next_candidate_for_cluster( // If we are allowing unrelated clustering and no molecule has been found, // get unrelated candidate for cluster. - if (allow_unrelated_clustering_ && best_molecule == nullptr) { + if (allow_unrelated_clustering_ && best_molecule == PackMoleculeId::INVALID()) { if (num_unrelated_clustering_attempts_ < max_unrelated_clustering_attempts_) { best_molecule = get_unrelated_candidate_for_cluster(cluster_id, cluster_legalizer); @@ -721,7 +722,8 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_flat_placement( const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { // Get the seed molecule root block. - AtomBlockId root_blk_id = cluster_gain_stats.seed_molecule->atom_block_ids[cluster_gain_stats.seed_molecule->root]; + const t_pack_molecule& seed_molecule = prepacker_.get_molecule(cluster_gain_stats.seed_molecule_id); + AtomBlockId root_blk_id = seed_molecule.atom_block_ids[seed_molecule.root]; // TODO: Instead of just using the seed, maybe we should get the candidates // of all molecules in the cluster? However, this may have its own // problems. @@ -733,17 +735,18 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_flat_placement( // tile or having an "unkown sub-tile" bin. VTR_ASSERT(sub_tile >= 0); // Add all of the molecules in the current tile as candidates. - const std::vector& mols_in_tile = flat_tile_placement_[tile_x][tile_y][tile_layer].sub_tile_mols[sub_tile]; + const std::vector& mols_in_tile = flat_tile_placement_[tile_x][tile_y][tile_layer].sub_tile_mols[sub_tile]; - for (t_pack_molecule* molecule : mols_in_tile) { + for (PackMoleculeId molecule_id : mols_in_tile) { // Add the molecule as a candidate if the molecule is not clustered and // is compatible with this cluster (using simple checks). - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, packer_opts_.feasible_block_array_size, attraction_groups, + prepacker_, atom_netlist_); } } @@ -752,22 +755,22 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_flat_placement( void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_and_timing( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */ for (AtomBlockId blk_id : cluster_gain_stats.marked_blocks) { // Get the molecule that contains this block. - t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id); + PackMoleculeId molecule_id = prepacker_.get_atom_molecule(blk_id); // Add the molecule as a candidate if the molecule is not clustered and // is compatible with this cluster (using simple checks). - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, packer_opts_.feasible_block_array_size, attraction_groups, + prepacker_, atom_netlist_); } } @@ -776,7 +779,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_connectivity( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { //TODO: For now, only done by fan-out; should also consider fan-in @@ -785,19 +787,19 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn /* First time finding transitive fanout candidates therefore alloc and load them */ load_transitive_fanout_candidates(cluster_gain_stats, legalization_cluster_id, - prepacker, cluster_legalizer); /* Only consider candidates that pass a very simple legality check */ for (const auto& transitive_candidate : cluster_gain_stats.transitive_fanout_candidates) { - t_pack_molecule* molecule = transitive_candidate.second; - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + PackMoleculeId molecule_id = transitive_candidate.second; + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, std::min(packer_opts_.feasible_block_array_size, AAPACK_MAX_TRANSITIVE_EXPLORE), attraction_groups, + prepacker_, atom_netlist_); } } @@ -806,7 +808,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_connectivity( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { /* Because the packer ignores high fanout nets when marking what blocks @@ -823,14 +824,15 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn AtomBlockId blk_id = atom_netlist_.pin_block(pin_id); - t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id); - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + PackMoleculeId molecule_id = prepacker_.get_atom_molecule(blk_id); + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, std::min(packer_opts_.feasible_block_array_size, AAPACK_MAX_HIGH_FANOUT_EXPLORE), attraction_groups, + prepacker_, atom_netlist_); count++; } @@ -841,7 +843,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_group( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups) { auto cluster_type = cluster_legalizer.get_cluster_type(legalization_cluster_id); @@ -883,13 +884,14 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou if (num_available_atoms < attraction_group_num_atoms_threshold_) { for (AtomBlockId atom_id : available_atoms) { //Only consider molecules that are unpacked and of the correct type - t_pack_molecule* molecule = prepacker.get_atom_molecule(atom_id); - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + PackMoleculeId molecule_id = prepacker_.get_atom_molecule(atom_id); + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, packer_opts_.feasible_block_array_size, attraction_groups, + prepacker_, atom_netlist_); } } @@ -903,13 +905,14 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou AtomBlockId blk_id = available_atoms[selected_atom]; //Only consider molecules that are unpacked and of the correct type - t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id); - if (!cluster_legalizer.is_mol_clustered(molecule) && - cluster_legalizer.is_molecule_compatible(molecule, legalization_cluster_id)) { - add_molecule_to_pb_stats_candidates(molecule, + PackMoleculeId molecule_id = prepacker_.get_atom_molecule(blk_id); + if (!cluster_legalizer.is_mol_clustered(molecule_id) && + cluster_legalizer.is_molecule_compatible(molecule_id, legalization_cluster_id)) { + add_molecule_to_pb_stats_candidates(molecule_id, cluster_gain_stats, packer_opts_.feasible_block_array_size, attraction_groups, + prepacker_, atom_netlist_); } } @@ -918,11 +921,13 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou /* * @brief Add blk to list of feasible blocks sorted according to gain. */ -static void add_molecule_to_pb_stats_candidates(t_pack_molecule* molecule, +static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id, ClusterGainStats& cluster_gain_stats, int max_queue_size, AttractionInfo& attraction_groups, + const Prepacker& prepacker, const AtomNetlist& atom_netlist) { + int num_molecule_failures = 0; AttractGroupId cluster_att_grp = cluster_gain_stats.attraction_grp_id; @@ -932,55 +937,56 @@ static void add_molecule_to_pb_stats_candidates(t_pack_molecule* molecule, * more molecules helps to achieve this purpose. */ if (attraction_groups.num_attraction_groups() > 0) { - auto got = cluster_gain_stats.atom_failures.find(molecule->atom_block_ids[0]); - if (got == cluster_gain_stats.atom_failures.end()) { + VTR_ASSERT(molecule_id.is_valid()); + auto got = cluster_gain_stats.mol_failures.find(molecule_id); + if (got == cluster_gain_stats.mol_failures.end()) { num_molecule_failures = 0; } else { num_molecule_failures = got->second; } if (num_molecule_failures > 0) { - remove_molecule_from_pb_stats_candidates(molecule, cluster_gain_stats); + remove_molecule_from_pb_stats_candidates(molecule_id, cluster_gain_stats); return; } } for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) { - if (cluster_gain_stats.feasible_blocks[i] == molecule) { + if (cluster_gain_stats.feasible_blocks[i] == molecule_id) { return; // already in queue, do nothing } } if (cluster_gain_stats.num_feasible_blocks >= max_queue_size - 1) { /* maximum size for array, remove smallest gain element and sort */ - if (get_molecule_gain(molecule, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist) > get_molecule_gain(cluster_gain_stats.feasible_blocks[0], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist)) { + if (get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist) > get_molecule_gain(cluster_gain_stats.feasible_blocks[0], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist)) { /* single loop insertion sort */ int j; for (j = 0; j < cluster_gain_stats.num_feasible_blocks - 1; j++) { - if (get_molecule_gain(molecule, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist) <= get_molecule_gain(cluster_gain_stats.feasible_blocks[j + 1], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist)) { - cluster_gain_stats.feasible_blocks[j] = molecule; + if (get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist) <= get_molecule_gain(cluster_gain_stats.feasible_blocks[j + 1], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist)) { + cluster_gain_stats.feasible_blocks[j] = molecule_id; break; } else { cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1]; } } if (j == cluster_gain_stats.num_feasible_blocks - 1) { - cluster_gain_stats.feasible_blocks[j] = molecule; + cluster_gain_stats.feasible_blocks[j] = molecule_id; } } } else { /* Expand array and single loop insertion sort */ int j; for (j = cluster_gain_stats.num_feasible_blocks - 1; j >= 0; j--) { - if (get_molecule_gain(cluster_gain_stats.feasible_blocks[j], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist) > get_molecule_gain(molecule, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, atom_netlist)) { + if (get_molecule_gain(cluster_gain_stats.feasible_blocks[j], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist) > get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist)) { cluster_gain_stats.feasible_blocks[j + 1] = cluster_gain_stats.feasible_blocks[j]; } else { - cluster_gain_stats.feasible_blocks[j + 1] = molecule; + cluster_gain_stats.feasible_blocks[j + 1] = molecule_id; break; } } if (j < 0) { - cluster_gain_stats.feasible_blocks[0] = molecule; + cluster_gain_stats.feasible_blocks[0] = molecule_id; } cluster_gain_stats.num_feasible_blocks++; } @@ -992,14 +998,14 @@ static void add_molecule_to_pb_stats_candidates(t_pack_molecule* molecule, * Useful for removing blocks that are repeatedly failing. If a block * has been found to be illegal, we don't repeatedly consider it. */ -static void remove_molecule_from_pb_stats_candidates(t_pack_molecule* molecule, +static void remove_molecule_from_pb_stats_candidates(PackMoleculeId molecule_id, ClusterGainStats& cluster_gain_stats) { int molecule_index; bool found_molecule = false; //find the molecule index for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) { - if (cluster_gain_stats.feasible_blocks[i] == molecule) { + if (cluster_gain_stats.feasible_blocks[i] == molecule_id) { found_molecule = true; molecule_index = i; } @@ -1025,54 +1031,58 @@ static void remove_molecule_from_pb_stats_candidates(t_pack_molecule* molecule, * + molecule_base_gain*some_factor * - introduced_input_nets_of_unrelated_blocks_pulled_in_by_molecule*some_other_factor */ -static float get_molecule_gain(t_pack_molecule* molecule, +static float get_molecule_gain(PackMoleculeId molecule_id, ClusterGainStats& cluster_gain_stats, AttractGroupId cluster_attraction_group_id, AttractionInfo& attraction_groups, int num_molecule_failures, + const Prepacker& prepacker, const AtomNetlist& atom_netlist) { + VTR_ASSERT(molecule_id.is_valid()); + const t_pack_molecule& molecule = prepacker.get_molecule(molecule_id); + float gain = 0; constexpr float attraction_group_penalty = 0.1; int num_introduced_inputs_of_indirectly_related_block = 0; - for (int i = 0; i < get_array_size_of_molecule(molecule); i++) { - AtomBlockId blk_id = molecule->atom_block_ids[i]; - if (blk_id) { - if (cluster_gain_stats.gain.count(blk_id) > 0) { - gain += cluster_gain_stats.gain[blk_id]; - } else { - /* This block has no connection with current cluster, penalize molecule for having this block - */ - for (auto pin_id : atom_netlist.block_input_pins(blk_id)) { - auto net_id = atom_netlist.pin_net(pin_id); - VTR_ASSERT(net_id); - - auto driver_pin_id = atom_netlist.net_driver(net_id); - VTR_ASSERT(driver_pin_id); - - auto driver_blk_id = atom_netlist.pin_block(driver_pin_id); - - num_introduced_inputs_of_indirectly_related_block++; - for (int iblk = 0; iblk < get_array_size_of_molecule(molecule); iblk++) { - if (molecule->atom_block_ids[iblk] && driver_blk_id == molecule->atom_block_ids[iblk]) { - //valid block which is driver (and hence not an input) - num_introduced_inputs_of_indirectly_related_block--; - break; - } + for (AtomBlockId blk_id : molecule.atom_block_ids) { + if (!blk_id.is_valid()) + continue; + + if (cluster_gain_stats.gain.count(blk_id) > 0) { + gain += cluster_gain_stats.gain[blk_id]; + } else { + /* This block has no connection with current cluster, penalize molecule for having this block + */ + for (auto pin_id : atom_netlist.block_input_pins(blk_id)) { + auto net_id = atom_netlist.pin_net(pin_id); + VTR_ASSERT(net_id); + + auto driver_pin_id = atom_netlist.net_driver(net_id); + VTR_ASSERT(driver_pin_id); + + auto driver_blk_id = atom_netlist.pin_block(driver_pin_id); + + num_introduced_inputs_of_indirectly_related_block++; + for (AtomBlockId blk_id_2 : molecule.atom_block_ids) { + if (blk_id_2.is_valid() && driver_blk_id == blk_id_2) { + //valid block which is driver (and hence not an input) + num_introduced_inputs_of_indirectly_related_block--; + break; } } } - AttractGroupId atom_grp_id = attraction_groups.get_atom_attraction_group(blk_id); - if (atom_grp_id == cluster_attraction_group_id && cluster_attraction_group_id != AttractGroupId::INVALID()) { - float att_grp_gain = attraction_groups.get_attraction_group_gain(atom_grp_id); - gain += att_grp_gain; - } else if (cluster_attraction_group_id != AttractGroupId::INVALID() && atom_grp_id != cluster_attraction_group_id) { - gain -= attraction_group_penalty; - } + } + AttractGroupId atom_grp_id = attraction_groups.get_atom_attraction_group(blk_id); + if (atom_grp_id == cluster_attraction_group_id && cluster_attraction_group_id != AttractGroupId::INVALID()) { + float att_grp_gain = attraction_groups.get_attraction_group_gain(atom_grp_id); + gain += att_grp_gain; + } else if (cluster_attraction_group_id != AttractGroupId::INVALID() && atom_grp_id != cluster_attraction_group_id) { + gain -= attraction_group_penalty; } } - gain += molecule->base_gain * 0.0001; /* Use base gain as tie breaker TODO: need to sweep this value and perhaps normalize */ + gain += molecule.base_gain * 0.0001; /* Use base gain as tie breaker TODO: need to sweep this value and perhaps normalize */ gain -= num_introduced_inputs_of_indirectly_related_block * (0.001); if (num_molecule_failures > 0 && attraction_groups.num_attraction_groups() > 0) { @@ -1085,7 +1095,6 @@ static float get_molecule_gain(t_pack_molecule* molecule, void GreedyCandidateSelector::load_transitive_fanout_candidates( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer) { // iterate over all the nets that have pins in this cluster for (AtomNetId net_id : cluster_gain_stats.marked_nets) { @@ -1120,16 +1129,17 @@ void GreedyCandidateSelector::load_transitive_fanout_candidates( } else { cluster_gain_stats.gain[blk_id] += 0.001; } - t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id); - VTR_ASSERT(!cluster_legalizer.is_mol_clustered(molecule)); - transitive_fanout_candidates.insert({molecule->atom_block_ids[molecule->root], molecule}); + PackMoleculeId molecule_id = prepacker_.get_atom_molecule(blk_id); + VTR_ASSERT(!cluster_legalizer.is_mol_clustered(molecule_id)); + const t_pack_molecule& molecule = prepacker_.get_molecule(molecule_id); + transitive_fanout_candidates.insert({molecule.atom_block_ids[molecule.root], molecule_id}); } } } } } -t_pack_molecule* GreedyCandidateSelector::get_unrelated_candidate_for_cluster( +PackMoleculeId GreedyCandidateSelector::get_unrelated_candidate_for_cluster( LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer) { // Necessary data structures are only allocated in unrelated clustering is @@ -1148,26 +1158,26 @@ t_pack_molecule* GreedyCandidateSelector::get_unrelated_candidate_for_cluster( for (int ext_inps = inputs_avail; ext_inps >= 0; ext_inps--) { // Get the molecule by the number of external inputs. - t_pack_molecule* molecule = nullptr; - for (t_pack_molecule* mol : unrelated_clustering_data_[ext_inps]) { + PackMoleculeId molecule = PackMoleculeId::INVALID(); + for (PackMoleculeId mol_id : unrelated_clustering_data_[ext_inps]) { /* TODO: Get better candidate atom block in future, eg. return most timing critical or some other smarter metric */ - if (!cluster_legalizer.is_mol_clustered(mol)) { + if (!cluster_legalizer.is_mol_clustered(mol_id)) { /* TODO: I should be using a better filtering check especially when I'm * dealing with multiple clock/multiple global reset signals where the clock/reset * packed in matters, need to do later when I have the circuits to check my work */ - if (cluster_legalizer.is_molecule_compatible(mol, cluster_id)) { - molecule = mol; + if (cluster_legalizer.is_molecule_compatible(mol_id, cluster_id)) { + molecule = mol_id; break; } } } // If a molecule could be found, return it. - if (molecule != nullptr) + if (molecule.is_valid()) return molecule; } // If no molecule could be found, return nullptr. - return nullptr; + return PackMoleculeId::INVALID(); } void GreedyCandidateSelector::update_candidate_selector_finalize_cluster( diff --git a/vpr/src/pack/greedy_candidate_selector.h b/vpr/src/pack/greedy_candidate_selector.h index 2ef43fbf940..9b70ec803ea 100644 --- a/vpr/src/pack/greedy_candidate_selector.h +++ b/vpr/src/pack/greedy_candidate_selector.h @@ -15,6 +15,7 @@ #include "attraction_groups.h" #include "cluster_legalizer.h" #include "physical_types.h" +#include "prepack.h" #include "vtr_ndmatrix.h" #include "vtr_vector.h" #include "vtr_random.h" @@ -26,7 +27,6 @@ class FlatPlacementInfo; class Prepacker; class SetupTimingInfo; class t_pack_high_fanout_thresholds; -class t_pack_molecule; struct t_model; struct t_molecule_stats; struct t_packer_opts; @@ -40,7 +40,7 @@ struct t_packer_opts; */ struct ClusterGainStats { /// @brief The seed molecule used to create this cluster. - t_pack_molecule* seed_molecule = nullptr; + PackMoleculeId seed_molecule_id = PackMoleculeId::INVALID(); /// @brief Has this cluster tried to get candidates by connectivity and /// timing yet. This helps ensure that we only do that once per @@ -60,12 +60,12 @@ struct ClusterGainStats { /// consideration. std::unordered_map sharing_gain; - /// @brief Stores the number of times atoms have failed to be packed into - /// the cluster. + /// @brief Stores the number of times molecules have failed to be packed + /// into the cluster. /// - /// key: root block id of the molecule, value: number of times the molecule - /// has failed to be packed into the cluster. - std::unordered_map atom_failures; + /// key: molecule id, value: number of times the molecule has failed to be + /// packed into the cluster. + std::unordered_map mol_failures; /// @brief List of nets with the num_pins_of_net_in_pb and gain entries /// altered (i.e. have some gain-related connection to the current @@ -84,7 +84,7 @@ struct ClusterGainStats { /// @brief Holding transitive fanout candidates key: root block id of the /// molecule, value: pointer to the molecule. // TODO: This should be an unordered map, unless stability is desired. - std::map transitive_fanout_candidates; + std::map transitive_fanout_candidates; /// @brief How many pins of each atom net are contained in the currently open pb? std::unordered_map num_pins_of_net_in_pb; @@ -98,7 +98,7 @@ struct ClusterGainStats { /// /// Sorted in ascending gain order so that the last cluster_ctx.blocks is /// the most desirable (this makes it easy to pop blocks off the list. - std::vector feasible_blocks; + std::vector feasible_blocks; int num_feasible_blocks; }; @@ -122,7 +122,7 @@ struct ClusterGainStats { * ClusterGainStats cluster_gain_stats = candidate_selector.create_cluster_gain_stats(...); * * // Select a candidate to pack into the cluster using the gain stats. - * t_pack_molecule* candidate_mol = candidate_selector.get_next_candidate_for_cluster(cluster_gain_stats, ...); + * PackMoleculeId candidate_mol = candidate_selector.get_next_candidate_for_cluster(cluster_gain_stats, ...); * * // ... (Try to pack the candidate into the cluster) * @@ -245,7 +245,7 @@ class GreedyCandidateSelector { * other. */ ClusterGainStats create_cluster_gain_stats( - t_pack_molecule* cluster_seed_mol, + PackMoleculeId cluster_seed_mol_id, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -271,7 +271,7 @@ class GreedyCandidateSelector { */ void update_cluster_gain_stats_candidate_success( ClusterGainStats& cluster_gain_stats, - t_pack_molecule* successful_mol, + PackMoleculeId successful_mol_id, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -290,7 +290,7 @@ class GreedyCandidateSelector { */ void update_cluster_gain_stats_candidate_failed( ClusterGainStats& cluster_gain_stats, - t_pack_molecule* failed_mol); + PackMoleculeId failed_mol_id); /** * @brief Given the cluster_gain_stats, select the next candidate molecule @@ -305,18 +305,14 @@ class GreedyCandidateSelector { * The legalization cluster id for the cluster. * @param cluster_legalizer * The legalizer used to create the cluster. - * @param prepacker - * The prepacker used to generate pack-pattern molecules of the - * atoms in the netlist. * @param attraction_groups * Groups of primitives that have extra attraction to each * other. */ - t_pack_molecule* get_next_candidate_for_cluster( + PackMoleculeId get_next_candidate_for_cluster( ClusterGainStats& cluster_gain_stats, LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer, - const Prepacker& prepacker, AttractionInfo& attraction_groups); /** @@ -419,7 +415,6 @@ class GreedyCandidateSelector { void add_cluster_molecule_candidates_by_connectivity_and_timing( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -438,7 +433,6 @@ class GreedyCandidateSelector { void load_transitive_fanout_candidates( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer); /* @@ -448,7 +442,6 @@ class GreedyCandidateSelector { void add_cluster_molecule_candidates_by_transitive_connectivity( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -459,7 +452,6 @@ class GreedyCandidateSelector { void add_cluster_molecule_candidates_by_highfanout_connectivity( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -477,7 +469,6 @@ class GreedyCandidateSelector { void add_cluster_molecule_candidates_by_attraction_group( ClusterGainStats& cluster_gain_stats, LegalizationClusterId legalization_cluster_id, - const Prepacker& prepacker, const ClusterLegalizer& cluster_legalizer, AttractionInfo& attraction_groups); @@ -485,7 +476,7 @@ class GreedyCandidateSelector { * @brief Finds a molecule to propose which is unrelated but may be good to * cluster. */ - t_pack_molecule* get_unrelated_candidate_for_cluster( + PackMoleculeId get_unrelated_candidate_for_cluster( LegalizationClusterId cluster_id, const ClusterLegalizer& cluster_legalizer); @@ -496,6 +487,9 @@ class GreedyCandidateSelector { /// @brief The atom netlist to cluster over. const AtomNetlist& atom_netlist_; + /// @brief The prepacker used to pack atoms into molecule pack patterns. + const Prepacker& prepacker_; + /// @brief The packer options used to configure the clusterer. const t_packer_opts& packer_opts_; @@ -536,7 +530,7 @@ class GreedyCandidateSelector { /// @brief Data pre-computed to help select unrelated molecules. This is a /// list of list of molecules sorted by their gain, where the first /// dimension is the number of external outputs of the molecule. - std::vector> unrelated_clustering_data_; + std::vector> unrelated_clustering_data_; /// @brief Placement information of the atoms in the netlist known before /// packing. @@ -549,13 +543,13 @@ class GreedyCandidateSelector { struct FlatTileMoleculeList { // A list of molecule in each sub_tile at this tile. Where each index // in the first dimension is the subtile [0, num_sub_tiles - 1]. - std::vector> sub_tile_mols; + std::vector> sub_tile_mols; // A list of molecules in the undefined sub-tile at this tile. An // undefined sub-tile is the location molecules go when the sub-tile // in the flat placement is unspecified for this atom. // Currently unused, but can be used to support that feature. - std::vector undefined_sub_tile_mols; + std::vector undefined_sub_tile_mols; }; /// @brief Pre-computed information on the flat placement. Lists all of the diff --git a/vpr/src/pack/greedy_clusterer.cpp b/vpr/src/pack/greedy_clusterer.cpp index 5733965f302..795858715d7 100644 --- a/vpr/src/pack/greedy_clusterer.cpp +++ b/vpr/src/pack/greedy_clusterer.cpp @@ -50,7 +50,6 @@ #include "constraints_report.h" #include "greedy_candidate_selector.h" #include "greedy_seed_selector.h" -#include "pack_types.h" #include "physical_types.h" #include "prepack.h" #include "vpr_context.h" @@ -98,7 +97,7 @@ GreedyClusterer::GreedyClusterer(const t_packer_opts& packer_opts, std::map GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, - Prepacker& prepacker, + const Prepacker& prepacker, bool allow_unrelated_clustering, bool balance_block_type_utilization, AttractionInfo& attraction_groups, @@ -114,7 +113,7 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, // The clustering stats holds information used for logging the progress // of the clustering to the user. t_cluster_progress_stats clustering_stats; - clustering_stats.num_molecules = prepacker.get_num_molecules(); + clustering_stats.num_molecules = prepacker.molecules().size(); // TODO: Create a ClusteringTimingManager class. // This code relies on the prepacker, once the prepacker is moved to @@ -155,8 +154,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, atom_criticality); // Pick the first seed molecule. - t_pack_molecule* seed_mol = seed_selector.get_next_seed(prepacker, - cluster_legalizer); + PackMoleculeId seed_mol_id = seed_selector.get_next_seed(prepacker, + cluster_legalizer); /**************************************************************** * Clustering @@ -166,9 +165,9 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, // Continue clustering as long as a valid seed is returned from the seed // selector. - while (seed_mol != nullptr) { + while (seed_mol_id.is_valid()) { // Check to ensure that this molecule is unclustered. - VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_mol)); + VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_mol_id)); // The basic algorithm: // 1) Try to put all the molecules in that you can without doing the @@ -179,7 +178,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, // Try to grow a cluster from the seed molecule without doing intra-lb // route for each molecule (i.e. just use faster but not fully // conservative legality checks). - LegalizationClusterId new_cluster_id = try_grow_cluster(seed_mol, + LegalizationClusterId new_cluster_id = try_grow_cluster( + seed_mol_id, candidate_selector, ClusterLegalizationStrategy::SKIP_INTRA_LB_ROUTE, cluster_legalizer, @@ -193,7 +193,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, // If the previous strategy failed, try to grow the cluster again, // but this time perform full legalization for each molecule added // to the cluster. - new_cluster_id = try_grow_cluster(seed_mol, + new_cluster_id = try_grow_cluster( + seed_mol_id, candidate_selector, ClusterLegalizationStrategy::FULL, cluster_legalizer, @@ -206,7 +207,7 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, // Ensure that the seed was packed successfully. VTR_ASSERT(new_cluster_id.is_valid()); - VTR_ASSERT(cluster_legalizer.is_mol_clustered(seed_mol)); + VTR_ASSERT(cluster_legalizer.is_mol_clustered(seed_mol_id)); // Update the clustering progress stats. size_t num_molecules_in_cluster = cluster_legalizer.get_num_molecules_in_cluster(new_cluster_id); @@ -224,8 +225,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, cluster_legalizer); // Pick new seed. - seed_mol = seed_selector.get_next_seed(prepacker, - cluster_legalizer); + seed_mol_id = seed_selector.get_next_seed(prepacker, + cluster_legalizer); } // If this architecture has LE physical block, report its usage. @@ -235,42 +236,42 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, } LegalizationClusterId GreedyClusterer::try_grow_cluster( - t_pack_molecule* seed_mol, + PackMoleculeId seed_mol_id, GreedyCandidateSelector& candidate_selector, ClusterLegalizationStrategy strategy, ClusterLegalizer& cluster_legalizer, - Prepacker& prepacker, + const Prepacker& prepacker, bool balance_block_type_utilization, AttractionInfo& attraction_groups, std::map& num_used_type_instances, DeviceContext& mutable_device_ctx) { // Check to ensure that this molecule is unclustered. - VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_mol)); + VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_mol_id)); // Set the legalization strategy of the cluster legalizer. cluster_legalizer.set_legalization_strategy(strategy); // Use the seed to start a new cluster. - LegalizationClusterId legalization_cluster_id = start_new_cluster(seed_mol, + LegalizationClusterId legalization_cluster_id = start_new_cluster(seed_mol_id, cluster_legalizer, + prepacker, balance_block_type_utilization, num_used_type_instances, mutable_device_ctx); // Create the cluster gain stats. This updates the gains in the candidate // selector due to a new molecule being clustered. - ClusterGainStats cluster_gain_stats = candidate_selector.create_cluster_gain_stats(seed_mol, + ClusterGainStats cluster_gain_stats = candidate_selector.create_cluster_gain_stats(seed_mol_id, legalization_cluster_id, cluster_legalizer, attraction_groups); // Select the first candidate molecule to try to add to this cluster. - t_pack_molecule* candidate_mol = candidate_selector.get_next_candidate_for_cluster( + PackMoleculeId candidate_mol_id = candidate_selector.get_next_candidate_for_cluster( cluster_gain_stats, legalization_cluster_id, cluster_legalizer, - prepacker, attraction_groups); /* @@ -290,11 +291,12 @@ LegalizationClusterId GreedyClusterer::try_grow_cluster( // 1) No candidate molecule is proposed. // 2) The same candidate was proposed multiple times. int num_repeated_molecules = 0; - while (candidate_mol != nullptr && num_repeated_molecules < max_num_repeated_molecules) { + while (candidate_mol_id.is_valid() && num_repeated_molecules < max_num_repeated_molecules) { // Try to cluster the candidate molecule into the cluster. - bool success = try_add_candidate_mol_to_cluster(candidate_mol, + bool success = try_add_candidate_mol_to_cluster(candidate_mol_id, legalization_cluster_id, - cluster_legalizer); + cluster_legalizer, + prepacker); // If the candidate molecule was clustered successfully, update // the cluster stats. @@ -302,7 +304,7 @@ LegalizationClusterId GreedyClusterer::try_grow_cluster( // If the last candidate was clustered successfully, update the // gains in the candidate selector. candidate_selector.update_cluster_gain_stats_candidate_success(cluster_gain_stats, - candidate_mol, + candidate_mol_id, legalization_cluster_id, cluster_legalizer, attraction_groups); @@ -310,22 +312,21 @@ LegalizationClusterId GreedyClusterer::try_grow_cluster( // If the last candidate was not clustered successfully, update the // gains in the candidate selector accordingly. candidate_selector.update_cluster_gain_stats_candidate_failed(cluster_gain_stats, - candidate_mol); + candidate_mol_id); } // Get the next candidate molecule. - t_pack_molecule* prev_candidate_mol = candidate_mol; - candidate_mol = candidate_selector.get_next_candidate_for_cluster( + PackMoleculeId prev_candidate_mol_id = candidate_mol_id; + candidate_mol_id = candidate_selector.get_next_candidate_for_cluster( cluster_gain_stats, legalization_cluster_id, cluster_legalizer, - prepacker, attraction_groups); // If the next candidate molecule is the same as the previous // candidate molecule, increment the number of repeated // molecules counter. - if (candidate_mol == prev_candidate_mol) + if (candidate_mol_id == prev_candidate_mol_id) num_repeated_molecules++; } @@ -367,14 +368,18 @@ LegalizationClusterId GreedyClusterer::try_grow_cluster( } LegalizationClusterId GreedyClusterer::start_new_cluster( - t_pack_molecule* seed_mol, + PackMoleculeId seed_mol_id, ClusterLegalizer& cluster_legalizer, + const Prepacker& prepacker, bool balance_block_type_utilization, std::map& num_used_type_instances, DeviceContext& mutable_device_ctx) { + VTR_ASSERT(seed_mol_id.is_valid()); + const t_pack_molecule& seed_mol = prepacker.get_molecule(seed_mol_id); + /* Allocate a dummy initial cluster and load a atom block as a seed and check if it is legal */ - AtomBlockId root_atom = seed_mol->atom_block_ids[seed_mol->root]; + AtomBlockId root_atom = seed_mol.atom_block_ids[seed_mol.root]; const std::string& root_atom_name = atom_netlist_.block_name(root_atom); const t_model* root_model = atom_netlist_.block_model(root_atom); @@ -406,8 +411,8 @@ LegalizationClusterId GreedyClusterer::start_new_cluster( if (log_verbosity_ > 2) { VTR_LOG("\tSeed: '%s' (%s)", root_atom_name.c_str(), root_model->name); - VTR_LOGV(seed_mol->pack_pattern, " molecule_type %s molecule_size %zu", - seed_mol->pack_pattern->name, seed_mol->atom_block_ids.size()); + VTR_LOGV(seed_mol.pack_pattern, " molecule_type %s molecule_size %zu", + seed_mol.pack_pattern->name, seed_mol.atom_block_ids.size()); VTR_LOG("\n"); } @@ -419,7 +424,7 @@ LegalizationClusterId GreedyClusterer::start_new_cluster( //Try packing into each mode e_block_pack_status pack_result = e_block_pack_status::BLK_STATUS_UNDEFINED; for (int j = 0; j < type->pb_graph_head->pb_type->num_modes && !success; j++) { - std::tie(pack_result, new_cluster_id) = cluster_legalizer.start_new_cluster(seed_mol, type, j); + std::tie(pack_result, new_cluster_id) = cluster_legalizer.start_new_cluster(seed_mol_id, type, j); success = (pack_result == e_block_pack_status::BLK_PASSED); } @@ -435,11 +440,11 @@ LegalizationClusterId GreedyClusterer::start_new_cluster( if (!success) { //Explored all candidates - if (seed_mol->type == MOLECULE_FORCED_PACK) { + if (seed_mol.type == e_pack_pattern_molecule_type::MOLECULE_FORCED_PACK) { VPR_FATAL_ERROR(VPR_ERROR_PACK, "Can not find any logic block that can implement molecule.\n" "\tPattern %s %s\n", - seed_mol->pack_pattern->name, + seed_mol.pack_pattern->name, root_atom_name.c_str()); } else { VPR_FATAL_ERROR(VPR_ERROR_PACK, @@ -482,15 +487,16 @@ LegalizationClusterId GreedyClusterer::start_new_cluster( return new_cluster_id; } -bool GreedyClusterer::try_add_candidate_mol_to_cluster(t_pack_molecule* candidate_mol, +bool GreedyClusterer::try_add_candidate_mol_to_cluster(PackMoleculeId candidate_mol_id, LegalizationClusterId legalization_cluster_id, - ClusterLegalizer& cluster_legalizer) { - VTR_ASSERT(candidate_mol != nullptr); - VTR_ASSERT(!cluster_legalizer.is_mol_clustered(candidate_mol)); + ClusterLegalizer& cluster_legalizer, + const Prepacker& prepacker) { + VTR_ASSERT(candidate_mol_id.is_valid()); + VTR_ASSERT(!cluster_legalizer.is_mol_clustered(candidate_mol_id)); VTR_ASSERT(legalization_cluster_id.is_valid()); - e_block_pack_status pack_status = cluster_legalizer.add_mol_to_cluster(candidate_mol, - legalization_cluster_id); + e_block_pack_status pack_status = cluster_legalizer.add_mol_to_cluster(candidate_mol_id, + legalization_cluster_id); // Print helpful debugging log messages. if (log_verbosity_ > 2) { @@ -515,14 +521,15 @@ bool GreedyClusterer::try_add_candidate_mol_to_cluster(t_pack_molecule* candidat break; } // Get the block name and model name - AtomBlockId blk_id = candidate_mol->atom_block_ids[candidate_mol->root]; + const t_pack_molecule& candidate_mol = prepacker.get_molecule(candidate_mol_id); + AtomBlockId blk_id = candidate_mol.atom_block_ids[candidate_mol.root]; VTR_ASSERT(blk_id.is_valid()); std::string blk_name = atom_netlist_.block_name(blk_id); const t_model* blk_model = atom_netlist_.block_model(blk_id); VTR_LOG("'%s' (%s)", blk_name.c_str(), blk_model->name); - VTR_LOGV(candidate_mol->pack_pattern, " molecule %s molecule_size %zu", - candidate_mol->pack_pattern->name, - candidate_mol->atom_block_ids.size()); + VTR_LOGV(candidate_mol.pack_pattern, " molecule %s molecule_size %zu", + candidate_mol.pack_pattern->name, + candidate_mol.atom_block_ids.size()); VTR_LOG("\n"); fflush(stdout); } diff --git a/vpr/src/pack/greedy_clusterer.h b/vpr/src/pack/greedy_clusterer.h index 93f23cbb775..92fd491bdd7 100644 --- a/vpr/src/pack/greedy_clusterer.h +++ b/vpr/src/pack/greedy_clusterer.h @@ -13,6 +13,7 @@ #include #include "cluster_legalizer.h" #include "physical_types.h" +#include "prepack.h" // Forward declarations class AtomNetId; @@ -21,10 +22,8 @@ class AttractionInfo; class DeviceContext; class FlatPlacementInfo; class GreedyCandidateSelector; -class Prepacker; class SetupTimingInfo; class t_pack_high_fanout_thresholds; -class t_pack_molecule; struct t_analysis_opts; struct t_clustering_data; struct t_packer_opts; @@ -129,7 +128,7 @@ class GreedyClusterer { */ std::map do_clustering(ClusterLegalizer& cluster_legalizer, - Prepacker& prepacker, + const Prepacker& prepacker, bool allow_unrelated_clustering, bool balance_block_type_utilization, AttractionInfo& attraction_groups, @@ -152,11 +151,11 @@ class GreedyClusterer { * legalizer for each molecule added. This cannot fail (assuming the seed * can exist in a cluster), so it will always return a valid cluster ID. */ - LegalizationClusterId try_grow_cluster(t_pack_molecule* seed_mol, + LegalizationClusterId try_grow_cluster(PackMoleculeId seed_mol_id, GreedyCandidateSelector& candidate_selector, ClusterLegalizationStrategy strategy, ClusterLegalizer& cluster_legalizer, - Prepacker& prepacker, + const Prepacker& prepacker, bool balance_block_type_utilization, AttractionInfo& attraction_groups, std::map& num_used_type_instances, @@ -176,8 +175,9 @@ class GreedyClusterer { * device grid if it find thats more clusters of specific logical block * types have been created than the device can support. */ - LegalizationClusterId start_new_cluster(t_pack_molecule* seed_mol, + LegalizationClusterId start_new_cluster(PackMoleculeId seed_mol_id, ClusterLegalizer& cluster_legalizer, + const Prepacker& prepacker, bool balance_block_type_utilization, std::map& num_used_type_instances, DeviceContext& mutable_device_ctx); @@ -187,9 +187,10 @@ class GreedyClusterer { * Returns true if the molecule was clustered successfully, false * otherwise. */ - bool try_add_candidate_mol_to_cluster(t_pack_molecule* candidate_mol, + bool try_add_candidate_mol_to_cluster(PackMoleculeId candidate_mol_id, LegalizationClusterId legalization_cluster_id, - ClusterLegalizer& cluster_legalizer); + ClusterLegalizer& cluster_legalizer, + const Prepacker& prepacker); /** * @brief Log the physical block usage of the logic element in the diff --git a/vpr/src/pack/greedy_seed_selector.cpp b/vpr/src/pack/greedy_seed_selector.cpp index 24a57930f71..302352261c4 100644 --- a/vpr/src/pack/greedy_seed_selector.cpp +++ b/vpr/src/pack/greedy_seed_selector.cpp @@ -42,8 +42,8 @@ static inline float get_seed_gain(AtomBlockId blk_id, // instead. case e_cluster_seed::MAX_INPUTS: { - const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk_id); - const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol, atom_netlist); + PackMoleculeId blk_mol_id = prepacker.get_atom_molecule(blk_id); + const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol_id, atom_netlist); return molecule_stats.num_used_ext_inputs; } // By blended gain (criticality and inputs used). @@ -54,8 +54,8 @@ static inline float get_seed_gain(AtomBlockId blk_id, // it, and number of external inputs. float seed_blend_fac = 0.5f; - const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk_id); - const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol, atom_netlist); + PackMoleculeId blk_mol_id = prepacker.get_atom_molecule(blk_id); + const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol_id, atom_netlist); VTR_ASSERT(max_molecule_stats.num_used_ext_inputs > 0); float used_ext_input_pin_ratio = vtr::safe_ratio(molecule_stats.num_used_ext_inputs, max_molecule_stats.num_used_ext_inputs); @@ -69,8 +69,8 @@ static inline float get_seed_gain(AtomBlockId blk_id, // harder to pack. case e_cluster_seed::MAX_PINS: { - const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk_id); - const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol, atom_netlist); + PackMoleculeId blk_mol_id = prepacker.get_atom_molecule(blk_id); + const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol_id, atom_netlist); return molecule_stats.num_pins; } // By input pins per molecule (i.e. available pins on primitives, not pins in use). @@ -78,14 +78,14 @@ static inline float get_seed_gain(AtomBlockId blk_id, // harder to pack. case e_cluster_seed::MAX_INPUT_PINS: { - const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk_id); - const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol, atom_netlist); + PackMoleculeId blk_mol_id = prepacker.get_atom_molecule(blk_id); + const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(blk_mol_id, atom_netlist); return molecule_stats.num_input_pins; } case e_cluster_seed::BLEND2: { - const t_pack_molecule* mol = prepacker.get_atom_molecule(blk_id); - const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(mol, atom_netlist); + PackMoleculeId mol_id = prepacker.get_atom_molecule(blk_id); + const t_molecule_stats molecule_stats = prepacker.calc_molecule_stats(mol_id, atom_netlist); float pin_ratio = vtr::safe_ratio(molecule_stats.num_pins, max_molecule_stats.num_pins); float input_pin_ratio = vtr::safe_ratio(molecule_stats.num_input_pins, max_molecule_stats.num_input_pins); @@ -210,8 +210,8 @@ GreedySeedSelector::GreedySeedSelector(const AtomNetlist& atom_netlist, seed_index_ = 0; } -t_pack_molecule* GreedySeedSelector::get_next_seed(const Prepacker& prepacker, - const ClusterLegalizer& cluster_legalizer) { +PackMoleculeId GreedySeedSelector::get_next_seed(const Prepacker& prepacker, + const ClusterLegalizer& cluster_legalizer) { while (seed_index_ < seed_atoms_.size()) { // Get the current seed atom at the seed index and increment the // seed index. @@ -227,14 +227,14 @@ t_pack_molecule* GreedySeedSelector::get_next_seed(const Prepacker& prepacker, // Get the molecule that contains this atom and return it as the // next seed. - t_pack_molecule* seed_molecule = prepacker.get_atom_molecule(seed_blk_id); - VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_molecule)); - return seed_molecule; + PackMoleculeId seed_molecule_id = prepacker.get_atom_molecule(seed_blk_id); + VTR_ASSERT(!cluster_legalizer.is_mol_clustered(seed_molecule_id)); + return seed_molecule_id; } // If the previous loop does not return a molecule, it implies that all // atoms have been clustered or have already been proposed as a seed. // Return nullptr to signify that there are no further seeds. - return nullptr; + return PackMoleculeId::INVALID(); } diff --git a/vpr/src/pack/greedy_seed_selector.h b/vpr/src/pack/greedy_seed_selector.h index f6eee80da4b..15e9d5ee87a 100644 --- a/vpr/src/pack/greedy_seed_selector.h +++ b/vpr/src/pack/greedy_seed_selector.h @@ -8,12 +8,12 @@ #pragma once +#include "prepack.h" #include "vpr_types.h" // Forward declarations class AtomNetlist; class ClusterLegalizer; -class Prepacker; struct t_molecule_stats; /** @@ -55,7 +55,7 @@ class GreedySeedSelector { /** * @brief Propose a new seed molecule to start a new cluster with. If no - * unclustered molecules exist, will return nullptr. + * unclustered molecules exist, will return an invalid ID. * * This method will never return a molecule which has already been clustered * (according to the cluster legalizer) and will never propose a molecule @@ -71,8 +71,8 @@ class GreedySeedSelector { * clusters. This is used to check if a molecule has already * been clustered or not. */ - t_pack_molecule* get_next_seed(const Prepacker& prepacker, - const ClusterLegalizer& cluster_legalizer); + PackMoleculeId get_next_seed(const Prepacker& prepacker, + const ClusterLegalizer& cluster_legalizer); // TODO: Maybe create an update_seed_gains method to update the seed atoms // list using current clustering information. diff --git a/vpr/src/pack/output_clustering.cpp b/vpr/src/pack/output_clustering.cpp index 83949655b2b..813a5e842a5 100644 --- a/vpr/src/pack/output_clustering.cpp +++ b/vpr/src/pack/output_clustering.cpp @@ -12,6 +12,7 @@ #include "cluster_legalizer.h" #include "clustered_netlist.h" #include "physical_types.h" +#include "physical_types_util.h" #include "prepack.h" #include "vpr_context.h" #include "vtr_assert.h" diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 8c342c39018..361db74e682 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -63,8 +63,7 @@ bool try_pack(t_packer_opts* packer_opts, // The Prepacker object performs prepacking and stores the pack molecules. // As long as the molecules are used, this object must persist. VTR_LOG("Begin prepacking.\n"); - Prepacker prepacker; - prepacker.init(atom_ctx.nlist, device_ctx.logical_block_types); + const Prepacker prepacker(atom_ctx.nlist, device_ctx.logical_block_types); /* We keep attraction groups off in the first iteration, and * only turn on in later iterations if some floorplan regions turn out to be overfull. diff --git a/vpr/src/pack/post_routing_pb_pin_fixup.cpp b/vpr/src/pack/post_routing_pb_pin_fixup.cpp index 78084d56df3..ebaffe22f98 100644 --- a/vpr/src/pack/post_routing_pb_pin_fixup.cpp +++ b/vpr/src/pack/post_routing_pb_pin_fixup.cpp @@ -3,13 +3,12 @@ * after routing optimization *******************************************************************/ /* Headers from vtrutil library */ +#include "physical_types_util.h" #include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "vpr_error.h" #include "vpr_utils.h" -#include "rr_graph2.h" #include "annotate_routing.h" diff --git a/vpr/src/pack/prepack.cpp b/vpr/src/pack/prepack.cpp index 9cda9de0360..da89aab9abf 100644 --- a/vpr/src/pack/prepack.cpp +++ b/vpr/src/pack/prepack.cpp @@ -39,13 +39,6 @@ static void free_list_of_pack_patterns(std::vector& list_of_pac static void free_pack_pattern(t_pack_patterns* pack_pattern); -static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_pack_patterns, - vtr::vector& expected_lowest_cost_pb_gnode, - const int num_packing_patterns, - std::multimap& atom_molecules, - const AtomNetlist& atom_nlist, - const std::vector& logical_block_types); - static void discover_pattern_names_in_pb_graph_node(t_pb_graph_node* pb_graph_node, std::unordered_map& pattern_names); @@ -75,21 +68,15 @@ static int compare_pack_pattern(const t_pack_patterns* pattern_a, const t_pack_p static void free_pack_pattern_block(t_pack_pattern_block* pattern_block, t_pack_pattern_block** pattern_block_list); -static t_pack_molecule* try_create_molecule(t_pack_patterns* list_of_pack_patterns, - const int pack_pattern_index, - AtomBlockId blk_id, - std::multimap& atom_molecules, - const AtomNetlist& atom_nlist); - -static bool try_expand_molecule(t_pack_molecule* molecule, +static bool try_expand_molecule(t_pack_molecule& molecule, const AtomBlockId blk_id, - const std::multimap& atom_molecules, + const std::multimap& atom_molecules, const AtomNetlist& atom_nlist); static void print_pack_molecules(const char* fname, - const t_pack_patterns* list_of_pack_patterns, + const std::vector& list_of_pack_patterns, const int num_pack_patterns, - const t_pack_molecule* list_of_molecules, + const vtr::vector_map& pack_molecules, const AtomNetlist& atom_nlist); static t_pb_graph_node* get_expected_lowest_cost_primitive_for_atom_block(const AtomBlockId blk_id, @@ -99,7 +86,7 @@ static t_pb_graph_node* get_expected_lowest_cost_primitive_for_atom_block_in_pb_ static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_patterns, - const std::multimap& atom_molecules, + const std::multimap& atom_molecules, const AtomNetlist& atom_nlist); static std::vector find_end_of_path(t_pb_graph_pin* input_pin, int pattern_index); @@ -114,8 +101,10 @@ static void update_chain_root_pins(t_pack_patterns* chain_pattern, static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, std::vector& connected_primitive_pins); static void init_molecule_chain_info(const AtomBlockId blk_id, - t_pack_molecule* molecule, - const std::multimap& atom_molecules, + t_pack_molecule& molecule, + const vtr::vector_map& pack_molecules, + const std::multimap& atom_molecules, + vtr::vector& chain_info, const AtomNetlist& atom_nlist); static AtomBlockId get_sink_block(const AtomBlockId block_id, @@ -799,29 +788,18 @@ static void backward_expand_pack_pattern_from_edge(const t_pb_graph_edge* expans * 3. Chained molecules are molecules that follow a carry-chain style pattern, * ie. a single linear chain that can be split across multiple complex blocks */ -static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_pack_patterns, - vtr::vector& expected_lowest_cost_pb_gnode, - const int num_packing_patterns, - std::multimap& atom_molecules, - const AtomNetlist& atom_nlist, - const std::vector& logical_block_types) { - int i, j, best_pattern; - t_pack_molecule* list_of_molecules_head; - t_pack_molecule* cur_molecule; - bool* is_used; - - is_used = new bool[num_packing_patterns]; - for (i = 0; i < num_packing_patterns; i++) - is_used[i] = false; - - cur_molecule = list_of_molecules_head = nullptr; +void Prepacker::alloc_and_load_pack_molecules(std::multimap& atom_molecules_multimap, + const AtomNetlist& atom_nlist, + const std::vector& logical_block_types) { + std::vector is_used(list_of_pack_patterns.size(), false); /* Find forced pack patterns * Simplifying assumptions: Each atom can map to at most one molecule, * use first-fit mapping based on priority of pattern * TODO: Need to investigate better mapping strategies than first-fit */ - for (i = 0; i < num_packing_patterns; i++) { + size_t num_packing_patterns = list_of_pack_patterns.size(); + for (size_t i = 0; i < num_packing_patterns; i++) { /* Skip pack patterns for modes that are disabled for packing, * Ensure no resources in unpackable modes will be mapped during pre-packing stage */ @@ -830,8 +808,8 @@ static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_p continue; } - best_pattern = 0; - for (j = 1; j < num_packing_patterns; j++) { + size_t best_pattern = 0; + for (size_t j = 1; j < num_packing_patterns; j++) { if (is_used[best_pattern]) { best_pattern = j; } else if (is_used[j] == false && compare_pack_pattern(&list_of_pack_patterns[j], &list_of_pack_patterns[best_pattern]) == 1) { @@ -845,34 +823,38 @@ static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_p for (auto blk_iter = blocks.begin(); blk_iter != blocks.end(); ++blk_iter) { auto blk_id = *blk_iter; - cur_molecule = try_create_molecule(list_of_pack_patterns, best_pattern, blk_id, atom_molecules, atom_nlist); - if (cur_molecule != nullptr) { - cur_molecule->next = list_of_molecules_head; - /* In the event of multiple molecules with the same atom block pattern, - * bias to use the molecule with less costly physical resources first */ - /* TODO: Need to normalize magical number 100 */ - cur_molecule->base_gain = cur_molecule->num_blocks - (cur_molecule->pack_pattern->base_cost / 100); - list_of_molecules_head = cur_molecule; - - //Note: atom_molecules is an (ordered) multimap so the last molecule - // inserted for a given blk_id will be the last valid element - // in the equal_range - auto rng = atom_molecules.equal_range(blk_id); //The range of molecules matching this block - bool range_empty = (rng.first == rng.second); - bool cur_was_last_inserted = false; - if (!range_empty) { - auto last_valid_iter = --rng.second; //Iterator to last element (only valid if range is not empty) - cur_was_last_inserted = (last_valid_iter->second == cur_molecule); - } - if (range_empty || !cur_was_last_inserted) { - /* molecule did not cover current atom (possibly because molecule created is - * part of a long chain that extends past multiple logic blocks), try again */ - --blk_iter; - } + PackMoleculeId cur_molecule_id = try_create_molecule(best_pattern, + blk_id, + atom_molecules_multimap, + atom_nlist); + + // If the molecule could not be created, move to the next block. + if (!cur_molecule_id.is_valid()) + continue; + + /* In the event of multiple molecules with the same atom block pattern, + * bias to use the molecule with less costly physical resources first */ + /* TODO: Need to normalize magical number 100 */ + t_pack_molecule& cur_molecule = pack_molecules_[cur_molecule_id]; + cur_molecule.base_gain = cur_molecule.atom_block_ids.size() - (cur_molecule.pack_pattern->base_cost / 100); + + //Note: atom_molecules is an (ordered) multimap so the last molecule + // inserted for a given blk_id will be the last valid element + // in the equal_range + auto rng = atom_molecules_multimap.equal_range(blk_id); //The range of molecules matching this block + bool range_empty = (rng.first == rng.second); + bool cur_was_last_inserted = false; + if (!range_empty) { + auto last_valid_iter = --rng.second; //Iterator to last element (only valid if range is not empty) + cur_was_last_inserted = (last_valid_iter->second == cur_molecule_id); + } + if (range_empty || !cur_was_last_inserted) { + /* molecule did not cover current atom (possibly because molecule created is + * part of a long chain that extends past multiple logic blocks), try again */ + --blk_iter; } } } - delete[] is_used; /* List all atom blocks as a molecule for blocks that do not belong to any molecules. * This allows the packer to be consistent as it now packs molecules only instead of atoms and molecules @@ -883,14 +865,6 @@ static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_p for (auto blk_id : atom_nlist.blocks()) { t_pb_graph_node* best = get_expected_lowest_cost_primitive_for_atom_block(blk_id, logical_block_types); if (!best) { - /* Free the molecules in the linked list to avoid memory leakage */ - cur_molecule = list_of_molecules_head; - while (cur_molecule) { - t_pack_molecule* molecule_to_free = cur_molecule; - cur_molecule = cur_molecule->next; - delete molecule_to_free; - } - VPR_FATAL_ERROR(VPR_ERROR_PACK, "Failed to find any location to pack primitive of type '%s' in architecture", atom_nlist.block_model(blk_id)->name); } @@ -899,33 +873,32 @@ static t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_p expected_lowest_cost_pb_gnode[blk_id] = best; - auto rng = atom_molecules.equal_range(blk_id); + auto rng = atom_molecules_multimap.equal_range(blk_id); bool rng_empty = (rng.first == rng.second); if (rng_empty) { - cur_molecule = new t_pack_molecule; - cur_molecule->type = MOLECULE_SINGLE_ATOM; - cur_molecule->num_blocks = 1; - cur_molecule->root = 0; - cur_molecule->pack_pattern = nullptr; + PackMoleculeId new_molecule_id = PackMoleculeId(pack_molecules_.size()); + t_pack_molecule new_molecule; + new_molecule.type = e_pack_pattern_molecule_type::MOLECULE_SINGLE_ATOM; + new_molecule.root = 0; + new_molecule.pack_pattern = nullptr; - cur_molecule->atom_block_ids = {blk_id}; + new_molecule.atom_block_ids = {blk_id}; - cur_molecule->next = list_of_molecules_head; - cur_molecule->base_gain = 1; - list_of_molecules_head = cur_molecule; + new_molecule.base_gain = 1; + new_molecule.chain_id = MoleculeChainId::INVALID(); - atom_molecules.insert({blk_id, cur_molecule}); + atom_molecules_multimap.insert({blk_id, new_molecule_id}); + pack_molecules_.push_back(std::move(new_molecule)); + pack_molecule_ids_.push_back(new_molecule_id); } } if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_PRE_PACKING_MOLECULES_AND_PATTERNS)) { print_pack_molecules(getEchoFileName(E_ECHO_PRE_PACKING_MOLECULES_AND_PATTERNS), list_of_pack_patterns, num_packing_patterns, - list_of_molecules_head, + pack_molecules_, atom_nlist); } - - return list_of_molecules_head; } static void free_pack_pattern_block(t_pack_pattern_block* pattern_block, t_pack_pattern_block** pattern_block_list) { @@ -959,59 +932,59 @@ static void free_pack_pattern_block(t_pack_pattern_block* pattern_block, t_pack_ * * Side Effect: If successful, link atom to molecule */ -static t_pack_molecule* try_create_molecule(t_pack_patterns* list_of_pack_patterns, - const int pack_pattern_index, - AtomBlockId blk_id, - std::multimap& atom_molecules, - const AtomNetlist& atom_nlist) { - t_pack_molecule* molecule; - +PackMoleculeId Prepacker::try_create_molecule(const int pack_pattern_index, + AtomBlockId blk_id, + std::multimap& atom_molecules_multimap, + const AtomNetlist& atom_nlist) { auto pack_pattern = &list_of_pack_patterns[pack_pattern_index]; // Check pack pattern validity if (pack_pattern == nullptr || pack_pattern->num_blocks == 0 || pack_pattern->root_block == nullptr) { - return nullptr; + return PackMoleculeId::INVALID(); } // If a chain pattern extends beyond a single logic block, we must find // the furthest blk_id up the chain that is not mapped to a molecule yet. if (pack_pattern->is_chain) { - blk_id = find_new_root_atom_for_chain(blk_id, pack_pattern, atom_molecules, atom_nlist); - if (!blk_id) return nullptr; + blk_id = find_new_root_atom_for_chain(blk_id, pack_pattern, atom_molecules_multimap, atom_nlist); + if (!blk_id) return PackMoleculeId::INVALID(); } - molecule = new t_pack_molecule; - molecule->type = MOLECULE_FORCED_PACK; - molecule->pack_pattern = pack_pattern; - molecule->atom_block_ids = std::vector(pack_pattern->num_blocks); //Initializes invalid - molecule->num_blocks = pack_pattern->num_blocks; - molecule->root = pack_pattern->root_block->block_id; + PackMoleculeId new_molecule_id = PackMoleculeId(pack_molecules_.size()); + t_pack_molecule molecule; + molecule.base_gain = 0.f; + molecule.type = e_pack_pattern_molecule_type::MOLECULE_FORCED_PACK; + molecule.pack_pattern = pack_pattern; + molecule.atom_block_ids = std::vector(pack_pattern->num_blocks); //Initializes invalid + molecule.root = pack_pattern->root_block->block_id; + molecule.chain_id = MoleculeChainId::INVALID(); - if (try_expand_molecule(molecule, blk_id, atom_molecules, atom_nlist)) { - // Success! commit molecule + if (!try_expand_molecule(molecule, blk_id, atom_molecules_multimap, atom_nlist)) { + // Failed to create molecule + return PackMoleculeId::INVALID(); + } - // update chain info for chain molecules - if (molecule->pack_pattern->is_chain) { - init_molecule_chain_info(blk_id, molecule, atom_molecules, atom_nlist); - } + // Success! commit molecule - // update the atom_molcules with the atoms that are mapped to this molecule - for (int i = 0; i < molecule->pack_pattern->num_blocks; i++) { - auto blk_id2 = molecule->atom_block_ids[i]; - if (!blk_id2) { - VTR_ASSERT(molecule->pack_pattern->is_block_optional[i]); - continue; - } + // update chain info for chain molecules + if (molecule.pack_pattern->is_chain) { + init_molecule_chain_info(blk_id, molecule, pack_molecules_, atom_molecules_multimap, chain_info_, atom_nlist); + } - atom_molecules.insert({blk_id2, molecule}); + // update the atom_molcules with the atoms that are mapped to this molecule + for (int i = 0; i < molecule.pack_pattern->num_blocks; i++) { + auto blk_id2 = molecule.atom_block_ids[i]; + if (!blk_id2) { + VTR_ASSERT(molecule.pack_pattern->is_block_optional[i]); + continue; } - } else { - // Failed to create molecule - delete molecule; - return nullptr; + + atom_molecules_multimap.insert({blk_id2, new_molecule_id}); } - return molecule; + pack_molecules_.push_back(std::move(molecule)); + pack_molecule_ids_.push_back(new_molecule_id); + return new_molecule_id; } /** @@ -1027,15 +1000,15 @@ static t_pack_molecule* try_create_molecule(t_pack_patterns* list_of_pack_patter * atom_molecules : map of atom block ids that are assigned a molecule and a pointer to this molecule * blk_id : chosen to be the root of this molecule and the code is expanding from */ -static bool try_expand_molecule(t_pack_molecule* molecule, +static bool try_expand_molecule(t_pack_molecule& molecule, const AtomBlockId blk_id, - const std::multimap& atom_molecules, + const std::multimap& atom_molecules, const AtomNetlist& atom_nlist) { // root block of the pack pattern, which is the starting point of this pattern - const auto pattern_root_block = molecule->pack_pattern->root_block; + const auto pattern_root_block = molecule.pack_pattern->root_block; // bool array indicating whether a position in a pack pattern is optional or should // be filled with an atom for legality - const auto is_block_optional = molecule->pack_pattern->is_block_optional; + const auto is_block_optional = molecule.pack_pattern->is_block_optional; // create a queue of pattern block and atom block id suggested for this block std::queue> pattern_block_queue; @@ -1054,7 +1027,7 @@ static bool try_expand_molecule(t_pack_molecule* molecule, pattern_block_queue.pop(); // get the atom block id of the atom occupying this primitive position in this molecule - auto molecule_atom_block_id = molecule->atom_block_ids[pattern_block->block_id]; + auto molecule_atom_block_id = molecule.atom_block_ids[pattern_block->block_id]; // if this primitive position in this molecule is already visited and // matches block in the atom netlist go to the next node in the queue @@ -1078,7 +1051,7 @@ static bool try_expand_molecule(t_pack_molecule* molecule, } // set this node in the molecule as visited - molecule->atom_block_ids[pattern_block->block_id] = block_id; + molecule.atom_block_ids[pattern_block->block_id] = block_id; // starting from the first connections, add all the connections of this block to the queue auto block_connection = pattern_block->connections; @@ -1178,13 +1151,12 @@ static AtomBlockId get_driving_block(const AtomBlockId block_id, } static void print_pack_molecules(const char* fname, - const t_pack_patterns* list_of_pack_patterns, + const std::vector& list_of_pack_patterns, const int num_pack_patterns, - const t_pack_molecule* list_of_molecules, + const vtr::vector_map& pack_molecules, const AtomNetlist& atom_nlist) { int i; FILE* fp; - const t_pack_molecule* list_of_molecules_current; fp = std::fopen(fname, "w"); fprintf(fp, "# of pack patterns %d\n", num_pack_patterns); @@ -1198,24 +1170,23 @@ static void print_pack_molecules(const char* fname, list_of_pack_patterns[i].root_block->pb_type->name); } - list_of_molecules_current = list_of_molecules; - while (list_of_molecules_current != nullptr) { - if (list_of_molecules_current->type == MOLECULE_SINGLE_ATOM) { + for (const t_pack_molecule& molecule : pack_molecules) { + if (molecule.type == e_pack_pattern_molecule_type::MOLECULE_SINGLE_ATOM) { fprintf(fp, "\nmolecule type: atom\n"); fprintf(fp, "\tpattern index %d: atom block %s\n", i, - atom_nlist.block_name(list_of_molecules_current->atom_block_ids[0]).c_str()); - } else if (list_of_molecules_current->type == MOLECULE_FORCED_PACK) { + atom_nlist.block_name(molecule.atom_block_ids[0]).c_str()); + } else if (molecule.type == e_pack_pattern_molecule_type::MOLECULE_FORCED_PACK) { fprintf(fp, "\nmolecule type: %s\n", - list_of_molecules_current->pack_pattern->name); - for (i = 0; i < list_of_molecules_current->pack_pattern->num_blocks; + molecule.pack_pattern->name); + for (i = 0; i < molecule.pack_pattern->num_blocks; i++) { - if (!list_of_molecules_current->atom_block_ids[i]) { + if (!molecule.atom_block_ids[i]) { fprintf(fp, "\tpattern index %d: empty \n", i); } else { fprintf(fp, "\tpattern index %d: atom block %s", i, - atom_nlist.block_name(list_of_molecules_current->atom_block_ids[i]).c_str()); - if (list_of_molecules_current->pack_pattern->root_block->block_id == i) { + atom_nlist.block_name(molecule.atom_block_ids[i]).c_str()); + if (molecule.pack_pattern->root_block->block_id == i) { fprintf(fp, " root node\n"); } else { fprintf(fp, "\n"); @@ -1225,7 +1196,6 @@ static void print_pack_molecules(const char* fname, } else { VTR_ASSERT(0); } - list_of_molecules_current = list_of_molecules_current->next; } fclose(fp); @@ -1332,7 +1302,7 @@ static int compare_pack_pattern(const t_pack_patterns* pattern_a, const t_pack_p */ static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_patterns, - const std::multimap& atom_molecules, + const std::multimap& atom_molecules, const AtomNetlist& atom_nlist) { AtomBlockId new_root_blk_id; t_pb_graph_pin* root_ipin; @@ -1630,14 +1600,16 @@ static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input * and so on. */ static void init_molecule_chain_info(const AtomBlockId blk_id, - t_pack_molecule* molecule, - const std::multimap &atom_molecules, + t_pack_molecule& molecule, + const vtr::vector_map& pack_molecules, + const std::multimap &atom_molecules, + vtr::vector& chain_info, const AtomNetlist& atom_nlist) { // the input molecule to this function should have a pack // pattern assigned to it and the input block should be valid - VTR_ASSERT(molecule->pack_pattern && blk_id); + VTR_ASSERT(molecule.pack_pattern && blk_id); - auto root_ipin = molecule->pack_pattern->chain_root_pins[0][0]; + auto root_ipin = molecule.pack_pattern->chain_root_pins[0][0]; auto model_pin = root_ipin->port->model_port; auto pin_bit = root_ipin->pin_number; @@ -1652,18 +1624,23 @@ static void init_molecule_chain_info(const AtomBlockId blk_id, // if either there is no driver to the block input pin or // if the driver is not part of a molecule if (!driver_atom_id || itr == atom_molecules.end()) { - // allocate chain info - molecule->chain_info = std::make_shared(); - // this is not the first molecule to be created for this chain + MoleculeChainId new_chain_id = MoleculeChainId(chain_info.size()); + t_chain_info new_chain_info; + new_chain_info.is_long_chain = false; + chain_info.push_back(std::move(new_chain_info)); + molecule.chain_id = new_chain_id; } else { + // this is not the first molecule to be created for this chain // molecule driving blk_id - auto prev_molecule = itr->second; + PackMoleculeId prev_molecule_id = itr->second; + VTR_ASSERT(prev_molecule_id.is_valid()); + const t_pack_molecule& prev_molecule = pack_molecules[prev_molecule_id]; // molecule should have chain_info associated with it - VTR_ASSERT(prev_molecule && prev_molecule->chain_info); + VTR_ASSERT(prev_molecule.chain_id.is_valid()); // this molecule is now known to belong to a long chain - prev_molecule->chain_info->is_long_chain = true; - // this new molecule should share the same chain_info - molecule->chain_info = prev_molecule->chain_info; + chain_info[prev_molecule.chain_id].is_long_chain = true; + // this new molecule should share the same chain + molecule.chain_id = prev_molecule.chain_id; } } @@ -1689,55 +1666,44 @@ static void print_chain_starting_points(t_pack_patterns* chain_pattern) { VTR_LOG("\n"); } -/** - * This function frees the linked list of pack molecules. - */ -static void free_pack_molecules(t_pack_molecule* list_of_pack_molecules) { - t_pack_molecule* cur_pack_molecule = list_of_pack_molecules; - while (cur_pack_molecule != nullptr) { - cur_pack_molecule = list_of_pack_molecules->next; - delete list_of_pack_molecules; - list_of_pack_molecules = cur_pack_molecule; - } -} - -void Prepacker::init(const AtomNetlist& atom_nlist, const std::vector& logical_block_types) { - VTR_ASSERT(list_of_pack_molecules == nullptr && "Prepacker cannot be initialized twice."); +Prepacker::Prepacker(const AtomNetlist& atom_nlist, + const std::vector& logical_block_types) { + VTR_ASSERT(pack_molecules_.empty() && "Prepacker cannot be initialized twice."); // Allocate the pack patterns from the logical block types. list_of_pack_patterns = alloc_and_load_pack_patterns(logical_block_types); // Use the pack patterns to allocate and load the pack molecules. - std::multimap atom_molecules_multimap; + std::multimap atom_molecules_multimap; expected_lowest_cost_pb_gnode.resize(atom_nlist.blocks().size(), nullptr); - list_of_pack_molecules = alloc_and_load_pack_molecules(list_of_pack_patterns.data(), - expected_lowest_cost_pb_gnode, - list_of_pack_patterns.size(), - atom_molecules_multimap, - atom_nlist, - logical_block_types); + alloc_and_load_pack_molecules(atom_molecules_multimap, + atom_nlist, + logical_block_types); // The multimap is a legacy thing. Since blocks can be part of multiple pack // patterns, during prepacking a block may be contained within multiple // molecules. However, by the end of prepacking, molecules should be // combined such that each block is contained in one and only one molecule. - atom_molecules.resize(atom_nlist.blocks().size(), nullptr); + atom_molecule_.resize(atom_nlist.blocks().size(), PackMoleculeId::INVALID()); for (AtomBlockId blk_id : atom_nlist.blocks()) { // Every atom block should be packed into a single molecule (no more // or less). VTR_ASSERT(atom_molecules_multimap.count(blk_id) == 1); - atom_molecules[blk_id] = atom_molecules_multimap.find(blk_id)->second; + atom_molecule_[blk_id] = atom_molecules_multimap.find(blk_id)->second; } } // TODO: Since this is constant per molecule, it may make sense to precompute // this information and store it in the prepacker class. This may be // expensive to calculate for large molecules. -t_molecule_stats Prepacker::calc_molecule_stats(const t_pack_molecule* molecule, +t_molecule_stats Prepacker::calc_molecule_stats(PackMoleculeId molecule_id, const AtomNetlist& atom_nlist) const { + VTR_ASSERT(molecule_id.is_valid()); t_molecule_stats molecule_stats; + const t_pack_molecule& molecule = pack_molecules_[molecule_id]; + //Calculate the number of available pins on primitives within the molecule - for (auto blk : molecule->atom_block_ids) { + for (auto blk : molecule.atom_block_ids) { if (!blk) continue; ++molecule_stats.num_blocks; //Record number of valid blocks in molecule @@ -1755,8 +1721,8 @@ t_molecule_stats Prepacker::calc_molecule_stats(const t_pack_molecule* molecule, molecule_stats.num_pins = molecule_stats.num_input_pins + molecule_stats.num_output_pins; //Calculate the number of externally used pins - std::set molecule_atoms(molecule->atom_block_ids.begin(), molecule->atom_block_ids.end()); - for (auto blk : molecule->atom_block_ids) { + std::set molecule_atoms(molecule.atom_block_ids.begin(), molecule.atom_block_ids.end()); + for (auto blk : molecule.atom_block_ids) { if (!blk) continue; for (auto pin : atom_nlist.block_pins(blk)) { @@ -1803,11 +1769,9 @@ t_molecule_stats Prepacker::calc_molecule_stats(const t_pack_molecule* molecule, t_molecule_stats Prepacker::calc_max_molecule_stats(const AtomNetlist& atom_nlist) const { t_molecule_stats max_molecules_stats; - t_pack_molecule* molecule_head = list_of_pack_molecules; - for (auto cur_molecule = molecule_head; cur_molecule != nullptr; cur_molecule = cur_molecule->next) { + for (PackMoleculeId molecule_id : molecules()) { //Calculate per-molecule statistics - (void)atom_nlist; - t_molecule_stats cur_molecule_stats = calc_molecule_stats(cur_molecule, atom_nlist); + t_molecule_stats cur_molecule_stats = calc_molecule_stats(molecule_id, atom_nlist); //Record the maximums (member-wise) over all molecules max_molecules_stats.num_blocks = std::max(max_molecules_stats.num_blocks, cur_molecule_stats.num_blocks); @@ -1824,15 +1788,9 @@ t_molecule_stats Prepacker::calc_max_molecule_stats(const AtomNetlist& atom_nlis return max_molecules_stats; } -void Prepacker::reset() { +Prepacker::~Prepacker() { // When the prepacker is reset (or destroyed), clean up the internal data // members. free_list_of_pack_patterns(list_of_pack_patterns); - free_pack_molecules(list_of_pack_molecules); - // Reset everything to default state. - list_of_pack_patterns.clear(); - list_of_pack_molecules = nullptr; - atom_molecules.clear(); - expected_lowest_cost_pb_gnode.clear(); } diff --git a/vpr/src/pack/prepack.h b/vpr/src/pack/prepack.h index 810c79bd19c..8fe2c583eca 100644 --- a/vpr/src/pack/prepack.h +++ b/vpr/src/pack/prepack.h @@ -7,19 +7,106 @@ * 2) Carry-chains */ -#ifndef PREPACK_H -#define PREPACK_H +#pragma once #include -#include "vpr_types.h" +#include "atom_netlist_fwd.h" +#include "cad_types.h" #include "vtr_assert.h" +#include "vtr_range.h" +#include "vtr_strong_id.h" #include "vtr_vector.h" +#include "vtr_vector_map.h" -class AtomNetlist; -class AtomBlockId; -struct t_molecule_stats; +// Forward declarations +class t_pack_molecule; struct t_logical_block_type; +// A unique ID used to identify a molecule generated by the prepacker. +struct pack_molecule_id_tag; +typedef vtr::StrongId PackMoleculeId; + +// A unique ID used to identify a chain of molecules generated by the prepacker. +struct molecule_chain_id_tag; +typedef vtr::StrongId MoleculeChainId; + +/** + * @brief Holds general information to be shared between molecules that + * represent the same chained pack pattern. + * + * For example, molecules that are representing a long carry chain that spans + * multiple logic blocks. + */ +struct t_chain_info { + /// @brief Is this a long chain that is divided on multiple clusters + /// (divided on multiple molecules). + bool is_long_chain = false; +}; + +/** + * @brief Describes the molecule pack pattern type. + */ +enum class e_pack_pattern_molecule_type : bool { + MOLECULE_SINGLE_ATOM, ///root_block in the atom_blocks_ids. + /// root_block_id = atom_block_ids[root] + int root; + + /// @brief [0..num_blocks-1] IDs of atom blocks that implements this molecule, + /// indexed by t_pack_pattern_block->block_id. + /// + /// This vector may contain invalid atom block ids (when the molecule does + /// not completely fill the pattern). + std::vector atom_block_ids; + + /// @brief The unique ID of the chain this molecule is a part of if is_chain. + /// If this molecule is not part of a chain, this would be invalid. + /// + /// Multiple molecules may point to the same chain. + MoleculeChainId chain_id; + + // ========================================================================= + // Class methods + // ========================================================================= + + // A molecule is a chain if it is a forced pack and its pack pattern is a chain + inline bool is_chain() const { + return type == e_pack_pattern_molecule_type::MOLECULE_FORCED_PACK && pack_pattern->is_chain; + } +}; + /** * @brief Statistics on a molecule. * @@ -79,16 +166,22 @@ struct t_molecule_stats { */ class Prepacker { public: - // The constructor is default, the init method performs prepacking. - Prepacker() = default; + // Iterator for the pack molecule IDs + typedef typename vtr::vector_map::const_iterator molecule_iterator; + + // Range for the pack molecule IDs + typedef typename vtr::Range molecule_range; // This class maintains pointers to internal data structures, and as such // should not be copied or moved (prevents unsafe accesses). Prepacker(const Prepacker&) = delete; Prepacker& operator=(const Prepacker&) = delete; + // Destructor of the class. + ~Prepacker(); + /** - * @brief Performs prepacking. + * @brief Construtor. Performs prepacking. * * Initializes the prepacker by performing prepacking and allocating the * necessary data strucutres. @@ -96,19 +189,28 @@ class Prepacker { * @param atom_nlist The atom netlist to prepack. * @param logical_block_types A list of the logical block types on the device. */ - void init(const AtomNetlist& atom_nlist, const std::vector &logical_block_types); + Prepacker(const AtomNetlist& atom_nlist, + const std::vector &logical_block_types); + + /** + * @brief A range of all prepacked molecules. Every atom should exist in one + * of these molecules. + */ + inline molecule_range molecules() const { + return vtr::make_range(pack_molecule_ids_.begin(), pack_molecule_ids_.end()); + } /** * @brief Get the cluster molecule containing the given atom block. * * @param blk_id The atom block to get the molecule of. */ - inline t_pack_molecule* get_atom_molecule(AtomBlockId blk_id) const { + inline PackMoleculeId get_atom_molecule(AtomBlockId blk_id) const { // Safety debug to ensure the blk is valid and has a molecule entry. - VTR_ASSERT_SAFE(blk_id.is_valid() && (size_t)blk_id < atom_molecules.size()); + VTR_ASSERT_SAFE(blk_id.is_valid() && (size_t)blk_id < atom_molecule_.size()); // Safety debug to ensure the molecule is valid - VTR_ASSERT_DEBUG(atom_molecules[blk_id] != nullptr); - return atom_molecules[blk_id]; + VTR_ASSERT_DEBUG(atom_molecule_[blk_id].is_valid()); + return atom_molecule_[blk_id]; } /** @@ -125,34 +227,10 @@ class Prepacker { return expected_lowest_cost_pb_gnode[blk_id]; } - /** - * @brief Returns the total number of molecules in the prepacker. - */ - inline size_t get_num_molecules() const { - size_t num_molecules = 0; - t_pack_molecule* molecule_head = list_of_pack_molecules; - for (auto cur_molecule = molecule_head; cur_molecule != nullptr; cur_molecule = cur_molecule->next) { - ++num_molecules; - } - return num_molecules; - } - - /** - * @brief Returns all of the molecules as a vector. - */ - inline std::vector get_molecules_vector() const { - std::vector molecules; - t_pack_molecule* molecule_head = list_of_pack_molecules; - for (auto cur_molecule = molecule_head; cur_molecule != nullptr; cur_molecule = cur_molecule->next) { - molecules.push_back(cur_molecule); - } - return molecules; - } - /* * @brief Calculates molecule statistics for a single molecule. */ - t_molecule_stats calc_molecule_stats(const t_pack_molecule* molecule, + t_molecule_stats calc_molecule_stats(PackMoleculeId molecule_id, const AtomNetlist& atom_netlist) const; /** @@ -165,37 +243,76 @@ class Prepacker { */ inline size_t get_max_molecule_size() const { size_t max_molecule_size = 1; - t_pack_molecule* molecule_head = list_of_pack_molecules; - for (auto cur_molecule = molecule_head; cur_molecule != nullptr; cur_molecule = cur_molecule->next) { - max_molecule_size = std::max(max_molecule_size, cur_molecule->num_blocks); + for (const t_pack_molecule& molecule : pack_molecules_) { + max_molecule_size = std::max(max_molecule_size, molecule.atom_block_ids.size()); } return max_molecule_size; } /** - * @brief Resets the prepacker object. Clearing all state. - * - * This resets the prepacker, allowing it to prepack again and also freeing - * any state. + * @brief Get information about the molecule associated with the given ID. + */ + inline const t_pack_molecule& get_molecule(PackMoleculeId molecule_id) const { + VTR_ASSERT(molecule_id.is_valid()); + return pack_molecules_[molecule_id]; + } + + /** + * @brief Get information about the chain associated with the given ID. */ - void reset(); + inline const t_chain_info& get_molecule_chain_info(MoleculeChainId chain_id) const { + VTR_ASSERT(chain_id.is_valid()); + return chain_info_[chain_id]; + } - /// @brief Destructor of the prepacker class. Calls the reset method. - ~Prepacker() { reset(); } + /** + * @brief Get the number of unique molecule chains from the prepacker. + */ + inline size_t get_num_molecule_chains() const { + return chain_info_.size(); + } private: /** - * @brief A linked list of all the packing molecules that are loaded in - * prepacking stage. + * Pre-pack atoms in netlist to molecules + * 1. Single atoms are by definition a molecule. + * 2. Forced pack molecules are groupings of atoms that matches a t_pack_pattern definition. + * 3. Chained molecules are molecules that follow a carry-chain style pattern, + * ie. a single linear chain that can be split across multiple complex blocks + */ + void alloc_and_load_pack_molecules(std::multimap& atom_molecules_multimap, + const AtomNetlist& atom_nlist, + const std::vector& logical_block_types); + + /** + * Given a pattern and an atom block to serve as the root block, determine if + * the candidate atom block serving as the root node matches the pattern. + * If yes, return the molecule with this atom block as the root, if not, return NULL * - * All of the molecules in the prepacker are allocated into this linked list - * and must be freed eventually. + * Limitations: Currently assumes that forced pack nets must be single-fanout as + * this covers all the reasonable architectures we wanted. More complicated + * structures should probably be handled either downstream (general packing) + * or upstream (in tech mapping). + * If this limitation is too constraining, code is designed so that this limitation can be removed * - * TODO: Should use a vtr::vector instead of a linked list for storage. Then - * instead of pointers, IDs can be used to manipulate the molecules - * which would be safer. + * Side Effect: If successful, link atom to molecule + */ + PackMoleculeId try_create_molecule(const int pack_pattern_index, + AtomBlockId blk_id, + std::multimap& atom_molecules_multimap, + const AtomNetlist& atom_nlist); +private: + /** + * @brief Collection of all molecule IDs. If an entry in this map is invalid + * it means that the molecule should be destroyed. + */ + vtr::vector_map pack_molecule_ids_; + + /** + * @brief Lookup between each molecule ID and the information associated with + * that molecule. */ - t_pack_molecule* list_of_pack_molecules = nullptr; + vtr::vector_map pack_molecules_; /** * @brief The molecules associated with each atom block. @@ -203,7 +320,7 @@ class Prepacker { * This vector is loaded in the init method and cleared in the reset method. * The pointers in this vector are shared with list_of_pack_molecules. */ - vtr::vector atom_molecules; + vtr::vector atom_molecule_; /// @brief A vector of the expected lowest cost physical block graph node. vtr::vector expected_lowest_cost_pb_gnode; @@ -212,6 +329,11 @@ class Prepacker { /// molecules keep pointers to this vector, so this needs to remain /// for the lifetime of the molecules. std::vector list_of_pack_patterns; + + /** + * @brief Lookup between each chain ID and the information associated with + * that chain. + */ + vtr::vector chain_info_; }; -#endif diff --git a/vpr/src/pack/sync_netlists_to_routing_flat.cpp b/vpr/src/pack/sync_netlists_to_routing_flat.cpp index 8aa54bb7f1a..4ced3b9afd4 100644 --- a/vpr/src/pack/sync_netlists_to_routing_flat.cpp +++ b/vpr/src/pack/sync_netlists_to_routing_flat.cpp @@ -5,19 +5,15 @@ */ #include "clustered_netlist_fwd.h" -#include "clustered_netlist_utils.h" #include "logic_types.h" #include "netlist_fwd.h" #include "physical_types.h" +#include "physical_types_util.h" #include "vtr_time.h" #include "vtr_assert.h" -#include "vtr_log.h" -#include "annotate_routing.h" #include "globals.h" -#include "vpr_error.h" #include "vpr_utils.h" -#include "rr_graph2.h" #include "sync_netlists_to_routing_flat.h" diff --git a/vpr/src/pack/verify_flat_placement.cpp b/vpr/src/pack/verify_flat_placement.cpp index 5e657eabb98..1aee5bd53ae 100644 --- a/vpr/src/pack/verify_flat_placement.cpp +++ b/vpr/src/pack/verify_flat_placement.cpp @@ -69,14 +69,14 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme // // TODO: In the future, we can support if some of the atoms are undefined, // but that can be fixed-up before calling this method. - std::vector molecules = prepacker.get_molecules_vector(); - for (t_pack_molecule* mol : molecules) { - AtomBlockId root_blk_id = mol->atom_block_ids[mol->root]; + for (PackMoleculeId mol_id : prepacker.molecules()) { + const t_pack_molecule& mol = prepacker.get_molecule(mol_id); + AtomBlockId root_blk_id = mol.atom_block_ids[mol.root]; float root_pos_x = flat_placement_info.blk_x_pos[root_blk_id]; float root_pos_y = flat_placement_info.blk_y_pos[root_blk_id]; float root_layer = flat_placement_info.blk_layer[root_blk_id]; int root_sub_tile = flat_placement_info.blk_sub_tile[root_blk_id]; - for (AtomBlockId mol_blk_id : mol->atom_block_ids) { + for (AtomBlockId mol_blk_id : mol.atom_block_ids) { if (!mol_blk_id.is_valid()) continue; if (flat_placement_info.blk_x_pos[mol_blk_id] != root_pos_x || diff --git a/vpr/src/place/compressed_grid.cpp b/vpr/src/place/compressed_grid.cpp index 33fa04cbfc1..00889b114d6 100644 --- a/vpr/src/place/compressed_grid.cpp +++ b/vpr/src/place/compressed_grid.cpp @@ -3,6 +3,7 @@ #include "arch_util.h" #include "globals.h" +#include "physical_types_util.h" #include "vtr_time.h" /** diff --git a/vpr/src/place/delay_model/override_delay_model.cpp b/vpr/src/place/delay_model/override_delay_model.cpp index 83141fb4bad..60c99f6b793 100644 --- a/vpr/src/place/delay_model/override_delay_model.cpp +++ b/vpr/src/place/delay_model/override_delay_model.cpp @@ -2,6 +2,7 @@ #include "override_delay_model.h" #include "compute_delta_delays_utils.h" +#include "physical_types_util.h" #ifdef VTR_ENABLE_CAPNPROTO # include "capnp/serialize.h" diff --git a/vpr/src/place/delay_model/place_delay_model.cpp b/vpr/src/place/delay_model/place_delay_model.cpp index 04267e0e5f1..6ff7ad3a0cf 100644 --- a/vpr/src/place/delay_model/place_delay_model.cpp +++ b/vpr/src/place/delay_model/place_delay_model.cpp @@ -7,7 +7,7 @@ #include "place_delay_model.h" #include "globals.h" -#include "router_lookahead_map.h" +#include "physical_types_util.h" #include "placer_state.h" #include "vpr_error.h" diff --git a/vpr/src/place/grid_tile_lookup.cpp b/vpr/src/place/grid_tile_lookup.cpp index 964fbb1a6b3..cfef5d21e9b 100644 --- a/vpr/src/place/grid_tile_lookup.cpp +++ b/vpr/src/place/grid_tile_lookup.cpp @@ -1,4 +1,5 @@ #include "grid_tile_lookup.h" +#include "physical_types_util.h" GridTileLookup::GridTileLookup() : max_placement_locations(g_vpr_ctx.device().logical_block_types.size()) { diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 50d71de0d68..4f385508051 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -1,7 +1,7 @@ #include "FlatPlacementInfo.h" #include "atom_netlist_fwd.h" +#include "physical_types_util.h" #include "place_macro.h" -#include "vtr_memory.h" #include "vtr_random.h" #include "vtr_time.h" #include "vpr_types.h" diff --git a/vpr/src/place/move_generators/centroid_move_generator.cpp b/vpr/src/place/move_generators/centroid_move_generator.cpp index 767fbf2ce7e..509cc4ff1ff 100644 --- a/vpr/src/place/move_generators/centroid_move_generator.cpp +++ b/vpr/src/place/move_generators/centroid_move_generator.cpp @@ -1,4 +1,5 @@ #include "centroid_move_generator.h" +#include "physical_types_util.h" #include "vpr_types.h" #include "globals.h" #include "place_constraints.h" @@ -309,4 +310,4 @@ t_pl_loc CentroidMoveGenerator::calculate_centroid_loc_(ClusterBlockId b_from, centroid.layer = (int)std::round(acc_layer / acc_weight); return centroid; -} \ No newline at end of file +} diff --git a/vpr/src/place/move_generators/critical_uniform_move_generator.cpp b/vpr/src/place/move_generators/critical_uniform_move_generator.cpp index 7d36889c2f6..cffa0cb9254 100644 --- a/vpr/src/place/move_generators/critical_uniform_move_generator.cpp +++ b/vpr/src/place/move_generators/critical_uniform_move_generator.cpp @@ -2,6 +2,7 @@ #include "critical_uniform_move_generator.h" #include "globals.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "placer_state.h" #include "move_utils.h" diff --git a/vpr/src/place/move_generators/feasible_region_move_generator.cpp b/vpr/src/place/move_generators/feasible_region_move_generator.cpp index 1c719a7b0ff..69bbd6ab948 100644 --- a/vpr/src/place/move_generators/feasible_region_move_generator.cpp +++ b/vpr/src/place/move_generators/feasible_region_move_generator.cpp @@ -1,6 +1,7 @@ #include "feasible_region_move_generator.h" #include "globals.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "placer_state.h" #include "move_utils.h" @@ -150,4 +151,4 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& } return create_move; -} \ No newline at end of file +} diff --git a/vpr/src/place/move_generators/manual_move_generator.cpp b/vpr/src/place/move_generators/manual_move_generator.cpp index f320d9ef1ea..98405265067 100644 --- a/vpr/src/place/move_generators/manual_move_generator.cpp +++ b/vpr/src/place/move_generators/manual_move_generator.cpp @@ -12,6 +12,7 @@ #include "manual_move_generator.h" #include "manual_moves.h" +#include "physical_types_util.h" #include "placer_state.h" #ifndef NO_GRAPHICS diff --git a/vpr/src/place/move_generators/median_move_generator.cpp b/vpr/src/place/move_generators/median_move_generator.cpp index 99c1b892e17..6103bd73564 100644 --- a/vpr/src/place/move_generators/median_move_generator.cpp +++ b/vpr/src/place/move_generators/median_move_generator.cpp @@ -1,6 +1,7 @@ #include "median_move_generator.h" #include "globals.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "placer_state.h" #include "move_utils.h" diff --git a/vpr/src/place/move_generators/uniform_move_generator.cpp b/vpr/src/place/move_generators/uniform_move_generator.cpp index 7190918aba3..c183cd60dde 100644 --- a/vpr/src/place/move_generators/uniform_move_generator.cpp +++ b/vpr/src/place/move_generators/uniform_move_generator.cpp @@ -1,6 +1,7 @@ #include "uniform_move_generator.h" #include "globals.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "placer_state.h" #include "move_utils.h" diff --git a/vpr/src/place/move_generators/weighted_median_move_generator.cpp b/vpr/src/place/move_generators/weighted_median_move_generator.cpp index de949d37a75..edd1363c886 100644 --- a/vpr/src/place/move_generators/weighted_median_move_generator.cpp +++ b/vpr/src/place/move_generators/weighted_median_move_generator.cpp @@ -1,6 +1,7 @@ #include "weighted_median_move_generator.h" #include "globals.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "placer_state.h" #include "move_utils.h" diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index b8d0cb3c9e2..f05419afbfd 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -3,6 +3,7 @@ #include "move_transactions.h" #include "globals.h" +#include "physical_types_util.h" #include "vtr_random.h" #include "draw_debug.h" diff --git a/vpr/src/place/noc_place_utils.cpp b/vpr/src/place/noc_place_utils.cpp index 9f5fbb6045d..5fbe1cfac23 100644 --- a/vpr/src/place/noc_place_utils.cpp +++ b/vpr/src/place/noc_place_utils.cpp @@ -2,6 +2,7 @@ #include "noc_place_utils.h" #include "globals.h" +#include "physical_types_util.h" #include "vtr_log.h" #include "vtr_assert.h" #include "vtr_random.h" diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 2fee09e9d7b..60af70704a6 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -10,6 +10,7 @@ #include "globals.h" #include "place_constraints.h" +#include "physical_types_util.h" #include "place_util.h" #include "vpr_context.h" diff --git a/vpr/src/place/place_macro.cpp b/vpr/src/place/place_macro.cpp index 3568405290c..23520a3cbed 100644 --- a/vpr/src/place/place_macro.cpp +++ b/vpr/src/place/place_macro.cpp @@ -7,6 +7,7 @@ #include #include +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_util.h" #include "vpr_utils.h" diff --git a/vpr/src/place/place_util.cpp b/vpr/src/place/place_util.cpp index e3f3d9da567..f2e47ea17c6 100644 --- a/vpr/src/place/place_util.cpp +++ b/vpr/src/place/place_util.cpp @@ -7,6 +7,7 @@ #include "place_util.h" #include "globals.h" #include "draw_global.h" +#include "physical_types_util.h" #include "place_constraints.h" #include "noc_place_utils.h" diff --git a/vpr/src/place/verify_placement.cpp b/vpr/src/place/verify_placement.cpp index 9e9dd6fbcd8..2330b340b64 100644 --- a/vpr/src/place/verify_placement.cpp +++ b/vpr/src/place/verify_placement.cpp @@ -18,6 +18,7 @@ #include "device_grid.h" #include "partition_region.h" #include "physical_types.h" +#include "physical_types_util.h" #include "place_macro.h" #include "vpr_context.h" #include "vpr_types.h" diff --git a/vpr/src/power/power.cpp b/vpr/src/power/power.cpp index f2df57f8e88..af1bf0560c5 100644 --- a/vpr/src/power/power.cpp +++ b/vpr/src/power/power.cpp @@ -26,13 +26,12 @@ #include #include #include -#include +#include "physical_types_util.h" #include "vtr_util.h" #include "vtr_path.h" #include "vtr_log.h" #include "vtr_assert.h" -#include "vtr_memory.h" #include "power.h" #include "power_components.h" @@ -44,7 +43,6 @@ #include "physical_types.h" #include "globals.h" -#include "rr_graph.h" #include "vpr_utils.h" /************************* DEFINES **********************************/ diff --git a/vpr/src/route/cb_metrics.cpp b/vpr/src/route/cb_metrics.cpp index a1fa4294179..c549afe5e04 100644 --- a/vpr/src/route/cb_metrics.cpp +++ b/vpr/src/route/cb_metrics.cpp @@ -19,28 +19,22 @@ #include #include -#include #include #include #include -#include -#include -#include -#include #include #include #include +#include "physical_types_util.h" #include "vtr_random.h" -#include "vtr_assert.h" #include "vtr_log.h" #include "vtr_math.h" #include "vpr_types.h" #include "vpr_error.h" -#include "vpr_utils.h" #include "cb_metrics.h" diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp index a8bc1f98126..725edeb8d13 100644 --- a/vpr/src/route/check_route.cpp +++ b/vpr/src/route/check_route.cpp @@ -1,21 +1,19 @@ #include "check_route.h" +#include "physical_types_util.h" #include "route_common.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "vtr_memory.h" #include "vtr_time.h" #include "vpr_types.h" #include "vpr_error.h" #include "globals.h" -#include "route_export.h" #include "rr_graph.h" #include "check_rr_graph.h" -#include "read_xml_arch_file.h" #include "route_tree.h" /******************** Subroutines local to this module **********************/ diff --git a/vpr/src/route/overuse_report.cpp b/vpr/src/route/overuse_report.cpp index a542e58000e..c9be3b22a22 100644 --- a/vpr/src/route/overuse_report.cpp +++ b/vpr/src/route/overuse_report.cpp @@ -1,6 +1,7 @@ #include "overuse_report.h" #include +#include "physical_types_util.h" #include "vtr_log.h" /** diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index 5ec0184be49..5ef6480a1f5 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -2,11 +2,16 @@ #include "atom_netlist_utils.h" #include "connection_router_interface.h" +#include "describe_rr_node.h" #include "draw_global.h" -#include "place_and_route.h" #include "route_common.h" +#include "physical_types_util.h" #include "route_export.h" -#include "rr_graph.h" + +#if defined(VPR_USE_TBB) +# include +# include +#endif /* The numbering relation between the channels and clbs is: * * * diff --git a/vpr/src/route/route_utils.cpp b/vpr/src/route/route_utils.cpp index b398066769f..abc89a66ec5 100644 --- a/vpr/src/route/route_utils.cpp +++ b/vpr/src/route/route_utils.cpp @@ -10,6 +10,7 @@ #include "net_delay.h" #include "netlist_fwd.h" #include "overuse_report.h" +#include "physical_types_util.h" #include "place_and_route.h" #include "route_debug.h" diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp index a3d468b901c..b0c5e719eb9 100644 --- a/vpr/src/route/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead_map.cpp @@ -24,20 +24,16 @@ #include #include #include "connection_router_interface.h" +#include "physical_types_util.h" #include "vpr_types.h" -#include "vpr_error.h" #include "vpr_utils.h" #include "globals.h" #include "vtr_math.h" -#include "vtr_log.h" #include "vtr_assert.h" #include "vtr_time.h" -#include "vtr_geometry.h" #include "router_lookahead_map.h" #include "router_lookahead_map_utils.h" -#include "rr_graph2.h" #include "rr_graph.h" -#include "route_common.h" #ifdef VTR_ENABLE_CAPNPROTO # include "capnp/serialize.h" diff --git a/vpr/src/route/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead_map_utils.cpp index 5a55ed8c979..9ec6e6a9151 100644 --- a/vpr/src/route/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead_map_utils.cpp @@ -12,6 +12,7 @@ #include #include "globals.h" +#include "physical_types_util.h" #include "vpr_context.h" #include "vtr_math.h" #include "vtr_time.h" diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 0b2073555de..6b91ebe46c4 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -5,10 +5,11 @@ #include #include #include +#include "alloc_and_load_rr_indexed_data.h" +#include "physical_types_util.h" #include "vtr_assert.h" #include "vtr_util.h" -#include "vtr_memory.h" #include "vtr_math.h" #include "vtr_log.h" #include "vtr_time.h" @@ -25,15 +26,11 @@ #include "rr_graph2.h" #include "rr_graph_sbox.h" #include "rr_graph_timing_params.h" -#include "rr_graph_indexed_data.h" #include "check_rr_graph.h" -#include "read_xml_arch_file.h" #include "echo_files.h" -#include "cb_metrics.h" #include "build_switchblocks.h" #include "rr_graph_writer.h" #include "rr_graph_reader.h" -#include "router_lookahead_map.h" #include "rr_graph_clock.h" #include "edge_groups.h" #include "rr_graph_builder.h" diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index fc271a8b795..128617d317e 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1,9 +1,9 @@ #include +#include "describe_rr_node.h" +#include "physical_types_util.h" #include "vtr_util.h" #include "vtr_assert.h" -#include "vtr_log.h" -#include "vtr_memory.h" #include "vpr_types.h" #include "vpr_error.h" @@ -11,9 +11,7 @@ #include "globals.h" #include "rr_graph_utils.h" #include "rr_graph2.h" -#include "rr_graph.h" #include "rr_graph_sbox.h" -#include "read_xml_arch_file.h" #include "rr_types.h" constexpr short UN_SET = -1; @@ -3161,4 +3159,4 @@ static bool should_apply_switch_override(int switch_override) { inline int get_chan_width(enum e_side side, const t_chan_width* nodes_per_chan) { return (side == TOP || side == BOTTOM ? nodes_per_chan->y_max : nodes_per_chan->x_max); -} \ No newline at end of file +} diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 37b485158c0..b2240c5bcf6 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -4,11 +4,10 @@ #include #include "pack_types.h" -#include "prepack.h" +#include "physical_types_util.h" #include "vpr_context.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "vtr_memory.h" #include "vpr_types.h" #include "vpr_error.h" @@ -19,7 +18,6 @@ #include "cluster_placement.h" #include "device_grid.h" #include "user_route_constraints.h" -#include "placer_state.h" #include "grid_block.h" /* This module contains subroutines that are used in several unrelated parts * diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index abaafadbfe7..23d69eae471 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -1,23 +1,18 @@ #ifndef VPR_UTILS_H #define VPR_UTILS_H -#include -#include - -#include "vpr_types.h" -#include "vtr_vector.h" - -#include "atom_netlist.h" -#include "clustered_netlist.h" -#include "netlist.h" #include "arch_util.h" -#include "physical_types_util.h" +#include "atom_netlist.h" +#include "device_grid.h" #include "rr_graph_utils.h" -#include "vpr_constraints.h" +#include "vpr_types.h" +#include "vtr_vector.h" +#include +#include +// Forward declaration class DeviceGrid; -class PlacerState; -class Prepacker; +class UserRouteConstraints; const t_model* find_model(const t_model* models, const std::string& name, bool required = true); const t_model_ports* find_model_port(const t_model* model, const std::string& name, bool required = true); diff --git a/vpr/test/test_ap_netlist.cpp b/vpr/test/test_ap_netlist.cpp index 9dad87819ca..ddbeffeea2b 100644 --- a/vpr/test/test_ap_netlist.cpp +++ b/vpr/test/test_ap_netlist.cpp @@ -11,7 +11,7 @@ #include "catch2/catch_test_macros.hpp" #include "ap_netlist.h" -#include "vpr_types.h" +#include "prepack.h" namespace { @@ -19,18 +19,18 @@ TEST_CASE("test_ap_netlist_data_storage", "[vpr_ap_netlist]") { // Create a test netlist object. APNetlist test_netlist("test_netlist"); // Create a few molecules. - t_pack_molecule mol_a; - t_pack_molecule mol_b; - t_pack_molecule mol_c; + PackMoleculeId mol_a_id; + PackMoleculeId mol_b_id; + PackMoleculeId mol_c_id; // Create blocks for these molecules. - APBlockId block_id_a = test_netlist.create_block("BlockA", &mol_a); - APBlockId block_id_b = test_netlist.create_block("BlockB", &mol_b); - APBlockId block_id_c = test_netlist.create_block("BlockC", &mol_c); + APBlockId block_id_a = test_netlist.create_block("BlockA", mol_a_id); + APBlockId block_id_b = test_netlist.create_block("BlockB", mol_b_id); + APBlockId block_id_c = test_netlist.create_block("BlockC", mol_c_id); SECTION("Test block_molecule returns the correct molecule after creation") { - REQUIRE(test_netlist.block_molecule(block_id_a) == &mol_a); - REQUIRE(test_netlist.block_molecule(block_id_b) == &mol_b); - REQUIRE(test_netlist.block_molecule(block_id_c) == &mol_c); + REQUIRE(test_netlist.block_molecule(block_id_a) == mol_a_id); + REQUIRE(test_netlist.block_molecule(block_id_b) == mol_b_id); + REQUIRE(test_netlist.block_molecule(block_id_c) == mol_c_id); } // Delete block B to reorganize the blocks internally. @@ -42,13 +42,13 @@ TEST_CASE("test_ap_netlist_data_storage", "[vpr_ap_netlist]") { block_id_c = test_netlist.find_block("BlockC"); SECTION("Test block_molecule returns the correct molecule after compression") { - REQUIRE(test_netlist.block_molecule(block_id_a) == &mol_a); - REQUIRE(test_netlist.block_molecule(block_id_c) == &mol_c); + REQUIRE(test_netlist.block_molecule(block_id_a) == mol_a_id); + REQUIRE(test_netlist.block_molecule(block_id_c) == mol_c_id); } // Create a new block, and fix its location. - t_pack_molecule fixed_mol; - APBlockId fixed_block_id = test_netlist.create_block("FixedBlock", &fixed_mol); + PackMoleculeId fixed_mol_id; + APBlockId fixed_block_id = test_netlist.create_block("FixedBlock", fixed_mol_id); APFixedBlockLoc fixed_block_loc; fixed_block_loc.x = 12; fixed_block_loc.y = 42; diff --git a/vpr/test/test_ap_partial_placement.cpp b/vpr/test/test_ap_partial_placement.cpp index c460df48227..5e0ebf16c33 100644 --- a/vpr/test/test_ap_partial_placement.cpp +++ b/vpr/test/test_ap_partial_placement.cpp @@ -12,7 +12,7 @@ #include "ap_netlist.h" #include "partial_placement.h" -#include "vpr_types.h" +#include "prepack.h" namespace { @@ -20,13 +20,13 @@ TEST_CASE("test_ap_partial_placement_verify", "[vpr_ap]") { // Create a test netlist object. APNetlist test_netlist("test_netlist"); // Create a few molecules. - t_pack_molecule mol_a; - t_pack_molecule mol_b; - t_pack_molecule mol_c; + PackMoleculeId mol_a_id; + PackMoleculeId mol_b_id; + PackMoleculeId mol_c_id; // Create blocks for these molecules. - APBlockId block_id_a = test_netlist.create_block("BlockA", &mol_a); - APBlockId block_id_b = test_netlist.create_block("BlockB", &mol_b); - APBlockId block_id_c = test_netlist.create_block("BlockC", &mol_c); + APBlockId block_id_a = test_netlist.create_block("BlockA", mol_a_id); + APBlockId block_id_b = test_netlist.create_block("BlockB", mol_b_id); + APBlockId block_id_c = test_netlist.create_block("BlockC", mol_c_id); // Fix BlockC. APFixedBlockLoc fixed_block_loc; fixed_block_loc.x = 12;