aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-02-07 19:19:15 +0000
committerDavid Shah <dave@ds0.me>2019-02-25 11:49:25 +0000
commit55b0b60d9d58961bfefea66fcc197b399424d9d6 (patch)
treeeafd31eed747136436d5b9d082f3a7cabb320429
parentf5b11ce075544d00ccafaf4363d099b6f1806335 (diff)
downloadnextpnr-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.cc4
-rw-r--r--ecp5/arch.cc21
-rw-r--r--ecp5/arch.h2
-rwxr-xr-xecp5/trellis_import.py10
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"