Added reporting critical paths in JSON format
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
d8571b6c00
commit
c6dc1f535a
@ -1251,8 +1251,8 @@ CriticalPathReport build_critical_path_report(Context* ctx, ClockPair &clocks, c
|
|||||||
seg_logic.type = CriticalPathSegment::Type::LOGIC;
|
seg_logic.type = CriticalPathSegment::Type::LOGIC;
|
||||||
seg_logic.delay = setup;
|
seg_logic.delay = setup;
|
||||||
seg_logic.budget = 0;
|
seg_logic.budget = 0;
|
||||||
seg_logic.from = std::make_pair(nullptr, IdString());
|
seg_logic.from = std::make_pair(const_cast<CellInfo*>(last_cell), last_port);
|
||||||
seg_logic.to = std::make_pair(const_cast<CellInfo*>(last_cell), last_port);
|
seg_logic.to = seg_logic.from;
|
||||||
seg_logic.net = nullptr;
|
seg_logic.net = nullptr;
|
||||||
report.segments.push_back(seg_logic);
|
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) {
|
if (segment.type == CriticalPathSegment::Type::LOGIC) {
|
||||||
logic_total += segment.delay;
|
logic_total += segment.delay;
|
||||||
if (segment.from.first != nullptr) {
|
if (segment.from != segment.to) {
|
||||||
log_info("%4.1f %4.1f Source %s.%s\n",
|
log_info("%4.1f %4.1f Source %s.%s\n",
|
||||||
ctx->getDelayNS(segment.delay),
|
ctx->getDelayNS(segment.delay),
|
||||||
ctx->getDelayNS(total),
|
ctx->getDelayNS(total),
|
||||||
@ -1567,16 +1567,6 @@ void write_timing_report(
|
|||||||
const DetailedNetTimings& detailed_net_timings
|
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) {
|
auto event_name = [ctx](const ClockEvent &e) {
|
||||||
std::string value;
|
std::string value;
|
||||||
if (e.clock == ctx->id("$async$"))
|
if (e.clock == ctx->id("$async$"))
|
||||||
@ -1587,8 +1577,46 @@ void write_timing_report(
|
|||||||
return value;
|
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
|
// Open the file
|
||||||
FILE* fp = fopen(file_name.c_str(), "w");
|
FILE* fp = fopen(file_name.c_str(), "w");
|
||||||
@ -1601,11 +1629,8 @@ void write_timing_report(
|
|||||||
critPathsJson.push_back(Json::object({
|
critPathsJson.push_back(Json::object({
|
||||||
{"from", event_name(report.second.clock_pair.start)},
|
{"from", event_name(report.second.clock_pair.start)},
|
||||||
{"to", event_name(report.second.clock_pair.end)},
|
{"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
|
// Cross-domain paths
|
||||||
@ -1613,17 +1638,14 @@ void write_timing_report(
|
|||||||
critPathsJson.push_back(Json::object({
|
critPathsJson.push_back(Json::object({
|
||||||
{"from", event_name(report.clock_pair.start)},
|
{"from", event_name(report.clock_pair.start)},
|
||||||
{"to", event_name(report.clock_pair.end)},
|
{"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
|
// Detailed per-net timing analysis
|
||||||
auto detailedNetTimingsJson = Json::array();
|
auto detailedNetTimingsJson = Json::array();
|
||||||
for (const auto& it : detailed_net_timings) {
|
for (const auto& it : detailed_net_timings) {
|
||||||
const NetInfo* net = it.first;
|
const NetInfo* net = it.first;
|
||||||
const std::string drv_port = cellport_name(net->driver);
|
|
||||||
|
|
||||||
ClockEvent start = it.second[0].clock_pair.start;
|
ClockEvent start = it.second[0].clock_pair.start;
|
||||||
|
|
||||||
@ -1635,7 +1657,8 @@ void write_timing_report(
|
|||||||
NPNR_ASSERT(sink_timing.clock_pair.start == start);
|
NPNR_ASSERT(sink_timing.clock_pair.start == start);
|
||||||
|
|
||||||
auto endpointJson = Json::object({
|
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)},
|
{"event", event_name(sink_timing.clock_pair.end)},
|
||||||
{"delay", ctx->getDelayNS(sink_timing.delay)},
|
{"delay", ctx->getDelayNS(sink_timing.delay)},
|
||||||
{"budget", ctx->getDelayNS(sink_timing.budget)}
|
{"budget", ctx->getDelayNS(sink_timing.budget)}
|
||||||
@ -1645,7 +1668,8 @@ void write_timing_report(
|
|||||||
|
|
||||||
auto netTimingJson = Json::object({
|
auto netTimingJson = Json::object({
|
||||||
{"net", net->name.c_str(ctx)},
|
{"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)},
|
{"event", event_name(start)},
|
||||||
{"endpoints", endpointsJson}
|
{"endpoints", endpointsJson}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user