Skip to content

Commit

Permalink
timing: Allow critical path traversal for shortest paths
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanG077 committed Sep 6, 2024
1 parent 2183bc6 commit e8863ce
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
2 changes: 1 addition & 1 deletion common/kernel/nextpnr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ 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)
static std::string tmgPortClass_to_str(TimingPortClass tmg_class)
{
switch (tmg_class) {
case TMG_CLOCK_INPUT:
Expand Down
25 changes: 15 additions & 10 deletions common/kernel/timing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,8 @@ std::vector<CellPortKey> TimingAnalyser::get_worst_eps(domain_id_t domain_pair,
return worst_eps;
}

CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, CellPortKey endpoint)
CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair, CellPortKey endpoint,
bool longest_path)
{
CriticalPath report;

Expand Down Expand Up @@ -846,11 +847,18 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair,
std::vector<PortRef> crit_path_rev;
auto cursor = endpoint;

while (cursor != CellPortKey()) {
auto next_cursor = [longest_path](ArrivReqTime &arrival) {
if (longest_path) {
return arrival.bwd_max;
}
return arrival.bwd_min;
};

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)
Expand All @@ -862,9 +870,7 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair,
if (!ports.at(cursor).arrival.count(dp.key.launch))
break;

cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_max;
auto cell = cell_info(cursor);
auto &port = port_info(cursor);
cursor = next_cursor(ports.at(cursor).arrival.at(dp.key.launch));
}

auto crit_path = boost::adaptors::reverse(crit_path_rev);
Expand All @@ -873,8 +879,7 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair,
auto &front_port = front.cell->ports.at(front.port);
auto &front_driver = front_port.net->driver;

int port_clocks;
auto portClass = ctx->getPortTimingClass(front_driver.cell, front_driver.port, port_clocks);
portClass = ctx->getPortTimingClass(front_driver.cell, front_driver.port, port_clocks);

const CellInfo *last_cell = front.cell;
IdString last_port = front_driver.port;
Expand Down Expand Up @@ -997,7 +1002,7 @@ void TimingAnalyser::build_crit_path_reports()
clock_fmax[launch.clock].achieved = Fmax;
clock_fmax[launch.clock].constraint = target;

clock_reports[launch.clock] = build_critical_path_report(i, worst_endpoint.at(0));
clock_reports[launch.clock] = build_critical_path_report(i, worst_endpoint.at(0), true);

empty_clocks.erase(launch.clock);
}
Expand All @@ -1015,7 +1020,7 @@ void TimingAnalyser::build_crit_path_reports()
if (worst_endpoint.empty())
continue;

xclock_reports.emplace_back(build_critical_path_report(i, worst_endpoint.at(0)));
xclock_reports.emplace_back(build_critical_path_report(i, worst_endpoint.at(0), true));
}

auto cmp_crit_path = [&](const CriticalPath &ra, const CriticalPath &rb) {
Expand Down
4 changes: 3 additions & 1 deletion common/kernel/timing.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ struct TimingAnalyser
void compute_criticality();

void build_detailed_net_timing_report();
CriticalPath build_critical_path_report(domain_id_t domain_pair, CellPortKey endpoint);
// longest_path indicate whether to follow the longest or shortest path from endpoint to startpoint
// longest paths are interesting for setup violations and shortest paths are interesting for hold violations
CriticalPath build_critical_path_report(domain_id_t domain_pair, CellPortKey endpoint, bool longest_path);
void build_crit_path_reports();
void build_slack_histogram_report();

Expand Down

0 comments on commit e8863ce

Please sign in to comment.