tscircuit / tscircuit/schematic-trace-solver

bug: a single oscillating net pair aborts TraceOverlapShiftSolver and leaves independent cross-net overlaps unresolved

Open
#1,102 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
13
Forks
314
Avg merge
9h 3m
Merged PRs (30d)
132

Description

TraceOverlapShiftSolver treats its A -> B -> A oscillation guard as a reason to stop the entire solve. The first net pair that oscillates aborts the whole pass, so every other cross-net overlap still queued at that moment is silently left in the output, even though those pairs are independent and would have been corrected in the next few iterations.

Sub-solver

lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, in _step():

if (this.returnsToPreviousTraceState(nextTraceState)) {
  this.activeSubSolver = null
  this.solved = true   // <- ends the whole solver, not just this net pair
  return
}

Reproduction

Minimized from tests/repros/assets/board-1273-trace-overlap-cycle.input.json (74 chips -> 5 chips, 14 pins). Two cross-net collinear overlaps survive the shift solver: GND/VBUS and RTS/DTR. Only the GND/VBUS pair actually oscillates.

{
 "chips": [
  {
   "chipId": "schematic_component_23",
   "center": {
    "x": 11.084375,
    "y": -5.325
   },
   "width": 2.3000000000000007,
   "height": 3.2000000000000006,
   "pins": [
    {
     "pinId": "schematic_port_75",
     "x": 9.934375,
     "y": -4.325
    },
    {
     "pinId": "schematic_port_79",
     "x": 9.934375,
     "y": -5.125
    },
    {
     "pinId": "schematic_port_80",
     "x": 9.934375,
     "y": -5.325
    },
    {
     "pinId": "schematic_port_96",
     "x": 12.234375,
     "y": -5.025
    },
    {
     "pinId": "schematic_port_100",
     "x": 12.234375,
     "y": -4.2250000000000005
    },
    {
     "pinId": "schematic_port_101",
     "x": 12.234375,
     "y": -4.025
    }
   ],
   "sectionId": "USB to UART"
  },
  {
   "chipId": "schematic_component_26",
   "center": {
    "x": 7.629375,
    "y": -3.9250000000000007
   },
   "width": 0.7800000000000002,
   "height": 0.7600000000000011,
   "pins": [
    {
     "pinId": "schematic_port_106",
     "x": 7.564375,
     "y": -4.3050000000000015,
     "_facingDirection": "y-"
    }
   ],
   "sectionId": "USB to UART"
  },
  {
   "chipId": "schematic_component_27",
   "center": {
    "x": 9.221875,
    "y": -5.55
   },
   "width": 1.205,
   "height": 0.5999999999999996,
   "pins": [
    {
     "pinId": "schematic_port_108",
     "x": 8.944374999999999,
     "y": -5.25,
     "_facingDirection": "y+"
    },
    {
     "pinId": "schematic_port_109",
     "x": 8.944374999999999,
     "y": -5.85,
     "_facingDirection": "y-"
    }
   ],
   "sectionId": "USB to UART"
  },
  {
   "chipId": "schematic_component_28",
   "center": {
    "x": 9.221875,
    "y": -4.23
   },
   "width": 1.205,
   "height": 0.6000000000000014,
   "pins": [
    {
     "pinId": "schematic_port_111",
     "x": 8.944374999999999,
     "y": -3.9299999999999997
    }
   ],
   "sectionId": "USB to UART"
  },
  {
   "chipId": "schematic_component_32",
   "center": {
    "x": 15.769374999999998,
    "y": -4.724999999999999
   },
   "width": 2,
   "height": 0.8000000000000007,
   "pins": [
    {
     "pinId": "schematic_port_118",
     "x": 14.769374999999998,
     "y": -4.524999999999999
    },
    {
     "pinId": "schematic_port_119",
     "x": 14.769374999999998,
     "y": -4.724999999999999
    },
    {
     "pinId": "schematic_port_121",
     "x": 16.769374999999997,
     "y": -4.924999999999999
    },
    {
     "pinId": "schematic_port_122",
     "x": 16.769374999999997,
     "y": -4.724999999999999
    }
   ],
   "sectionId": "USB to UART"
  }
 ],
 "directConnections": [
  {
   "netId": ".R5 > .pin1 to .U6 > .VBUS",
   "pinIds": [
    "schematic_port_108",
    "schematic_port_80"
   ]
  }
 ],
 "netConnections": [
  {
   "netId": "GND",
   "isGround": true,
   "netLabelWidth": 0.42,
   "netLabelHeight": 0.48,
   "pinIds": [
    "schematic_port_75",
    "schematic_port_101",
    "schematic_port_106",
    "schematic_port_109"
   ]
  },
  {
   "netId": "VBUS",
   "netLabelWidth": 0.42,
   "netLabelHeight": 0.6,
   "pinIds": [
    "schematic_port_79",
    "schematic_port_111"
   ]
  },
  {
   "netId": "RTS",
   "netLabelWidth": 0.48,
   "pinIds": [
    "schematic_port_96",
    "schematic_port_118",
    "schematic_port_122"
   ]
  },
  {
   "netId": "DTR",
   "netLabelWidth": 0.48,
   "pinIds": [
    "schematic_port_100",
    "schematic_port_119",
    "schematic_port_121"
   ]
  }
 ],
 "textBoxes": [],
 "availableNetLabelOrientations": {
  "GND": [
   "y-"
  ],
  "VBUS": [
   "y+"
  ],
  "RTS": [
   "x-",
   "x+"
  ],
  "DTR": [
   "x-",
   "x+"
  ]
 },
 "maxMspPairDistance": 8,
 "_hideRatsNet": false
}
const solver = new SchematicTracePipelineSolver(inputProblem)
solver.solve()
// inspect solver.traceOverlapShiftSolver.correctedTraceMap for
// cross-net segments that are collinear and overlapping

Observed

The solver stops at iteration 9 with solved === true, and two distinct cross-net pairs still overlap collinearly:

connectivity_net0 ~ connectivity_net1   (GND / VBUS, the oscillating pair)
connectivity_net3 ~ connectivity_net4   (RTS / DTR, independent)

The RTS/DTR traces share an exact coordinate over a positive-length span, so they render as one wire.

On the full board-1273 fixture the same abort leaves 6 unresolved cross-net pairs after 27 iterations.

Expected

Oscillation between two nets should suspend only that net pair. Independent overlaps should keep being corrected until no correctable overlap remains. For this input only connectivity_net0 ~ connectivity_net1 should remain; RTS/DTR should be separated.

On board-1273 this takes the unresolved pairs from 6 down to 1 (the single genuinely oscillating pair), with the same 135 traces routed and no trace added or dropped.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, especially _step() and returnsToPreviousTraceState(), then run the provided board-1273 reproduction through SchematicTracePipelineSolver. Verify that an oscillating GND/VBUS pair no longer ends the entire pass and that the independent RTS/DTR overlap is corrected. Done means only the genuinely oscillating pair remains, with 135 traces and no trace added or dropped.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.