placer1: Allow chain position swaps after legalisation
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
3650c8a0e7
commit
23306c163f
@ -304,7 +304,7 @@ class ConstraintLegaliseWorker
|
|||||||
// Set the strength to locked on all cells in chain
|
// Set the strength to locked on all cells in chain
|
||||||
void lockdown_chain(CellInfo *root)
|
void lockdown_chain(CellInfo *root)
|
||||||
{
|
{
|
||||||
root->belStrength = STRENGTH_LOCKED;
|
root->belStrength = STRENGTH_STRONG;
|
||||||
for (auto child : root->constr_children)
|
for (auto child : root->constr_children)
|
||||||
lockdown_chain(child);
|
lockdown_chain(child);
|
||||||
}
|
}
|
||||||
@ -380,7 +380,7 @@ class ConstraintLegaliseWorker
|
|||||||
rippedCells.insert(confl_cell->name);
|
rippedCells.insert(confl_cell->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_LOCKED);
|
ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_STRONG);
|
||||||
rippedCells.erase(cp.first);
|
rippedCells.erase(cp.first);
|
||||||
}
|
}
|
||||||
for (auto cp : solution) {
|
for (auto cp : solution) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "placer1.h"
|
#include "placer1.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -42,6 +43,8 @@
|
|||||||
#include "place_common.h"
|
#include "place_common.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, std::size_t>>
|
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, std::size_t>>
|
||||||
{
|
{
|
||||||
@ -152,6 +155,8 @@ class SAPlacer
|
|||||||
|
|
||||||
// Sort to-place cells for deterministic initial placement
|
// Sort to-place cells for deterministic initial placement
|
||||||
std::vector<CellInfo *> autoplaced;
|
std::vector<CellInfo *> autoplaced;
|
||||||
|
std::vector<CellInfo *> chain_basis;
|
||||||
|
|
||||||
for (auto &cell : ctx->cells) {
|
for (auto &cell : ctx->cells) {
|
||||||
CellInfo *ci = cell.second.get();
|
CellInfo *ci = cell.second.get();
|
||||||
if (ci->bel == BelId()) {
|
if (ci->bel == BelId()) {
|
||||||
@ -219,6 +224,13 @@ class SAPlacer
|
|||||||
if (try_bel != BelId() && try_bel != cell->bel)
|
if (try_bel != BelId() && try_bel != cell->bel)
|
||||||
try_swap_position(cell, try_bel);
|
try_swap_position(cell, try_bel);
|
||||||
}
|
}
|
||||||
|
// Also try swapping chains, if applicable
|
||||||
|
for (auto cb : chain_basis) {
|
||||||
|
Loc chain_base_loc = ctx->getBelLocation(cb->bel);
|
||||||
|
BelId try_base = random_bel_for_cell(cb, chain_base_loc.z);
|
||||||
|
if (try_base != BelId() && try_base != cb->bel)
|
||||||
|
try_swap_chain(cb, try_base);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr_wirelen_cost < min_wirelen) {
|
if (curr_wirelen_cost < min_wirelen) {
|
||||||
@ -276,8 +288,11 @@ class SAPlacer
|
|||||||
if (legalise_relative_constraints(ctx)) {
|
if (legalise_relative_constraints(ctx)) {
|
||||||
// Only increase temperature if something was moved
|
// Only increase temperature if something was moved
|
||||||
autoplaced.clear();
|
autoplaced.clear();
|
||||||
|
chain_basis.clear();
|
||||||
for (auto cell : sorted(ctx->cells)) {
|
for (auto cell : sorted(ctx->cells)) {
|
||||||
if (cell.second->belStrength < STRENGTH_STRONG)
|
if (cell.second->belStrength <= STRENGTH_STRONG && cell.second->constr_parent == nullptr && !cell.second->constr_children.empty())
|
||||||
|
chain_basis.push_back(cell.second);
|
||||||
|
else if (cell.second->belStrength < STRENGTH_STRONG)
|
||||||
autoplaced.push_back(cell.second);
|
autoplaced.push_back(cell.second);
|
||||||
}
|
}
|
||||||
temp = post_legalise_temp;
|
temp = post_legalise_temp;
|
||||||
@ -458,9 +473,101 @@ class SAPlacer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_constrained(CellInfo *cell) {
|
||||||
|
return cell->constr_parent != nullptr || !cell->constr_children.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap the Bel of a cell with another, return the original location
|
||||||
|
BelId swap_cell_bels(CellInfo *cell, BelId newBel) {
|
||||||
|
BelId oldBel = cell->bel;
|
||||||
|
CellInfo *bound = ctx->getBoundBelCell(newBel);
|
||||||
|
if (bound != nullptr)
|
||||||
|
ctx->unbindBel(newBel);
|
||||||
|
ctx->unbindBel(oldBel);
|
||||||
|
ctx->bindBel(newBel, cell, is_constrained(cell) ? STRENGTH_STRONG : STRENGTH_WEAK);
|
||||||
|
if (bound != nullptr)
|
||||||
|
ctx->bindBel(oldBel, bound, is_constrained(bound) ? STRENGTH_STRONG : STRENGTH_WEAK);
|
||||||
|
return oldBel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover the relative positions of all cells in a chain
|
||||||
|
void discover_chain(Loc baseLoc, CellInfo *cell, std::vector<std::pair<CellInfo*, Loc>> &cell_rel) {
|
||||||
|
Loc cellLoc = ctx->getBelLocation(cell->bel);
|
||||||
|
Loc rel{cellLoc.x - baseLoc.x, cellLoc.y - baseLoc.y, cellLoc.z};
|
||||||
|
cell_rel.emplace_back(std::make_pair(cell, rel));
|
||||||
|
for (auto child : cell->constr_children)
|
||||||
|
discover_chain(baseLoc, child, cell_rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to swap a chain with a non-chain
|
||||||
|
bool try_swap_chain(CellInfo *cell, BelId newBase) {
|
||||||
|
std::vector<std::pair<CellInfo *, Loc>> cell_rel;
|
||||||
|
std::unordered_set<IdString> cells;
|
||||||
|
std::vector<std::pair<CellInfo*, BelId>> moves_made;
|
||||||
|
std::vector<std::pair<CellInfo *, BelId>> dest_bels;
|
||||||
|
double delta = 0;
|
||||||
|
moveChange.reset();
|
||||||
|
log_info("finding cells for chain swap %s\n", cell->name.c_str(ctx));
|
||||||
|
|
||||||
|
Loc baseLoc = ctx->getBelLocation(cell->bel);
|
||||||
|
discover_chain(baseLoc, cell, cell_rel);
|
||||||
|
Loc newBaseLoc = ctx->getBelLocation(newBase);
|
||||||
|
NPNR_ASSERT(newBaseLoc.z == baseLoc.z);
|
||||||
|
for (const auto &cr : cell_rel)
|
||||||
|
cells.insert(cr.first->name);
|
||||||
|
|
||||||
|
for (const auto &cr : cell_rel) {
|
||||||
|
Loc targetLoc = {newBaseLoc.x + cr.second.x, newBaseLoc.y + cr.second.y, cr.second.z};
|
||||||
|
BelId targetBel = ctx->getBelByLocation(targetLoc);
|
||||||
|
if (targetBel == BelId())
|
||||||
|
return false;
|
||||||
|
if (ctx->getBelType(targetBel) != cell->type)
|
||||||
|
return false;
|
||||||
|
CellInfo *bound = ctx->getBoundBelCell(targetBel);
|
||||||
|
// We don't consider swapping chains with other chains, at least for the time being - unless it is
|
||||||
|
// part of this chain
|
||||||
|
if (bound != nullptr && !cells.count(bound->name) && (bound->belStrength >= STRENGTH_STRONG || is_constrained(bound)))
|
||||||
|
return false;
|
||||||
|
dest_bels.emplace_back(std::make_pair(cr.first, targetBel));
|
||||||
|
}
|
||||||
|
log_info("trying chain swap %s\n", cell->name.c_str(ctx));
|
||||||
|
// <cell, oldBel>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
for (const auto &mm : moves_made) {
|
||||||
|
if (!ctx->isBelLocationValid(mm.first->bel))
|
||||||
|
goto swap_fail;
|
||||||
|
if (!ctx->isBelLocationValid(mm.second))
|
||||||
|
goto swap_fail;
|
||||||
|
add_move_cell(moveChange, mm.first, mm.second);
|
||||||
|
CellInfo *bound = ctx->getBoundBelCell(mm.second);
|
||||||
|
if (bound != nullptr)
|
||||||
|
add_move_cell(moveChange, bound, mm.first->bel);
|
||||||
|
}
|
||||||
|
compute_cost_changes(moveChange);
|
||||||
|
delta = lambda * (moveChange.timing_delta / last_timing_cost) +
|
||||||
|
(1 - lambda) * (double(moveChange.wirelen_delta) / last_wirelen_cost);
|
||||||
|
n_move++;
|
||||||
|
// SA acceptance criterea
|
||||||
|
if (delta < 0 || (temp > 1e-8 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
|
||||||
|
n_accept++;
|
||||||
|
log_info("accepted chain swap %s\n", cell->name.c_str(ctx));
|
||||||
|
} else {
|
||||||
|
goto swap_fail;
|
||||||
|
}
|
||||||
|
commit_cost_changes(moveChange);
|
||||||
|
return true;
|
||||||
|
swap_fail:
|
||||||
|
for (const auto &entry : boost::adaptors::reverse(moves_made))
|
||||||
|
swap_cell_bels(entry.first, entry.second);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Find a random Bel of the correct type for a cell, within the specified
|
// Find a random Bel of the correct type for a cell, within the specified
|
||||||
// diameter
|
// diameter
|
||||||
BelId random_bel_for_cell(CellInfo *cell)
|
BelId random_bel_for_cell(CellInfo *cell, int force_z = -1)
|
||||||
{
|
{
|
||||||
IdString targetType = cell->type;
|
IdString targetType = cell->type;
|
||||||
Loc curr_loc = ctx->getBelLocation(cell->bel);
|
Loc curr_loc = ctx->getBelLocation(cell->bel);
|
||||||
@ -479,6 +586,11 @@ class SAPlacer
|
|||||||
if (fb.size() == 0)
|
if (fb.size() == 0)
|
||||||
continue;
|
continue;
|
||||||
BelId bel = fb.at(ctx->rng(int(fb.size())));
|
BelId bel = fb.at(ctx->rng(int(fb.size())));
|
||||||
|
if (force_z != -1) {
|
||||||
|
Loc loc = ctx->getBelLocation(bel);
|
||||||
|
if (loc.z != force_z)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (locked_bels.find(bel) != locked_bels.end())
|
if (locked_bels.find(bel) != locked_bels.end())
|
||||||
continue;
|
continue;
|
||||||
return bel;
|
return bel;
|
||||||
|
Loading…
Reference in New Issue
Block a user