ecp5: Pre-place PLLs and use dedicated routes into globals
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
fc08856537
commit
5ddf99cf5d
@ -298,6 +298,8 @@ class Ecp5GlobalRouter
|
||||
} else {
|
||||
// Check for dedicated routing
|
||||
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) {
|
||||
// log_info("dedicated route %s -> %s\n", ctx->getWireName(ctx->getBelPinWire(drv_bel,
|
||||
// drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx));
|
||||
return 0;
|
||||
}
|
||||
// Driver is locked
|
||||
@ -308,7 +310,7 @@ class Ecp5GlobalRouter
|
||||
}
|
||||
|
||||
// Return true if a short (<5) route exists between two wires
|
||||
bool has_short_route(WireId src, WireId dst, int thresh = 5)
|
||||
bool has_short_route(WireId src, WireId dst, int thresh = 7)
|
||||
{
|
||||
std::queue<WireId> visit;
|
||||
std::unordered_map<WireId, PipId> backtrace;
|
||||
@ -316,7 +318,7 @@ class Ecp5GlobalRouter
|
||||
WireId cursor;
|
||||
while (true) {
|
||||
|
||||
if (visit.empty() || visit.size() > 1000) {
|
||||
if (visit.empty() || visit.size() > 10000) {
|
||||
// log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx),
|
||||
// ctx->getWireName(dst).c_str(ctx));
|
||||
return false;
|
||||
|
55
ecp5/pack.cc
55
ecp5/pack.cc
@ -1323,6 +1323,60 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
|
||||
// Preplace PLL
|
||||
void preplace_plls()
|
||||
{
|
||||
std::set<BelId> available_plls;
|
||||
for (auto bel : ctx->getBels()) {
|
||||
if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel))
|
||||
available_plls.insert(bel);
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
|
||||
available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL")))));
|
||||
}
|
||||
// Place PLL connected to fixed drivers such as IO close to their source
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
|
||||
const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI);
|
||||
if (drivernet == nullptr || drivernet->driver.cell == nullptr)
|
||||
continue;
|
||||
const CellInfo *drivercell = drivernet->driver.cell;
|
||||
if (!drivercell->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL"))));
|
||||
Loc drvloc = ctx->getBelLocation(drvbel);
|
||||
BelId closest_pll;
|
||||
int closest_distance = std::numeric_limits<int>::max();
|
||||
for (auto bel : available_plls) {
|
||||
Loc pllloc = ctx->getBelLocation(bel);
|
||||
int distance = std::abs(drvloc.x - pllloc.x) + std::abs(drvloc.y - pllloc.y);
|
||||
if (distance < closest_distance) {
|
||||
closest_pll = bel;
|
||||
closest_distance = distance;
|
||||
}
|
||||
}
|
||||
if (closest_pll == BelId())
|
||||
log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx));
|
||||
available_plls.erase(closest_pll);
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(closest_pll).str(ctx);
|
||||
}
|
||||
}
|
||||
// Place PLLs driven by logic, etc, randomly
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
|
||||
if (available_plls.empty())
|
||||
log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx));
|
||||
BelId next_pll = *(available_plls.begin());
|
||||
available_plls.erase(next_pll);
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(next_pll).str(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void pack()
|
||||
{
|
||||
@ -1330,6 +1384,7 @@ class Ecp5Packer
|
||||
pack_ebr();
|
||||
pack_dsps();
|
||||
pack_dcus();
|
||||
preplace_plls();
|
||||
pack_constants();
|
||||
pack_dram();
|
||||
pack_carries();
|
||||
|
Loading…
Reference in New Issue
Block a user