diff options
-rw-r--r-- | common/placer1.cc | 3 | ||||
-rw-r--r-- | common/timing.cc | 43 | ||||
-rw-r--r-- | docs/archapi.md | 4 | ||||
-rw-r--r-- | ecp5/arch.cc | 2 | ||||
-rw-r--r-- | ecp5/arch.h | 2 | ||||
-rw-r--r-- | generic/arch.cc | 2 | ||||
-rw-r--r-- | generic/arch.h | 2 | ||||
-rw-r--r-- | ice40/arch.cc | 27 | ||||
-rw-r--r-- | ice40/arch.h | 2 | ||||
-rw-r--r-- | ice40/main.cc | 1 |
10 files changed, 57 insertions, 31 deletions
diff --git a/common/placer1.cc b/common/placer1.cc index 4ba0f3cf..1d00e77a 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -138,7 +138,8 @@ class SAPlacer if ((placed_cells - constr_placed_cells) % 500 != 0) log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), int(autoplaced.size())); - assign_budget(ctx); + if (ctx->slack_redist_iter > 0) + assign_budget(ctx); ctx->yield(); log_info("Running simulated annealing placer.\n"); diff --git a/common/timing.cc b/common/timing.cc index d214793c..c00e1ba5 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 David Shah <david@symbioticeda.com> + * Copyright (C) 2018 Eddie Hung <eddieh@ece.ubc.ca> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,36 +33,42 @@ typedef std::map<int, unsigned> DelayFrequency; struct Timing { Context *ctx; + bool net_delays; bool update; delay_t min_slack; PortRefVector current_path; PortRefVector *crit_path; DelayFrequency *slack_histogram; - Timing(Context *ctx, bool update, PortRefVector *crit_path = nullptr, DelayFrequency *slack_histogram = nullptr) - : ctx(ctx), update(update), min_slack(1.0e12 / ctx->target_freq), crit_path(crit_path), - slack_histogram(slack_histogram) + Timing(Context *ctx, bool net_delays, bool update, PortRefVector *crit_path = nullptr, + DelayFrequency *slack_histogram = nullptr) + : ctx(ctx), net_delays(net_delays), update(update), min_slack(1.0e12 / ctx->target_freq), + crit_path(crit_path), slack_histogram(slack_histogram) { } delay_t follow_net(NetInfo *net, int path_length, delay_t slack) { - delay_t net_budget = slack / (path_length + 1); + const delay_t default_budget = slack / (path_length + 1); + delay_t net_budget = default_budget; for (auto &usr : net->users) { + auto delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t(); if (crit_path) current_path.push_back(&usr); - // If budget override is less than existing budget, then do not increment - // path length - int pl = path_length + 1; - auto budget = ctx->getBudgetOverride(net, usr, net_budget); - if (budget < net_budget) { - net_budget = budget; - pl = std::max(1, path_length); + // If budget override exists, use that value and do not increment path_length + auto budget = default_budget; + if (ctx->getBudgetOverride(net, usr, budget)) { + if (update) + usr.budget = std::min(usr.budget, budget); + budget = follow_user_port(usr, path_length, slack - budget); + net_budget = std::min(net_budget, budget); + } + else { + budget = follow_user_port(usr, path_length + 1, slack - delay); + net_budget = std::min(net_budget, budget); + if (update) + usr.budget = std::min(usr.budget, delay + budget); } - auto delay = ctx->getNetinfoRouteDelay(net, usr); - net_budget = std::min(net_budget, follow_user_port(usr, pl, slack - delay)); - if (update) - usr.budget = std::min(usr.budget, delay + net_budget); if (crit_path) current_path.pop_back(); } @@ -149,10 +156,10 @@ void assign_budget(Context *ctx, bool quiet) { if (!quiet) { log_break(); - log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->target_freq/1e6); + log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->target_freq / 1e6); } - Timing timing(ctx, true /* update */); + Timing timing(ctx, ctx->slack_redist_iter > 0 /* net_delays */, true /* update */); timing.assign_budget(); if (!quiet || ctx->verbose) { @@ -194,7 +201,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path) PortRefVector crit_path; DelayFrequency slack_histogram; - Timing timing(ctx, false /* update */, print_path ? &crit_path : nullptr, + Timing timing(ctx, true /* net_delays */, false /* update */, print_path ? &crit_path : nullptr, print_histogram ? &slack_histogram : nullptr); auto min_slack = timing.walk_paths(); diff --git a/docs/archapi.md b/docs/archapi.md index 79562fe6..222b9f78 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -402,9 +402,9 @@ Convert an `delay_t` to an actual real-world delay in nanoseconds. Convert a `delay_t` to an integer for checksum calculations. -### delay\_t getBudgetOverride(const NetInfo \*net\_info, const PortRef &sink, delay\_t budget) const +### bool getBudgetOverride(const NetInfo \*net\_info, const PortRef &sink, delay\_t &budget) const -Overwrite or modify the timing budget for a given arc. Returns the new budget. +Overwrite or modify (in-place) the timing budget for a given arc. Returns a bool to indicate whether this was done. Flow Methods ------------ diff --git a/ecp5/arch.cc b/ecp5/arch.cc index d72b0085..d2d62241 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -422,7 +422,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 200 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y)); } -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const { return budget; } +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; } // ----------------------------------------------------------------------- diff --git a/ecp5/arch.h b/ecp5/arch.h index 74f0c4e1..e00e111a 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -805,7 +805,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } uint32_t getDelayChecksum(delay_t v) const { return v; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; // ------------------------------------------------- diff --git a/generic/arch.cc b/generic/arch.cc index 7e65d411..0fa93da8 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -408,7 +408,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return (dx + dy) * grid_distance_to_delay; } -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const { return budget; } +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; } // --------------------------------------------------------------- diff --git a/generic/arch.h b/generic/arch.h index a5b3470f..59fe8d05 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -200,7 +200,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 1.0; } float getDelayNS(delay_t v) const { return v; } uint32_t getDelayChecksum(delay_t v) const { return 0; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; bool pack() { return true; } bool place(); diff --git a/ice40/arch.cc b/ice40/arch.cc index 0b168383..fcc9d798 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -637,17 +637,34 @@ std::vector<GroupId> Arch::getGroupGroups(GroupId group) const // ----------------------------------------------------------------------- -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { const auto &driver = net_info->driver; - if (driver.port == id_cout) { + if (driver.port == id_cout && sink.port == id_cin) { auto driver_loc = getBelLocation(driver.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel); if (driver_loc.y == sink_loc.y) - return 0; - return 250; + budget = 0; + else switch (args.type) { +#ifndef ICE40_HX1K_ONLY + case ArchArgs::HX8K: +#endif + case ArchArgs::HX1K: + budget = 190; break; +#ifndef ICE40_HX1K_ONLY + case ArchArgs::LP384: + case ArchArgs::LP1K: + case ArchArgs::LP8K: + budget = 290; break; + case ArchArgs::UP5K: + budget = 560; break; +#endif + default: + log_error("Unsupported iCE40 chip type.\n"); + } + return true; } - return budget; + return false; } // ----------------------------------------------------------------------- diff --git a/ice40/arch.h b/ice40/arch.h index 236f73f1..328950df 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -766,7 +766,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } uint32_t getDelayChecksum(delay_t v) const { return v; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; // ------------------------------------------------- diff --git a/ice40/main.cc b/ice40/main.cc index 358bf3c5..78236af1 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -366,6 +366,7 @@ int main(int argc, char *argv[]) if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); + assign_budget(ctx.get()); ctx->check(); print_utilisation(ctx.get()); if (!vm.count("pack-only")) { |