tscircuit / tscircuit/core

[RFC] Replace silent capacitor auto-detection with explicit intent and a deterministic "Placement Advisor"

Open
#2,964 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
58
Forks
203
Avg merge
7h 39m
Merged PRs (30d)
286

Description

[RFC] Replace silent capacitor auto-detection with explicit intent and a deterministic "Placement Advisor"

Motivation & Context

This issue addresses the recent proposals and discussions (#2955, #2962) around automatically detecting decoupling capacitors and silently injecting maximum trace-length constraints (e.g., automatically applying a 1mm constraint to any capacitor bridging a requiresPower pin and GND).

The original goal is highly valid: users (and LLMs generating tscircuit code) frequently forget to constrain physical trace lengths, resulting in boards that pass DRC but fail physically due to parasitic inductance.

However, relying on netlist topology to autodetect physical intent introduces severe architectural risks. This RFC proposes pivoting from silent auto-detection to an explicit intent API backed by a deterministic Placement Advisor, ensuring we protect users from bad physics without taking control away from the designer.

The Problem: Why Pure Topology-Based Auto-Detection is Dangerous
1. The Inversion of View and Model

When a human draws a schematic (the View), spatial proximity implies intent. But the compiler operates on a flattened netlist (the Model). When a heuristic script attempts to look at net.VCC and guess which capacitor belongs to which IC, it is trying to perform View $\rightarrow$ Model inference on a system that has been stripped of its visual context. This creates dangerous many-to-many ambiguities.

2. False Positives (Bulk vs. Decoupling Physics)

Topology alone cannot differentiate a decoupling capacitor from a bulk/reservoir capacitor. Both bridge VCC and GND. However, their physical placement rules are exact opposites:

  • Decoupling (e.g., 100nF Ceramic): Demands ultra-short traces (<1mm) to the power pin.
  • Bulk (e.g., 220µF Electrolytic): Has no strict proximity requirement to the pin, but often requires a minimum distance from heat-generating components (like voltage regulators) to prevent thermal derating.

If we automatically assume every power-to-ground capacitor is a decap, we will force the autorouter to apply a 1mm constraint to a massive 220µF electrolytic cap, resulting in absurd layouts or silent routing failures.

3. Stochastic Compounding

When an LLM (a stochastic generator) writes code, and the compiler (using heuristics) guesses what that code means, we lose all deterministic truth. The code no longer represents what the engineer meant, and the layout no longer reflects physical reality.

Proposed Architecture: The Power Capacitor Placement Advisor

Instead of silently mutating constraints, the compiler should act as a strict senior engineer: demanding explicit intent and failing loud when physics are at risk.

1. Explicit Intent is the Single Source of Truth

We should handle constraints by attaching them directly to Trace instances in Capacitor.doInitialCreateTracesFromProps, bypassing netlist ambiguity entirely.

// Explicit intent: The constraint is unambiguously bound to U1
<capacitor 
  capacitance="100nF" 
  decouplingFor={U1} 
  maxDecouplingTraceLength="1mm" 
/>

2. Classification by Value, Not Just Topology

To protect users who forget to define decouplingFor, we introduce a classifyPowerCap function that evaluates the component's values, not just its net connections:

  • <= 1µF (Ceramic) $\rightarrow$ Decoupling
  • >= 10µF (Electrolytic/Tantalum) $\rightarrow$ Bulk
  • 1µF - 10µF $\rightarrow$ Ambiguous
3. Fail Loud, Never Silent (Confidence Tiers)

Based on the classification, the compiler emits actionable feedback via renderError or warnings, rather than silently mutating the trace constraints.

  • High Confidence Error (Missing Decap Constraint): If a 100nF ceramic capacitor bridges a power net but lacks decouplingFor or a trace constraint, the build fails:

Error: C4 is topologically a decoupling cap but lacks a trace-length constraint. This is likely to cause IC brown-outs. To fix: add maxDecouplingTraceLength="1mm" (or decouplingFor={U1}). To override: add allowUnconstrained.

  • Medium Confidence Warning (Ambiguous Value): If a 4.7µF cap is detected without explicit intent:

⚠️ Warning: C9 (4.7µF) sits between VCC and GND. It could be a decoupling or bulk cap. Recommend explicitly defining decouplingFor or bulkFor.

4. Zero Silent Mutations

The framework must never silently rewrite the user's design. If we wish to offer an "auto-fix" to inject constraints, it must be invoked explicitly by the user (e.g., via tsci fix), which writes a visible diff to the source file.

Implementation Steps
  1. Deprecate/Reject any logic that automatically pairs power pins to capacitors based purely on flattened netlist matching.
  2. **Update Capacitor.ts** to strictly validate decouplingFor and decouplingTo during doInitialCreateTracesFromProps, raising a renderError if intent is partially defined or ambiguous.
  3. Propagate Constraints Directly: Ensure maxDecouplingTraceLength is passed directly onto the generated Trace objects before handing the Circuit JSON to the router.
  4. Implement the Advisor: Add the value-based classification linter to flag high-risk missing constraints before the routing phase begins.

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 with Capacitor.ts and doInitialCreateTracesFromProps, then trace how renderError and generated Trace objects reach the router. Review the existing automatic power-pin/capacitor pairing logic and determine how the proposed explicit intent and value-based advisor fit there. Done means the RFC's four implementation steps are addressed without silent constraint mutations.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.