Browse Source

measure.c, rewrite do_measure()

pre-master-46
h_vogt 13 years ago
committed by rlar
parent
commit
12e19d140b
  1. 116
      src/frontend/measure.c
  2. 2
      src/include/ngspice/fteext.h

116
src/frontend/measure.c

@ -23,12 +23,6 @@
static wordlist *measure_parse_line(char *line); static wordlist *measure_parse_line(char *line);
static bool measure_valid[20000];/* TRUE: if measurement no. [xxx] has been done successfully
(not used anywhere)*/
static bool just_chk_meas; /* TRUE: only check if measurement can be done successfully,
no output generated (if option autostop is set)*/
static bool measures_passed; /* TRUE: stop simulation (if option autostop is set)*/
extern bool ft_batchmode; extern bool ft_batchmode;
extern bool rflag; extern bool rflag;
@ -154,8 +148,6 @@ chkAnalysisType(char *an_type)
if (strcmp(an_type, "tran") != 0 && strcmp(an_type, "ac") != 0 && if (strcmp(an_type, "tran") != 0 && strcmp(an_type, "ac") != 0 &&
strcmp(an_type, "dc") != 0 && strcmp(an_type, "sp") != 0) strcmp(an_type, "dc") != 0 && strcmp(an_type, "sp") != 0)
return FALSE; return FALSE;
// else if (ft_batchmode == TRUE)
// return FALSE;
else else
return TRUE; return TRUE;
} }
@ -165,9 +157,10 @@ chkAnalysisType(char *an_type)
On error returns FALSE. */ On error returns FALSE. */
static bool static bool
get_double_value( get_double_value(
char **line, /*in|out: pointer to line to be parsed */
char *name, /*in: xxx e.g. 'val' from 'val=0.5' */
double *value /*out: return value (e.g. 0.5) from 'val=0.5'*/
char **line, /*in|out: pointer to line to be parsed */
char *name, /*in: xxx e.g. 'val' from 'val=0.5' */
double *value, /*out: return value (e.g. 0.5) from 'val=0.5'*/
bool just_chk_meas /* in: just check measurement if true */
) )
{ {
char *token = gettok(line); char *token = gettok(line);
@ -210,43 +203,44 @@ get_double_value(
/* Entry point for .meas evaluation. /* Entry point for .meas evaluation.
Called in fcn dosim() from runcoms.c:335, after simulation is finished Called in fcn dosim() from runcoms.c:335, after simulation is finished
with chk_only set to FALSE. with chk_only set to FALSE.
Called from fcn check_autostop()
with chk_only set to TRUE (no printouts, no params set). */
void
Called from fcn check_autostop(),
with chk_only set to TRUE (no printouts, no params set).
This function returns TRUE if all measurements are ready and complete;
FALSE otherwise. If called with chk_only, we can exit early if we
fail a test in order to reduce execution time. */
bool
do_measure( do_measure(
char *what, /*in: analysis type*/ char *what, /*in: analysis type*/
bool chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/ bool chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/
/*global variable measures_passed
out: set to FALSE if .meas syntax is violated (used with autostop)*/
) )
{ {
struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard; struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard;
char *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000]; char *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000];
int idx = 0, ok = 0;
int fail;
int ok = 0;
int fail;
int num_failed = 0;
double result = 0; double result = 0;
bool first_time = TRUE; bool first_time = TRUE;
bool measures_passed;
wordlist *measure_word_list; wordlist *measure_word_list;
int precision = measure_get_precision(); int precision = measure_get_precision();
#ifdef HAS_WINDOWS #ifdef HAS_WINDOWS
if (!chk_only) if (!chk_only)
SetAnalyse("meas", 0); SetAnalyse("meas", 0);
#endif #endif
just_chk_meas = chk_only;
an_name = strdup(what); /* analysis type, e.g. "tran" */ an_name = strdup(what); /* analysis type, e.g. "tran" */
strtolower(an_name); strtolower(an_name);
measure_word_list = NULL; measure_word_list = NULL;
measures_passed = TRUE;
/* don't allow .meas if batchmode is set by -b and -r rawfile given */ /* don't allow .meas if batchmode is set by -b and -r rawfile given */
if (ft_batchmode && rflag) { if (ft_batchmode && rflag) {
fprintf(cp_err, "\nNo .measure possible in batch mode (-b) with -r rawfile set!\n"); fprintf(cp_err, "\nNo .measure possible in batch mode (-b) with -r rawfile set!\n");
fprintf(cp_err, "Remove rawfile and use .print or .plot or\n"); fprintf(cp_err, "Remove rawfile and use .print or .plot or\n");
fprintf(cp_err, "select interactive mode (optionally with .control section) instead.\n\n"); fprintf(cp_err, "select interactive mode (optionally with .control section) instead.\n\n");
return;
return (measures_passed);
} }
/* Evaluating the linked list of .meas cards, assembled from the input deck /* Evaluating the linked list of .meas cards, assembled from the input deck
@ -274,7 +268,7 @@ do_measure(
meastype = gettok(&line); meastype = gettok(&line);
if (chkAnalysisType(an_type) != TRUE) { if (chkAnalysisType(an_type) != TRUE) {
if (just_chk_meas != TRUE) {
if (!chk_only) {
fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum); fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum);
fprintf(cp_err, " %s\n", meas_card->li_line); fprintf(cp_err, " %s\n", meas_card->li_line);
} }
@ -288,9 +282,8 @@ do_measure(
else if (first_time) { else if (first_time) {
first_time = FALSE; first_time = FALSE;
if (just_chk_meas != TRUE && strcmp(an_type, "tran") == 0) {
if (!chk_only && strcmp(an_type, "tran") == 0) {
fprintf(stdout, "\n Measurements for Transient Analysis\n\n"); fprintf(stdout, "\n Measurements for Transient Analysis\n\n");
// plot_cur = setcplot("tran");
} }
} }
@ -313,44 +306,48 @@ do_measure(
if (measure_word_list) { if (measure_word_list) {
fail = get_measure2(measure_word_list, &result, out_line, chk_only); fail = get_measure2(measure_word_list, &result, out_line, chk_only);
if (fail) { if (fail) {
measure_valid[idx++] = FALSE;
measures_passed = FALSE; measures_passed = FALSE;
if (!chk_only) if (!chk_only)
fprintf(stderr, " %s failed!\n\n", meas_card->li_line); fprintf(stderr, " %s failed!\n\n", meas_card->li_line);
num_failed++;
if (chk_only) {
/* added for speed - cleanup last parse and break */
txfree(an_type);
txfree(resname);
txfree(meastype);
break;
}
} else { } else {
if (!(just_chk_meas))
if (!chk_only)
nupa_add_param(resname, result); nupa_add_param(resname, result);
measure_valid[idx++] = TRUE;
} }
wl_free(measure_word_list); wl_free(measure_word_list);
} else { } else {
measure_valid[idx++] = FALSE;
measures_passed = FALSE; measures_passed = FALSE;
num_failed++;
} }
newcard = alloc(struct line);
newcard->li_line = strdup(out_line);
newcard->li_next = NULL;
if (!chk_only) {
newcard = alloc(struct line);
newcard->li_line = strdup(out_line);
newcard->li_next = NULL;
if (meas_results == NULL) {
meas_results = end = newcard;
} else {
end->li_next = newcard;
end = newcard;
if (meas_results == NULL) {
meas_results = end = newcard;
} else {
end->li_next = newcard;
end = newcard;
}
} }
txfree(an_type); txfree(an_type);
txfree(resname); txfree(resname);
txfree(meastype); txfree(meastype);
/* see if number of measurements exceeds fixed array size of 20,000 */
if (idx >= 20000) {
fprintf(stderr, "ERROR: number of measurements exceeds 20,000!\nAborting...\n");
controlled_exit(EXIT_FAILURE);
}
} /* end of for loop (first pass through .meas lines) */ } /* end of for loop (first pass through .meas lines) */
if (chk_only)
return (measures_passed);
/* second pass through .meas cards: now do param|expr .meas statements */ /* second pass through .meas cards: now do param|expr .meas statements */
newcard = meas_results; newcard = meas_results;
@ -364,7 +361,7 @@ do_measure(
meastype = gettok(&line); meastype = gettok(&line);
if (chkAnalysisType(an_type) != TRUE) { if (chkAnalysisType(an_type) != TRUE) {
if (just_chk_meas != TRUE) {
if (!chk_only) {
fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum); fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum);
fprintf(cp_err, " %s\n", meas_card->li_line); fprintf(cp_err, " %s\n", meas_card->li_line);
} }
@ -383,7 +380,7 @@ do_measure(
if (strncmp(meastype, "param", 5) != 0 && strncmp(meastype, "expr", 4) != 0) { if (strncmp(meastype, "param", 5) != 0 && strncmp(meastype, "expr", 4) != 0) {
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, "%s", newcard->li_line); fprintf(stdout, "%s", newcard->li_line);
end = newcard; end = newcard;
newcard = newcard->li_next; newcard = newcard->li_next;
@ -397,24 +394,24 @@ do_measure(
continue; continue;
} }
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, "%-20s=", resname); fprintf(stdout, "%-20s=", resname);
if (just_chk_meas != TRUE) {
if (!chk_only) {
ok = nupa_eval(meas_card->li_line, meas_card->li_linenum, meas_card->li_linenum_orig); ok = nupa_eval(meas_card->li_line, meas_card->li_linenum, meas_card->li_linenum_orig);
if (ok) { if (ok) {
str_ptr = strstr(meas_card->li_line, meastype); str_ptr = strstr(meas_card->li_line, meastype);
if (!get_double_value(&str_ptr, meastype, &result)) {
if (just_chk_meas != TRUE)
if (!get_double_value(&str_ptr, meastype, &result, chk_only)) {
if (!chk_only)
fprintf(stdout, " failed\n"); fprintf(stdout, " failed\n");
} else { } else {
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, " %.*e\n", precision, result); fprintf(stdout, " %.*e\n", precision, result);
nupa_add_param(resname, result); nupa_add_param(resname, result);
} }
} else { } else {
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, " failed\n"); fprintf(stdout, " failed\n");
} }
} }
@ -423,35 +420,30 @@ do_measure(
txfree(meastype); txfree(meastype);
} }
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, "\n"); fprintf(stdout, "\n");
txfree(an_name); txfree(an_name);
fflush(stdout); fflush(stdout);
//nupa_list_params();
return(measures_passed);
} }
/* called from dctran.c:470, if timepoint is accepted. /* called from dctran.c:470, if timepoint is accepted.
Returns TRUE if measurement (just a check, no output) has been successful. Returns TRUE if measurement (just a check, no output) has been successful.
If TRUE is returned, transient simulation is stopped. 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".*/
Returns TRUE if "autostop" has been set as an option and if do_measure
passes all tests and thereby returns TRUE. 'what' is set to "tran". */
bool bool
check_autostop(char* what) check_autostop(char* what)
{ {
bool flag = FALSE; bool flag = FALSE;
measures_passed = TRUE;
if (cp_getvar("autostop", CP_BOOL, NULL)) {
do_measure(what, TRUE);
if (measures_passed == TRUE)
flag = TRUE;
}
if (cp_getvar("autostop", CP_BOOL, NULL))
flag = do_measure(what, TRUE);
return flag; return flag;
} }

2
src/include/ngspice/fteext.h

@ -266,7 +266,7 @@ extern void spar_write(char *name, struct plot *pl, double val);
extern struct plot *raw_read(char *name); extern struct plot *raw_read(char *name);
/* meas.c */ /* meas.c */
extern void do_measure(char *what, bool chk_only);
extern bool do_measure(char *what, bool chk_only);
extern bool check_autostop(char *what); extern bool check_autostop(char *what);
/* randnumb.c */ /* randnumb.c */

Loading…
Cancel
Save