From 508fad0f55dcda3545305d6582c367ef7dca06ac Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 10 Oct 2023 21:44:03 +0100 Subject: [PATCH] In dctran.c, call EVTcall_hybrids() (which then calls a subset of code model instances) only when the current timestep was successful. That is efficient and means that code models may rely on such calls, for example a co-simulator may safely advance to the end of the timestep. The function cm_irreversible() that is mentioned in a comment will be added in a later commit. --- src/spicelib/analysis/dctran.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index 3a913cefc..e7da2097c 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -787,14 +787,6 @@ resume: converged = NIiter(ckt,ckt->CKTtranMaxIter); -#ifdef XSPICE - if(ckt->evt->counts.num_insts > 0) { - g_mif_info.circuit.evt_step = ckt->CKTtime; - EVTcall_hybrids(ckt); - } -/* gtri - end - wbk - Call all hybrids */ - -#endif ckt->CKTstat->STATtimePts ++; ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITPRED; if(firsttime) { @@ -830,8 +822,10 @@ resume: #ifdef XSPICE /* gtri - begin - wbk - Add Breakpoint stuff */ - /* Force backup if temporary breakpoint is < current time */ } else if(g_mif_info.breakpoint.current < ckt->CKTtime) { + /* Force backup if temporary breakpoint is < current time */ + + past_breakpoint: ckt->CKTsaveDelta = ckt->CKTdelta; ckt->CKTtime -= ckt->CKTdelta; ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime; @@ -879,6 +873,27 @@ resume: return(error); } if (newdelta > .9 * ckt->CKTdelta) { +#if defined(XSPICE) + /* The timestep has succeeded. XSPICE instances with + * both analog and event ports ("hybrids") and others + * that have called cm_irreversible() receive an EVENT + * call here that allows them to capture their final + * port values and advance co-simulations. As this is an EVENT + * call, they are not expected to do any integrations, + * so there is no need for a further convergence test. + */ + + if (ckt->evt->counts.num_hybrids > 0) { + g_mif_info.circuit.evt_step = ckt->CKTtime; + EVTcall_hybrids(ckt); + if (g_mif_info.breakpoint.current < ckt->CKTtime) { + /* A hybrid requested a breakpoint in the past. */ + + goto past_breakpoint; + } + } +#endif + if ((ckt->CKTorder == 1) && (ckt->CKTmaxOrder > 1)) { /* don't rise the order for backward Euler */ newdelta = ckt->CKTdelta; ckt->CKTorder = 2; @@ -893,6 +908,7 @@ resume: } /* time point OK - 630 */ ckt->CKTdelta = newdelta; + #ifdef NDEV if (!ft_norefprint) { /* show a time process indicator, by Gong Ding, gdiso@ustc.edu */