Layer 2 V1 — MOSFET / IGBT builder helpers¶
V6 shipped the generic CircuitBuilder (with
add_switch, add_diode, add_resistor, etc.). V1 of
Layer 2 adds SMPS-friendly device wrappers that bake in:
- Power-switch defaults (
R_on,R_offtypical of modern Si MOSFETs and IGBT modules). - Body-diode wiring (one-call instead of two).
- SI units (ohms, volts) so users don't manually compute conductance.
API¶
// MOSFET — single controlled switch, no body diode.
b.add_mosfet("Q1", "drain", "source",
R_on=1e-3, R_off=1e9);
// MOSFET with intrinsic anti-parallel body diode.
b.add_mosfet_with_body_diode(
"Q1", "drain", "source",
R_on=1e-3, R_off=1e9, V_F=0.7);
// IGBT — single controlled switch (no body diode by
// default, since discrete IGBTs typically don't include
// one).
b.add_igbt("T1", "collector", "emitter",
R_on=10e-3, R_off=1e9);
Available from both C++ and Python — same names, same defaults.
Defaults¶
| Param | MOSFET | IGBT | Notes |
|---|---|---|---|
R_on |
1 mΩ | 10 mΩ | Typical Si power device |
R_off |
1 GΩ | 1 GΩ | Leakage cap |
V_F (body diode) |
0.7 V | — | Si body diode |
g_on_diode |
1 kS | — | Matches add_diode default |
g_off_diode |
1 nS | — | Matches add_diode default |
add_mosfet_with_body_diode internals¶
b.add_mosfet_with_body_diode("Q1", "drain", "source")
Adds TWO branches in sequence:
- Switch branch (drain → source) with
g_on = 1/R_on,g_off = 1/R_off. Driven byswitch_fn(t)at simulation time. - Diode branch (source → drain — ANTI-PARALLEL!) with
V_th = V_F,g_on = g_on_diode,g_off = g_off_diode. Auto-commutates via the V2 diode-iteration loop.
The diode direction (source → drain) matches the intrinsic body-diode direction of an n-channel MOSFET: conduction flows from source to drain when the channel is off and the load tries to push current backward (typical freewheeling scenario in inductive loads).
SMPS example: synchronous buck¶
CircuitBuilder b;
b.add_voltage_source("Vin", "vin", "gnd", 24.0);
// High-side MOSFET (the controlled "buck" switch).
b.add_mosfet_with_body_diode("Q1", "vin", "sw");
// Low-side MOSFET (synchronous rectifier — its body
// diode handles dead-time freewheeling).
b.add_mosfet_with_body_diode("Q2", "sw", "gnd");
// LC output filter + load.
b.add_inductor ("L1", "sw", "vout", 100e-6);
b.add_capacitor("Cout", "vout", "gnd", 47e-6);
b.add_resistor ("R_L", "vout", "gnd", 10.0);
Without the V1 helpers:
// Same circuit, manually:
b.add_voltage_source("Vin", "vin", "gnd", 24.0);
// Q1 main switch + Q1 body diode (4 branches just for the
// two MOSFETs!).
b.add_switch("Q1_main", "vin", "sw", 1000.0, 1e-9);
b.add_diode ("Q1_body", "sw", "vin", 1e3, 1e-9, 0.7);
b.add_switch("Q2_main", "sw", "gnd", 1000.0, 1e-9);
b.add_diode ("Q2_body", "gnd", "sw", 1e3, 1e-9, 0.7);
b.add_inductor ("L1", "sw", "vout", 100e-6);
b.add_capacitor("Cout", "vout", "gnd", 47e-6);
b.add_resistor ("R_L", "vout", "gnd", 10.0);
Equivalent topology, but the V1 helpers cut 4 lines and remove the mental load of remembering body-diode direction and default conductances.
Python¶
Identical names + defaults:
import pulsim as p
b = p.CircuitBuilder()
b.add_voltage_source("Vin", "vin", "gnd", 24.0)
b.add_mosfet_with_body_diode("Q1", "vin", "sw")
b.add_diode("D1", "gnd", "sw", 1e3, 1e-9, V_th=0.7)
b.add_inductor("L1", "sw", "vout", 100e-6)
b.add_capacitor("Cout", "vout", "gnd", 47e-6)
b.add_resistor("R_L", "vout", "gnd", 10.0)
cache = p.PwlStateSpaceCache(b.graph, b.pool)
cache.build(dt=1e-7)
# ... ready for run_transient.
Test coverage¶
C++ (core/tests/v2/builder/test_circuit_builder.cpp,
6 new cases):
- add_mosfet adds 1 branch, correct g_on = 1/R_on.
- add_mosfet defaults (R_on = 1mΩ, R_off = 1GΩ).
- add_mosfet_with_body_diode adds 2 branches, diode
anti-parallel direction.
- add_mosfet_with_body_diode defaults (V_F = 0.7 V).
- add_igbt adds 1 branch, correct IGBT defaults.
- Buck topology smoke: source + MOSFET-w-body-diode +
freewheeling diode + R = 5 branches with the expected
StoredKind per branch.
Python (python/tests/v2/test_v2_python_bindings.py,
5 new cases):
- add_mosfet callable.
- add_mosfet_with_body_diode adds 2 branches.
- add_mosfet with custom R_on.
- add_igbt callable.
- Buck topology via the MOSFET helper builds + factors
without raising.
What V0 deliberately does NOT do¶
- Shichman-Hodges Level 1 MOSFET (
I_D = K (V_GS − V_T)²in saturation). Requires a 3-terminal AD-driven channel model with the gate as a control input. Future research OpenSpec. - Gate-charge / switching-loss modeling (
C_iss,C_oss,t_on,t_off,E_on,E_off). V0 treats switching as instantaneous. - Temperature dependence (R_on(T), V_F(T)). V0 is isothermal.
- Three-terminal package with gate node. V0 uses the
switch_fn mechanism — gate signals come in via
switch_fn(t), not as an explicit gate node.
Files¶
- MODIFIED
core/include/pulsim/builder/circuit_builder.hpp(+add_mosfet,add_mosfet_with_body_diode,add_igbt) - MODIFIED
core/tests/v2/builder/test_circuit_builder.cpp(+ 6 cases) - MODIFIED
python/bindings_v2_kernel.cpp(+ 3 Python bindings) - MODIFIED
python/tests/v2/test_v2_python_bindings.py(+ 5 cases) - NEW
openspec/changes/pulsim-v2-mosfet-igbt/