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 {
|
} else {
|
||||||
// Check for dedicated routing
|
// Check for dedicated routing
|
||||||
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
// Driver is locked
|
// Driver is locked
|
||||||
@ -308,7 +310,7 @@ class Ecp5GlobalRouter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return true if a short (<5) route exists between two wires
|
// 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::queue<WireId> visit;
|
||||||
std::unordered_map<WireId, PipId> backtrace;
|
std::unordered_map<WireId, PipId> backtrace;
|
||||||
@ -316,7 +318,7 @@ class Ecp5GlobalRouter
|
|||||||
WireId cursor;
|
WireId cursor;
|
||||||
while (true) {
|
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),
|
// log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx),
|
||||||
// ctx->getWireName(dst).c_str(ctx));
|
// ctx->getWireName(dst).c_str(ctx));
|
||||||
return false;
|
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:
|
public:
|
||||||
void pack()
|
void pack()
|
||||||
{
|
{
|
||||||
@ -1330,6 +1384,7 @@ class Ecp5Packer
|
|||||||
pack_ebr();
|
pack_ebr();
|
||||||
pack_dsps();
|
pack_dsps();
|
||||||
pack_dcus();
|
pack_dcus();
|
||||||
|
preplace_plls();
|
||||||
pack_constants();
|
pack_constants();
|
||||||
pack_dram();
|
pack_dram();
|
||||||
pack_carries();
|
pack_carries();
|
||||||
|
Loading…
Reference in New Issue
Block a user