@ -19,9 +19,6 @@ extern void fftFree(void);
extern bool ft_ngdebug ; /* some additional debug info printed */
extern bool ft_ngdebug ; /* some additional debug info printed */
# define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
# define TIMETOL 1e-7
int
int
VSRCaccept ( CKTcircuit * ckt , GENmodel * inModel )
VSRCaccept ( CKTcircuit * ckt , GENmodel * inModel )
/* set up the breakpoint table. */
/* set up the breakpoint table. */
@ -51,7 +48,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
case PULSE : {
case PULSE : {
double TD , TR , TF , PW , PER ;
double TD , TR , TF , PW , PER ;
double tshift ;
double time = 0. ;
double time = 0. ;
double basetime = 0 ;
double basetime = 0 ;
double tmax = 1e99 ;
double tmax = 1e99 ;
@ -79,7 +75,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
/* offset time by delay */
/* offset time by delay */
time = ckt - > CKTtime - TD ;
time = ckt - > CKTtime - TD ;
tshift = TD ;
if ( newcompat . xs ) {
if ( newcompat . xs ) {
/* normalize phase to 0 - 360° */
/* normalize phase to 0 - 360° */
@ -90,71 +85,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
while ( deltat > 0 )
while ( deltat > 0 )
deltat - = PER ;
deltat - = PER ;
time + = deltat ;
time + = deltat ;
tshift = TD - deltat ;
}
else if ( PHASE > 0.0 ) {
} else if ( PHASE > 0.0 ) {
tmax = PHASE * PER ;
tmax = PHASE * PER ;
if ( time > tmax )
break ;
}
}
if ( ! newcompat . xs & & time > tmax ) {
/* Do nothing */
}
else {
if ( ckt - > CKTtime > = here - > VSRCbreak_time ) {
double wait ;
if ( time > = PER ) {
if ( time > = PER ) {
/* repeating signal - figure out where we are */
/* in period */
/* Repeating signal: where in period are we? */
basetime = PER * floor ( time / PER ) ;
basetime = PER * floor ( time / PER ) ;
time - = basetime ;
time - = basetime ;
}
}
if ( time < = 0.0 | | time > = TR + PW + TF ) {
if ( ckt - > CKTbreak & & SAMETIME ( time , 0.0 ) ) {
error = CKTsetBreak ( ckt , basetime + TR + tshift ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & SAMETIME ( TR + PW + TF , time ) ) {
error = CKTsetBreak ( ckt , basetime + PER + tshift ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & ( time = = - tshift ) ) {
error = CKTsetBreak ( ckt , basetime + tshift ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & SAMETIME ( PER , time ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR + PER ) ;
if ( error ) return ( error ) ;
}
}
else if ( time > = TR & & time < = TR + PW ) {
if ( ckt - > CKTbreak & & SAMETIME ( time , TR ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR + PW ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & SAMETIME ( TR + PW , time ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR + PW + TF ) ;
if ( error ) return ( error ) ;
}
}
else if ( time > 0 & & time < TR ) {
if ( ckt - > CKTbreak & & SAMETIME ( time , 0 ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & SAMETIME ( time , TR ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR + PW ) ;
if ( error ) return ( error ) ;
}
}
else { /* time > TR + PW && < TR + PW + TF */
if ( ckt - > CKTbreak & & SAMETIME ( time , TR + PW ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + TR + PW + TF ) ;
if ( error ) return ( error ) ;
}
else if ( ckt - > CKTbreak & & SAMETIME ( time , TR + PW + TF ) ) {
error = CKTsetBreak ( ckt , basetime + tshift + PER ) ;
if ( error ) return ( error ) ;
}
/* Set next breakpoint. */
if ( time < 0.0 ) {
/* Await first pulse */
wait = - time ;
} else if ( time < TR ) {
/* Wait for end of rise. */
wait = TR - time ;
} else if ( time < TR + PW ) {
/* Wait for fall. */
wait = TR + PW - time ;
} else if ( time < TR + PW + TF ) {
/* Wait for end of fall. */
wait = TR + PW + TF - time ;
} else {
/* Wait for next pulse. */
wait = PER - time ;
}
}
here - > VSRCbreak_time = ckt - > CKTtime + wait ;
error = CKTsetBreak ( ckt , here - > VSRCbreak_time ) ;
if ( error )
return error ;
/* If a timestep ends just before the break time,
* the break request may be ignored .
* Set threshold for requesting following break .
*/
here - > VSRCbreak_time - = ckt - > CKTminBreak ;
}
}
}
}
break ;
break ;
@ -179,25 +158,46 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
}
}
break ;
break ;
case PWL : {
int i ;
if ( ckt - > CKTtime < * ( here - > VSRCcoeffs ) ) {
if ( ckt - > CKTbreak ) {
error = CKTsetBreak ( ckt , * ( here - > VSRCcoeffs ) ) ;
break ;
case PWL :
if ( ckt - > CKTtime > = here - > VSRCbreak_time ) {
double time , end , period ;
int i ;
time = ckt - > CKTtime - here - > VSRCrdelay ;
end =
here - > VSRCcoeffs [ here - > VSRCfunctionOrder - 2 ] ;
if ( time > end ) {
if ( here - > VSRCrGiven ) {
/* Repeating. */
period = end -
here - > VSRCcoeffs [ here - > VSRCrBreakpt ] ;
time - = period * floor ( time / period ) ;
} else {
here - > VSRCbreak_time = ckt - > CKTfinalTime ;
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 ;
for ( i = 0 ;
i < here - > VSRCfunctionOrder ;
i + = 2 ) {
if ( here - > VSRCcoeffs [ i ] > time ) {
here - > VSRCbreak_time =
ckt - > CKTtime +
here - > VSRCcoeffs [ i ] - time ;
error = CKTsetBreak ( ckt ,
here - > VSRCbreak_time ) ;
if ( error )
return error ;
here - > VSRCbreak_time - = ckt - > CKTminBreak ;
break ;
}
}
}
}
}
break ;
break ;
}
/**** tansient noise routines:
/**** tr ansient noise routines:
VNoi2 2 0 DC 0 TRNOISE ( 10 n 0.5 n 0 0 n ) : generate gaussian distributed noise
VNoi2 2 0 DC 0 TRNOISE ( 10 n 0.5 n 0 0 n ) : generate gaussian distributed noise
rms value , time step , 0 0
rms value , time step , 0 0
VNoi1 1 0 DC 0 TRNOISE ( 0 n 0.5 n 1 10 n ) : generate 1 / f noise
VNoi1 1 0 DC 0 TRNOISE ( 0 n 0.5 n 1 10 n ) : generate 1 / f noise
@ -205,6 +205,7 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
*/
*/
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 ;
double RTSAM = state - > RTSAM ;
@ -220,61 +221,55 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
fftFree ( ) ;
fftFree ( ) ;
}
}
# endif
# endif
if ( TS > 0 & & ckt - > CKTtime > = here - > VSRCbreak_time ) {
if ( here - > VSRCbreak_time < 0.0 )
here - > VSRCbreak_time = TS ;
else
here - > VSRCbreak_time + = TS ;
error = CKTsetBreak ( ckt , here - > VSRCbreak_time ) ;
if ( error )
return ( error ) ;
here - > VSRCbreak_time - = ckt - > CKTminBreak ;
}
if ( ckt - > CKTbreak ) {
int n = ( int ) floor ( ckt - > CKTtime / TS + 0.5 ) ;
volatile double nearest = n * TS ;
if ( RTSAM < = 0 )
break ; /* No shot noise. */
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 ) ;
}
if ( ckt - > CKTtime = = 0 ) {
/* initialzing here again needed for repeated calls to tran command */
state - > RTScapTime = exprand ( state - > RTSCAPT ) ;
state - > RTSemTime =
state - > RTScapTime + exprand ( state - > RTSEMT ) ;
error = CKTsetBreak ( ckt , state - > RTScapTime ) ;
if ( error )
return ( error ) ;
break ;
}
}
if ( RTSAM > 0 ) {
double RTScapTime = state - > RTScapTime ;
double RTSemTime = state - > RTSemTime ;
double RTSCAPT = state - > RTSCAPT ;
double RTSEMT = state - > RTSEMT ;
if ( ckt - > CKTtime = = 0 ) {
/* initialzing here again needed for repeated calls to tran command */
state - > RTScapTime = RTScapTime = exprand ( RTSCAPT ) ;
state - > RTSemTime = RTSemTime = RTScapTime + exprand ( RTSEMT ) ;
if ( ckt - > CKTbreak ) {
error = CKTsetBreak ( ckt , RTScapTime ) ;
if ( error )
return ( error ) ;
}
}
/* Break handling code ends a timestep close to
* the requested time .
*/
if ( AlmostEqualUlps ( RTScapTime , ckt - > CKTtime , 3 ) ) {
if ( ckt - > CKTbreak ) {
error = CKTsetBreak ( ckt , RTSemTime ) ;
if ( error )
return ( error ) ;
}
}
if ( ckt - > CKTtime > =
state - > RTScapTime - ckt - > CKTminBreak & &
ckt - > CKTtime < =
state - > RTScapTime + ckt - > CKTminBreak ) {
error = CKTsetBreak ( ckt , state - > 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 - > CKTtime > =
state - > RTSemTime - ckt - > CKTminBreak ) {
/* new values */
if ( ckt - > CKTbreak ) {
error = CKTsetBreak ( ckt , RTScapTime ) ;
if ( error )
return ( error ) ;
}
}
state - > RTScapTime =
ckt - > CKTtime + exprand ( state - > RTSCAPT ) ;
state - > RTSemTime =
state - > RTScapTime + exprand ( state - > RTSEMT ) ;
error = CKTsetBreak ( ckt , state - > RTScapTime ) ;
if ( error )
return ( error ) ;
}
}
}
}
break ;
break ;
@ -286,30 +281,22 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
if ( ckt - > CKTtime = = 0 & & TD > 0 ) {
if ( ckt - > CKTtime = = 0 & & TD > 0 ) {
error = CKTsetBreak ( ckt , TD ) ;
error = CKTsetBreak ( ckt , TD ) ;
here - > VSRCbreak_time = TD ;
if ( error )
if ( error )
return ( error ) ;
return ( error ) ;
break ;
}
}
double time = ckt - > CKTtime - TD ;
if ( time < 0 ) break ;
if ( ckt - > CKTbreak ) {
int n = ( int ) floor ( time / TS + 0.5 ) ;
volatile double nearest = n * TS ;
if ( AlmostEqualUlps ( nearest , time , 10 ) ) {
/* carefully calculate `next'
* make sure it is really identical
* with the next calculated ` nearest ' value
*/
volatile double next = ( n + 1 ) * TS + TD ;
error = CKTsetBreak ( ckt , next ) ;
if ( error )
return ( error ) ;
state - > value = trrandom_state_get ( state ) ;
}
if ( ckt - > CKTtime > = here - > VSRCbreak_time ) {
if ( here - > VSRCbreak_time < 0.0 )
here - > VSRCbreak_time = TS ;
else
here - > VSRCbreak_time + = TS ;
error = CKTsetBreak ( ckt , here - > VSRCbreak_time ) ;
if ( error )
return ( error ) ;
here - > VSRCbreak_time - = ckt - > CKTminBreak ;
state - > value = trrandom_state_get ( state ) ;
}
}
}
}
break ;
break ;
@ -323,7 +310,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
} / / switch
} / / switch
} / / if . . . else
} / / if . . . else
bkptset : ;
} / / for
} / / for
} / / for
} / / for