diff options
author | David Shah <dave@ds0.me> | 2019-02-07 19:19:15 +0000 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2019-02-25 11:49:25 +0000 |
commit | 55b0b60d9d58961bfefea66fcc197b399424d9d6 (patch) | |
tree | eafd31eed747136436d5b9d082f3a7cabb320429 | |
parent | f5b11ce075544d00ccafaf4363d099b6f1806335 (diff) | |
download | nextpnr-55b0b60d9d58961bfefea66fcc197b399424d9d6.tar.gz nextpnr-55b0b60d9d58961bfefea66fcc197b399424d9d6.tar.bz2 nextpnr-55b0b60d9d58961bfefea66fcc197b399424d9d6.zip |
ecp5: Router performance improvements
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r-- | common/timing.cc | 4 | ||||
-rw-r--r-- | ecp5/arch.cc | 21 | ||||
-rw-r--r-- | ecp5/arch.h | 2 | ||||
-rwxr-xr-x | ecp5/trellis_import.py | 10 |
4 files changed, 30 insertions, 7 deletions
diff --git a/common/timing.cc b/common/timing.cc index 64dcdf71..db38b11b 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -837,6 +837,10 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p auto cursor = sink_wire; delay_t delay; while (driver_wire != cursor) { +#ifdef ARCH_ECP5 + if (net->is_global) + break; +#endif auto it = net->wires.find(cursor); assert(it != net->wires.end()); auto pip = it->second.pip; diff --git a/ecp5/arch.cc b/ecp5/arch.cc index ad207d14..2bce0b01 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -427,6 +427,16 @@ BelId Arch::getBelByLocation(Loc loc) const delay_t Arch::estimateDelay(WireId src, WireId dst) const { + WireId cursor = dst; + + int num_uh = locInfo(dst)->wire_data[dst.index].num_uphill; + if (num_uh < 6) { + for (auto uh : getPipsUphill(dst)) { + if (getPipSrcWire(uh) == src) + return getPipDelay(uh).maxDelay(); + } + } + auto est_location = [&](WireId w) -> std::pair<int16_t, int16_t> { if (w.location.x == 0 && w.location.y == 0) { // Global wires @@ -448,7 +458,8 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const auto src_loc = est_location(src), dst_loc = est_location(dst); - return (110 - 10 * args.speed) + (200 - 20 * args.speed) * (abs(src_loc.first - dst_loc.first) + abs(src_loc.second - dst_loc.second)); + int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second); + return (130 - 13 * args.speed) * (4 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const @@ -458,16 +469,18 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 0; auto driver_loc = getBelLocation(driver.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel); - return (110 - 10 * args.speed) + (200 - 20 * args.speed) * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y)); + + int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y); + return (130 - 13 * args.speed) * (4 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { if (net_info->driver.port == id_FCO && sink.port == id_FCI) { - return true; budget = 0; - } else if (sink.port == id_FXA || sink.port == id_FXB) { return true; + } else if (sink.port == id_FXA || sink.port == id_FXB) { budget = 0; + return true; } else { return false; } diff --git a/ecp5/arch.h b/ecp5/arch.h index 6a2f2bf5..ee412cca 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -918,7 +918,7 @@ struct Arch : BaseCtx delay_t estimateDelay(WireId src, WireId dst) const; delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; delay_t getDelayEpsilon() const { return 20; } - delay_t getRipupDelayPenalty() const { return 200; } + delay_t getRipupDelayPenalty() const { return 500; } float getDelayNS(delay_t v) const { return v * 0.001; } DelayInfo getDelayFromNS(float ns) const { diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py index 6acc32c5..610bd331 100755 --- a/ecp5/trellis_import.py +++ b/ecp5/trellis_import.py @@ -153,7 +153,7 @@ speed_grade_names = ["6", "7", "8", "8_5G"] speed_grade_cells = {} speed_grade_pips = {} -pip_class_to_idx = {"default": 0} +pip_class_to_idx = {"default": 0, "zero": 1} timing_port_xform = { "RAD0": "D0", @@ -199,7 +199,7 @@ def process_timing_data(): pip_class_delays = [] for i in range(len(pip_class_to_idx)): pip_class_delays.append((50, 50, 0, 0)) - + pip_class_delays[pip_class_to_idx["zero"]] = (0, 0, 0, 0) with open(timing_dbs.interconnect_db_path("ECP5", grade)) as f: interconn_data = json.load(f) for pipclass, pipdata in sorted(interconn_data.items()): @@ -219,6 +219,12 @@ def process_timing_data(): def get_pip_class(wire_from, wire_to): + + if "FCO" in wire_from or "FCI" in wire_to: + return pip_class_to_idx["zero"] + if "F5" in wire_from or "FX" in wire_from or "FXA" in wire_to or "FXB" in wire_to: + return pip_class_to_idx["zero"] + class_name = pip_classes.get_pip_class(wire_from, wire_to) if class_name is None or class_name not in pip_class_to_idx: class_name = "default" |