Skip to content

Commit

Permalink
Merge pull request #2659 from verilog-to-routing/placement_move_primi…
Browse files Browse the repository at this point in the history
…tive_robert_refactoring

[vpr][place] Placement move primitive refactoring
  • Loading branch information
vaughnbetz authored Jul 29, 2024
2 parents edce4b4 + c7cbf33 commit 36ed2b2
Show file tree
Hide file tree
Showing 13 changed files with 516 additions and 515 deletions.
2 changes: 1 addition & 1 deletion vpr/src/place/initial_noc_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
89 changes: 61 additions & 28 deletions vpr/src/place/move_transactions.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
Expand All @@ -15,36 +27,57 @@ 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;
}

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_loc> t_pl_blocks_to_be_moved::t_pl_blocks_to_be_moved::determine_locations_emptied_by_move() {
std::set<t_pl_loc> moved_from_set;
std::set<t_pl_loc> 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<t_pl_loc> 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();
auto& device_ctx = g_vpr_ctx.device();

//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;
Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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();
}
41 changes: 26 additions & 15 deletions vpr/src/place/move_transactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand All @@ -25,41 +32,45 @@ 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] *
* affected_pins: pins affected by this move (used to *
* 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<t_pl_loc> determine_locations_emptied_by_move();

int num_moved_blocks = 0;
std::vector<t_pl_moved_block> moved_blocks;
std::unordered_set<t_pl_loc> moved_from;
std::unordered_set<t_pl_loc> moved_to;

std::vector<ClusterPinId> 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);

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
36 changes: 8 additions & 28 deletions vpr/src/place/move_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "move_utils.h"

#include "move_transactions.h"
#include "place_util.h"
#include "globals.h"

Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<int> affected_macros;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<t_pl_loc> determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& blocks_affected) {
std::set<t_pl_loc> moved_from;
std::set<t_pl_loc> 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<t_pl_loc> 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) {
Expand Down
2 changes: 0 additions & 2 deletions vpr/src/place/move_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<t_pl_loc> 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.
*
Expand Down
Loading

0 comments on commit 36ed2b2

Please sign in to comment.