diff options
-rw-r--r-- | common/timing.cc | 16 | ||||
-rw-r--r-- | ecp5/arch.cc | 29 | ||||
-rw-r--r-- | ecp5/arch.h | 1 | ||||
-rwxr-xr-x | ecp5/trellis_import.py | 14 |
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 |