Bias Construction¶
Demand-driven bias-generation construction for
enumerate_circuits().
The bias generator is not an enumerated module variant: it is constructed
per combination from what the other slots actually consume on each bias rail.
This replaces the enumerate-then-filter-then-prune chain that the fixed
bias_generation variants needed (issues #99/#101/#102): every consumed
rail gets exactly the leg its consumer requires, so flavor mismatches,
unused legs, and the redundant rail-7 diode cannot arise in the first place.
Each consumed rail is classified into a kind – the type system this module is built around:
gate_vdd– a consumer MOSFET gate whose source sits at vdd (a PMOS current source). The rail must sit one|V_GSP|below vdd, and the leg’s diode-connected PMOS is the mirror master of its consumers: the sizer sets the consumer current by W/L ratio instead of hoping a voltage matches.gate_gnd– mirror image: consumer gate with source at gnd (NMOS current sink); NMOS diode leg oneV_GSNabove gnd.current_source– the consumer brings its own NMOS reference diode (a current-mirror tail’s mirror diode). The rail is a current interface: the leg is a bare PMOS mirror sourcing the reference current into the consumer’s diode. A voltage-style leg here would either duplicate the consumer’s diode (parallel diodes splitting the reference current) or fight it (the measured 22x rail-7 contention of issue #99).current_sink– mirror image for a PMOS-diode consumer: bare NMOS mirror sinking the reference current.cascode_gnd– an NMOS cascode gate: consumer gate on the rail with its source on an internal node (a stacked device below). The rail must sit at the cascode’sV_GSplus the saturation floor of the stack under it, so the leg is a diode-connected NMOS (the trackingV_GSpart) on a small floor resistor (out = V_GSN + I*R), both sized per-rail by the sizer from the consumer stack (issue #99’s parked cascode class).cascode_vdd– mirror image for PMOS cascode gates: diode-connected PMOS on a resistor to vdd (out = vdd - |V_GSP| - I*R).tunable– no structurally implied level: conflicting demands on a shared rail. The leg is a PMOS mirror into a resistor (out = I_leg * R), per-rail tunable by the sizer (issue #100).
The leg templates and the multi-reference core (NMOS master on the ibias
pin, plus a pref branch deriving the PMOS-side mirror reference, emitted
only when a leg needs it) live in config/bias_legs.yaml – see its header
for the electrical layout and the template net-name contract.
Both the demand analysis and the assembly are structural (actual device
terminal references, no YAML tags), so new consumer variants are classified
correctly without code changes. Construction must run after
prune_cmfb() /
prune_tail_current(),
so emptied placeholder slots demand nothing.
- circuitgenome.synthesizer.bias_construction.PREF_KINDS = frozenset({'cascode_gnd', 'current_source', 'gate_gnd', 'tunable'})¶
Rail kinds whose legs mirror from the PMOS-side reference gate. Present for documentation; the pref branch is actually emitted on a structural check (an instantiated leg terminal referencing
pref).
- circuitgenome.synthesizer.bias_construction.rail_flavor_from_diode(devices, node)[source]¶
Return the supply a diode-connected MOSFET on node pins it to.
A diode-connected device (
d == g == node) ties the node oneV_GSaway from whatever its source ultimately rests on, and its channel type names that supply: PMOS conducts from vdd ("vdd"), NMOS to gnd ("gnd"). The channel type is used rather than the source terminal so stacked references (a cascode tail’sd == g == biasdevice whose source is an internal node of the stack) resolve correctly. ReturnsNonewhen no diode-connected MOSFET sits on node.
- circuitgenome.synthesizer.bias_construction.required_rail_kinds(topology, variant_map)[source]¶
Return
{rail_index: kind}for every bias rail actually consumed.A rail is consumed when any device terminal of the slot’s variant references the port the topology wires to
net_bias1..``net_bias8`` (declared-but-unwiredoptionalports are ignored, exactly like the retiredneeded_bias_outputs). The kind combines the per-device votes of_device_votes()across all consuming slots:a diode vote wins over gate votes: the consumer’s own diode makes the rail a current interface, and any mirror gates riding on it (the tail’s output device) are slaved to that diode, not to the leg;
a single gate kind is taken as-is;
a single cascode kind (and no diode/gate votes) is taken as-is – a supply-referenced gate sharing the rail would need one
V_GSwhere the cascode needsV_GSplus a floor, so that mix is a conflict;conflicting votes fall back to
tunable– the honest “no single structural level implied” answer.
Unconsumed rails are absent from the result and get no leg at all.
- Parameters:
topology (TopologyTemplate)
variant_map (dict[str, ModuleVariant])
- Return type:
- circuitgenome.synthesizer.bias_construction.construct_bias_generation(topology, variant_map, library)[source]¶
Assemble the bias-generation variant this combination needs.
Emits the master reference, one leg per consumed rail (template chosen by
required_rail_kinds(), with the per-leg netsout/midrewritten toout{i}/mid{i}and each ref suffixed with the rail index), and theprefbranch when any instantiated leg references theprefnet. The result is a normalModuleVariant(nameconstructed_bias) – downstream wiring, serialization, and the recognizer treat it like any other variant.pref(and the pref branch’sprefsrc/ncasc, and the cascode legs’mid{i}) are not ports, so they resolve to slot-internal nets.- Parameters:
topology (TopologyTemplate)
variant_map (dict[str, ModuleVariant])
library (BiasLegLibrary)
- Return type: