From 944eaeacaeb4ac8c8a4c2d6d49c5d4334acd3769 Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 22 May 2024 22:56:51 +0100 Subject: [PATCH] router2: additional heatmap data --- common/route/router2.cc | 59 ++++++++++++++++++++++--- python/plot_congestion_by_coordinate.py | 27 +++++++++++ python/plot_congestion_by_wiretype.py | 56 +++++++++++++++++++++++ 3 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 python/plot_congestion_by_coordinate.py create mode 100644 python/plot_congestion_by_wiretype.py diff --git a/common/route/router2.cc b/common/route/router2.cc index 8dcec6e91c..ebe81fc849 100644 --- a/common/route/router2.cc +++ b/common/route/router2.cc @@ -1154,7 +1154,7 @@ struct Router2 return success; } - void write_wiretype_heatmap(std::ostream &out) + void write_congestion_by_wiretype_heatmap(std::ostream &out) { dict> cong_by_type; size_t max_cong = 0; @@ -1180,6 +1180,33 @@ struct Router2 } } + void write_utilisation_by_wiretype_heatmap(std::ostream &out) + { + dict util_by_type; + for (auto &wd : flat_wires) { + IdString type = ctx->getWireType(wd.w); + if (wd.curr_cong > 0) + util_by_type[type] += wd.curr_cong; + } + // Write csv + for (auto &u : util_by_type) + out << u.first.c_str(ctx) << "," << u.second << std::endl; + } + + void write_congestion_by_coordinate_heatmap(std::ostream &out) + { + auto util_by_coord = std::vector>(ctx->getGridDimX() + 1, std::vector(ctx->getGridDimY() + 1, 0)); + for (auto &wd : flat_wires) + if (wd.curr_cong > 1) + util_by_coord[wd.x][wd.y] += wd.curr_cong; + // Write csv + for (auto &x : util_by_coord) { + for (auto y : x) + out << y << ","; + out << std::endl; + } + } + int mid_x = 0, mid_y = 0; void partition_nets() @@ -1439,12 +1466,30 @@ struct Router2 update_congestion(); 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()); + { + std::string filename(cfg.heatmap + "_congestion_by_wiretype_" + std::to_string(iter) + ".csv"); + std::ofstream cong_map(filename); + if (!cong_map) + log_error("Failed to open congestion-by-wiretype heatmap %s for writing.\n", filename.c_str()); + write_congestion_by_wiretype_heatmap(cong_map); + log_info(" wrote congestion-by-wiretype heatmap to %s.\n", filename.c_str()); + } + { + std::string filename(cfg.heatmap + "_utilisation_by_wiretype_" + std::to_string(iter) + ".csv"); + std::ofstream cong_map(filename); + if (!cong_map) + log_error("Failed to open utilisation-by-wiretype heatmap %s for writing.\n", filename.c_str()); + write_utilisation_by_wiretype_heatmap(cong_map); + log_info(" wrote utilisation-by-wiretype heatmap to %s.\n", filename.c_str()); + } + { + std::string filename(cfg.heatmap + "_congestion_by_coordinate_" + std::to_string(iter) + ".csv"); + std::ofstream cong_map(filename); + if (!cong_map) + log_error("Failed to open congestion-by-coordinate heatmap %s for writing.\n", filename.c_str()); + write_congestion_by_coordinate_heatmap(cong_map); + log_info(" wrote congestion-by-coordinate heatmap to %s.\n", filename.c_str()); + } } int tmgfail = 0; if (timing_driven) diff --git a/python/plot_congestion_by_coordinate.py b/python/plot_congestion_by_coordinate.py new file mode 100644 index 0000000000..a9e7833d49 --- /dev/null +++ b/python/plot_congestion_by_coordinate.py @@ -0,0 +1,27 @@ +import csv +import sys + +import matplotlib.pyplot as plt + +data = [] + +file = 1 +try: + while True: + print("{}/heatmap_congestion_by_coordinate_{}.csv".format(sys.argv[1], file)) + with open("{}/heatmap_congestion_by_coordinate_{}.csv".format(sys.argv[1], file)) as f: + file_data = [] + reader = csv.reader(f, delimiter=',') + for row in reader: + file_data.append([float(x) for x in row if x != '']) + data.append(file_data) + file += 1 +except FileNotFoundError: + pass + +for i, file_data in enumerate(data): + plt.imshow(file_data, cmap="gray", aspect="equal") + plt.title("heatmap for iteration {}".format(i+1)) + plt.tight_layout() + plt.savefig("{}/heatmap_congestion_by_coordinate_{:03}.png".format(sys.argv[1], i), dpi=300) + plt.clf() diff --git a/python/plot_congestion_by_wiretype.py b/python/plot_congestion_by_wiretype.py new file mode 100644 index 0000000000..6f44a1ab47 --- /dev/null +++ b/python/plot_congestion_by_wiretype.py @@ -0,0 +1,56 @@ +import csv +import sys + +import matplotlib.pyplot as plt + +data = {} +max_bars = {} + +file = 1 +try: + while True: + print("{}/heatmap_congestion_by_wiretype_{}.csv".format(sys.argv[1], file)) + with open("{}/heatmap_congestion_by_wiretype_{}.csv".format(sys.argv[1], file)) as f: + reader = csv.reader(f, delimiter=',') + for row in [x for x in reader][1:]: + key = row[0] + values = [float(x) for x in row[1:] if x != ''] + # Ignore wires without overuse + values[0] = 0 + values[1] = 0 + if key not in data: + data[key] = [] + max_bars[key] = 0 + data[key].append(values) + max_bars[key] = max(max_bars[key], len(values)) + file += 1 +except FileNotFoundError: + pass +finally: + file -= 1 + +to_remove = [] +for key in data.keys(): + if sum([sum(values) for values in data[key]]) == 0: + # Prune entries that never have any overuse to attempt to reduce visual clutter + to_remove.append(key) + else: + # Pad entries as needed + for values in data[key]: + while len(values) < max_bars[key]: + values.append(0) +for key in to_remove: + del data[key] + +COLS = 2 +for i in range(file): + plt.suptitle("heatmap for iteration {}".format(i)) + fig, axs = plt.subplots((len(data.keys())+(COLS-1))//COLS, COLS) + for j, key in enumerate(data.keys()): + if sum(data[key][i]) > 0: + axs[j//COLS, j%COLS].bar([x for x in range(len(data[key][i]))], data[key][i]) + axs[j//COLS, j%COLS].set_title(key) + else: + axs[j//COLS, j%COLS].set_axis_off() + plt.savefig("{}/heatmap_congestion_by_wiretype_{:03}.png".format(sys.argv[1], i), dpi=300) + plt.close()