fixed 555-timer-2 convergence issue
This commit is contained in:
parent
347c51c523
commit
96551df137
|
|
@ -151,6 +151,14 @@ struct CKTcircuit {
|
|||
/* `.option nostaterestore` opt-out of the dctran failed-attempt
|
||||
* device-state restore (CKTstate0 <- CKTstate1 on timepoint retry). */
|
||||
int CKTstateRestoreOff;
|
||||
/* `.option noorderguard` opt-out of the dctran non-uniform-history
|
||||
* predictor guard (forced CKTorder=1 on >10x dt-history ratio). */
|
||||
int CKTorderGuardOff;
|
||||
/* `.option currentsettle` opt-IN to honoring device convTest
|
||||
* CKTnoncon reports in NIconvTest (upstream trunk 0638aaa16
|
||||
* current-settling enforcement). Default 0 = ngspice-46
|
||||
* solution-only convergence semantics. */
|
||||
int CKTcurrentSettle;
|
||||
/* Per-iteration count of huge-finite Jacobian entries clipped by
|
||||
* sanitize_jacobian during CKTload. When > 0, the model evaluation
|
||||
* is in a numerical regime (e.g. BSIM-BULK near a singular operating
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ enum {
|
|||
* SPICE3 solution-only behaviour. */
|
||||
OPT_NOSTATERESTORE, /* `.option nostaterestore` opts out of the dctran
|
||||
* failed-attempt device-state restore. */
|
||||
OPT_NOORDERGUARD, /* `.option noorderguard` opts out of the dctran
|
||||
* non-uniform-history predictor order guard. */
|
||||
OPT_EQNS,
|
||||
OPT_REORDTIME,
|
||||
OPT_METHOD,
|
||||
|
|
@ -156,6 +158,14 @@ enum {
|
|||
OPT_NODTCLEAR, /* `.option nodtclear` disables the small-dt
|
||||
* CKTnoncon clear in niiter.c. See CKTdtClearOff
|
||||
* comment in cktdefs.h. */
|
||||
OPT_CURRENTSETTLE, /* `.option currentsettle` opts IN to NIconvTest
|
||||
* honoring device convTest CKTnoncon reports.
|
||||
* NOTE: appended at the enum TAIL deliberately —
|
||||
* the region between OPT_GMIN=1 and
|
||||
* OPT_SYNCTIME=58 is full; inserting there
|
||||
* collides auto-numbered members with the
|
||||
* OPT_SYNCTIME anchor (duplicate-case build
|
||||
* error in cktacct.c). */
|
||||
};
|
||||
|
||||
#ifdef XSPICE
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ struct TSKtask {
|
|||
unsigned int TSKnoStateRestore:1; /* `.option nostaterestore` disables
|
||||
* the dctran failed-attempt state
|
||||
* restore (CKTstate0 <- CKTstate1) */
|
||||
unsigned int TSKnoOrderGuard:1; /* `.option noorderguard` disables
|
||||
* the dctran non-uniform-history
|
||||
* predictor order guard */
|
||||
unsigned int TSKcurrentSettle:1; /* `.option currentsettle` enables
|
||||
* device-current settling
|
||||
* enforcement in NIconvTest */
|
||||
unsigned int TSKtryToCompact:1; /* flag for LTRA lines */
|
||||
unsigned int TSKbadMos3:1; /* flag for MOS3 models */
|
||||
unsigned int TSKkeepOpInfo:1; /* flag for small signal analyses */
|
||||
|
|
|
|||
|
|
@ -82,8 +82,17 @@ NIconvTest(CKTcircuit *ckt)
|
|||
#ifdef NEWCONV
|
||||
i = CKTconvTest(ckt);
|
||||
/* The individual testers, called by CKTconvTest, set
|
||||
* ckt->CKTnoncon and ckt->CKTtroubleElt appropriately. */
|
||||
if (ckt->CKTnoncon != 0) {
|
||||
* ckt->CKTnoncon and ckt->CKTtroubleElt appropriately.
|
||||
*
|
||||
* Honoring those reports here (upstream trunk 0638aaa16,
|
||||
* "Continue Newton iteration until currents settle") activates a
|
||||
* device-current settling test that had been dead code since
|
||||
* spice3f5. It regresses legacy decks whose devices genuinely
|
||||
* oscillate at tight tolerances yet simulated acceptably for
|
||||
* decades under the solution-only test (e.g. the bundled
|
||||
* 555-timer-2 example at its own RELTOL=1e-4). Enforce only on
|
||||
* `.option currentsettle`; the default matches ngspice-46. */
|
||||
if (ckt->CKTcurrentSettle && ckt->CKTnoncon != 0) {
|
||||
ckt->CKTtroubleNode = 0;
|
||||
return(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ int OSDItrunc(GENmodel *in_model, CKTcircuit *ckt, double *timestep) {
|
|||
* the most recently accepted step so that fast edges are resolved
|
||||
* gradually.
|
||||
*
|
||||
* Was 2.0× originally, tightened to 1.5× for pinb/net_7 oscillation
|
||||
* (commit 143a0805f) and now to 1.2× for foundry_a ULP driver_lv_2v5_tb
|
||||
* Was 2.0× originally, tightened to 1.5× for pinb/net_7 oscillation,
|
||||
* and now to 1.2× for foundry_a ULP driver_lv_2v5_tb
|
||||
* to address residual pinb failure at t ≈ 1.369 µs. At 1.5×, dt
|
||||
* could grow from ~10 ps post-breakpoint to ~5 ns (the user's max
|
||||
* step) in ~15 accepted steps; once Newton had to land a 0.5 V swing
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ CKTdoJob(CKTcircuit* ckt, int reset, TSKtask* task)
|
|||
ckt->CKTosdiStepRejectOff = task->TSKnoOsdiStepReject;
|
||||
ckt->CKTdtClearOff = task->TSKnoDtClear;
|
||||
ckt->CKTstateRestoreOff = task->TSKnoStateRestore;
|
||||
ckt->CKTorderGuardOff = task->TSKnoOrderGuard;
|
||||
ckt->CKTcurrentSettle = task->TSKcurrentSettle;
|
||||
ckt->CKTosdiVlim = task->TSKosdiVlim;
|
||||
ckt->CKTosdiVlimVds = task->TSKosdiVlimVds;
|
||||
ckt->CKTosdiVlimVgs = task->TSKosdiVlimVgs;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ CKTsetOpt(CKTcircuit *ckt, JOB *anal, int opt, IFvalue *val)
|
|||
case OPT_NOSTATERESTORE:
|
||||
task->TSKnoStateRestore = (val->iValue != 0);
|
||||
break;
|
||||
case OPT_NOORDERGUARD:
|
||||
task->TSKnoOrderGuard = (val->iValue != 0);
|
||||
break;
|
||||
case OPT_CURRENTSETTLE:
|
||||
task->TSKcurrentSettle = (val->iValue != 0);
|
||||
break;
|
||||
case OPT_GMIN:
|
||||
task->TSKgmin = val->rValue;
|
||||
break;
|
||||
|
|
@ -304,6 +310,8 @@ static IFparm OPTtbl[] = {
|
|||
{ "noosdistepreject", OPT_NOOSDISTEPREJECT, IF_SET|IF_FLAG, "Disable OSDI axis-3 step rejection (osdiload.c sanitize_jacobian + REJECT_STEP)" },
|
||||
{ "nodtclear", OPT_NODTCLEAR, IF_SET|IF_FLAG, "Disable small-dt CKTnoncon clear (niiter.c); revert to abort-from-spurious-noncon at dt<1ps" },
|
||||
{ "nostaterestore", OPT_NOSTATERESTORE, IF_SET|IF_FLAG, "Disable dctran failed-attempt device-state restore (CKTstate0 <- CKTstate1 on retry)" },
|
||||
{ "noorderguard", OPT_NOORDERGUARD, IF_SET|IF_FLAG, "Disable dctran non-uniform-history predictor order guard (forced order-1 on >10x dt ratio)" },
|
||||
{ "currentsettle", OPT_CURRENTSETTLE, IF_SET|IF_FLAG, "Enable device-current settling enforcement in NIconvTest (trunk 0638aaa16 behaviour; default is ngspice-46 solution-only)" },
|
||||
{ "gmin", OPT_GMIN,IF_SET|IF_REAL,"Minimum conductance" },
|
||||
{ "gshunt", OPT_GSHUNT,IF_SET|IF_REAL,"Shunt conductance" },
|
||||
{ "reltol", OPT_RELTOL,IF_SET|IF_REAL ,"Relative error tolerence"},
|
||||
|
|
|
|||
|
|
@ -710,8 +710,21 @@ resume:
|
|||
*
|
||||
* Threshold of 10× chosen so smooth dt-growth sequences
|
||||
* (e.g. the 1.5× cap, factor 1.5 per step) never trigger
|
||||
* — only genuine breakpoint-induced discontinuities. */
|
||||
if (ckt->CKTorder > 1 &&
|
||||
* — only genuine breakpoint-induced discontinuities.
|
||||
*
|
||||
* OSDI circuits only (CKTosdiPresent), like the NIiter Δv
|
||||
* limiter: the failure mode this guards against was observed
|
||||
* on OSDI/BSIM-BULK drivers, while for native-device decks
|
||||
* the forced order-1 steps inflate LTE at breakpoint-dense
|
||||
* switching (smaller dt), and combined with the axis-4
|
||||
* residual check this walled the bundled 555-timer-2 example
|
||||
* at t=3.27ms (RELTOL=1e-4). Stock predictor behaviour is
|
||||
* restored for non-OSDI circuits.
|
||||
*
|
||||
* Opt-out via `.option noorderguard` (diagnostic: lets a
|
||||
* suspect deck run with the stock always-order-2 predictor). */
|
||||
if (ckt->CKTosdiPresent &&
|
||||
!ckt->CKTorderGuardOff && ckt->CKTorder > 1 &&
|
||||
ckt->CKTdeltaOld[1] > 0.0 && ckt->CKTdeltaOld[2] > 0.0) {
|
||||
double r = ckt->CKTdeltaOld[1] / ckt->CKTdeltaOld[2];
|
||||
if (r > 10.0 || r < 0.1) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue