aboutsummaryrefslogtreecommitdiffstats
path: root/common/report.cc
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-04-08 13:42:54 +0100
committergatecat <gatecat@ds0.me>2022-04-08 13:42:54 +0100
commit49f178ed94b5fad00d25dbd12adea0bf4732f803 (patch)
treeea642e20bc07441a800944390e1f904e6ce5b113 /common/report.cc
parente42e22575f20b59634f88b5cf694efdb413ff0a0 (diff)
downloadnextpnr-49f178ed94b5fad00d25dbd12adea0bf4732f803.tar.gz
nextpnr-49f178ed94b5fad00d25dbd12adea0bf4732f803.tar.bz2
nextpnr-49f178ed94b5fad00d25dbd12adea0bf4732f803.zip
Split up common into kernel,place,route
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'common/report.cc')
-rw-r--r--common/report.cc259
1 files changed, 0 insertions, 259 deletions
diff --git a/common/report.cc b/common/report.cc
deleted file mode 100644
index 98ff14fb..00000000
--- a/common/report.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * nextpnr -- Next Generation Place and Route
- *
- * Copyright (C) 2021 gatecat <gatecat@ds0.me>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "json11.hpp"
-#include "nextpnr.h"
-
-NEXTPNR_NAMESPACE_BEGIN
-
-using namespace json11;
-
-namespace {
-dict<IdString, std::pair<int, int>> get_utilization(const Context *ctx)
-{
- // Sort by Bel type
- dict<IdString, std::pair<int, int>> result;
- for (auto &cell : ctx->cells) {
- result[ctx->getBelBucketName(ctx->getBelBucketForCellType(cell.second.get()->type))].first++;
- }
- for (auto bel : ctx->getBels()) {
- if (!ctx->getBelHidden(bel)) {
- result[ctx->getBelBucketName(ctx->getBelBucketForBel(bel))].second++;
- }
- }
- return result;
-}
-} // namespace
-
-static std::string clock_event_name(const Context *ctx, const ClockEvent &e)
-{
- std::string value;
- if (e.clock == ctx->id("$async$"))
- value = std::string("<async>");
- else
- value = (e.edge == FALLING_EDGE ? std::string("negedge ") : std::string("posedge ")) + e.clock.str(ctx);
- return value;
-};
-
-static Json::array report_critical_paths(const Context *ctx)
-{
-
- auto report_critical_path = [ctx](const CriticalPath &report) {
- Json::array pathJson;
-
- for (const auto &segment : report.segments) {
-
- const auto &driver = ctx->cells.at(segment.from.first);
- const auto &sink = ctx->cells.at(segment.to.first);
-
- auto fromLoc = ctx->getBelLocation(driver->bel);
- auto toLoc = ctx->getBelLocation(sink->bel);
-
- auto fromJson = Json::object({{"cell", segment.from.first.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.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 == CriticalPath::Segment::Type::CLK_TO_Q) {
- segmentJson["type"] = "clk-to-q";
- } else if (segment.type == CriticalPath::Segment::Type::SOURCE) {
- segmentJson["type"] = "source";
- } else if (segment.type == CriticalPath::Segment::Type::LOGIC) {
- segmentJson["type"] = "logic";
- } else if (segment.type == CriticalPath::Segment::Type::SETUP) {
- segmentJson["type"] = "setup";
- } else if (segment.type == CriticalPath::Segment::Type::ROUTING) {
- segmentJson["type"] = "routing";
- segmentJson["net"] = segment.net.c_str(ctx);
- segmentJson["budget"] = ctx->getDelayNS(segment.budget);
- }
-
- pathJson.push_back(segmentJson);
- }
-
- return pathJson;
- };
-
- auto critPathsJson = Json::array();
-
- // Critical paths
- for (auto &report : ctx->timing_result.clock_paths) {
-
- critPathsJson.push_back(Json::object({{"from", clock_event_name(ctx, report.second.clock_pair.start)},
- {"to", clock_event_name(ctx, report.second.clock_pair.end)},
- {"path", report_critical_path(report.second)}}));
- }
-
- // Cross-domain paths
- for (auto &report : ctx->timing_result.xclock_paths) {
- critPathsJson.push_back(Json::object({{"from", clock_event_name(ctx, report.clock_pair.start)},
- {"to", clock_event_name(ctx, report.clock_pair.end)},
- {"path", report_critical_path(report)}}));
- }
-
- return critPathsJson;
-}
-
-static Json::array report_detailed_net_timings(const Context *ctx)
-{
- auto detailedNetTimingsJson = Json::array();
-
- // Detailed per-net timing analysis
- for (const auto &it : ctx->timing_result.detailed_net_timings) {
-
- const NetInfo *net = ctx->nets.at(it.first).get();
- ClockEvent start = it.second[0].clock_pair.start;
-
- Json::array endpointsJson;
- for (const auto &sink_timing : it.second) {
-
- // FIXME: Is it possible that there are multiple different start
- // events for a single net? It has a single driver
- NPNR_ASSERT(sink_timing.clock_pair.start == start);
-
- auto endpointJson = Json::object({{"cell", sink_timing.cell_port.first.c_str(ctx)},
- {"port", sink_timing.cell_port.second.c_str(ctx)},
- {"event", clock_event_name(ctx, sink_timing.clock_pair.end)},
- {"delay", ctx->getDelayNS(sink_timing.delay)},
- {"budget", ctx->getDelayNS(sink_timing.budget)}});
- endpointsJson.push_back(endpointJson);
- }
-
- auto netTimingJson = Json::object({{"net", net->name.c_str(ctx)},
- {"driver", net->driver.cell->name.c_str(ctx)},
- {"port", net->driver.port.c_str(ctx)},
- {"event", clock_event_name(ctx, start)},
- {"endpoints", endpointsJson}});
-
- detailedNetTimingsJson.push_back(netTimingJson);
- }
-
- return detailedNetTimingsJson;
-}
-
-/*
-Report JSON structure:
-
-{
- "utilization": {
- <BEL name>: {
- "available": <available count>,
- "used": <used count>
- },
- ...
- },
- "fmax" {
- <clock name>: {
- "achieved": <achieved fmax [MHz]>,
- "constraint": <target fmax [MHz]>
- },
- ...
- },
- "critical_paths": [
- {
- "from": <clock event edge and name>,
- "to": <clock event edge and name>,
- "path": [
- {
- "from": {
- "cell": <driver cell name>
- "port": <driver port name>
- "loc": [
- <grid x>,
- <grid y>
- ]
- },
- "to": {
- "cell": <sink cell name>
- "port": <sink port name>
- "loc": [
- <grid x>,
- <grid y>
- ]
- },
- "type": <path segment type "clk-to-q", "source", "logic", "routing" or "setup">,
- "net": <net name (for routing only!)>,
- "delay": <segment delay [ns]>,
- "budget": <segment delay budget [ns] (for routing only!)>,
- }
- ...
- ]
- },
- ...
- ],
- "detailed_net_timings": [
- {
- "driver": <driving cell name>,
- "port": <driving cell port name>,
- "event": <driver clock event name>,
- "net": <net name>,
- "endpoints": [
- {
- "cell": <sink cell name>,
- "port": <sink cell port name>,
- "event": <destination clock event name>,
- "delay": <delay [ns]>,
- "budget": <delay budget [ns]>,
- }
- ...
- ]
- }
- ...
- ]
-}
-*/
-
-void Context::writeReport(std::ostream &out) const
-{
- auto util = get_utilization(this);
- dict<std::string, Json> util_json;
- for (const auto &kv : util) {
- util_json[kv.first.str(this)] = Json::object{
- {"used", kv.second.first},
- {"available", kv.second.second},
- };
- }
- dict<std::string, Json> fmax_json;
- for (const auto &kv : timing_result.clock_fmax) {
- fmax_json[kv.first.str(this)] = Json::object{
- {"achieved", kv.second.achieved},
- {"constraint", kv.second.constraint},
- };
- }
-
- Json::object jsonRoot{
- {"utilization", util_json}, {"fmax", fmax_json}, {"critical_paths", report_critical_paths(this)}};
-
- if (detailed_timing_report) {
- jsonRoot["detailed_net_timings"] = report_detailed_net_timings(this);
- }
-
- out << Json(jsonRoot).dump() << std::endl;
-}
-
-NEXTPNR_NAMESPACE_END