Fix title parser and feedback component routing in schematics

Title parser: always use line 0 as title per SPICE convention instead
of skipping * comment lines (which consumed component definitions).

Layout engine: pass growing placed set to path tracing to prevent
feedback components (e.g. col→base cap) from being double-traced.
Route feedback paths from the output terminal horizontally right
instead of defaulting to "down" through the transistor body.
This commit is contained in:
Ryan Malloy 2026-03-01 23:30:57 -07:00
parent 2faa581e0b
commit 347f569968

View File

@ -122,15 +122,12 @@ def parse_netlist(text: str) -> ParsedNetlist:
if not lines: if not lines:
return ParsedNetlist() return ParsedNetlist()
# First non-blank, non-directive line is the title (SPICE convention) # SPICE convention: line 1 is always the title, regardless of content.
title = "" # Strip leading * or ; (common title prefix) for display purposes.
first_content = 0 title = lines[0].strip()
for i, line in enumerate(lines): if title.startswith(("*", ";")):
stripped = line.strip() title = title[1:].strip()
if stripped and not stripped.startswith(("*", ";", ".")): first_content = 1
title = stripped
first_content = i + 1
break
# Pre-scan for .model statements to determine BJT/MOSFET polarity # Pre-scan for .model statements to determine BJT/MOSFET polarity
models: dict[str, str] = {} models: dict[str, str] = {}
@ -503,7 +500,7 @@ def _plan_active_layout(
placed = set(exclude) placed = set(exclude)
for tname, tnode in terminals.items(): for tname, tnode in terminals.items():
tpaths = _trace_paths_from_terminal(tnode, tname, node_map, exclude) tpaths = _trace_paths_from_terminal(tnode, tname, node_map, placed)
paths[tname] = tpaths paths[tname] = tpaths
for p in tpaths: for p in tpaths:
for c in p.components: for c in p.components:
@ -557,6 +554,11 @@ def _path_style(
return "output" return "output"
if path.end_type == "ground": if path.end_type == "ground":
return "down" return "down"
# Feedback / coupling paths ending at non-supply, non-ground nodes
# (e.g., collector→base feedback cap): route horizontally outward
# from the output terminal to avoid crossing through the body.
if term_name == output_term:
return "output"
return "down" return "down"