ecp5: Fix db import, improve timing data debugging
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
19cc284b8c
commit
13244e513b
@ -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) {
|
||||
|
29
ecp5/arch.cc
29
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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user