Models¶
Core data models for the subcircuit and functional block recognizers.
All structures are plain dataclasses — they carry no logic and can be freely
inspected or passed between pipeline stages. They mirror the 3-layer
pipeline described in the design doc
(docs/plans/2026_06_15_subcircuit_and_functional_block_recognizer.md):
ParsedNetlistis the output of Layer 0 (netlist parsing).SubcircuitRecognitionResult(made up ofRecognizedStructureinstances) is the output of Layer 1, the Subcircuit Recognizer (SR).FunctionalBlockRecognitionResult(made up ofSlotAssignmentinstances) is the output of Layer 2, the Functional Block Recognizer (FBR).
PatternDevice, PatternDef, and HookMatch describe
the SR pattern-library schema used by
circuitgenome.recognizer.subcircuit_recognizer.
- class circuitgenome.recognizer.models.ParsedNetlist(name, external_ports, devices, internal_nets)[source]¶
Bases:
objectA flat SPICE subcircuit, parsed into devices and net names.
Output of
parse()(Layer 0) – the structural inverse ofto_flat_spice().- Parameters:
- class circuitgenome.recognizer.models.RecognizedStructure(name, category, circuit_block, index, tech_type, pins, devices, children=<factory>)[source]¶
Bases:
objectA single recognized structure – one SR pattern match.
Produced by
recognize()(Layer 1).SubcircuitRecognitionResult.structuresmay contain multiple overlappingRecognizedStructureinstances covering the same devices (seeSubcircuitRecognitionResult); FBR (Layer 2) is responsible for picking, per topology slot, the one whosepinsline up with that slot’s expected connectivity.- Parameters:
name (str) – The matching
PatternDef’s name, e.g."differential_pair_nmos". For composite patterns (seePatternDef) this is also the correspondingopamp_modules.yamlvariant name.category (str | None) – The matching pattern’s category, e.g.
"input_pair"(one of theopamp_modules.yamlmodule categories).Nonefor level-0 primitives and structural composites that have no FBR counterpart.circuit_block (str | None) – High-level functional block, e.g.
"gain_stage_1","gain_stage_2","bias","compensation", or"cmfb".Nonefor primitives and structural composites. Used bygroup_by_category()to group structures without a topology template.index (int) – 0-based instance number, distinguishing repeated matches of the same pattern (e.g. a second
differential_pair_nmoscandidate elsewhere in the netlist).tech_type (str | None) –
"n","p", orNone– the technology of the pattern’sPatternDef.tech_type_fromtemplate device, orNoneif the pattern doesn’t declare one.pins (dict[str, str]) – Maps pin names (from
PatternDef.pins, plus anyextra_pinscontributed by aHookMatch) to the actual net names they resolve to in this netlist.devices (list[Device]) – The actual
Deviceinstances matched by this structure (the base template assignment, plus anyextra_devicesfrom aHookMatch).children (list[RecognizedStructure]) – Sub-structures from multi-level composition. Empty for level-0 primitives and MVP composite-only patterns; populated for level-1+ patterns.
- children: list[RecognizedStructure]¶
- class circuitgenome.recognizer.models.SubcircuitRecognitionResult(structures, unrecognized_devices=<factory>)[source]¶
Bases:
objectOutput of Layer 1, the Subcircuit Recognizer (SR).
- Parameters:
structures (list[RecognizedStructure]) – Every
RecognizedStructurematched by any pattern in the library. May contain multiple overlapping candidates for the same device-set – e.g. two patterns with structurally identical templates but different categories/names, or a composite pattern’s reference device that also satisfies a smaller, unrelated pattern. SR reports every candidate; it does not pick a winner. Layer 2 (FBR) resolves overlaps using topology context.unrecognized_devices (list[Device]) – Devices matched by no pattern. For a netlist produced by
to_flat_spice()from a knownSynthesizedCircuit, this should be empty – a non-empty list indicates a pattern-library gap.
- structures: list[RecognizedStructure]¶
- class circuitgenome.recognizer.models.PatternDevice(ref, type)[source]¶
Bases:
objectOne template device within a
PatternDef.- Parameters:
ref (str) – Template-local reference used by
PatternDef.same_netandPatternDef.pinsto refer to this device, e.g."m1". Scoped to the enclosing pattern – unrelated to the actual netlist’s device refs.type (str) – The device type this template slot matches:
"nmos","pmos","resistor", or"capacitor". Matchestype.
- class circuitgenome.recognizer.models.ChildDef(pattern, devices)[source]¶
Bases:
objectOne required child in a multi-level composite pattern.
- Parameters:
pattern (str) – Name of the expected child
PatternDef, e.g."diode_connected_nmos".devices (list[str]) – Template device refs (from the enclosing
PatternDef) that together form this child. E.g.["m_ref"]for a single-device child or["m_dr", "m_dl"]for a two-device child.
- class circuitgenome.recognizer.models.PatternDef(name, category, circuit_block, devices, same_net, pins, tech_type_from=None, hook=None, children=<factory>, exclusive=False, priority=0)[source]¶
Bases:
objectA single SR pattern definition, loaded from
config/primitives.yaml,config/structural_patterns.yaml, orconfig/opamp_patterns.yaml.A pattern is a small template graph: a handful of typed
PatternDeviceslots,same_netequality constraints between their terminals, and apinsmap exporting named nets. Seerecognize()for the matching algorithm.Level-0 primitive patterns describe single-device topological facts (e.g.
diode_connected_nmos). Exclusive primitives claim a device for exactly one pattern (higherprioritywins).Level-1+ composite patterns declare
childrenreferencing lower-level patterns they compose; the SR verifies those children are present before accepting a match.MVP composite patterns (no
children, notexclusive) correspond 1:1 to anopamp_modules.yamlmodule variant and run in the same single-pass loop as before.- Parameters:
name (str) – Unique pattern name, e.g.
"differential_pair_nmos". For composite patterns, also theopamp_modules.yamlvariant name – this is the value that ends up inRecognizedStructure.nameandSlotAssignment.pattern_name.category (str | None) – The
opamp_modules.yamlmodule category this pattern represents, e.g."input_pair".Nonefor primitives and structural composites without an FBR counterpart. Copied intoRecognizedStructure.category.circuit_block (str | None) – High-level functional block this pattern belongs to, e.g.
"gain_stage_1","gain_stage_2","bias","compensation", or"cmfb". Usesgain_stage_Nnaming (neversecond_stage) to avoid clashing withcategoryvalues.Nonefor primitives and structural composites. Copied intoRecognizedStructure.circuit_block.devices (list[PatternDevice]) – The pattern’s template devices. The matcher searches for an injective assignment from these to actual netlist devices of matching
PatternDevice.type.same_net (list[list[str]]) – Equality constraints on resolved terminals, each written as a list of
"template_ref.terminal"strings, e.g.[["m1.s", "m2.s"]]means “m1’s source andm2’s source must be the same net”. These are the only required equalities – terminals not listed are unconstrained, so a more-connected real circuit can still match.pins (dict[str, str]) – Maps an exported pin name to a
"template_ref.terminal"string. Resolved through the matched assignment to produceRecognizedStructure.pins.tech_type_from (str | None) – The template device ref (e.g.
"m1") whose matchedtype(first character,"n"or"p") becomesRecognizedStructure.tech_type.Noneif the pattern declares no dominant technology.hook (str | None) – Optional
"module:function"path to an extra-check function (seeHookMatch), resolved dynamically byrecognize(). Most patterns have no hook.children (list[ChildDef]) – Required sub-structures for multi-level composition. Empty for level-0 patterns and MVP composites. When non-empty,
recognizeverifies each child is present as a matched structure at the previous level before accepting this pattern’s match.exclusive (bool) – If
True, this pattern claims its matched device(s) exclusively in Pass 0 – each device is assigned to at most one exclusive pattern. Only level-0 primitives use this.priority (int) – Tie-breaking priority among
exclusivepatterns that match the same device; higher wins. E.g.diode_connected_nmos(priority 10) beatsnmos(priority 0).
- devices: list[PatternDevice]¶
- class circuitgenome.recognizer.models.HookMatch(extra_devices=<factory>, extra_pins=<factory>)[source]¶
Bases:
objectAccept-and-extend result of a
PatternDef.hookfunction.A hook is called once per base-template match (
recognize()’s(assignment, pins, netlist)) and returns either:None– reject this match entirely (it is dropped, as if the pattern hadn’t matched).a
HookMatch– accept the match, mergingextra_devicesintoRecognizedStructure.devicesandextra_pinsintoRecognizedStructure.pins(in addition to the base template’s devices/pins).
The motivating example is
diode_connected_mosfet_bias(diode_connected_mosfet_bias_legs()): its base template is just the 1-device diode-connected bias reference, and the hook discovers however many output “legs” (1-7, one per needed bias rail) are actually present in the netlist and appends their devices andlegN_outpins.- Parameters:
extra_devices (list[Device]) – Additional
Deviceinstances to append toRecognizedStructure.devices, beyond the base template assignment.extra_pins (dict[str, str]) – Additional
pin name -> net nameentries to merge intoRecognizedStructure.pins, beyond the base template’sPatternDef.pins.
- class circuitgenome.recognizer.models.SlotAssignment(slot_name, pattern_name, structure)[source]¶
Bases:
objectOne FBR decision: a recognized structure assigned to a topology slot.
- Parameters:
slot_name (str) – The
nameof the topology slot this assignment fills, e.g."input_pair".pattern_name (str) – The assigned structure’s
RecognizedStructure.name. For a correct round trip, this equals thenameof the variant that was synthesized into this slot.structure (RecognizedStructure) – The assigned
RecognizedStructureitself.
- structure: RecognizedStructure¶
- class circuitgenome.recognizer.models.FunctionalBlockRecognitionResult(slot_assignments, unassigned_structures=<factory>, unrecognized_devices=<factory>)[source]¶
Bases:
objectOutput of Layer 2, the Functional Block Recognizer (FBR).
MVP taxonomy: the
opamp_modules.yamlcategories plus the matchedTopologyTemplate(design doc section 6.2). Produced byassign_slots().- Parameters:
slot_assignments (dict[str, SlotAssignment]) – Maps each
namethat received a candidate to itsSlotAssignment. Shaped likevariant_map({slot_name: ...}), so the two can be compared directly in round-trip tests.unassigned_structures (list[RecognizedStructure]) – SR candidates that were not assigned to any slot (e.g. overlapping/spurious pattern matches that lost to a better-connected candidate).
unrecognized_devices (list[Device]) – Passed through unchanged from
SubcircuitRecognitionResult.unrecognized_devices.
- slot_assignments: dict[str, SlotAssignment]¶
- unassigned_structures: list[RecognizedStructure]¶
- class circuitgenome.recognizer.models.CategoryGroupResult(groups, unrecognized_devices=<factory>)[source]¶
Bases:
objectLayer 2 output when no
TopologyTemplateis available.Produced by
group_by_category(). Structures are grouped first bycircuit_block(e.g."gain_stage_1","bias") then bycategory(e.g."input_pair","load"). Within each category list, candidates are ranked by descending external-port adjacency — how many of the structure’s pins connect directly to a subcircuit external port.- Parameters:
groups (dict[str, dict[str, list[RecognizedStructure]]]) –
circuit_block → category → candidates(ranked, best-guess first). Structures withcircuit_block=Noneare excluded.unrecognized_devices (list[Device]) – Passed through unchanged from
SubcircuitRecognitionResult.unrecognized_devices.