aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorMaciej Kurc <mkurc@antmicro.com>2021-09-10 15:44:46 +0200
committerMaciej Kurc <mkurc@antmicro.com>2021-09-28 17:42:51 +0200
commitc6dc1f535acd2e9d0893ac17c9fa204e8b2370a6 (patch)
tree2c59c1b9ed98f7cdd3e986b26354263b966e7549 /common
parentd8571b6c008fd89a3dc59122dccaf16054b7c592 (diff)
downloadnextpnr-c6dc1f535acd2e9d0893ac17c9fa204e8b2370a6.tar.gz
nextpnr-c6dc1f535acd2e9d0893ac17c9fa204e8b2370a6.tar.bz2
nextpnr-c6dc1f535acd2e9d0893ac17c9fa204e8b2370a6.zip
Added reporting critical paths in JSON format
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
Diffstat (limited to 'common')
-rw-r--r--common/timing.cc74
1 files changed, 49 insertions, 25 deletions
diff --git a/common/timing.cc b/common/timing.cc
index 596058eb..8c4002d0 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -1251,8 +1251,8 @@ CriticalPathReport build_critical_path_report(Context* ctx, ClockPair &clocks, c
seg_logic.type = CriticalPathSegment::Type::LOGIC;
seg_logic.delay = setup;
seg_logic.budget = 0;
- seg_logic.from = std::make_pair(nullptr, IdString());
- seg_logic.to = std::make_pair(const_cast<CellInfo*>(last_cell), last_port);
+ seg_logic.from = std::make_pair(const_cast<CellInfo*>(last_cell), last_port);
+ seg_logic.to = seg_logic.from;
seg_logic.net = nullptr;
report.segments.push_back(seg_logic);
}
@@ -1366,7 +1366,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
if (segment.type == CriticalPathSegment::Type::LOGIC) {
logic_total += segment.delay;
- if (segment.from.first != nullptr) {
+ if (segment.from != segment.to) {
log_info("%4.1f %4.1f Source %s.%s\n",
ctx->getDelayNS(segment.delay),
ctx->getDelayNS(total),
@@ -1567,16 +1567,6 @@ void write_timing_report(
const DetailedNetTimings& detailed_net_timings
)
{
- auto cellport_name = [ctx](const PortRef& port) {
- std::string str;
- if (port.cell != nullptr) {
- str = std::string(port.cell->name.c_str(ctx));
- } else {
- str = "<none>"; // FIXME: When does that happen?
- }
- return str + "." + std::string(port.port.c_str(ctx));
- };
-
auto event_name = [ctx](const ClockEvent &e) {
std::string value;
if (e.clock == ctx->id("$async$"))
@@ -1587,8 +1577,46 @@ void write_timing_report(
return value;
};
-// auto report_critical_path = [ctx](const ClockPair &clocks, const PortRefVector &path) {
-// }
+ auto report_critical_path = [ctx](const CriticalPathReport& report) {
+ Json::array pathJson;
+
+ for (const auto& segment : report.segments) {
+
+ auto fromLoc = ctx->getBelLocation(segment.from.first->bel);
+ auto toLoc = ctx->getBelLocation(segment.to.first->bel);
+
+ auto fromJson = Json::object({
+ {"cell", segment.from.first->name.c_str(ctx)},
+ {"port", segment.from.second.c_str(ctx)},
+ {"loc", Json::array({fromLoc.x, fromLoc.y})}
+ });
+
+ auto toJson = Json::object({
+ {"cell", segment.to.first->name.c_str(ctx)},
+ {"port", segment.to.second.c_str(ctx)},
+ {"loc", Json::array({toLoc.x, toLoc.y})}
+ });
+
+ auto segmentJson = Json::object({
+ {"delay", ctx->getDelayNS(segment.delay)},
+ {"from", fromJson},
+ {"to", toJson},
+ });
+
+ if (segment.type == CriticalPathSegment::Type::LOGIC) {
+ segmentJson["type"] = "logic";
+ }
+ else if (segment.type == CriticalPathSegment::Type::ROUTING) {
+ segmentJson["type"] = "routing";
+ segmentJson["net"] = segment.net->name.c_str(ctx);
+ segmentJson["budget"] = ctx->getDelayNS(segment.budget);
+ }
+
+ pathJson.push_back(segmentJson);
+ }
+
+ return pathJson;
+ };
// Open the file
FILE* fp = fopen(file_name.c_str(), "w");
@@ -1601,11 +1629,8 @@ void write_timing_report(
critPathsJson.push_back(Json::object({
{"from", event_name(report.second.clock_pair.start)},
{"to", event_name(report.second.clock_pair.end)},
- {"path", Json()}
+ {"path", report_critical_path(report.second)}
}));
-
- //auto &crit_path = clock.second.second.ports;
- //print_path_report(clock.second.first, crit_path);
}
// Cross-domain paths
@@ -1613,17 +1638,14 @@ void write_timing_report(
critPathsJson.push_back(Json::object({
{"from", event_name(report.clock_pair.start)},
{"to", event_name(report.clock_pair.end)},
- {"path", Json()}
+ {"path", report_critical_path(report)}
}));
-// auto &crit_path = crit_paths.at(xclock).ports;
-// print_path_report(xclock, crit_path);
}
// Detailed per-net timing analysis
auto detailedNetTimingsJson = Json::array();
for (const auto& it : detailed_net_timings) {
const NetInfo* net = it.first;
- const std::string drv_port = cellport_name(net->driver);
ClockEvent start = it.second[0].clock_pair.start;
@@ -1635,7 +1657,8 @@ void write_timing_report(
NPNR_ASSERT(sink_timing.clock_pair.start == start);
auto endpointJson = Json::object({
- {"sink", cellport_name(sink_timing.sink)},
+ {"cell", sink_timing.sink.cell->name.c_str(ctx)},
+ {"port", sink_timing.sink.port.c_str(ctx)},
{"event", event_name(sink_timing.clock_pair.end)},
{"delay", ctx->getDelayNS(sink_timing.delay)},
{"budget", ctx->getDelayNS(sink_timing.budget)}
@@ -1645,7 +1668,8 @@ void write_timing_report(
auto netTimingJson = Json::object({
{"net", net->name.c_str(ctx)},
- {"driver", drv_port},
+ {"driver", net->driver.cell->name.c_str(ctx)},
+ {"port", net->driver.port.c_str(ctx)},
{"event", event_name(start)},
{"endpoints", endpointsJson}
});