Extract template registries into templates.py
The two inline registries (_TEMPLATES, _ASC_TEMPLATES) plus their ~30 generator-function imports were pure data living in server.py. Move them to a dedicated templates.py as NETLIST_TEMPLATES / ASC_TEMPLATES, and add resolve_template() (netlist-first precedence) + all_template_names() to replace the '.get() or .get()' dual-lookup dance that tune_circuit used. server.py: 3257 -> 2949 lines. Registries verified byte-identical to the originals (keys, params, descriptions, func identities); netlist-first precedence for names in both registries preserved; live tune_circuit / create_from_template / generate_schematic unchanged.
This commit is contained in:
parent
7c4f09cbb3
commit
c71b3bbb4c
@ -21,51 +21,6 @@ import numpy as np
|
|||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
from fastmcp.prompts import Message
|
from fastmcp.prompts import Message
|
||||||
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_boost_converter as generate_boost_converter_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_buck_converter as generate_buck_converter_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_colpitts_oscillator as generate_colpitts_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_common_emitter_amp as generate_ce_amp_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_current_mirror as generate_current_mirror_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_differential_amp as generate_diff_amp_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_h_bridge as generate_h_bridge_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_instrumentation_amp as generate_inamp_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_inverting_amp,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_ldo_regulator as generate_ldo_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_non_inverting_amp as generate_noninv_amp_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_rc_lowpass as generate_rc_lowpass_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_sallen_key_lowpass as generate_sallen_key_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_transimpedance_amp as generate_tia_asc,
|
|
||||||
)
|
|
||||||
from .asc_generator import (
|
|
||||||
generate_voltage_divider as generate_voltage_divider_asc,
|
|
||||||
)
|
|
||||||
from .batch import (
|
from .batch import (
|
||||||
run_monte_carlo,
|
run_monte_carlo,
|
||||||
run_parameter_sweep,
|
run_parameter_sweep,
|
||||||
@ -82,24 +37,7 @@ from .drc import run_drc as _run_drc
|
|||||||
from .log_parser import parse_log
|
from .log_parser import parse_log
|
||||||
from .models import search_models as _search_models
|
from .models import search_models as _search_models
|
||||||
from .models import search_subcircuits as _search_subcircuits
|
from .models import search_subcircuits as _search_subcircuits
|
||||||
from .netlist import (
|
from .netlist import Netlist
|
||||||
Netlist,
|
|
||||||
boost_converter,
|
|
||||||
buck_converter,
|
|
||||||
colpitts_oscillator,
|
|
||||||
common_emitter_amplifier,
|
|
||||||
current_mirror,
|
|
||||||
differential_amplifier,
|
|
||||||
h_bridge,
|
|
||||||
instrumentation_amplifier,
|
|
||||||
inverting_amplifier,
|
|
||||||
ldo_regulator,
|
|
||||||
non_inverting_amplifier,
|
|
||||||
rc_lowpass,
|
|
||||||
sallen_key_lowpass,
|
|
||||||
transimpedance_amplifier,
|
|
||||||
voltage_divider,
|
|
||||||
)
|
|
||||||
from .noise_analysis import (
|
from .noise_analysis import (
|
||||||
compute_noise_metrics,
|
compute_noise_metrics,
|
||||||
compute_spot_noise,
|
compute_spot_noise,
|
||||||
@ -122,6 +60,12 @@ from .spicebook import (
|
|||||||
)
|
)
|
||||||
from .stability import compute_stability_metrics
|
from .stability import compute_stability_metrics
|
||||||
from .svg_plot import plot_bode, plot_spectrum, plot_timeseries, plot_timeseries_multi
|
from .svg_plot import plot_bode, plot_spectrum, plot_timeseries, plot_timeseries_multi
|
||||||
|
from .templates import (
|
||||||
|
ASC_TEMPLATES,
|
||||||
|
NETLIST_TEMPLATES,
|
||||||
|
all_template_names,
|
||||||
|
resolve_template,
|
||||||
|
)
|
||||||
from .touchstone import parse_touchstone, s_param_to_db
|
from .touchstone import parse_touchstone, s_param_to_db
|
||||||
from .waveform_expr import WaveformCalculator
|
from .waveform_expr import WaveformCalculator
|
||||||
from .waveform_math import (
|
from .waveform_math import (
|
||||||
@ -1200,7 +1144,7 @@ async def tune_circuit(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
template: Template name (from list_templates). Works with both
|
template: Template name (from list_templates). Works with both
|
||||||
netlist templates (_TEMPLATES) and schematic templates (_ASC_TEMPLATES).
|
netlist templates (NETLIST_TEMPLATES) and schematic templates (ASC_TEMPLATES).
|
||||||
params: Component value overrides (e.g., {"r": "2.2k", "c": "47n"}).
|
params: Component value overrides (e.g., {"r": "2.2k", "c": "47n"}).
|
||||||
Use list_templates to see available parameters.
|
Use list_templates to see available parameters.
|
||||||
targets: Performance targets to check against. Each key is a metric name,
|
targets: Performance targets to check against. Each key is a metric name,
|
||||||
@ -1213,14 +1157,12 @@ async def tune_circuit(
|
|||||||
Returns:
|
Returns:
|
||||||
Dict with metrics, target comparison, and tuning suggestions.
|
Dict with metrics, target comparison, and tuning suggestions.
|
||||||
"""
|
"""
|
||||||
# --- 1. Look up template ---
|
# --- 1. Look up template (netlist registry first) ---
|
||||||
tmpl = _TEMPLATES.get(template)
|
found = resolve_template(template)
|
||||||
is_netlist = tmpl is not None
|
if found is None:
|
||||||
if tmpl is None:
|
names = all_template_names()
|
||||||
tmpl = _ASC_TEMPLATES.get(template)
|
|
||||||
if tmpl is None:
|
|
||||||
names = sorted(set(list(_TEMPLATES.keys()) + list(_ASC_TEMPLATES.keys())))
|
|
||||||
return {"error": f"Unknown template '{template}'. Available: {', '.join(names)}"}
|
return {"error": f"Unknown template '{template}'. Available: {', '.join(names)}"}
|
||||||
|
tmpl, is_netlist = found
|
||||||
|
|
||||||
# --- 2. Build effective params ---
|
# --- 2. Build effective params ---
|
||||||
effective_params: dict[str, str] = dict(tmpl["params"])
|
effective_params: dict[str, str] = dict(tmpl["params"])
|
||||||
@ -1773,103 +1715,6 @@ async def monte_carlo(
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
|
||||||
_ASC_TEMPLATES: dict[str, dict] = {
|
|
||||||
"rc_lowpass": {
|
|
||||||
"func": generate_rc_lowpass_asc,
|
|
||||||
"description": "RC lowpass filter with AC analysis",
|
|
||||||
"params": {"r": "1k", "c": "100n"},
|
|
||||||
},
|
|
||||||
"voltage_divider": {
|
|
||||||
"func": generate_voltage_divider_asc,
|
|
||||||
"description": "Resistive voltage divider with .op analysis",
|
|
||||||
"params": {"r1": "10k", "r2": "10k", "vin": "5"},
|
|
||||||
},
|
|
||||||
"inverting_amp": {
|
|
||||||
"func": generate_inverting_amp,
|
|
||||||
"description": "Inverting op-amp amplifier (gain = -Rf/Rin)",
|
|
||||||
"params": {"rin": "10k", "rf": "100k"},
|
|
||||||
},
|
|
||||||
"non_inverting_amp": {
|
|
||||||
"func": generate_noninv_amp_asc,
|
|
||||||
"description": "Non-inverting op-amp amplifier (gain = 1 + Rf/Rin)",
|
|
||||||
"params": {"rin": "10k", "rf": "100k"},
|
|
||||||
},
|
|
||||||
"common_emitter_amp": {
|
|
||||||
"func": generate_ce_amp_asc,
|
|
||||||
"description": "Common-emitter BJT amplifier with voltage divider bias",
|
|
||||||
"params": {
|
|
||||||
"rc": "2.2k", "rb1": "56k", "rb2": "12k", "re": "1k",
|
|
||||||
"cc_in": "10u", "cc_out": "10u", "ce": "47u",
|
|
||||||
"vcc": "12", "bjt_model": "2N2222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"colpitts_oscillator": {
|
|
||||||
"func": generate_colpitts_asc,
|
|
||||||
"description": "Colpitts oscillator with LC tank and BJT",
|
|
||||||
"params": {
|
|
||||||
"ind": "1u", "c1": "100p", "c2": "100p",
|
|
||||||
"rb": "47k", "rc": "1k", "re": "470",
|
|
||||||
"vcc": "12", "bjt_model": "2N2222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"differential_amp": {
|
|
||||||
"func": generate_diff_amp_asc,
|
|
||||||
"description": "Differential amplifier with op-amp",
|
|
||||||
"params": {"r1": "10k", "r2": "10k", "r3": "10k", "r4": "10k"},
|
|
||||||
},
|
|
||||||
"buck_converter": {
|
|
||||||
"func": generate_buck_converter_asc,
|
|
||||||
"description": "Buck (step-down) converter with NMOS switch",
|
|
||||||
"params": {
|
|
||||||
"ind": "10u", "c_out": "100u", "r_load": "10",
|
|
||||||
"v_in": "12", "duty_cycle": "0.5", "freq": "100k",
|
|
||||||
"mosfet_model": "IRF540N", "diode_model": "1N5819",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"ldo_regulator": {
|
|
||||||
"func": generate_ldo_asc,
|
|
||||||
"description": "LDO voltage regulator with PMOS pass transistor",
|
|
||||||
"params": {
|
|
||||||
"r1": "10k", "r2": "10k", "pass_transistor": "IRF9540N",
|
|
||||||
"v_in": "8", "v_ref": "2.5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"h_bridge": {
|
|
||||||
"func": generate_h_bridge_asc,
|
|
||||||
"description": "H-bridge motor driver with 4 NMOS transistors",
|
|
||||||
"params": {"v_supply": "12", "r_load": "10", "mosfet_model": "IRF540N"},
|
|
||||||
},
|
|
||||||
"sallen_key_lowpass": {
|
|
||||||
"func": generate_sallen_key_asc,
|
|
||||||
"description": "Sallen-Key lowpass filter (unity gain, 2nd order)",
|
|
||||||
"params": {"r1": "10k", "r2": "10k", "c1": "10n", "c2": "10n"},
|
|
||||||
},
|
|
||||||
"boost_converter": {
|
|
||||||
"func": generate_boost_converter_asc,
|
|
||||||
"description": "Boost (step-up) converter with NMOS switch",
|
|
||||||
"params": {
|
|
||||||
"ind": "10u", "c_out": "100u", "r_load": "50",
|
|
||||||
"v_in": "5", "duty_cycle": "0.5", "freq": "100k",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"instrumentation_amp": {
|
|
||||||
"func": generate_inamp_asc,
|
|
||||||
"description": "3-opamp instrumentation amplifier",
|
|
||||||
"params": {"r1": "10k", "r2": "10k", "r3": "10k", "r_gain": "10k"},
|
|
||||||
},
|
|
||||||
"current_mirror": {
|
|
||||||
"func": generate_current_mirror_asc,
|
|
||||||
"description": "BJT current mirror with reference and load",
|
|
||||||
"params": {"r_ref": "10k", "r_load": "1k", "vcc": "12"},
|
|
||||||
},
|
|
||||||
"transimpedance_amp": {
|
|
||||||
"func": generate_tia_asc,
|
|
||||||
"description": "Transimpedance amplifier (current to voltage)",
|
|
||||||
"params": {"rf": "100k", "cf": "1p", "i_source": "1u"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def generate_schematic(
|
def generate_schematic(
|
||||||
template: str,
|
template: str,
|
||||||
@ -1894,11 +1739,11 @@ def generate_schematic(
|
|||||||
Use list_templates to see available parameters for each template.
|
Use list_templates to see available parameters for each template.
|
||||||
output_path: Where to save the .asc file (None = auto in /tmp)
|
output_path: Where to save the .asc file (None = auto in /tmp)
|
||||||
"""
|
"""
|
||||||
if template not in _ASC_TEMPLATES:
|
if template not in ASC_TEMPLATES:
|
||||||
names = ", ".join(sorted(_ASC_TEMPLATES))
|
names = ", ".join(sorted(ASC_TEMPLATES))
|
||||||
return {"error": f"Unknown template '{template}'. Available: {names}"}
|
return {"error": f"Unknown template '{template}'. Available: {names}"}
|
||||||
|
|
||||||
entry = _ASC_TEMPLATES[template]
|
entry = ASC_TEMPLATES[template]
|
||||||
call_params: dict[str, str | float] = {}
|
call_params: dict[str, str | float] = {}
|
||||||
|
|
||||||
if params:
|
if params:
|
||||||
@ -2143,159 +1988,6 @@ def create_netlist(
|
|||||||
# CIRCUIT TEMPLATE TOOLS
|
# CIRCUIT TEMPLATE TOOLS
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Registry of netlist templates with parameter metadata
|
|
||||||
_TEMPLATES: dict[str, dict] = {
|
|
||||||
"voltage_divider": {
|
|
||||||
"func": voltage_divider,
|
|
||||||
"description": "Resistive voltage divider with .op or custom analysis",
|
|
||||||
"params": {"v_in": "5", "r1": "10k", "r2": "10k", "sim_type": "op"},
|
|
||||||
},
|
|
||||||
"rc_lowpass": {
|
|
||||||
"func": rc_lowpass,
|
|
||||||
"description": "RC lowpass filter with AC sweep",
|
|
||||||
"params": {"r": "1k", "c": "100n", "f_start": "1", "f_stop": "1meg"},
|
|
||||||
},
|
|
||||||
"inverting_amplifier": {
|
|
||||||
"func": inverting_amplifier,
|
|
||||||
"description": "Inverting op-amp (gain = -Rf/Rin), +/-15V supply",
|
|
||||||
"params": {"r_in": "10k", "r_f": "100k", "opamp_model": "LT1001"},
|
|
||||||
},
|
|
||||||
"non_inverting_amplifier": {
|
|
||||||
"func": non_inverting_amplifier,
|
|
||||||
"description": "Non-inverting op-amp (gain = 1 + Rf/Rin), +/-15V supply",
|
|
||||||
"params": {"r_in": "10k", "r_f": "100k", "opamp_model": "LT1001"},
|
|
||||||
},
|
|
||||||
"differential_amplifier": {
|
|
||||||
"func": differential_amplifier,
|
|
||||||
"description": "Diff amp: Vout = (R2/R1)*(V2-V1), +/-15V supply",
|
|
||||||
"params": {
|
|
||||||
"r1": "10k",
|
|
||||||
"r2": "10k",
|
|
||||||
"r3": "10k",
|
|
||||||
"r4": "10k",
|
|
||||||
"opamp_model": "LT1001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"common_emitter_amplifier": {
|
|
||||||
"func": common_emitter_amplifier,
|
|
||||||
"description": "BJT common-emitter with voltage divider bias",
|
|
||||||
"params": {
|
|
||||||
"rc": "2.2k",
|
|
||||||
"rb1": "56k",
|
|
||||||
"rb2": "12k",
|
|
||||||
"re": "1k",
|
|
||||||
"cc1": "10u",
|
|
||||||
"cc2": "10u",
|
|
||||||
"ce": "47u",
|
|
||||||
"vcc": "12",
|
|
||||||
"bjt_model": "2N2222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"buck_converter": {
|
|
||||||
"func": buck_converter,
|
|
||||||
"description": "Step-down DC-DC converter with MOSFET switch",
|
|
||||||
"params": {
|
|
||||||
"ind": "10u",
|
|
||||||
"c_out": "100u",
|
|
||||||
"r_load": "10",
|
|
||||||
"v_in": "12",
|
|
||||||
"duty_cycle": "0.5",
|
|
||||||
"freq": "100k",
|
|
||||||
"mosfet_model": "IRF540N",
|
|
||||||
"diode_model": "1N5819",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"ldo_regulator": {
|
|
||||||
"func": ldo_regulator,
|
|
||||||
"description": "LDO regulator: Vout = Vref * (1 + R1/R2)",
|
|
||||||
"params": {
|
|
||||||
"opamp_model": "LT1001",
|
|
||||||
"r1": "10k",
|
|
||||||
"r2": "10k",
|
|
||||||
"pass_transistor": "IRF9540N",
|
|
||||||
"v_in": "8",
|
|
||||||
"v_ref": "2.5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"colpitts_oscillator": {
|
|
||||||
"func": colpitts_oscillator,
|
|
||||||
"description": "LC oscillator: f ~ 1/(2pi*sqrt(L*Cseries))",
|
|
||||||
"params": {
|
|
||||||
"ind": "1u",
|
|
||||||
"c1": "100p",
|
|
||||||
"c2": "100p",
|
|
||||||
"rb": "47k",
|
|
||||||
"rc": "1k",
|
|
||||||
"re": "470",
|
|
||||||
"vcc": "12",
|
|
||||||
"bjt_model": "2N2222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"h_bridge": {
|
|
||||||
"func": h_bridge,
|
|
||||||
"description": "4-MOSFET H-bridge motor driver with dead time",
|
|
||||||
"params": {
|
|
||||||
"v_supply": "12",
|
|
||||||
"r_load": "10",
|
|
||||||
"mosfet_model": "IRF540N",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"sallen_key_lowpass": {
|
|
||||||
"func": sallen_key_lowpass,
|
|
||||||
"description": "Sallen-Key lowpass filter (unity gain, 2nd order)",
|
|
||||||
"params": {
|
|
||||||
"r1": "10k",
|
|
||||||
"r2": "10k",
|
|
||||||
"c1": "10n",
|
|
||||||
"c2": "10n",
|
|
||||||
"opamp_model": "LT1001",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"boost_converter": {
|
|
||||||
"func": boost_converter,
|
|
||||||
"description": "Step-up DC-DC converter with MOSFET switch",
|
|
||||||
"params": {
|
|
||||||
"ind": "10u",
|
|
||||||
"c_out": "100u",
|
|
||||||
"r_load": "50",
|
|
||||||
"v_in": "5",
|
|
||||||
"duty_cycle": "0.5",
|
|
||||||
"freq": "100k",
|
|
||||||
"mosfet_model": "IRF540N",
|
|
||||||
"diode_model": "1N5819",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"instrumentation_amplifier": {
|
|
||||||
"func": instrumentation_amplifier,
|
|
||||||
"description": "3-opamp instrumentation amp: gain = 1 + 2*R1/R_gain",
|
|
||||||
"params": {
|
|
||||||
"r1": "10k",
|
|
||||||
"r2": "10k",
|
|
||||||
"r3": "10k",
|
|
||||||
"r_gain": "10k",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"current_mirror": {
|
|
||||||
"func": current_mirror,
|
|
||||||
"description": "BJT current mirror with reference resistor",
|
|
||||||
"params": {
|
|
||||||
"r_ref": "10k",
|
|
||||||
"r_load": "1k",
|
|
||||||
"vcc": "12",
|
|
||||||
"bjt_model": "2N2222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"transimpedance_amplifier": {
|
|
||||||
"func": transimpedance_amplifier,
|
|
||||||
"description": "TIA: converts input current to output voltage (Vout = -Iph * Rf)",
|
|
||||||
"params": {
|
|
||||||
"rf": "100k",
|
|
||||||
"cf": "1p",
|
|
||||||
"i_source": "1u",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def create_from_template(
|
def create_from_template(
|
||||||
@ -2329,13 +2021,13 @@ def create_from_template(
|
|||||||
params: Optional dict of parameter overrides (all values as strings)
|
params: Optional dict of parameter overrides (all values as strings)
|
||||||
output_path: Where to save .cir file (None = auto in /tmp)
|
output_path: Where to save .cir file (None = auto in /tmp)
|
||||||
"""
|
"""
|
||||||
template = _TEMPLATES.get(template_name)
|
template = NETLIST_TEMPLATES.get(template_name)
|
||||||
if template is None:
|
if template is None:
|
||||||
return {
|
return {
|
||||||
"error": f"Unknown template '{template_name}'",
|
"error": f"Unknown template '{template_name}'",
|
||||||
"available_templates": [
|
"available_templates": [
|
||||||
{"name": k, "description": v["description"], "params": v["params"]}
|
{"name": k, "description": v["description"], "params": v["params"]}
|
||||||
for k, v in _TEMPLATES.items()
|
for k, v in NETLIST_TEMPLATES.items()
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2386,9 +2078,9 @@ def list_templates() -> dict:
|
|||||||
"description": info["description"],
|
"description": info["description"],
|
||||||
"params": info["params"],
|
"params": info["params"],
|
||||||
}
|
}
|
||||||
for name, info in _TEMPLATES.items()
|
for name, info in NETLIST_TEMPLATES.items()
|
||||||
],
|
],
|
||||||
"total_count": len(_TEMPLATES),
|
"total_count": len(NETLIST_TEMPLATES),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2639,11 +2331,11 @@ def resource_templates() -> str:
|
|||||||
templates = {
|
templates = {
|
||||||
"netlist_templates": [
|
"netlist_templates": [
|
||||||
{"name": name, "description": info["description"], "params": info["params"]}
|
{"name": name, "description": info["description"], "params": info["params"]}
|
||||||
for name, info in _TEMPLATES.items()
|
for name, info in NETLIST_TEMPLATES.items()
|
||||||
],
|
],
|
||||||
"schematic_templates": [
|
"schematic_templates": [
|
||||||
{"name": name, "description": info["description"], "params": info["params"]}
|
{"name": name, "description": info["description"], "params": info["params"]}
|
||||||
for name, info in _ASC_TEMPLATES.items()
|
for name, info in ASC_TEMPLATES.items()
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
return json.dumps(templates, indent=2)
|
return json.dumps(templates, indent=2)
|
||||||
@ -2653,8 +2345,8 @@ def resource_templates() -> str:
|
|||||||
def resource_template_detail(name: str) -> str:
|
def resource_template_detail(name: str) -> str:
|
||||||
"""Detailed information about a specific circuit template."""
|
"""Detailed information about a specific circuit template."""
|
||||||
# Check both registries
|
# Check both registries
|
||||||
netlist_info = _TEMPLATES.get(name)
|
netlist_info = NETLIST_TEMPLATES.get(name)
|
||||||
asc_info = _ASC_TEMPLATES.get(name)
|
asc_info = ASC_TEMPLATES.get(name)
|
||||||
|
|
||||||
if not netlist_info and not asc_info:
|
if not netlist_info and not asc_info:
|
||||||
return json.dumps({"error": f"Template '{name}' not found"})
|
return json.dumps({"error": f"Template '{name}' not found"})
|
||||||
|
|||||||
315
src/mcltspice/templates.py
Normal file
315
src/mcltspice/templates.py
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
"""Circuit template registries.
|
||||||
|
|
||||||
|
Two registries map template names to builder functions and default params:
|
||||||
|
|
||||||
|
- NETLIST_TEMPLATES -> .netlist builders, producing SPICE .cir netlists
|
||||||
|
- ASC_TEMPLATES -> .asc_generator builders, producing graphical schematics
|
||||||
|
|
||||||
|
Some names appear in both (e.g. rc_lowpass). resolve_template() applies a
|
||||||
|
netlist-first precedence so a name available in both resolves to its netlist
|
||||||
|
form, matching the historical lookup order in tune_circuit.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .asc_generator import (
|
||||||
|
generate_boost_converter,
|
||||||
|
generate_buck_converter,
|
||||||
|
generate_colpitts_oscillator,
|
||||||
|
generate_common_emitter_amp,
|
||||||
|
generate_current_mirror,
|
||||||
|
generate_differential_amp,
|
||||||
|
generate_h_bridge,
|
||||||
|
generate_instrumentation_amp,
|
||||||
|
generate_inverting_amp,
|
||||||
|
generate_ldo_regulator,
|
||||||
|
generate_non_inverting_amp,
|
||||||
|
generate_rc_lowpass,
|
||||||
|
generate_sallen_key_lowpass,
|
||||||
|
generate_transimpedance_amp,
|
||||||
|
generate_voltage_divider,
|
||||||
|
)
|
||||||
|
from .netlist import (
|
||||||
|
boost_converter,
|
||||||
|
buck_converter,
|
||||||
|
colpitts_oscillator,
|
||||||
|
common_emitter_amplifier,
|
||||||
|
current_mirror,
|
||||||
|
differential_amplifier,
|
||||||
|
h_bridge,
|
||||||
|
instrumentation_amplifier,
|
||||||
|
inverting_amplifier,
|
||||||
|
ldo_regulator,
|
||||||
|
non_inverting_amplifier,
|
||||||
|
rc_lowpass,
|
||||||
|
sallen_key_lowpass,
|
||||||
|
transimpedance_amplifier,
|
||||||
|
voltage_divider,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Graphical .asc schematic templates (generate_schematic, tune_circuit fallback)
|
||||||
|
ASC_TEMPLATES: dict[str, dict] = {
|
||||||
|
"rc_lowpass": {
|
||||||
|
"func": generate_rc_lowpass,
|
||||||
|
"description": "RC lowpass filter with AC analysis",
|
||||||
|
"params": {"r": "1k", "c": "100n"},
|
||||||
|
},
|
||||||
|
"voltage_divider": {
|
||||||
|
"func": generate_voltage_divider,
|
||||||
|
"description": "Resistive voltage divider with .op analysis",
|
||||||
|
"params": {"r1": "10k", "r2": "10k", "vin": "5"},
|
||||||
|
},
|
||||||
|
"inverting_amp": {
|
||||||
|
"func": generate_inverting_amp,
|
||||||
|
"description": "Inverting op-amp amplifier (gain = -Rf/Rin)",
|
||||||
|
"params": {"rin": "10k", "rf": "100k"},
|
||||||
|
},
|
||||||
|
"non_inverting_amp": {
|
||||||
|
"func": generate_non_inverting_amp,
|
||||||
|
"description": "Non-inverting op-amp amplifier (gain = 1 + Rf/Rin)",
|
||||||
|
"params": {"rin": "10k", "rf": "100k"},
|
||||||
|
},
|
||||||
|
"common_emitter_amp": {
|
||||||
|
"func": generate_common_emitter_amp,
|
||||||
|
"description": "Common-emitter BJT amplifier with voltage divider bias",
|
||||||
|
"params": {
|
||||||
|
"rc": "2.2k", "rb1": "56k", "rb2": "12k", "re": "1k",
|
||||||
|
"cc_in": "10u", "cc_out": "10u", "ce": "47u",
|
||||||
|
"vcc": "12", "bjt_model": "2N2222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"colpitts_oscillator": {
|
||||||
|
"func": generate_colpitts_oscillator,
|
||||||
|
"description": "Colpitts oscillator with LC tank and BJT",
|
||||||
|
"params": {
|
||||||
|
"ind": "1u", "c1": "100p", "c2": "100p",
|
||||||
|
"rb": "47k", "rc": "1k", "re": "470",
|
||||||
|
"vcc": "12", "bjt_model": "2N2222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"differential_amp": {
|
||||||
|
"func": generate_differential_amp,
|
||||||
|
"description": "Differential amplifier with op-amp",
|
||||||
|
"params": {"r1": "10k", "r2": "10k", "r3": "10k", "r4": "10k"},
|
||||||
|
},
|
||||||
|
"buck_converter": {
|
||||||
|
"func": generate_buck_converter,
|
||||||
|
"description": "Buck (step-down) converter with NMOS switch",
|
||||||
|
"params": {
|
||||||
|
"ind": "10u", "c_out": "100u", "r_load": "10",
|
||||||
|
"v_in": "12", "duty_cycle": "0.5", "freq": "100k",
|
||||||
|
"mosfet_model": "IRF540N", "diode_model": "1N5819",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ldo_regulator": {
|
||||||
|
"func": generate_ldo_regulator,
|
||||||
|
"description": "LDO voltage regulator with PMOS pass transistor",
|
||||||
|
"params": {
|
||||||
|
"r1": "10k", "r2": "10k", "pass_transistor": "IRF9540N",
|
||||||
|
"v_in": "8", "v_ref": "2.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"h_bridge": {
|
||||||
|
"func": generate_h_bridge,
|
||||||
|
"description": "H-bridge motor driver with 4 NMOS transistors",
|
||||||
|
"params": {"v_supply": "12", "r_load": "10", "mosfet_model": "IRF540N"},
|
||||||
|
},
|
||||||
|
"sallen_key_lowpass": {
|
||||||
|
"func": generate_sallen_key_lowpass,
|
||||||
|
"description": "Sallen-Key lowpass filter (unity gain, 2nd order)",
|
||||||
|
"params": {"r1": "10k", "r2": "10k", "c1": "10n", "c2": "10n"},
|
||||||
|
},
|
||||||
|
"boost_converter": {
|
||||||
|
"func": generate_boost_converter,
|
||||||
|
"description": "Boost (step-up) converter with NMOS switch",
|
||||||
|
"params": {
|
||||||
|
"ind": "10u", "c_out": "100u", "r_load": "50",
|
||||||
|
"v_in": "5", "duty_cycle": "0.5", "freq": "100k",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"instrumentation_amp": {
|
||||||
|
"func": generate_instrumentation_amp,
|
||||||
|
"description": "3-opamp instrumentation amplifier",
|
||||||
|
"params": {"r1": "10k", "r2": "10k", "r3": "10k", "r_gain": "10k"},
|
||||||
|
},
|
||||||
|
"current_mirror": {
|
||||||
|
"func": generate_current_mirror,
|
||||||
|
"description": "BJT current mirror with reference and load",
|
||||||
|
"params": {"r_ref": "10k", "r_load": "1k", "vcc": "12"},
|
||||||
|
},
|
||||||
|
"transimpedance_amp": {
|
||||||
|
"func": generate_transimpedance_amp,
|
||||||
|
"description": "Transimpedance amplifier (current to voltage)",
|
||||||
|
"params": {"rf": "100k", "cf": "1p", "i_source": "1u"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPICE .cir netlist templates (create_from_template, list_templates, tune_circuit)
|
||||||
|
NETLIST_TEMPLATES: dict[str, dict] = {
|
||||||
|
"voltage_divider": {
|
||||||
|
"func": voltage_divider,
|
||||||
|
"description": "Resistive voltage divider with .op or custom analysis",
|
||||||
|
"params": {"v_in": "5", "r1": "10k", "r2": "10k", "sim_type": "op"},
|
||||||
|
},
|
||||||
|
"rc_lowpass": {
|
||||||
|
"func": rc_lowpass,
|
||||||
|
"description": "RC lowpass filter with AC sweep",
|
||||||
|
"params": {"r": "1k", "c": "100n", "f_start": "1", "f_stop": "1meg"},
|
||||||
|
},
|
||||||
|
"inverting_amplifier": {
|
||||||
|
"func": inverting_amplifier,
|
||||||
|
"description": "Inverting op-amp (gain = -Rf/Rin), +/-15V supply",
|
||||||
|
"params": {"r_in": "10k", "r_f": "100k", "opamp_model": "LT1001"},
|
||||||
|
},
|
||||||
|
"non_inverting_amplifier": {
|
||||||
|
"func": non_inverting_amplifier,
|
||||||
|
"description": "Non-inverting op-amp (gain = 1 + Rf/Rin), +/-15V supply",
|
||||||
|
"params": {"r_in": "10k", "r_f": "100k", "opamp_model": "LT1001"},
|
||||||
|
},
|
||||||
|
"differential_amplifier": {
|
||||||
|
"func": differential_amplifier,
|
||||||
|
"description": "Diff amp: Vout = (R2/R1)*(V2-V1), +/-15V supply",
|
||||||
|
"params": {
|
||||||
|
"r1": "10k",
|
||||||
|
"r2": "10k",
|
||||||
|
"r3": "10k",
|
||||||
|
"r4": "10k",
|
||||||
|
"opamp_model": "LT1001",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"common_emitter_amplifier": {
|
||||||
|
"func": common_emitter_amplifier,
|
||||||
|
"description": "BJT common-emitter with voltage divider bias",
|
||||||
|
"params": {
|
||||||
|
"rc": "2.2k",
|
||||||
|
"rb1": "56k",
|
||||||
|
"rb2": "12k",
|
||||||
|
"re": "1k",
|
||||||
|
"cc1": "10u",
|
||||||
|
"cc2": "10u",
|
||||||
|
"ce": "47u",
|
||||||
|
"vcc": "12",
|
||||||
|
"bjt_model": "2N2222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"buck_converter": {
|
||||||
|
"func": buck_converter,
|
||||||
|
"description": "Step-down DC-DC converter with MOSFET switch",
|
||||||
|
"params": {
|
||||||
|
"ind": "10u",
|
||||||
|
"c_out": "100u",
|
||||||
|
"r_load": "10",
|
||||||
|
"v_in": "12",
|
||||||
|
"duty_cycle": "0.5",
|
||||||
|
"freq": "100k",
|
||||||
|
"mosfet_model": "IRF540N",
|
||||||
|
"diode_model": "1N5819",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ldo_regulator": {
|
||||||
|
"func": ldo_regulator,
|
||||||
|
"description": "LDO regulator: Vout = Vref * (1 + R1/R2)",
|
||||||
|
"params": {
|
||||||
|
"opamp_model": "LT1001",
|
||||||
|
"r1": "10k",
|
||||||
|
"r2": "10k",
|
||||||
|
"pass_transistor": "IRF9540N",
|
||||||
|
"v_in": "8",
|
||||||
|
"v_ref": "2.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"colpitts_oscillator": {
|
||||||
|
"func": colpitts_oscillator,
|
||||||
|
"description": "LC oscillator: f ~ 1/(2pi*sqrt(L*Cseries))",
|
||||||
|
"params": {
|
||||||
|
"ind": "1u",
|
||||||
|
"c1": "100p",
|
||||||
|
"c2": "100p",
|
||||||
|
"rb": "47k",
|
||||||
|
"rc": "1k",
|
||||||
|
"re": "470",
|
||||||
|
"vcc": "12",
|
||||||
|
"bjt_model": "2N2222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"h_bridge": {
|
||||||
|
"func": h_bridge,
|
||||||
|
"description": "4-MOSFET H-bridge motor driver with dead time",
|
||||||
|
"params": {
|
||||||
|
"v_supply": "12",
|
||||||
|
"r_load": "10",
|
||||||
|
"mosfet_model": "IRF540N",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sallen_key_lowpass": {
|
||||||
|
"func": sallen_key_lowpass,
|
||||||
|
"description": "Sallen-Key lowpass filter (unity gain, 2nd order)",
|
||||||
|
"params": {
|
||||||
|
"r1": "10k",
|
||||||
|
"r2": "10k",
|
||||||
|
"c1": "10n",
|
||||||
|
"c2": "10n",
|
||||||
|
"opamp_model": "LT1001",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"boost_converter": {
|
||||||
|
"func": boost_converter,
|
||||||
|
"description": "Step-up DC-DC converter with MOSFET switch",
|
||||||
|
"params": {
|
||||||
|
"ind": "10u",
|
||||||
|
"c_out": "100u",
|
||||||
|
"r_load": "50",
|
||||||
|
"v_in": "5",
|
||||||
|
"duty_cycle": "0.5",
|
||||||
|
"freq": "100k",
|
||||||
|
"mosfet_model": "IRF540N",
|
||||||
|
"diode_model": "1N5819",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"instrumentation_amplifier": {
|
||||||
|
"func": instrumentation_amplifier,
|
||||||
|
"description": "3-opamp instrumentation amp: gain = 1 + 2*R1/R_gain",
|
||||||
|
"params": {
|
||||||
|
"r1": "10k",
|
||||||
|
"r2": "10k",
|
||||||
|
"r3": "10k",
|
||||||
|
"r_gain": "10k",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"current_mirror": {
|
||||||
|
"func": current_mirror,
|
||||||
|
"description": "BJT current mirror with reference resistor",
|
||||||
|
"params": {
|
||||||
|
"r_ref": "10k",
|
||||||
|
"r_load": "1k",
|
||||||
|
"vcc": "12",
|
||||||
|
"bjt_model": "2N2222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"transimpedance_amplifier": {
|
||||||
|
"func": transimpedance_amplifier,
|
||||||
|
"description": "TIA: converts input current to output voltage (Vout = -Iph * Rf)",
|
||||||
|
"params": {
|
||||||
|
"rf": "100k",
|
||||||
|
"cf": "1p",
|
||||||
|
"i_source": "1u",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_template(name: str) -> tuple[dict, bool] | None:
|
||||||
|
"""Resolve a template name to (entry, is_netlist), netlist registry first.
|
||||||
|
|
||||||
|
Returns None if the name is in neither registry. Netlist-first precedence
|
||||||
|
preserves the historical lookup order: a name present in both registries
|
||||||
|
(e.g. "rc_lowpass") resolves to its netlist form.
|
||||||
|
"""
|
||||||
|
if name in NETLIST_TEMPLATES:
|
||||||
|
return NETLIST_TEMPLATES[name], True
|
||||||
|
if name in ASC_TEMPLATES:
|
||||||
|
return ASC_TEMPLATES[name], False
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def all_template_names() -> list[str]:
|
||||||
|
"""Sorted union of every template name across both registries."""
|
||||||
|
return sorted(set(NETLIST_TEMPLATES) | set(ASC_TEMPLATES))
|
||||||
Loading…
x
Reference in New Issue
Block a user