From 2a246632bbe3bf452c13d2392227a098e47db3dd Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 29 Apr 2026 13:34:22 +0200 Subject: [PATCH] Add instance parameters td anr to the ISRC pwl source, like has been available with voltage source VSRC. --- src/spicelib/devices/isrc/isrc.c | 2 + src/spicelib/devices/isrc/isrcacct.c | 58 +++++++++++++++++++++++++++- src/spicelib/devices/isrc/isrcdefs.h | 13 +++++-- src/spicelib/devices/isrc/isrcload.c | 50 +++++++++++++++++++++++- src/spicelib/devices/isrc/isrcpar.c | 44 +++++++++++++++++++++ 5 files changed, 159 insertions(+), 8 deletions(-) diff --git a/src/spicelib/devices/isrc/isrc.c b/src/spicelib/devices/isrc/isrc.c index 8272357f8..331937717 100644 --- a/src/spicelib/devices/isrc/isrc.c +++ b/src/spicelib/devices/isrc/isrc.c @@ -39,6 +39,8 @@ IFparm ISRCpTable[] = { /* parameters */ OP ("v", ISRC_VOLTS, IF_REAL, "Voltage across the supply"), OP ("p", ISRC_POWER, IF_REAL, "Power supplied by the source"), OP ("current", ISRC_CURRENT, IF_REAL, "Current in DC or Transient mode"), + IP ("r", ISRC_R, IF_REAL, "pwl repeat value"), + IP ("td", ISRC_TD, IF_REAL, "pwl delay value"), IP ("distof1", ISRC_D_F1, IF_REALVEC,"f1 input for distortion"), IP ("distof2", ISRC_D_F2, IF_REALVEC,"f2 input for distortion") }; diff --git a/src/spicelib/devices/isrc/isrcacct.c b/src/spicelib/devices/isrc/isrcacct.c index abf232f01..94ae4ba6e 100644 --- a/src/spicelib/devices/isrc/isrcacct.c +++ b/src/spicelib/devices/isrc/isrcacct.c @@ -183,6 +183,60 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) } break; + case PWL: { + if (ckt->CKTtime >= here->ISRCbreak_time) { + double time, atime, end, period; + int i; + + time = ckt->CKTtime - here->ISRCrdelay; + end = + here->ISRCcoeffs[here->ISRCfunctionOrder - 2]; + if (time > end) { + if (here->ISRCrGiven) { + /* Repeating. */ + + period = end - + here->ISRCcoeffs[here->ISRCrBreakpt]; + time -= + here->ISRCcoeffs[here->ISRCrBreakpt]; + time -= period * floor(time / period); + time += + here->ISRCcoeffs[here->ISRCrBreakpt]; + } + else { + here->ISRCbreak_time = ckt->CKTfinalTime; + break; + } + } + + /* A request for a breakpoint very close + * to the current time will be ignored. + * Adjust so the next corner will be + * selected. + */ + + atime = time + ckt->CKTminBreak; + + for (i = 0; + i < here->ISRCfunctionOrder; + i += 2) { + if (here->ISRCcoeffs[i] > atime) { + here->ISRCbreak_time = + ckt->CKTtime + + here->ISRCcoeffs[i] - time; + error = CKTsetBreak(ckt, + here->ISRCbreak_time); + if (error) + return error; + here->ISRCbreak_time -= ckt->CKTminBreak; + break; + } + } + } + break; + } + +/* case PWL: { int i; if(ckt->CKTtime < *(here->ISRCcoeffs)) { @@ -200,7 +254,7 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) } break; } - +*/ /**** tansient noise routines: INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise rms value, time step, 0 0 @@ -320,7 +374,7 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) } // switch } // if ... else -bkptset: ; +// bkptset: ; } // for } // for diff --git a/src/spicelib/devices/isrc/isrcdefs.h b/src/spicelib/devices/isrc/isrcdefs.h index d6f474fec..c599022c8 100644 --- a/src/spicelib/devices/isrc/isrcdefs.h +++ b/src/spicelib/devices/isrc/isrcdefs.h @@ -32,6 +32,8 @@ typedef struct sISRCinstance { int ISRCfunctionType; /* code number of function type for source */ int ISRCfunctionOrder; /* order of the function for the source */ + int ISRCrBreakpt; /* pwl repeat breakpoint index */ + double ISRCbreak_time; /* time of most-recent breakpoint */ double *ISRCcoeffs; /* pointer to array of coefficients */ double ISRCdcValue; /* DC and TRANSIENT value of source */ @@ -51,6 +53,9 @@ typedef struct sISRCinstance { struct trnoise_state *ISRCtrnoise_state; /* transient noise */ struct trrandom_state *ISRCtrrandom_state; /* transient random source */ + double ISRCr; /* pwl repeat */ + double ISRCrdelay; /* pwl delay period */ + /* needed for outputting results */ double ISRCcurrent; /* current value */ @@ -64,6 +69,7 @@ typedef struct sISRCinstance { unsigned ISRCdGiven :1 ; /* flag to indicate source is a distortion input */ unsigned ISRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */ unsigned ISRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */ + unsigned ISRCrGiven : 1; /* flag to indicate repeating pwl */ } ISRCinstance ; @@ -123,11 +129,10 @@ enum { ISRC_D_F2, ISRC_VOLTS, ISRC_AM, + ISRC_R, + ISRC_TD, ISRC_CURRENT, -}; - -enum { - ISRC_TRNOISE = 25, + ISRC_TRNOISE, ISRC_TRRANDOM, ISRC_EXTERNAL, }; diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index ccf282e17..13a19f68e 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -31,7 +31,7 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) { ISRCmodel *model = (ISRCmodel *) inModel; ISRCinstance *here; - double value; + double value = 0.0; double time; double m; @@ -300,6 +300,51 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) break; case PWL: { + int i; + double end_time, itime; + + time -= here->ISRCrdelay; + if (time <= here->ISRCcoeffs[0]) { + value = here->ISRCcoeffs[1]; + break; + } + + end_time = + here->ISRCcoeffs[here->ISRCfunctionOrder - 2]; + if (time > end_time) { + double period; + + if (here->ISRCrGiven) { + /* Repeating. */ + + period = end_time - + here->ISRCcoeffs[here->ISRCrBreakpt]; + time -= here->ISRCcoeffs[here->ISRCrBreakpt]; + time -= period * floor(time / period); + time += here->ISRCcoeffs[here->ISRCrBreakpt]; + } + else { + value = + here->ISRCcoeffs[here->ISRCfunctionOrder - 1]; + break; + } + } + + for (i = 2; i < here->ISRCfunctionOrder; i += 2) { + itime = here->ISRCcoeffs[i]; + if (itime >= time) { + time -= here->ISRCcoeffs[i - 2]; + time /= here->ISRCcoeffs[i] - + here->ISRCcoeffs[i - 2]; + value = here->ISRCcoeffs[i - 1]; + value += time * + (here->ISRCcoeffs[i + 1] - + here->ISRCcoeffs[i - 1]); + break; + } + } + break; +/* int i; if(time < *(here->ISRCcoeffs)) { value = *(here->ISRCcoeffs + 1) ; @@ -323,6 +368,7 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) } value = *(here->ISRCcoeffs+ here->ISRCfunctionOrder-1) ; break; + */ } /**** tansient noise routines: @@ -396,7 +442,7 @@ INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise } // switch } // else (line 48) -loadDone: +// loadDone: /* gtri - begin - wbk - modify for supply ramping option */ #ifdef XSPICE_EXP diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index f66b3bd03..7f0fc3e84 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -123,6 +123,50 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) break; + case ISRC_TD: + here->ISRCrdelay = value->rValue; + break; + + case ISRC_R: { + double end_time; + /* Parameter r of pwl may now be parameterized: + if r == -1, no repetition done. + if r == 0, repeat forever. + if r == xx, repeat from time xx to last time point given. */ + if (value->rValue < -0.5) { + here->ISRCrGiven = FALSE; + break; + } + + /* buggy input? r is not a repetition coefficient */ + if (!here->ISRCcoeffs || here->ISRCfunctionOrder < 2) { + here->ISRCrGiven = FALSE; + break; + } + + here->ISRCr = value->rValue; + here->ISRCrGiven = TRUE; + + for (i = 0; i < here->ISRCfunctionOrder; i += 2) { + here->ISRCrBreakpt = i; + if (here->ISRCr == *(here->ISRCcoeffs + i)) + break; + } + + end_time = *(here->ISRCcoeffs + here->ISRCfunctionOrder - 2); + if (here->ISRCr >= end_time) { + fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->ISRCr); + return (E_PARMVAL); + } + + if (here->ISRCr != *(here->ISRCcoeffs + here->ISRCrBreakpt)) { + fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source does not match any time point given!\n", here->ISRCr); + return (E_PARMVAL); + } + + break; + } + case ISRC_SFFM: if(value->v.numValue < 2) return(E_BADPARM);