router2: Add heatmap by routing resource type
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
5a41d2070c
commit
1595c07260
@ -170,6 +170,9 @@ po::options_description CommandHandler::getGeneralOptions()
|
|||||||
"placer heap criticality exponent (int, default: 2)");
|
"placer heap criticality exponent (int, default: 2)");
|
||||||
general.add_options()("placer-heap-timingweight", po::value<int>(), "placer heap timing weight (int, default: 10)");
|
general.add_options()("placer-heap-timingweight", po::value<int>(), "placer heap timing weight (int, default: 10)");
|
||||||
|
|
||||||
|
general.add_options()("router2-heatmap", po::value<std::string>(),
|
||||||
|
"prefix for router2 resource congestion heatmaps");
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
@ -278,6 +281,8 @@ void CommandHandler::setupContext(Context *ctx)
|
|||||||
|
|
||||||
if (vm.count("placer-heap-timingweight"))
|
if (vm.count("placer-heap-timingweight"))
|
||||||
ctx->settings[ctx->id("placerHeap/timingWeight")] = std::to_string(vm["placer-heap-timingweight"].as<int>());
|
ctx->settings[ctx->id("placerHeap/timingWeight")] = std::to_string(vm["placer-heap-timingweight"].as<int>());
|
||||||
|
if (vm.count("router2-heatmap"))
|
||||||
|
ctx->settings[ctx->id("router2/heatmap")] = vm["router2-heatmap"].as<std::string>();
|
||||||
|
|
||||||
// Setting default values
|
// Setting default values
|
||||||
if (ctx->settings.find(ctx->id("target_freq")) == ctx->settings.end())
|
if (ctx->settings.find(ctx->id("target_freq")) == ctx->settings.end())
|
||||||
|
@ -1043,7 +1043,7 @@ struct Router2
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_heatmap(std::ostream &out, bool congestion = false)
|
void write_xy_heatmap(std::ostream &out, bool congestion = false)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<int>> hm_xy;
|
std::vector<std::vector<int>> hm_xy;
|
||||||
int max_x = 0, max_y = 0;
|
int max_x = 0, max_y = 0;
|
||||||
@ -1080,6 +1080,33 @@ struct Router2
|
|||||||
out << std::endl;
|
out << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_wiretype_heatmap(std::ostream &out)
|
||||||
|
{
|
||||||
|
std::unordered_map<IdString, std::vector<int>> cong_by_type;
|
||||||
|
size_t max_cong = 0;
|
||||||
|
// Build histogram
|
||||||
|
for (auto &wd : flat_wires) {
|
||||||
|
size_t val = wd.bound_nets.size();
|
||||||
|
IdString type = ctx->getWireType(wd.w);
|
||||||
|
max_cong = std::max(max_cong, val);
|
||||||
|
if (cong_by_type[type].size() <= max_cong)
|
||||||
|
cong_by_type[type].resize(max_cong + 1);
|
||||||
|
cong_by_type[type].at(val) += 1;
|
||||||
|
}
|
||||||
|
// Write csv
|
||||||
|
out << "type,";
|
||||||
|
for (size_t i = 0; i <= max_cong; i++)
|
||||||
|
out << "bound=" << i << ",";
|
||||||
|
out << std::endl;
|
||||||
|
for (auto &ty : sorted_ref(cong_by_type)) {
|
||||||
|
out << ctx->nameOf(ty.first) << ",";
|
||||||
|
for (int count : ty.second)
|
||||||
|
out << count << ",";
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mid_x = 0, mid_y = 0;
|
int mid_x = 0, mid_y = 0;
|
||||||
|
|
||||||
void partition_nets()
|
void partition_nets()
|
||||||
@ -1332,9 +1359,17 @@ struct Router2
|
|||||||
#if 0
|
#if 0
|
||||||
if (iter == 1 && ctx->debug) {
|
if (iter == 1 && ctx->debug) {
|
||||||
std::ofstream cong_map("cong_map_0.csv");
|
std::ofstream cong_map("cong_map_0.csv");
|
||||||
write_heatmap(cong_map, true);
|
write_xy_heatmap(cong_map, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (!cfg.heatmap.empty()) {
|
||||||
|
std::string filename(cfg.heatmap + "_" + std::to_string(iter) + ".csv");
|
||||||
|
std::ofstream cong_map(filename);
|
||||||
|
if (!cong_map)
|
||||||
|
log_error("Failed to open wiretype heatmap %s for writing.\n", filename.c_str());
|
||||||
|
write_wiretype_heatmap(cong_map);
|
||||||
|
log_info(" wrote wiretype heatmap to %s.\n", filename.c_str());
|
||||||
|
}
|
||||||
dump_statistics();
|
dump_statistics();
|
||||||
|
|
||||||
if (overused_wires == 0) {
|
if (overused_wires == 0) {
|
||||||
@ -1394,6 +1429,10 @@ Router2Cfg::Router2Cfg(Context *ctx)
|
|||||||
curr_cong_mult = ctx->setting<float>("router2/currCongWeightMult", 2.0f);
|
curr_cong_mult = ctx->setting<float>("router2/currCongWeightMult", 2.0f);
|
||||||
estimate_weight = ctx->setting<float>("router2/estimateWeight", 1.75f);
|
estimate_weight = ctx->setting<float>("router2/estimateWeight", 1.75f);
|
||||||
perf_profile = ctx->setting<bool>("router2/perfProfile", false);
|
perf_profile = ctx->setting<bool>("router2/perfProfile", false);
|
||||||
|
if (ctx->settings.count(ctx->id("router2/heatmap")))
|
||||||
|
heatmap = ctx->settings.at(ctx->id("router2/heatmap")).as_string();
|
||||||
|
else
|
||||||
|
heatmap = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -49,6 +49,8 @@ struct Router2Cfg
|
|||||||
|
|
||||||
// Print additional performance profiling information
|
// Print additional performance profiling information
|
||||||
bool perf_profile = false;
|
bool perf_profile = false;
|
||||||
|
|
||||||
|
std::string heatmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
void router2(Context *ctx, const Router2Cfg &cfg);
|
void router2(Context *ctx, const Router2Cfg &cfg);
|
||||||
|
@ -325,6 +325,17 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdString Arch::getWireType(WireId wire) const
|
||||||
|
{
|
||||||
|
IdString basename(wire_data(wire).name);
|
||||||
|
const std::string &basename_str = basename.str(this);
|
||||||
|
// Interconnect - derive a type
|
||||||
|
if ((basename_str[0] == 'H' || basename_str[0] == 'V') && basename_str[1] == '0')
|
||||||
|
return id(basename_str.substr(0, 4));
|
||||||
|
else
|
||||||
|
return id_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
PipId Arch::getPipByName(IdStringList name) const
|
PipId Arch::getPipByName(IdStringList name) const
|
||||||
|
@ -1034,6 +1034,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
WireId getWireByName(IdStringList name) const override;
|
WireId getWireByName(IdStringList name) const override;
|
||||||
|
|
||||||
IdStringList getWireName(WireId wire) const override
|
IdStringList getWireName(WireId wire) const override
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -1043,6 +1044,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const override;
|
std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const override;
|
||||||
|
IdString getWireType(WireId wire) const override;
|
||||||
|
|
||||||
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); }
|
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); }
|
||||||
|
|
||||||
|
@ -503,3 +503,5 @@ X(U2END2)
|
|||||||
X(U3END3)
|
X(U3END3)
|
||||||
X(UED0THEN)
|
X(UED0THEN)
|
||||||
X(URXCKINE)
|
X(URXCKINE)
|
||||||
|
|
||||||
|
X(GENERAL)
|
||||||
|
Loading…
Reference in New Issue
Block a user