diff --git a/src/include/uisrc.h b/src/include/uisrc.h index 1f50ea37b..7f217c1e1 100644 --- a/src/include/uisrc.h +++ b/src/include/uisrc.h @@ -6,8 +6,9 @@ struct pwl_state double *arr; int len; int position; - int XrBreakpt; + int rBreakpt; int rpt_cnt; + double td, tp; }; #endif diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index bfb80c29d..d7acfaed9 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -22,33 +22,61 @@ Modified: 2000 Alansfixes static double pwl_state_get(struct pwl_state *this, double time) { + double td = this->td; + double tp = this->tp; + + int rBreakpt = this->rBreakpt; + /* 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 ) */ + /* fixme, einen warp einbauen wenns nicht passt ? */ + for (;;) { - double t1 = this->arr[this->position + 0]; - double t2 = this->arr[this->position + 2]; + /* carefully exactly duplicate the math in vsrcacct .. */ + + volatile double t1 = this->arr[this->position + 0] + td + (this->rpt_cnt * tp); + volatile double t2 = this->arr[this->position + 2] + td + (this->rpt_cnt * tp); double v1, v2; if (time >= t2) { - if (this->position+4 >= this->len) + if (this->position+4 < this->len) { + this->position += 2; + continue; + } + + if (tp == 0.0) return this->arr[this->len-1]; - this->position += 2; + + /* actually a += 4 step, but the intermediate + * suffices t1 == t2 + */ + + this->position = rBreakpt; + this->rpt_cnt++; continue; } if (time < t1) { - if (this->position == 0) + if (this->position > rBreakpt) { /*fixme must be 0 !! vfor non repeat*/ + this->position -= 2; + continue; + } + + if (tp == 0.0 || this->rpt_cnt == 0) return this->arr[1]; - this->position = 0; + + /* actually a -= 4 step, but ... */ + + this->position = this->len - 4; + this->rpt_cnt--; continue; } @@ -66,10 +94,21 @@ static void pwl_state_init(struct pwl_state *this, ISRCinstance *here) { +#if 0 + assert + ( here->ISRCrGiven + ? here->ISRCr >= 0 && here->ISRCrperiod > 0 && here->ISRCrBreakpt >= 0 + : here->ISRCr == 0 && here->ISRCrperiod == 0 && here->ISRCrBreakpt == 0 ); +#endif + this->len = here->ISRCfunctionOrder; this->arr = here->ISRCcoeffs; this->position = 0; -#warning "Baustelle, ..." + this->rpt_cnt = 0; + + this->td = here->ISRCrdelay; + this->tp = here->ISRCrperiod; + this->rBreakpt = here->ISRCrBreakpt; } @@ -348,26 +387,12 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) case PWL: { - 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); } - 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 = pwl_state_get((struct pwl_state *) here -> ISRC_state, time); } break; diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 17fa42bb0..d26c92388 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -105,12 +105,13 @@ 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); - fprintf(stderr, " has non-increasing PWL time points.\n"); - } + if (here->ISRCcoeffs[2*i + 2] < here->ISRCcoeffs[2*i]) { + fprintf(stderr, + "ERROR: current source %s," + " PWL time stamps are not allowed to decrease.\n", + here->ISRCname); + return(E_PARMVAL); + } } break; @@ -120,28 +121,30 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) break; case ISRC_R: { - double end_time; - here->ISRCr = value->rValue; - here->ISRCrGiven = TRUE; + double Tr = value->rValue; + double Tperiod; - for ( i = 0; i < here->ISRCfunctionOrder; i += 2 ) { - here->ISRCrBreakpt = i; - if ( here->ISRCr == *(here->ISRCcoeffs+i) ) break; + for ( i = 0; i < here->ISRCfunctionOrder; i += 2 ) + if ( Tr == here->ISRCcoeffs[i] ) + break; + + if (i == here->ISRCfunctionOrder) { + fprintf(stderr, "ERROR: repeat start time value %g for pwl current source does not match any time point given!\n", Tr ); + return ( E_PARMVAL ); } - 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 ); + Tperiod = + here->ISRCcoeffs[here->ISRCfunctionOrder-2] - Tr; + + if (Tperiod == 0.0) { + fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source would cause a period of 0\n", Tr ); + 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]; + here->ISRCrGiven = TRUE; + here->ISRCr = Tr; + here->ISRCrperiod = Tperiod; + here->ISRCrBreakpt = i; } break; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index de5fbbebf..cec8142fe 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -20,8 +20,13 @@ Modified: 2000 AlansFixes static double -pwl_state_get(struct pwl_state *this, double time, double td, double tp, int XrBreakpt) +pwl_state_get(struct pwl_state *this, double time) { + double td = this->td; + double tp = this->tp; + + int rBreakpt = this->rBreakpt; + /* fixme, enter mehrmals im sägezahn ... * 1) optimier dafür * 2) stelle sicher, dass das jeweils höchste timestamp zum zug kommt @@ -54,13 +59,13 @@ pwl_state_get(struct pwl_state *this, double time, double td, double tp, int XrB * suffices t1 == t2 */ - this->position = XrBreakpt; + this->position = rBreakpt; this->rpt_cnt++; continue; } if (time < t1) { - if (this->position > XrBreakpt) { /*fixme must be 0 !! vfor non repeat*/ + if (this->position > rBreakpt) { this->position -= 2; continue; } @@ -89,10 +94,21 @@ static void pwl_state_init(struct pwl_state *this, VSRCinstance *here) { +#if 0 + assert + ( here->VSRCrGiven + ? here->VSRCr >= 0 && here->VSRCrperiod > 0 && here->VSRCrBreakpt >= 0 + : here->VSRCr == 0 && here->VSRCrperiod == 0 && here->VSRCrBreakpt == 0 ); +#endif + this->len = here->VSRCfunctionOrder; this->arr = here->VSRCcoeffs; this->position = 0; this->rpt_cnt = 0; + + this->td = here->VSRCrdelay; + this->tp = here->VSRCrperiod; + this->rBreakpt = here->VSRCrBreakpt; } @@ -371,23 +387,12 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) case PWL: { - struct pwl_state *state; - - double td = here->VSRCrdelay; - double tp = here->VSRCrperiod; - if (!here->VSRC_state) { here->VSRC_state = TMALLOC(struct pwl_state, 1); pwl_state_init((struct pwl_state *) here->VSRC_state, here); } - state = (struct pwl_state *) here -> VSRC_state; - - if (here->VSRCrGiven) { - value = pwl_state_get(state, time, td, tp, here->VSRCrBreakpt); - } else { - value = pwl_state_get(state, time, td, 0.0, 0); - } + value = pwl_state_get((struct pwl_state *) here -> VSRC_state, time); } break; diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index 5dbb79924..c4db5fc05 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -107,10 +107,10 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) for (i=0; i<(here->VSRCfunctionOrder/2)-1; i++) { if (here->VSRCcoeffs[2*i + 2] < here->VSRCcoeffs[2*i]) { fprintf(stderr, - "Warning : voltage source %s" - " has non-increasing PWL time points.\n", + "ERROR: voltage source %s," + " PWL time stamps are not allowed to decrease.\n", here->VSRCname); - break; + return(E_PARMVAL); } }