Improving post-ripup placement in the legaliser
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
87a5b72126
commit
b0b16a344a
@ -79,7 +79,8 @@ wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
|
|||||||
{
|
{
|
||||||
std::set<IdString> nets;
|
std::set<IdString> nets;
|
||||||
for (auto p : cell->ports) {
|
for (auto p : cell->ports) {
|
||||||
nets.insert(p.first);
|
if (p.second.net)
|
||||||
|
nets.insert(p.second.net->name);
|
||||||
}
|
}
|
||||||
wirelen_t wirelength = 0;
|
wirelen_t wirelength = 0;
|
||||||
float tns = 0;
|
float tns = 0;
|
||||||
@ -89,4 +90,65 @@ wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
|
|||||||
return wirelength;
|
return wirelength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel)
|
||||||
|
{
|
||||||
|
BelId oldBel = cell->bel;
|
||||||
|
cell->bel = bel;
|
||||||
|
wirelen_t wirelen = get_cell_wirelength(ctx, cell);
|
||||||
|
cell->bel = oldBel;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
BelType targetType = ctx->belTypeFromId(cell->type);
|
||||||
|
for (auto bel : ctx->getBels()) {
|
||||||
|
if (ctx->getBelType(bel) == targetType && (!require_legality || ctx->isValidBelForCell(cell, bel))) {
|
||||||
|
if (ctx->checkBelAvail(bel)) {
|
||||||
|
wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
|
||||||
|
if (wirelen <= best_wirelen) {
|
||||||
|
best_wirelen = wirelen;
|
||||||
|
best_bel = bel;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
|
||||||
|
if (wirelen <= best_ripup_wirelen) {
|
||||||
|
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
|
||||||
|
if (ripup_target->belStrength < STRENGTH_STRONG) {
|
||||||
|
best_ripup_wirelen = wirelen;
|
||||||
|
ripup_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 {
|
||||||
|
all_placed = true;
|
||||||
|
}
|
||||||
|
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
|
||||||
|
|
||||||
|
cell = ripup_target;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -33,7 +33,7 @@ wirelen_t get_net_wirelength(const Context *ctx, const NetInfo *net, float &tns)
|
|||||||
wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell);
|
wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell);
|
||||||
|
|
||||||
// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
|
// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
|
||||||
bool place_single_cell(const Context *ctx, CellInfo *cell, bool require_legality);
|
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
|
|||||||
|
|
||||||
static wchar_t *program;
|
static wchar_t *program;
|
||||||
|
|
||||||
void init_python(const char *executable,bool first)
|
void init_python(const char *executable, bool first)
|
||||||
{
|
{
|
||||||
#ifdef MAIN_EXECUTABLE
|
#ifdef MAIN_EXECUTABLE
|
||||||
program = Py_DecodeLocale(executable, NULL);
|
program = Py_DecodeLocale(executable, NULL);
|
||||||
@ -138,8 +138,7 @@ void init_python(const char *executable,bool first)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (first)
|
if (first) {
|
||||||
{
|
|
||||||
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
|
PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
|
||||||
emb::append_inittab();
|
emb::append_inittab();
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "cells.h"
|
#include "cells.h"
|
||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "place_common.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -379,7 +380,7 @@ class PlacementLegaliser
|
|||||||
bool success = true;
|
bool success = true;
|
||||||
for (auto cell : sorted(rippedCells)) {
|
for (auto cell : sorted(rippedCells)) {
|
||||||
CellInfo *ci = ctx->cells.at(cell).get();
|
CellInfo *ci = ctx->cells.at(cell).get();
|
||||||
bool placed = place_single_cell(ci);
|
bool placed = place_single_cell(ctx, ci, true);
|
||||||
if (!placed) {
|
if (!placed) {
|
||||||
if (ctx->force) {
|
if (ctx->force) {
|
||||||
log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), ci->type.c_str(ctx));
|
log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), ci->type.c_str(ctx));
|
||||||
@ -392,19 +393,6 @@ class PlacementLegaliser
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place a single cell in the first valid location
|
|
||||||
bool place_single_cell(CellInfo *cell)
|
|
||||||
{
|
|
||||||
BelType tgtType = ctx->belTypeFromId(cell->type);
|
|
||||||
for (auto bel : ctx->getBels()) {
|
|
||||||
if (ctx->getBelType(bel) == tgtType && ctx->checkBelAvail(bel) && ctx->isValidBelForCell(cell, bel)) {
|
|
||||||
ctx->bindBel(bel, cell->name, STRENGTH_WEAK);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Context *ctx;
|
Context *ctx;
|
||||||
std::unordered_set<IdString> rippedCells;
|
std::unordered_set<IdString> rippedCells;
|
||||||
std::unordered_set<IdString> createdCells;
|
std::unordered_set<IdString> createdCells;
|
||||||
|
Loading…
Reference in New Issue
Block a user