diff --git a/common/kernel/nextpnr_types.h b/common/kernel/nextpnr_types.h index ec1ac111..dd8eeecb 100644 --- a/common/kernel/nextpnr_types.h +++ b/common/kernel/nextpnr_types.h @@ -203,6 +203,32 @@ enum TimingPortClass TMG_IGNORE, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis }; +std::string tmgPortClass_to_str(TimingPortClass tmg_class) +{ + switch (tmg_class) { + case TMG_CLOCK_INPUT: + return "TMG_CLOCK_INPUT"; + case TMG_GEN_CLOCK: + return "TMG_GEN_CLOCK"; + case TMG_REGISTER_INPUT: + return "TMG_REGISTER_INPUT"; + case TMG_REGISTER_OUTPUT: + return "TMG_REGISTER_OUTPUT"; + case TMG_COMB_INPUT: + return "TMG_COMB_INPUT"; + case TMG_COMB_OUTPUT: + return "TMG_COMB_OUTPUT"; + case TMG_STARTPOINT: + return "TMG_STARTPOINT"; + case TMG_ENDPOINT: + return "TMG_ENDPOINT"; + case TMG_IGNORE: + return "TMG_IGNORE"; + default: + return "TMG_BOOM"; + } +} + enum ClockEdge { RISING_EDGE, diff --git a/common/kernel/timing.cc b/common/kernel/timing.cc index 105d20f9..30faaf46 100644 --- a/common/kernel/timing.cc +++ b/common/kernel/timing.cc @@ -826,16 +826,31 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, } } + // Set hold time + auto cell = cell_info(endpoint); + auto &port = port_info(endpoint); + int port_clocks; + auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks); + if (portClass == TMG_REGISTER_INPUT) { + for (int i = 0; i < port_clocks; i++) { + auto info = ctx->getPortClockingInfo(cell, port.name, i); + if (!cell->ports.count(info.clock_port) || cell->ports.at(info.clock_port).net == nullptr) + continue; + + report.bound.min_delay = info.hold.min_delay; + break; + } + } + pool> visited; std::vector crit_path_rev; auto cursor = endpoint; while (cursor != CellPortKey()) { - auto cell = cell_info(cursor); - auto &port = port_info(cursor); int port_clocks; auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks); + printf("%s.%s %s\n", cell->name.c_str(ctx), port.name.c_str(ctx), tmgPortClass_to_str(portClass)); // combinational loop if (!visited.insert(std::make_pair(cell->name, port.name)).second) @@ -848,6 +863,8 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, break; cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_max; + auto cell = cell_info(cursor); + auto &port = port_info(cursor); } auto crit_path = boost::adaptors::reverse(crit_path_rev);