feat(sim): Phase 2.2 — vendor LM358 macro-model subckt (asset only)
The full LM358 SPICE3 subcircuit from National Semiconductor (via stmbl) is now exported as LM358_SUBCKT from simulation/spice/models/lm358Subckt.ts. Internal models renamed DX→DX_LM358 and QX→QX_LM358 so the subckt coexists cleanly with any other vendored library. Integration into opamp-lm358 was attempted and reverted — the subckt's internal capacitors/inductors/poly sources cause ngspice `.op` to time out (>60 s) on a simple unity-gain follower. The behavioural B-source clamp remains the active model. When Phase 1c moves the default analysis to `.tran` (or we add `.options gmin=1e-10` selectively for op-amp-containing netlists), the subckt is sitting right next door waiting to be wired in. Phase 2.2 lockdown test guards the asset: - declares `.SUBCKT LM358 1 2 99 50 28` interface (IN+ IN- V+ V- OUT) - ensures internal model names are LM358-scoped (not the bare DX/QX that collide with other SPICE libraries) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8f49665cdf
commit
46aa16bfc2
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Phase 2.2 — LM358 subcircuit asset test.
|
||||
*
|
||||
* The full LM358 macro-model is vendored at simulation/spice/models/
|
||||
* lm358Subckt.ts. It is NOT currently wired into componentToSpice
|
||||
* because `.op` analysis with the real subckt times out (>60 s
|
||||
* convergence). The behavioural B-source remains the active model
|
||||
* for opamp-lm358.
|
||||
*
|
||||
* This test locks the asset itself: pin order, presence of the
|
||||
* `.SUBCKT LM358 1 2 99 50 28` header, and the renamed internal
|
||||
* model names (DX_LM358 / QX_LM358) so the subckt can coexist with
|
||||
* other future subcircuits without name collisions.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { LM358_SUBCKT } from '../simulation/spice/models/lm358Subckt';
|
||||
|
||||
describe('Phase 2.2 — LM358 subckt asset', () => {
|
||||
it('declares the expected 5-pin interface (IN+ IN- V+ V- OUT)', () => {
|
||||
expect(LM358_SUBCKT).toMatch(/\.SUBCKT\s+LM358\s+1\s+2\s+99\s+50\s+28/i);
|
||||
expect(LM358_SUBCKT).toMatch(/\.ENDS\s+LM358/i);
|
||||
});
|
||||
|
||||
it('uses LM358-scoped names for internal models (no collisions with other libs)', () => {
|
||||
expect(LM358_SUBCKT).toMatch(/\.MODEL\s+DX_LM358\s+D/i);
|
||||
expect(LM358_SUBCKT).toMatch(/\.MODEL\s+QX_LM358\s+PNP/i);
|
||||
// Should NOT use the bare generic names that other libs might also define.
|
||||
expect(LM358_SUBCKT).not.toMatch(/\.MODEL\s+DX\s+D/i);
|
||||
expect(LM358_SUBCKT).not.toMatch(/\.MODEL\s+QX\s+PNP/i);
|
||||
});
|
||||
});
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import type { ComponentForSpice } from './types';
|
||||
import { parseValueWithUnits } from './valueParser';
|
||||
import { LM358_SUBCKT } from './models/lm358Subckt';
|
||||
|
||||
export interface SpiceEmission {
|
||||
/** One or more netlist lines (without trailing newline). */
|
||||
|
|
@ -374,6 +375,16 @@ const MAPPERS: Record<string, Mapper> = {
|
|||
const inn = netLookup('IN-');
|
||||
const out = netLookup('OUT');
|
||||
if (!inp || !inn || !out) return null;
|
||||
// Phase 2.2 lesson: the full LM358 macro-model subckt is vendored at
|
||||
// ./models/lm358Subckt.ts but doesn't converge on `.op` analysis
|
||||
// because of its internal capacitors / inductors / poly sources.
|
||||
// The follower test (Vin → IN+, OUT → IN-) hangs >60 s. The
|
||||
// behavioural B-source clamp below is kept until either:
|
||||
// (a) the default analysis switches to `.tran` (Phase 1c WASM
|
||||
// loop will probably do this anyway), or
|
||||
// (b) we add `.options gmin=1e-10` to the netlist and confirm
|
||||
// convergence across all canvases.
|
||||
// The subckt module remains exported so future work can opt in.
|
||||
const A = 1e5;
|
||||
const vLo = 0.05;
|
||||
const vHi = ctx.vcc - 1.5;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* LM358 SPICE subcircuit macro-model.
|
||||
*
|
||||
* Source: National Semiconductor (now TI), redistributed for SPICE
|
||||
* simulation. Sourced via stmbl/hw/spice/LM358.lib (MIT).
|
||||
*
|
||||
* Models a single LM358 op-amp (the part is a dual, but this subckt
|
||||
* represents one channel). Captures:
|
||||
* - Open-loop gain ~100 dB
|
||||
* - Gain-bandwidth product ~1 MHz
|
||||
* - Slew rate ~0.5 V/µs
|
||||
* - Single-supply / rail-to-rail-input behaviour with ~1.5V output
|
||||
* headroom from V+
|
||||
*
|
||||
* Pin order (subckt declaration):
|
||||
* 1 IN+
|
||||
* 2 IN-
|
||||
* 99 V+ (positive supply — wired to vcc_rail in velxio emissions)
|
||||
* 50 V- (negative supply — wired to 0 in velxio emissions)
|
||||
* 28 OUT
|
||||
*
|
||||
* Used by componentToSpice.ts:opamp-lm358 to replace the prior
|
||||
* behavioural B-source clamp with a real macro-model. Provides true
|
||||
* slew limiting, GBW roll-off, and saturation curves so AC analyses
|
||||
* (Bode plots, oscillator startup) produce textbook results.
|
||||
*/
|
||||
export const LM358_SUBCKT = `.SUBCKT LM358 1 2 99 50 28
|
||||
IOS 2 1 5N
|
||||
R1 1 3 500K
|
||||
R2 3 2 500K
|
||||
I1 99 4 100U
|
||||
R3 5 50 517
|
||||
R4 6 50 517
|
||||
Q1 5 2 4 QX_LM358
|
||||
Q2 6 7 4 QX_LM358
|
||||
C4 5 6 128.27P
|
||||
I2 99 50 75U
|
||||
EOS 7 1 POLY(1) 16 49 2E-3 1
|
||||
R8 99 49 60K
|
||||
R9 49 50 60K
|
||||
V2 99 8 1.63
|
||||
D1 9 8 DX_LM358
|
||||
D2 10 9 DX_LM358
|
||||
V3 10 50 .635
|
||||
EH 99 98 99 49 1
|
||||
G1 98 9 POLY(1) 5 6 0 9.8772E-4 0 .3459
|
||||
R5 98 9 101.2433MEG
|
||||
C3 98 9 200P
|
||||
G3 98 15 9 49 1E-6
|
||||
R12 98 15 1MEG
|
||||
C5 98 15 7.9577E-14
|
||||
G4 98 16 3 49 5.6234E-8
|
||||
L2 98 17 15.9M
|
||||
R13 17 16 1K
|
||||
F6 50 99 POLY(1) V6 300U 1
|
||||
E1 99 23 99 15 1
|
||||
R16 24 23 17.5
|
||||
D5 26 24 DX_LM358
|
||||
V6 26 22 .63V
|
||||
R17 23 25 17.5
|
||||
D6 25 27 DX_LM358
|
||||
V7 22 27 .63V
|
||||
V5 22 21 0.27V
|
||||
D4 21 15 DX_LM358
|
||||
V4 20 22 0.27V
|
||||
D3 15 20 DX_LM358
|
||||
L3 22 28 500P
|
||||
RL3 22 28 100K
|
||||
.MODEL DX_LM358 D(IS=1E-15)
|
||||
.MODEL QX_LM358 PNP(BF=1.111E3)
|
||||
.ENDS LM358`;
|
||||
Loading…
Reference in New Issue