Skip to content

Commit

Permalink
placer1: Fix various bitrot
Browse files Browse the repository at this point in the history
Signed-off-by: gatecat <[email protected]>
  • Loading branch information
gatecat committed Dec 13, 2023
1 parent d1083fd commit 535709a
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 133 deletions.
156 changes: 83 additions & 73 deletions common/place/place_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "place_common.h"
#include <cmath>
#include "fast_bels.h"
#include "log.h"
#include "util.h"

Expand Down Expand Up @@ -102,84 +103,14 @@ wirelen_t get_cell_metric_at_bel(const Context *ctx, CellInfo *cell, BelId bel,
return wirelen;
}

// Placing a single cell
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
{
bool all_placed = false;
int iters = 25;
while (!all_placed) {
BelId best_bel = BelId();
wirelen_t best_wirelen = std::numeric_limits<wirelen_t>::max(),
best_ripup_wirelen = std::numeric_limits<wirelen_t>::max();
CellInfo *ripup_target = nullptr;
BelId ripup_bel = BelId();
if (cell->bel != BelId()) {
ctx->unbindBel(cell->bel);
}
IdString targetType = cell->type;
for (auto bel : ctx->getBels()) {
if (ctx->isValidBelForCellType(targetType, bel)) {
if (ctx->checkBelAvail(bel)) {
wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
if (iters >= 4)
wirelen += ctx->rng(25);
if (wirelen <= best_wirelen) {
best_wirelen = wirelen;
best_bel = bel;
}
} else {
wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
if (iters >= 4)
wirelen += ctx->rng(25);
if (wirelen <= best_ripup_wirelen) {
CellInfo *curr_cell = ctx->getBoundBelCell(bel);
if (curr_cell->belStrength < STRENGTH_STRONG) {
best_ripup_wirelen = wirelen;
ripup_bel = bel;
ripup_target = curr_cell;
}
}
}
}
}
if (best_bel == BelId()) {
if (iters == 0) {
log_error("failed to place cell '%s' of type '%s' (ripup iteration limit exceeded)\n",
cell->name.c_str(ctx), cell->type.c_str(ctx));
}
if (ripup_bel == BelId()) {
log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
}
--iters;
ctx->unbindBel(ripup_target->bel);
best_bel = ripup_bel;
} else {
ripup_target = nullptr;
all_placed = true;
}
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
if (require_legality && !ctx->isBelLocationValid(best_bel)) {
ctx->unbindBel(best_bel);
if (ripup_target != nullptr) {
ctx->bindBel(best_bel, ripup_target, STRENGTH_WEAK);
}
all_placed = false;
continue;
}
if (ctx->verbose)
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->nameOfBel(best_bel));
cell = ripup_target;
}
return true;
}

class ConstraintLegaliseWorker
{
private:
Context *ctx;
std::set<IdString> rippedCells;
dict<IdString, Loc> oldLocations;
dict<ClusterId, std::vector<CellInfo *>> cluster2cells;
FastBels fast_bels;

class IncreasingDiameterSearch
{
Expand Down Expand Up @@ -376,8 +307,87 @@ class ConstraintLegaliseWorker
// Check if constraints are currently satisfied on a cell and its children
bool constraints_satisfied(const CellInfo *cell) { return get_constraints_distance(ctx, cell) == 0; }

// Placing a single cell
bool place_single_cell(CellInfo *cell)
{
int diameter = 1;
while (cell) {
CellInfo *ripup_target = nullptr;
if (cell->bel != BelId()) {
ctx->unbindBel(cell->bel);
}
FastBels::FastBelsData *bel_data;
fast_bels.getBelsForCellType(cell->type, &bel_data);

int iter = 0;
BelId best_bel = BelId();
wirelen_t best_metric = std::numeric_limits<wirelen_t>::max();

while (true) {
++iter;
if (iter >= (5 * diameter)) {
iter = 0;
if (diameter < std::max(ctx->getGridDimX(), ctx->getGridDimY()))
++diameter;
if (best_bel != BelId())
break;
}
auto old_loc = oldLocations.at(cell->name);
int nx = old_loc.x - (diameter / 2) + ctx->rng(diameter),
ny = old_loc.y - (diameter / 2) + ctx->rng(diameter);
if (nx < 0 || nx >= int(bel_data->size()))
continue;
if (ny < 0 || ny >= int(bel_data->at(nx).size()))
continue;
const auto &fb = bel_data->at(nx).at(ny);
if (fb.size() == 0)
continue;
BelId bel = fb.at(ctx->rng(int(fb.size())));
if (cell->region && cell->region->constr_bels && !cell->region->bels.count(bel))
continue;
if (!ctx->isValidBelForCellType(cell->type, bel))
continue;
ripup_target = ctx->getBoundBelCell(bel);
if (ripup_target != nullptr) {
if (ripup_target->belStrength > STRENGTH_STRONG || ripup_target->cluster != ClusterId())
continue;
ctx->unbindBel(bel);
} else if (!ctx->checkBelAvail(bel)) {
continue;
}
ctx->bindBel(bel, cell, STRENGTH_WEAK);
if (!ctx->isBelLocationValid(bel)) {
ctx->unbindBel(bel);
if (ripup_target)
ctx->bindBel(bel, ripup_target, STRENGTH_WEAK);
continue;
}
wirelen_t new_metric = get_cell_metric(ctx, cell, MetricType::COST);
if (ripup_target)
new_metric *= 5;
if (new_metric < best_metric) {
best_bel = bel;
best_metric = new_metric;
}
ctx->unbindBel(bel);
if (ripup_target)
ctx->bindBel(bel, ripup_target, STRENGTH_WEAK);
}

// Back annotate location
ripup_target = ctx->getBoundBelCell(best_bel);
if (ripup_target)
ctx->unbindBel(best_bel);
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);

cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
cell = ripup_target;
}
return true;
}

public:
ConstraintLegaliseWorker(Context *ctx) : ctx(ctx)
ConstraintLegaliseWorker(Context *ctx) : ctx(ctx), fast_bels(ctx, /*check_bel_available=*/false, 0)
{
for (auto &cell : ctx->cells) {
if (cell.second->cluster != ClusterId())
Expand Down Expand Up @@ -429,7 +439,7 @@ class ConstraintLegaliseWorker
if (print_stats("legalising chains") == 0)
return 0;
for (auto rippedCell : rippedCells) {
bool res = place_single_cell(ctx, ctx->cells.at(rippedCell).get(), true);
bool res = place_single_cell(ctx->cells.at(rippedCell).get());
if (!res) {
log_error("failed to place cell '%s' after relative constraint legalisation\n", rippedCell.c_str(ctx));
return -1;
Expand Down
3 changes: 0 additions & 3 deletions common/place/place_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ wirelen_t get_cell_metric(const Context *ctx, const CellInfo *cell, MetricType t
// Return the wirelength of all nets connected to a cell, when the cell is at a given bel
wirelen_t get_cell_metric_at_bel(const Context *ctx, CellInfo *cell, BelId bel, MetricType type);

// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality);

// Modify a design s.t. all relative placement constraints are satisfied
bool legalise_relative_constraints(Context *ctx);

Expand Down
92 changes: 35 additions & 57 deletions common/place/placer1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -416,73 +416,51 @@ class SAPlacer
}

private:
std::vector<BelId> all_bels;
// Initial random placement
void place_initial(CellInfo *cell)
{
bool all_placed = false;
int iters = 25;
while (!all_placed) {
BelId best_bel = BelId();
uint64_t best_score = std::numeric_limits<uint64_t>::max(),
best_ripup_score = std::numeric_limits<uint64_t>::max();
while (cell) {
CellInfo *ripup_target = nullptr;
BelId ripup_bel = BelId();
if (cell->bel != BelId()) {
ctx->unbindBel(cell->bel);
}
IdString targetType = cell->type;

auto proc_bel = [&](BelId bel) {
if (ctx->isValidBelForCellType(targetType, bel)) {
if (ctx->checkBelAvail(bel)) {
uint64_t score = ctx->rng64();
if (score <= best_score) {
best_score = score;
best_bel = bel;
}
} else {
uint64_t score = ctx->rng64();
CellInfo *bound_cell = ctx->getBoundBelCell(bel);
if (score <= best_ripup_score && bound_cell->belStrength < STRENGTH_STRONG) {
best_ripup_score = score;
ripup_target = bound_cell;
ripup_bel = bel;
}
}
}
};

if (cell->region != nullptr && cell->region->constr_bels) {
for (auto bel : cell->region->bels) {
proc_bel(bel);
}
} else {
for (auto bel : ctx->getBels()) {
proc_bel(bel);
}
}

if (best_bel == BelId()) {
if (iters == 0 || ripup_bel == BelId())
log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
--iters;
ctx->unbindBel(ripup_target->bel);
best_bel = ripup_bel;
} else {
ripup_target = nullptr;
all_placed = true;
}
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);

if (!ctx->isBelLocationValid(best_bel)) {
ctx->unbindBel(best_bel);
FastBels::FastBelsData *bel_data;
auto type_cnt = fast_bels.getBelsForCellType(cell->type, &bel_data);

while (true) {
int nx = ctx->rng(max_x + 1), ny = ctx->rng(max_y + 1);
if (cfg.minBelsForGridPick >= 0 && type_cnt < cfg.minBelsForGridPick)
nx = ny = 0;
if (nx >= int(bel_data->size()))
continue;
if (ny >= int(bel_data->at(nx).size()))
continue;
const auto &fb = bel_data->at(nx).at(ny);
if (fb.size() == 0)
continue;
BelId bel = fb.at(ctx->rng(int(fb.size())));
if (cell->region && cell->region->constr_bels && !cell->region->bels.count(bel))
continue;
if (!ctx->isValidBelForCellType(cell->type, bel))
continue;
ripup_target = ctx->getBoundBelCell(bel);
if (ripup_target != nullptr) {
ctx->bindBel(best_bel, ripup_target, STRENGTH_WEAK);
if (ripup_target->belStrength > STRENGTH_STRONG)
continue;
ctx->unbindBel(bel);
} else if (!ctx->checkBelAvail(bel)) {
continue;
}
all_placed = false;
continue;
ctx->bindBel(bel, cell, STRENGTH_WEAK);
if (!ctx->isBelLocationValid(bel)) {
ctx->unbindBel(bel);
if (ripup_target)
ctx->bindBel(bel, ripup_target, STRENGTH_WEAK);
continue;
}
break;
}

// Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
cell = ripup_target;
Expand Down

0 comments on commit 535709a

Please sign in to comment.