graph LR NL["Netlist\np1.json"] --> FG["Flow graph\ncreate_flow_graph"] FG --> IP["Initial placement\nsnake fill + shuffle"] IP --> OPT["Per-axis optimize\nHoward + legalize"] OPT --> IO["I/O pad snap"] IO --> OUT["Placement\nSVG output"] OPT -->|"repeat until stall"| OPT style NL fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style FG fill:#fff9c4,stroke:#f57f17,stroke-width:3px style IP fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style OPT fill:#f8bbd0,stroke:#c2185b,stroke-width:3px style IO fill:#d1c4e9,stroke:#6a1b9a,stroke-width:3px style OUT fill:#ffe0b2,stroke:#e65100,stroke-width:3px
graph TD OPT["optimize_axis(place, axis)"] --> H["apply_howard\nMinParametricSolver"] OPT --> L["legalize_modules\nHungarian assignment"] H --> D["distance(ratio, arc)\n533K calls / run"] L --> M["min_weight_full_matching\n211 calls / run"] style OPT fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style H fill:#ffcdd2,stroke:#c62828,stroke-width:3px style L fill:#f8bbd0,stroke:#c2185b,stroke-width:3px style D fill:#fff9c4,stroke:#f57f17,stroke-width:3px style M fill:#fff9c4,stroke:#f57f17,stroke-width:3px
graph LR LW["LocalWindowLegalizer"] --> B["build nx.Graph\n93K add_edge + 93K add_node"] B --> MW["minimum_weight_full_matching"] MW --> BI["biadjacency_matrix\n+ bipartite.sets + color()"] BI --> S["scipy linear_sum_assignment"] style LW fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style B fill:#ffcdd2,stroke:#c62828,stroke-width:3px style MW fill:#ffe0b2,stroke:#e65100,stroke-width:3px style BI fill:#ffe0b2,stroke:#e65100,stroke-width:3px style S fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
graph TD A["direct scipy on {v: {slot: weight}}"] --> Q{"same min-weight\nmatching?"} Q -->|"ties broken differently"| R["placement trajectory changes"] R --> W["quality test regressed\n50x50: 1680 >= 1600"] Q -->|"replicate networkx order"| OK["color() DFS + set-iteration order"] OK --> Z["0 / 3000 mismatches"] style A fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style Q fill:#fff9c4,stroke:#f57f17,stroke-width:3px style R fill:#ffcdd2,stroke:#c62828,stroke-width:3px style W fill:#ffcdd2,stroke:#c62828,stroke-width:3px style OK fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style Z fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
graph LR PY["Python NnsPlacer"] --> CPP["nnsplace-cpp\nheaders + source/*.cpp"] CPP --> HOW["Howard relaxation"] CPP --> MATCH["Hungarian matching"] HOW --> F1["Domain = Coord\n+ operator T()"] MATCH --> F2["hash map + hoisted buffers"] MATCH --> F3["stop widening at the grid"] style PY fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style CPP fill:#fff9c4,stroke:#f57f17,stroke-width:3px style HOW fill:#ffcdd2,stroke:#c62828,stroke-width:3px style MATCH fill:#f8bbd0,stroke:#c2185b,stroke-width:3px style F1 fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style F2 fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style F3 fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
graph TD W["legalize bucket\nm = 32 modules"] --> R11["ring = 11\nmatch?"] R11 -->|"fail"| R12["ring = 12 ... 49\n39 full matching attempts"] R12 --> FB["global fallback\nadd_all_slots"] W --> EARLY["ring >= grid ?\nno new slot possible"] EARLY --> SKIP["break -> fallback"] style W fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style R11 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style R12 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style FB fill:#ffe0b2,stroke:#e65100,stroke-width:3px style EARLY fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style SKIP fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
graph LR OPT["optimisation"] --> EQ{"same\nresult?"} EQ -->|"tie-breaks"| T["networkx set-iteration order\nreplicated exactly"] EQ -->|"no-op guards"| G["ring >= grid\nprovably adds no slot"] EQ -->|"domain change"| D["floor-div stays exact\nint vs Fraction"] T --> OK["24/24 bit-identical\n0/3000 matching"] G --> OK D --> OK style OPT fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style EQ fill:#fff9c4,stroke:#f57f17,stroke-width:3px style T fill:#f8bbd0,stroke:#c2185b,stroke-width:3px style G fill:#d1c4e9,stroke:#6a1b9a,stroke-width:3px style D fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style OK fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px