Skip to content

Fix fixed clusters issue #2495

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

Merged
merged 21 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8f524fb
const ref and c_str
soheilshahrouz Feb 12, 2024
5d01eb3
store movable blocks in placement context
soheilshahrouz Feb 12, 2024
5a11f2b
select random blocks from movable blocks
soheilshahrouz Feb 12, 2024
433b495
make reading placement file more robust
soheilshahrouz Feb 12, 2024
3d9ebdc
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz Feb 24, 2024
03fce64
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz Apr 10, 2024
15cf98e
address PR comments
soheilshahrouz Apr 10, 2024
8bd04e4
add movable_blocks_per_type()
soheilshahrouz Apr 10, 2024
14fd2da
call create_move_generators() after initial_placement()
soheilshahrouz Apr 11, 2024
edfc3cc
remove blocks_per_type() from clustered_netlist
soheilshahrouz Apr 11, 2024
0e0c633
RL agents selects empty block type when all blocks are locked
soheilshahrouz Apr 16, 2024
a26f328
warning message to say why mismatches are ignored
soheilshahrouz Apr 17, 2024
544d175
remove unused #includes
soheilshahrouz Apr 17, 2024
ebabb0d
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz Apr 17, 2024
419324e
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz May 1, 2024
2d34797
replace unordered_map with vector for storing movable blocks for each…
soheilshahrouz May 1, 2024
5625dcb
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz May 31, 2024
05beae3
resolve conflicts with master
soheilshahrouz Jun 15, 2024
6fa53e1
create move generators after movable blocks are determined
soheilshahrouz Jun 24, 2024
8641b86
Merge branch 'master' into fix_fixed_clusters_issue
soheilshahrouz Jun 24, 2024
0abbaa2
update min_chan_width_routing_area_total and min_chan_width_routing_a…
soheilshahrouz Jun 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions vpr/src/base/read_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ void read_place_header(std::ifstream& placement_file,
bool seen_netlist_id = false;
bool seen_grid_dimensions = false;

// store the current position in file
// if an invalid line is read, we might need to return to the beginning of that line
std::streampos file_pos = placement_file.tellg();

while (std::getline(placement_file, line) && (!seen_netlist_id || !seen_grid_dimensions)) { //Parse line-by-line
++lineno;
++lineno;

std::vector<std::string> tokens = vtr::split(line);

Expand All @@ -120,7 +124,7 @@ void read_place_header(std::ifstream& placement_file,
std::string place_netlist_id = tokens[3];
std::string place_netlist_file = tokens[1];

if (place_netlist_id != cluster_ctx.clb_nlist.netlist_id().c_str()) {
if (place_netlist_id != cluster_ctx.clb_nlist.netlist_id()) {
auto msg = vtr::string_fmt(
"The packed netlist file that generated placement (File: '%s' ID: '%s')"
" does not match current netlist (File: '%s' ID: '%s')",
Expand All @@ -146,19 +150,41 @@ void read_place_header(std::ifstream& placement_file,
size_t place_file_width = vtr::atou(tokens[2]);
size_t place_file_height = vtr::atou(tokens[4]);
if (grid.width() != place_file_width || grid.height() != place_file_height) {
vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
"Current FPGA size (%d x %d) is different from size when placement generated (%d x %d)",
grid.width(), grid.height(), place_file_width, place_file_height);
auto msg = vtr::string_fmt(
"Current FPGA size (%d x %d) is different from size when placement generated (%d x %d)",
grid.width(), grid.height(), place_file_width, place_file_height);
if (verify_file_digests) {
vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno, msg.c_str());
} else {
VTR_LOGF_WARN(place_file, lineno, "%s\n", msg.c_str());
}
}

seen_grid_dimensions = true;

} else {
//Unrecognized
vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
"Invalid line '%s' in placement file header",
line.c_str());
auto msg = vtr::string_fmt(
"Invalid line '%s' in placement file header."
"Expected to see netlist filename and device size first.",
line.c_str());

if (verify_file_digests) {
vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno, msg.c_str());
} else {
VTR_LOGF_WARN(place_file, lineno, "%s\n", msg.c_str());
}

if ((tokens.size() == 4 || (tokens.size() > 4 && tokens[4][0] == '#')) ||
(tokens.size() == 5 || (tokens.size() > 5 && tokens[5][0] == '#'))) {
placement_file.seekg(file_pos);
break;
}
}

// store the current position in the file before reading the next line
// we might need to return to this position
file_pos = placement_file.tellg();
}
}

Expand Down
6 changes: 3 additions & 3 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ bool vpr_pack_flow(t_vpr_setup& vpr_setup, const t_arch& arch) {
check_netlist(packer_opts.pack_verbosity);

/* Output the netlist stats to console and optionally to file. */
writeClusteredNetlistStats(vpr_setup.FileNameOpts.write_block_usage.c_str());
writeClusteredNetlistStats(vpr_setup.FileNameOpts.write_block_usage);

// print the total number of used physical blocks for each
// physical block type after finishing the packing stage
Expand Down Expand Up @@ -1424,13 +1424,13 @@ void vpr_analysis(const Netlist<>& net_list,

//Write the post-syntesis netlist
if (vpr_setup.AnalysisOpts.gen_post_synthesis_netlist) {
netlist_writer(atom_ctx.nlist.netlist_name().c_str(), analysis_delay_calc,
netlist_writer(atom_ctx.nlist.netlist_name(), analysis_delay_calc,
vpr_setup.AnalysisOpts);
}

//Write the post-implementation merged netlist
if (vpr_setup.AnalysisOpts.gen_post_implementation_merged_netlist) {
merged_netlist_writer(atom_ctx.nlist.netlist_name().c_str(), analysis_delay_calc, vpr_setup.AnalysisOpts);
merged_netlist_writer(atom_ctx.nlist.netlist_name(), analysis_delay_calc, vpr_setup.AnalysisOpts);
}

//Do power analysis
Expand Down
5 changes: 5 additions & 0 deletions vpr/src/base/vpr_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,11 @@ struct PlacementContext : public Context {
///@brief The pl_macros array stores all the placement macros (usually carry chains).
std::vector<t_pl_macro> pl_macros;

///@brief Stores ClusterBlockId of all movable clustered blocks.
std::vector<ClusterBlockId> movable_blocks;

std::unordered_map<int, std::vector<ClusterBlockId>> movable_blocks_per_type;

/**
* @brief Compressed grid space for each block type
*
Expand Down
67 changes: 66 additions & 1 deletion vpr/src/place/initial_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ static void place_all_blocks(const t_placer_opts& placer_opts, vtr::vector<Clust
*/
static void check_initial_placement_legality();

/**
* @brief Fills movable_blocks in global PlacementContext
*/
static void fill_movable_blocks();

static void check_initial_placement_legality() {
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.placement();
Expand All @@ -223,6 +228,28 @@ static void check_initial_placement_legality() {
"If VPR was run with floorplan constraints, the constraints may be too tight.\n",
unplaced_blocks);
}

for (auto movable_blk_id : place_ctx.movable_blocks) {
if (place_ctx.block_locs[movable_blk_id].is_fixed) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Fixed block was mistakenly marked as movable during initial placement.\n");
}
}

for (const auto& blk_type : place_ctx.movable_blocks_per_type) {
int logical_block_type = blk_type.first;
const auto& movable_blocks = blk_type.second;
for (auto movable_blk_id : movable_blocks) {
if (place_ctx.block_locs[movable_blk_id].is_fixed) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Fixed block of logical type %d was mistakenly marked as movable during initial placement.\n",
logical_block_type);
}
if (cluster_ctx.clb_nlist.block_type(movable_blk_id)->index != logical_block_type) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Clustered block of logical type %d was mistakenly marked as logical type %d.\n",
cluster_ctx.clb_nlist.block_type(movable_blk_id)->index,
logical_block_type);
}
}
}
}

bool is_block_placed(ClusterBlockId blk_id) {
Expand Down Expand Up @@ -1093,6 +1120,41 @@ bool place_one_block(const ClusterBlockId& blk_id,
return placed_macro;
}

static void fill_movable_blocks() {
auto& place_ctx = g_vpr_ctx.mutable_placement();
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& device_ctx = g_vpr_ctx.device();

place_ctx.movable_blocks.clear();
place_ctx.movable_blocks_per_type.clear();

std::vector<int> available_logical_blk_types;

for (const auto& logical_blk_type : device_ctx.logical_block_types) {
//ignore empty type
if (logical_blk_type.index == 0) {
continue;
}

const auto& blk_per_type = cluster_ctx.clb_nlist.blocks_per_type(logical_blk_type);

if (!blk_per_type.empty()) {
available_logical_blk_types.push_back(logical_blk_type.index);
}
}

// iterate over all clustered blocks and store block ids of movable ones
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
const auto& loc = place_ctx.block_locs[blk_id];
if (!loc.is_fixed) {
place_ctx.movable_blocks.push_back(blk_id);

const t_logical_block_type_ptr block_type = cluster_ctx.clb_nlist.block_type(blk_id);
place_ctx.movable_blocks_per_type[block_type->index].push_back(blk_id);
}
}
}

void initial_placement(const t_placer_opts& placer_opts,
const char* constraints_file,
const t_noc_opts& noc_opts) {
Expand All @@ -1109,7 +1171,7 @@ void initial_placement(const t_placer_opts& placer_opts,
propagate_place_constraints();

/*Mark the blocks that have already been locked to one spot via floorplan constraints
* as fixed so they do not get moved during initial placement or later during the simulated annealing stage of placement*/
* as fixed, so they do not get moved during initial placement or later during the simulated annealing stage of placement*/
mark_fixed_blocks();

if (noc_opts.noc) {
Expand All @@ -1123,6 +1185,9 @@ void initial_placement(const t_placer_opts& placer_opts,
//Place all blocks
place_all_blocks(placer_opts, block_scores, placer_opts.pad_loc_type, constraints_file);


fill_movable_blocks();

//if any blocks remain unplaced, print an error
check_initial_placement_legality();

Expand Down
78 changes: 21 additions & 57 deletions vpr/src/place/move_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,80 +590,44 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& /* placer_opts */,
return b_from;
}

//Pick a random block to be swapped with another random block.
//Pick a random movable block to be swapped with another random block.
//If none is found return ClusterBlockId::INVALID()
ClusterBlockId pick_from_block() {
/* Some blocks may be fixed, and should never be moved from their *
* initial positions. If we randomly selected such a block try *
* another random block. *
* *
* We need to track the blocks we have tried to avoid an infinite *
* loop if all blocks are fixed. */
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.mutable_placement();

std::unordered_set<ClusterBlockId> tried_from_blocks;

//Keep selecting random blocks as long as there are any untried blocks
//Can get slow if there are many blocks but only a few (or none) can move
while (tried_from_blocks.size() < cluster_ctx.clb_nlist.blocks().size()) {
//Pick a block at random
ClusterBlockId b_from = ClusterBlockId(vtr::irand((int)cluster_ctx.clb_nlist.blocks().size() - 1));

//Record it as tried
tried_from_blocks.insert(b_from);

if (place_ctx.block_locs[b_from].is_fixed) {
continue; //Fixed location, try again
}
// get the number of movable clustered blocks
const size_t n_movable_blocks = place_ctx.movable_blocks.size();

//Found a movable block
if (n_movable_blocks > 0) {
//Pick a movable block at random and return it
auto b_from = ClusterBlockId(vtr::irand((int)n_movable_blocks - 1));
return b_from;
} else {
//No movable blocks found
return ClusterBlockId::INVALID();
}

//No movable blocks found
return ClusterBlockId::INVALID();
}

//Pick a random block with a specific blk_type to be swapped with another random block.
//Pick a random movable block with a specific blk_type to be swapped with another random block.
//If none is found return ClusterBlockId::INVALID()
ClusterBlockId pick_from_block(const int logical_blk_type_index) {
/* Some blocks may be fixed, and should never be moved from their *
* initial positions. If we randomly selected such a block try *
* another random block. *
* *
* We need to track the blocks we have tried to avoid an infinite *
* loop if all blocks are fixed. */
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.mutable_placement();
t_logical_block_type blk_type_temp;
blk_type_temp.index = logical_blk_type_index;
const auto& blocks_per_type = cluster_ctx.clb_nlist.blocks_per_type(blk_type_temp);

//no blocks with this type is available
if (blocks_per_type.empty()) {
return ClusterBlockId::INVALID();
}

std::unordered_set<ClusterBlockId> tried_from_blocks;
auto found_blocks = place_ctx.movable_blocks_per_type.find(logical_blk_type_index);
if (found_blocks != place_ctx.movable_blocks_per_type.end()) {
const auto& blocks_per_type = found_blocks->second;
//no blocks with this type is movable
if (blocks_per_type.empty()) {
return ClusterBlockId::INVALID();
}

//Keep selecting random blocks as long as there are any untried blocks with type "blk_type"
//Can get slow if there are many blocks but only a few (or none) can move
while (tried_from_blocks.size() < blocks_per_type.size()) {
//Pick a block at random
ClusterBlockId b_from = ClusterBlockId(blocks_per_type[vtr::irand((int)blocks_per_type.size() - 1)]);
//Record it as tried
tried_from_blocks.insert(b_from);
auto b_from = ClusterBlockId(blocks_per_type[vtr::irand((int)blocks_per_type.size() - 1)]);

if (place_ctx.block_locs[b_from].is_fixed) {
continue; //Fixed location, try again
}
//Found a movable block
// return the movable block of the given type
return b_from;
}

//No movable blocks found
//Unreachable statement
return ClusterBlockId::INVALID();
}

Expand Down Expand Up @@ -1077,9 +1041,9 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type,
else
possibilities = delta_cx;

while (!legal && (int)tried_cx_to.size() < possibilities) { //Until legal or all possibilities exhaused
while (!legal && (int)tried_cx_to.size() < possibilities) { //Until legal or all possibilities exhausted
//Pick a random x-location within [min_cx, max_cx],
//until we find a legal swap, or have exhuasted all possiblites
//until we find a legal swap, or have exhausted all possibilities
to_loc.x = search_range.xmin + vtr::irand(delta_cx);

VTR_ASSERT(to_loc.x >= search_range.xmin);
Expand Down