Device Model

Small-signal device-model abstraction shared by both sizing paths.

The op-amp topology relationships (gain = ∏ gmᵢ·routᵢ, GBW = gm1/2πCc, phase margin, CMRR, …) are model-independent — only the device primitives differ:

  • the Level-1 square law (equations.gm/gd/vds_sat), used for the card-less generic tech, and

  • the gm/Id lookup table (GmIdLut), used for PTM nodes.

Both implement DeviceModel so compute_requirements and _evaluate_metrics in sizer can stay single-source. Level1Model reproduces the existing numbers exactly (regression-safe); GmIdModel adds the LUT-backed primitives plus the geometry inversion and L-selection policy used by the procedural geometry pass.

Two roles drive the gm/Id policy:

  • "signal" — a gain/transconductance device (input pair, gain-stage signal transistor): its gm/Id is set by the required gm; L favours a balance of gain and ft.

  • "current_source" — a bias/load device (tail, active load, bias gen): no gm target; sized at a nominal gm/Id and a longer L for high output resistance.

class circuitgenome.sizer.shared.device_model.DeviceModel(*args, **kwargs)[source]

Bases: Protocol

Small-signal primitives consumed by requirement-derivation and metrics.

All geometry arguments are in µm and currents in A; dtype is "nmos" or "pmos". Level1Model implements these from the square law and GmIdModel from the LUT, so the topology math in sizer can call through one interface.

is_gmid: bool
gm(dtype, w_um, l_um, ids)[source]

Transconductance gm in A/V at the device’s operating point.

Parameters:
Return type:

float

gds(dtype, w_um, l_um, ids)[source]

Output conductance gds in A/V at the device’s operating point.

Parameters:
Return type:

float

vds_sat(dtype, w_um, l_um, ids)[source]

Minimum |VDS| for saturation in V.

Parameters:
Return type:

float

vgs(dtype, w_um, l_um, ids)[source]

Gate-source voltage in V (signed: +ve NMOS, −ve PMOS).

Parameters:
Return type:

float

gm_ceiling(dtype, ids, l_um)[source]

Physical upper bound on gm in A/V (weak-inversion limit).

Parameters:
Return type:

float

gds_estimate(dtype, ids, role)[source]

Geometry-free gds in A/V from the device’s role.

Used during requirement derivation, before geometry is chosen, where Level-1 returns λ·Id and gm/Id uses the role’s nominal operating point (see SIGNAL / CURRENT_SOURCE).

Parameters:
Return type:

float

class circuitgenome.sizer.shared.device_model.Level1Model(tech)[source]

Bases: object

Shichman-Hodges primitives — byte-for-byte the current generic behaviour.

Parameters:

tech (TechParams)

is_gmid = False
gm(dtype, w_um, l_um, ids)[source]

Square-law gm √(2·µCox·(W/L)·|Id|) (gm()).

gds(dtype, w_um, l_um, ids)[source]

Level-1 gds λ·|Id| — geometry-independent (W/L ignored).

vds_sat(dtype, w_um, l_um, ids)[source]

Square-law saturation overdrive (vds_sat()).

vgs(dtype, w_um, l_um, ids)[source]

Square-law gate-source voltage (vgs_from_ids()).

gm_ceiling(dtype, ids, l_um)[source]

Weak-inversion gm ceiling 25·|Id| (dtype/L-independent).

gds_estimate(dtype, ids, role)[source]

Geometry-free gds λ·|Id|role is irrelevant under the square law.

class circuitgenome.sizer.shared.device_model.GmIdPolicy(signal_l_mult=2.0, cs_l_mult=4.0, cs_gmid=10.0, signal_nominal_gmid=14.0, cascode_l_mult=3.0, cascode_gmid=8.0)[source]

Bases: object

L / gm-Id selection policy for the procedural gm/Id sizer.

Defaults are starting points tuned during SPICE validation. At L_min the 45 nm intrinsic gain gm/gds is only ~7, so gain-critical (signal) devices use a moderate L multiple; current sources use a longer L for output resistance and a low gm/Id for headroom.

Parameters:
signal_l_mult: float = 2.0
cs_l_mult: float = 4.0
cs_gmid: float = 10.0
signal_nominal_gmid: float = 14.0
cascode_l_mult: float = 3.0
cascode_gmid: float = 8.0
class circuitgenome.sizer.shared.device_model.GeomResult(w_um, l_um, gm_id, gm_id_capped)[source]

Bases: object

Geometry computed for one device by GmIdModel.geometry_for().

Parameters:
  • w_um (float) – Gate width in µm.

  • l_um (float) – Gate length in µm (from the L-policy, grid-snapped).

  • gm_id (float) – Operating transconductance efficiency gm/Id in 1/V.

  • gm_id_capped (bool) – True when the gm/Id target was clamped to the table’s weak-inversion ceiling (the design will fall short of its gm).

w_um: float
l_um: float
gm_id: float
gm_id_capped: bool
class circuitgenome.sizer.shared.device_model.GmIdModel(tech, lut, policy=None)[source]

Bases: object

LUT-backed primitives + geometry inversion and L-policy.

Parameters:
is_gmid = True
role_length(role)[source]

Channel length for role from the L-policy multiplier (µm, snapped).

Parameters:

role (str)

Return type:

float

length_for(l_mult)[source]

Channel length for an explicit L multiple of length.min (µm, snapped).

Parameters:

l_mult (float)

Return type:

float

gm(dtype, w_um, l_um, ids)[source]

Transconductance (gm/Id)·|Id| at the geometry’s operating point.

gds(dtype, w_um, l_um, ids)[source]

Output conductance gm/(gm/gds) read from the LUT at the operating gm/Id.

vds_sat(dtype, w_um, l_um, ids)[source]

Saturation overdrive VDS,sat read from the LUT (V).

vgs(dtype, w_um, l_um, ids)[source]

Gate-source voltage from the LUT, signed +ve NMOS / −ve PMOS.

gm_ceiling(dtype, ids, l_um)[source]

Weak-inversion gm ceiling max_gm_id·|Id| from the table.

gds_estimate(dtype, ids, role)[source]

Geometry-free gds from the role’s nominal operating point.

geometry_for(dtype, ids, role, gm_target=None, *, gm_id=None, l_um=None, gm_id_min=None)[source]

Compute (W, L) for a device from its role and (optional) gm target.

current_source/cascode devices use the policy gm/Id (cascodes at a smaller-Vdsat region); signal devices set gm/Id = gm_target/Id, clamped to the table’s weak-inversion ceiling.

gm_id and l_um are per-device design-intent overrides (from the block registry): an explicit gm/Id region for a non-signal device and an explicit channel length. When None they fall back to the role policy, so the default behaviour is unchanged. gm_id is ignored for a signal device with a gm target — its gm/Id is always solved from the spec.

gm_id_min floors the operating gm/Id regardless of role — used to cap VDS_sat for output-swing (weaker inversion = lower Vdsat). Raising a solved signal gm/Id is spec-safe: gm = (gm/Id)·Id only grows.

Parameters:
Return type:

GeomResult

circuitgenome.sizer.shared.device_model.build_device_model(tech)[source]

Select the gm/Id model when the tech carries a LUT, else Level-1.

Parameters:

tech (TechParams)

Return type:

DeviceModel