fix: detour net-label connectors around blocking traces (#674)#716
fix: detour net-label connectors around blocking traces (#674)#716DPS0340 wants to merge 4 commits into
Conversation
Progress on tscircuit#674. AvailableNetOrientationSolver generated connector traces (from a label's original anchor to its corrected position) without checking whether the connector crosses an existing trace from a different net. Each crossing renders as a false junction. On the tscircuit#674 board this produced 3 crossings, e.g. the V3_3 connector slicing through the JP1.1-SJ3.1 trace; example45 and bug-report-20260708T055430Z each had one more. Candidate evaluation now rejects candidates whose connector would cross another net's trace, with a fallback pass that permits crossings when no crossing-free candidate exists (so orientation constraints still win over crossing avoidance, matching repro51's pinned behavior). Crossings drop 2->1 on example45 and bug-report-20260708T055430Z (snapshots updated). The tscircuit#674 board's remaining 3 crossings need connector rerouting around blocking traces — pinned with a test.failing for follow-up.
@mohan-bee was right that the hand-made bug report was wrong. The tscircuit#674 issue already has a bot-imported report at tests/bug-reports/bug-report-20260717T022934Z (directory name derived from the issue's created_at by .github/scripts/import-json-bug-report.ts), and I had hand-created a second directory holding a byte-identical copy. Removes the hand-made directory and points the repro at the existing bug report, which already carries its own snapshot test. Full suite 145 pass / 0 fail.
Labels are processed one at a time, so each connector is validated against only the traces that exist when its own label is handled. On the tscircuit#674 board that ordering hides a real crossing: the orientation-4 connector is routed at index 14, but the orientation-9 connector it collides with is not created until index 17, so the earlier one never had a chance to avoid it. Adds a post-pass that runs once every connector exists. For each generated connector still crossing another net, it tries the mirrored L-route (turning on the other axis first) and adopts it when that route is crossing-free and does not hit a chip or another label. Only connectors this solver generated are moved; pin-to-pin traces from earlier solvers are untouched. Crossings per board, measured against the previous commit: bug-report-20260717-connector-crossing-674 3 -> 2 bug-report-20260706T213649Z 11 -> 9 bug-report-20260706T220324Z 6 -> 5 bug-report-20260721T221026Z 5 -> 4 bug-report-20260717T022934Z 3 -> 2 example43 1 -> 0 The two remaining on the tscircuit#674 board stay walled in — the mirrored route crosses something as well, so those need the connector routed around the blocking trace. Still pinned by the existing test.failing. Full suite 146 pass / 0 fail; 10 snapshots updated.
) Completes tscircuit#674. The previous commit tries the mirrored L-route, which clears a crossing when the blocking trace only sits on one axis between the endpoints. Two crossings on the tscircuit#674 board survived that: JP1.1-SJ3.1 x available-net-orientation-3-V3_3 U1.1-U1.3 x available-net-orientation-5-GND For both, the blocking trace lies between source and target on *both* axes, so every L-shape crosses it regardless of which corner it turns. The connector has to step away from the source, run across, and come back. The re-route pass now walks candidate routes cheapest-first: the mirrored L, then U-shaped detours at increasing perpendicular offsets in both directions. The first route clear of other nets, chips and labels wins, so connectors deviate as little as possible. Different-net crossings per board, measured against origin/main: bug-report-20260717T022934Z (tscircuit#674 board) 3 -> 0 bug-report-20260706T213649Z 11 -> 9 bug-report-20260706T220324Z 6 -> 5 bug-report-20260721T221026Z 5 -> 4 bug-report-20260716T144856Z 4 -> 3 example45 2 -> 1 example43 1 -> 0 No board regressed. With the tscircuit#674 board clean, the repro's assertion is no longer test.failing. Full suite 145 pass / 0 fail.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@mohan-bee @seveibar — this is the follow-up I split out of #703, ready for review whenever convenient. It's stacked on #703, so it should be reviewed/merged after that one. What it does: #703 fixes the connector crossings it can fix by re-cornering, but two on the #674 board can't be — the blocking trace sits between source and target on both axes, so every L-shape crosses it. This adds U-shaped detours at increasing perpendicular offsets, tried cheapest-first after the mirrored L. Measured against No board regressed. Full suite green, |
|
Update on this one, since #703 (which this depends on) is now closed in favour of #719. I measured all three branches against So this branch does help, but #719 alone does better — and the two conflict in That surprised me, because this PR was written as the finisher for #674: it adds connector detour routing on top of #703's check, and on the #674 board specifically it reaches 0 crossings. The wider measurement says that gain does not generalise — the detour logic helps that board while #719's simpler "reject the candidate and keep searching" does better across the rest. I'd rather not have you review a branch built on a closed one, so: I'm marking this as draft and will rebase it onto #719 once that lands, then re-measure. If detour routing still buys anything on top of #719, I'll reopen it with the numbers; if it doesn't, I'll close it. Either way it shouldn't cost you a review right now. Sorry for the churn — I should have measured across all boards before stacking these. |
|
Closing this. It was built on #703, which I closed in favour of #719, and re-testing it against current Measured across all imported bug reports, counting different-net crossings: The detour routing here reaches 0 crossings on the #674 board specifically, which is what made it look like the finisher. Across the full set it does worse than the simpler "reject the candidate and keep searching" approach in #719 — 31 vs 20. It also no longer applies cleanly: cherry-picking its detour commit onto the current #719/#723 stack conflicts in Sorry for the noise on this one — it should have been measured across all boards before I opened it rather than on the single board it targeted. |
Follow-up to #703, as offered there. Depends on #703 — it builds on that branch, so please merge #703 first (or I can rebase onto
mainonce it lands).This finishes off #674: the board goes from 3 different-net crossings to 0.
Why #703 alone wasn't enough
Two things were hiding crossings from the existing check.
1. Ordering. Labels are processed one at a time, so each connector is only validated against traces that exist at that moment. On this board
orientation-4is routed at index 14 but collides withorientation-9, which isn't created until index 17 — the earlier connector never had a chance to see it. Fixed by re-checking every connector once they all exist.2. No L-shape works. For the last two, the blocking trace sits between source and target on both axes:
Both L-shapes cross it, whichever corner they turn. The connector has to step away, run across, and come back — so the re-route pass now tries U-shaped detours at increasing perpendicular offsets after the mirrored L, taking the first route that's clear of other nets, chips and labels. Cheapest-first, so connectors deviate as little as possible.
Results
Different-net crossings per board, measured against
origin/main:No board regressed. With the #674 board clean, the repro's assertion is no longer
test.failing.Full suite 145 pass / 0 fail.