diff --git a/backend/src/spicebook/engine/schematic.py b/backend/src/spicebook/engine/schematic.py index 3acd216..7a4a0f7 100644 --- a/backend/src/spicebook/engine/schematic.py +++ b/backend/src/spicebook/engine/schematic.py @@ -122,15 +122,12 @@ def parse_netlist(text: str) -> ParsedNetlist: if not lines: return ParsedNetlist() - # First non-blank, non-directive line is the title (SPICE convention) - title = "" - first_content = 0 - for i, line in enumerate(lines): - stripped = line.strip() - if stripped and not stripped.startswith(("*", ";", ".")): - title = stripped - first_content = i + 1 - break + # SPICE convention: line 1 is always the title, regardless of content. + # Strip leading * or ; (common title prefix) for display purposes. + title = lines[0].strip() + if title.startswith(("*", ";")): + title = title[1:].strip() + first_content = 1 # Pre-scan for .model statements to determine BJT/MOSFET polarity models: dict[str, str] = {} @@ -503,7 +500,7 @@ def _plan_active_layout( placed = set(exclude) 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 for p in tpaths: for c in p.components: @@ -557,6 +554,11 @@ def _path_style( return "output" if path.end_type == "ground": 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"