recognizer/ — a visual tour

Six Python files that read a flat SPICE netlist and reverse-engineer its analog structure: which transistors form a differential pair, a current mirror, a bias generator — and which functional block each belongs to. Pick a page below, or read them top to bottom in learning order.

The one idea behind the whole package

"Given a flat pile of transistors with no labels, name the analog building blocks — using nothing but which devices share which wires."

A synthesized opamp, once flattened to SPICE, is just 20–40 devices and a mess of net names. A human designer glances at it and sees structure instantly. This package teaches a computer to do the same, in three layers, each a clean transform whose output is the next layer's input.

The three-layer pipeline

This is the map to keep in mind. Hover a stage to trace its data flow; click any box to open its page.

Layer 0 · parse() SPICE text → ParsedNetlist Layer 1 · recognize() match templates → every candidate hooks variable-size legs Layer 2 · FBR assign_slots() · group_by_category() candidates → named functional blocks models the dataclasses __init__ · public façade re-exports the 4 verbs + 7 shapes every layer's output is the next layer's input
Three transforms in a line; models supplies the shapes to all of them; hooks extends Layer 1; __init__ wraps it all in one import. Click a box to dive in.

Read in this order (reordered for learning)

Not the file's order, not alphabetical — simplest and most foundational first, orchestrator last. Learn the nouns, then the transforms bottom-up, then the façade that ties them together.

How these pages mirror the source tree

The generated pages follow the layout of circuitgenome/recognizer/ one-to-one. The tree is flat (the only subfolder, config/, holds YAML pattern libraries — no Python to explain, shown greyed below).

recognizer/ ├── __init__.py # 6 · public façade ├── models.py # 1 · dataclasses ├── netlist_parser.py # 2 · Layer 0 ├── subcircuit_recognizer.py # 3 · Layer 1 ├── hooks.py # 4 · Layer 1 hooks ├── functional_block_recognizer.py # 5 · Layer 2 └── config/ # YAML pattern libraries (not Python) ├── primitives.yaml ├── structural_patterns.yaml └── opamp_patterns.yaml

The whole package, in one snippet

If you remember nothing else, remember this shape — four verbs, three layers, one direction of flow:

from circuitgenome.recognizer import parse, recognize, group_by_category

netlist = parse(spice_text)              # Layer 0
sr      = recognize(netlist)             # Layer 1 — every candidate, overlaps and all
fbr     = group_by_category(sr, netlist) # Layer 2 — best-guess functional groups

In one sentence: the recognizer package turns a flat SPICE netlist into named analog building blocks through three connectivity-driven layers — parse, recognize, assign — that never look at a single transistor size.


Generated with the explain-code-with-fig skill · intuition-first teaching, hand-authored themeable SVG