#!/usr/bin/env python3 from __future__ import annotations import json from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import pandas as pd import sqlite3 WNS_KEYS = [ "timing__setup__wns", "timing__setup__WNS", "finish__timing__setup__wns", "timing__setup__ws", "finish__timing__setup__ws", "route__timing__setup__ws", "cts__timing__setup__ws", "detailedplace__timing__setup__ws", "floorplan__timing__setup__ws", "globalplace__timing__setup__ws", "globalroute__timing__setup__ws", "placeopt__timing__setup__ws", ] AREA_KEYS = [ "finish__design__die__area", "globalroute__design__die__area", "placeopt__design__die__area", "detailedplace__design__die__area", "floorplan__design__die__area", "design__die__area", ] def pick_first(metrics: dict, keys: list[str]) -> float | None: for k in keys: if k in metrics: try: return float(metrics[k]) except Exception: return None lower = {kk.lower(): kk for kk in metrics.keys()} for k in keys: kk = lower.get(k.lower()) if kk: try: return float(metrics[kk]) except Exception: return None return None def load_metrics(mj: str | None) -> dict | None: if not mj: return None try: return json.loads(mj) except Exception: return None def main() -> None: import argparse p = argparse.ArgumentParser(description="Generate Pareto scatter (area vs WNS)") p.add_argument("--db", default="runs/sweep_finish.sqlite", help="SQLite database path") p.add_argument("--out", default="runs/sweep_finish/plots/pareto_area_vs_wns", help="Output path without extension") args = p.parse_args() con = sqlite3.connect(args.db) df = pd.read_sql_query("SELECT * FROM trials", con) con.close() rows = [] for _, row in df.iterrows(): metrics = load_metrics(row.get("metrics_json")) if not metrics: continue wns = pick_first(metrics, WNS_KEYS) area = pick_first(metrics, AREA_KEYS) if wns is None or area is None: continue rows.append({"wns": wns, "area": area, "fidelity": row.get("fidelity", "unknown")}) if not rows: print("No points with both WNS and area found.") return plot_df = pd.DataFrame(rows) colors = { "synth": "#999999", "place": "#4B8BBE", "route": "#306998", "finish": "#E07B39", "unknown": "#666666", } markers = { "synth": "o", "place": "s", "route": "^", "finish": "D", "unknown": "o", } fig, ax = plt.subplots(figsize=(6.4, 4.6)) for fid, group in plot_df.groupby("fidelity"): ax.scatter( group["area"], group["wns"], label=fid, color=colors.get(fid, "#666666"), marker=markers.get(fid, "o"), alpha=0.75, edgecolors="none", ) ax.axhline(0.0, color="#333333", linewidth=0.8, linestyle="--") ax.set_xlabel("Die area (um^2)") ax.set_ylabel("WNS (ns)") ax.set_title("Area vs WNS (Pareto scatter)") ax.legend(frameon=False, fontsize=8, loc="best") fig.tight_layout() out_base = Path(args.out) out_base.parent.mkdir(parents=True, exist_ok=True) fig.savefig(out_base.with_suffix(".png"), dpi=300) fig.savefig(out_base.with_suffix(".pdf")) plt.close(fig) if __name__ == "__main__": main()