diff --git a/ChangeLog b/ChangeLog index b45cec09c..d632cf2a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-12-17 Holger Vogt + * isrc.c, isrcacct.c, isrcload.c, isrcpar.c, isrcdefs.h: + transient noise in independent current source + 2010-12-15 Dietmar Warning * devices/bsim3soi/b4soild.c: fixed a double consideration of the multiplier m for conductances gm, gds, gmbs diff --git a/src/spicelib/devices/isrc/isrc.c b/src/spicelib/devices/isrc/isrc.c index 3ba2fd2aa..06f6f88a7 100644 --- a/src/spicelib/devices/isrc/isrc.c +++ b/src/spicelib/devices/isrc/isrc.c @@ -21,6 +21,7 @@ IFparm ISRCpTable[] = { /* parameters */ IOP ( "pwl", ISRC_PWL, IF_REALVEC,"Piecewise linear description"), IOP ( "sffm", ISRC_SFFM, IF_REALVEC,"Single freq. FM description"), IOP ( "am", ISRC_AM, IF_REALVEC,"Amplitude modulation description"), + IOP ( "trnoise", ISRC_TRNOISE, IF_REALVEC,"Transient noise descripton"), OPU ( "neg_node",ISRC_NEG_NODE, IF_INTEGER,"Negative node of source"), OPU ( "pos_node",ISRC_POS_NODE, IF_INTEGER,"Positive node of source"), OPU ( "acreal", ISRC_AC_REAL, IF_REAL ,"AC real part"), diff --git a/src/spicelib/devices/isrc/isrcacct.c b/src/spicelib/devices/isrc/isrcacct.c index 3b5699fd3..f2d2698c8 100644 --- a/src/spicelib/devices/isrc/isrcacct.c +++ b/src/spicelib/devices/isrc/isrcacct.c @@ -9,6 +9,12 @@ Author: 1985 Thomas L. Quarles #include "trandefs.h" #include "sperror.h" #include "suffix.h" +#include "missing_math.h" +#include "1-f-code.h" + +extern int fftInit(long M); +extern void fftFree(void); +extern void rffts(float *data, long M, long Rows); int ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) @@ -31,164 +37,200 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) } else { /* use the transient functions */ switch(here->ISRCfunctionType) { - default: { /* no function specified:DC no breakpoints */ - break; - } + default: { /* no function specified:DC no breakpoints */ + break; + } - case PULSE: { + case PULSE: { #define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW) #define TIMETOL 1e-7 - double TD, TR, TF, PW, PER; + double TD, TR, TF, PW, PER; /* gtri - begin - wbk - add PHASE parameter */ #ifdef XSPICE - double PHASE; - double phase; - double deltat; - double basephase; + double PHASE; + double phase; + double deltat; + double basephase; #endif - double time; - double basetime = 0; + double time; + double basetime = 0; - TD = here->ISRCfunctionOrder > 2 - ? here->ISRCcoeffs[2] : 0.0; - TR = here->ISRCfunctionOrder > 3 - && here->ISRCcoeffs[3] != 0.0 - ? here->ISRCcoeffs[3] : ckt->CKTstep; - TF = here->ISRCfunctionOrder > 4 - && here->ISRCcoeffs[4] != 0.0 - ? here->ISRCcoeffs[4] : ckt->CKTstep; - PW = here->ISRCfunctionOrder > 5 - && here->ISRCcoeffs[5] != 0.0 - ? here->ISRCcoeffs[5] : ckt->CKTfinalTime; - PER = here->ISRCfunctionOrder > 6 - && here->ISRCcoeffs[6] != 0.0 - ? here->ISRCcoeffs[6] : ckt->CKTfinalTime; + TD = here->ISRCfunctionOrder > 2 + ? here->ISRCcoeffs[2] : 0.0; + TR = here->ISRCfunctionOrder > 3 + && here->ISRCcoeffs[3] != 0.0 + ? here->ISRCcoeffs[3] : ckt->CKTstep; + TF = here->ISRCfunctionOrder > 4 + && here->ISRCcoeffs[4] != 0.0 + ? here->ISRCcoeffs[4] : ckt->CKTstep; + PW = here->ISRCfunctionOrder > 5 + && here->ISRCcoeffs[5] != 0.0 + ? here->ISRCcoeffs[5] : ckt->CKTfinalTime; + PER = here->ISRCfunctionOrder > 6 + && here->ISRCcoeffs[6] != 0.0 + ? here->ISRCcoeffs[6] : ckt->CKTfinalTime; #ifdef XSPICE - PHASE = here->ISRCfunctionOrder > 8 - ? here->ISRCcoeffs[7] : 0.0; + PHASE = here->ISRCfunctionOrder > 8 + ? here->ISRCcoeffs[7] : 0.0; #endif - /* offset time by delay and limit to zero */ - time = ckt->CKTtime - TD; + /* offset time by delay and limit to zero */ + time = ckt->CKTtime - TD; #ifdef XSPICE - if(time < 0.0) - time = 0.0; + if(time < 0.0) + time = 0.0; #endif #ifdef XSPICE - /* normalize phase to 0 - 2PI */ - phase = PHASE * M_PI / 180.0; - basephase = 2 * M_PI * floor(phase / (2 * M_PI)); - phase -= basephase; + /* normalize phase to 0 - 2PI */ + phase = PHASE * M_PI / 180.0; + basephase = 2 * M_PI * floor(phase / (2 * M_PI)); + phase -= basephase; - /* compute equivalent delta time and add to time */ - deltat = (phase / (2 * M_PI)) * PER; - time += deltat; + /* compute equivalent delta time and add to time */ + deltat = (phase / (2 * M_PI)) * PER; + time += deltat; #endif /* gtri - end - wbk - add PHASE parameter */ - - - - - if(time >= PER) { - /* repeating signal - figure out where we are */ - /* in period */ - basetime = PER * floor(time/PER); - time -= basetime; - } - - if( time <= 0.0 || time >= TR + PW + TF) { - if(ckt->CKTbreak && SAMETIME(time,0.0)) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TR + TD); - if(error) return(error); - } else if(ckt->CKTbreak && SAMETIME(TR+PW+TF,time) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + PER + TD); - if(error) return(error); - } else if (ckt->CKTbreak && (time == -TD) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD); - if(error) return(error); - } else if (ckt->CKTbreak && SAMETIME(PER,time) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD + TR + PER); - if(error) return(error); + if(time >= PER) { + /* repeating signal - figure out where we are */ + /* in period */ + basetime = PER * floor(time/PER); + time -= basetime; } - } else if ( time >= TR && time <= TR + PW) { - if(ckt->CKTbreak && SAMETIME(time,TR) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+TR + PW); - if(error) return(error); - } else if(ckt->CKTbreak && SAMETIME(TR+PW,time) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+TR + PW + TF); - if(error) return(error); - } - } else if (time > 0 && time < TR) { - if(ckt->CKTbreak && SAMETIME(time,0) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+TR); - if(error) return(error); - } else if(ckt->CKTbreak && SAMETIME(time,TR)) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+TR + PW); - if(error) return(error); - } - } else { /* time > TR + PW && < TR + PW + TF */ - if(ckt->CKTbreak && SAMETIME(time,TR+PW) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+TR + PW +TF); - if(error) return(error); - } else if(ckt->CKTbreak && SAMETIME(time,TR+PW+TF) ) { - /* set next breakpoint */ - error = CKTsetBreak(ckt,basetime + TD+PER); - if(error) return(error); - } - } - } - break; - case SINE: { - /* no breakpoints (yet) */ - } - break; - case EXP: { - /* no breakpoints (yet) */ - } - break; - case SFFM:{ - /* no breakpoints (yet) */ - } - break; - case AM:{ - /* no breakpoints (yet) */ - } - break; - case PWL: { - int i; - if(ckt->CKTtime < *(here->ISRCcoeffs)) { - if(ckt->CKTbreak) { - error = CKTsetBreak(ckt,*(here->ISRCcoeffs)); - break; - } - } - for(i=0;i<(here->ISRCfunctionOrder/2)-1;i++) { - if((*(here->ISRCcoeffs+2*i)==ckt->CKTtime)) { - if(ckt->CKTbreak) { - error = CKTsetBreak(ckt, - *(here->ISRCcoeffs+2*i+2)); + if( time <= 0.0 || time >= TR + PW + TF) { + if(ckt->CKTbreak && SAMETIME(time,0.0)) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TR + TD); + if(error) return(error); + } else if(ckt->CKTbreak && SAMETIME(TR+PW+TF,time) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + PER + TD); + if(error) return(error); + } else if (ckt->CKTbreak && (time == -TD) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD); + if(error) return(error); + } else if (ckt->CKTbreak && SAMETIME(PER,time) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD + TR + PER); if(error) return(error); } - goto bkptset; - } + } else if ( time >= TR && time <= TR + PW) { + if(ckt->CKTbreak && SAMETIME(time,TR) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+TR + PW); + if(error) return(error); + } else if(ckt->CKTbreak && SAMETIME(TR+PW,time) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+TR + PW + TF); + if(error) return(error); + } + } else if (time > 0 && time < TR) { + if(ckt->CKTbreak && SAMETIME(time,0) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+TR); + if(error) return(error); + } else if(ckt->CKTbreak && SAMETIME(time,TR)) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+TR + PW); + if(error) return(error); + } + } else { /* time > TR + PW && < TR + PW + TF */ + if(ckt->CKTbreak && SAMETIME(time,TR+PW) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+TR + PW +TF); + if(error) return(error); + } else if(ckt->CKTbreak && SAMETIME(time,TR+PW+TF) ) { + /* set next breakpoint */ + error = CKTsetBreak(ckt,basetime + TD+PER); + if(error) return(error); + } + } } break; - } + + case SINE: { + /* no breakpoints (yet) */ + } + break; + case EXP: { + /* no breakpoints (yet) */ + } + break; + case SFFM:{ + /* no breakpoints (yet) */ + } + break; + case AM:{ + /* no breakpoints (yet) */ + } + break; + case PWL: { + int i; + if(ckt->CKTtime < *(here->ISRCcoeffs)) { + if(ckt->CKTbreak) { + error = CKTsetBreak(ckt,*(here->ISRCcoeffs)); + break; + } + } + for(i=0;i<(here->ISRCfunctionOrder/2)-1;i++) { + if((*(here->ISRCcoeffs+2*i)==ckt->CKTtime)) { + if(ckt->CKTbreak) { + error = CKTsetBreak(ckt, + *(here->ISRCcoeffs+2*i+2)); + if(error) return(error); + } + goto bkptset; + } + } + 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 +INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise + 0, time step, exponent < 2, rms value +*/ + case TRNOISE: { + + struct trnoise_state *state = here -> ISRCtrnoise_state; + double TS = state -> TS; + + if (TS == 0.0) // no further breakpoint if value not given + break; + + /* FIXME, dont' want this here, over to aof_get or somesuch */ + if (ckt->CKTtime == 0.0) { + printf("VSRC: free fft tables\n"); + fftFree(); + } + + if(ckt->CKTbreak) { + + int n = (int) floor(ckt->CKTtime / TS + 0.5); + volatile double nearest = n * TS; + + if(AlmostEqualUlps(nearest, ckt->CKTtime, 3)) { + /* carefull calculate `next' + * make sure it is really identical + * with the next calculated `nearest' value + */ + volatile double next = (n+1) * TS; + error = CKTsetBreak(ckt, next); + if(error) + return(error); + } + } + } + break; + } } bkptset: ; diff --git a/src/spicelib/devices/isrc/isrcdefs.h b/src/spicelib/devices/isrc/isrcdefs.h index ebfd8583f..459eae473 100644 --- a/src/spicelib/devices/isrc/isrcdefs.h +++ b/src/spicelib/devices/isrc/isrcdefs.h @@ -42,6 +42,8 @@ typedef struct sISRCinstance { double ISRCdF1phase; /* distortion f1 phase */ double ISRCdF2phase; /* distortion f2 phase */ + struct trnoise_state *ISRCtrnoise_state; /* transient noise */ + /* gtri - begin - add member to hold current source value */ #ifdef XSPICE /* needed for outputting results */ @@ -82,6 +84,7 @@ typedef struct sISRCmodel { /* model structure for a resistor */ #define SFFM 4 #define PWL 5 #define AM 6 +#define TRNOISE 7 #endif /*PULSE*/ /* device parameters */ @@ -113,7 +116,7 @@ typedef struct sISRCmodel { /* model structure for a resistor */ #define ISRC_CURRENT 22 #endif /* gtri - end - add define for current source value */ - +#define ISRC_TRNOISE 25 /* model parameters */ /* device questions */ diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index 92125143f..e9a935c92 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -11,6 +11,7 @@ $Id$ #include "trandefs.h" #include "sperror.h" #include "suffix.h" +#include "1-f-code.h" #ifdef XSPICE_EXP #include "cmproto.h" @@ -33,7 +34,7 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = model->ISRCinstances; here != NULL ; here=here->ISRCnextInstance) { - if (here->ISRCowner != ARCHme) continue; + if (here->ISRCowner != ARCHme) continue; if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->ISRCdcGiven ) { @@ -53,269 +54,303 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) /* use transient function */ switch(here->ISRCfunctionType) { - case PULSE: { - double V1, V2, TD, TR, TF, PW, PER; - double basetime = 0; + case PULSE: { + double V1, V2, TD, TR, TF, PW, PER; + double basetime = 0; #ifdef XSPICE - double PHASE; - double phase; - double deltat; - double basephase; + double PHASE; + double phase; + double deltat; + double basephase; #endif - V1 = here->ISRCcoeffs[0]; - V2 = here->ISRCcoeffs[1]; - TD = here->ISRCfunctionOrder > 2 - ? here->ISRCcoeffs[2] : 0.0; - TR = here->ISRCfunctionOrder > 3 - && here->ISRCcoeffs[3] != 0.0 - ? here->ISRCcoeffs[3] : ckt->CKTstep; - TF = here->ISRCfunctionOrder > 4 - && here->ISRCcoeffs[4] != 0.0 - ? here->ISRCcoeffs[4] : ckt->CKTstep; - PW = here->ISRCfunctionOrder > 5 - && here->ISRCcoeffs[5] != 0.0 - ? here->ISRCcoeffs[5] : ckt->CKTfinalTime; - PER = here->ISRCfunctionOrder > 6 - && here->ISRCcoeffs[6] != 0.0 - ? here->ISRCcoeffs[6] : ckt->CKTfinalTime; + V1 = here->ISRCcoeffs[0]; + V2 = here->ISRCcoeffs[1]; + TD = here->ISRCfunctionOrder > 2 + ? here->ISRCcoeffs[2] : 0.0; + TR = here->ISRCfunctionOrder > 3 + && here->ISRCcoeffs[3] != 0.0 + ? here->ISRCcoeffs[3] : ckt->CKTstep; + TF = here->ISRCfunctionOrder > 4 + && here->ISRCcoeffs[4] != 0.0 + ? here->ISRCcoeffs[4] : ckt->CKTstep; + PW = here->ISRCfunctionOrder > 5 + && here->ISRCcoeffs[5] != 0.0 + ? here->ISRCcoeffs[5] : ckt->CKTfinalTime; + PER = here->ISRCfunctionOrder > 6 + && here->ISRCcoeffs[6] != 0.0 + ? here->ISRCcoeffs[6] : ckt->CKTfinalTime; #ifdef XSPICE /* gtri - begin - wbk - add PHASE parameter */ - PHASE = here->ISRCfunctionOrder > 7 - ? here->ISRCcoeffs[7] : 0.0; + PHASE = here->ISRCfunctionOrder > 7 + ? here->ISRCcoeffs[7] : 0.0; /* normalize phase to 0 - 2PI */ - phase = PHASE * M_PI / 180.0; - basephase = 2 * M_PI * floor(phase / (2 * M_PI)); - phase -= basephase; + phase = PHASE * M_PI / 180.0; + basephase = 2 * M_PI * floor(phase / (2 * M_PI)); + phase -= basephase; - /* compute equivalent delta time and add to time */ - deltat = (phase / (2 * M_PI)) * PER; - time += deltat; + /* compute equivalent delta time and add to time */ + deltat = (phase / (2 * M_PI)) * PER; + time += deltat; /* gtri - end - wbk - add PHASE parameter */ #endif - time -= TD; - - if(time > PER) { - /* repeating signal - figure out where we are */ - /* in period */ - basetime = PER * floor(time/PER); - time -= basetime; + time -= TD; + + if(time > PER) { + /* repeating signal - figure out where we are */ + /* in period */ + basetime = PER * floor(time/PER); + time -= basetime; + } + if( time <= 0 || time >= TR + PW + TF) { + value = V1; + } else if ( time >= TR && time <= TR + PW) { + value = V2; + } else if (time > 0 && time < TR) { + value = V1 + (V2 - V1) * (time) / TR; + } else { /* time > TR + PW && < TR + PW + TF */ + value = V2 + (V1 - V2) * (time - (TR + PW)) / TF; + } } - if( time <= 0 || time >= TR + PW + TF) { - value = V1; - } else if ( time >= TR && time <= TR + PW) { - value = V2; - } else if (time > 0 && time < TR) { - value = V1 + (V2 - V1) * (time) / TR; - } else { /* time > TR + PW && < TR + PW + TF */ - value = V2 + (V1 - V2) * (time - (TR + PW)) / TF; - } - } - break; + break; - case SINE: { + case SINE: { - double VO, VA, FREQ, TD, THETA; + double VO, VA, FREQ, TD, THETA; /* gtri - begin - wbk - add PHASE parameter */ #ifdef XSPICE - double PHASE; - double phase; + double PHASE; + double phase; - PHASE = here->ISRCfunctionOrder > 5 - ? here->ISRCcoeffs[5] : 0.0; + PHASE = here->ISRCfunctionOrder > 5 + ? here->ISRCcoeffs[5] : 0.0; - /* compute phase in radians */ - phase = PHASE * M_PI / 180.0; + /* compute phase in radians */ + phase = PHASE * M_PI / 180.0; #endif - VO = here->ISRCcoeffs[0]; - VA = here->ISRCcoeffs[1]; - FREQ = here->ISRCfunctionOrder > 2 - && here->ISRCcoeffs[2] != 0.0 - ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); - TD = here->ISRCfunctionOrder > 3 - ? here->ISRCcoeffs[3] : 0.0; - THETA = here->ISRCfunctionOrder > 4 - ? here->ISRCcoeffs[4] : 0.0; + VO = here->ISRCcoeffs[0]; + VA = here->ISRCcoeffs[1]; + FREQ = here->ISRCfunctionOrder > 2 + && here->ISRCcoeffs[2] != 0.0 + ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); + TD = here->ISRCfunctionOrder > 3 + ? here->ISRCcoeffs[3] : 0.0; + THETA = here->ISRCfunctionOrder > 4 + ? here->ISRCcoeffs[4] : 0.0; - time -= TD; - if (time <= 0) { + time -= TD; + if (time <= 0) { #ifdef XSPICE - value = VO + VA * sin(phase); - } else { - value = VO + VA * sin(FREQ*time * 2.0 * M_PI + phase) * - exp(-time*THETA); + value = VO + VA * sin(phase); + } else { + value = VO + VA * sin(FREQ*time * 2.0 * M_PI + phase) * + exp(-time*THETA); #else - value = VO; - } else { - value = VO + VA * sin(FREQ*time * 2.0 * M_PI) * - exp(-time*THETA); + value = VO; + } else { + value = VO + VA * sin(FREQ*time * 2.0 * M_PI) * + exp(-time*THETA); #endif /* gtri - end - wbk - add PHASE parameter */ + } } - } - break; - case EXP: { - double V1, V2, TD1, TD2, TAU1, TAU2; + break; + + case EXP: { + double V1, V2, TD1, TD2, TAU1, TAU2; - V1 = here->ISRCcoeffs[0]; - V2 = here->ISRCcoeffs[1]; - TD1 = here->ISRCfunctionOrder > 2 - && here->ISRCcoeffs[2] != 0.0 - ? here->ISRCcoeffs[2] : ckt->CKTstep; - TAU1 = here->ISRCfunctionOrder > 3 - && here->ISRCcoeffs[3] != 0.0 - ? here->ISRCcoeffs[3] : ckt->CKTstep; - TD2 = here->ISRCfunctionOrder > 4 - && here->ISRCcoeffs[4] != 0.0 - ? here->ISRCcoeffs[4] : TD1 + ckt->CKTstep; - TAU2 = here->ISRCfunctionOrder > 5 - && here->ISRCcoeffs[5] - ? here->ISRCcoeffs[5] : ckt->CKTstep; + V1 = here->ISRCcoeffs[0]; + V2 = here->ISRCcoeffs[1]; + TD1 = here->ISRCfunctionOrder > 2 + && here->ISRCcoeffs[2] != 0.0 + ? here->ISRCcoeffs[2] : ckt->CKTstep; + TAU1 = here->ISRCfunctionOrder > 3 + && here->ISRCcoeffs[3] != 0.0 + ? here->ISRCcoeffs[3] : ckt->CKTstep; + TD2 = here->ISRCfunctionOrder > 4 + && here->ISRCcoeffs[4] != 0.0 + ? here->ISRCcoeffs[4] : TD1 + ckt->CKTstep; + TAU2 = here->ISRCfunctionOrder > 5 + && here->ISRCcoeffs[5] + ? here->ISRCcoeffs[5] : ckt->CKTstep; - if(time <= TD1) { - value = V1; - } else if (time <= TD2) { - value = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1)); - } else { - value = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1)) + - (V1-V2)*(1-exp(-(time-TD2)/TAU2)) ; + if(time <= TD1) { + value = V1; + } else if (time <= TD2) { + value = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1)); + } else { + value = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1)) + + (V1-V2)*(1-exp(-(time-TD2)/TAU2)) ; + } } - } - break; - case SFFM:{ + break; + + case SFFM:{ - double VO, VA, FC, MDI, FS; + double VO, VA, FC, MDI, FS; /* gtri - begin - wbk - add PHASE parameters */ #ifdef XSPICE - double PHASEC, PHASES; - double phasec; - double phases; + double PHASEC, PHASES; + double phasec; + double phases; - PHASEC = here->ISRCfunctionOrder > 5 - ? here->ISRCcoeffs[5] : 0.0; - PHASES = here->ISRCfunctionOrder > 6 - ? here->ISRCcoeffs[6] : 0.0; + PHASEC = here->ISRCfunctionOrder > 5 + ? here->ISRCcoeffs[5] : 0.0; + PHASES = here->ISRCfunctionOrder > 6 + ? here->ISRCcoeffs[6] : 0.0; - /* compute phases in radians */ - phasec = PHASEC * M_PI / 180.0; - phases = PHASES * M_PI / 180.0; + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0; + phases = PHASES * M_PI / 180.0; #endif - VO = here->ISRCcoeffs[0]; - VA = here->ISRCcoeffs[1]; - FC = here->ISRCfunctionOrder > 2 - && here->ISRCcoeffs[2] - ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); - MDI = here->ISRCfunctionOrder > 3 - ? here->ISRCcoeffs[3] : 0.0; - FS = here->ISRCfunctionOrder > 4 - && here->ISRCcoeffs[4] - ? here->ISRCcoeffs[4] : (1/ckt->CKTfinalTime); + VO = here->ISRCcoeffs[0]; + VA = here->ISRCcoeffs[1]; + FC = here->ISRCfunctionOrder > 2 + && here->ISRCcoeffs[2] + ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); + MDI = here->ISRCfunctionOrder > 3 + ? here->ISRCcoeffs[3] : 0.0; + FS = here->ISRCfunctionOrder > 4 + && here->ISRCcoeffs[4] + ? here->ISRCcoeffs[4] : (1/ckt->CKTfinalTime); #ifdef XSPICE /* compute waveform value */ - value = VO + VA * - sin((2.0 * M_PI * FC * time + phasec) + - MDI * sin(2.0 * M_PI * FS * time + phases)); + value = VO + VA * + sin((2.0 * M_PI * FC * time + phasec) + + MDI * sin(2.0 * M_PI * FS * time + phases)); #else /* XSPICE */ - value = VO + VA * - sin((2.0 * M_PI * FC * time) + - MDI * sin(2.0 * M_PI * FS * time)); + value = VO + VA * + sin((2.0 * M_PI * FC * time) + + MDI * sin(2.0 * M_PI * FS * time)); #endif /* XSPICE */ /* gtri - end - wbk - add PHASE parameters */ - } - break; - case AM:{ + } + break; + + case AM:{ - double VA, FC, MF, VO, TD; + double VA, FC, MF, VO, TD; /* gtri - begin - wbk - add PHASE parameters */ #ifdef XSPICE - double PHASEC, PHASES; - double phasec; - double phases; + double PHASEC, PHASES; + double phasec; + double phases; - PHASEC = here->ISRCfunctionOrder > 5 - ? here->ISRCcoeffs[5] : 0.0; - PHASES = here->ISRCfunctionOrder > 6 - ? here->ISRCcoeffs[6] : 0.0; + PHASEC = here->ISRCfunctionOrder > 5 + ? here->ISRCcoeffs[5] : 0.0; + PHASES = here->ISRCfunctionOrder > 6 + ? here->ISRCcoeffs[6] : 0.0; - /* compute phases in radians */ - phasec = PHASEC * M_PI / 180.0; - phases = PHASES * M_PI / 180.0; + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0; + phases = PHASES * M_PI / 180.0; #endif - VA = here->ISRCcoeffs[0]; - VO = here->ISRCcoeffs[1]; - MF = here->ISRCfunctionOrder > 2 - && here->ISRCcoeffs[2] - ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); - FC = here->ISRCfunctionOrder > 3 - ? here->ISRCcoeffs[3] : 0.0; - TD = here->ISRCfunctionOrder > 4 - && here->ISRCcoeffs[4] - ? here->ISRCcoeffs[4] : 0.0; + VA = here->ISRCcoeffs[0]; + VO = here->ISRCcoeffs[1]; + MF = here->ISRCfunctionOrder > 2 + && here->ISRCcoeffs[2] + ? here->ISRCcoeffs[2] : (1/ckt->CKTfinalTime); + FC = here->ISRCfunctionOrder > 3 + ? here->ISRCcoeffs[3] : 0.0; + TD = here->ISRCfunctionOrder > 4 + && here->ISRCcoeffs[4] + ? here->ISRCcoeffs[4] : 0.0; - time -= TD; - if (time <= 0) { - value = 0; - } else { + time -= TD; + if (time <= 0) { + value = 0; + } else { #ifdef XSPICE /* compute waveform value */ - value = VA * (VO + sin(2.0 * M_PI * MF * time + phases )) * - sin(2 * M_PI * FC * time + phases); + value = VA * (VO + sin(2.0 * M_PI * MF * time + phases )) * + sin(2 * M_PI * FC * time + phases); #else /* XSPICE */ - value = VA * (VO + sin(2.0 * M_PI * MF * time)) * - sin(2 * M_PI * FC * time); + value = VA * (VO + sin(2.0 * M_PI * MF * time)) * + sin(2 * M_PI * FC * time); #endif - } + } /* gtri - end - wbk - add PHASE parameters */ - } - break; - default: -#ifdef XSPICE_EXP - value = here->ISRCdcValue; -#else - value = here->ISRCdcValue * ckt->CKTsrcFact; -#endif + } break; - case PWL: { - int i; - if(time< *(here->ISRCcoeffs)) { - value = *(here->ISRCcoeffs + 1) ; + + default: +#ifdef XSPICE_EXP + value = here->ISRCdcValue; +#else + value = here->ISRCdcValue * ckt->CKTsrcFact; +#endif + break; + + case PWL: { + int i; + if(time< *(here->ISRCcoeffs)) { + value = *(here->ISRCcoeffs + 1) ; + break; + } + for(i=0;i<=(here->ISRCfunctionOrder/2)-1;i++) { + if((*(here->ISRCcoeffs+2*i)==time)) { + value = *(here->ISRCcoeffs+2*i+1); + goto loadDone; + } + if((*(here->ISRCcoeffs+2*i)ISRCcoeffs+2*(i+1)) >time)) { + value = *(here->ISRCcoeffs+2*i+1) + + (((time-*(here->ISRCcoeffs+2*i))/ + (*(here->ISRCcoeffs+2*(i+1)) - + *(here->ISRCcoeffs+2*i))) * + (*(here->ISRCcoeffs+2*i+3) - + *(here->ISRCcoeffs+2*i+1))); + goto loadDone; + } + } + value = *(here->ISRCcoeffs+ here->ISRCfunctionOrder-1) ; break; } - for(i=0;i<=(here->ISRCfunctionOrder/2)-1;i++) { - if((*(here->ISRCcoeffs+2*i)==time)) { - value = *(here->ISRCcoeffs+2*i+1); - goto loadDone; + +/**** tansient noise routines: +INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise + rms value, time step, 0 0 +INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise + 0, time step, exponent < 2, rms value +*/ + case TRNOISE: { + + struct trnoise_state *state = here -> ISRCtrnoise_state; + + double TS = state -> TS; + + if(TS == 0.0) { + value = 0.0; + } else { + size_t n1 = (size_t) floor(time / TS); + + double V1 = trnoise_state_get(state, ckt, n1); + double V2 = trnoise_state_get(state, ckt, n1+1); + + value = V1 + (V2 - V1) * (time / TS - n1); } - if((*(here->ISRCcoeffs+2*i)ISRCcoeffs+2*(i+1)) >time)) { - value = *(here->ISRCcoeffs+2*i+1) + - (((time-*(here->ISRCcoeffs+2*i))/ - (*(here->ISRCcoeffs+2*(i+1)) - - *(here->ISRCcoeffs+2*i))) * - (*(here->ISRCcoeffs+2*i+3) - - *(here->ISRCcoeffs+2*i+1))); - goto loadDone; - } - } - value = *(here->ISRCcoeffs+ here->ISRCfunctionOrder-1) ; - break; - } - } - } + + if(here -> ISRCdcGiven) + value += here->ISRCdcValue; + } // case + break; + + } // switch + } // else (line 48) loadDone: /* gtri - begin - wbk - modify for supply ramping option */ #ifdef XSPICE_EXP - value *= ckt->CKTsrcFact; + value *= ckt->CKTsrcFact; value *= cm_analog_ramp_factor(); #else @@ -333,7 +368,6 @@ loadDone: here->ISRCcurrent = value; /* gtri - end - wbk - record value so it can be output if requested */ #endif - } } return(OK); diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 17d26bcd2..d63e66c1d 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -11,14 +11,14 @@ Modified: 2000 AlansFixes #include "isrcdefs.h" #include "sperror.h" #include "suffix.h" +#include "1-f-code.h" /* ARGSUSED */ int ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) { - -int i; + int i; ISRCinstance *here = (ISRCinstance*)inst; NG_IGNORE(select); @@ -150,6 +150,32 @@ int i; return(E_BADPARM); } break; + + case ISRC_TRNOISE: { + double NA, TS; + double NALPHA = 0.0; + double NAMP = 0.0; + + here->ISRCfunctionType = TRNOISE; + here->ISRCfuncTGiven = TRUE; + here->ISRCcoeffs = value->v.vec.rVec; + here->ISRCfunctionOrder = value->v.numValue; + here->ISRCcoeffsGiven = TRUE; + + NA = here->ISRCcoeffs[0]; // input is rms value + TS = here->ISRCcoeffs[1]; // time step + + if (here->ISRCfunctionOrder > 2) + NALPHA = here->ISRCcoeffs[2]; + + if (here->ISRCfunctionOrder > 3 && NALPHA != 0.0) + NAMP = here->ISRCcoeffs[3]; + + here->ISRCtrnoise_state = + trnoise_state_init(NA, TS, NALPHA, NAMP); + } + break; + default: return(E_BADPARM); }