diff --git a/common/kernel/context.cc b/common/kernel/context.cc index b194675d4e..0e99c1b6f0 100644 --- a/common/kernel/context.cc +++ b/common/kernel/context.cc @@ -116,10 +116,10 @@ delay_t Context::predictArcDelay(const NetInfo *net_info, const PortRef &sink) c delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const { -#ifdef ARCH_ECP5 - if (net_info->is_global) - return 0; -#endif + // #ifdef ARCH_ECP5 + // if (net_info->is_global) + // return 0; + // #endif if (net_info->wires.empty()) return predictArcDelay(net_info, user_info); @@ -417,7 +417,7 @@ void Context::check() const namespace { struct FixupHierarchyWorker { - FixupHierarchyWorker(Context *ctx) : ctx(ctx){}; + FixupHierarchyWorker(Context *ctx) : ctx(ctx) {}; Context *ctx; void run() { diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index bf3420bc37..20b95d3c5e 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -174,10 +174,20 @@ void TimingAnalyser::get_route_delays() NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr || ni->driver.cell->bel == BelId()) continue; + + if (clock_skew) { + printf("net %s has driver %s.%s\n", ni->name.c_str(ctx), ni->driver.cell->name.c_str(ctx), + ni->driver.port.c_str(ctx)); + } for (auto &usr : ni->users) { if (usr.cell->bel == BelId()) continue; ports.at(CellPortKey(usr)).route_delay = DelayPair(ctx->getNetinfoRouteDelay(ni, usr)); + + if (clock_skew) { + printf("\tuser %s.%s, delay: %f\n", usr.cell->name.c_str(ctx), usr.port.c_str(ctx), + ctx->getDelayNS(ctx->getNetinfoRouteDelay(ni, usr))); + } } } } @@ -567,12 +577,15 @@ void TimingAnalyser::walk_forward() auto &pd = ports.at(sp.first); DelayPair init_arrival(0); CellPortKey clock_key; - // TODO: clock routing delay, if analysis of that is enabled if (sp.second != IdString()) { // clocked startpoints have a clock-to-out time for (auto &fanin : pd.cell_arcs) { if (fanin.type == CellArc::CLK_TO_Q && fanin.other_port == sp.second) { - init_arrival = init_arrival + fanin.value.delayPair(); + init_arrival += fanin.value.delayPair(); + if (clock_skew) { + auto clock_delay = ports.at(CellPortKey(sp.first.cell, fanin.other_port)).route_delay; + init_arrival += clock_delay; + } break; } } @@ -619,20 +632,28 @@ void TimingAnalyser::walk_backward() auto &dom = domains.at(dom_id); for (auto &ep : dom.endpoints) { auto &pd = ports.at(ep.first); - DelayPair init_setuphold(0); + DelayPair init_required(0); CellPortKey clock_key; // TODO: clock routing delay, if analysis of that is enabled if (ep.second != IdString()) { // Add setup/hold time, if this endpoint is clocked for (auto &fanin : pd.cell_arcs) { - if (fanin.type == CellArc::SETUP && fanin.other_port == ep.second) - init_setuphold.min_delay -= fanin.value.maxDelay(); + printf("walk bwd %s.%s, fanin: %s, arctype: %s\n", ep.first.cell.c_str(ctx), + ep.first.port.c_str(ctx), fanin.other_port.c_str(ctx), arcType_to_str(fanin.type).c_str()); + + if (fanin.type == CellArc::SETUP && fanin.other_port == ep.second) { + if (clock_skew) { + auto clock_delay = ports.at(CellPortKey(ep.first.cell, fanin.other_port)).route_delay; + init_required += clock_delay; + } + init_required.min_delay -= fanin.value.maxDelay(); + } if (fanin.type == CellArc::HOLD && fanin.other_port == ep.second) - init_setuphold.max_delay -= fanin.value.maxDelay(); + init_required.max_delay -= fanin.value.maxDelay(); } clock_key = CellPortKey(ep.first.cell, ep.second); } - set_required_time(ep.first, dom_id, init_setuphold, 1, clock_key); + set_required_time(ep.first, dom_id, init_required, 1, clock_key); } } // Walk backwards in topological order @@ -1211,6 +1232,8 @@ void timing_analysis(Context *ctx, bool print_slack_histogram, bool print_fmax, bool update_results) { TimingAnalyser tmg(ctx); + tmg.setup_only = false; + tmg.clock_skew = true; tmg.setup(ctx->detailed_timing_report, print_slack_histogram, print_path || print_fmax); auto &result = tmg.get_timing_result(); diff --git a/common/kernel/timing.h b/common/kernel/timing.h index ac78be4b79..eea57700da 100644 --- a/common/kernel/timing.h +++ b/common/kernel/timing.h @@ -98,6 +98,10 @@ struct TimingAnalyser TimingResult &get_timing_result() { return result; } + // Enable analysis of clock skew between FFs. + // Only do this after legal placement + bool clock_skew = false; + bool setup_only = false; bool have_loops = false; bool updated_domains = false;