| | |
| | 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() |
| |
|