placer1: Allow swapping chains with other chains
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
7c82a04df5
commit
f119f56e63
@ -119,6 +119,12 @@ class SAPlacer
|
|||||||
region_bounds[r->name] = bb;
|
region_bounds[r->name] = bb;
|
||||||
}
|
}
|
||||||
build_port_index();
|
build_port_index();
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo *ci = cell.second.get();
|
||||||
|
if (ci->cluster == ClusterId())
|
||||||
|
continue;
|
||||||
|
cluster2cell[ci->cluster].push_back(ci);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~SAPlacer()
|
~SAPlacer()
|
||||||
@ -616,56 +622,99 @@ class SAPlacer
|
|||||||
bool try_swap_chain(CellInfo *cell, BelId newBase)
|
bool try_swap_chain(CellInfo *cell, BelId newBase)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<CellInfo *, Loc>> cell_rel;
|
std::vector<std::pair<CellInfo *, Loc>> cell_rel;
|
||||||
pool<IdString> cells;
|
dict<IdString, BelId> moved_cells;
|
||||||
std::vector<std::pair<CellInfo *, BelId>> moves_made;
|
|
||||||
std::vector<std::pair<CellInfo *, BelId>> dest_bels;
|
std::vector<std::pair<CellInfo *, BelId>> dest_bels;
|
||||||
double delta = 0;
|
double delta = 0;
|
||||||
int orig_share_cost = total_net_share;
|
int orig_share_cost = total_net_share;
|
||||||
moveChange.reset(this);
|
moveChange.reset(this);
|
||||||
#if 0
|
#if CHAIN_DEBUG
|
||||||
if (ctx->debug)
|
|
||||||
log_info("finding cells for chain swap %s\n", cell->name.c_str(ctx));
|
log_info("finding cells for chain swap %s\n", cell->name.c_str(ctx));
|
||||||
#endif
|
#endif
|
||||||
if (!ctx->getClusterPlacement(cell->cluster, newBase, dest_bels))
|
std::queue<std::pair<ClusterId, BelId>> displaced_clusters;
|
||||||
return false;
|
displaced_clusters.emplace(cell->cluster, newBase);
|
||||||
|
while (!displaced_clusters.empty()) {
|
||||||
for (const auto &db : dest_bels)
|
auto cursor = displaced_clusters.front();
|
||||||
cells.insert(db.first->name);
|
displaced_clusters.pop();
|
||||||
|
if (!ctx->getClusterPlacement(cursor.first, cursor.second, dest_bels))
|
||||||
|
goto swap_fail;
|
||||||
|
for (const auto &db : dest_bels) {
|
||||||
|
// Ensure the cluster is ripped up
|
||||||
|
if (db.first->bel != BelId()) {
|
||||||
|
moved_cells[db.first->name] = db.first->bel;
|
||||||
|
#if CHAIN_DEBUG
|
||||||
|
log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(db.first->bel));
|
||||||
|
#endif
|
||||||
|
ctx->unbindBel(db.first->bel);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const auto &db : dest_bels) {
|
for (const auto &db : dest_bels) {
|
||||||
CellInfo *bound = ctx->getBoundBelCell(db.second);
|
CellInfo *bound = ctx->getBoundBelCell(db.second);
|
||||||
// We don't consider swapping chains with other chains, at least for the time being - unless it is
|
BelId old_bel = moved_cells.at(db.first->name);
|
||||||
// part of this chain
|
if (!ctx->checkBelAvail(old_bel) && bound != nullptr) {
|
||||||
if (bound != nullptr && !cells.count(bound->name) &&
|
// Simple swap no longer possible
|
||||||
(bound->belStrength >= STRENGTH_STRONG || bound->cluster != ClusterId()))
|
goto swap_fail;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (bound != nullptr)
|
|
||||||
if (!ctx->isValidBelForCellType(bound->type, db.first->bel))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
#if 0
|
if (bound != nullptr) {
|
||||||
if (ctx->debug)
|
if (moved_cells.count(bound->name)) {
|
||||||
log_info("trying chain swap %s\n", cell->name.c_str(ctx));
|
// Don't move a cell multiple times in the same go
|
||||||
|
goto swap_fail;
|
||||||
|
} else if (bound->belStrength > STRENGTH_STRONG) {
|
||||||
|
goto swap_fail;
|
||||||
|
} else if (bound->cluster != ClusterId()) {
|
||||||
|
// Displace the entire cluster
|
||||||
|
Loc old_loc = ctx->getBelLocation(old_bel);
|
||||||
|
Loc bound_loc = ctx->getBelLocation(bound->bel);
|
||||||
|
Loc root_loc = ctx->getBelLocation(ctx->getClusterRootCell(bound->cluster)->bel);
|
||||||
|
BelId new_root = ctx->getBelByLocation(Loc(old_loc.x + (root_loc.x - bound_loc.x),
|
||||||
|
old_loc.y + (root_loc.y - bound_loc.y),
|
||||||
|
old_loc.z + (root_loc.z - bound_loc.z)));
|
||||||
|
if (new_root == BelId())
|
||||||
|
goto swap_fail;
|
||||||
|
for (auto cluster_cell : cluster2cell.at(bound->cluster)) {
|
||||||
|
moved_cells[cluster_cell->name] = cluster_cell->bel;
|
||||||
|
#if CHAIN_DEBUG
|
||||||
|
log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(cluster_cell->bel));
|
||||||
#endif
|
#endif
|
||||||
// <cell, oldBel>
|
ctx->unbindBel(cluster_cell->bel);
|
||||||
for (const auto &db : dest_bels) {
|
|
||||||
BelId oldBel = swap_cell_bels(db.first, db.second);
|
|
||||||
moves_made.emplace_back(std::make_pair(db.first, oldBel));
|
|
||||||
CellInfo *bound = ctx->getBoundBelCell(oldBel);
|
|
||||||
add_move_cell(moveChange, db.first, oldBel);
|
|
||||||
if (bound != nullptr)
|
|
||||||
add_move_cell(moveChange, bound, db.second);
|
|
||||||
}
|
}
|
||||||
for (const auto &mm : moves_made) {
|
displaced_clusters.emplace(bound->cluster, new_root);
|
||||||
if (!ctx->isBelLocationValid(mm.first->bel) || !mm.first->testRegion(mm.first->bel))
|
} else {
|
||||||
goto swap_fail;
|
// Just a single cell to move
|
||||||
if (!ctx->isBelLocationValid(mm.second))
|
moved_cells[bound->name] = bound->bel;
|
||||||
goto swap_fail;
|
#if CHAIN_DEBUG
|
||||||
CellInfo *bound = ctx->getBoundBelCell(mm.second);
|
log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(bound->bel));
|
||||||
if (bound && !bound->testRegion(bound->bel))
|
log_info("%d bind %s %s\n", __LINE__, ctx->nameOfBel(old_bel), ctx->nameOf(bound));
|
||||||
|
#endif
|
||||||
|
ctx->unbindBel(bound->bel);
|
||||||
|
ctx->bindBel(old_bel, bound, STRENGTH_WEAK);
|
||||||
|
add_move_cell(moveChange, bound, moved_cells.at(bound->name));
|
||||||
|
if (cfg.netShareWeight > 0)
|
||||||
|
update_nets_by_tile(bound, ctx->getBelLocation(moved_cells.at(bound->name)),
|
||||||
|
ctx->getBelLocation(old_bel));
|
||||||
|
}
|
||||||
|
} else if (!ctx->checkBelAvail(db.second)) {
|
||||||
goto swap_fail;
|
goto swap_fail;
|
||||||
}
|
}
|
||||||
|
// All those shenanigans should now mean the target bel is free to use
|
||||||
|
#if CHAIN_DEBUG
|
||||||
|
log_info("%d bind %s %s\n", __LINE__, ctx->nameOfBel(db.second), ctx->nameOf(db.first));
|
||||||
|
#endif
|
||||||
|
ctx->bindBel(db.second, db.first, STRENGTH_WEAK);
|
||||||
|
add_move_cell(moveChange, db.first, moved_cells.at(db.first->name));
|
||||||
|
if (cfg.netShareWeight > 0)
|
||||||
|
update_nets_by_tile(db.first, ctx->getBelLocation(moved_cells.at(db.first->name)),
|
||||||
|
ctx->getBelLocation(db.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &mm : moved_cells) {
|
||||||
|
CellInfo *cell = ctx->cells.at(mm.first).get();
|
||||||
|
if (!ctx->isBelLocationValid(cell->bel) || !cell->testRegion(cell->bel))
|
||||||
|
goto swap_fail;
|
||||||
|
}
|
||||||
|
#if CHAIN_DEBUG
|
||||||
|
log_info("legal chain swap %s\n", cell->name.c_str(ctx));
|
||||||
|
#endif
|
||||||
compute_cost_changes(moveChange);
|
compute_cost_changes(moveChange);
|
||||||
delta = lambda * (moveChange.timing_delta / last_timing_cost) +
|
delta = lambda * (moveChange.timing_delta / last_timing_cost) +
|
||||||
(1 - lambda) * (double(moveChange.wirelen_delta) / last_wirelen_cost);
|
(1 - lambda) * (double(moveChange.wirelen_delta) / last_wirelen_cost);
|
||||||
@ -675,10 +724,9 @@ class SAPlacer
|
|||||||
}
|
}
|
||||||
n_move++;
|
n_move++;
|
||||||
// SA acceptance criteria
|
// SA acceptance criteria
|
||||||
if (delta < 0 || (temp > 1e-9 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
|
if (delta < 0 || (temp > 1e-8 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
|
||||||
n_accept++;
|
n_accept++;
|
||||||
#if 0
|
#if CHAIN_DEBUG
|
||||||
if (ctx->debug)
|
|
||||||
log_info("accepted chain swap %s\n", cell->name.c_str(ctx));
|
log_info("accepted chain swap %s\n", cell->name.c_str(ctx));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@ -687,8 +735,15 @@ class SAPlacer
|
|||||||
commit_cost_changes(moveChange);
|
commit_cost_changes(moveChange);
|
||||||
return true;
|
return true;
|
||||||
swap_fail:
|
swap_fail:
|
||||||
for (const auto &entry : boost::adaptors::reverse(moves_made))
|
for (auto cell_pair : moved_cells) {
|
||||||
swap_cell_bels(entry.first, entry.second);
|
CellInfo *cell = ctx->cells.at(cell_pair.first).get();
|
||||||
|
if (cell->bel != BelId())
|
||||||
|
ctx->unbindBel(cell->bel);
|
||||||
|
}
|
||||||
|
for (auto cell_pair : moved_cells) {
|
||||||
|
CellInfo *cell = ctx->cells.at(cell_pair.first).get();
|
||||||
|
ctx->bindBel(cell_pair.second, cell, STRENGTH_WEAK);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,6 +1238,9 @@ class SAPlacer
|
|||||||
// Fast lookup for cell port to net user index
|
// Fast lookup for cell port to net user index
|
||||||
dict<std::pair<IdString, IdString>, size_t> fast_port_to_user;
|
dict<std::pair<IdString, IdString>, size_t> fast_port_to_user;
|
||||||
|
|
||||||
|
// Fast lookup for cell to clusters
|
||||||
|
dict<ClusterId, std::vector<CellInfo *>> cluster2cell;
|
||||||
|
|
||||||
// Wirelength and timing cost at last and current iteration
|
// Wirelength and timing cost at last and current iteration
|
||||||
wirelen_t last_wirelen_cost, curr_wirelen_cost;
|
wirelen_t last_wirelen_cost, curr_wirelen_cost;
|
||||||
double last_timing_cost, curr_timing_cost;
|
double last_timing_cost, curr_timing_cost;
|
||||||
|
Loading…
Reference in New Issue
Block a user