From 53a09636321bcb3d3d44805d82c1fddadbd7e685 Mon Sep 17 00:00:00 2001 From: Robert Larice Date: Mon, 17 Dec 2012 20:58:02 +0100 Subject: [PATCH] angefangene vsrc baustelle wip, versuch eines PWL vsrc rewrites --- src/spicelib/devices/vsrc/vsrcacct.c | 72 ++++++++++++++++++---- src/spicelib/devices/vsrc/vsrcdefs.h | 12 ++++ src/spicelib/devices/vsrc/vsrcload.c | 90 ++++++++++++++++++---------- src/spicelib/devices/vsrc/vsrcpar.c | 5 +- 4 files changed, 136 insertions(+), 43 deletions(-) diff --git a/src/spicelib/devices/vsrc/vsrcacct.c b/src/spicelib/devices/vsrc/vsrcacct.c index 25765ca9c..3d112f47d 100644 --- a/src/spicelib/devices/vsrc/vsrcacct.c +++ b/src/spicelib/devices/vsrc/vsrcacct.c @@ -165,22 +165,75 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel) break; case PWL: { - int i; - if(ckt->CKTtime < *(here->VSRCcoeffs)) { + double td = here->VSRCrdelay; + double tp = here->VSRCrperiod; + volatile double bp; + + if (ckt->CKTtime < here->VSRCcoeffs [0] + td) { + here->nxt = 0; + here->rpt = 0; if(ckt->CKTbreak) { - error = CKTsetBreak(ckt,*(here->VSRCcoeffs)); + error = CKTsetBreak(ckt, here->VSRCcoeffs [0] + td); break; } } - for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) { - if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) { - error = CKTsetBreak(ckt, *(here->VSRCcoeffs+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->VSRCfunctionOrder) + break; + + bp = here->VSRCcoeffs[here->nxt] + td + (here->rpt * tp); + + if (!AlmostEqualUlps(bp, ckt->CKTtime, 3)) + break; + + for (;;) { + volatile double t; + + here->nxt += 2; + if (here->nxt >= here->VSRCfunctionOrder) { + if (!here->VSRCrGiven) + break; + here->nxt = here->VSRCrBreakpt; + here->rpt++; } + + t = here->VSRCcoeffs[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: VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise @@ -289,7 +342,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel) } // switch } // if ... else -bkptset: ; } // for } // for diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index d8f71ec5e..ccd19bc71 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -52,9 +52,12 @@ typedef struct sVSRCinstance { struct trnoise_state *VSRCtrnoise_state; /* transient noise */ struct trrandom_state *VSRCtrrandom_state; /* transient random source */ + struct pwl_state *VSRC_state; + int nxt, rpt; double VSRCr; /* pwl repeat */ double VSRCrdelay; /* pwl delay period */ + double VSRCrperiod; double *VSRCposIbrptr; /* pointer to sparse matrix element at * (positive node, branch equation) */ double *VSRCnegIbrptr; /* pointer to sparse matrix element at @@ -78,6 +81,15 @@ typedef struct sVSRCinstance { } VSRCinstance ; +struct pwl_state +{ + double *arr; + int len; + int position; + int bpoint; +}; + + /* per model data */ typedef struct sVSRCmodel { diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 3f5726449..9acc987f7 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -18,6 +18,55 @@ Modified: 2000 AlansFixes /* gtri - end - wbk - modify for supply ramping option */ #endif + +static double +pwl_state_get(struct pwl_state *this, double time) +{ + 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, VSRCinstance *here) +{ + + this->len = here->VSRCfunctionOrder; + this->arr = here->VSRCcoeffs; + this->position = 0; + this->bpoint = 0; +} + + +/*-----------------------------------------------------------------------------*/ + + int VSRCload(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current value into the @@ -289,45 +338,22 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) break; case PWL: { - int i = 0, num_repeat = 0, ii = 0; - double foo, repeat_time = 0, end_time, breakpt_time, itime; - time -= here->VSRCrdelay; + struct pwl_state *state; - if(time < *(here->VSRCcoeffs)) { - foo = *(here->VSRCcoeffs + 1) ; - value = foo; - goto loadDone; + if (!here->VSRC_state) { + here->VSRC_state = TMALLOC(struct pwl_state, 1); + pwl_state_init((struct pwl_state *) here->VSRC_state, here); } - 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; + state = (struct pwl_state *) here -> VSRC_state; - if ( !here->VSRCrGiven ) goto loadDone; + /* fixme repeat value ignored */ + value = pwl_state_get(state, time - here->VSRCrdelay); - 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; + goto loadDone; } + break; /**** tansient noise routines: VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index e0db81974..48a007c17 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -105,6 +105,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) copy_coeffs(here, value); for (i=0; i<(here->VSRCfunctionOrder/2)-1; i++) { + /* fixme identical soll erlaubt werden */ if (*(here->VSRCcoeffs+2*(i+1))<=*(here->VSRCcoeffs+2*i)) { fprintf(stderr, "Warning : voltage source %s", here->VSRCname); @@ -129,6 +130,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) } end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2); + /* actually ok, würde stationaer bedeuten ... und ist so gut wie no repeat */ if ( here->VSRCr > end_time ) { fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->VSRCr ); return ( E_PARMVAL ); @@ -139,8 +141,9 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) return ( E_PARMVAL ); } - break; + here ->VSRCrperiod = end_time - here->VSRCcoeffs[here->VSRCrBreakpt]; } + break; case VSRC_SFFM: if(value->v.numValue < 2)