gm/Id — Geometry

Procedural geometry assignment for the gm/Id sizing path.

Replaces CP-SAT for PTM nodes: geometry is computed, not searched. With Id fixed by KCL and gm/Id = gm_req/Id fixed, the LUT gives Id/W W directly, so this is a deterministic forward pass:

  1. per-device (W, L) from GmIdModel.geometry_for();

  2. snap W to the width grid (L is already grid-aligned by the L-policy);

  3. symmetry — matched pairs get the anchor’s geometry (plain assignment);

  4. mirror ratios — each output’s W is the exact current ratio times the diode-connected reference’s W at matched L (no Fraction rounding);

  5. load margin — a single-ended plain current-source load balancing a mirrored tail gets _LOAD_CS_MARGIN extra width (see its docstring).

Symmetry is applied before mirror ratios; on the rare device that is both, the mirror constraint wins (it is the bias-current-correctness fix). Both rules are self-consistent for matched pairs, so the order only matters for resolution, not for the result.

circuitgenome.sizer.gmid.geometry.swing_gm_id_floor(model, dtype, l_um, vod_max)[source]

gm/Id floor so vds_sat _SWING_VDSAT_FRACTION · vod_max.

Returns (floor, fits_raw_budget). floor is the smallest LUT gm/Id meeting the margin target (weaker inversion = lower Vdsat), or the table’s weakest-inversion point as best effort when no point reaches the target. fits_raw_budget is False when even the weakest inversion cannot fit the raw budget — the output stage cannot meet the swing spec at all.

Parameters:
Return type:

tuple[float, bool]

circuitgenome.sizer.gmid.geometry.assign_geometry_gmid(model, all_transistors, slot_transistors, ids_map, intents, gm_target_map, tech, vod_max_map=None)[source]

Return ({ref: TransistorSizing}, warnings, feasible) for the gm/Id path.

Geometry follows each device’s TransistorIntent: its role, its (per-block) gm/Id region and channel length. Signal devices ignore the intent’s gm/Id and solve it from gm_target_map.

vod_max_map carries the output-swing Vdsat budgets: output-path devices get a gm/Id floor targeting _SWING_VDSAT_FRACTION of their budget. Excluded from the floor (but still checked against the raw budget):

  • mirror outputs — their inversion tracks the diode reference;

  • signal devices under a cascode first-stage load — their V_GS is the stage-interface pin (stage_interface), and moving it for swing breaks the knife-edge saturation window (measured: 18 accepted folded-cascode + common_source_nmos candidates lost to a blanket floor). Those candidates’ high loop gain keeps the swing bench tracking well past the Vdsat point, so the floor is not needed there.

feasible is False when an output-path device cannot fit its raw budget even at the weakest inversion.

Parameters:
Return type:

tuple[dict[str, TransistorSizing], list[str], bool]