add comments
This commit is contained in:
parent
2b7ec35695
commit
72a5e9754d
|
|
@ -1,3 +1,6 @@
|
|||
2009-08-05 Holger Vogt
|
||||
* measure.c: add comments (not yet complete)
|
||||
|
||||
2009-08-04 Dietmar Warning
|
||||
* configure.in, ngspice.h: looking for unistd.h & usage
|
||||
* bsim2/b2ld.c: correct args size
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/* Routines to evaluate the .measure cards.
|
||||
Entry point is function do_measure(), called by fcn dosim()
|
||||
from runcoms.c:335, after simulation is finished.
|
||||
|
||||
$Id&
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cpdefs.h"
|
||||
#include "ftedefs.h"
|
||||
|
|
@ -16,7 +23,7 @@ static bool measure_valid[20000];
|
|||
static bool just_chk_meas;
|
||||
static bool measures_passed;
|
||||
|
||||
|
||||
/** return precision (either 5 or environment variable NGSPICE_MEAS_PRECISION) */
|
||||
static int
|
||||
get_measure_precision()
|
||||
{
|
||||
|
|
@ -43,7 +50,7 @@ interpolate( struct dvec *time, struct dvec *values, int i, int j, double var_va
|
|||
}
|
||||
|
||||
static double
|
||||
get_volt_time( struct dvec *time, struct dvec *values, double value, char polarity, int index, bool *failed )
|
||||
get_volt_time( struct dvec *time, struct dvec *values, double value, char polarity, int mindex, bool *failed )
|
||||
{
|
||||
int i = 0, count = 0;
|
||||
double comp_time = 0;
|
||||
|
|
@ -52,13 +59,13 @@ get_volt_time( struct dvec *time, struct dvec *values, double value, char polari
|
|||
if ( polarity == 'r' ) {
|
||||
if ( values->v_realdata[i] < value && value <= values->v_realdata[i+1] ) {
|
||||
count++;
|
||||
if ( count == index ) comp_time = interpolate( time, values, i, i+1, value, 'x' );
|
||||
if ( count == mindex ) comp_time = interpolate( time, values, i, i+1, value, 'x' );
|
||||
}
|
||||
}
|
||||
else if ( polarity == 'f' ) {
|
||||
if ( values->v_realdata[i] >= value && value > values->v_realdata[i+1] ) {
|
||||
count++;
|
||||
if ( count == index ) comp_time = interpolate( time, values, i, i+1, value, 'x' );
|
||||
if ( count == mindex ) comp_time = interpolate( time, values, i, i+1, value, 'x' );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -71,10 +78,25 @@ get_volt_time( struct dvec *time, struct dvec *values, double value, char polari
|
|||
return comp_time;
|
||||
}
|
||||
|
||||
/* Evaluate the delay between time values at trig and targ i or v levels.
|
||||
Called by fcn do_delay_measurement().
|
||||
Returns FALSE if successful.*/
|
||||
static bool
|
||||
measure( char *trig_name, double trig_value, char trig_polarity, int trig_index,
|
||||
char *targ_name, double targ_value, char targ_polarity, int targ_index, double *result,
|
||||
double *trig_time, double *targ_time ) {
|
||||
measure(
|
||||
char *trig_name, /*in: name (e.g. in) of vector (e.g. v(in)) following trig parameter */
|
||||
double trig_value, /*in: i or v level following trig parameter */
|
||||
char trig_polarity, /*in: r for rising slope, f for falling slope */
|
||||
int trig_index, /*in: time is measured only after this number of rising (
|
||||
falling) slopes with trigvalue has been detected*/
|
||||
char *targ_name, /*in: name (e.g. in) of vector (e.g. v(in)) following targ parameter */
|
||||
double targ_value, /*in: i or v level following targ parameter */
|
||||
char targ_polarity, /*in: r for rising slope, f for falling slope */
|
||||
int targ_index, /*in: time is measured only after this number of rising (
|
||||
falling) slopes with targvalue has been detected */
|
||||
double *result, /*out: difference between *targ_time and *trig_time*/
|
||||
double *trig_time, /*out: time at given i or v level following trig parameter*/
|
||||
double *targ_time /*out: time at given i or v level following targ parameter*/
|
||||
) {
|
||||
struct dvec *time = vec_get("time");
|
||||
struct dvec *trig = vec_get(trig_name);
|
||||
struct dvec *targ = vec_get(targ_name);
|
||||
|
|
@ -307,12 +329,11 @@ get_double_value( char **line, char *name, double *value ) {
|
|||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*
|
||||
* gettok skips over whitespace and returns the next token found. This is
|
||||
* the original version. It does not "do the right thing" when you have
|
||||
* parens or commas anywhere in the nodelist. Note that I left this unmodified
|
||||
* since I didn't want to break any fcns which called it from elsewhere than
|
||||
* subckt.c. -- SDB 12.3.2003.
|
||||
* Since gettok doesn't work right try a new version that does. WPS.
|
||||
gettok_paren skips over whitespace and returns the next token found. Here it
|
||||
is used only to return part of a vector, eg V(in) or I(mynode).
|
||||
For example v(in) has already been stripped to in) when gettok_paren is called.
|
||||
gettok_paren returns 'in', leaving ')' as the next character of s.
|
||||
Only called from fcn get_vector_name().
|
||||
*-------------------------------------------------------------------------*/
|
||||
static char *
|
||||
gettok_paren(char **s)
|
||||
|
|
@ -323,22 +344,26 @@ get_double_value( char **line, char *name, double *value ) {
|
|||
int paren;
|
||||
|
||||
paren = 0;
|
||||
/* skip over leading white spaces */
|
||||
while (isspace(**s))
|
||||
(*s)++;
|
||||
/* if nothing left (end of line), return NULL */
|
||||
if (!**s)
|
||||
return (NULL);
|
||||
|
||||
while ((c = **s) && !isspace(c)) {
|
||||
if (c == '('/*)*/)
|
||||
paren += 1;
|
||||
else if (c == /*(*/')'){
|
||||
paren -= 1;
|
||||
if( paren <= 0 )
|
||||
if( paren <= 0 ) /* added over gettok */
|
||||
break ;
|
||||
} else if (c == ',' && paren < 1)
|
||||
break;
|
||||
buf[i++] = *(*s)++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/* skip over trailing white spaces and commas*/
|
||||
while (isspace(**s) || **s == ',')
|
||||
(*s)++;
|
||||
return (copy(buf));
|
||||
|
|
@ -357,8 +382,18 @@ get_vector_name( char **line ) {
|
|||
return name;
|
||||
}
|
||||
|
||||
/* Evaluate measurement types trig|delay .
|
||||
Called by do_measure().
|
||||
Calls measure(). */
|
||||
static bool
|
||||
do_delay_measurement( char *resname, char *out_line, char *line, char *o_line, int meas_index, double *result ) {
|
||||
do_delay_measurement(
|
||||
char *resname, /*in: name of result parameter, defined by user*/
|
||||
char *out_line, /*out: output for printing */
|
||||
char *line, /*in: .meas card, first four parameters stripped */
|
||||
char *o_line, /*in: .meas card, complete */
|
||||
int meas_index, /*in: number of measurements */
|
||||
double *result /*out: delay value returned by measure() */
|
||||
) {
|
||||
char *trig_name, *targ_name, *token;
|
||||
char trig_type, targ_type, trig_polarity, targ_polarity;
|
||||
double targ_value, trig_value;
|
||||
|
|
@ -521,20 +556,46 @@ do_other_measurement( char *resname, char *out_line, char *meas_type, char *line
|
|||
return ( failed ) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
/* Entry point for .meas evaluation.
|
||||
Called in fcn dosim() from runcoms.c:335, after simulation is finished
|
||||
with chk_only set to FALSE.
|
||||
Called from fcn check_autostop()
|
||||
with chk_only set to TRUE (no printouts, no params set). */
|
||||
void
|
||||
do_measure( char *what, bool chk_only ) {
|
||||
do_measure(
|
||||
char *what, /*in: analysis type*/
|
||||
bool chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/
|
||||
/*global variable measure_type
|
||||
out: */
|
||||
) {
|
||||
struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard;
|
||||
char *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000];
|
||||
int index = 0, ok = 0;
|
||||
int mindex = 0, ok = 0;
|
||||
double result = 0;
|
||||
bool first_time = TRUE;
|
||||
int precision = get_measure_precision();
|
||||
|
||||
just_chk_meas = chk_only;
|
||||
just_chk_meas = chk_only;
|
||||
|
||||
an_name = strdup( what );
|
||||
an_name = strdup( what ); /* analysis type, e.g. "tran" */
|
||||
strtolower( an_name );
|
||||
|
||||
/* Evaluating the linked list of .meas cards, assembled from the input deck
|
||||
by fcn inp_spsource() in inp.c:575.
|
||||
A typical .meas card will contain:
|
||||
parameter value
|
||||
nameof card .meas(ure)
|
||||
analysis type tran only tran available currently
|
||||
result name myout defined by user
|
||||
measurement type trig|delay|param|expr|avg|mean|max|min|rms|integ(ral)|when
|
||||
|
||||
The measurement type determines how to continue the .meas card.
|
||||
trig|delay are handled in fcn do_delay_measurement(), param|expr are skipped
|
||||
in first pass through .meas cards and are treated in second pass,
|
||||
all others are treated in fcn do_other_measurement().
|
||||
*/
|
||||
|
||||
/* first pass through .meas cards: evaluate everything except param|expr */
|
||||
for ( meas_card = ft_curckt->ci_meas; meas_card != NULL; meas_card = meas_card->li_next ) {
|
||||
line = meas_card->li_line;
|
||||
|
||||
|
|
@ -551,6 +612,7 @@ do_measure( char *what, bool chk_only ) {
|
|||
txfree(an_type); txfree(resname); txfree(meastype);
|
||||
continue;
|
||||
}
|
||||
/* print header before evaluating first .meas line */
|
||||
else if ( first_time ) {
|
||||
first_time = FALSE;
|
||||
|
||||
|
|
@ -563,13 +625,14 @@ do_measure( char *what, bool chk_only ) {
|
|||
/* skip param|expr measurement types for now -- will be done after other measurements */
|
||||
if ( strncmp( meastype, "param", 5 ) == 0 || strncmp( meastype, "expr", 4 ) == 0 ) continue;
|
||||
|
||||
/* skip .meas line, if analysis type from line and name of analysis performed differ */
|
||||
if ( strcmp( an_name, an_type ) != 0 ) {
|
||||
txfree(an_type); txfree(resname); txfree(meastype);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strcmp( meastype, "trig" ) == 0 || strcmp( meastype, "delay" ) == 0 ) {
|
||||
if ( do_delay_measurement( resname, out_line, line, meas_card->li_line, index++, &result ) && just_chk_meas != TRUE ) {
|
||||
if ( strcmp( meastype, "trig" ) == 0 || strcmp( meastype, "delay" ) == 0 ) {
|
||||
if ( do_delay_measurement( resname, out_line, line, meas_card->li_line, mindex++, &result ) && just_chk_meas != TRUE ) {
|
||||
nupa_add_param( resname, result );
|
||||
}
|
||||
}
|
||||
|
|
@ -577,7 +640,7 @@ do_measure( char *what, bool chk_only ) {
|
|||
strcmp( meastype, "max" ) == 0 || strcmp( meastype, "min" ) == 0 ||
|
||||
strcmp( meastype, "rms" ) == 0 || strcmp( meastype, "integ" ) == 0 ||
|
||||
strcmp( meastype, "integral" ) == 0 || strcmp( meastype, "when" ) == 0 ) {
|
||||
if ( do_other_measurement( resname, out_line, meastype, line, meas_card->li_line, index++, &result ) && just_chk_meas != TRUE ) {
|
||||
if ( do_other_measurement( resname, out_line, meastype, line, meas_card->li_line, mindex++, &result ) && just_chk_meas != TRUE ) {
|
||||
nupa_add_param( resname, result );
|
||||
}
|
||||
}
|
||||
|
|
@ -603,16 +666,16 @@ do_measure( char *what, bool chk_only ) {
|
|||
txfree(an_type); txfree(resname); txfree(meastype);
|
||||
|
||||
// see if number of measurements exceeds fixed array size of 20,000
|
||||
if ( index >= 20000 ) {
|
||||
if ( mindex >= 20000 ) {
|
||||
fprintf( stderr, "ERROR: number of measurements exceeds 20,000!\nAborting...\n" );
|
||||
#ifdef HAS_WINDOWS
|
||||
winmessage("Fatal error in SPICE");
|
||||
#endif
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
} /* end of for loop (first pass through .meas lines) */
|
||||
|
||||
// now do param|expr .meas statements
|
||||
/* second pass through .meas cards: now do param|expr .meas statements */
|
||||
newcard = meas_results;
|
||||
for ( meas_card = ft_curckt->ci_meas; meas_card != NULL; meas_card = meas_card->li_next ) {
|
||||
line = meas_card->li_line;
|
||||
|
|
@ -679,6 +742,11 @@ do_measure( char *what, bool chk_only ) {
|
|||
//nupa_list_params();
|
||||
}
|
||||
|
||||
|
||||
/* called from dctran.c:470, if TRUE is returned, transient simulation is stopped.
|
||||
Returns TRUE if "autostop" has been set as an option and if measures_passed not
|
||||
set to FALSE during calling do_measure. what is set to "tran".*/
|
||||
|
||||
bool
|
||||
check_autostop( char* what ) {
|
||||
bool flag = FALSE;
|
||||
|
|
|
|||
Loading…
Reference in New Issue