diff --git a/ChangeLog b/ChangeLog index d632cf2a7..8177c890b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-12-18 Holger Vogt + * rnorrexp.c, randnumb.c, 1-f-code.c, main.c, + fteext.h, 1-f-code.h, + isrcacct.c, isrcload.c, isrcpar.c, + vsrcacct.c, vsrcload.c, vsrcpar.c, + maths/misc/makefile.am, + visualc/vngspice.vcproj, vngspice.sln: + Random telegraph noise added to independent voltage and current sources + 2010-12-17 Holger Vogt * isrc.c, isrcacct.c, isrcload.c, isrcpar.c, isrcdefs.h: transient noise in independent current source diff --git a/src/frontend/trannoise/1-f-code.c b/src/frontend/trannoise/1-f-code.c index ce0257f90..c6a4f155e 100644 --- a/src/frontend/trannoise/1-f-code.c +++ b/src/frontend/trannoise/1-f-code.c @@ -20,6 +20,7 @@ #include "fftext.h" #include "wallace.h" +extern double exprand(double); void f_alpha(int n_pts, int n_exp, float X[], float Q_d, float alpha) @@ -72,7 +73,8 @@ trnoise_state_gen(struct trnoise_state *this, CKTcircuit *ckt) if(this->top == 0) { if(cp_getvar("notrnoise", CP_BOOL, NULL)) - this -> NA = this -> TS = this -> NALPHA = this -> NAMP = 0.0; + this -> NA = this -> TS = this -> NALPHA = this -> NAMP = + this -> RTSAM = this -> RTSCAPT = this -> RTSEMT = 0.0; if((this->NALPHA > 0.0) && (this->NAMP > 0.0)) { @@ -148,7 +150,7 @@ trnoise_state_gen(struct trnoise_state *this, CKTcircuit *ckt) struct trnoise_state * -trnoise_state_init(double NA, double TS, double NALPHA, double NAMP) +trnoise_state_init(double NA, double TS, double NALPHA, double NAMP, double RTSAM, double RTSCAPT, double RTSEMT) { struct trnoise_state *this = TMALLOC(struct trnoise_state, 1); @@ -156,7 +158,13 @@ trnoise_state_init(double NA, double TS, double NALPHA, double NAMP) this->TS = TS; this->NALPHA = NALPHA; this->NAMP = NAMP; - + this->RTSAM = RTSAM; + this->RTSCAPT = RTSCAPT; + this->RTSEMT = RTSEMT; + if (RTSAM > 0) { + this->RTScapTime = exprand(RTSCAPT); + this->RTSemTime = this->RTScapTime + exprand(RTSEMT); + } this -> top = 0; this -> oneof = NULL; diff --git a/src/include/1-f-code.h b/src/include/1-f-code.h index 04a30dfff..39ec28443 100644 --- a/src/include/1-f-code.h +++ b/src/include/1-f-code.h @@ -13,14 +13,17 @@ struct trnoise_state double points[TRNOISE_STATE_MEM_LEN]; size_t top; - double NA, TS, NAMP, NALPHA; + double NA, TS, NAMP, NALPHA, RTSAM, RTSCAPT, RTSEMT; float *oneof; size_t oneof_length; + + double RTScapTime, RTSemTime; + bool RTS; }; -struct trnoise_state *trnoise_state_init(double NA, double TS, double NALPHA, double NAMP); +struct trnoise_state *trnoise_state_init(double NA, double TS, double NALPHA, double NAMP, double RTSAM, double RTSCAPT, double RTSEMT); void trnoise_state_gen(struct trnoise_state *this, CKTcircuit *ckt); void trnoise_state_free(struct trnoise_state *this); diff --git a/src/include/fteext.h b/src/include/fteext.h index 7ff288ade..564b2f1d8 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -231,6 +231,9 @@ extern bool check_autostop(char *what); /* randnumb.c */ extern void TausSeed(void); +/* rnorrexp.c */ +extern void zigset(unsigned long jsrseed); + /* resource.c */ extern void ft_ckspace(void); diff --git a/src/main.c b/src/main.c index a096cc877..15463a521 100644 --- a/src/main.c +++ b/src/main.c @@ -848,7 +848,8 @@ main(int argc, char **argv) } cp_program = ft_sim->simulator; - srand(getpid()); //srandom(getpid()); + srand(getpid()); + zigset(getpid()); TausSeed(); /* --- Process command line options --- */ diff --git a/src/maths/misc/Makefile.am b/src/maths/misc/Makefile.am index b5ff770fc..588669247 100644 --- a/src/maths/misc/Makefile.am +++ b/src/maths/misc/Makefile.am @@ -15,7 +15,8 @@ libmathmisc_la_SOURCES = \ scalb.c \ norm.h \ norm.c \ - randnumb.c + randnumb.c \ + rnorrexp.c EXTRA_DIST = test_accuracy.c test_erfc.c diff --git a/src/maths/misc/randnumb.c b/src/maths/misc/randnumb.c index 6b4dd62c1..991ac1f00 100644 --- a/src/maths/misc/randnumb.c +++ b/src/maths/misc/randnumb.c @@ -84,6 +84,7 @@ void checkseed(void) if (cp_getvar("rndseed", CP_NUM, &newseed)) { if ((newseed > 0) && (oldseed != newseed)) { srand(newseed); //srandom(newseed); + zigset(newseed); TausSeed(); oldseed = newseed; printf("Seed value for random number generator is set to %d\n", newseed); diff --git a/src/maths/misc/rnorrexp.c b/src/maths/misc/rnorrexp.c new file mode 100644 index 000000000..0d7dd56e6 --- /dev/null +++ b/src/maths/misc/rnorrexp.c @@ -0,0 +1,133 @@ +/* The ziggurat method for RNOR and REXP +Combine the code below with the main program in which you want +normal or exponential variates. Then use of RNOR in any expression +will provide a standard normal variate with mean zero, variance 1, +while use of REXP in any expression will provide an exponential variate +with density exp(-x),x>0. +Before using RNOR or REXP in your main, insert a command such as +zigset(86947731 ); +with your own choice of seed value>0, rather than 86947731. +(If you do not invoke zigset(...) you will get all zeros for RNOR and REXP.) +For details of the method, see Marsaglia and Tsang, "The ziggurat method +for generating random variables", Journ. Statistical Software. + +http://www.jstatsoft.org/v05/i08/supp/1 +download 2010-12-18 +*/ + +#include +static unsigned long jz,jsr=123456789; + +#define SHR3 (jz=jsr, jsr^=(jsr<<13), jsr^=(jsr>>17), jsr^=(jsr<<5),jz+jsr) +#define UNI (.5f + (signed) SHR3*.2328306e-9f) +#define IUNI SHR3 + +static long hz; +static unsigned long iz, kn[128], ke[256]; +static float wn[128],fn[128], we[256],fe[256]; + +#define RNOR (hz=SHR3, iz=hz&127, (fabs(hz)0)? r+x : -r-x; + } + /* iz>0, handle the wedges of other strips */ + if( fn[iz]+UNI*(fn[iz-1]-fn[iz]) < exp(-.5*x*x) ) return x; + + /* initiate, try to exit for(;;) for loop*/ + hz=SHR3; + iz=hz&127; + if(fabs(hz)=1;i--) + {dn=sqrt(-2.*log(vn/dn+exp(-.5*dn*dn))); + kn[i+1]=(dn/tn)*m1; + tn=dn; + fn[i]=exp(-.5*dn*dn); + wn[i]=dn/m1; + } + +/* Set up tables for REXP */ + q = ve/exp(-de); + ke[0]=(de/q)*m2; + ke[1]=0; + + we[0]=q/m2; + we[255]=de/m2; + + fe[0]=1.; + fe[255]=exp(-de); + + for(i=254;i>=1;i--) + {de=-log(ve/de+exp(-de)); + ke[i+1]= (de/te)*m2; + te=de; + fe[i]=exp(-de); + we[i]=de/m2; + } +} + + + + + diff --git a/src/spicelib/devices/isrc/isrcacct.c b/src/spicelib/devices/isrc/isrcacct.c index f2d2698c8..76f64f5eb 100644 --- a/src/spicelib/devices/isrc/isrcacct.c +++ b/src/spicelib/devices/isrc/isrcacct.c @@ -15,6 +15,7 @@ Author: 1985 Thomas L. Quarles extern int fftInit(long M); extern void fftFree(void); extern void rffts(float *data, long M, long Rows); +extern double exprand(double); int ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) @@ -202,8 +203,9 @@ INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise struct trnoise_state *state = here -> ISRCtrnoise_state; double TS = state -> TS; + double RTSAM = state ->RTSAM; - if (TS == 0.0) // no further breakpoint if value not given + if ((TS == 0.0) && (RTSAM == 0.0)) // no further breakpoint if value not given break; /* FIXME, dont' want this here, over to aof_get or somesuch */ @@ -228,6 +230,46 @@ INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise return(error); } } + + + if (RTSAM > 0) { + double RTScapTime = state->RTScapTime; + double RTSemTime = state->RTSemTime; + double RTSCAPT = state->RTSCAPT; + double RTSEMT = state->RTSEMT; + + if (ckt->CKTtime == 0) { + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTScapTime); + if(error) + return(error); + } + } + + if(AlmostEqualUlps(RTScapTime, ckt->CKTtime, 3)) { + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTSemTime); + if(error) + return(error); + } + } + + if(AlmostEqualUlps(RTSemTime, ckt->CKTtime, 3)) { + /* new values */ + RTScapTime = here -> ISRCtrnoise_state ->RTScapTime = ckt->CKTtime + exprand(RTSCAPT); + here -> ISRCtrnoise_state ->RTSemTime = RTScapTime + exprand(RTSEMT); + + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTScapTime); + if(error) + return(error); + } + + + } + + } + } break; diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index e9a935c92..fc0a61d3d 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -327,10 +327,13 @@ INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise struct trnoise_state *state = here -> ISRCtrnoise_state; double TS = state -> TS; + double RTSAM = state->RTSAM; + /* no noise */ if(TS == 0.0) { value = 0.0; } else { + /* 1/f and white noise */ size_t n1 = (size_t) floor(time / TS); double V1 = trnoise_state_get(state, ckt, n1); @@ -339,6 +342,14 @@ INoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise value = V1 + (V2 - V1) * (time / TS - n1); } + /* RTS noise */ + if (RTSAM > 0) { + double RTScapTime = state->RTScapTime; + if (time >= RTScapTime) + value += RTSAM; + } + + /* DC value */ if(here -> ISRCdcGiven) value += here->ISRCdcValue; } // case diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index d63e66c1d..b75f9e408 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -155,6 +155,9 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) double NA, TS; double NALPHA = 0.0; double NAMP = 0.0; + double RTSAM = 0.0; + double RTSCAPT = 0.0; + double RTSEMT = 0.0; here->ISRCfunctionType = TRNOISE; here->ISRCfuncTGiven = TRUE; @@ -171,8 +174,18 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) if (here->ISRCfunctionOrder > 3 && NALPHA != 0.0) NAMP = here->ISRCcoeffs[3]; + if (here->ISRCfunctionOrder > 4) + RTSAM = here->ISRCcoeffs[4]; // RTS amplitude + + if (here->ISRCfunctionOrder > 5 && RTSAM != 0.0) + RTSCAPT = here->ISRCcoeffs[5]; // RTS trap capture time + + if (here->ISRCfunctionOrder > 6 && RTSAM != 0.0) + RTSEMT = here->ISRCcoeffs[6]; // RTS trap emission time + here->ISRCtrnoise_state = - trnoise_state_init(NA, TS, NALPHA, NAMP); + trnoise_state_init(NA, TS, NALPHA, NAMP, RTSAM, RTSCAPT, RTSEMT); + } break; diff --git a/src/spicelib/devices/vsrc/vsrcacct.c b/src/spicelib/devices/vsrc/vsrcacct.c index f3e47057b..308bd35f7 100644 --- a/src/spicelib/devices/vsrc/vsrcacct.c +++ b/src/spicelib/devices/vsrc/vsrcacct.c @@ -15,6 +15,7 @@ Author: 1985 Thomas L. Quarles extern int fftInit(long M); extern void fftFree(void); extern void rffts(float *data, long M, long Rows); +extern double exprand(double); #define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW) #define TIMETOL 1e-7 @@ -197,8 +198,9 @@ VNoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise struct trnoise_state *state = here -> VSRCtrnoise_state; double TS = state -> TS; + double RTSAM = state ->RTSAM; - if (TS == 0.0) // no further breakpoint if value not given + if ((TS == 0.0) && (RTSAM == 0.0)) // no further breakpoint if value not given break; /* FIXME, dont' want this here, over to aof_get or somesuch */ @@ -223,6 +225,45 @@ VNoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise return(error); } } + + if (RTSAM > 0) { + double RTScapTime = state->RTScapTime; + double RTSemTime = state->RTSemTime; + double RTSCAPT = state->RTSCAPT; + double RTSEMT = state->RTSEMT; + + if (ckt->CKTtime == 0) { + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTScapTime); + if(error) + return(error); + } + } + + if(AlmostEqualUlps(RTScapTime, ckt->CKTtime, 3)) { + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTSemTime); + if(error) + return(error); + } + } + + if(AlmostEqualUlps(RTSemTime, ckt->CKTtime, 3)) { + /* new values */ + RTScapTime = here -> VSRCtrnoise_state ->RTScapTime = ckt->CKTtime + exprand(RTSCAPT); + here -> VSRCtrnoise_state ->RTSemTime = RTScapTime + exprand(RTSEMT); + + if (ckt->CKTbreak) { + error = CKTsetBreak(ckt, RTScapTime); + if(error) + return(error); + } + + + } + + } + } break; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 20f725693..ff55f9a25 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -58,303 +58,317 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) } /* use the transient functions */ switch(here->VSRCfunctionType) { - default: { /* no function specified: use the DC value */ - value = here->VSRCdcValue; - break; - } - - case PULSE: { - double V1, V2, TD, TR, TF, PW, PER; - double basetime = 0; + default: { /* no function specified: use the DC value */ + value = here->VSRCdcValue; + break; + } + + case PULSE: { + double V1, V2, TD, TR, TF, PW, PER; + double basetime = 0; #ifdef XSPICE - double PHASE; - double phase; - double deltat; + double PHASE; + double phase; + double deltat; #endif - V1 = here->VSRCcoeffs[0]; - V2 = here->VSRCcoeffs[1]; - TD = here->VSRCfunctionOrder > 2 - ? here->VSRCcoeffs[2] : 0.0; - TR = here->VSRCfunctionOrder > 3 - && here->VSRCcoeffs[3] != 0.0 - ? here->VSRCcoeffs[3] : ckt->CKTstep; - TF = here->VSRCfunctionOrder > 4 - && here->VSRCcoeffs[4] != 0.0 - ? here->VSRCcoeffs[4] : ckt->CKTstep; - PW = here->VSRCfunctionOrder > 5 - && here->VSRCcoeffs[5] != 0.0 - ? here->VSRCcoeffs[5] : ckt->CKTfinalTime; - PER = here->VSRCfunctionOrder > 6 - && here->VSRCcoeffs[6] != 0.0 - ? here->VSRCcoeffs[6] : ckt->CKTfinalTime; + V1 = here->VSRCcoeffs[0]; + V2 = here->VSRCcoeffs[1]; + TD = here->VSRCfunctionOrder > 2 + ? here->VSRCcoeffs[2] : 0.0; + TR = here->VSRCfunctionOrder > 3 + && here->VSRCcoeffs[3] != 0.0 + ? here->VSRCcoeffs[3] : ckt->CKTstep; + TF = here->VSRCfunctionOrder > 4 + && here->VSRCcoeffs[4] != 0.0 + ? here->VSRCcoeffs[4] : ckt->CKTstep; + PW = here->VSRCfunctionOrder > 5 + && here->VSRCcoeffs[5] != 0.0 + ? here->VSRCcoeffs[5] : ckt->CKTfinalTime; + PER = here->VSRCfunctionOrder > 6 + && here->VSRCcoeffs[6] != 0.0 + ? here->VSRCcoeffs[6] : ckt->CKTfinalTime; - /* shift time by delay time TD */ - time -= TD; + /* shift time by delay time TD */ + time -= TD; #ifdef XSPICE - /* gtri - begin - wbk - add PHASE parameter */ - PHASE = here->VSRCfunctionOrder > 7 - ? here->VSRCcoeffs[7] : 0.0; + /* gtri - begin - wbk - add PHASE parameter */ + PHASE = here->VSRCfunctionOrder > 7 + ? here->VSRCcoeffs[7] : 0.0; - /* normalize phase to cycles */ - phase = PHASE / 360.0; - phase = fmod(phase, 1.0); - deltat = phase * PER; - while (deltat > 0) - deltat -= PER; - /* shift time by pase (neg. for pos. phase value) */ - time += deltat; - /* gtri - end - wbk - add PHASE parameter */ + /* normalize phase to cycles */ + phase = PHASE / 360.0; + phase = fmod(phase, 1.0); + deltat = phase * PER; + while (deltat > 0) + deltat -= PER; + /* shift time by pase (neg. for pos. phase value) */ + time += deltat; + /* gtri - end - wbk - add PHASE parameter */ #endif - 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 > 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; + } - } - break; + } + break; - case SINE: { - - double VO, VA, FREQ, TD, THETA; - /* gtri - begin - wbk - add PHASE parameter */ + case SINE: { + + double VO, VA, FREQ, TD, THETA; + /* gtri - begin - wbk - add PHASE parameter */ #ifdef XSPICE - double PHASE; - double phase; + double PHASE; + double phase; - PHASE = here->VSRCfunctionOrder > 5 - ? here->VSRCcoeffs[5] : 0.0; - - /* compute phase in radians */ - phase = PHASE * M_PI / 180.0; + PHASE = here->VSRCfunctionOrder > 5 + ? here->VSRCcoeffs[5] : 0.0; + + /* compute phase in radians */ + phase = PHASE * M_PI / 180.0; #endif - VO = here->VSRCcoeffs[0]; - VA = here->VSRCcoeffs[1]; - FREQ = here->VSRCfunctionOrder > 2 - && here->VSRCcoeffs[2] != 0.0 - ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); - TD = here->VSRCfunctionOrder > 3 - ? here->VSRCcoeffs[3] : 0.0; - THETA = here->VSRCfunctionOrder > 4 - ? here->VSRCcoeffs[4] : 0.0; - - time -= TD; - if (time <= 0) { + VO = here->VSRCcoeffs[0]; + VA = here->VSRCcoeffs[1]; + FREQ = here->VSRCfunctionOrder > 2 + && here->VSRCcoeffs[2] != 0.0 + ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); + TD = here->VSRCfunctionOrder > 3 + ? here->VSRCcoeffs[3] : 0.0; + THETA = here->VSRCfunctionOrder > 4 + ? here->VSRCcoeffs[4] : 0.0; + + time -= TD; + if (time <= 0) { #ifdef XSPICE - value = VO + VA * sin(phase); - } else { + value = VO + VA * sin(phase); + } else { - value = VO + VA * sin(FREQ*time * 2.0 * M_PI + phase) * - exp(-time*THETA); + 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; + break; - case EXP: { - double V1, V2, TD1, TD2, TAU1, TAU2; - - V1 = here->VSRCcoeffs[0]; - V2 = here->VSRCcoeffs[1]; - TD1 = here->VSRCfunctionOrder > 2 - && here->VSRCcoeffs[2] != 0.0 - ? here->VSRCcoeffs[2] : ckt->CKTstep; - TAU1 = here->VSRCfunctionOrder > 3 - && here->VSRCcoeffs[3] != 0.0 - ? here->VSRCcoeffs[3] : ckt->CKTstep; - TD2 = here->VSRCfunctionOrder > 4 - && here->VSRCcoeffs[4] != 0.0 - ? here->VSRCcoeffs[4] : TD1 + ckt->CKTstep; - TAU2 = here->VSRCfunctionOrder > 5 - && here->VSRCcoeffs[5] - ? here->VSRCcoeffs[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)) ; + case EXP: { + double V1, V2, TD1, TD2, TAU1, TAU2; + + V1 = here->VSRCcoeffs[0]; + V2 = here->VSRCcoeffs[1]; + TD1 = here->VSRCfunctionOrder > 2 + && here->VSRCcoeffs[2] != 0.0 + ? here->VSRCcoeffs[2] : ckt->CKTstep; + TAU1 = here->VSRCfunctionOrder > 3 + && here->VSRCcoeffs[3] != 0.0 + ? here->VSRCcoeffs[3] : ckt->CKTstep; + TD2 = here->VSRCfunctionOrder > 4 + && here->VSRCcoeffs[4] != 0.0 + ? here->VSRCcoeffs[4] : TD1 + ckt->CKTstep; + TAU2 = here->VSRCfunctionOrder > 5 + && here->VSRCcoeffs[5] + ? here->VSRCcoeffs[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)) ; + } } - } - break; + break; - case SFFM:{ - - double VO, VA, FC, MDI, FS; + case SFFM:{ + + double VO, VA, FC, MDI, FS; /* gtri - begin - wbk - add PHASE parameters */ #ifdef XSPICE - double PHASEC, PHASES; - double phasec; - double phases; - - PHASEC = here->VSRCfunctionOrder > 5 - ? here->VSRCcoeffs[5] : 0.0; - PHASES = here->VSRCfunctionOrder > 6 - ? here->VSRCcoeffs[6] : 0.0; - - /* compute phases in radians */ - phasec = PHASEC * M_PI / 180.0; - phases = PHASES * M_PI / 180.0; + double PHASEC, PHASES; + double phasec; + double phases; + + PHASEC = here->VSRCfunctionOrder > 5 + ? here->VSRCcoeffs[5] : 0.0; + PHASES = here->VSRCfunctionOrder > 6 + ? here->VSRCcoeffs[6] : 0.0; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0; + phases = PHASES * M_PI / 180.0; #endif - VO = here->VSRCcoeffs[0]; - VA = here->VSRCcoeffs[1]; - FC = here->VSRCfunctionOrder > 2 - && here->VSRCcoeffs[2] - ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); - MDI = here->VSRCfunctionOrder > 3 - ? here->VSRCcoeffs[3] : 0.0; - FS = here->VSRCfunctionOrder > 4 - && here->VSRCcoeffs[4] - ? here->VSRCcoeffs[4] : (1/ckt->CKTfinalTime); + VO = here->VSRCcoeffs[0]; + VA = here->VSRCcoeffs[1]; + FC = here->VSRCfunctionOrder > 2 + && here->VSRCcoeffs[2] + ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); + MDI = here->VSRCfunctionOrder > 3 + ? here->VSRCcoeffs[3] : 0.0; + FS = here->VSRCfunctionOrder > 4 + && here->VSRCcoeffs[4] + ? here->VSRCcoeffs[4] : (1/ckt->CKTfinalTime); #ifdef XSPICE - /* compute waveform value */ - value = VO + VA * - sin((2 * M_PI * FC * time + phasec) + - MDI * sin(2.0 * M_PI * FS * time + phases)); + /* compute waveform value */ + value = VO + VA * + sin((2 * 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 * M_PI * FS * time)); + value = VO + VA * + sin((2.0 * M_PI * FC * time) + + MDI * sin(2 * M_PI * FS * time)); #endif /* XSPICE */ -/* gtri - end - wbk - add PHASE parameters */ - } - break; - case AM:{ - - double VA, FC, MF, VO, TD; -/* gtri - begin - wbk - add PHASE parameters */ + /* gtri - end - wbk - add PHASE parameters */ + } + break; + case AM:{ + + double VA, FC, MF, VO, TD; + /* gtri - begin - wbk - add PHASE parameters */ #ifdef XSPICE - double PHASEC, PHASES; - double phasec; - double phases; - - PHASEC = here->VSRCfunctionOrder > 5 - ? here->VSRCcoeffs[5] : 0.0; - PHASES = here->VSRCfunctionOrder > 6 - ? here->VSRCcoeffs[6] : 0.0; - - /* compute phases in radians */ - phasec = PHASEC * M_PI / 180.0; - phases = PHASES * M_PI / 180.0; + double PHASEC, PHASES; + double phasec; + double phases; + + PHASEC = here->VSRCfunctionOrder > 5 + ? here->VSRCcoeffs[5] : 0.0; + PHASES = here->VSRCfunctionOrder > 6 + ? here->VSRCcoeffs[6] : 0.0; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0; + phases = PHASES * M_PI / 180.0; #endif - VA = here->VSRCcoeffs[0]; - VO = here->VSRCcoeffs[1]; - MF = here->VSRCfunctionOrder > 2 - && here->VSRCcoeffs[2] - ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); - FC = here->VSRCfunctionOrder > 3 - ? here->VSRCcoeffs[3] : 0.0; - TD = here->VSRCfunctionOrder > 4 - && here->VSRCcoeffs[4] - ? here->VSRCcoeffs[4] : 0.0; + VA = here->VSRCcoeffs[0]; + VO = here->VSRCcoeffs[1]; + MF = here->VSRCfunctionOrder > 2 + && here->VSRCcoeffs[2] + ? here->VSRCcoeffs[2] : (1/ckt->CKTfinalTime); + FC = here->VSRCfunctionOrder > 3 + ? here->VSRCcoeffs[3] : 0.0; + TD = here->VSRCfunctionOrder > 4 + && here->VSRCcoeffs[4] + ? here->VSRCcoeffs[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); - + /* compute waveform value */ + 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 */ } - -/* gtri - end - wbk - add PHASE parameters */ - } - break; - case PWL: { - int i = 0, num_repeat = 0, ii = 0; - double foo, repeat_time = 0, end_time, breakpt_time, itime; + break; + case PWL: { + int i = 0, num_repeat = 0, ii = 0; + double foo, repeat_time = 0, end_time, breakpt_time, itime; - time -= here->VSRCrdelay; + time -= here->VSRCrdelay; - if(time < *(here->VSRCcoeffs)) { - foo = *(here->VSRCcoeffs + 1) ; - value = foo; - goto loadDone; - } + if(time < *(here->VSRCcoeffs)) { + foo = *(here->VSRCcoeffs + 1) ; + value = foo; + goto loadDone; + } - do { - for(i=ii ; i<(here->VSRCfunctionOrder/2)-1; i++ ) { - itime = *(here->VSRCcoeffs+2*i); - if ( AlmostEqualUlps(itime+repeat_time, time, 3 )) { - foo = *(here->VSRCcoeffs+2*i+1); - value = foo; - goto loadDone; - } else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time) - && (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) { - foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/ - (*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) * - (*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1))); - value = foo; - goto loadDone; + do { + for(i=ii ; i<(here->VSRCfunctionOrder/2)-1; i++ ) { + itime = *(here->VSRCcoeffs+2*i); + if ( AlmostEqualUlps(itime+repeat_time, time, 3 )) { + foo = *(here->VSRCcoeffs+2*i+1); + value = foo; + goto loadDone; + } else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time) + && (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) { + foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/ + (*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) * + (*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1))); + value = foo; + goto loadDone; + } } - } - foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ; - value = foo; + foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ; + value = foo; - if ( !here->VSRCrGiven ) goto loadDone; - - end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2); - breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt); - repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time; - ii = here->VSRCrBreakpt/2; - } while ( here->VSRCrGiven ); - break; - } + if ( !here->VSRCrGiven ) goto loadDone; + + end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2); + breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt); + repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time; + ii = here->VSRCrBreakpt/2; + } while ( here->VSRCrGiven ); + break; + } /**** tansient noise routines: VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise rms value, time step, 0 0 VNoi1 1 0 DC 0 TRNOISE(0n 0.5n 1 10n) : generate 1/f noise 0, time step, exponent < 2, rms value + +VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise + 0 0 0 0, amplitude, capture time, emission time */ - case TRNOISE: { + case TRNOISE: { - struct trnoise_state *state = here -> VSRCtrnoise_state; + struct trnoise_state *state = here -> VSRCtrnoise_state; - double TS = state -> TS; + double TS = state -> TS; + double RTSAM = state->RTSAM; - if(TS == 0.0) { - value = 0.0; - } else { - size_t n1 = (size_t) floor(time / TS); + /* no noise */ + if(TS == 0.0) { + value = 0.0; + } else { + /* 1/f and white noise */ + 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); + double V1 = trnoise_state_get(state, ckt, n1); + double V2 = trnoise_state_get(state, ckt, n1+1); - value = V1 + (V2 - V1) * (time / TS - n1); - } + value = V1 + (V2 - V1) * (time / TS - n1); + } + + /* RTS noise */ + if (RTSAM > 0) { + double RTScapTime = state->RTScapTime; + if (time >= RTScapTime) + value += RTSAM; + } - if(here -> VSRCdcGiven) - value += here->VSRCdcValue; - } // case - break; + /* DC value */ + if(here -> VSRCdcGiven) + value += here->VSRCdcValue; + } // case + break; } // switch } loadDone: diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index 7a4f9bd22..b98ac2a8d 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -174,6 +174,9 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) double NA, TS; double NALPHA = 0.0; double NAMP = 0.0; + double RTSAM = 0.0; + double RTSCAPT = 0.0; + double RTSEMT = 0.0; here->VSRCfunctionType = TRNOISE; here->VSRCfuncTGiven = TRUE; @@ -185,13 +188,22 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) TS = here->VSRCcoeffs[1]; // time step if (here->VSRCfunctionOrder > 2) - NALPHA = here->VSRCcoeffs[2]; + NALPHA = here->VSRCcoeffs[2]; // 1/f exponent if (here->VSRCfunctionOrder > 3 && NALPHA != 0.0) - NAMP = here->VSRCcoeffs[3]; + NAMP = here->VSRCcoeffs[3]; // 1/f amplitude + + if (here->VSRCfunctionOrder > 4) + RTSAM = here->VSRCcoeffs[4]; // RTS amplitude + + if (here->VSRCfunctionOrder > 5 && RTSAM != 0.0) + RTSCAPT = here->VSRCcoeffs[5]; // RTS trap capture time + + if (here->VSRCfunctionOrder > 6 && RTSAM != 0.0) + RTSEMT = here->VSRCcoeffs[6]; // RTS trap emission time here->VSRCtrnoise_state = - trnoise_state_init(NA, TS, NALPHA, NAMP); + trnoise_state_init(NA, TS, NALPHA, NAMP, RTSAM, RTSCAPT, RTSEMT); } break; default: diff --git a/visualc/vngspice.sln b/visualc/vngspice.sln index 92e8134ee..87ccee53e 100644 --- a/visualc/vngspice.sln +++ b/visualc/vngspice.sln @@ -40,4 +40,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + AMDCaProjectFile = D:\Spice_general\ng-spice-rework\visualc\CodeAnalyst\vngspice.caw + AMDCaPersistentStartup = vngspice + AMDCaPersistentConfig = Debug|Win32 + EndGlobalSection EndGlobal diff --git a/visualc/vngspice.vcproj b/visualc/vngspice.vcproj index 479b20f2d..348a7a7f1 100644 --- a/visualc/vngspice.vcproj +++ b/visualc/vngspice.vcproj @@ -1891,11 +1891,11 @@ > + +