diff --git a/libs/libvtrutil/src/vtr_log.h b/libs/libvtrutil/src/vtr_log.h index 3c52e249d9d..b1cc4c15186 100644 --- a/libs/libvtrutil/src/vtr_log.h +++ b/libs/libvtrutil/src/vtr_log.h @@ -13,8 +13,10 @@ * * Three types of log message types are defined: * - VTR_LOG : The standard 'info' type log message - * - VTR_LOG_WARN : A warning log message. This represents unusual condition that may indicate an issue but executiom continues - * - VTR_LOG_ERROR : An error log message. This represents a clear issue that should result in stopping the program execution. Please note that using this log message will not actually terminate the program. So a VtrError should be thrown after all the neccessary VTR_LOG_ERROR messages are printed. + * - VTR_LOG_WARN : A warning log message. This represents an unusual condition that may indicate an issue but execution continues + * - VTR_LOG_ERROR : An error log message. This represents a clear issue that should result in stopping the program execution. + * Please note that using this log message will not actually terminate the program. So a VtrError should be thrown + * after all the necessary VTR_LOG_ERROR messages are printed. * * For example: * @@ -27,7 +29,7 @@ * * Each of the three message types also have a VTR_LOGV_* variant, * which will cause the message to be logged if a user-defined condition - * is satisifed. + * is satisfied. * * For example: * diff --git a/vpr/src/base/blk_loc_registry.h b/vpr/src/base/blk_loc_registry.h index 9d3704f2c1c..4157299dbc0 100644 --- a/vpr/src/base/blk_loc_registry.h +++ b/vpr/src/base/blk_loc_registry.h @@ -1,5 +1,5 @@ -#ifndef VTR_BLK_LOC_REGISTRY_H -#define VTR_BLK_LOC_REGISTRY_H + +#pragma once #include "clustered_netlist_fwd.h" #include "vtr_vector_map.h" @@ -44,7 +44,14 @@ class BlkLocRegistry { */ PlaceMacros place_macros_; + /// @brief Stores ClusterBlockId of all movable clustered blocks + /// (blocks that are not locked down to a single location) + std::vector movable_blocks_; + public: + + ///@brief Stores ClusterBlockId of all movable clustered blocks of each block type + std::vector> movable_blocks_per_type_; const vtr::vector_map& block_locs() const; vtr::vector_map& mutable_block_locs(); @@ -66,6 +73,20 @@ class BlkLocRegistry { ///@brief Returns a mutable reference to placement macros. PlaceMacros& mutable_place_macros(); + /// @brief Returns a constant reference to the vector of ClusterBlockIds of all movable clustered blocks. + const std::vector& movable_blocks() const { return movable_blocks_; } + + /// @brief Returns a mutable reference to the vector of ClusterBlockIds of all movable clustered blocks. + std::vector& mutable_movable_blocks() { return movable_blocks_; } + + /// @brief Returns a constant reference to a vector of vectors, where each inner vector contains ClusterBlockIds + /// of movable clustered blocks for a specific block type + const std::vector>& movable_blocks_per_type() const { return movable_blocks_per_type_; } + + /// @brief Returns a mutable reference to a vector of vectors, where each inner vector contains ClusterBlockIds + /// of movable clustered blocks for a specific block type. + std::vector>& mutable_movable_blocks_per_type() { return movable_blocks_per_type_; } + /** * @brief Performs error checking to see if location is legal for block type, * and sets the location and grid usage of the block if it is legal. @@ -149,5 +170,3 @@ class BlkLocRegistry { e_expected_transaction expected_transaction_; }; - -#endif //VTR_BLK_LOC_REGISTRY_H diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 73a252a516a..9ec647e95df 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -362,12 +362,6 @@ struct PlacementContext : public Context { */ void unlock_loc_vars() { VTR_ASSERT_SAFE(!loc_vars_are_accessible_); loc_vars_are_accessible_ = true; } - ///@brief Stores ClusterBlockId of all movable clustered blocks (blocks that are not locked down to a single location) - std::vector movable_blocks; - - ///@brief Stores ClusterBlockId of all movable clustered of each block type - std::vector> movable_blocks_per_type; - /** * @brief Compressed grid space for each block type * diff --git a/vpr/src/place/RL_agent_util.cpp b/vpr/src/place/RL_agent_util.cpp index b33e05f077a..574a8118bb5 100644 --- a/vpr/src/place/RL_agent_util.cpp +++ b/vpr/src/place/RL_agent_util.cpp @@ -1,6 +1,9 @@ #include "RL_agent_util.h" + #include "static_move_generator.h" #include "manual_move_generator.h" +#include "placer_state.h" + std::pair, std::unique_ptr> create_move_generators(PlacerState& placer_state, const t_placer_opts& placer_opts, @@ -60,6 +63,13 @@ std::pair, std::unique_ptr> create second_state_avail_moves.push_back(e_move_type::NOC_ATTRACTION_CENTROID); } + std::vector num_movable_blocks_per_type; + std::ranges::transform(placer_state.blk_loc_registry().movable_blocks_per_type(), + std::back_inserter(num_movable_blocks_per_type), + [](const auto& innerVec) noexcept { + return innerVec.size(); + }); + if (placer_opts.place_agent_algorithm == e_agent_algorithm::E_GREEDY) { std::unique_ptr karmed_bandit_agent1, karmed_bandit_agent2; //agent's 1st state @@ -68,13 +78,15 @@ std::pair, std::unique_ptr> create karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_BLOCK_TYPE, placer_opts.place_agent_epsilon, - rng); + rng, + num_movable_blocks_per_type); } else { VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon, - rng); + rng, + num_movable_blocks_per_type); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.first = std::make_unique(placer_state, @@ -87,7 +99,8 @@ std::pair, std::unique_ptr> create karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE, placer_opts.place_agent_epsilon, - rng); + rng, + num_movable_blocks_per_type); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.second = std::make_unique(placer_state, reward_fun, @@ -102,12 +115,14 @@ std::pair, std::unique_ptr> create VTR_LOG("Using simple RL 'Softmax agent' for choosing move and block types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_BLOCK_TYPE, - rng); + rng, + num_movable_blocks_per_type); } else { VTR_LOG("Using simple RL 'Softmax agent' for choosing move types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_TYPE, - rng); + rng, + num_movable_blocks_per_type); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.first = std::make_unique(placer_state, @@ -119,7 +134,8 @@ std::pair, std::unique_ptr> create //agent's 2nd state karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE, - rng); + rng, + num_movable_blocks_per_type); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.second = std::make_unique(placer_state, reward_fun, diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index e6c8f8e09db..62f5795c372 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -239,17 +239,17 @@ static void place_all_blocks(const t_placer_opts& placer_opts, * throws an error indicating that initial placement can not be done with the current device size or * floorplanning constraints. */ -static void check_initial_placement_legality(const vtr::vector_map& block_locs); +static void check_initial_placement_legality(const BlkLocRegistry& blk_loc_registry); /** * @brief Fills movable_blocks in global PlacementContext */ -static void alloc_and_load_movable_blocks(const vtr::vector_map& block_locs); +static void alloc_and_load_movable_blocks(BlkLocRegistry& blk_loc_registry); -static void check_initial_placement_legality(const vtr::vector_map& block_locs) { - auto& cluster_ctx = g_vpr_ctx.clustering(); - auto& place_ctx = g_vpr_ctx.placement(); - auto& device_ctx = g_vpr_ctx.device(); +static void check_initial_placement_legality(const BlkLocRegistry& blk_loc_registry) { + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& device_ctx = g_vpr_ctx.device(); + const auto& block_locs = blk_loc_registry.block_locs(); int unplaced_blocks = 0; @@ -271,14 +271,14 @@ static void check_initial_placement_legality(const vtr::vector_map& block_locs) { - auto& place_ctx = g_vpr_ctx.mutable_placement(); +static void alloc_and_load_movable_blocks(BlkLocRegistry& blk_loc_registry) { const auto& cluster_ctx = g_vpr_ctx.clustering(); const auto& device_ctx = g_vpr_ctx.device(); - place_ctx.movable_blocks.clear(); - place_ctx.movable_blocks_per_type.clear(); + const auto& block_locs = blk_loc_registry.block_locs(); + auto& movable_blocks = blk_loc_registry.mutable_movable_blocks(); + auto& movable_blocks_per_type = blk_loc_registry.mutable_movable_blocks_per_type(); + + movable_blocks.clear(); + movable_blocks_per_type.clear(); size_t n_logical_blocks = device_ctx.logical_block_types.size(); - place_ctx.movable_blocks_per_type.resize(n_logical_blocks); + movable_blocks_per_type.resize(n_logical_blocks); // iterate over all clustered blocks and store block ids of movable ones for (ClusterBlockId blk_id : cluster_ctx.clb_nlist.blocks()) { const auto& loc = block_locs[blk_id]; if (!loc.is_fixed) { - place_ctx.movable_blocks.push_back(blk_id); + movable_blocks.push_back(blk_id); const t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(blk_id); - place_ctx.movable_blocks_per_type[block_type->index].push_back(blk_id); + movable_blocks_per_type[block_type->index].push_back(blk_id); } } } @@ -1162,7 +1165,6 @@ void initial_placement(const t_placer_opts& placer_opts, std::optional& noc_cost_handler, vtr::RngContainer& rng) { vtr::ScopedStartFinishTimer timer("Initial Placement"); - auto& block_locs = blk_loc_registry.mutable_block_locs(); const auto& place_macros = blk_loc_registry.place_macros(); /* Initialize the grid blocks to empty. @@ -1204,8 +1206,8 @@ void initial_placement(const t_placer_opts& placer_opts, place_all_blocks(placer_opts, block_scores, placer_opts.pad_loc_type, constraints_file, blk_loc_registry, rng); } - alloc_and_load_movable_blocks(block_locs); + alloc_and_load_movable_blocks(blk_loc_registry); // ensure all blocks are placed and that NoC routing has no cycles - check_initial_placement_legality(block_locs); + check_initial_placement_legality(blk_loc_registry); } diff --git a/vpr/src/place/move_generators/move_generator.cpp b/vpr/src/place/move_generators/move_generator.cpp index fd22e8d8b34..a28039cc4a3 100644 --- a/vpr/src/place/move_generators/move_generator.cpp +++ b/vpr/src/place/move_generators/move_generator.cpp @@ -51,7 +51,7 @@ void MoveGenerator::calculate_reward_and_process_outcome(const MoveOutcomeStats& } } -void MoveTypeStat::print_placement_move_types_stats() const { +void MoveTypeStat::print_placement_move_types_stats(const std::vector>& movable_blocks_per_type) const { VTR_LOG("\n\nPlacement perturbation distribution by block and move type: \n"); VTR_LOG( @@ -71,9 +71,9 @@ void MoveTypeStat::print_placement_move_types_stats() const { int num_of_avail_moves = blk_type_moves.size() / device_ctx.logical_block_types.size(); //Print placement information for each block type - for (const auto& itype : device_ctx.logical_block_types) { + for (const t_logical_block_type& itype : device_ctx.logical_block_types) { //Skip non-existing block types in the netlist - if (itype.index == 0 || movable_blocks_per_type(itype).empty()) { + if (itype.index == 0 || movable_blocks_per_type[itype.index].empty()) { continue; } diff --git a/vpr/src/place/move_generators/move_generator.h b/vpr/src/place/move_generators/move_generator.h index 5ca0b4ce1f5..c059c2b7f62 100644 --- a/vpr/src/place/move_generators/move_generator.h +++ b/vpr/src/place/move_generators/move_generator.h @@ -1,5 +1,5 @@ -#ifndef VPR_MOVE_GENERATOR_H -#define VPR_MOVE_GENERATOR_H + +#pragma once #include "vpr_types.h" #include "move_utils.h" @@ -35,9 +35,13 @@ struct MoveTypeStat { vtr::NdMatrix rejected_moves; /** - * @brief Prints placement perturbation distribution by block and move type. + * @brief Prints statistics on the distribution of placement perturbations, + * categorized by block type and move type. + * @param movable_blocks_per_type A vector of vectors, where each inner vector contains ClusterBlockIds of + * all movable blocks belonging to a specific logical type. The outer vector + * is indexed by the logical type index. */ - void print_placement_move_types_stats() const; + void print_placement_move_types_stats(const std::vector>& movable_blocks_per_type) const; inline void incr_blk_type_moves(const t_propose_action& proposed_action) { if (proposed_action.logical_blk_type_index != -1) { //if the agent proposed the block type, then collect the block type stat @@ -124,7 +128,7 @@ class MoveGenerator { const PlacerCriticalities* criticalities) = 0; /** - * @brief Recieves feedback about the outcome of the previously proposed move + * @brief Receives feedback about the outcome of the previously proposed move * * This function is very useful for RL agent to get the feedback to the agent * @@ -151,5 +155,3 @@ class MoveGenerator { e_reward_function reward_func_; vtr::RngContainer& rng_; }; - -#endif diff --git a/vpr/src/place/move_generators/simpleRL_move_generator.cpp b/vpr/src/place/move_generators/simpleRL_move_generator.cpp index f0ab253c680..cfb1453731b 100644 --- a/vpr/src/place/move_generators/simpleRL_move_generator.cpp +++ b/vpr/src/place/move_generators/simpleRL_move_generator.cpp @@ -37,11 +37,14 @@ void SimpleRLMoveGenerator::process_outcome(double reward, e_reward_function rew * K-Armed bandit agent implementation * * * * */ -KArmedBanditAgent::KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng) +KArmedBanditAgent::KArmedBanditAgent(std::vector available_moves, + e_agent_space agent_space, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type) : available_moves_(std::move(available_moves)) , propose_blk_type_(agent_space == e_agent_space::MOVE_BLOCK_TYPE) , rng_(rng) { - std::vector available_logical_block_types = get_available_logical_blk_types_(); + std::vector available_logical_block_types = get_available_logical_blk_types_(num_movable_blocks_per_type); num_available_types_ = available_logical_block_types.size(); size_t num_available_moves = available_moves_.size(); @@ -89,7 +92,7 @@ int KArmedBanditAgent::action_to_blk_type_(const size_t action_idx) { } } -std::vector KArmedBanditAgent::get_available_logical_blk_types_() { +std::vector KArmedBanditAgent::get_available_logical_blk_types_(const std::vector& num_movable_blocks_per_type) { const auto& device_ctx = g_vpr_ctx.device(); std::vector available_blk_types; @@ -99,9 +102,9 @@ std::vector KArmedBanditAgent::get_available_logical_blk_types_() { continue; } - const auto& blk_per_type = movable_blocks_per_type(logical_blk_type); + int num_blk_per_type = num_movable_blocks_per_type[logical_blk_type.index]; - if (!blk_per_type.empty()) { + if (num_blk_per_type > 0) { available_blk_types.push_back(logical_blk_type.index); } } @@ -192,8 +195,12 @@ int KArmedBanditAgent::agent_to_phy_blk_type(const int idx) { * E-greedy agent implementation * * * * */ -EpsilonGreedyAgent::EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon, vtr::RngContainer& rng) - : KArmedBanditAgent(std::move(available_moves), agent_space, rng) { +EpsilonGreedyAgent::EpsilonGreedyAgent(std::vector available_moves, + e_agent_space agent_space, + float epsilon, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type) + : KArmedBanditAgent(std::move(available_moves), agent_space, rng, num_movable_blocks_per_type) { set_epsilon(epsilon); init_q_scores_(); } @@ -267,16 +274,19 @@ void EpsilonGreedyAgent::set_epsilon_action_prob() { * Softmax agent implementation * * * * */ -SoftmaxAgent::SoftmaxAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng) - : KArmedBanditAgent(std::move(available_moves), agent_space, rng) { - init_q_scores_(); +SoftmaxAgent::SoftmaxAgent(std::vector available_moves, + e_agent_space agent_space, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type) + : KArmedBanditAgent(std::move(available_moves), agent_space, rng, num_movable_blocks_per_type) { + init_q_scores_(num_movable_blocks_per_type); } SoftmaxAgent::~SoftmaxAgent() { if (agent_info_file_) vtr::fclose(agent_info_file_); } -void SoftmaxAgent::init_q_scores_() { +void SoftmaxAgent::init_q_scores_(const std::vector& num_movable_blocks_per_type) { q_ = std::vector(num_available_actions_, 0.); exp_q_ = std::vector(num_available_actions_, 0.); num_action_chosen_ = std::vector(num_available_actions_, 0); @@ -297,7 +307,7 @@ void SoftmaxAgent::init_q_scores_() { * it will use the block ratio to calculate action probability for each q_table entry. */ if (propose_blk_type_) { - set_block_ratio_(); + set_block_ratio_(num_movable_blocks_per_type); } set_action_prob_(); } @@ -320,11 +330,8 @@ t_propose_action SoftmaxAgent::propose_action() { return proposed_action; } -void SoftmaxAgent::set_block_ratio_() { - const auto& place_ctx = g_vpr_ctx.placement(); - size_t num_movable_total_blocks = place_ctx.movable_blocks.size(); - - num_movable_total_blocks = std::max(num_movable_total_blocks, 1); +void SoftmaxAgent::set_block_ratio_(const std::vector& num_movable_blocks_per_type) { + size_t num_movable_total_blocks = std::max(1, std::accumulate(num_movable_blocks_per_type.begin(), num_movable_blocks_per_type.end(), 0)); // allocate enough space for available block types in the netlist block_type_ratio_.resize(num_available_types_); @@ -336,7 +343,7 @@ void SoftmaxAgent::set_block_ratio_() { for (size_t itype = 0; itype < num_available_types_; itype++) { t_logical_block_type blk_type; blk_type.index = agent_to_phy_blk_type(itype); - auto num_blocks = movable_blocks_per_type(blk_type).size(); + int num_blocks = num_movable_blocks_per_type[blk_type.index]; block_type_ratio_[itype] = (float)num_blocks / num_movable_total_blocks; block_type_ratio_[itype] /= available_moves_.size(); } diff --git a/vpr/src/place/move_generators/simpleRL_move_generator.h b/vpr/src/place/move_generators/simpleRL_move_generator.h index eacf736e79b..75a9474b69a 100644 --- a/vpr/src/place/move_generators/simpleRL_move_generator.h +++ b/vpr/src/place/move_generators/simpleRL_move_generator.h @@ -14,7 +14,10 @@ */ class KArmedBanditAgent { public: - KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng); + KArmedBanditAgent(std::vector available_moves, + e_agent_space agent_space, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type); virtual ~KArmedBanditAgent() = default; /** @@ -103,11 +106,13 @@ class KArmedBanditAgent { private: /** * @brief Iterates over all logical block types and check whether they exist in the - * netlist. Then, returns the logical block type indices found in the netlist. - * + * netlist. Then, returns the logical block type indices found in the netlist. + * @param movable_blocks_per_type A vector of vectors, where each inner vector contains ClusterBlockIds of + * all movable blocks belonging to a specific logical type. The outer vector + * is indexed by the logical type index. * @return A vector containing all logical block type indices that exist in the netlist. */ - static std::vector get_available_logical_blk_types_(); + static std::vector get_available_logical_blk_types_(const std::vector& num_movable_blocks_per_type); private: std::vector action_logical_blk_type_; @@ -122,7 +127,11 @@ class KArmedBanditAgent { */ class EpsilonGreedyAgent : public KArmedBanditAgent { public: - EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon, vtr::RngContainer& rng); + EpsilonGreedyAgent(std::vector available_moves, + e_agent_space agent_space, + float epsilon, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type); ~EpsilonGreedyAgent() override; t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform @@ -161,7 +170,10 @@ class EpsilonGreedyAgent : public KArmedBanditAgent { */ class SoftmaxAgent : public KArmedBanditAgent { public: - SoftmaxAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng); + SoftmaxAgent(std::vector available_moves, + e_agent_space agent_space, + vtr::RngContainer& rng, + const std::vector& num_movable_blocks_per_type); ~SoftmaxAgent() override; t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform @@ -169,13 +181,19 @@ class SoftmaxAgent : public KArmedBanditAgent { private: /** * @brief Initialize agent's Q-table and internal variable to zero (RL-agent learns everything throughout the placement run and has no prior knowledge) + * @param movable_blocks_per_type A vector of vectors, where each inner vector contains ClusterBlockIds of + * all movable blocks belonging to a specific logical type. The outer vector + * is indexed by the logical type index. */ - void init_q_scores_(); + void init_q_scores_(const std::vector& num_movable_blocks_per_type); /** * @brief Calculate the fraction of total netlist blocks for each agent block type and will be used by the "set_action_prob" function. + * @param movable_blocks_per_type A vector of vectors, where each inner vector contains ClusterBlockIds of + * all movable blocks belonging to a specific logical type. The outer vector + * is indexed by the logical type index. */ - void set_block_ratio_(); + void set_block_ratio_(const std::vector& num_movable_blocks_per_type); /** * @brief Set action probability for all available actions. diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 893e19243d8..b8d0cb3c9e2 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -554,13 +554,15 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, const PlacerState& placer_state, vtr::RngContainer& rng) { const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& blk_loc_registry = placer_state.blk_loc_registry(); ClusterBlockId b_from = ClusterBlockId::INVALID(); + if (highly_crit_block) { b_from = pick_from_highly_critical_block(*net_from, *pin_from, logical_blk_type_index, placer_state, *placer_criticalities, rng); } else { - b_from = pick_from_block(logical_blk_type_index, rng); + b_from = pick_from_block(logical_blk_type_index, rng, blk_loc_registry); } //if a movable block found, set the block type @@ -575,21 +577,12 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, return b_from; } -const std::vector& movable_blocks_per_type(const t_logical_block_type& blk_type) { - const auto& place_ctx = g_vpr_ctx.placement(); - - // the vector is returned as const reference to avoid unnecessary copies, - // especially that returned vectors may be very large as they contain - // all clustered blocks with a specific block type - return place_ctx.movable_blocks_per_type[blk_type.index]; -} - -ClusterBlockId pick_from_block(const int logical_blk_type_index, vtr::RngContainer& rng) { - const auto& place_ctx = g_vpr_ctx.placement(); - +ClusterBlockId pick_from_block(const int logical_blk_type_index, + vtr::RngContainer& rng, + const BlkLocRegistry& blk_loc_registry) { // if logical block type is specified, pick the 'from' block from blocks of that type; // otherwise, select it randomly from all blocks - const auto& movable_blocks = (logical_blk_type_index < 0 )? place_ctx.movable_blocks : place_ctx.movable_blocks_per_type[logical_blk_type_index]; + const auto& movable_blocks = (logical_blk_type_index < 0 ) ? blk_loc_registry.movable_blocks() : blk_loc_registry.movable_blocks_per_type()[logical_blk_type_index]; if (movable_blocks.empty()) { return ClusterBlockId::INVALID(); diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index ba93014297a..de2ea685369 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -1,5 +1,5 @@ -#ifndef VPR_MOVE_UTILS_H -#define VPR_MOVE_UTILS_H + +#pragma once #include "vpr_types.h" #include "move_transactions.h" @@ -178,24 +178,19 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, const PlacerState& placer_state, vtr::RngContainer& rng); -/** - * Returns all movable clustered blocks with a specified logical block type. - * @param blk_type Specifies the logical block block type. - * @return A const reference to a vector containing all movable blocks with the specified logical block type. - */ -const std::vector& movable_blocks_per_type(const t_logical_block_type& blk_type); - - /** * @brief Find a block with a specific block type to be swapped with another block * * @param logical_blk_type_index The logical type of the moving block. If a negative value is passed, * the block is selected randomly from all movable blocks and not from a specific type. * @param rng A random number generator used to select a random block. + * @param blk_loc_registry Contains movable blocks and movable blocks per type. * * @return BlockId of the selected block, ClusterBlockId::INVALID() if no block with specified block type found */ -ClusterBlockId pick_from_block(int logical_blk_type_index, vtr::RngContainer& rng); +ClusterBlockId pick_from_block(int logical_blk_type_index, + vtr::RngContainer& rng, + const BlkLocRegistry& blk_loc_registry); /** * @brief Find a highly critical block with a specific block type to be swapped with another block. @@ -459,4 +454,3 @@ std::pair union_2d_bb_incr(const std::vector& num_edge_vec, void enable_placer_debug(const t_placer_opts& placer_opts, ClusterBlockId blk_id); -#endif diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index e2a8e902e31..7e4d36cf54c 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -277,11 +277,11 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { } } -double NetCostHandler::comp_bb_cost(e_cost_methods method) { +std::pair NetCostHandler::comp_bb_cost(e_cost_methods method) { return comp_bb_cost_functor_(method); } -double NetCostHandler::comp_cube_bb_cost_(e_cost_methods method) { +std::pair NetCostHandler::comp_cube_bb_cost_(e_cost_methods method) { const auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = placer_state_.mutable_move(); @@ -309,16 +309,10 @@ double NetCostHandler::comp_cube_bb_cost_(e_cost_methods method) { } } - if (method == e_cost_methods::CHECK) { - VTR_LOG("\n"); - VTR_LOG("BB estimate of min-dist (placement) wire length: %.0f\n", - expected_wirelength); - } - - return cost; + return {cost, expected_wirelength}; } -double NetCostHandler::comp_per_layer_bb_cost_(e_cost_methods method) { +std::pair NetCostHandler::comp_per_layer_bb_cost_(e_cost_methods method) { const auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = placer_state_.mutable_move(); @@ -346,13 +340,7 @@ double NetCostHandler::comp_per_layer_bb_cost_(e_cost_methods method) { } } - if (method == e_cost_methods::CHECK) { - VTR_LOG("\n"); - VTR_LOG("BB estimate of min-dist (placement) wire length: %.0f\n", - expected_wirelength); - } - - return cost; + return {cost, expected_wirelength}; } void NetCostHandler::update_net_bb_(const ClusterNetId net, diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 64ade78f6a1..8049cd42c64 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -59,9 +59,11 @@ class NetCostHandler { * non_updateable_bb routine, to provide a cost which can be * used to check the correctness of the other routine. * @param method The method used to calculate placement cost. - * @return The bounding box cost of the placement. + * @return (bounding box cost of the placement, estimated wirelength) + * + * @note The returned estimated wirelength is valid only when method == CHECK */ - double comp_bb_cost(e_cost_methods method); + std::pair comp_bb_cost(e_cost_methods method); /** * @brief Find all the nets and pins affected by this swap and update costs. @@ -130,7 +132,7 @@ class NetCostHandler { ///@brief Contains some parameter that determine how the placement cost is computed. const t_placer_opts& placer_opts_; ///@brief Points to the proper method for computing the bounding box cost from scratch. - std::function comp_bb_cost_functor_; + std::function(e_cost_methods method)> comp_bb_cost_functor_; ///@brief Points to the proper method for updating the bounding box of a net. std::function update_bb_functor_; ///@brief Points to the proper method for getting the bounding box cost of a net @@ -456,17 +458,21 @@ class NetCostHandler { * @brief Computes the bounding box from scratch using 2D bounding boxes (per-layer mode) * @param method The method used to calculate placement cost. Specifies whether the cost is * computed from scratch or incrementally. - * @return Computed bounding box cost. + * @return (bounding box cost of the placement, estimated wirelength) + * + * @note The returned estimated wirelength is valid only when method == CHECK */ - double comp_per_layer_bb_cost_(e_cost_methods method); + std::pair comp_per_layer_bb_cost_(e_cost_methods method); /** * @brief Computes the bounding box from scratch using 3D bounding boxes (cube mode) * @param method The method used to calculate placement cost. Specifies whether the cost is * computed from scratch or incrementally. - * @return Computed bounding box cost. + * @return (bounding box cost of the placement, estimated wirelength) + * + * @note The returned estimated wirelength is valid only when method == CHECK */ - double comp_cube_bb_cost_(e_cost_methods method); + std::pair comp_cube_bb_cost_(e_cost_methods method); /** * @brief if "net" is not already stored as an affected net, add it in ts_nets_to_update. diff --git a/vpr/src/place/placement_log_printer.cpp b/vpr/src/place/placement_log_printer.cpp index a4eafb3b30f..114b92ccc4f 100644 --- a/vpr/src/place/placement_log_printer.cpp +++ b/vpr/src/place/placement_log_printer.cpp @@ -279,7 +279,7 @@ void PlacementLogPrinter::print_post_placement_stats() const { print_resources_utilization(); print_placement_swaps_stats(); - move_type_stats.print_placement_move_types_stats(); + move_type_stats.print_placement_move_types_stats(placer_.placer_state_.blk_loc_registry().movable_blocks_per_type()); if (placer_.noc_opts_.noc) { write_noc_placement_file(placer_.noc_opts_.noc_placement_file_name, diff --git a/vpr/src/place/placement_log_printer.h b/vpr/src/place/placement_log_printer.h index d538c20d895..13063543bb0 100644 --- a/vpr/src/place/placement_log_printer.h +++ b/vpr/src/place/placement_log_printer.h @@ -61,6 +61,8 @@ class PlacementLogPrinter { void print_initial_placement_stats() const; /// Prints final placement metrics and generates timing reports. void print_post_placement_stats() const; + /// Returns a bool to indicate whether the instance is in quiet mode. + bool quiet() const { return quiet_; } private: /** diff --git a/vpr/src/place/placer.cpp b/vpr/src/place/placer.cpp index 37b48f11d0d..98001469c99 100644 --- a/vpr/src/place/placer.cpp +++ b/vpr/src/place/placer.cpp @@ -105,7 +105,7 @@ Placer::Placer(const Netlist<>& net_list, } // Gets initial cost and loads bounding boxes. - costs_.bb_cost = net_cost_handler_.comp_bb_cost(e_cost_methods::NORMAL); + costs_.bb_cost = net_cost_handler_.comp_bb_cost(e_cost_methods::NORMAL).first; costs_.bb_cost_norm = 1 / costs_.bb_cost; if (placer_opts.place_algorithm.is_timing_driven()) { @@ -229,8 +229,8 @@ void Placer::check_place_() { } if (error == 0) { - VTR_LOG("\n"); - VTR_LOG("Completed placement consistency check successfully.\n"); + VTR_LOGV(!log_printer_.quiet(), + "\nCompleted placement consistency check successfully.\n"); } else { VPR_ERROR(VPR_ERROR_PLACE, @@ -244,7 +244,10 @@ int Placer::check_placement_costs_() { int error = 0; double timing_cost_check; - double bb_cost_check = net_cost_handler_.comp_bb_cost(e_cost_methods::CHECK); + const auto [bb_cost_check, expected_wirelength] = net_cost_handler_.comp_bb_cost(e_cost_methods::CHECK); + VTR_LOGV(!log_printer_.quiet(), + "\nBB estimate of min-dist (placement) wire length: %.0f\n", expected_wirelength); + if (fabs(bb_cost_check - costs_.bb_cost) > costs_.bb_cost * PL_INCREMENTAL_COST_TOLERANCE) { VTR_LOG_ERROR( @@ -255,7 +258,6 @@ int Placer::check_placement_costs_() { if (placer_opts_.place_algorithm.is_timing_driven()) { comp_td_costs(place_delay_model_.get(), *placer_criticalities_, placer_state_, &timing_cost_check); - //VTR_LOG("timing_cost recomputed from scratch: %g\n", timing_cost_check); if (fabs(timing_cost_check - costs_.timing_cost) > costs_.timing_cost * PL_INCREMENTAL_COST_TOLERANCE) { VTR_LOG_ERROR( "timing_cost_check: %g and timing_cost: %g differ in check_place.\n", @@ -343,8 +345,8 @@ void Placer::place() { critical_path_ = timing_info_->least_slack_critical_path(); - VTR_LOG("post-quench CPD = %g (ns) \n", - 1e9 * critical_path_.delay()); + VTR_LOGV(!log_printer_.quiet(), + "post-quench CPD = %g (ns) \n", 1e9 * critical_path_.delay()); } // See if our latest checkpoint is better than the current placement solution @@ -358,7 +360,7 @@ void Placer::place() { if (placer_opts_.placement_saves_per_temperature >= 1) { std::string filename = vtr::string_fmt("placement_%03d_%03d.place", annealing_state.num_temps + 1, 0); - VTR_LOG("Saving final placement to file: %s\n", filename.c_str()); + VTR_LOGV(!log_printer_.quiet(), "Saving final placement to file: %s\n", filename.c_str()); print_place(nullptr, nullptr, filename.c_str(), placer_state_.mutable_block_locs()); }