measure.c, rewrite do_measure()

This commit is contained in:
h_vogt 2012-12-09 13:13:35 +01:00 committed by rlar
parent 155b6134a8
commit 12e19d140b
2 changed files with 55 additions and 63 deletions

View File

@ -23,12 +23,6 @@
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 rflag;
@ -154,8 +148,6 @@ chkAnalysisType(char *an_type)
if (strcmp(an_type, "tran") != 0 && strcmp(an_type, "ac") != 0 &&
strcmp(an_type, "dc") != 0 && strcmp(an_type, "sp") != 0)
return FALSE;
// else if (ft_batchmode == TRUE)
// return FALSE;
else
return TRUE;
}
@ -165,9 +157,10 @@ chkAnalysisType(char *an_type)
On error returns FALSE. */
static bool
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);
@ -210,43 +203,44 @@ get_double_value(
/* 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
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(
char *what, /*in: analysis type*/
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;
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;
bool first_time = TRUE;
bool measures_passed;
wordlist *measure_word_list;
int precision = measure_get_precision();
#ifdef HAS_WINDOWS
if (!chk_only)
SetAnalyse("meas", 0);
#endif
just_chk_meas = chk_only;
an_name = strdup(what); /* analysis type, e.g. "tran" */
strtolower(an_name);
measure_word_list = NULL;
measures_passed = TRUE;
/* don't allow .meas if batchmode is set by -b and -r rawfile given */
if (ft_batchmode && rflag) {
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, "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
@ -274,7 +268,7 @@ do_measure(
meastype = gettok(&line);
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, " %s\n", meas_card->li_line);
}
@ -288,9 +282,8 @@ do_measure(
else if (first_time) {
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");
// plot_cur = setcplot("tran");
}
}
@ -313,44 +306,48 @@ do_measure(
if (measure_word_list) {
fail = get_measure2(measure_word_list, &result, out_line, chk_only);
if (fail) {
measure_valid[idx++] = FALSE;
measures_passed = FALSE;
if (!chk_only)
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 {
if (!(just_chk_meas))
if (!chk_only)
nupa_add_param(resname, result);
measure_valid[idx++] = TRUE;
}
wl_free(measure_word_list);
} else {
measure_valid[idx++] = 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(resname);
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) */
if (chk_only)
return (measures_passed);
/* second pass through .meas cards: now do param|expr .meas statements */
newcard = meas_results;
@ -364,7 +361,7 @@ do_measure(
meastype = gettok(&line);
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, " %s\n", meas_card->li_line);
}
@ -383,7 +380,7 @@ do_measure(
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);
end = newcard;
newcard = newcard->li_next;
@ -397,24 +394,24 @@ do_measure(
continue;
}
if (just_chk_meas != TRUE)
if (!chk_only)
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);
if (ok) {
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");
} else {
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, " %.*e\n", precision, result);
nupa_add_param(resname, result);
}
} else {
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, " failed\n");
}
}
@ -423,35 +420,30 @@ do_measure(
txfree(meastype);
}
if (just_chk_meas != TRUE)
if (!chk_only)
fprintf(stdout, "\n");
txfree(an_name);
fflush(stdout);
//nupa_list_params();
return(measures_passed);
}
/* called from dctran.c:470, if timepoint is accepted.
Returns TRUE if measurement (just a check, no output) has been successful.
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
check_autostop(char* what)
{
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;
}

View File

@ -266,7 +266,7 @@ extern void spar_write(char *name, struct plot *pl, double val);
extern struct plot *raw_read(char *name);
/* 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);
/* randnumb.c */