This patch fixes a bug when shared library uses XSPICE:

Don't subtract delta twice, when breakpoint is active
and step is rejected.
https://sourceforge.net/p/ngspice/patches/106/
Thanks to Vyacheslav Shevchuk
This commit is contained in:
Holger Vogt 2023-10-07 17:10:31 +02:00
parent 9944a4869f
commit ecb416b800
1 changed files with 57 additions and 4 deletions

View File

@ -2,6 +2,7 @@
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: 2000 AlansFixes
Modified: 2023 XSPICE breakpoint fix for shared ngspice by Vyacheslav Shevchuk
**********/
/* subroutine to do DC TRANSIENT analysis
@ -106,6 +107,25 @@ DCtran(CKTcircuit *ckt,
double ipc_last_time = 0.0;
double ipc_last_delta = 0.0;
/* gtri - end - wbk - 12/19/90 - Add IPC stuff */
// Fix for sharedsync olddelta: When DCTran processes
// either analog or XSPICE breakpoint, then it subtracts delta from
// ckt->CKTtime. It sends 0 as olddelta after analog breakpoint
// processing. Still, for XSPICE breakpoints it subtracts delta (see code
// 'else if(g_mif_info.breakpoint.current < ckt->CKTtime)' branch) and
// then sends non zero olddelta to sharedsync at the end of the function
// (see chkStep: label). Thus olddelta is subtracted twice. Then
// ckt->CKTtime becomes less than last_accepted_time.
// xspice_breakpoints_processed 0:
// XSPICE models didn't have breakpoints in [last_accepted_time, CKTtime].
// xspice_breakpoints_processed 1:
// convergence criteria are satisfied but XSPICE breakpoint(s) is in the
// time interval [last_accepted_time, CKTtime].
int xspice_breakpoints_processed = 0;
#ifdef SHARED_MODULE
double olddelta_for_shared_sync = 0.0;
#endif // SHARED_MODULE
#endif
#if defined CLUSTER || defined SHARED_MODULE
int redostep;
@ -680,7 +700,7 @@ resume:
} /* end if there are event instances */
/* gtri - end - wbk - Do event solution */
#else
#else /* no XSPICE */
#ifdef CLUSTER
if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) {
@ -697,7 +717,7 @@ resume:
ckt->CKTdelmin, 0, &ckt->CKTstat->STATrejected, 0);
#endif
#endif
#endif /* no XSPICE */
for(i=5; i>=0; i--)
ckt->CKTdeltaOld[i+1] = ckt->CKTdeltaOld[i];
ckt->CKTdeltaOld[0] = ckt->CKTdelta;
@ -722,6 +742,7 @@ resume:
ckt->CKTcurrentAnalysis = DOING_TRAN;
/* gtri - end - wbk - 4/17/91 - Fix Berkeley bug */
xspice_breakpoints_processed = 0;
#endif
olddelta=ckt->CKTdelta;
/* time abort? */
@ -815,6 +836,7 @@ resume:
ckt->CKTtime -= ckt->CKTdelta;
ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime;
g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta;
xspice_breakpoints_processed = 1;
if(firsttime) {
ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITTRAN;
@ -945,8 +967,24 @@ resume:
#ifdef XSPICE
/* gtri - begin - wbk - Do event backup */
if(ckt->evt->counts.num_insts > 0)
if(ckt->evt->counts.num_insts > 0) {
#ifdef SHARED_MODULE
double discard_start_time = ckt->CKTtime + ckt->CKTdelta;
// ngspice in executable mode subtracts olddelta from the time
// before new delta calculation, but it keeps delta in CKTtime and
// postpones subtraction in library mode. Delayed subtraction leads
// to incorrect points dropping because ckt->CKTdelta is almost always
// less than olddelta if there are convergence issues, and EVTbackup
// may drop valid events that need to be processed within
// [last_accepted_time, last_accepted_time + ckt->CKTdelta] range
// after delta adjustment.
if (redostep && xspice_breakpoints_processed == 0)
discard_start_time -= olddelta;
EVTbackup(ckt, discard_start_time);
#else
EVTbackup(ckt, ckt->CKTtime + ckt->CKTdelta);
#endif
}
/* gtri - end - wbk - Do event backup */
#endif
@ -973,10 +1011,25 @@ resume:
function.
*/
chkStep:
#ifdef XSPICE
// There is no need to subtract olddelta from ckt->CKTtime one more time
// if it has been subtracted during XSPICE breakpoint processing.
// olddelta will be reinitialized on
// the new iteration, so it reassigning here should be safe. It can't be
// zeroed during breakpoint processing because it takes part in the
// "timestep too small" check.
olddelta_for_shared_sync = olddelta;
if (xspice_breakpoints_processed)
olddelta_for_shared_sync = 0.0;
if(sharedsync(&ckt->CKTtime, &ckt->CKTdelta, olddelta_for_shared_sync, ckt->CKTfinalTime,
ckt->CKTdelmin, redostep, &ckt->CKTstat->STATrejected, 1) == 0)
goto nextTime;
#else
if(sharedsync(&ckt->CKTtime, &ckt->CKTdelta, olddelta, ckt->CKTfinalTime,
ckt->CKTdelmin, redostep, &ckt->CKTstat->STATrejected, 1) == 0)
goto nextTime;
#endif
#endif // XSPICE
#endif // SHARED_MODULE
}
/* NOTREACHED */