common: Add JSON timing and utilisation report
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
4ac00af6fa
commit
d2007a386c
@ -173,6 +173,9 @@ po::options_description CommandHandler::getGeneralOptions()
|
|||||||
general.add_options()("router2-heatmap", po::value<std::string>(),
|
general.add_options()("router2-heatmap", po::value<std::string>(),
|
||||||
"prefix for router2 resource congestion heatmaps");
|
"prefix for router2 resource congestion heatmaps");
|
||||||
|
|
||||||
|
general.add_options()("report", po::value<std::string>(),
|
||||||
|
"write timing and utilization report in JSON format to file");
|
||||||
|
|
||||||
general.add_options()("placed-svg", po::value<std::string>(), "write render of placement to SVG file");
|
general.add_options()("placed-svg", po::value<std::string>(), "write render of placement to SVG file");
|
||||||
general.add_options()("routed-svg", po::value<std::string>(), "write render of routing to SVG file");
|
general.add_options()("routed-svg", po::value<std::string>(), "write render of routing to SVG file");
|
||||||
|
|
||||||
@ -424,6 +427,14 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx)
|
|||||||
ctx->writeSDF(f, vm.count("sdf-cvc"));
|
ctx->writeSDF(f, vm.count("sdf-cvc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vm.count("report")) {
|
||||||
|
std::string filename = vm["report"].as<std::string>();
|
||||||
|
std::ofstream f(filename);
|
||||||
|
if (!f)
|
||||||
|
log_error("Failed to open report file '%s' for writing.\n", filename.c_str());
|
||||||
|
ctx->writeReport(f);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NO_PYTHON
|
#ifndef NO_PYTHON
|
||||||
deinit_python();
|
deinit_python();
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,6 +76,10 @@ struct Context : Arch, DeterministicRNG
|
|||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
|
// provided by report.cc
|
||||||
|
void writeReport(std::ostream &out) const;
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
uint32_t checksum() const;
|
uint32_t checksum() const;
|
||||||
|
|
||||||
void check() const;
|
void check() const;
|
||||||
|
68
common/report.cc
Normal file
68
common/report.cc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
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},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
out << Json(Json::object{
|
||||||
|
{"utilization", util_json},
|
||||||
|
{"fmax", fmax_json},
|
||||||
|
})
|
||||||
|
.dump()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
22
docs/report.md
Normal file
22
docs/report.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# JSON Reports
|
||||||
|
|
||||||
|
nextpnr can write a JSON report using `--report` post-place-and-route for integration with other build systems. It contains information on post-pack utilization and maximum achieved frequency for each clock domain, and is of the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"utilization": {
|
||||||
|
<beltype>: {
|
||||||
|
"used": <number of bels used in design>,
|
||||||
|
"available": <total number of bels available in device>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"fmax": {
|
||||||
|
<clock domain>: {
|
||||||
|
"achieved": <computed Fmax of routed design for clock in MHz>,
|
||||||
|
"constraint": <constraint for clock in MHz>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user