-
Notifications
You must be signed in to change notification settings - Fork 400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[vpr][place] Placement move primitive refactoring #2659
[vpr][place] Placement move primitive refactoring #2659
Conversation
2e19dc4
to
d8fe932
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments for all files other than net_cost_handler.cpp/.h
vpr/src/place/move_transactions.h
Outdated
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; | ||
size_t get_size_and_increment(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add doxygen documentation for this method.
* 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is probably a good idea to delete the default constructor if the objects of this type are always expected to be initialzed with a non-zero capacity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also delete the copy constructor to avoid unintended copies.
vpr/src/place/move_transactions.cpp
Outdated
|
||
t_pl_blocks_to_be_moved::t_pl_blocks_to_be_moved(size_t max_blocks){ | ||
moved_blocks.reserve(max_blocks); | ||
moved_blocks.resize(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is calling resize() necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is not necessary, the vector default constructor will set size to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is not necessary, the vector default constructor will set size to 0.
So I think it is better to remove it
vpr/src/place/move_transactions.cpp
Outdated
@@ -40,11 +51,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 auto& block : blocks_affected.moved_blocks) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the element type (t_pl_moved_block) is explicitly specified instead of using auto keyword, the code would be more readable, especially that the type name is not that long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also suggest that the element name changes from "block" to "moved_block"
vpr/src/place/move_utils.cpp
Outdated
@@ -488,12 +488,12 @@ std::set<t_pl_loc> determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& | |||
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) { | |||
for (const auto& block : blocks_affected.moved_blocks) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using the type name explicitly makes the code more readable
vpr/src/place/move_utils.cpp
Outdated
@@ -488,12 +488,12 @@ std::set<t_pl_loc> determine_locations_emptied_by_move(t_pl_blocks_to_be_moved& | |||
std::set<t_pl_loc> moved_from; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blocks_affected can be passed by const reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function can be implemented as member function in t_pl_blocks_to_be_moved
vpr/src/place/place_constraints.h
Outdated
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 auto& block : blocks_affected.moved_blocks) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit type name make the code more readable
vpr/src/place/place.cpp
Outdated
@@ -1378,7 +1378,7 @@ 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( | |||
find_affected_nets_and_update_costs( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if this function call is written in two lines, it would be more readable:
find_affected_nets_and_update_costs(place_algorithm, delay_model, criticalities,
blocks_affected, bb_delta_c, timing_delta_c);
vpr/src/place/place.cpp
Outdated
@@ -1569,7 +1568,7 @@ static e_move_result try_swap(const t_annealing_state* state, | |||
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; | |||
// std::cout << "Group move delta cost: " << delta_c << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove the else statement
I used it for debugging, but it somehow found its way into master
inet_cost, proposed_net_cost, and bb_updated_before grouped in a struct. bb_updated_before renamed to bb_update_status.
vpr/src/place/net_cost_handler.cpp
Outdated
public: | ||
void init(size_t num_nets, bool cube_bb); | ||
void get_non_updatable_bb(const ClusterNetId& net); | ||
bool is_driver(const t_physical_tile_type_ptr& blk_type, const ClusterPinId& blk_pin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the implementation of this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ClusterPinId is an integer. Passing a pointer and an integer by reference only make the code harder to read. These arguments are not large objects and passing them by value does not introduce any overhead.
static vtr::Matrix<int> ts_layer_sink_pin_count; | ||
/* [0...num_afftected_nets] -> net_id of the affected nets */ | ||
static std::vector<ClusterNetId> ts_nets_to_update; | ||
struct TSInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete non-default constructors to avoid copying or moving objects of types declared in this namesapce.
vpr/src/place/net_cost_handler.cpp
Outdated
const PlaceDelayModel* delay_model, | ||
const PlacerCriticalities* criticalities, | ||
const ClusterBlockId& blk_id, | ||
const ClusterPinId& pin_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass ClusterBlockId and ClusterPinId by value. These types are just integers
vpr/src/place/net_cost_handler.cpp
Outdated
* @brief This class is used to hide control flows needed to distinguish 2d and 3d placement | ||
*/ | ||
class BBUpdater { | ||
bool cube_bb = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is better to somehow differentiate member varaibles from arguments and local variable by naming them differently. For exmaple: cube_bb_ or m_cube_bb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using private keyword make the code more readable.
vpr/src/place/net_cost_handler.cpp
Outdated
} | ||
|
||
void BBUpdater::get_non_updatable_bb(const ClusterNetId& net) { | ||
if (cube_bb) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes single line if/else statement have braces and sometimes they don't. It is better to follow a consistent style. I think always using braces is better, even for single line if/else statements.
vpr/src/place/net_cost_handler.cpp
Outdated
size_t last_size = ts_info.ts_nets_to_update.size(); | ||
VTR_ASSERT(last_size < ts_info.ts_nets_to_update.capacity()); | ||
ts_info.ts_nets_to_update.resize(last_size + 1); | ||
ts_info.ts_nets_to_update[last_size] = net; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use push_back()
?
The assertion can also compare capacity and size before adding the new element.
vpr/src/place/net_cost_handler.cpp
Outdated
const PlaceDelayModel* delay_model, | ||
const PlacerCriticalities* criticalities, | ||
const ClusterBlockId& blk_id, | ||
const ClusterPinId& pin_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass ClusterBlockId and ClusterPinId types by value
vpr/src/place/net_cost_handler.cpp
Outdated
ts_layer_sink_pin_count[size_t(net_id)]); | ||
} | ||
static void set_bb_delta_cost(double& bb_delta_c) { | ||
for (const auto& ts_net: ts_info.ts_nets_to_update) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ClusterNetId is an integer, and it is not necessary to iterate over elements of this time by reference.
Using the type name explicitly make the code more readable.
vpr/src/place/net_cost_handler.cpp
Outdated
for (int inet_affected = 0; inet_affected < num_nets_affected; | ||
inet_affected++) { | ||
ClusterNetId net_id = ts_nets_to_update[inet_affected]; | ||
for (const auto& ts_net : ts_info.ts_nets_to_update) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to previous comments.
vpr/src/place/net_cost_handler.cpp
Outdated
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 auto& ts_net : ts_info.ts_nets_to_update) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type name
by value
d8fe932
to
c7cbf33
Compare
Thanks! I'm going to merge this, but I have one more comment you can address in another PR: (line 32 of move_transactions.cpp) |
In "net_cost_handler.cpp", there are three related global variables:
net_cost
,proposed_net_cost
, andbb_updated_before
. We can organize these by putting them into a struct calledt_net_cost_data
. You may also renamebb_updated_before
tobb_update_status
.In placement, we use two methods to update the bounding box: the 3D bounding box (also used for 2D architecture) and the per-layer bounding box. When a swap happens, multiple variables are updated, indicated by the
ts
(temporary swap) prefix. We can put all these variables into a class. Since only a subset is used depending on the bounding box type, you can examine how these variables are updated throughout the file and write methods for this class to update the appropriate ones.For runtime reasons, we initialize
ts_nets_to_update
to the number of nets in the netlist and use a variablenum_affected_nets
to indicate how many entries are valid. You can experiment to see how runtime is affected if we remove this variable and just reserve elements in this vector and use.size()
.The same approach is used for
std::vector<t_pl_moved_block>& moved_blocks
, which has as many entries as the total number of blocks, and we pass an integer to show how many entries are valid. You can also run an experiment to see how much runtime is affected if you remove this.QoR bitcoin_miner_stratixiv_arch_timing (final wire length remains the same):
baseline: packing: 354.64, placement: 3706.12, routing 409.20, vpr flow: 4930.11
modified: packing: 356.83, placement: 3777.65, routing 412.23, vpr flow: 4994.61