aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2018-11-16 12:59:27 +0000
committerDavid Shah <dave@ds0.me>2018-11-16 13:26:28 +0000
commit13244e513b2a7454f2fa6d952df334439d28588a (patch)
tree954408662b0ed447bad6640eaef0889f37b97214
parent19cc284b8cd6293430dd8acc11ace73b8e13b287 (diff)
downloadnextpnr-13244e513b2a7454f2fa6d952df334439d28588a.tar.gz
nextpnr-13244e513b2a7454f2fa6d952df334439d28588a.tar.bz2
nextpnr-13244e513b2a7454f2fa6d952df334439d28588a.zip
ecp5: Fix db import, improve timing data debugging
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r--common/timing.cc16
-rw-r--r--ecp5/arch.cc29
-rw-r--r--ecp5/arch.h1
-rwxr-xr-xecp5/trellis_import.py14
4 files changed, 55 insertions, 5 deletions
diff --git a/common/timing.cc b/common/timing.cc
index 80be554c..00142a4d 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -554,6 +554,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
Fmax = 1000 / ctx->getDelayNS(path.second.path_delay);
else
Fmax = 500 / ctx->getDelayNS(path.second.path_delay);
+ log_info("%d %f\n", a.edge == b.edge, ctx->getDelayNS(path.second.path_delay));
if (!clock_fmax.count(a.clock) || Fmax < clock_fmax.at(a.clock)) {
clock_reports[a.clock] = path;
clock_fmax[a.clock] = Fmax;
@@ -608,6 +609,8 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
if (clknet != nullptr && clknet->name == clocks.start.clock &&
clockInfo.edge == clocks.start.edge) {
last_port = clockInfo.clock_port;
+ total += clockInfo.clockToQ.maxDelay();
+ break;
}
}
}
@@ -623,7 +626,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
if (last_port == driver.port) {
// Case where we start with a STARTPOINT etc
comb_delay = ctx->getDelayFromNS(0);
- } else {
+ } else if (total == 0) {
ctx->getCellDelay(sink_cell, last_port, driver.port, comb_delay);
}
total += comb_delay.maxDelay();
@@ -657,7 +660,18 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
}
}
last_port = sink->port;
+
}
+ int clockCount = 0;
+ auto sinkClass = ctx->getPortTimingClass(crit_path.back()->cell, crit_path.back()->port, clockCount);
+ if (sinkClass == TMG_REGISTER_INPUT && clockCount > 0) {
+ auto sinkClockInfo = ctx->getPortClockingInfo(crit_path.back()->cell, crit_path.back()->port, 0);
+ delay_t setup = sinkClockInfo.setup.maxDelay();
+ total += setup;
+ log_info("%4.1f %4.1f Setup %s.%s\n", ctx->getDelayNS(setup), ctx->getDelayNS(total),
+ crit_path.back()->cell->name.c_str(ctx), crit_path.back()->port.c_str(ctx));
+ }
+
};
for (auto &clock : clock_reports) {
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 25229f26..9b28f56b 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -422,7 +422,34 @@ bool Arch::route()
{
route_ecp5_globals(getCtx());
assign_budget(getCtx(), true);
- return router1(getCtx(), Router1Cfg(getCtx()));
+
+ bool result = router1(getCtx(), Router1Cfg(getCtx()));
+#if 0
+ std::vector<std::pair<WireId, int>> fanout_vector;
+ std::copy(wire_fanout.begin(), wire_fanout.end(), std::back_inserter(fanout_vector));
+ std::sort(fanout_vector.begin(), fanout_vector.end(), [](const std::pair<WireId, int> &a, const std::pair<WireId, int> &b) {
+ return a.second > b.second;
+ });
+ for (size_t i = 0; i < std::min(size_t(20), fanout_vector.size()); i++)
+ log_info(" fanout %s = %d\n", getWireName(fanout_vector[i].first).c_str(this), fanout_vector[i].second);
+ log_break();
+ PipId slowest_pip;
+ delay_t slowest_pipdelay = 0;
+ for (auto pip : pip_to_net) {
+ if (pip.second) {
+ delay_t dly = getPipDelay(pip.first).maxDelay();
+ if (dly > slowest_pipdelay) {
+ slowest_pip = pip.first;
+ slowest_pipdelay = dly;
+ }
+ }
+ }
+ log_info(" slowest pip %s = %.02f ns\n", getPipName(slowest_pip).c_str(this), getDelayNS(slowest_pipdelay));
+ log_info(" fanout %d\n", wire_fanout[getPipSrcWire(slowest_pip)]);
+ log_info(" base %d adder %d\n", speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_base_delay,
+ speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_fanout_adder);
+#endif
+ return result;
}
// -----------------------------------------------------------------------
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 52cca416..cf30876b 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -827,6 +827,7 @@ struct Arch : BaseCtx
auto fnd_fanout = wire_fanout.find(getPipSrcWire(pip));
if (fnd_fanout != wire_fanout.end())
fanout = fnd_fanout->second;
+ NPNR_ASSERT(locInfo(pip)->pip_data[pip.index].timing_class < speed_grade->num_pip_classes);
delay.min_delay = speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].min_base_delay
+ fanout * speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].min_fanout_adder;
delay.max_delay = speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].max_base_delay
diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py
index d9892a28..31f136a2 100755
--- a/ecp5/trellis_import.py
+++ b/ecp5/trellis_import.py
@@ -185,16 +185,24 @@ def process_timing_data():
else:
assert False, entry["type"]
cells.append((celltype, delays, setupholds))
- pip_class_delays = [(50, 50, 0, 0)] # default: 50ps delay, 0ps fanout
+ pip_class_delays = []
+ for i in range(len(pip_class_to_idx)):
+ pip_class_delays.append((50, 50, 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()):
- pip_class_to_idx[pipclass] = len(pip_class_delays)
+
min_delay = pipdata["delay"][0]
max_delay = pipdata["delay"][2]
min_fanout = pipdata["fanout"][0]
max_fanout = pipdata["fanout"][2]
- pip_class_delays.append((min_delay, max_delay, min_fanout, max_fanout))
+ if grade == "6":
+ pip_class_to_idx[pipclass] = len(pip_class_delays)
+ pip_class_delays.append((min_delay, max_delay, min_fanout, max_fanout))
+ else:
+ if pipclass in pip_class_to_idx:
+ pip_class_delays[pip_class_to_idx[pipclass]] = (min_delay, max_delay, min_fanout, max_fanout)
speed_grade_cells[grade] = cells
speed_grade_pips[grade] = pip_class_delays