From ec1ab0af88d042cbc62611d3f47a1e3607477d36 Mon Sep 17 00:00:00 2001 From: Robert Larice Date: Mon, 17 Dec 2012 20:58:41 +0100 Subject: [PATCH] copy to isrc fixme some E_BADPARM unterschiede fixme eine noise ist missing fixme einige der vars sollten in die pwl struct --- src/include/uisrc.h | 12 ++++ src/spicelib/devices/isrc/isrc.c | 2 + src/spicelib/devices/isrc/isrcacct.c | 74 +++++++++++++++++---- src/spicelib/devices/isrc/isrcask.c | 6 ++ src/spicelib/devices/isrc/isrcdefs.h | 11 ++++ src/spicelib/devices/isrc/isrcload.c | 99 ++++++++++++++++++++++------ src/spicelib/devices/isrc/isrcpar.c | 31 +++++++++ src/spicelib/devices/vsrc/vsrcdefs.h | 10 +-- 8 files changed, 204 insertions(+), 41 deletions(-) create mode 100644 src/include/uisrc.h diff --git a/src/include/uisrc.h b/src/include/uisrc.h new file mode 100644 index 000000000..9007308e0 --- /dev/null +++ b/src/include/uisrc.h @@ -0,0 +1,12 @@ +#ifndef FOO_H_INCLUDED +#define FOO_H_INCLUDED + +struct pwl_state +{ + double *arr; + int len; + int position; + int bpoint; +}; + +#endif diff --git a/src/spicelib/devices/isrc/isrc.c b/src/spicelib/devices/isrc/isrc.c index e872642ae..b7ec636f8 100644 --- a/src/spicelib/devices/isrc/isrc.c +++ b/src/spicelib/devices/isrc/isrc.c @@ -40,6 +40,8 @@ IFparm ISRCpTable[] = { /* parameters */ OP ("current", ISRC_CURRENT, IF_REAL, "Current in DC or Transient mode"), #endif /* gtri - end - add parameter for current source value */ + 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 fb3252147..69ce5c9aa 100644 --- a/src/spicelib/devices/isrc/isrcacct.c +++ b/src/spicelib/devices/isrc/isrcacct.c @@ -165,22 +165,75 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) break; case PWL: { - int i; - if(ckt->CKTtime < *(here->ISRCcoeffs)) { + double td = here->ISRCrdelay; + double tp = here->ISRCrperiod; + volatile double bp; + + if (ckt->CKTtime < here->ISRCcoeffs [0] + td) { + here->nxt = 0; + here->rpt = 0; if(ckt->CKTbreak) { - error = CKTsetBreak(ckt,*(here->ISRCcoeffs)); + error = CKTsetBreak(ckt, here->ISRCcoeffs [0] + td); break; } } - for(i=0;i<(here->ISRCfunctionOrder/2)-1;i++) { - if ( ckt->CKTbreak && AlmostEqualUlps(*(here->ISRCcoeffs+2*i), ckt->CKTtime, 3 ) ) { - error = CKTsetBreak(ckt, *(here->ISRCcoeffs+2*i+2)); - if(error) return(error); - goto bkptset; + + /* check td + first >= 0 */ + + /* + * Postition: + * nxt = [0, order[ + * rpt = [0.. [ + * with + * time == arr[nxt] + rpt*period + td + * + * (fixme, no thats inclusive see above) + * + * evtl ==order als Ende Kriterium, !!! must + */ + + /* (libc) Remainder Functions, `same sign ...' and magnitude ... */ + +#if 0 + if (repeat && (time > tstart)) + rest = tstart + fmod(time - tstart, period); + else + rest = time; +#endif + + if (!ckt->CKTbreak || here->nxt >= here->ISRCfunctionOrder) + break; + + bp = here->ISRCcoeffs[here->nxt] + td + (here->rpt * tp); + + if (!AlmostEqualUlps(bp, ckt->CKTtime, 3)) + break; + + for (;;) { + volatile double t; + + here->nxt += 2; + if (here->nxt >= here->ISRCfunctionOrder) { + if (!here->ISRCrGiven) + break; + here->nxt = here->ISRCrBreakpt; + here->rpt++; } + + t = here->ISRCcoeffs[here->nxt] + td + (here->rpt * tp); + + /* CKTtime isn't exactly identical to bp, thus ... */ + if (t <= ckt->CKTtime || t <= bp) + continue; + + bp = t; + error = CKTsetBreak(ckt, bp); + if (error) + return(error); + break; } - break; } + break; /**** tansient noise routines: INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise @@ -200,7 +253,7 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) /* FIXME, dont' want this here, over to aof_get or somesuch */ if (ckt->CKTtime == 0.0) { if (ft_ngdebug) - printf("VSRC: free fft tables\n"); + printf("ISRC: free fft tables\n"); fftFree(); } @@ -289,7 +342,6 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel) } // switch } // if ... else -bkptset: ; } // for } // for diff --git a/src/spicelib/devices/isrc/isrcask.c b/src/spicelib/devices/isrc/isrcask.c index 3740ab331..31fa7e31e 100644 --- a/src/spicelib/devices/isrc/isrcask.c +++ b/src/spicelib/devices/isrc/isrcask.c @@ -70,6 +70,12 @@ ISRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue * case ISRC_AC_IMAG: value->rValue = here->ISRCacImag; return (OK); + case ISRC_R: + value->rValue = here->ISRCr; + return (OK); + case ISRC_TD: + value->rValue = here->ISRCrdelay; + return (OK); case ISRC_FCN_ORDER: value->rValue = here->ISRCfunctionOrder; return (OK); diff --git a/src/spicelib/devices/isrc/isrcdefs.h b/src/spicelib/devices/isrc/isrcdefs.h index 53939074e..d6fee48bf 100644 --- a/src/spicelib/devices/isrc/isrcdefs.h +++ b/src/spicelib/devices/isrc/isrcdefs.h @@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles #include "ngspice/cktdefs.h" #include "ngspice/gendefs.h" #include "ngspice/complex.h" +#include "uisrc.h" /* * structures to describe independent current sources @@ -30,6 +31,7 @@ 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 *ISRCcoeffs; /* pointer to array of coefficients */ double ISRCdcValue; /* DC and TRANSIENT value of source */ @@ -47,6 +49,12 @@ typedef struct sISRCinstance { struct trnoise_state *ISRCtrnoise_state; /* transient noise */ struct trrandom_state *ISRCtrrandom_state; /* transient random source */ + struct pwl_state *ISRC_state; + + int nxt, rpt; + double ISRCr; /* pwl repeat */ + double ISRCrdelay; /* pwl delay period */ + double ISRCrperiod; /* gtri - begin - add member to hold current source value */ #ifdef XSPICE @@ -64,6 +72,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,6 +132,8 @@ typedef struct sISRCmodel { /* gtri - end - add define for current source value */ #define ISRC_TRNOISE 25 #define ISRC_TRRANDOM 26 +#define ISRC_R 27 +#define ISRC_TD 28 /* model parameters */ diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index 2d23c554c..02271406c 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -18,6 +18,64 @@ Modified: 2000 Alansfixes /* gtri - end - wbk - modify for supply ramping option */ #endif + +static double +pwl_state_get(struct pwl_state *this, double time) +{ + /* fixme, enter mehrmals im sägezahn ... + * 1) optimier dafür + * 2) stelle sicher, dass das jeweils höchste timestamp zum zug kommt + * (allow step antwort *) + * invariant bei repeat: + * enter time < timof(last-point) + * this->position < indexof(last-point) (fixme really ? wenn es nur 2 points sind zB ) + */ + + for (;;) { + + double t1 = this->arr[this->position + 0]; + double t2 = this->arr[this->position + 2]; + + double v1, v2; + + if (time >= t2) { + if (this->position+4 >= this->len) + return this->arr[this->len-1]; + this->position += 2; + continue; + } + + if (time < t1) { + if (this->position == 0) + return this->arr[1]; + this->position = 0; + continue; + } + + /* invariant: t1 <= time < t2 ==> t1 != t2 */ + + v1 = this->arr[this->position + 1]; + v2 = this->arr[this->position + 3]; + + return v1 + ((v2-v1)/(t2-t1)) * (time - t1); + } +} + + +static void +pwl_state_init(struct pwl_state *this, ISRCinstance *here) +{ + + this->len = here->ISRCfunctionOrder; + this->arr = here->ISRCcoeffs; + this->position = 0; + this->bpoint = 0; +} + + +/*-----------------------------------------------------------------------------*/ + + int ISRCload(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current value into the @@ -289,30 +347,29 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) break; case PWL: { - int i; - if(time < *(here->ISRCcoeffs)) { - value = *(here->ISRCcoeffs + 1) ; - break; + + struct pwl_state *state; + + double td = here->ISRCrdelay; + double tp = here->ISRCrperiod; + double r = here->ISRCr; + + if (!here->ISRC_state) { + here->ISRC_state = TMALLOC(struct pwl_state, 1); + pwl_state_init((struct pwl_state *) here->ISRC_state, here); } - 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; - } + + state = (struct pwl_state *) here -> ISRC_state; + + /* fixme repeat value ignored */ + if (here->ISRCrGiven && time - td - r >= 0) { + double t = fmod(time - td - r, tp) + r; + value = pwl_state_get(state, t); + } else { + value = pwl_state_get(state, time - td); } - value = *(here->ISRCcoeffs+ here->ISRCfunctionOrder-1) ; - break; } + break; /**** tansient noise routines: INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 2ce4c2580..17fa42bb0 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -105,6 +105,7 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) copy_coeffs(here, value); for (i=0; i<(here->ISRCfunctionOrder/2)-1; i++) { + /* fixme identical soll erlaubt werden */ if (*(here->ISRCcoeffs+2*(i+1))<=*(here->ISRCcoeffs+2*i)) { fprintf(stderr, "Warning : current source %s", here->ISRCname); @@ -114,6 +115,36 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) break; + case ISRC_TD: + here->ISRCrdelay = value->rValue; + break; + + case ISRC_R: { + double end_time; + 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); + /* actually ok, würde stationaer bedeuten ... und ist so gut wie no repeat */ + 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 ); + } + + here ->ISRCrperiod = end_time - here->ISRCcoeffs[here->ISRCrBreakpt]; + } + break; + case ISRC_SFFM: if(value->v.numValue < 2) return(E_BADPARM); diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index ccd19bc71..0cffed3f3 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles #include "ngspice/cktdefs.h" #include "ngspice/gendefs.h" #include "ngspice/complex.h" +#include "uisrc.h" struct trnoise_state; @@ -81,15 +82,6 @@ typedef struct sVSRCinstance { } VSRCinstance ; -struct pwl_state -{ - double *arr; - int len; - int position; - int bpoint; -}; - - /* per model data */ typedef struct sVSRCmodel {