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
|
/* `.option nostaterestore` opt-out of the dctran failed-attempt
|
||||||
* device-state restore (CKTstate0 <- CKTstate1 on timepoint retry). */
|
* device-state restore (CKTstate0 <- CKTstate1 on timepoint retry). */
|
||||||
int CKTstateRestoreOff;
|
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
|
/* Per-iteration count of huge-finite Jacobian entries clipped by
|
||||||
* sanitize_jacobian during CKTload. When > 0, the model evaluation
|
* sanitize_jacobian during CKTload. When > 0, the model evaluation
|
||||||
* is in a numerical regime (e.g. BSIM-BULK near a singular operating
|
* is in a numerical regime (e.g. BSIM-BULK near a singular operating
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,8 @@ enum {
|
||||||
* SPICE3 solution-only behaviour. */
|
* SPICE3 solution-only behaviour. */
|
||||||
OPT_NOSTATERESTORE, /* `.option nostaterestore` opts out of the dctran
|
OPT_NOSTATERESTORE, /* `.option nostaterestore` opts out of the dctran
|
||||||
* failed-attempt device-state restore. */
|
* failed-attempt device-state restore. */
|
||||||
|
OPT_NOORDERGUARD, /* `.option noorderguard` opts out of the dctran
|
||||||
|
* non-uniform-history predictor order guard. */
|
||||||
OPT_EQNS,
|
OPT_EQNS,
|
||||||
OPT_REORDTIME,
|
OPT_REORDTIME,
|
||||||
OPT_METHOD,
|
OPT_METHOD,
|
||||||
|
|
@ -156,6 +158,14 @@ enum {
|
||||||
OPT_NODTCLEAR, /* `.option nodtclear` disables the small-dt
|
OPT_NODTCLEAR, /* `.option nodtclear` disables the small-dt
|
||||||
* CKTnoncon clear in niiter.c. See CKTdtClearOff
|
* CKTnoncon clear in niiter.c. See CKTdtClearOff
|
||||||
* comment in cktdefs.h. */
|
* 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
|
#ifdef XSPICE
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,12 @@ struct TSKtask {
|
||||||
unsigned int TSKnoStateRestore:1; /* `.option nostaterestore` disables
|
unsigned int TSKnoStateRestore:1; /* `.option nostaterestore` disables
|
||||||
* the dctran failed-attempt state
|
* the dctran failed-attempt state
|
||||||
* restore (CKTstate0 <- CKTstate1) */
|
* 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 TSKtryToCompact:1; /* flag for LTRA lines */
|
||||||
unsigned int TSKbadMos3:1; /* flag for MOS3 models */
|
unsigned int TSKbadMos3:1; /* flag for MOS3 models */
|
||||||
unsigned int TSKkeepOpInfo:1; /* flag for small signal analyses */
|
unsigned int TSKkeepOpInfo:1; /* flag for small signal analyses */
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,17 @@ NIconvTest(CKTcircuit *ckt)
|
||||||
#ifdef NEWCONV
|
#ifdef NEWCONV
|
||||||
i = CKTconvTest(ckt);
|
i = CKTconvTest(ckt);
|
||||||
/* The individual testers, called by CKTconvTest, set
|
/* The individual testers, called by CKTconvTest, set
|
||||||
* ckt->CKTnoncon and ckt->CKTtroubleElt appropriately. */
|
* ckt->CKTnoncon and ckt->CKTtroubleElt appropriately.
|
||||||
if (ckt->CKTnoncon != 0) {
|
*
|
||||||
|
* 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;
|
ckt->CKTtroubleNode = 0;
|
||||||
return(1);
|
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
|
* the most recently accepted step so that fast edges are resolved
|
||||||
* gradually.
|
* gradually.
|
||||||
*
|
*
|
||||||
* Was 2.0× originally, tightened to 1.5× for pinb/net_7 oscillation
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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->CKTosdiStepRejectOff = task->TSKnoOsdiStepReject;
|
||||||
ckt->CKTdtClearOff = task->TSKnoDtClear;
|
ckt->CKTdtClearOff = task->TSKnoDtClear;
|
||||||
ckt->CKTstateRestoreOff = task->TSKnoStateRestore;
|
ckt->CKTstateRestoreOff = task->TSKnoStateRestore;
|
||||||
|
ckt->CKTorderGuardOff = task->TSKnoOrderGuard;
|
||||||
|
ckt->CKTcurrentSettle = task->TSKcurrentSettle;
|
||||||
ckt->CKTosdiVlim = task->TSKosdiVlim;
|
ckt->CKTosdiVlim = task->TSKosdiVlim;
|
||||||
ckt->CKTosdiVlimVds = task->TSKosdiVlimVds;
|
ckt->CKTosdiVlimVds = task->TSKosdiVlimVds;
|
||||||
ckt->CKTosdiVlimVgs = task->TSKosdiVlimVgs;
|
ckt->CKTosdiVlimVgs = task->TSKosdiVlimVgs;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,12 @@ CKTsetOpt(CKTcircuit *ckt, JOB *anal, int opt, IFvalue *val)
|
||||||
case OPT_NOSTATERESTORE:
|
case OPT_NOSTATERESTORE:
|
||||||
task->TSKnoStateRestore = (val->iValue != 0);
|
task->TSKnoStateRestore = (val->iValue != 0);
|
||||||
break;
|
break;
|
||||||
|
case OPT_NOORDERGUARD:
|
||||||
|
task->TSKnoOrderGuard = (val->iValue != 0);
|
||||||
|
break;
|
||||||
|
case OPT_CURRENTSETTLE:
|
||||||
|
task->TSKcurrentSettle = (val->iValue != 0);
|
||||||
|
break;
|
||||||
case OPT_GMIN:
|
case OPT_GMIN:
|
||||||
task->TSKgmin = val->rValue;
|
task->TSKgmin = val->rValue;
|
||||||
break;
|
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)" },
|
{ "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" },
|
{ "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)" },
|
{ "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" },
|
{ "gmin", OPT_GMIN,IF_SET|IF_REAL,"Minimum conductance" },
|
||||||
{ "gshunt", OPT_GSHUNT,IF_SET|IF_REAL,"Shunt conductance" },
|
{ "gshunt", OPT_GSHUNT,IF_SET|IF_REAL,"Shunt conductance" },
|
||||||
{ "reltol", OPT_RELTOL,IF_SET|IF_REAL ,"Relative error tolerence"},
|
{ "reltol", OPT_RELTOL,IF_SET|IF_REAL ,"Relative error tolerence"},
|
||||||
|
|
|
||||||
|
|
@ -710,8 +710,21 @@ resume:
|
||||||
*
|
*
|
||||||
* Threshold of 10× chosen so smooth dt-growth sequences
|
* Threshold of 10× chosen so smooth dt-growth sequences
|
||||||
* (e.g. the 1.5× cap, factor 1.5 per step) never trigger
|
* (e.g. the 1.5× cap, factor 1.5 per step) never trigger
|
||||||
* — only genuine breakpoint-induced discontinuities. */
|
* — only genuine breakpoint-induced discontinuities.
|
||||||
if (ckt->CKTorder > 1 &&
|
*
|
||||||
|
* 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) {
|
ckt->CKTdeltaOld[1] > 0.0 && ckt->CKTdeltaOld[2] > 0.0) {
|
||||||
double r = ckt->CKTdeltaOld[1] / ckt->CKTdeltaOld[2];
|
double r = ckt->CKTdeltaOld[1] / ckt->CKTdeltaOld[2];
|
||||||
if (r > 10.0 || r < 0.1) {
|
if (r > 10.0 || r < 0.1) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue