diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/arch_api.h | 2 | ||||
-rw-r--r-- | common/arch_pybindings_shared.h | 4 | ||||
-rw-r--r-- | common/command.cc | 8 | ||||
-rw-r--r-- | common/context.cc | 23 | ||||
-rw-r--r-- | common/context.h | 2 | ||||
-rw-r--r-- | common/hashlib.h | 7 | ||||
-rw-r--r-- | common/nextpnr_namespaces.h | 2 | ||||
-rw-r--r-- | common/place_common.cc | 2 | ||||
-rw-r--r-- | common/placer1.cc | 4 | ||||
-rw-r--r-- | common/pybindings.cc | 5 | ||||
-rw-r--r-- | common/pywrappers.h | 17 | ||||
-rw-r--r-- | common/router1.cc | 133 | ||||
-rw-r--r-- | common/router2.cc | 4 | ||||
-rw-r--r-- | common/sso_array.h | 20 | ||||
-rw-r--r-- | common/timing.cc | 2 | ||||
-rw-r--r-- | common/timing_opt.cc | 8 |
16 files changed, 202 insertions, 41 deletions
diff --git a/common/arch_api.h b/common/arch_api.h index e49d26c1..14a30652 100644 --- a/common/arch_api.h +++ b/common/arch_api.h @@ -110,7 +110,7 @@ template <typename R> struct ArchAPI : BaseCtx virtual typename R::GroupPipsRangeT getGroupPips(GroupId group) const = 0; virtual typename R::GroupGroupsRangeT getGroupGroups(GroupId group) const = 0; // Delay Methods - virtual delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const = 0; + virtual delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const = 0; virtual delay_t getDelayEpsilon() const = 0; virtual delay_t getRipupDelayPenalty() const = 0; virtual float getDelayNS(delay_t v) const = 0; diff --git a/common/arch_pybindings_shared.h b/common/arch_pybindings_shared.h index f44aa70e..b3dc0506 100644 --- a/common/arch_pybindings_shared.h +++ b/common/arch_pybindings_shared.h @@ -48,6 +48,8 @@ fn_wrapper_2a_v<Context, decltype(&Context::copyBelPorts), &Context::copyBelPort fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType"); +fn_wrapper_1a<Context, decltype(&Context::getBelLocation), &Context::getBelLocation, pass_through<Loc>, + conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelLocation"); fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>, conv_from_str<BelId>>::def_wrap(ctx_cls, "checkBelAvail"); fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, @@ -92,6 +94,8 @@ fn_wrapper_0a<Context, decltype(&Context::getPips), &Context::getPips, wrap_cont "getPips"); fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum"); +fn_wrapper_1a<Context, decltype(&Context::getPipLocation), &Context::getPipLocation, pass_through<Loc>, + conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipLocation"); fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>, addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( diff --git a/common/command.cc b/common/command.cc index 5a13fb55..d4279a58 100644 --- a/common/command.cc +++ b/common/command.cc @@ -176,7 +176,9 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("router2-heatmap", po::value<std::string>(), "prefix for router2 resource congestion heatmaps"); - general.add_options()("router2-tmg-ripup", "enable experimental timing-driven ripup in router2"); + general.add_options()("tmg-ripup", "enable experimental timing-driven ripup in router"); + general.add_options()("router2-tmg-ripup", + "enable experimental timing-driven ripup in router (deprecated; use --tmg-ripup instead)"); general.add_options()("report", po::value<std::string>(), "write timing and utilization report in JSON format to file"); @@ -298,8 +300,8 @@ void CommandHandler::setupContext(Context *ctx) ctx->settings[ctx->id("placerHeap/timingWeight")] = std::to_string(vm["placer-heap-timingweight"].as<int>()); if (vm.count("router2-heatmap")) ctx->settings[ctx->id("router2/heatmap")] = vm["router2-heatmap"].as<std::string>(); - if (vm.count("router2-tmg-ripup")) - ctx->settings[ctx->id("router2/tmg_ripup")] = true; + if (vm.count("tmg-ripup") || vm.count("router2-tmg-ripup")) + ctx->settings[ctx->id("router/tmg_ripup")] = true; // Setting default values if (ctx->settings.find(ctx->id("target_freq")) == ctx->settings.end()) diff --git a/common/context.cc b/common/context.cc index 6bba5cbe..faddf825 100644 --- a/common/context.cc +++ b/common/context.cc @@ -90,6 +90,25 @@ WireId Context::getNetinfoSinkWire(const NetInfo *net_info, const PortRef &sink, return WireId(); } +delay_t Context::predictArcDelay(const NetInfo *net_info, const PortRef &sink) const +{ + if (net_info->driver.cell == nullptr || net_info->driver.cell->bel == BelId() || sink.cell->bel == BelId()) + return 0; + IdString driver_pin, sink_pin; + // Pick the first pin for a prediction; assume all will be similar enouhg + for (auto pin : getBelPinsForCellPin(net_info->driver.cell, net_info->driver.port)) { + driver_pin = pin; + break; + } + for (auto pin : getBelPinsForCellPin(sink.cell, sink.port)) { + sink_pin = pin; + break; + } + if (driver_pin == IdString() || sink_pin == IdString()) + return 0; + return predictDelay(net_info->driver.cell->bel, driver_pin, sink.cell->bel, sink_pin); +} + delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const { #ifdef ARCH_ECP5 @@ -98,7 +117,7 @@ delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &us #endif if (net_info->wires.empty()) - return predictDelay(net_info, user_info); + return predictArcDelay(net_info, user_info); WireId src_wire = getNetinfoSourceWire(net_info); if (src_wire == WireId()) @@ -128,7 +147,7 @@ delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &us if (cursor == src_wire) max_delay = std::max(max_delay, delay + getWireDelay(src_wire).maxDelay()); // routed else - max_delay = std::max(max_delay, predictDelay(net_info, user_info)); // unrouted + max_delay = std::max(max_delay, predictArcDelay(net_info, user_info)); // unrouted } return max_delay; } diff --git a/common/context.h b/common/context.h index 6adbbdb5..cb8fd257 100644 --- a/common/context.h +++ b/common/context.h @@ -51,6 +51,8 @@ struct Context : Arch, DeterministicRNG // -------------------------------------------------------------- + delay_t predictArcDelay(const NetInfo *net_info, const PortRef &sink) const; + WireId getNetinfoSourceWire(const NetInfo *net_info) const; SSOArray<WireId, 2> getNetinfoSinkWires(const NetInfo *net_info, const PortRef &sink) const; size_t getNetinfoSinkWireCount(const NetInfo *net_info, const PortRef &sink) const; diff --git a/common/hashlib.h b/common/hashlib.h index b71f0129..70de8c91 100644 --- a/common/hashlib.h +++ b/common/hashlib.h @@ -26,8 +26,11 @@ NEXTPNR_NAMESPACE_BEGIN const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; -// The XOR version of DJB2 -inline unsigned int mkhash(unsigned int a, unsigned int b) { return ((a << 5) + a) ^ b; } +// Cantor pairing function for two non-negative integers +// https://en.wikipedia.org/wiki/Pairing_function +inline unsigned int mkhash(unsigned int a, unsigned int b) { + return (a*a + 3*a + 2*a*b + b + b*b) / 2; +} // traditionally 5381 is used as starting value for the djb2 hash const unsigned int mkhash_init = 5381; diff --git a/common/nextpnr_namespaces.h b/common/nextpnr_namespaces.h index 6fb0aa77..b758d7c5 100644 --- a/common/nextpnr_namespaces.h +++ b/common/nextpnr_namespaces.h @@ -33,6 +33,8 @@ #define USING_NEXTPNR_NAMESPACE #endif +#define NPNR_UNUSED(x) ((void)x) + #if defined(__GNUC__) || defined(__clang__) #define NPNR_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) #define NPNR_NORETURN __attribute__((noreturn)) diff --git a/common/place_common.cc b/common/place_common.cc index bcfa3633..e03fca55 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -50,7 +50,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type if (load_cell->bel == BelId()) continue; if (timing_driven) { - delay_t net_delay = ctx->predictDelay(net, load); + delay_t net_delay = ctx->predictArcDelay(net, load); auto slack = load.budget - net_delay; if (slack < 0) negative_slack += slack; diff --git a/common/placer1.cc b/common/placer1.cc index 4db1c951..6de035b4 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -866,11 +866,11 @@ class SAPlacer if (ctx->getPortTimingClass(net->driver.cell, net->driver.port, cc) == TMG_IGNORE) return 0; if (cfg.budgetBased) { - double delay = ctx->getDelayNS(ctx->predictDelay(net, net->users.at(user))); + double delay = ctx->getDelayNS(ctx->predictArcDelay(net, net->users.at(user))); return std::min(10.0, std::exp(delay - ctx->getDelayNS(net->users.at(user).budget) / 10)); } else { float crit = tmg.get_criticality(CellPortKey(net->users.at(user))); - double delay = ctx->getDelayNS(ctx->predictDelay(net, net->users.at(user))); + double delay = ctx->getDelayNS(ctx->predictArcDelay(net, net->users.at(user))); return delay * std::pow(crit, crit_exp); } } diff --git a/common/pybindings.cc b/common/pybindings.cc index f9ee9eb7..eef460ce 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -83,6 +83,8 @@ template <> struct string_converter<Property> } // namespace PythonConversion +std::string loc_repr_py(Loc loc) { return stringf("Loc(%d, %d, %d)", loc.x, loc.y, loc.z); } + PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m) { py::register_exception_translator([](std::exception_ptr p) { @@ -175,7 +177,8 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m) .def(py::init<int, int, int>()) .def_readwrite("x", &Loc::x) .def_readwrite("y", &Loc::y) - .def_readwrite("z", &Loc::z); + .def_readwrite("z", &Loc::z) + .def("__repr__", loc_repr_py); auto ci_cls = py::class_<ContextualWrapper<CellInfo &>>(m, "CellInfo"); readwrite_wrapper<CellInfo &, decltype(&CellInfo::name), &CellInfo::name, conv_to_str<IdString>, diff --git a/common/pywrappers.h b/common/pywrappers.h index 66dec6fb..60ef65be 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -257,7 +257,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1)); + (base.*fn)(arg1_conv()(ctx, arg1)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -280,7 +280,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)); + (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -304,7 +304,7 @@ struct fn_wrapper_3a_v { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)); + (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -331,8 +331,7 @@ struct fn_wrapper_4a_v { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), - arg4_conv()(ctx, arg4)); + (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -360,8 +359,8 @@ struct fn_wrapper_5a_v { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), - arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5)); + (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4), + arg5_conv()(ctx, arg5)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -390,8 +389,8 @@ struct fn_wrapper_6a_v { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), - arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6)); + (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), arg4_conv()(ctx, arg4), + arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6)); } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } diff --git a/common/router1.cc b/common/router1.cc index 0ff2bedd..f387aee1 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -117,14 +117,24 @@ struct Router1 int arcs_without_ripup = 0; bool ripup_flag; - Router1(Context *ctx, const Router1Cfg &cfg) : ctx(ctx), cfg(cfg) {} + TimingAnalyser tmg; + + bool timing_driven = true; + + Router1(Context *ctx, const Router1Cfg &cfg) : ctx(ctx), cfg(cfg), tmg(ctx) + { + timing_driven = ctx->setting<bool>("timing_driven"); + tmg.setup(); + tmg.run(); + } void arc_queue_insert(const arc_key &arc, WireId src_wire, WireId dst_wire) { if (queued_arcs.count(arc)) return; - delay_t pri = ctx->estimateDelay(src_wire, dst_wire) - arc.net_info->users[arc.user_idx].budget; + delay_t pri = ctx->estimateDelay(src_wire, dst_wire) * + (100 * tmg.get_criticality(CellPortKey(arc.net_info->users.at(arc.user_idx)))); arc_entry entry; entry.arc = arc; @@ -459,6 +469,8 @@ struct Router1 auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], arc.phys_idx); ripup_flag = false; + float crit = tmg.get_criticality(CellPortKey(net_info->users.at(user_idx))); + if (ctx->debug) { log("Routing arc %d on net %s (%d arcs total):\n", user_idx, ctx->nameOf(net_info), int(net_info->users.size())); @@ -536,6 +548,7 @@ struct Router1 delay_t next_delay = qw.delay + ctx->getPipDelay(pip).maxDelay(); delay_t next_penalty = qw.penalty; delay_t next_bonus = qw.bonus; + delay_t penalty_delta = 0; WireId next_wire = ctx->getPipDstWire(pip); next_delay += ctx->getWireDelay(next_wire).maxDelay(); @@ -544,7 +557,7 @@ struct Router1 NetInfo *conflictWireNet = nullptr, *conflictPipNet = nullptr; if (net_info->wires.count(next_wire) && net_info->wires.at(next_wire).pip == pip) { - next_bonus += cfg.reuseBonus; + next_bonus += cfg.reuseBonus * (1.0 - crit); } else { if (!ctx->checkWireAvail(next_wire)) { if (!ripup) @@ -609,34 +622,36 @@ struct Router1 if (conflictWireWire != WireId()) { auto scores_it = wireScores.find(conflictWireWire); if (scores_it != wireScores.end()) - next_penalty += scores_it->second * cfg.wireRipupPenalty; - next_penalty += cfg.wireRipupPenalty; + penalty_delta += scores_it->second * cfg.wireRipupPenalty; + penalty_delta += cfg.wireRipupPenalty; } if (conflictPipWire != WireId()) { auto scores_it = wireScores.find(conflictPipWire); if (scores_it != wireScores.end()) - next_penalty += scores_it->second * cfg.wireRipupPenalty; - next_penalty += cfg.wireRipupPenalty; + penalty_delta += scores_it->second * cfg.wireRipupPenalty; + penalty_delta += cfg.wireRipupPenalty; } if (conflictWireNet != nullptr) { auto scores_it = netScores.find(conflictWireNet); if (scores_it != netScores.end()) - next_penalty += scores_it->second * cfg.netRipupPenalty; - next_penalty += cfg.netRipupPenalty; - next_penalty += conflictWireNet->wires.size() * cfg.wireRipupPenalty; + penalty_delta += scores_it->second * cfg.netRipupPenalty; + penalty_delta += cfg.netRipupPenalty; + penalty_delta += conflictWireNet->wires.size() * cfg.wireRipupPenalty; } if (conflictPipNet != nullptr) { auto scores_it = netScores.find(conflictPipNet); if (scores_it != netScores.end()) - next_penalty += scores_it->second * cfg.netRipupPenalty; - next_penalty += cfg.netRipupPenalty; - next_penalty += conflictPipNet->wires.size() * cfg.wireRipupPenalty; + penalty_delta += scores_it->second * cfg.netRipupPenalty; + penalty_delta += cfg.netRipupPenalty; + penalty_delta += conflictPipNet->wires.size() * cfg.wireRipupPenalty; } } + next_penalty += penalty_delta * (timing_driven ? std::max(0.05, (1.0 - crit)) : 1); + delay_t next_score = next_delay + next_penalty; NPNR_ASSERT(next_score >= 0); @@ -778,6 +793,53 @@ struct Router1 return true; } + + delay_t find_slack_thresh() + { + // If more than 5% of arcs have negative slack; use the 5% threshold as a ripup criteria + int arc_count = 0; + int failed_count = 0; + delay_t default_thresh = ctx->getDelayEpsilon(); + + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); + if (skip_net(ni)) + continue; + for (size_t i = 0; i < ni->users.size(); i++) { + auto &usr = ni->users.at(i); + ++arc_count; + delay_t slack = tmg.get_setup_slack(CellPortKey(usr)); + if (slack == std::numeric_limits<delay_t>::min()) + continue; + if (slack < default_thresh) + ++failed_count; + } + } + + if (arc_count < 50 || (failed_count < (0.05 * arc_count))) { + return default_thresh; + } + + std::vector<delay_t> slacks; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); + if (skip_net(ni)) + continue; + for (size_t i = 0; i < ni->users.size(); i++) { + auto &usr = ni->users.at(i); + delay_t slack = tmg.get_setup_slack(CellPortKey(usr)); + if (slack == std::numeric_limits<delay_t>::min()) + continue; + slacks.push_back(slack); + } + } + std::sort(slacks.begin(), slacks.end()); + delay_t thresh = slacks.at(int(slacks.size() * 0.05)); + log_warning("%.f%% of arcs have failing slack; using %.2fns as ripup threshold. Consider a reduced Fmax " + "constraint.\n", + (100.0 * failed_count) / arc_count, ctx->getDelayNS(thresh)); + return thresh; + } }; } // namespace @@ -819,6 +881,9 @@ bool router1(Context *ctx, const Router1Cfg &cfg) int iter_cnt = 0; int last_arcs_with_ripup = 0; int last_arcs_without_ripup = 0; + int timing_fail_count = 0; + bool timing_ripup = ctx->setting<bool>("router/tmg_ripup", false); + delay_t ripup_slack = 0; log_info(" | (re-)routed arcs | delta | remaining| time spent |\n"); log_info(" IterCnt | w/ripup wo/ripup | w/r wo/r | arcs| batch(sec) total(sec)|\n"); @@ -854,6 +919,48 @@ bool router1(Context *ctx, const Router1Cfg &cfg) #endif return false; } + // Timing driven ripup + if (timing_ripup && router.arc_queue.empty() && timing_fail_count < 50) { + ++timing_fail_count; + router.tmg.run(); + delay_t wns = 0, tns = 0; + if (timing_fail_count == 1) + ripup_slack = router.find_slack_thresh(); + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); + if (router.skip_net(ni)) + continue; + bool is_locked = false; + for (auto &wire : ni->wires) { + if (wire.second.strength > STRENGTH_STRONG) + is_locked = true; + } + if (is_locked) + continue; + for (size_t i = 0; i < ni->users.size(); i++) { + auto &usr = ni->users.at(i); + delay_t slack = router.tmg.get_setup_slack(CellPortKey(usr)); + if (slack == std::numeric_limits<delay_t>::min()) + continue; + if (slack < 0) { + wns = std::min(wns, slack); + tns += slack; + } + if (slack <= ripup_slack) { + for (WireId w : ctx->getNetinfoSinkWires(ni, usr)) { + if (ctx->checkWireAvail(w)) + continue; + router.ripup_wire(w); + } + } + } + } + log_info(" %d arcs ripped up due to negative slack WNS=%.02fns TNS=%.02fns.\n", + int(router.arc_queue.size()), ctx->getDelayNS(wns), ctx->getDelayNS(tns)); + iter_cnt = 0; + router.wireScores.clear(); + router.netScores.clear(); + } } auto rend = std::chrono::high_resolution_clock::now(); log_info("%10d | %8d %10d | %4d %5d | %9d| %10.02f %10.02f|\n", iter_cnt, router.arcs_with_ripup, diff --git a/common/router2.cc b/common/router2.cc index d713cce2..c76e1f61 100644 --- a/common/router2.cc +++ b/common/router2.cc @@ -1373,8 +1373,8 @@ struct Router2 route_queue.push_back(i); timing_driven = ctx->setting<bool>("timing_driven"); - if (ctx->settings.count(ctx->id("router2/tmg_ripup"))) - timing_driven_ripup = timing_driven && ctx->setting<bool>("router2/tmg_ripup"); + if (ctx->settings.count(ctx->id("router/tmg_ripup"))) + timing_driven_ripup = timing_driven && ctx->setting<bool>("router/tmg_ripup"); else timing_driven_ripup = false; log_info("Running main router loop...\n"); diff --git a/common/sso_array.h b/common/sso_array.h index 1fae6c57..80e7d1c1 100644 --- a/common/sso_array.h +++ b/common/sso_array.h @@ -70,6 +70,26 @@ template <typename T, std::size_t N> class SSOArray std::copy(other.begin(), other.end(), begin()); } + SSOArray(SSOArray &&other) : m_size(other.size()) + { + if (is_heap()) + data_heap = other.data_heap; + else + std::copy(other.begin(), other.end(), begin()); + other.m_size = 0; + } + SSOArray &operator=(const SSOArray &other) + { + if (&other == this) + return *this; + if (is_heap()) + delete[] data_heap; + m_size = other.m_size; + alloc(); + std::copy(other.begin(), other.end(), begin()); + return *this; + } + template <typename Tother> SSOArray(const Tother &other) : m_size(other.size()) { alloc(); diff --git a/common/timing.cc b/common/timing.cc index e305d82d..f30d4fc5 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -1378,7 +1378,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p auto driver_wire = ctx->getNetinfoSourceWire(net); auto sink_wire = ctx->getNetinfoSinkWire(net, sink_ref, 0); log_info(" prediction: %f ns estimate: %f ns\n", - ctx->getDelayNS(ctx->predictDelay(net, sink_ref)), + ctx->getDelayNS(ctx->predictArcDelay(net, sink_ref)), ctx->getDelayNS(ctx->estimateDelay(driver_wire, sink_wire))); auto cursor = sink_wire; delay_t delay; diff --git a/common/timing_opt.cc b/common/timing_opt.cc index 6dd93d67..a73a70cf 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -99,7 +99,7 @@ class TimingOptimiser continue; for (auto user : net->users) { if (user.cell == cell && user.port == port.first) { - if (ctx->predictDelay(net, user) > + if (ctx->predictArcDelay(net, user) > 1.1 * max_net_delay.at(std::make_pair(cell->name, port.first))) return false; } @@ -111,7 +111,7 @@ class TimingOptimiser BelId dstBel = user.cell->bel; if (dstBel == BelId()) continue; - if (ctx->predictDelay(net, user) > + if (ctx->predictArcDelay(net, user) > 1.1 * max_net_delay.at(std::make_pair(user.cell->name, user.port))) { return false; @@ -413,7 +413,7 @@ class TimingOptimiser 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); + original_delay += ctx->predictArcDelay(pn, usr); break; } } @@ -497,7 +497,7 @@ class TimingOptimiser 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) { - total_delay += ctx->predictDelay(pn, usr); + total_delay += ctx->predictArcDelay(pn, usr); break; } } |