Source code for circuitgenome.sizer.sizer

"""
Initial Sizing module — Layer 3 of the CircuitGenome pipeline.

:func:`size_circuit` is the dispatcher: it routes a parsed netlist plus its
Layer-2 :class:`~circuitgenome.recognizer.models.FunctionalBlockRecognitionResult`
and a performance spec to the right sizer and returns a
:class:`~.shared.models.SizingResult`.

* technologies with a gm/Id LUT → the block-based gm/Id pipeline
  (:func:`~circuitgenome.sizer.gmid.gmid_sizer.size_gmid`);
* the card-less ``generic`` technology → the Level-1 CP-SAT sizer
  (:func:`~.analytical.level1.size_level1`);
* a PTM/SPICE-model node **without** a LUT → ``UnsupportedTechError`` (the
  Level-1 square-law numbers are not valid for such nodes).
"""
from __future__ import annotations

from circuitgenome.recognizer.models import (
    FunctionalBlockRecognitionResult,
    ParsedNetlist,
    SubcircuitRecognitionResult,
)
from circuitgenome.synthesizer.models import TopologyTemplate

from .shared.models import SizingResult, SizingSpec, TechParams, UnsupportedTechError


[docs] def size_circuit( parsed: ParsedNetlist, sr_result: SubcircuitRecognitionResult, fbr_result: FunctionalBlockRecognitionResult, topology: TopologyTemplate, tech: TechParams, spec: SizingSpec, *, time_limit_s: float = 30.0, ) -> SizingResult: """Compute initial transistor W/L values satisfying ``spec``. :param parsed: Layer-0 parsed netlist. :param sr_result: Layer-1 subcircuit recognition result (unused directly but kept for API symmetry with the pipeline). :param fbr_result: Layer-2 FBR result from :func:`~circuitgenome.recognizer.functional_block_recognizer.assign_slots`. Must use **topology mode** (not group-by-category). :param topology: Topology template corresponding to ``fbr_result``. :param tech: Technology parameters (from :func:`~.shared.loader.load_tech`). :param spec: Performance specification. :param time_limit_s: CP-SAT solver time limit in seconds (Level-1 path only). :returns: :class:`~.shared.models.SizingResult` with per-transistor sizing, compensation cap, computed metrics, and safety margins. """ # gm/Id technologies (LUT present) use the block-based pipeline. if getattr(tech, "gmid_lut", None): from .gmid import size_gmid return size_gmid(parsed, sr_result, fbr_result, topology, tech, spec) # A PTM/SPICE-model node without a gm/Id LUT must not silently fall through # to the Level-1 square-law sizer — those are the inaccurate numbers gm/Id # exists to avoid. Only the card-less generic tech uses the analytical path. if getattr(tech, "spice_model", None): raise UnsupportedTechError( f"Technology '{tech.name}' is a PTM/SPICE-model node without a gm/Id " f"LUT. The analytical (Level-1) sizer is not valid for PTM nodes — " f"characterize a gm/Id LUT first (see issue #73). Only the 'generic' " f"technology uses the analytical sizer.") from .analytical.level1 import size_level1 return size_level1(parsed, sr_result, fbr_result, topology, tech, spec, time_limit_s=time_limit_s)