CMFB Compatibility

CMFB-slot compatibility filter and pruning for enumerate_circuits().

Every fully_differential topology has a cmfb slot, wired cmfb.out -> net_cmfb_out -> load.bias_cmfb. But only 4 of the 12 load variants – folded_cascode_load_{nmos,pmos}_input_differential_output (gating mn3/mn4 or mp1/mp2) and current_source_load_{pmos,nmos} (gating both branch devices, issue #112), the four tagged output_cardinality: "differential" – declare bias_cmfb as role: input and actually reference it from a device terminal. The other 8 load variants declare bias_cmfb as role: optional and never reference it, so net_cmfb_out drives nothing for those combinations.

Without a filter, both cmfb variants (resistive_sense_cmfb/ dda_cmfb) would be enumerated for every combination, but for the 8 non-"differential" loads the choice between them makes zero difference to the assembled circuit – pure combinatorial duplication, plus 7-8 dead cmfb_* devices and an unnecessarily “needed” bias rail 4 (cmfb.bias).

is_cmfb_compatible() collapses this duplication: for a load whose output_cardinality isn’t "differential", only the canonical CANONICAL_CMFB_VARIANT is allowed through. prune_cmfb() then empties that variant’s ports/devices for those combinations, so it contributes no devices and cmfb.bias is no longer “needed” (see required_rail_kinds()).

To extend: tag a new or edited load variant with output_cardinality: "differential" (and give it a real bias_cmfb: role: input consumer) to make it a genuine cmfb consumer – no code changes needed here.

circuitgenome.synthesizer.compatibility.cmfb.is_cmfb_compatible(variant_map)[source]

Return False if cmfb’s variant choice is irrelevant for this combination.

Topologies without a cmfb slot are unaffected. For a load whose output_cardinality is "differential", both cmfb variants drive a real bias_cmfb consumer and remain distinct. For every other load, cmfb.out drives nothing, so only CANONICAL_CMFB_VARIANT is allowed through – the other variant would otherwise be enumerated as a duplicate no-op circuit.

Parameters:

variant_map (dict[str, ModuleVariant])

Return type:

bool

circuitgenome.synthesizer.compatibility.cmfb.prune_cmfb(variant, load)[source]

Return an empty placeholder if load doesn’t consume cmfb.out.

If load’s output_cardinality is "differential", variant is returned unchanged. Otherwise, returns a copy of variant with no ports and no devices – it contributes nothing to the assembled circuit, and cmfb.bias is no longer “needed” by required_rail_kinds().

Parameters:
Return type:

ModuleVariant