From f53dc8d3c9735b4d9c50db1848de9dd3fefbe7ef Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 2 Dec 2018 15:49:24 +0000 Subject: timing_opt: Improve heuristics Signed-off-by: David Shah --- common/timing.cc | 7 +++++- common/timing_opt.cc | 63 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 21 deletions(-) (limited to 'common') diff --git a/common/timing.cc b/common/timing.cc index 18caa989..6965307d 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -566,16 +566,20 @@ struct Timing auto &nc = (*net_crit)[net->name]; if (nc.slack.empty()) nc.slack.resize(net->users.size(), std::numeric_limits::max()); +#if 0 if (ctx->debug) log_info("Net %s cd %s\n", net->name.c_str(ctx), startdomain.first.clock.c_str(ctx)); +#endif for (size_t i = 0; i < net->users.size(); i++) { delay_t slack = nd.min_required.at(i) - (nd.max_arrival + ctx->getNetinfoRouteDelay(net, net->users.at(i))); +#if 0 if (ctx->debug) log_info(" user %s.%s required %.02fns arrival %.02f route %.02f slack %.02f\n", net->users.at(i).cell->name.c_str(ctx), net->users.at(i).port.c_str(ctx), ctx->getDelayNS(nd.min_required.at(i)), ctx->getDelayNS(nd.max_arrival), ctx->getDelayNS(ctx->getNetinfoRouteDelay(net, net->users.at(i))), ctx->getDelayNS(slack)); +#endif if (worst_slack.count(startdomain.first)) worst_slack.at(startdomain.first) = std::min(worst_slack.at(startdomain.first), slack); else @@ -612,7 +616,7 @@ struct Timing nc.cd_worst_slack = std::min(nc.cd_worst_slack, worst_slack.at(startdomain.first)); } } - +#if 0 if (ctx->debug) { for (auto &nc : *net_crit) { NetInfo *net = ctx->nets.at(nc.first).get(); @@ -628,6 +632,7 @@ struct Timing log_break(); } } +#endif } return min_slack; } diff --git a/common/timing_opt.cc b/common/timing_opt.cc index ed1618da..e8bb7d4f 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -90,7 +90,7 @@ class TimingOptimiser log_info(" Iteration %d...\n", i); get_criticalities(ctx, &net_crit); setup_delay_limits(); - auto crit_paths = find_crit_paths(0.95, 1000); + auto crit_paths = find_crit_paths(0.98, 1000); for (auto &path : crit_paths) optimise_path(path); #if 1 @@ -140,27 +140,23 @@ class TimingOptimiser if (port.second.type == PORT_IN) { if (net->driver.cell == nullptr || net->driver.cell->bel == BelId()) continue; - BelId srcBel = net->driver.cell->bel; - if (ctx->estimateDelay(ctx->getBelPinWire(srcBel, net->driver.port), - ctx->getBelPinWire(cell->bel, port.first)) > - max_net_delay.at(std::make_pair(cell->name, port.first))) - return false; + for (auto user : net->users) { + if (user.cell == cell && user.port == port.first) { + if (ctx->predictDelay(net, user) > + 1.1 * max_net_delay.at(std::make_pair(cell->name, port.first))) + return false; + } + } + } else if (port.second.type == PORT_OUT) { for (auto user : net->users) { // This could get expensive for high-fanout nets?? BelId dstBel = user.cell->bel; if (dstBel == BelId()) continue; - if (ctx->estimateDelay(ctx->getBelPinWire(cell->bel, port.first), - ctx->getBelPinWire(dstBel, user.port)) > - max_net_delay.at(std::make_pair(user.cell->name, user.port))) { -#if 0 - if (ctx->debug) { - log_info(" est delay %.02fns exceeded maximum %.02fns\n", ctx->getDelayNS(ctx->estimateDelay(ctx->getBelPinWire(cell->bel, port.first), - ctx->getBelPinWire(dstBel, user.port))), - ctx->getDelayNS(max_net_delay.at(std::make_pair(user.cell->name, user.port)))); - } -#endif + if (ctx->predictDelay(net, user) > + 1.1 * max_net_delay.at(std::make_pair(user.cell->name, user.port))) { + return false; } } @@ -370,7 +366,7 @@ class TimingOptimiser int ccount; DelayInfo combDelay; TimingPortClass tpclass = ctx->getPortTimingClass(cell, port.first, ccount); - if (tpclass != TMG_COMB_OUTPUT) + if (tpclass != TMG_COMB_OUTPUT && tpclass != TMG_REGISTER_OUTPUT) continue; bool is_path = ctx->getCellDelay(cell, fwd_cursor->port, port.first, combDelay); if (!is_path) @@ -408,6 +404,17 @@ class TimingOptimiser bel_candidate_cells.clear(); if (ctx->debug) log_info("Optimising the following path: \n"); + + auto front_port = path.front(); + NetInfo *front_net = front_port->cell->ports.at(front_port->port).net; + if (front_net != nullptr && front_net->driver.cell != nullptr) { + auto front_cell = front_net->driver.cell; + if (front_cell->belStrength <= STRENGTH_WEAK && cfg.cellTypes.count(front_cell->type) && + front_cell->constr_parent == nullptr && front_cell->constr_children.empty()) { + path_cells.push_back(front_cell->name); + } + } + for (auto port : path) { if (ctx->debug) { float crit = 0; @@ -429,7 +436,7 @@ class TimingOptimiser path_cells.push_back(port->cell->name); } - if (path_cells.size() < 3) { + if (path_cells.size() < 2) { if (ctx->debug) { log_info("Too few moveable cells; skipping path\n"); log_break(); @@ -437,8 +444,23 @@ class TimingOptimiser return; } + + // Calculate original delay before touching anything + delay_t original_delay = 0; + + for (size_t i = 0; i < path.size(); i++) { + NetInfo *pn = path.at(i)->cell->ports.at(path.at(i)->port).net; + for (size_t j = 0; j < pn->users.size(); j++) { + auto & usr = pn->users.at(j); + if (usr.cell == path.at(i)->cell && usr.port == path.at(i)->port) { + original_delay += ctx->predictDelay(pn, usr); + break; + } + } + } + IdString last_cell; - const int d = 4; // FIXME: how to best determine d + const int d = 3; // FIXME: how to best determine d for (auto cell : path_cells) { // FIXME: when should we allow swapping due to a lack of candidates find_neighbours(ctx->cells[cell].get(), last_cell, d, false); @@ -556,7 +578,8 @@ class TimingOptimiser route_to_solution.push_back(cursor); } if (ctx->debug) - log_info("Found a solution with cost %.02f ns\n", ctx->getDelayNS(lowest->second)); + log_info("Found a solution with cost %.02f ns (existing path %.02f ns)\n", ctx->getDelayNS(lowest->second), + ctx->getDelayNS(original_delay)); for (auto rt_entry : boost::adaptors::reverse(route_to_solution)) { CellInfo *cell = ctx->cells.at(rt_entry.first).get(); cell_swap_bel(cell, rt_entry.second); -- cgit v1.2.3