Refactor some common code to CellInfo methods

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-02-23 11:42:33 +00:00
parent 72b7a2e107
commit 162793aa87
6 changed files with 43 additions and 38 deletions

View File

@ -223,6 +223,28 @@ void CellInfo::unsetParam(IdString name) { params.erase(name); }
void CellInfo::setAttr(IdString name, Property value) { attrs[name] = value; } void CellInfo::setAttr(IdString name, Property value) { attrs[name] = value; }
void CellInfo::unsetAttr(IdString name) { attrs.erase(name); } void CellInfo::unsetAttr(IdString name) { attrs.erase(name); }
bool CellInfo::isConstrained(bool include_abs_z_constr) const
{
return constr_parent != nullptr || !constr_children.empty() || (include_abs_z_constr && constr_abs_z);
}
bool CellInfo::testRegion(BelId bel) const
{
return region == nullptr || !region->constr_bels || region->bels.count(bel);
}
Loc CellInfo::getConstrainedLoc(Loc parent_loc) const
{
NPNR_ASSERT(constr_parent != nullptr);
Loc cloc = parent_loc;
if (constr_x != UNCONSTR)
cloc.x += constr_x;
if (constr_y != UNCONSTR)
cloc.y += constr_y;
if (constr_z != UNCONSTR)
cloc.z = constr_abs_z ? constr_z : (parent_loc.z + constr_z);
return cloc;
}
std::string Property::to_string() const std::string Property::to_string() const
{ {
if (is_string) { if (is_string) {

View File

@ -664,6 +664,14 @@ struct CellInfo : ArchCellInfo
void unsetParam(IdString name); void unsetParam(IdString name);
void setAttr(IdString name, Property value); void setAttr(IdString name, Property value);
void unsetAttr(IdString name); void unsetAttr(IdString name);
// return true if the cell has placement constraints (optionally excluding the case where the only case is an
// absolute z constraint)
bool isConstrained(bool include_abs_z_constr = true) const;
// check whether a bel complies with the cell's region constraint
bool testRegion(BelId bel) const;
// get the constrained location for this cell given a provisional location for its parent
Loc getConstrainedLoc(Loc parent_loc) const;
}; };
enum TimingPortClass enum TimingPortClass

View File

@ -536,12 +536,4 @@ int get_constraints_distance(const Context *ctx, const CellInfo *cell)
return dist; return dist;
} }
bool check_cell_bel_region(const CellInfo *cell, BelId bel)
{
if (cell->region != nullptr && cell->region->constr_bels && !cell->region->bels.count(bel))
return false;
else
return true;
}
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -50,9 +50,6 @@ bool legalise_relative_constraints(Context *ctx);
// Get the total distance from satisfied constraints for a cell // Get the total distance from satisfied constraints for a cell
int get_constraints_distance(const Context *ctx, const CellInfo *cell); int get_constraints_distance(const Context *ctx, const CellInfo *cell);
// Check that a Bel is within the region for a cell
bool check_cell_bel_region(const CellInfo *cell, BelId bel);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END
#endif #endif

View File

@ -504,12 +504,12 @@ class SAPlacer
{ {
static const double epsilon = 1e-20; static const double epsilon = 1e-20;
moveChange.reset(this); moveChange.reset(this);
if (!require_legal && is_constrained(cell)) if (!require_legal && cell->isConstrained(false))
return false; return false;
BelId oldBel = cell->bel; BelId oldBel = cell->bel;
CellInfo *other_cell = ctx->getBoundBelCell(newBel); CellInfo *other_cell = ctx->getBoundBelCell(newBel);
if (!require_legal && other_cell != nullptr && if (!require_legal && other_cell != nullptr &&
(is_constrained(other_cell) || other_cell->belStrength > STRENGTH_WEAK)) { (other_cell->isConstrained(false) || other_cell->belStrength > STRENGTH_WEAK)) {
return false; return false;
} }
int old_dist = get_constraints_distance(ctx, cell); int old_dist = get_constraints_distance(ctx, cell);
@ -589,11 +589,6 @@ 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 // Swap the Bel of a cell with another, return the original location
BelId swap_cell_bels(CellInfo *cell, BelId newBel) BelId swap_cell_bels(CellInfo *cell, BelId newBel)
{ {
@ -605,9 +600,9 @@ class SAPlacer
if (bound != nullptr) if (bound != nullptr)
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
ctx->bindBel(newBel, cell, is_constrained(cell) ? STRENGTH_STRONG : STRENGTH_WEAK); ctx->bindBel(newBel, cell, cell->isConstrained(false) ? STRENGTH_STRONG : STRENGTH_WEAK);
if (bound != nullptr) { if (bound != nullptr) {
ctx->bindBel(oldBel, bound, is_constrained(bound) ? STRENGTH_STRONG : STRENGTH_WEAK); ctx->bindBel(oldBel, bound, bound->isConstrained(false) ? STRENGTH_STRONG : STRENGTH_WEAK);
if (cfg.netShareWeight > 0) if (cfg.netShareWeight > 0)
update_nets_by_tile(bound, ctx->getBelLocation(newBel), ctx->getBelLocation(oldBel)); update_nets_by_tile(bound, ctx->getBelLocation(newBel), ctx->getBelLocation(oldBel));
} }
@ -658,7 +653,7 @@ class SAPlacer
// We don't consider swapping chains with other chains, at least for the time being - unless it is // We don't consider swapping chains with other chains, at least for the time being - unless it is
// part of this chain // part of this chain
if (bound != nullptr && !cells.count(bound->name) && if (bound != nullptr && !cells.count(bound->name) &&
(bound->belStrength >= STRENGTH_STRONG || is_constrained(bound))) (bound->belStrength >= STRENGTH_STRONG || bound->isConstrained(false)))
return false; return false;
dest_bels.emplace_back(std::make_pair(cr.first, targetBel)); dest_bels.emplace_back(std::make_pair(cr.first, targetBel));
} }
@ -676,12 +671,12 @@ class SAPlacer
add_move_cell(moveChange, bound, db.second); add_move_cell(moveChange, bound, db.second);
} }
for (const auto &mm : moves_made) { for (const auto &mm : moves_made) {
if (!ctx->isBelLocationValid(mm.first->bel) || !check_cell_bel_region(mm.first, mm.first->bel)) if (!ctx->isBelLocationValid(mm.first->bel) || !mm.first->testRegion(mm.first->bel))
goto swap_fail; goto swap_fail;
if (!ctx->isBelLocationValid(mm.second)) if (!ctx->isBelLocationValid(mm.second))
goto swap_fail; goto swap_fail;
CellInfo *bound = ctx->getBoundBelCell(mm.second); CellInfo *bound = ctx->getBoundBelCell(mm.second);
if (bound && !check_cell_bel_region(bound, bound->bel)) if (bound && !bound->testRegion(bound->bel))
goto swap_fail; goto swap_fail;
} }
compute_cost_changes(moveChange); compute_cost_changes(moveChange);
@ -752,7 +747,7 @@ class SAPlacer
if (loc.z != force_z) if (loc.z != force_z)
continue; continue;
} }
if (!check_cell_bel_region(cell, bel)) if (!cell->testRegion(bel))
continue; continue;
if (locked_bels.find(bel) != locked_bels.end()) if (locked_bels.find(bel) != locked_bels.end())
continue; continue;

View File

@ -937,7 +937,7 @@ class HeAPPlacer
// The case where we have no relative constraints // The case where we have no relative constraints
for (auto sz : fb->at(nx).at(ny)) { for (auto sz : fb->at(nx).at(ny)) {
// Look through all bels in this tile; checking region constraint if applicable // Look through all bels in this tile; checking region constraint if applicable
if (ci->region != nullptr && ci->region->constr_bels && !ci->region->bels.count(sz)) if (!ci->testRegion(sz))
continue; continue;
// Prefer available bels; unless we are dealing with a wide radius (e.g. difficult control sets) // Prefer available bels; unless we are dealing with a wide radius (e.g. difficult control sets)
// or occasionally trigger a tiebreaker // or occasionally trigger a tiebreaker
@ -945,8 +945,7 @@ class HeAPPlacer
CellInfo *bound = ctx->getBoundBelCell(sz); CellInfo *bound = ctx->getBoundBelCell(sz);
if (bound != nullptr) { if (bound != nullptr) {
// Only rip up cells without constraints // Only rip up cells without constraints
if (bound->constr_parent != nullptr || !bound->constr_children.empty() || if (bound->isConstrained())
bound->constr_abs_z)
continue; continue;
ctx->unbindBel(bound->bel); ctx->unbindBel(bound->bel);
} }
@ -1020,7 +1019,7 @@ class HeAPPlacer
// Get the bel we're going to place this cell at // Get the bel we're going to place this cell at
BelId target = ctx->getBelByLocation(ploc); BelId target = ctx->getBelByLocation(ploc);
// Check it satisfies the region constraint if applicable // Check it satisfies the region constraint if applicable
if (vc->region != nullptr && vc->region->constr_bels && !vc->region->bels.count(target)) if (!vc->testRegion(target))
goto fail; goto fail;
CellInfo *bound; CellInfo *bound;
// Check that the target bel exists and is of a suitable type // Check that the target bel exists and is of a suitable type
@ -1029,21 +1028,13 @@ class HeAPPlacer
bound = ctx->getBoundBelCell(target); bound = ctx->getBoundBelCell(target);
// Chains cannot overlap; so if we have to ripup a cell make sure it isn't part of a chain // Chains cannot overlap; so if we have to ripup a cell make sure it isn't part of a chain
if (bound != nullptr) if (bound != nullptr)
if (bound->constr_z != bound->UNCONSTR || bound->constr_parent != nullptr || if (bound->isConstrained() || bound->belStrength > STRENGTH_WEAK)
!bound->constr_children.empty() || bound->belStrength > STRENGTH_WEAK)
goto fail; goto fail;
targets.emplace_back(vc, target); targets.emplace_back(vc, target);
for (auto child : vc->constr_children) { for (auto child : vc->constr_children) {
// For all the constrained children; compute the location we need to place them at and // For all the constrained children; compute the location we need to place them at and
// add them to the queue // add them to the queue
Loc cloc = ploc; visit.emplace(child, child->getConstrainedLoc(ploc));
if (child->constr_x != child->UNCONSTR)
cloc.x += child->constr_x;
if (child->constr_y != child->UNCONSTR)
cloc.y += child->constr_y;
if (child->constr_z != child->UNCONSTR)
cloc.z = child->constr_abs_z ? child->constr_z : (ploc.z + child->constr_z);
visit.emplace(child, cloc);
} }
} }
// Actually perform the move; keeping track of the moves we make so we can revert them if needed // Actually perform the move; keeping track of the moves we make so we can revert them if needed