ecp5: Compute derived constraints iteratively
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
0bc88e622c
commit
ab50a6ef54
43
ecp5/pack.cc
43
ecp5/pack.cc
@ -2154,6 +2154,12 @@ class Ecp5Packer
|
||||
|
||||
auto equals_epsilon = [](delay_t a, delay_t b) { return (std::abs(a - b) / std::max(double(b), 1.0)) < 1e-3; };
|
||||
|
||||
std::unordered_set<IdString> user_constrained, changed_nets;
|
||||
for (auto &net : ctx->nets) {
|
||||
if (net.second->clkconstr != nullptr)
|
||||
user_constrained.insert(net.first);
|
||||
changed_nets.insert(net.first);
|
||||
}
|
||||
auto get_period = [&](CellInfo *ci, IdString port, delay_t &period) {
|
||||
if (!ci->ports.count(port))
|
||||
return false;
|
||||
@ -2170,8 +2176,10 @@ class Ecp5Packer
|
||||
NetInfo *to = ci->ports.at(port).net;
|
||||
if (to == nullptr)
|
||||
return;
|
||||
if (to->clkconstr != nullptr && !equals_epsilon(to->clkconstr->period.min_delay, period)) {
|
||||
log_warning(" Overriding derived constraint of %.1f on net %s with user-specified constraint of "
|
||||
if (to->clkconstr != nullptr) {
|
||||
if (!equals_epsilon(to->clkconstr->period.min_delay, period) && user_constrained.count(to->name))
|
||||
log_warning(
|
||||
" Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of "
|
||||
"%.1f MHz.\n",
|
||||
MHz(to->clkconstr->period.min_delay), to->name.c_str(ctx), MHz(period));
|
||||
return;
|
||||
@ -2185,6 +2193,7 @@ class Ecp5Packer
|
||||
to->clkconstr->period.max_delay = period;
|
||||
log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.min_delay),
|
||||
to->name.c_str(ctx));
|
||||
changed_nets.insert(to->name);
|
||||
};
|
||||
|
||||
auto copy_constraint = [&](CellInfo *ci, IdString fromPort, IdString toPort, double ratio = 1.0) {
|
||||
@ -2193,9 +2202,12 @@ class Ecp5Packer
|
||||
NetInfo *from = ci->ports.at(fromPort).net, *to = ci->ports.at(toPort).net;
|
||||
if (from == nullptr || from->clkconstr == nullptr || to == nullptr)
|
||||
return;
|
||||
if (to->clkconstr != nullptr &&
|
||||
!equals_epsilon(to->clkconstr->period.min_delay, delay_t(from->clkconstr->period.min_delay / ratio))) {
|
||||
log_warning(" Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of "
|
||||
if (to->clkconstr != nullptr) {
|
||||
if (!equals_epsilon(to->clkconstr->period.min_delay,
|
||||
delay_t(from->clkconstr->period.min_delay / ratio)) &&
|
||||
user_constrained.count(to->name))
|
||||
log_warning(
|
||||
" Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of "
|
||||
"%.1f MHz.\n",
|
||||
MHz(to->clkconstr->period.min_delay), to->name.c_str(ctx),
|
||||
MHz(delay_t(from->clkconstr->period.min_delay / ratio)));
|
||||
@ -2207,10 +2219,23 @@ class Ecp5Packer
|
||||
to->clkconstr->period = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->period.min_delay) / ratio);
|
||||
log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.min_delay),
|
||||
to->name.c_str(ctx));
|
||||
changed_nets.insert(to->name);
|
||||
};
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
// Run in a loop while constraints are changing to deal with dependencies
|
||||
// Iteration limit avoids hanging in crazy loopback situation (self-fed PLLs or dividers, etc)
|
||||
int iter = 0;
|
||||
const int itermax = 5000;
|
||||
while (!changed_nets.empty() && iter < itermax) {
|
||||
++iter;
|
||||
std::unordered_set<IdString> changed_cells;
|
||||
for (auto net : changed_nets)
|
||||
for (auto &user : ctx->nets.at(net)->users)
|
||||
if (user.port == id_CLKI || user.port == id_ECLKI)
|
||||
changed_cells.insert(user.cell->name);
|
||||
changed_nets.clear();
|
||||
for (auto cell : sorted(changed_cells)) {
|
||||
CellInfo *ci = ctx->cells.at(cell).get();
|
||||
if (ci->type == id_CLKDIVF) {
|
||||
std::string div = str_or_default(ci->params, ctx->id("DIV"), "2.0");
|
||||
double ratio;
|
||||
@ -2248,7 +2273,8 @@ class Ecp5Packer
|
||||
double vco_period = period_in_div / feedback_div;
|
||||
double vco_freq = MHz(vco_period);
|
||||
if (vco_freq < 400 || vco_freq > 800)
|
||||
log_info(" Derived VCO frequency %.1f MHz of PLL '%s' is out of legal range [400MHz, 800MHz]\n",
|
||||
log_info(" Derived VCO frequency %.1f MHz of PLL '%s' is out of legal range [400MHz, "
|
||||
"800MHz]\n",
|
||||
vco_freq, ci->name.c_str(ctx));
|
||||
set_period(ci, id_CLKOP, vco_period * int_or_default(ci->params, ctx->id("CLKOP_DIV"), 1));
|
||||
set_period(ci, id_CLKOS, vco_period * int_or_default(ci->params, ctx->id("CLKOS_DIV"), 1));
|
||||
@ -2260,6 +2286,7 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void pack()
|
||||
|
Loading…
Reference in New Issue
Block a user