diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index 2cf2bf3f1f3..8532d063133 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -220,7 +220,7 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts) { // Generate and evaluate router moves for (int i_move = 0; i_move < N_MOVES; i_move++) { e_create_move create_move_outcome = e_create_move::ABORT; - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); // Shrink the range limit over time float r_lim_decayed = 1.0f + (N_MOVES - i_move) * (max_r_lim / N_MOVES); create_move_outcome = propose_router_swap(blocks_affected, r_lim_decayed); diff --git a/vpr/src/place/move_transactions.cpp b/vpr/src/place/move_transactions.cpp index f36dd4d5e39..db06d34e608 100644 --- a/vpr/src/place/move_transactions.cpp +++ b/vpr/src/place/move_transactions.cpp @@ -1,12 +1,24 @@ +#include "move_transactions.h" #include "move_utils.h" #include "globals.h" #include "place_util.h" +#include "vtr_assert.h" + +t_pl_blocks_to_be_moved::t_pl_blocks_to_be_moved(size_t max_blocks){ + moved_blocks.reserve(max_blocks); +} + +size_t t_pl_blocks_to_be_moved::get_size_and_increment() { + VTR_ASSERT_SAFE(moved_blocks.size() < moved_blocks.capacity()); + moved_blocks.resize(moved_blocks.size() + 1); + return moved_blocks.size() - 1; +} //Records that block 'blk' should be moved to the specified 'to' location -e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId blk, t_pl_loc to) { - auto res = blocks_affected.moved_to.emplace(to); - if (!res.second) { +e_block_move_result t_pl_blocks_to_be_moved::record_block_move(ClusterBlockId blk, t_pl_loc to) { + auto [to_it, to_success] = moved_to.emplace(to); + if (!to_success) { log_move_abort("duplicate block move to location"); return e_block_move_result::ABORT; } @@ -15,8 +27,9 @@ e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, t_pl_loc from = place_ctx.block_locs[blk].loc; - auto res2 = blocks_affected.moved_from.emplace(from); - if (!res2.second) { + auto [_, from_success] = moved_from.emplace(from); + if (!from_success) { + moved_to.erase(to_it); log_move_abort("duplicate block move from location"); return e_block_move_result::ABORT; } @@ -24,15 +37,35 @@ e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, VTR_ASSERT_SAFE(to.sub_tile < int(place_ctx.grid_blocks.num_blocks_at_location({to.x, to.y, to.layer}))); // Sets up the blocks moved - int imoved_blk = blocks_affected.num_moved_blocks; - blocks_affected.moved_blocks[imoved_blk].block_num = blk; - blocks_affected.moved_blocks[imoved_blk].old_loc = from; - blocks_affected.moved_blocks[imoved_blk].new_loc = to; - blocks_affected.num_moved_blocks++; + size_t imoved_blk = get_size_and_increment(); + moved_blocks[imoved_blk].block_num = blk; + moved_blocks[imoved_blk].old_loc = from; + moved_blocks[imoved_blk].new_loc = to; return e_block_move_result::VALID; } +//Examines the currently proposed move and determine any empty locations +std::set t_pl_blocks_to_be_moved::t_pl_blocks_to_be_moved::determine_locations_emptied_by_move() { + std::set moved_from_set; + std::set moved_to_set; + + for (const t_pl_moved_block& moved_block : moved_blocks) { + //When a block is moved its old location becomes free + moved_from_set.emplace(moved_block.old_loc); + + //But any block later moved to a position fills it + moved_to_set.emplace(moved_block.new_loc); + } + + std::set empty_locs; + std::set_difference(moved_from_set.begin(), moved_from_set.end(), + moved_to_set.begin(), moved_to_set.end(), + std::inserter(empty_locs, empty_locs.begin())); + + return empty_locs; +} + //Moves the blocks in blocks_affected to their new locations void apply_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) { auto& place_ctx = g_vpr_ctx.mutable_placement(); @@ -40,11 +73,11 @@ void apply_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) { //Swap the blocks, but don't swap the nets or update place_ctx.grid_blocks //yet since we don't know whether the swap will be accepted - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + for (const t_pl_moved_block& moved_block : blocks_affected.moved_blocks) { + ClusterBlockId blk = moved_block.block_num; - const t_pl_loc& old_loc = blocks_affected.moved_blocks[iblk].old_loc; - const t_pl_loc& new_loc = blocks_affected.moved_blocks[iblk].new_loc; + const t_pl_loc& old_loc = moved_block.old_loc; + const t_pl_loc& new_loc = moved_block.new_loc; // move the block to its new location place_ctx.block_locs[blk].loc = new_loc; @@ -67,11 +100,11 @@ void commit_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) { auto& place_ctx = g_vpr_ctx.mutable_placement(); /* Swap physical location */ - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + for (const t_pl_moved_block& moved_block : blocks_affected.moved_blocks) { + ClusterBlockId blk = moved_block.block_num; - const t_pl_loc& to = blocks_affected.moved_blocks[iblk].new_loc; - const t_pl_loc& from = blocks_affected.moved_blocks[iblk].old_loc; + const t_pl_loc& to = moved_block.new_loc; + const t_pl_loc& from = moved_block.old_loc; //Remove from old location only if it hasn't already been updated by a previous block update if (place_ctx.grid_blocks.block_at_location(from) == blk) { @@ -97,11 +130,11 @@ void revert_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) { auto& device_ctx = g_vpr_ctx.device(); // Swap the blocks back, nets not yet swapped they don't need to be changed - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + for (const t_pl_moved_block& moved_block : blocks_affected.moved_blocks) { + ClusterBlockId blk = moved_block.block_num; - const t_pl_loc& old_loc = blocks_affected.moved_blocks[iblk].old_loc; - const t_pl_loc& new_loc = blocks_affected.moved_blocks[iblk].new_loc; + const t_pl_loc& old_loc = moved_block.old_loc; + const t_pl_loc& new_loc = moved_block.new_loc; // return the block to where it was before the swap place_ctx.block_locs[blk].loc = old_loc; @@ -121,15 +154,15 @@ void revert_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected) { } //Clears the current move so a new move can be proposed -void clear_move_blocks(t_pl_blocks_to_be_moved& blocks_affected) { +void t_pl_blocks_to_be_moved::clear_move_blocks() { //Reset moved flags - blocks_affected.moved_to.clear(); - blocks_affected.moved_from.clear(); + moved_to.clear(); + moved_from.clear(); - //For run-time, we just reset num_moved_blocks to zero, but do not free the blocks_affected + //For run-time, we just reset size of blocks_affected.moved_blocks to zero, but do not free the blocks_affected //array to avoid memory allocation - blocks_affected.num_moved_blocks = 0; + moved_blocks.resize(0); - blocks_affected.affected_pins.clear(); + affected_pins.clear(); } diff --git a/vpr/src/place/move_transactions.h b/vpr/src/place/move_transactions.h index 27dd2b1b3c6..65e4c89774b 100644 --- a/vpr/src/place/move_transactions.h +++ b/vpr/src/place/move_transactions.h @@ -3,6 +3,13 @@ #include "vpr_types.h" #include "clustered_netlist_utils.h" +enum class e_block_move_result { + VALID, //Move successful + ABORT, //Unable to perform move + INVERT, //Try move again but with from/to inverted + INVERT_VALID //Completed inverted move +}; + /* Stores the information of the move for a block that is * * moved during placement * * block_num: the index of the moved block * @@ -25,8 +32,6 @@ struct t_pl_moved_block { * placement, in the form of array of structs instead of struct with * * arrays for cache effifiency * * - * num_moved_blocks: total number of blocks moved when * - * swapping two blocks. * * moved blocks: a list of moved blocks data structure with * * information on the move. * * [0...max_blocks-1] * @@ -34,10 +39,26 @@ struct t_pl_moved_block { * incrementally invalidate parts of the timing * * graph. */ struct t_pl_blocks_to_be_moved { - explicit t_pl_blocks_to_be_moved(size_t max_blocks) - : moved_blocks(max_blocks) {} + explicit t_pl_blocks_to_be_moved(size_t max_blocks); + t_pl_blocks_to_be_moved() = delete; + t_pl_blocks_to_be_moved(const t_pl_blocks_to_be_moved&) = delete; + t_pl_blocks_to_be_moved(t_pl_blocks_to_be_moved&&) = delete; + +/** + * @brief This function increments the size of the moved_blocks vector and return the index + * of the newly added last elements. + */ + size_t get_size_and_increment(); + +/** + * @brief This function clears all data structures of this struct. + */ + void clear_move_blocks(); + + e_block_move_result record_block_move(ClusterBlockId blk, t_pl_loc to); + + std::set determine_locations_emptied_by_move(); - int num_moved_blocks = 0; std::vector moved_blocks; std::unordered_set moved_from; std::unordered_set moved_to; @@ -45,14 +66,6 @@ struct t_pl_blocks_to_be_moved { std::vector affected_pins; }; -enum class e_block_move_result { - VALID, //Move successful - ABORT, //Unable to perform move - INVERT, //Try move again but with from/to inverted - INVERT_VALID //Completed inverted move -}; - -e_block_move_result record_block_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId blk, t_pl_loc to); void apply_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected); @@ -60,6 +73,4 @@ void commit_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected); void revert_move_blocks(const t_pl_blocks_to_be_moved& blocks_affected); -void clear_move_blocks(t_pl_blocks_to_be_moved& blocks_affected); - #endif diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 8c6ae2a6249..02e20f24fd0 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -1,5 +1,6 @@ #include "move_utils.h" +#include "move_transactions.h" #include "place_util.h" #include "globals.h" @@ -141,7 +142,7 @@ e_block_move_result record_single_block_swap(t_pl_blocks_to_be_moved& blocks_aff // Check whether the to_location is empty if (b_to == EMPTY_BLOCK_ID) { // Sets up the blocks moved - outcome = record_block_move(blocks_affected, b_from, to); + outcome = blocks_affected.record_block_move(b_from, to); } else if (b_to != INVALID_BLOCK_ID) { // Check whether block to is compatible with from location @@ -152,14 +153,14 @@ e_block_move_result record_single_block_swap(t_pl_blocks_to_be_moved& blocks_aff } // Sets up the blocks moved - outcome = record_block_move(blocks_affected, b_from, to); + outcome = blocks_affected.record_block_move(b_from, to); if (outcome != e_block_move_result::VALID) { return outcome; } t_pl_loc from = place_ctx.block_locs[b_from].loc; - outcome = record_block_move(blocks_affected, b_to, from); + outcome = blocks_affected.record_block_move(b_to, from); } // Finish swapping the blocks and setting up blocks_affected @@ -341,7 +342,7 @@ e_block_move_result record_macro_move(t_pl_blocks_to_be_moved& blocks_affected, ClusterBlockId blk_to = place_ctx.grid_blocks.block_at_location(to); - record_block_move(blocks_affected, member.blk_index, to); + blocks_affected.record_block_move(member.blk_index, to); int imacro_to = -1; get_imacro_from_iblk(&imacro_to, blk_to, place_ctx.pl_macros); @@ -392,7 +393,7 @@ e_block_move_result record_macro_self_swaps(t_pl_blocks_to_be_moved& blocks_affe auto& place_ctx = g_vpr_ctx.placement(); //Reset any partial move - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); //Collect the macros affected std::vector affected_macros; @@ -431,14 +432,14 @@ e_block_move_result record_macro_self_swaps(t_pl_blocks_to_be_moved& blocks_affe std::copy_if(displaced_blocks.begin(), displaced_blocks.end(), std::back_inserter(non_macro_displaced_blocks), is_non_macro_block); //Based on the currently queued block moves, find the empty 'holes' left behind - auto empty_locs = determine_locations_emptied_by_move(blocks_affected); + auto empty_locs = blocks_affected.determine_locations_emptied_by_move(); VTR_ASSERT_SAFE(empty_locs.size() >= non_macro_displaced_blocks.size()); //Fit the displaced blocks into the empty locations auto loc_itr = empty_locs.begin(); for (auto blk : non_macro_displaced_blocks) { - outcome = record_block_move(blocks_affected, blk, *loc_itr); + outcome = blocks_affected.record_block_move(blk, *loc_itr); ++loc_itr; } @@ -483,27 +484,6 @@ bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to) { return true; } -//Examines the currently proposed move and determine any empty locations -std::set determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& blocks_affected) { - std::set moved_from; - std::set moved_to; - - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - //When a block is moved its old location becomes free - moved_from.emplace(blocks_affected.moved_blocks[iblk].old_loc); - - //But any block later moved to a position fills it - moved_to.emplace(blocks_affected.moved_blocks[iblk].new_loc); - } - - std::set empty_locs; - std::set_difference(moved_from.begin(), moved_from.end(), - moved_to.begin(), moved_to.end(), - std::inserter(empty_locs, empty_locs.begin())); - - return empty_locs; -} - #ifdef VTR_ENABLE_DEBUG_LOGGING void enable_placer_debug(const t_placer_opts& placer_opts, ClusterBlockId blk_id) { diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index ce599492358..3bb70438eae 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -125,8 +125,6 @@ e_block_move_result record_macro_self_swaps(t_pl_blocks_to_be_moved& blocks_affe */ bool is_legal_swap_to_location(ClusterBlockId blk, t_pl_loc to); -std::set determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& blocks_affected); - /** * @brief Propose block for the RL agent based on required block type. * diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index ad0f643ceb4..53aed32dea1 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1,30 +1,32 @@ /** * @file net_cost_handler.cpp * @brief This file contains the implementation of functions used to update placement cost when a new move is proposed/committed. - * - * VPR placement cost consists of three terms which represent wirelength, timing, and NoC cost. - * - * To get an estimation of the wirelength of each net, the Half Perimeter Wire Length (HPWL) approach is used. In this approach, - * half of the perimeter of the bounding box which contains all terminals of the net is multiplied by a correction factor, - * and the resulting number is considered as an estimation of the bounding box. - * - * Currently, we have two types of bounding boxes: 3D bounding box (or Cube BB) and per-layer bounding box. - * If the FPGA grid is a 2D structure, a Cube bounding box is used, which will always have the z direction equal to 1. For 3D architectures, - * the user can specify the type of bounding box. If no type is specified, the RR graph is analyzed. If all inter-die connections happen from OPINs, - * the Cube bounding box is chosen; otherwise, the per-layer bounding box is chosen. In the Cube bounding box, when a net is stretched across multiple layers, - * the edges of the bounding box are determined by all of the blocks on all layers. - * When the per-layer bounding box is used, a separate bounding box for each layer is created, and the wirelength estimation for each layer is calculated. - * To get the total wirelength of a net, the wirelength estimation on all layers is summed up. For more details, please refer to Amin Mohaghegh's MASc thesis. - * - * For timing estimation, the placement delay model is used. For 2D architectures, you can think of the placement delay model as a 2D array indexed by dx and dy. - * To get a delay estimation of a connection (from a source to a sink), first, dx and dy between these two points should be calculated, - * and these two numbers are the indices to access this 2D array. By default, the placement delay model is created by iterating over the router lookahead + * + * VPR placement cost consists of three terms which represent wirelength, timing, and NoC cost. + * + * To get an estimation of the wirelength of each net, the Half Perimeter Wire Length (HPWL) approach is used. In this approach, + * half of the perimeter of the bounding box which contains all terminals of the net is multiplied by a correction factor, + * and the resulting number is considered as an estimation of the bounding box. + * + * Currently, we have two types of bounding boxes: 3D bounding box (or Cube BB) and per-layer bounding box. + * If the FPGA grid is a 2D structure, a Cube bounding box is used, which will always have the z direction equal to 1. For 3D architectures, + * the user can specify the type of bounding box. If no type is specified, the RR graph is analyzed. If all inter-die connections happen from OPINs, + * the Cube bounding box is chosen; otherwise, the per-layer bounding box is chosen. In the Cube bounding box, when a net is stretched across multiple layers, + * the edges of the bounding box are determined by all of the blocks on all layers. + * When the per-layer bounding box is used, a separate bounding box for each layer is created, and the wirelength estimation for each layer is calculated. + * To get the total wirelength of a net, the wirelength estimation on all layers is summed up. For more details, please refer to Amin Mohaghegh's MASc thesis. + * + * For timing estimation, the placement delay model is used. For 2D architectures, you can think of the placement delay model as a 2D array indexed by dx and dy. + * To get a delay estimation of a connection (from a source to a sink), first, dx and dy between these two points should be calculated, + * and these two numbers are the indices to access this 2D array. By default, the placement delay model is created by iterating over the router lookahead * to get the minimum cost for each dx and dy. - * + * * @date July 12, 2024 */ #include "net_cost_handler.h" +#include "clustered_netlist_fwd.h" #include "globals.h" +#include "physical_types.h" #include "placer_globals.h" #include "move_utils.h" #include "place_timing_update.h" @@ -35,8 +37,8 @@ using std::max; using std::min; /** - * @brief for the states of the bounding box. - * Stored as char for memory efficiency. + * @brief for the states of the bounding box. + * Stored as char for memory efficiency. */ enum class NetUpdateState { NOT_UPDATED_YET, @@ -44,83 +46,114 @@ enum class NetUpdateState { GOT_FROM_SCRATCH }; -/** - * @brief The error tolerance due to round off for the total cost computation. - * When we check it from scratch vs. incrementally. 0.01 means that there is a 1% error tolerance. +/** + * @brief The error tolerance due to round off for the total cost computation. + * When we check it from scratch vs. incrementally. 0.01 means that there is a 1% error tolerance. */ #define ERROR_TOL .01 const int MAX_FANOUT_CROSSING_COUNT = 50; -/** - * @brief Crossing counts for nets with different #'s of pins. From - * ICCAD 94 pp. 690 - 695 (with linear interpolation applied by me). - * Multiplied to bounding box of a net to better estimate wire length - * for higher fanout nets. Each entry is the correction factor for the +/** + * @brief Crossing counts for nets with different #'s of pins. From + * ICCAD 94 pp. 690 - 695 (with linear interpolation applied by me). + * Multiplied to bounding box of a net to better estimate wire length + * for higher fanout nets. Each entry is the correction factor for the * fanout index-1 */ static const float cross_count[MAX_FANOUT_CROSSING_COUNT] = {/* [0..49] */ 1.0, 1.0, 1.0, 1.0828, - 1.1536, 1.2206, 1.2823, 1.3385, 1.3991, 1.4493, 1.4974, 1.5455, 1.5937, - 1.6418, 1.6899, 1.7304, 1.7709, 1.8114, 1.8519, 1.8924, 1.9288, 1.9652, - 2.0015, 2.0379, 2.0743, 2.1061, 2.1379, 2.1698, 2.2016, 2.2334, 2.2646, - 2.2958, 2.3271, 2.3583, 2.3895, 2.4187, 2.4479, 2.4772, 2.5064, 2.5356, - 2.5610, 2.5864, 2.6117, 2.6371, 2.6625, 2.6887, 2.7148, 2.7410, 2.7671, - 2.7933}; - -/** - * @brief Matrices below are used to precompute the inverse of the average - * number of tracks per channel between [subhigh] and [sublow]. Access - * them as chan?_place_cost_fac[subhigh][sublow]. They are used to - * speed up the computation of the cost function that takes the length - * of the net bounding box in each dimension, divided by the average - * number of tracks in that direction; for other cost functions they - * will never be used. + 1.1536, 1.2206, 1.2823, 1.3385, 1.3991, 1.4493, 1.4974, 1.5455, 1.5937, + 1.6418, 1.6899, 1.7304, 1.7709, 1.8114, 1.8519, 1.8924, 1.9288, 1.9652, + 2.0015, 2.0379, 2.0743, 2.1061, 2.1379, 2.1698, 2.2016, 2.2334, 2.2646, + 2.2958, 2.3271, 2.3583, 2.3895, 2.4187, 2.4479, 2.4772, 2.5064, 2.5356, + 2.5610, 2.5864, 2.6117, 2.6371, 2.6625, 2.6887, 2.7148, 2.7410, 2.7671, + 2.7933}; + +/** + * @brief Matrices below are used to precompute the inverse of the average + * number of tracks per channel between [subhigh] and [sublow]. Access + * them as chan?_place_cost_fac[subhigh][sublow]. They are used to + * speed up the computation of the cost function that takes the length + * of the net bounding box in each dimension, divided by the average + * number of tracks in that direction; for other cost functions they + * will never be used. */ static vtr::NdMatrix chanx_place_cost_fac({0, 0}); // [0...device_ctx.grid.width()-2] static vtr::NdMatrix chany_place_cost_fac({0, 0}); // [0...device_ctx.grid.height()-2] +namespace { /** - * @brief Cost of a net, and a temporary cost of a net used during move assessment. - * We also use negative cost values in proposed_net_cost as a flag to indicate that + * @brief For each of the vectors in this struct, there is one entry per cluster level net: + * [0...cluster_ctx.clb_nlist.nets().size()-1]. + * net_cost and proposed_net_cost: Cost of a net, and a temporary cost of a net used during move assessment. + * We also use negative cost values in proposed_net_cost as a flag to indicate that * the cost of a net has not yet been updated. - */ -static vtr::vector net_cost, proposed_net_cost; - -/** * - * @brief Flag array to indicate whether the specific bounding box has been updated - * in this particular swap or not. If it has been updated before, the code - * must use the updated data, instead of the out-of-date data passed into the - * subroutine, particularly used in try_swap(). The value NOT_UPDATED_YET - * indicates that the net has not been updated before, UPDATED_ONCE indicated + * bb_update_status: Flag array to indicate whether the specific bounding box has been updated + * in this particular swap or not. If it has been updated before, the code + * must use the updated data, instead of the out-of-date data passed into the + * subroutine, particularly used in try_swap(). The value NOT_UPDATED_YET + * indicates that the net has not been updated before, UPDATED_ONCE indicated * that the net has been updated once, if it is going to be updated again, the - * values from the previous update must be used. GOT_FROM_SCRATCH is only - * applicable for nets larger than SMALL_NETS and it indicates that the + * values from the previous update must be used. GOT_FROM_SCRATCH is only + * applicable for nets larger than SMALL_NETS and it indicates that the * particular bounding box is not incrementally updated, and hence the * bounding box is got from scratch, so the bounding box would definitely be - * right, DO NOT update again. + * right, DO NOT update again. */ -static vtr::vector bb_updated_before; // [0...cluster_ctx.clb_nlist.nets().size()-1] +struct PLNetCost { + vtr::vector net_cost; + vtr::vector proposed_net_cost; + vtr::vector bb_update_status; +}; /* The following arrays are used by the try_swap function for speed. */ /** - * The wire length estimation is based on the bounding box of the net. In the case of the 2D architecture, + * @brief The wire length estimation is based on the bounding box of the net. In the case of the 2D architecture, * we use a 3D BB with the z-dimension (layer) set to 1. In the case of 3D architecture, there 2 types of bounding box: * 3D and per-layer. The type is determined at the beginning of the placement and stored in the placement context. - * - * * If the bonding box is of the type 3D, ts_bb_coord_new and ts_bb_edge_new are used. Otherwise, layer_ts_bb_edge_new and * layer_ts_bb_coord_new are used. */ -/* [0...cluster_ctx.clb_nlist.nets().size()-1] -> 3D bounding box*/ -static vtr::vector ts_bb_coord_new, ts_bb_edge_new; -/* [0...cluster_ctx.clb_nlist.nets().size()-1][0...num_layers-1] -> 2D bonding box on a layer*/ -static vtr::vector> layer_ts_bb_edge_new, layer_ts_bb_coord_new; -/* [0...cluster_ctx.clb_nlist.nets().size()-1][0...num_layers-1] -> number of sink pins on a layer*/ -static vtr::Matrix ts_layer_sink_pin_count; -/* [0...num_afftected_nets] -> net_id of the affected nets */ -static std::vector ts_nets_to_update; +struct TSInfo { + /* [0...cluster_ctx.clb_nlist.nets().size()-1] -> 3D bounding box*/ + vtr::vector ts_bb_coord_new, ts_bb_edge_new; + /* [0...cluster_ctx.clb_nlist.nets().size()-1][0...num_layers-1] -> 2D bonding box on a layer*/ + vtr::vector> layer_ts_bb_edge_new, layer_ts_bb_coord_new; + /* [0...cluster_ctx.clb_nlist.nets().size()-1][0...num_layers-1] -> number of sink pins on a layer*/ + vtr::Matrix ts_layer_sink_pin_count; + /* [0...num_afftected_nets] -> net_id of the affected nets */ + std::vector ts_nets_to_update; + // TSInfo(const TSInfo&) = delete; + // TSInfo(TSInfo&&) = delete; +}; + +/** + * @brief This class is used to hide control flows needed to distinguish 2d and 3d placement + */ +class BBUpdater { + // BBUpdater(const BBUpdater&) = delete; + // BBUpdater(BBUpdater&&) = delete; + + private: + bool m_cube_bb = false; + + public: + void init(size_t num_nets, bool cube_bb); + void get_non_updatable_bb(const ClusterNetId& net); + void update_bb(ClusterNetId net_id, t_physical_tile_loc pin_old_loc, t_physical_tile_loc pin_new_loc, bool is_driver); + double get_net_cost(const ClusterNetId net_id); + void set_ts_bb_coord(const ClusterNetId net_id); + void set_ts_edge(const ClusterNetId net_id); +}; +} // namespace + +static struct PLNetCost pl_net_cost; + +static struct TSInfo ts_info; + +static BBUpdater bb_updater; /** * @param net @@ -128,11 +161,10 @@ static std::vector ts_nets_to_update; * @return True if the driver block of the net is among the moving blocks */ static bool driven_by_moved_block(const ClusterNetId net, - const int num_blocks, const std::vector& moved_blocks); /** * @brief Update the bounding box (3D) of the net connected to blk_pin. The old and new locations of the pin are - * stored in pl_moved_block. The updated bounding box will be stored in ts data structures. Do not update the net + * stored in pl_moved_block. The updated bounding box will be stored in ts data structures. Do not update the net * cost here since it should only be updated once per net, not once per pin. * @param net * @param blk @@ -146,7 +178,7 @@ static void update_net_bb(const ClusterNetId& net, /** * @brief Calculate the new connection delay and timing cost of all the - * sink pins affected by moving a specific pin to a new location. Also + * sink pins affected by moving a specific pin to a new location. Also * calculates the total change in the timing cost. * @param delay_model * @param criticalities @@ -165,11 +197,10 @@ static void update_td_delta_costs(const PlaceDelayModel* delay_model, bool is_src_moving); /** - * @brief if "net" is not already stored as an affected net, mark it in ts_nets_to_update and increment num_affected_nets + * @brief if "net" is not already stored as an affected net, add it in ts_nets_to_update. * @param net ID of a net affected by a move - * @param num_affected_nets Incremented if this is a new net affected, and returned via reference. */ -static void record_affected_net(const ClusterNetId net, int& num_affected_nets); +static void record_affected_net(const ClusterNetId net); /** * @brief Call suitable function based on the bounding box type to update the bounding box of the net connected to pin_id. Also, @@ -182,29 +213,27 @@ static void record_affected_net(const ClusterNetId net, int& num_affected_nets); * @param moving_blk_inf Data structure that holds information, e.g., old location and new locatoin, about all moving blocks * @param affected_pins Netlist pins which are affected, in terms placement cost, by the proposed move. * @param timing_delta_c Timing cost change based on the proposed move - * @param num_affected_nets A pointer to the first free element of ts_nets_to_update. If a new net is added, the pointer should be increamented. * @param is_src_moving Is the moving pin the source of a net. */ static void update_net_info_on_pin_move(const t_place_algorithm& place_algorithm, - const PlaceDelayModel* delay_model, - const PlacerCriticalities* criticalities, - const ClusterBlockId& blk_id, - const ClusterPinId& pin_id, - const t_pl_moved_block& moving_blk_inf, - std::vector& affected_pins, - double& timing_delta_c, - int& num_affected_nets, - bool is_src_moving); - + const PlaceDelayModel* delay_model, + const PlacerCriticalities* criticalities, + const ClusterBlockId blk_id, + const ClusterPinId pin_id, + const t_pl_moved_block& moving_blk_inf, + std::vector& affected_pins, + double& timing_delta_c, + bool is_src_moving); + /** * @brief Update the 3D bounding box of "net_id" incrementally based on the old and new locations of a pin on that net - * @details Updates the bounding box of a net by storing its coordinates in the bb_coord_new data structure and the - * number of blocks on each edge in the bb_edge_new data structure. This routine should only be called for large nets, - * since it has some overhead relative to just doing a brute force bounding box calculation. The bounding box coordinate - * and edge information for inet must be valid before this routine is called. Currently assumes channels on both sides of - * the CLBs forming the edges of the bounding box can be used. Essentially, I am assuming the pins always lie on the - * outside of the bounding box. The x and y coordinates are the pin's x and y coordinates. IO blocks are considered to be one - * cell in for simplicity. + * @details Updates the bounding box of a net by storing its coordinates in the bb_coord_new data structure and the + * number of blocks on each edge in the bb_edge_new data structure. This routine should only be called for large nets, + * since it has some overhead relative to just doing a brute force bounding box calculation. The bounding box coordinate + * and edge information for inet must be valid before this routine is called. Currently assumes channels on both sides of + * the CLBs forming the edges of the bounding box can be used. Essentially, I am assuming the pins always lie on the + * outside of the bounding box. The x and y coordinates are the pin's x and y coordinates. IO blocks are considered to be one + * cell in for simplicity. * @param bb_edge_new Number of blocks on the edges of the bounding box * @param bb_coord_new Coordinates of the bounding box * @param num_sink_pin_layer_new Number of sinks of the given net on each layer @@ -228,28 +257,8 @@ static void update_bb(ClusterNetId net_id, * @param num_sink_pin_layer Store the number of sink pins of "net_id" on each layer */ static void get_non_updatable_bb(ClusterNetId net_id, - t_bb& bb_coord_new, - vtr::NdMatrixProxy num_sink_pin_layer); - - -/** - * @brief Update the bounding box (per-layer) of the net connected to blk_pin. The old and new locations of the pin are - * stored in pl_moved_block. The updated bounding box will be stored in ts data structures. - * @details Finds the bounding box of a net and stores its coordinates in the bb_coord_new - * data structure. This routine should only be called for small nets, since it does not - * determine enough information for the bounding box to be updated incrementally later. - * Currently assumes channels on both sides of the CLBs forming the edges of the bounding box - * can be used. Essentially, I am assuming the pins always lie on the outside of the - * bounding box. - * @param net ID of the net for which the bounding box is requested - * @param blk ID of the moving block - * @param blk_pin ID of the pin connected to the net - * @param pl_moved_block Placement info about - */ -static void update_net_layer_bb(const ClusterNetId& net, - const ClusterBlockId& blk, - const ClusterPinId& blk_pin, - const t_pl_moved_block& pl_moved_block); + t_bb& bb_coord_new, + vtr::NdMatrixProxy num_sink_pin_layer); /** * @brief Calculate the per-layer bounding box of "net_id" from scratch (based on the block locations stored in place_ctx) and @@ -262,15 +271,14 @@ static void get_non_updatable_layer_bb(ClusterNetId net_id, std::vector& bb_coord_new, vtr::NdMatrixProxy num_sink_layer); - /** * @brief Update the per-layer bounding box of "net_id" incrementally based on the old and new locations of a pin on that net - * @details Updates the bounding box of a net by storing its coordinates in the bb_coord_new data structure and - * the number of blocks on each edge in the bb_edge_new data structure. This routine should only be called for - * large nets, since it has some overhead relative to just doing a brute force bounding box calculation. - * The bounding box coordinate and edge information for inet must be valid before this routine is called. - * Currently assumes channels on both sides of the CLBs forming the edges of the bounding box can be used. - * Essentially, I am assuming the pins always lie on the outside of the bounding box. The x and y coordinates + * @details Updates the bounding box of a net by storing its coordinates in the bb_coord_new data structure and + * the number of blocks on each edge in the bb_edge_new data structure. This routine should only be called for + * large nets, since it has some overhead relative to just doing a brute force bounding box calculation. + * The bounding box coordinate and edge information for inet must be valid before this routine is called. + * Currently assumes channels on both sides of the CLBs forming the edges of the bounding box can be used. + * Essentially, I am assuming the pins always lie on the outside of the bounding box. The x and y coordinates * are the pin's x and y coordinates. IO blocks are considered to be one cell in for simplicity. * @param bb_edge_new Number of blocks on the edges of the bounding box * @param bb_coord_new Coordinates of the bounding box @@ -307,11 +315,11 @@ static inline void update_bb_layer_changed(ClusterNetId net_id, vtr::NdMatrixProxy bb_pin_sink_count_new, std::vector& bb_edge_new, std::vector& bb_coord_new); - + /** * @brief Calculate the per-layer BB of a large net from scratch and update coord, edge, and num_sink_pin_layer data structures. - * @details This routine finds the bounding box of each net from scratch when the bounding box is of type per-layer (i.e. from - * only the block location information). It updates the coordinate, number of pins on each edge information, and the + * @details This routine finds the bounding box of each net from scratch when the bounding box is of type per-layer (i.e. from + * only the block location information). It updates the coordinate, number of pins on each edge information, and the * number of sinks on each layer. It should only be called when the bounding box information is not valid. * @param net_id ID of the net which the moving pin belongs to * @param coords Bounding box coordinates of the net. It is calculated in this function @@ -331,8 +339,8 @@ static void get_layer_bb_from_scratch(ClusterNetId net_id, * @return Wirelength cost of the net */ static double get_net_layer_bb_wire_cost(ClusterNetId /* net_id */, - const std::vector& bb, - const vtr::NdMatrixProxy layer_pin_sink_count); + const std::vector& bb, + const vtr::NdMatrixProxy layer_pin_sink_count); /** * @brief Given the per-layer BB, calculate the wire-length estimate of the net on each layer @@ -342,8 +350,8 @@ static double get_net_layer_bb_wire_cost(ClusterNetId /* net_id */, * @return Wirelength estimate of the net */ static double get_net_wirelength_from_layer_bb(ClusterNetId /* net_id */, - const std::vector& bb, - const vtr::NdMatrixProxy layer_pin_sink_count); + const std::vector& bb, + const vtr::NdMatrixProxy layer_pin_sink_count); /** * @brief This function is called in update_layer_bb to update the net's bounding box incrementally if @@ -421,8 +429,8 @@ static void add_block_to_bb(const t_physical_tile_loc& new_pin_loc, /** * @brief Calculate the 3D BB of a large net from scratch and update coord, edge, and num_sink_pin_layer data structures. - * @details This routine finds the bounding box of each net from scratch (i.e. from only the block location information). It updates both the - * coordinate and number of pins on each edge information. It should only be called when the bounding box + * @details This routine finds the bounding box of each net from scratch (i.e. from only the block location information). It updates both the + * coordinate and number of pins on each edge information. It should only be called when the bounding box * information is not valid. * @param net_id ID of the net which the moving pin belongs to * @param coords Bounding box coordinates of the net. It is calculated in this function @@ -442,8 +450,6 @@ static void get_bb_from_scratch(ClusterNetId net_id, */ static double get_net_cost(ClusterNetId net_id, const t_bb& bb); - - /** * @brief Given the 3D BB, calculate the wire-length estimate of the net * @param net_id ID of the net which wirelength estimate is requested @@ -452,8 +458,6 @@ static double get_net_cost(ClusterNetId net_id, const t_bb& bb); */ static double get_net_wirelength_estimate(ClusterNetId net_id, const t_bb& bb); - - /** * @brief To mitigate round-off errors, every once in a while, the costs of nets are summed up from scratch. * This functions is called to do that for bb cost. It doesn't calculate the BBs from scratch, it would only add the costs again. @@ -462,33 +466,113 @@ static double get_net_wirelength_estimate(ClusterNetId net_id, const t_bb& bb); static double recompute_bb_cost(); /** - * @brief To get the wirelength cost/est, BB perimeter is multiplied by a factor to approximately correct for the half-perimeter + * @brief To get the wirelength cost/est, BB perimeter is multiplied by a factor to approximately correct for the half-perimeter * bounding box wirelength's underestimate of wiring for nets with fanout greater than 2. * @return Multiplicative wirelength correction factor */ static double wirelength_crossing_count(size_t fanout); /** - * @brief Calculates and returns the total bb (wirelength) cost change that would result from moving the blocks + * @brief Calculates and returns the total bb (wirelength) cost change that would result from moving the blocks * indicated in the blocks_affected data structure. - * @param num_affected_nets Number of valid elements in ts_bb_coord_new * @param bb_delta_c Cost difference after and before moving the block */ -static void set_bb_delta_cost(const int num_affected_nets, double& bb_delta_c); +static void set_bb_delta_cost(double& bb_delta_c); /******************************* End of Function definitions ************************************/ +namespace { +// Initialize the ts vectors +void BBUpdater::init(size_t num_nets, bool cube_bb) { + const int num_layers = g_vpr_ctx.device().grid.get_num_layers(); + + m_cube_bb = cube_bb; + // Either 3D BB or per layer BB data structure are used, not both. + if (m_cube_bb) { + ts_info.ts_bb_edge_new.resize(num_nets, t_bb()); + ts_info.ts_bb_coord_new.resize(num_nets, t_bb()); + } else { + ts_info.layer_ts_bb_edge_new.resize(num_nets, std::vector(num_layers, t_2D_bb())); + ts_info.layer_ts_bb_coord_new.resize(num_nets, std::vector(num_layers, t_2D_bb())); + } + + /* This initializes the whole matrix to OPEN which is an invalid value*/ + ts_info.ts_layer_sink_pin_count.resize({num_nets, size_t(num_layers)}, OPEN); + + ts_info.ts_nets_to_update.resize(num_nets, ClusterNetId::INVALID()); +} + +void BBUpdater::get_non_updatable_bb(const ClusterNetId& net) { + if (m_cube_bb) { + ::get_non_updatable_bb(net, + ts_info.ts_bb_coord_new[net], + ts_info.ts_layer_sink_pin_count[size_t(net)]); + } + else { + ::get_non_updatable_layer_bb(net, + ts_info.layer_ts_bb_coord_new[net], + ts_info.ts_layer_sink_pin_count[size_t(net)]); + } +} + +void BBUpdater::update_bb(ClusterNetId net_id, t_physical_tile_loc pin_old_loc, t_physical_tile_loc pin_new_loc, bool is_driver) { + if (m_cube_bb) { + ::update_bb(net_id, + ts_info.ts_bb_edge_new[net_id], + ts_info.ts_bb_coord_new[net_id], + ts_info.ts_layer_sink_pin_count[size_t(net_id)], + pin_old_loc, + pin_new_loc, + is_driver); + } + else { + ::update_layer_bb(net_id, + ts_info.layer_ts_bb_edge_new[net_id], + ts_info.layer_ts_bb_coord_new[net_id], + ts_info.ts_layer_sink_pin_count[size_t(net_id)], + pin_old_loc, + pin_new_loc, + is_driver); + } +} + +double BBUpdater::get_net_cost(const ClusterNetId net_id) { + if (m_cube_bb) { + return ::get_net_cost(net_id, ts_info.ts_bb_coord_new[net_id]); + } + else { + return ::get_net_layer_bb_wire_cost(net_id, ts_info.layer_ts_bb_coord_new[net_id], ts_info.ts_layer_sink_pin_count[size_t(net_id)]); + } +} + +void BBUpdater::set_ts_bb_coord(const ClusterNetId net_id) { + auto& place_move_ctx = g_placer_ctx.mutable_move(); + if (m_cube_bb) { + place_move_ctx.bb_coords[net_id] = ts_info.ts_bb_coord_new[net_id]; + } else { + place_move_ctx.layer_bb_coords[net_id] = ts_info.layer_ts_bb_coord_new[net_id]; + } +} + +void BBUpdater::set_ts_edge(const ClusterNetId net_id) { + auto& place_move_ctx = g_placer_ctx.mutable_move(); + if (m_cube_bb) { + place_move_ctx.bb_num_on_edges[net_id] = ts_info.ts_bb_edge_new[net_id]; + } else { + place_move_ctx.layer_bb_num_on_edges[net_id] = ts_info.layer_ts_bb_edge_new[net_id]; + } +} +} // namespace //Returns true if 'net' is driven by one of the blocks in 'blocks_affected' static bool driven_by_moved_block(const ClusterNetId net, - const int num_blocks, const std::vector& moved_blocks) { auto& clb_nlist = g_vpr_ctx.clustering().clb_nlist; bool is_driven_by_move_blk = false; ClusterBlockId net_driver_block = clb_nlist.net_driver_block( net); - for (int block_num = 0; block_num < num_blocks; block_num++) { - if (net_driver_block == moved_blocks[block_num].block_num) { + for (const auto& block : moved_blocks) { + if (net_driver_block == block.block_num) { is_driven_by_move_blk = true; break; } @@ -506,48 +590,8 @@ static void update_net_bb(const ClusterNetId& net, if (cluster_ctx.clb_nlist.net_sinks(net).size() < SMALL_NET) { //For small nets brute-force bounding box update is faster - if (bb_updated_before[net] == NetUpdateState::NOT_UPDATED_YET) { //Only once per-net - get_non_updatable_bb(net, - ts_bb_coord_new[net], - ts_layer_sink_pin_count[size_t(net)]); - } - } else { - //For large nets, update bounding box incrementally - int iblk_pin = tile_pin_index(blk_pin); - bool src_pin = cluster_ctx.clb_nlist.pin_type(blk_pin) == PinType::DRIVER; - - t_physical_tile_type_ptr blk_type = physical_tile_type(blk); - int pin_width_offset = blk_type->pin_width_offset[iblk_pin]; - int pin_height_offset = blk_type->pin_height_offset[iblk_pin]; - - //Incremental bounding box update - update_bb(net, - ts_bb_edge_new[net], - ts_bb_coord_new[net], - ts_layer_sink_pin_count[size_t(net)], - {pl_moved_block.old_loc.x + pin_width_offset, - pl_moved_block.old_loc.y + pin_height_offset, - pl_moved_block.old_loc.layer}, - {pl_moved_block.new_loc.x + pin_width_offset, - pl_moved_block.new_loc.y + pin_height_offset, - pl_moved_block.new_loc.layer}, - src_pin); - } -} - -static void update_net_layer_bb(const ClusterNetId& net, - const ClusterBlockId& blk, - const ClusterPinId& blk_pin, - const t_pl_moved_block& pl_moved_block) { - auto& cluster_ctx = g_vpr_ctx.clustering(); - - if (cluster_ctx.clb_nlist.net_sinks(net).size() < SMALL_NET) { - //For small nets brute-force bounding box update is faster - - if (bb_updated_before[net] == NetUpdateState::NOT_UPDATED_YET) { //Only once per-net - get_non_updatable_layer_bb(net, - layer_ts_bb_coord_new[net], - ts_layer_sink_pin_count[size_t(net)]); + if (pl_net_cost.bb_update_status[net] == NetUpdateState::NOT_UPDATED_YET) { //Only once per-net + bb_updater.get_non_updatable_bb(net); } } else { //For large nets, update bounding box incrementally @@ -556,21 +600,17 @@ static void update_net_layer_bb(const ClusterNetId& net, t_physical_tile_type_ptr blk_type = physical_tile_type(blk); int pin_width_offset = blk_type->pin_width_offset[iblk_pin]; int pin_height_offset = blk_type->pin_height_offset[iblk_pin]; - - auto pin_dir = get_pin_type_from_pin_physical_num(blk_type, iblk_pin); + bool is_driver = cluster_ctx.clb_nlist.pin_type(blk_pin) == PinType::DRIVER; //Incremental bounding box update - update_layer_bb(net, - layer_ts_bb_edge_new[net], - layer_ts_bb_coord_new[net], - ts_layer_sink_pin_count[size_t(net)], - {pl_moved_block.old_loc.x + pin_width_offset, - pl_moved_block.old_loc.y + pin_height_offset, - pl_moved_block.old_loc.layer}, - {pl_moved_block.new_loc.x + pin_width_offset, - pl_moved_block.new_loc.y + pin_height_offset, - pl_moved_block.new_loc.layer}, - pin_dir == e_pin_type::DRIVER); + bb_updater.update_bb(net, + {pl_moved_block.old_loc.x + pin_width_offset, + pl_moved_block.old_loc.y + pin_height_offset, + pl_moved_block.old_loc.layer}, + {pl_moved_block.new_loc.x + pin_width_offset, + pl_moved_block.new_loc.y + pin_height_offset, + pl_moved_block.new_loc.layer}, + is_driver); } } @@ -581,7 +621,6 @@ static void update_td_delta_costs(const PlaceDelayModel* delay_model, std::vector& affected_pins, double& delta_timing_cost, bool is_src_moving) { - /** * Assumes that the blocks have been moved to the proposed new locations. * Otherwise, the routine comp_td_single_connection_delay() will not be @@ -667,29 +706,27 @@ static void update_td_delta_costs(const PlaceDelayModel* delay_model, } ///@brief Record effected nets. -static void record_affected_net(const ClusterNetId net, - int& num_affected_nets) { +static void record_affected_net(const ClusterNetId net) { /* Record effected nets. */ - if (proposed_net_cost[net] < 0.) { + if (pl_net_cost.proposed_net_cost[net] < 0.) { /* Net not marked yet. */ - ts_nets_to_update[num_affected_nets] = net; - num_affected_nets++; + VTR_ASSERT_SAFE(ts_info.ts_nets_to_update.size() < ts_info.ts_nets_to_update.capacity()); + ts_info.ts_nets_to_update.push_back(net); /* Flag to say we've marked this net. */ - proposed_net_cost[net] = 1.; + pl_net_cost.proposed_net_cost[net] = 1.; } } static void update_net_info_on_pin_move(const t_place_algorithm& place_algorithm, - const PlaceDelayModel* delay_model, - const PlacerCriticalities* criticalities, - const ClusterBlockId& blk_id, - const ClusterPinId& pin_id, - const t_pl_moved_block& moving_blk_inf, - std::vector& affected_pins, - double& timing_delta_c, - int& num_affected_nets, - bool is_src_moving) { + const PlaceDelayModel* delay_model, + const PlacerCriticalities* criticalities, + const ClusterBlockId blk_id, + const ClusterPinId pin_id, + const t_pl_moved_block& moving_blk_inf, + std::vector& affected_pins, + double& timing_delta_c, + bool is_src_moving) { const auto& cluster_ctx = g_vpr_ctx.clustering(); const ClusterNetId net_id = cluster_ctx.clb_nlist.pin_net(pin_id); VTR_ASSERT_SAFE_MSG(net_id, @@ -702,16 +739,10 @@ static void update_net_info_on_pin_move(const t_place_algorithm& place_algorithm } /* Record effected nets */ - record_affected_net(net_id, num_affected_nets); - - const auto& cube_bb = g_vpr_ctx.placement().cube_bb; + record_affected_net(net_id); /* Update the net bounding boxes. */ - if (cube_bb) { - update_net_bb(net_id, blk_id, pin_id, moving_blk_inf); - } else { - update_net_layer_bb(net_id, blk_id, pin_id, moving_blk_inf); - } + update_net_bb(net_id, blk_id, pin_id, moving_blk_inf); if (place_algorithm.is_timing_driven()) { /* Determine the change in connection delay and timing cost. */ @@ -726,8 +757,8 @@ static void update_net_info_on_pin_move(const t_place_algorithm& place_algorithm } static void get_non_updatable_bb(ClusterNetId net_id, - t_bb& bb_coord_new, - vtr::NdMatrixProxy num_sink_pin_layer) { + t_bb& bb_coord_new, + vtr::NdMatrixProxy num_sink_pin_layer) { //TODO: account for multiple physical pin instances per logical pin int xmax, ymax, layer_max, xmin, ymin, layer_min, x, y, layer; @@ -894,19 +925,18 @@ static void update_bb(ClusterNetId net_id, pin_old_loc.layer_num = max(min(pin_old_loc.layer_num, device_ctx.grid.get_num_layers() - 1), 0); /* Check if the net had been updated before. */ - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { /* The net had been updated from scratch, DO NOT update again! */ return; } - vtr::NdMatrixProxy curr_num_sink_pin_layer = (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) ? - place_move_ctx.num_sink_pin_layer[size_t(net_id)] : num_sink_pin_layer_new; + vtr::NdMatrixProxy curr_num_sink_pin_layer = (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) ? place_move_ctx.num_sink_pin_layer[size_t(net_id)] : num_sink_pin_layer_new; - if (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) { /* The net had NOT been updated before, could use the old values */ curr_bb_edge = &place_move_ctx.bb_num_on_edges[net_id]; curr_bb_coord = &place_move_ctx.bb_coords[net_id]; - bb_updated_before[net_id] = NetUpdateState::UPDATED_ONCE; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::UPDATED_ONCE; } else { /* The net had been updated before, must use the new values */ curr_bb_coord = &bb_coord_new; @@ -922,7 +952,7 @@ static void update_bb(ClusterNetId net_id, if (pin_old_loc.x == curr_bb_coord->xmax) { /* Old position at xmax. */ if (curr_bb_edge->xmax == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.xmax = curr_bb_edge->xmax - 1; @@ -954,7 +984,7 @@ static void update_bb(ClusterNetId net_id, if (pin_old_loc.x == curr_bb_coord->xmin) { /* Old position at xmin. */ if (curr_bb_edge->xmin == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.xmin = curr_bb_edge->xmin - 1; @@ -995,7 +1025,7 @@ static void update_bb(ClusterNetId net_id, if (pin_old_loc.y == curr_bb_coord->ymax) { /* Old position at ymax. */ if (curr_bb_edge->ymax == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.ymax = curr_bb_edge->ymax - 1; @@ -1027,7 +1057,7 @@ static void update_bb(ClusterNetId net_id, if (pin_old_loc.y == curr_bb_coord->ymin) { /* Old position at ymin. */ if (curr_bb_edge->ymin == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.ymin = curr_bb_edge->ymin - 1; @@ -1077,7 +1107,7 @@ static void update_bb(ClusterNetId net_id, if (pin_old_loc.layer_num == curr_bb_coord->layer_max) { if (curr_bb_edge->layer_max == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.layer_max = curr_bb_edge->layer_max - 1; @@ -1088,7 +1118,6 @@ static void update_bb(ClusterNetId net_id, bb_edge_new.layer_max = curr_bb_edge->layer_max; } - if (pin_new_loc.layer_num < curr_bb_coord->layer_min) { bb_coord_new.layer_min = pin_new_loc.layer_num; bb_edge_new.layer_min = 1; @@ -1101,12 +1130,10 @@ static void update_bb(ClusterNetId net_id, } } else if (pin_new_loc.layer_num > pin_old_loc.layer_num) { - - if (pin_old_loc.layer_num == curr_bb_coord->layer_min) { if (curr_bb_edge->layer_min == 1) { get_bb_from_scratch(net_id, bb_coord_new, bb_edge_new, num_sink_pin_layer_new); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { bb_edge_new.layer_min = curr_bb_edge->layer_min - 1; @@ -1128,23 +1155,22 @@ static void update_bb(ClusterNetId net_id, bb_edge_new.layer_max = curr_bb_edge->layer_max; } - - } else {//pin_new_loc.layer_num == pin_old_loc.layer_num + } else { //pin_new_loc.layer_num == pin_old_loc.layer_num bb_coord_new.layer_min = curr_bb_coord->layer_min; bb_coord_new.layer_max = curr_bb_coord->layer_max; bb_edge_new.layer_min = curr_bb_edge->layer_min; bb_edge_new.layer_max = curr_bb_edge->layer_max; } - } else {// num_layers == 1 + } else { // num_layers == 1 bb_coord_new.layer_min = curr_bb_coord->layer_min; bb_coord_new.layer_max = curr_bb_coord->layer_max; bb_edge_new.layer_min = curr_bb_edge->layer_min; bb_edge_new.layer_max = curr_bb_edge->layer_max; } - if (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) { - bb_updated_before[net_id] = NetUpdateState::UPDATED_ONCE; + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) { + pl_net_cost.bb_update_status[net_id] = NetUpdateState::UPDATED_ONCE; } } @@ -1155,7 +1181,6 @@ static void update_layer_bb(ClusterNetId net_id, t_physical_tile_loc pin_old_loc, t_physical_tile_loc pin_new_loc, bool is_output_pin) { - auto& device_ctx = g_vpr_ctx.device(); auto& place_move_ctx = g_placer_ctx.move(); @@ -1165,20 +1190,19 @@ static void update_layer_bb(ClusterNetId net_id, pin_old_loc.y = max(min(pin_old_loc.y, device_ctx.grid.height() - 2), 1); //-2 for no perim channels /* Check if the net had been updated before. */ - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { /* The net had been updated from scratch, DO NOT update again! */ return; } - const vtr::NdMatrixProxy curr_layer_pin_sink_count = (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) ? - place_move_ctx.num_sink_pin_layer[size_t(net_id)] : bb_pin_sink_count_new; + const vtr::NdMatrixProxy curr_layer_pin_sink_count = (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) ? place_move_ctx.num_sink_pin_layer[size_t(net_id)] : bb_pin_sink_count_new; const std::vector*curr_bb_edge, *curr_bb_coord; - if (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) { /* The net had NOT been updated before, could use the old values */ curr_bb_edge = &place_move_ctx.layer_bb_num_on_edges[net_id]; curr_bb_coord = &place_move_ctx.layer_bb_coords[net_id]; - bb_updated_before[net_id] = NetUpdateState::UPDATED_ONCE; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::UPDATED_ONCE; } else { /* The net had been updated before, must use the new values */ curr_bb_edge = &bb_edge_new; @@ -1220,8 +1244,8 @@ static void update_layer_bb(ClusterNetId net_id, bb_coord_new); } - if (bb_updated_before[net_id] == NetUpdateState::NOT_UPDATED_YET) { - bb_updated_before[net_id] = NetUpdateState::UPDATED_ONCE; + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::NOT_UPDATED_YET) { + pl_net_cost.bb_update_status[net_id] = NetUpdateState::UPDATED_ONCE; } } @@ -1252,7 +1276,7 @@ static inline void update_bb_same_layer(ClusterNetId net_id, curr_bb_coord[layer_num].xmax, bb_edge_new[layer_num].xmax, bb_coord_new[layer_num].xmax); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1275,7 +1299,7 @@ static inline void update_bb_same_layer(ClusterNetId net_id, curr_bb_coord[layer_num].xmin, bb_edge_new[layer_num].xmin, bb_coord_new[layer_num].xmin); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1299,7 +1323,7 @@ static inline void update_bb_same_layer(ClusterNetId net_id, curr_bb_coord[layer_num].ymax, bb_edge_new[layer_num].ymax, bb_coord_new[layer_num].ymax); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1322,7 +1346,7 @@ static inline void update_bb_same_layer(ClusterNetId net_id, curr_bb_coord[layer_num].ymin, bb_edge_new[layer_num].ymin, bb_coord_new[layer_num].ymin); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1367,7 +1391,7 @@ static inline void update_bb_layer_changed(ClusterNetId net_id, curr_bb_coord[old_layer_num].xmax, bb_edge_new[old_layer_num].xmax, bb_coord_new[old_layer_num].xmax); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } else if (x_old == curr_bb_coord[old_layer_num].xmin) { @@ -1379,7 +1403,7 @@ static inline void update_bb_layer_changed(ClusterNetId net_id, curr_bb_coord[old_layer_num].xmin, bb_edge_new[old_layer_num].xmin, bb_coord_new[old_layer_num].xmin); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1393,7 +1417,7 @@ static inline void update_bb_layer_changed(ClusterNetId net_id, curr_bb_coord[old_layer_num].ymax, bb_edge_new[old_layer_num].ymax, bb_coord_new[old_layer_num].ymax); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } else if (y_old == curr_bb_coord[old_layer_num].ymin) { @@ -1405,7 +1429,7 @@ static inline void update_bb_layer_changed(ClusterNetId net_id, curr_bb_coord[old_layer_num].ymin, bb_edge_new[old_layer_num].ymin, bb_coord_new[old_layer_num].ymin); - if (bb_updated_before[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { + if (pl_net_cost.bb_update_status[net_id] == NetUpdateState::GOT_FROM_SCRATCH) { return; } } @@ -1445,7 +1469,7 @@ static inline void update_bb_edge(ClusterNetId net_id, bb_edge_new, bb_coord_new, bb_layer_pin_sink_count); - bb_updated_before[net_id] = NetUpdateState::GOT_FROM_SCRATCH; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::GOT_FROM_SCRATCH; return; } else { new_num_block_on_edge = old_num_block_on_edge - 1; @@ -1461,7 +1485,7 @@ static void add_block_to_bb(const t_physical_tile_loc& new_pin_loc, int x_new = new_pin_loc.x; int y_new = new_pin_loc.y; - /* + /* This function is called to only update the bounding box on the new layer from a block moving to this layer from another layer. Thus, we only need to assess the effect of this new block on the edges. @@ -1612,7 +1636,6 @@ static void get_bb_from_scratch(ClusterNetId net_id, VTR_ASSERT_DEBUG(layer_min >= 0 && layer_min < device_ctx.grid.get_num_layers()); VTR_ASSERT_DEBUG(layer_max >= 0 && layer_max < device_ctx.grid.get_num_layers()); - num_on_edges.xmin = xmin_edge; num_on_edges.xmax = xmax_edge; num_on_edges.ymin = ymin_edge; @@ -1760,8 +1783,8 @@ static double get_net_cost(ClusterNetId net_id, const t_bb& bb) { } static double get_net_layer_bb_wire_cost(ClusterNetId /* net_id */, - const std::vector& bb, - const vtr::NdMatrixProxy layer_pin_sink_count) { + const std::vector& bb, + const vtr::NdMatrixProxy layer_pin_sink_count) { /* Finds the cost due to one net by looking at its coordinate bounding * * box. */ @@ -1774,10 +1797,10 @@ static double get_net_layer_bb_wire_cost(ClusterNetId /* net_id */, if (layer_pin_sink_count[layer_num] == 0) { continue; } - /* - adjust the bounding box half perimeter by the wirelength correction - factor based on terminal count, which is 1 for the source + the number - of sinks on this layer. + /* + adjust the bounding box half perimeter by the wirelength correction + factor based on terminal count, which is 1 for the source + the number + of sinks on this layer. */ crossing = wirelength_crossing_count(layer_pin_sink_count[layer_num] + 1); @@ -1820,8 +1843,8 @@ static double get_net_wirelength_estimate(ClusterNetId net_id, const t_bb& bb) { } static double get_net_wirelength_from_layer_bb(ClusterNetId /* net_id */, - const std::vector& bb, - const vtr::NdMatrixProxy layer_pin_sink_count) { + const std::vector& bb, + const vtr::NdMatrixProxy layer_pin_sink_count) { /* WMF: Finds the estimate of wirelength due to one net by looking at * * its coordinate bounding box. */ @@ -1830,7 +1853,7 @@ static double get_net_wirelength_from_layer_bb(ClusterNetId /* net_id */, int num_layers = g_vpr_ctx.device().grid.get_num_layers(); for (int layer_num = 0; layer_num < num_layers; layer_num++) { - VTR_ASSERT_SAFE (layer_pin_sink_count[layer_num] != OPEN); + VTR_ASSERT_SAFE(layer_pin_sink_count[layer_num] != OPEN); if (layer_pin_sink_count[layer_num] == 0) { continue; } @@ -1859,7 +1882,7 @@ static double recompute_bb_cost() { for (auto net_id : cluster_ctx.clb_nlist.nets()) { /* for each net ... */ if (!cluster_ctx.clb_nlist.net_is_ignored(net_id)) { /* Do only if not ignored. */ /* Bounding boxes don't have to be recomputed; they're correct. */ - cost += net_cost[net_id]; + cost += pl_net_cost.net_cost[net_id]; } } @@ -1877,26 +1900,17 @@ static double wirelength_crossing_count(size_t fanout) { } } -static void set_bb_delta_cost(const int num_affected_nets, double& bb_delta_c) { - for (int inet_affected = 0; inet_affected < num_affected_nets; - inet_affected++) { - ClusterNetId net_id = ts_nets_to_update[inet_affected]; - const auto& cube_bb = g_vpr_ctx.placement().cube_bb; - - if (cube_bb) { - proposed_net_cost[net_id] = get_net_cost(net_id, - ts_bb_coord_new[net_id]); - } else { - proposed_net_cost[net_id] = get_net_layer_bb_wire_cost(net_id, - layer_ts_bb_coord_new[net_id], - ts_layer_sink_pin_count[size_t(net_id)]); - } +static void set_bb_delta_cost(double& bb_delta_c) { + for (const ClusterNetId ts_net: ts_info.ts_nets_to_update) { + ClusterNetId net_id = ts_net; + + pl_net_cost.proposed_net_cost[net_id] = bb_updater.get_net_cost(net_id); - bb_delta_c += proposed_net_cost[net_id] - net_cost[net_id]; + bb_delta_c += pl_net_cost.proposed_net_cost[net_id] - pl_net_cost.net_cost[net_id]; } } -int find_affected_nets_and_update_costs( +void find_affected_nets_and_update_costs( const t_place_algorithm& place_algorithm, const PlaceDelayModel* delay_model, const PlacerCriticalities* criticalities, @@ -1907,13 +1921,13 @@ int find_affected_nets_and_update_costs( VTR_ASSERT_SAFE(timing_delta_c == 0.); auto& clb_nlist = g_vpr_ctx.clustering().clb_nlist; - int num_affected_nets = 0; + ts_info.ts_nets_to_update.resize(0); /* Go through all the blocks moved. */ - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; iblk++) { - const auto& moving_block_inf = blocks_affected.moved_blocks[iblk]; + for (const auto& block : blocks_affected.moved_blocks) { + const auto& moving_block_inf = block; auto& affected_pins = blocks_affected.affected_pins; - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + ClusterBlockId blk = block.block_num; /* Go through all the pins in the moved block. */ for (ClusterPinId blk_pin : clb_nlist.block_pins(blk)) { @@ -1921,7 +1935,6 @@ int find_affected_nets_and_update_costs( if (clb_nlist.pin_type(blk_pin) == PinType::SINK) { ClusterNetId net_id = clb_nlist.pin_net(blk_pin); is_src_moving = driven_by_moved_block(net_id, - blocks_affected.num_moved_blocks, blocks_affected.moved_blocks); } update_net_info_on_pin_move(place_algorithm, @@ -1932,16 +1945,13 @@ int find_affected_nets_and_update_costs( moving_block_inf, affected_pins, timing_delta_c, - num_affected_nets, is_src_moving); } } /* Now update the bounding box costs (since the net bounding * * boxes are up-to-date). The cost is only updated once per net. */ - set_bb_delta_cost(num_affected_nets, bb_delta_c); - - return num_affected_nets; + set_bb_delta_cost(bb_delta_c); } double comp_bb_cost(e_cost_methods method) { @@ -1966,8 +1976,8 @@ double comp_bb_cost(e_cost_methods method) { place_move_ctx.num_sink_pin_layer[size_t(net_id)]); } - net_cost[net_id] = get_net_cost(net_id, place_move_ctx.bb_coords[net_id]); - cost += net_cost[net_id]; + pl_net_cost.net_cost[net_id] = get_net_cost(net_id, place_move_ctx.bb_coords[net_id]); + cost += pl_net_cost.net_cost[net_id]; if (method == CHECK) expected_wirelength += get_net_wirelength_estimate(net_id, place_move_ctx.bb_coords[net_id]); } @@ -2003,14 +2013,14 @@ double comp_layer_bb_cost(e_cost_methods method) { place_move_ctx.num_sink_pin_layer[size_t(net_id)]); } - net_cost[net_id] = get_net_layer_bb_wire_cost(net_id, - place_move_ctx.layer_bb_coords[net_id], - place_move_ctx.num_sink_pin_layer[size_t(net_id)]); - cost += net_cost[net_id]; + pl_net_cost.net_cost[net_id] = get_net_layer_bb_wire_cost(net_id, + place_move_ctx.layer_bb_coords[net_id], + place_move_ctx.num_sink_pin_layer[size_t(net_id)]); + cost += pl_net_cost.net_cost[net_id]; if (method == CHECK) expected_wirelength += get_net_wirelength_from_layer_bb(net_id, - place_move_ctx.layer_bb_coords[net_id], - place_move_ctx.num_sink_pin_layer[size_t(net_id)]); + place_move_ctx.layer_bb_coords[net_id], + place_move_ctx.num_sink_pin_layer[size_t(net_id)]); } } @@ -2022,57 +2032,46 @@ double comp_layer_bb_cost(e_cost_methods method) { return cost; } -void update_move_nets(int num_nets_affected, - const bool cube_bb) { +void update_move_nets() { /* update net cost functions and reset flags. */ auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = g_placer_ctx.mutable_move(); - for (int inet_affected = 0; inet_affected < num_nets_affected; - inet_affected++) { - ClusterNetId net_id = ts_nets_to_update[inet_affected]; + for (const ClusterNetId ts_net : ts_info.ts_nets_to_update) { + ClusterNetId net_id = ts_net; - if (cube_bb) { - place_move_ctx.bb_coords[net_id] = ts_bb_coord_new[net_id]; - } else { - place_move_ctx.layer_bb_coords[net_id] = layer_ts_bb_coord_new[net_id]; - } + bb_updater.set_ts_bb_coord(net_id); for (int layer_num = 0; layer_num < g_vpr_ctx.device().grid.get_num_layers(); layer_num++) { - place_move_ctx.num_sink_pin_layer[size_t(net_id)][layer_num] = ts_layer_sink_pin_count[size_t(net_id)][layer_num]; + place_move_ctx.num_sink_pin_layer[size_t(net_id)][layer_num] = ts_info.ts_layer_sink_pin_count[size_t(net_id)][layer_num]; } if (cluster_ctx.clb_nlist.net_sinks(net_id).size() >= SMALL_NET) { - if (cube_bb) { - place_move_ctx.bb_num_on_edges[net_id] = ts_bb_edge_new[net_id]; - } else { - place_move_ctx.layer_bb_num_on_edges[net_id] = layer_ts_bb_edge_new[net_id]; - } + bb_updater.set_ts_edge(net_id); } - net_cost[net_id] = proposed_net_cost[net_id]; + pl_net_cost.net_cost[net_id] = pl_net_cost.proposed_net_cost[net_id]; /* negative proposed_net_cost value is acting as a flag to mean not computed yet. */ - proposed_net_cost[net_id] = -1; - bb_updated_before[net_id] = NetUpdateState::NOT_UPDATED_YET; + pl_net_cost.proposed_net_cost[net_id] = -1; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::NOT_UPDATED_YET; } } -void reset_move_nets(int num_nets_affected) { +void reset_move_nets() { /* Reset the net cost function flags first. */ - for (int inet_affected = 0; inet_affected < num_nets_affected; - inet_affected++) { - ClusterNetId net_id = ts_nets_to_update[inet_affected]; - proposed_net_cost[net_id] = -1; - bb_updated_before[net_id] = NetUpdateState::NOT_UPDATED_YET; + for (const ClusterNetId ts_net : ts_info.ts_nets_to_update) { + ClusterNetId net_id = ts_net; + pl_net_cost.proposed_net_cost[net_id] = -1; + pl_net_cost.bb_update_status[net_id] = NetUpdateState::NOT_UPDATED_YET; } } void recompute_costs_from_scratch(const t_placer_opts& placer_opts, - const t_noc_opts& noc_opts, - const PlaceDelayModel* delay_model, - const PlacerCriticalities* criticalities, - t_placer_costs* costs) { + const t_noc_opts& noc_opts, + const PlaceDelayModel* delay_model, + const PlacerCriticalities* criticalities, + t_placer_costs* costs) { auto check_and_print_cost = [](double new_cost, double old_cost, const std::string& cost_name) { @@ -2147,9 +2146,9 @@ void alloc_and_load_chan_w_factors_for_place_cost(float place_cost_exp) { auto& device_ctx = g_vpr_ctx.device(); - /* - Access arrays below as chan?_place_cost_fac[subhigh][sublow]. Since subhigh must be greater than or - equal to sublow, we will only access the lower half of a matrix, but we allocate the whole matrix anyway + /* + Access arrays below as chan?_place_cost_fac[subhigh][sublow]. Since subhigh must be greater than or + equal to sublow, we will only access the lower half of a matrix, but we allocate the whole matrix anyway for simplicity so we can use the vtr utility matrix functions. */ @@ -2232,49 +2231,35 @@ void alloc_and_load_chan_w_factors_for_place_cost(float place_cost_exp) { } } -void free_chan_w_factors_for_place_cost () { +void free_chan_w_factors_for_place_cost() { chanx_place_cost_fac.clear(); chany_place_cost_fac.clear(); } void init_place_move_structs(size_t num_nets) { - net_cost.resize(num_nets, -1.); - proposed_net_cost.resize(num_nets, -1.); + pl_net_cost.net_cost.resize(num_nets, -1.); + pl_net_cost.proposed_net_cost.resize(num_nets, -1.); /* Used to store costs for moves not yet made and to indicate when a net's * * cost has been recomputed. proposed_net_cost[inet] < 0 means net's cost hasn't * * been recomputed. */ - bb_updated_before.resize(num_nets, NetUpdateState::NOT_UPDATED_YET); + pl_net_cost.bb_update_status.resize(num_nets, NetUpdateState::NOT_UPDATED_YET); } void free_place_move_structs() { - vtr::release_memory(net_cost); - vtr::release_memory(proposed_net_cost); - vtr::release_memory(bb_updated_before); + vtr::release_memory(pl_net_cost.net_cost); + vtr::release_memory(pl_net_cost.proposed_net_cost); + vtr::release_memory(pl_net_cost.bb_update_status); } void init_try_swap_net_cost_structs(size_t num_nets, bool cube_bb) { - const int num_layers = g_vpr_ctx.device().grid.get_num_layers(); - - if (cube_bb) { - ts_bb_edge_new.resize(num_nets, t_bb()); - ts_bb_coord_new.resize(num_nets, t_bb()); - } else { - VTR_ASSERT_SAFE(!cube_bb); - layer_ts_bb_edge_new.resize(num_nets, std::vector(num_layers, t_2D_bb())); - layer_ts_bb_coord_new.resize(num_nets, std::vector(num_layers, t_2D_bb())); - } - - /*This initialize the whole matrix to OPEN which is an invalid value*/ - ts_layer_sink_pin_count.resize({num_nets, size_t(num_layers)}, OPEN); - - ts_nets_to_update.resize(num_nets, ClusterNetId::INVALID()); + bb_updater.init(num_nets, cube_bb); } void free_try_swap_net_cost_structs() { - vtr::release_memory(ts_bb_edge_new); - vtr::release_memory(ts_bb_coord_new); - vtr::release_memory(layer_ts_bb_edge_new); - vtr::release_memory(layer_ts_bb_coord_new); - ts_layer_sink_pin_count.clear(); - vtr::release_memory(ts_nets_to_update); + vtr::release_memory(ts_info.ts_bb_edge_new); + vtr::release_memory(ts_info.ts_bb_coord_new); + vtr::release_memory(ts_info.layer_ts_bb_edge_new); + vtr::release_memory(ts_info.layer_ts_bb_coord_new); + ts_info.ts_layer_sink_pin_count.clear(); + vtr::release_memory(ts_info.ts_nets_to_update); } diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 57c64cadca5..0e72611b323 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -6,8 +6,8 @@ /** * @brief The method used to calculate palcement cost - * @details For comp_cost. NORMAL means use the method that generates updateable bounding boxes for speed. - * CHECK means compute all bounding boxes from scratch using a very simple routine to allow checks + * @details For comp_cost. NORMAL means use the method that generates updateable bounding boxes for speed. + * CHECK means compute all bounding boxes from scratch using a very simple routine to allow checks * of the other costs. * NORMAL: Compute cost efficiently using incremental techniques. * CHECK: Brute-force cost computation; useful to validate the more complex incremental cost update code. @@ -36,7 +36,8 @@ enum e_cost_methods { * * The change in the bounding box cost is stored in `bb_delta_c`. * The change in the timing cost is stored in `timing_delta_c`. - * + * ts_nets_to_update is also extended with the latest net. + * * @param place_algorithm * @param delay_model * @param criticalities @@ -45,7 +46,7 @@ enum e_cost_methods { * @param timing_delta_c * @return The number of affected nets. */ -int find_affected_nets_and_update_costs( +void find_affected_nets_and_update_costs( const t_place_algorithm& place_algorithm, const PlaceDelayModel* delay_model, const PlacerCriticalities* criticalities, @@ -54,27 +55,27 @@ int find_affected_nets_and_update_costs( double& timing_delta_c); /** - * @brief Finds the bb cost from scratch (based on 3D BB). - * Done only when the placement has been radically changed - * (i.e. after initial placement). Otherwise find the cost - * change incrementally. If method check is NORMAL, we find - * bounding boxes that are updatable for the larger nets. - * If method is CHECK, all bounding boxes are found via the - * non_updateable_bb routine, to provide a cost which can be - * used to check the correctness of the other routine. + * @brief Finds the bb cost from scratch (based on 3D BB). + * Done only when the placement has been radically changed + * (i.e. after initial placement). Otherwise find the cost + * change incrementally. If method check is NORMAL, we find + * bounding boxes that are updatable for the larger nets. + * If method is CHECK, all bounding boxes are found via the + * non_updateable_bb routine, to provide a cost which can be + * used to check the correctness of the other routine. * @param method * @return The bounding box cost of the placement, computed by the 3D method. */ double comp_bb_cost(e_cost_methods method); /** - * @brief Finds the bb cost from scratch (based on per-layer BB). - * Done only when the placement has been radically changed - * (i.e. after initial placement). Otherwise find the cost change - * incrementally. If method check is NORMAL, we find bounding boxes - * that are updateable for the larger nets. If method is CHECK, all - * bounding boxes are found via the non_updateable_bb routine, to provide - * a cost which can be used to check the correctness of the other routine. + * @brief Finds the bb cost from scratch (based on per-layer BB). + * Done only when the placement has been radically changed + * (i.e. after initial placement). Otherwise find the cost change + * incrementally. If method check is NORMAL, we find bounding boxes + * that are updateable for the larger nets. If method is CHECK, all + * bounding boxes are found via the non_updateable_bb routine, to provide + * a cost which can be used to check the correctness of the other routine. * @param method * @return The placement bounding box cost, computed by the per layer method. */ @@ -83,20 +84,18 @@ double comp_layer_bb_cost(e_cost_methods method); /** * @brief update net cost data structures (in placer context and net_cost in .cpp file) and reset flags (proposed_net_cost and bb_updated_before). * @param num_nets_affected The number of nets affected by the move. It is used to determine the index up to which elements in ts_nets_to_update are valid. - * @param cube_bb True if we should use the 3D bounding box (cube_bb), false otherwise. */ -void update_move_nets(int num_nets_affected, - const bool cube_bb); +void update_move_nets(); /** * @brief Reset the net cost function flags (proposed_net_cost and bb_updated_before) * @param num_nets_affected */ -void reset_move_nets(int num_nets_affected); +void reset_move_nets(); /** * @brief re-calculates different terms of the cost function (wire-length, timing, NoC) and update "costs" accordingly. It is important to note that - * in this function bounding box and connection delays are not calculated from scratch. However, it iterates over all nets and connections and updates + * in this function bounding box and connection delays are not calculated from scratch. However, it iterates over all nets and connections and updates * their costs by a complete summation, rather than incrementally. * @param placer_opts * @param noc_opts @@ -105,16 +104,16 @@ void reset_move_nets(int num_nets_affected); * @param costs passed by reference and computed by this routine (i.e. returned by reference) */ void recompute_costs_from_scratch(const t_placer_opts& placer_opts, - const t_noc_opts& noc_opts, - const PlaceDelayModel* delay_model, - const PlacerCriticalities* criticalities, - t_placer_costs* costs); + const t_noc_opts& noc_opts, + const PlaceDelayModel* delay_model, + const PlacerCriticalities* criticalities, + t_placer_costs* costs); /** * @brief Allocates and loads the chanx_place_cost_fac and chany_place_cost_fac * arrays with the inverse of the average number of tracks per channel * between [subhigh] and [sublow]. - * @param place_cost_exp It is an exponent to which you take the average inverse channel + * @param place_cost_exp It is an exponent to which you take the average inverse channel * capacity; a higher value would favour wider channels more over narrower channels during placement (usually we use 1). */ void alloc_and_load_chan_w_factors_for_place_cost(float place_cost_exp); @@ -122,7 +121,7 @@ void alloc_and_load_chan_w_factors_for_place_cost(float place_cost_exp); /** * @brief Frees the chanx_place_cost_fac and chany_place_cost_fac arrays. */ -void free_chan_w_factors_for_place_cost (); +void free_chan_w_factors_for_place_cost(); /** * @brief Resize net_cost, proposed_net_cost, and bb_updated_before data structures to accommodate all nets. @@ -136,8 +135,8 @@ void init_place_move_structs(size_t num_nets); void free_place_move_structs(); /** - * @brief Resize temporary storage data structures needed to determine which nets are affected by a move and data needed per net - * about where their terminals are in order to quickly (incrementally) update their wirelength costs. These data structures are + * @brief Resize temporary storage data structures needed to determine which nets are affected by a move and data needed per net + * about where their terminals are in order to quickly (incrementally) update their wirelength costs. These data structures are * (layer_)ts_bb_edge_new, (layer_)ts_bb_coord_new, ts_layer_sink_pin_count, and ts_nets_to_update. * @param num_nets Number of nets in the netlist used by the placement engine (currently clustered netlist) * @param cube_bb True if the 3D bounding box should be used, false otherwise. diff --git a/vpr/src/place/noc_place_utils.cpp b/vpr/src/place/noc_place_utils.cpp index 0b9e274b85b..d8d9b481ec1 100644 --- a/vpr/src/place/noc_place_utils.cpp +++ b/vpr/src/place/noc_place_utils.cpp @@ -136,8 +136,8 @@ void find_affected_noc_routers_and_update_noc_costs(const t_pl_blocks_to_be_move affected_noc_links.clear(); // go through the moved blocks and process them only if they are NoC routers - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + for (const auto& block : blocks_affected.moved_blocks) { + ClusterBlockId blk = block.block_num; // check if the current moved block is a noc router if (noc_traffic_flows_storage.check_if_cluster_block_has_traffic_flows(blk)) { @@ -291,8 +291,8 @@ void revert_noc_traffic_flow_routes(const t_pl_blocks_to_be_moved& blocks_affect std::unordered_set reverted_traffic_flows; // go through the moved blocks and process them only if they are NoC routers - for (int iblk = 0; iblk < blocks_affected.num_moved_blocks; ++iblk) { - ClusterBlockId blk = blocks_affected.moved_blocks[iblk].block_num; + for (const auto& block : blocks_affected.moved_blocks) { + ClusterBlockId blk = block.block_num; // check if the current moved block is a noc router if (noc_traffic_flows_storage.check_if_cluster_block_has_traffic_flows(blk)) { @@ -323,7 +323,7 @@ void re_route_traffic_flow(NocTrafficFlowId traffic_flow_id, // get the current traffic flow info const t_noc_traffic_flow& curr_traffic_flow = noc_traffic_flows_storage.get_single_noc_traffic_flow(traffic_flow_id); - /* since the current traffic flow route will be + /* since the current traffic flow route will be * changed, first we need to decrement the bandwidth * usage of all links that are part of * the existing traffic flow route @@ -994,4 +994,4 @@ static std::vector find_affected_links_by_flow_reroute(std::vector f_move_stats_file(nullptr, t, \ int(b_from), int(b_to), \ from_type->name, (to_type ? to_type->name : "EMPTY"), \ - affected_blocks.num_moved_blocks); \ + affected_blocks.moved_blocks.size()); \ } \ } while (false) @@ -1325,8 +1325,8 @@ static e_move_result try_swap(const t_annealing_state* state, if (manual_move_enabled) { #ifndef NO_GRAPHICS create_move_outcome = manual_move_display_and_propose(manual_move_generator, blocks_affected, proposed_action.move_type, rlim, placer_opts, criticalities); -#else //NO_GRAPHICS - //Cast to void to explicitly avoid warning. +#else //NO_GRAPHICS + //Cast to void to explicitly avoid warning. (void)manual_move_generator; #endif //NO_GRAPHICS } else if (router_block_move) { @@ -1378,9 +1378,8 @@ static e_move_result try_swap(const t_annealing_state* state, // //Also find all the pins affected by the swap, and calculates new connection //delays and timing costs and store them in proposed_* data structures. - int num_nets_affected = find_affected_nets_and_update_costs( - place_algorithm, delay_model, criticalities, blocks_affected, - bb_delta_c, timing_delta_c); + find_affected_nets_and_update_costs(place_algorithm, delay_model, criticalities, + blocks_affected, bb_delta_c, timing_delta_c); //For setup slack analysis, we first do a timing analysis to get the newest //slack values resulted from the proposed block moves. If the move turns out @@ -1481,8 +1480,7 @@ static e_move_result try_swap(const t_annealing_state* state, } /* Update net cost functions and reset flags. */ - update_move_nets(num_nets_affected, - g_vpr_ctx.placement().cube_bb); + update_move_nets(); /* Update clb data structures since we kept the move. */ commit_move_blocks(blocks_affected); @@ -1506,7 +1504,7 @@ static e_move_result try_swap(const t_annealing_state* state, VTR_ASSERT_SAFE(move_outcome == REJECTED); /* Reset the net cost function flags first. */ - reset_move_nets(num_nets_affected); + reset_move_nets(); /* Restore the place_ctx.block_locs data structures to their state before the move. */ revert_move_blocks(blocks_affected); @@ -1568,8 +1566,6 @@ static e_move_result try_swap(const t_annealing_state* state, if (!router_block_move) { calculate_reward_and_process_outcome(placer_opts, move_outcome_stats, delta_c, timing_bb_factor, move_generator); - } else { -// std::cout << "Group move delta cost: " << delta_c << std::endl; } #ifdef VTR_ENABLE_DEBUG_LOGGING @@ -1579,7 +1575,7 @@ static e_move_result try_swap(const t_annealing_state* state, #endif /* Clear the data structure containing block move info */ - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); //VTR_ASSERT(check_macro_placement_consistency() == 0); #if 0 @@ -1627,9 +1623,9 @@ static bool is_cube_bb(const e_place_bounding_box_mode place_bb_mode, * loop iteration of the placement. At each temperature change, these * values are updated so that we can balance the tradeoff between the * different placement cost components (timing, wirelength and NoC). - * Depending on the placement mode the corresponding normalization factors are + * Depending on the placement mode the corresponding normalization factors are * updated. - * + * * @param costs Contains the normalization factors which need to be updated * @param placer_opts Determines the placement mode * @param noc_opts Determines if placement includes the NoC @@ -1652,7 +1648,7 @@ static void update_placement_cost_normalization_factors(t_placer_costs* costs, c /** * @brief Compute the total normalized cost for a given placement. This * computation will vary depending on the placement modes. - * + * * @param costs The current placement cost components and their normalization * factors * @param placer_opts Determines the placement mode @@ -1916,7 +1912,7 @@ static void alloc_and_load_placement_structs(float place_cost_exp, elem = OPEN; } - alloc_and_load_chan_w_factors_for_place_cost (place_cost_exp); + alloc_and_load_chan_w_factors_for_place_cost(place_cost_exp); alloc_and_load_try_swap_structs(cube_bb); @@ -1956,7 +1952,7 @@ static void free_placement_structs(const t_placer_opts& placer_opts, const t_noc place_move_ctx.num_sink_pin_layer.clear(); - free_chan_w_factors_for_place_cost (); + free_chan_w_factors_for_place_cost(); free_try_swap_structs(); @@ -2185,7 +2181,7 @@ int check_macro_placement_consistency() { error++; } } // Finish going through all the members - } // Finish going through all the macros + } // Finish going through all the macros return error; } @@ -2373,10 +2369,9 @@ static void print_placement_move_types_stats(const MoveTypeStat& move_type_stat) int total_moves = 0; for (size_t i = 0; i < move_type_stat.blk_type_moves.size(); ++i) { - total_moves += move_type_stat.blk_type_moves.get(i); + total_moves += move_type_stat.blk_type_moves.get(i); } - auto& device_ctx = g_vpr_ctx.device(); int count = 0; int num_of_avail_moves = move_type_stat.blk_type_moves.size() / device_ctx.logical_block_types.size(); diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index ff5aacbb092..493f378b99d 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -100,16 +100,16 @@ void print_macro_constraint_error(const t_pl_macro& pl_macro); inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) { bool floorplan_legal; - for (int i = 0; i < blocks_affected.num_moved_blocks; i++) { - floorplan_legal = cluster_floorplanning_legal(blocks_affected.moved_blocks[i].block_num, - blocks_affected.moved_blocks[i].new_loc); + for (const t_pl_moved_block& moved_block : blocks_affected.moved_blocks) { + floorplan_legal = cluster_floorplanning_legal(moved_block.block_num, + moved_block.new_loc); if (!floorplan_legal) { VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\tMove aborted for block %zu, location tried was x: %d, y: %d, subtile: %d \n", - size_t(blocks_affected.moved_blocks[i].block_num), - blocks_affected.moved_blocks[i].new_loc.x, - blocks_affected.moved_blocks[i].new_loc.y, - blocks_affected.moved_blocks[i].new_loc.sub_tile); + size_t(moved_block.block_num), + moved_block.new_loc.x, + moved_block.new_loc.y, + moved_block.new_loc.sub_tile); return false; } } diff --git a/vpr/src/place/placer_breakpoint.cpp b/vpr/src/place/placer_breakpoint.cpp index 4b23862daf9..b576bc64f04 100644 --- a/vpr/src/place/placer_breakpoint.cpp +++ b/vpr/src/place/placer_breakpoint.cpp @@ -8,7 +8,7 @@ std::map available_move_types = { # ifndef NO_GRAPHICS //transforms the vector moved_blocks to a vector of ints and adds it in glob_breakpoint_state -void transform_blocks_affected(t_pl_blocks_to_be_moved blocksAffected) { +void transform_blocks_affected(const t_pl_blocks_to_be_moved& blocksAffected) { get_bp_state_globals()->get_glob_breakpoint_state()->blocks_affected_by_move.clear(); for (size_t i = 0; i < blocksAffected.moved_blocks.size(); i++) { //size_t conversion is required since block_num is of type ClusterBlockId and can't be cast to an int. And this vector has to be of type int to be recognized in expr_eval class diff --git a/vpr/src/place/placer_breakpoint.h b/vpr/src/place/placer_breakpoint.h index 36f2da7ef63..c01ef77450c 100644 --- a/vpr/src/place/placer_breakpoint.h +++ b/vpr/src/place/placer_breakpoint.h @@ -10,7 +10,7 @@ #ifdef VTR_ENABLE_DEBUG_LOGGING //transforms the vector moved_blocks to a vector of ints and adds it in glob_breakpoint_state -void transform_blocks_affected(t_pl_blocks_to_be_moved blocksAffected); +void transform_blocks_affected(const t_pl_blocks_to_be_moved& blocksAffected); //checks the breakpoint and see whether one of them was reached and pause place,emt accordingly void stop_placement_and_check_breakpoints(t_pl_blocks_to_be_moved& blocks_affected, e_move_result move_outcome, double delta_c, double bb_delta_c, double timing_delta_c); diff --git a/vpr/test/test_noc_place_utils.cpp b/vpr/test/test_noc_place_utils.cpp index 80023cf8b81..4633996458d 100644 --- a/vpr/test/test_noc_place_utils.cpp +++ b/vpr/test/test_noc_place_utils.cpp @@ -748,7 +748,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ } while (swap_router_block_one == swap_router_block_two); //set up the moved blocks datastructure for the test function - blocks_affected.num_moved_blocks = 2; + blocks_affected.moved_blocks.resize(2); blocks_affected.moved_blocks[0].block_num = swap_router_block_one; blocks_affected.moved_blocks[0].old_loc = t_pl_loc(noc_ctx.noc_model.get_single_noc_router(router_where_cluster_is_placed[swap_router_block_one]).get_router_grid_position_x(), @@ -878,7 +878,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ commit_noc_costs(); // clear the affected blocks - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); // clear the routed traffic flows routed_traffic_flows.clear(); @@ -903,7 +903,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ // now perform the swap //set up the moved blocks datastructure for the test function - blocks_affected.num_moved_blocks = 2; + blocks_affected.moved_blocks.resize(2); blocks_affected.moved_blocks[0].block_num = swap_router_block_one; @@ -1026,7 +1026,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ commit_noc_costs(); // clear the affected blocks - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); /* * Now we will run a test where one of the router clusters we will swap has no traffic flows associated with it. This will make sure whether the test @@ -1039,7 +1039,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ // now perform the swap //set up the moved blocks datastructure for the test function - blocks_affected.num_moved_blocks = 2; + blocks_affected.moved_blocks.resize(2); blocks_affected.moved_blocks[0].block_num = swap_router_block_one; @@ -1127,7 +1127,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ commit_noc_costs(); // clear the affected blocks - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); /* * Now we will run a test where both of the router clusters being swapped @@ -1142,7 +1142,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ // now perform the swap //set up the moved blocks datastructure for the test function - blocks_affected.num_moved_blocks = 2; + blocks_affected.moved_blocks.resize(2); blocks_affected.moved_blocks[0].block_num = swap_router_block_one; @@ -1192,7 +1192,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_ commit_noc_costs(); // clear the affected blocks - clear_move_blocks(blocks_affected); + blocks_affected.clear_move_blocks(); // now verify the test function by comparing the link bandwidths in the noc model (should have been updated by the test function) to the golden set int number_of_links = golden_link_bandwidths.size(); @@ -1584,7 +1584,7 @@ TEST_CASE("test_revert_noc_traffic_flow_routes", "[noc_place_utils]") { //set up the moved blocks datastructure for the test function // this is needed for the test function (it needs to know what blocks were swapped, so it can undo it) - blocks_affected.num_moved_blocks = 2; + blocks_affected.moved_blocks.resize(2); blocks_affected.moved_blocks[0].block_num = swap_router_block_one; blocks_affected.moved_blocks[0].old_loc = t_pl_loc(noc_ctx.noc_model.get_single_noc_router(router_where_cluster_is_placed[swap_router_block_one]).get_router_grid_position_x(),