inp.c, incom.c: enable evaluation of all statistical functions agauss, gauss, aunif, unif, limit

inp.c: agauss in MC with prof. libraries, second part: after subcircuit expansion, replace all agauss occurrencies in b-lines by their respective return value of fcn agauss()
This commit is contained in:
h_vogt 2016-03-19 16:11:14 +01:00 committed by rlar
parent 56f03605dc
commit 9ae9968902
2 changed files with 81 additions and 17 deletions

View File

@ -60,7 +60,7 @@ static void inp_parse_temper_trees(void);
static wordlist *inp_savecurrents(struct line *deck, struct line *options, wordlist *wl, wordlist *controls);
static void eval_agauss_bsource(struct line *deck);
static void eval_agauss_bsource(struct line *deck, char *fcn);
void line_free_x(struct line *deck, bool recurse);
void create_circbyline(char *line);
@ -666,7 +666,10 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
inp_parse_temper(deck);
/* replace agauss(x,y,z) in each b-line by suitable value */
eval_agauss_bsource(deck);
static char *statfcn[] = { "agauss", "gauss", "aunif", "unif", "limit" };
int ii;
for (ii = 0; ii < 5; ii++)
eval_agauss_bsource(deck, statfcn[ii]);
/* If user wants all currents saved (.options savecurrents), add .save
to wl_first with all terminal currents available on selected devices */
@ -1887,7 +1890,38 @@ agauss(double nominal_val, double abs_variation, double sigma)
}
/* Second step to enable agauss in professional parameter decks:
static double
gauss(double nominal_val, double rel_variation, double sigma)
{
double stdvar;
stdvar = nominal_val * rel_variation / sigma;
return (nominal_val + stdvar * gauss0());
}
static double
unif(double nominal_val, double rel_variation)
{
return (nominal_val + nominal_val * rel_variation * drand());
}
static double
aunif(double nominal_val, double abs_variation)
{
return (nominal_val + abs_variation * drand());
}
static double
limit(double nominal_val, double abs_variation)
{
return (nominal_val + (drand() > 0 ? abs_variation : -1. * abs_variation));
}
/* Second step to enable functions agauss, gauss, aunif, unif, limit
* in professional parameter decks:
* agauss has been preserved by replacement operation of .func
* (function inp_fix_agauss_in_param() in inpcom.c).
* After subcircuit expansion, agauss may be still existing in b-lines,
@ -1900,7 +1934,7 @@ agauss(double nominal_val, double abs_variation, double sigma)
*/
static void
eval_agauss_bsource(struct line *deck)
eval_agauss_bsource(struct line *deck, char *fcn)
{
struct line *card;
double x, y, z, val;
@ -1927,7 +1961,7 @@ eval_agauss_bsource(struct line *deck)
if (*curr_line != 'b')
continue;
while ((ap = search_identifier(curr_line, "agauss", curr_line)) != NULL) {
while ((ap = search_identifier(curr_line, fcn, curr_line)) != NULL) {
char *lparen, *rparen, *begstr, *contstr = NULL, *new_line, *midstr;
char *tmp1str, *tmp2str, *delstr;
int nerror;
@ -1947,10 +1981,35 @@ eval_agauss_bsource(struct line *deck)
delstr = tmp2str = gettok(&tmp1str);
y = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
delstr = tmp2str = gettok(&tmp1str);
z = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
val = agauss(x, y, z);
if (cieq(fcn, "agauss")) {
delstr = tmp2str = gettok(&tmp1str);
z = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
val = agauss(x, y, z);
}
else if (cieq(fcn, "gauss")) {
delstr = tmp2str = gettok(&tmp1str);
z = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
val = gauss(x, y, z);
}
else if (cieq(fcn, "aunif")) {
val = aunif(x, y);
}
else if (cieq(fcn, "unif")) {
val = unif(x, y);
}
else if (cieq(fcn, "limit")) {
val = limit(x, y);
}
else {
fprintf(cp_err, "ERROR: Unknown function %s, cannot evaluate\n", fcn);
tfree(begstr);
tfree(contstr);
tfree(midstr);
return;
}
new_line = tprintf("%s%g%s", begstr, val, contstr);
tfree(card->li_line);
curr_line = card->li_line = new_line;

View File

@ -141,7 +141,7 @@ static void replace_token(char *string, char *token, int where, int total);
static void inp_add_series_resistor(struct line *deck);
static void subckt_params_to_param(struct line *deck);
static void inp_fix_temper_in_param(struct line *deck);
static void inp_fix_agauss_in_param(struct line *deck);
static void inp_fix_agauss_in_param(struct line *deck, char *fcn);
static char *inp_spawn_brace(char *s);
@ -518,7 +518,11 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile)
rv . line_number = inp_split_multi_param_lines(working, rv . line_number);
inp_fix_macro_param_func_paren_io(working);
inp_fix_agauss_in_param(working);
static char *statfcn[] = { "agauss", "gauss", "aunif", "unif", "limit" };
int ii;
for (ii = 0; ii < 5; ii++)
inp_fix_agauss_in_param(working, statfcn[ii]);
inp_fix_temper_in_param(working);
@ -6131,8 +6135,9 @@ inp_fix_temper_in_param(struct line *deck)
}
/* Convert .param lines containing function 'agauss' into .func lines:
* .param xxx1 = 'agauss()' ---> .func xxx1() 'agauss()'
/* Convert .param lines containing function 'agauss' and others
* (function name handed over by *fcn), into .func lines:
* .param xxx1 = 'aunif()' ---> .func xxx1() 'aunif()'
* Add info about the functions (name, subcircuit depth, number of
* subckt) to linked list new_func.
* Then scan new_func, for each xxx1 scan all lines of deck,
@ -6145,7 +6150,7 @@ inp_fix_temper_in_param(struct line *deck)
*/
static void
inp_fix_agauss_in_param(struct line *deck)
inp_fix_agauss_in_param(struct line *deck, char *fcn)
{
int skip_control = 0, subckt_depth = 0, j, *sub_count;
char *funcbody, *funcname;
@ -6199,7 +6204,7 @@ inp_fix_agauss_in_param(struct line *deck)
char *p, *temper, *equal_ptr, *lhs_b, *lhs_e;
temper = search_identifier(curr_line, "agauss", curr_line);
temper = search_identifier(curr_line, fcn, curr_line);
if (!temper)
continue;
@ -6232,9 +6237,9 @@ inp_fix_agauss_in_param(struct line *deck)
if (temper < equal_ptr) {
fprintf(stderr,
"Error: you cannot assign a value to TEMPER\n"
"Error: you cannot assign a value to %s\n"
" Line no. %d, %s\n",
card->li_linenum, curr_line);
fcn, card->li_linenum, curr_line);
controlled_exit(EXIT_BAD);
}