Browse Source

Convert .param lines containing 'agauss' and others

into .func (xxx1() 'agauss()', replace all xxx1 entries
by function xxx1().
After subcircuit expansion, replace agauss and others
in B-Line by their suitable values.
pre-master-46
Holger Vogt 8 years ago
parent
commit
10c6c5c38b
  1. 156
      src/frontend/inp.c
  2. 210
      src/frontend/inpcom.c

156
src/frontend/inp.c

@ -58,6 +58,7 @@ static void dotifeval(struct card *deck);
static wordlist *inp_savecurrents(struct card *deck, struct card *options, wordlist *wl, wordlist *controls);
static void eval_agauss(struct card *deck, char *fcn);
void line_free_x(struct card *deck, bool recurse);
void create_circbyline(char *line);
@ -378,7 +379,6 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
/* called with *fp == NULL and intfile: we want to load circuit from circarray */
if (fp || intfile) {
deck = inp_readall(fp, dir_name, comfile, intfile, &expr_w_temper);
/* files starting with *ng_script are user supplied command files */
if (deck && ciprefix("*ng_script", deck->line))
comfile = TRUE;
@ -599,6 +599,12 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
#ifdef HAS_PROGREP
SetAnalyse("Prepare Deck", 0);
#endif
/*FIXME This is for the globel param setting only */
/* replace agauss(x,y,z) in each b-line by suitable value */
static char *statfcn[] = { "agauss", "gauss", "aunif", "unif", "limit" };
int ii;
for (ii = 0; ii < 5; ii++)
eval_agauss(deck, statfcn[ii]);
/* Now expand subcircuit macros and substitute numparams.*/
if (!cp_getvar("nosubckt", CP_BOOL, NULL, 0))
if ((deck->nextcard = inp_subcktexpand(deck->nextcard)) == NULL) {
@ -678,6 +684,13 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
if (expr_w_temper)
inp_parse_temper(deck, &modtlist, &devtlist);
/* replace agauss(x,y,z) in each b-line by suitable value */
/* FIXME: This is for the local param setting (not yet implemented in
inp_fix_agauss_in_param() for model parameters according to HSPICE manual)
static char *statfcn[] = { "agauss", "gauss", "aunif", "unif", "limit" };
int ii;
for (ii = 0; ii < 5; ii++)
eval_agauss(deck, statfcn[ii]); */
/* If user wants all currents saved (.options savecurrents), add .save
to wl_first with all terminal currents available on selected devices */
wl_first = inp_savecurrents(deck, options, wl_first, controls);
@ -1873,3 +1886,144 @@ inp_savecurrents(struct card *deck, struct card *options, wordlist *wl, wordlist
return wl_append(wl, wl_reverse(p));
}
static double
agauss(double nominal_val, double abs_variation, double sigma)
{
double stdvar;
stdvar = abs_variation / sigma;
return (nominal_val + stdvar * gauss1());
}
static double
gauss(double nominal_val, double rel_variation, double sigma)
{
double stdvar;
stdvar = nominal_val * rel_variation / sigma;
return (nominal_val + stdvar * gauss1());
}
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,
* however agauss does not exist in the B source parser, and it would
* not make sense in adding it there, because in each time step a different
* return form agauss would result.
* So we have to do the following in each B-line:
* check for agauss(x,y,z), and replace it by a suitable return value
* of agauss()
* agauss may also occur in .param lines, which have to be treated as well
*/
static void
eval_agauss(struct card *deck, char *fcn)
{
struct card *card;
double x, y, z, val;
card = deck;
for (; card; card = card->nextcard) {
int skip_control = 0;
char *ap, *curr_line = card->line;
/* exclude any command inside .control ... .endc */
if (ciprefix(".control", curr_line)) {
skip_control++;
continue;
}
else if (ciprefix(".endc", curr_line)) {
skip_control--;
continue;
}
else if (skip_control > 0) {
continue;
}
if ((*curr_line != 'b') && !ciprefix(".para", curr_line))
continue;
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;
begstr = copy_substring(curr_line, ap);
lparen = strchr(ap, '(');
rparen = strchr(ap, ')');
tmp1str = midstr = copy_substring(lparen + 1, rparen);
if (rparen + 1)
contstr = copy(rparen + 1);
/* find the parameters */
delstr = tmp2str = gettok(&tmp1str);
x = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
delstr = tmp2str = gettok(&tmp1str);
y = INPevaluate(&tmp2str, &nerror, 1);
tfree(delstr);
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->line);
curr_line = card->line = new_line;
tfree(begstr);
tfree(contstr);
tfree(midstr);
}
}
}

210
src/frontend/inpcom.c

@ -138,6 +138,7 @@ static void replace_token(char *string, char *token, int where, int total);
static void inp_add_series_resistor(struct card *deck);
static void subckt_params_to_param(struct card *deck);
static void inp_fix_temper_in_param(struct card *deck);
static void inp_fix_agauss_in_param(struct card *deck, char *fcn);
static void inp_vdmos_model(struct card *deck);
static char *inp_spawn_brace(char *s);
@ -585,6 +586,11 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_t
rv . line_number = inp_split_multi_param_lines(working, rv . line_number);
inp_fix_macro_param_func_paren_io(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);
inp_expand_macros_in_deck(NULL, working);
@ -6040,6 +6046,210 @@ inp_fix_temper_in_param(struct card *deck)
}
/* 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,
* find all xxx1 and convert them to a function:
* xxx1 ---> xxx1()
*
* In a second step, after subcircuits have been expanded, all occurencies
* of agauss in a b-line are replaced by their suitable value (function
* eval_agauss() in inp.c).
*/
static void
inp_fix_agauss_in_param(struct card *deck, char *fcn)
{
int skip_control = 0, subckt_depth = 0, j, *sub_count;
char *funcbody, *funcname;
struct func_temper *f, *funcs = NULL, **funcs_tail_ptr = &funcs;
struct card *card;
sub_count = TMALLOC(int, 16);
for (j = 0; j < 16; j++)
sub_count[j] = 0;
/* first pass:
* determine all .param with agauss inside and replace by .func
* convert
* .param xxx1 = 'agauss(x,y,z) * 25'
* to
* .func xxx1() 'agauss(x,y,z) * 25'
*/
card = deck;
for (; card; card = card->nextcard) {
char *curr_line = card->line;
if (*curr_line == '*')
continue;
/* determine nested depths of subcircuits */
if (ciprefix(".subckt", curr_line)) {
subckt_depth++;
sub_count[subckt_depth]++;
continue;
}
else if (ciprefix(".ends", curr_line)) {
subckt_depth--;
continue;
}
/* exclude any command inside .control ... .endc */
if (ciprefix(".control", curr_line)) {
skip_control++;
continue;
}
else if (ciprefix(".endc", curr_line)) {
skip_control--;
continue;
}
else if (skip_control > 0) {
continue;
}
if (ciprefix(".para", curr_line)) {
char *p, *temper, *equal_ptr, *lhs_b, *lhs_e;
temper = search_identifier(curr_line, fcn, curr_line);
if (!temper)
continue;
equal_ptr = find_assignment(curr_line);
if (!equal_ptr) {
fprintf(stderr, "ERROR: could not find '=' on parameter line '%s'!\n", curr_line);
controlled_exit(EXIT_FAILURE);
}
/* .param lines with `,' separated multiple parameters
* must have been split in inp_split_multi_param_lines()
*/
if (find_assignment(equal_ptr + 1)) {
fprintf(stderr, "ERROR: internal error on line '%s'!\n", curr_line);
controlled_exit(EXIT_FAILURE);
}
lhs_b = skip_non_ws(curr_line); // eat .param
lhs_b = skip_ws(lhs_b);
lhs_e = skip_back_ws(equal_ptr, curr_line);
/* skip if this is a function already */
p = strpbrk(lhs_b, "(,)");
if (p && p < lhs_e)
continue;
if (temper < equal_ptr) {
fprintf(stderr,
"Error: you cannot assign a value to %s\n"
" Line no. %d, %s\n",
fcn, card->linenum, curr_line);
controlled_exit(EXIT_BAD);
}
funcname = copy_substring(lhs_b, lhs_e);
funcbody = copy(equal_ptr + 1);
*funcs_tail_ptr =
inp_new_func(funcname, funcbody, card, sub_count, subckt_depth);
funcs_tail_ptr = &(*funcs_tail_ptr)->next;
tfree(funcbody);
}
}
/* second pass:
* for each .func entry in `funcs' start the insertion operation:
* search each line from the deck which has the suitable
* subcircuit nesting data.
* for tokens xxx equalling the funcname, replace xxx by xxx().
*/
for (f = funcs; f; f = f->next) {
for (j = 0; j < 16; j++)
sub_count[j] = 0;
card = deck;
for (; card; card = card->nextcard) {
char *new_str = NULL; /* string we assemble here */
char *curr_line = card->line;
char *firsttok_str;
if (*curr_line == '*')
continue;
/* determine nested depths of subcircuits */
if (ciprefix(".subckt", curr_line)) {
subckt_depth++;
sub_count[subckt_depth]++;
continue;
}
else if (ciprefix(".ends", curr_line)) {
subckt_depth--;
continue;
}
/* exclude any command inside .control ... .endc */
if (ciprefix(".control", curr_line)) {
skip_control++;
continue;
}
else if (ciprefix(".endc", curr_line)) {
skip_control--;
continue;
}
else if (skip_control > 0) {
continue;
}
/* if function is not at top level,
exclude lines which do not have the same subcircuit
nesting depth and number as found in f */
if (f->subckt_depth > 0) {
if (subckt_depth != f->subckt_depth)
continue;
if (sub_count[subckt_depth] != f->subckt_count)
continue;
}
/* remove first token, ignore it here, restore it later */
firsttok_str = gettok(&curr_line);
if (*curr_line == '\0') {
tfree(firsttok_str);
continue;
}
new_str = inp_functionalise_identifier(curr_line, f->funcname);
if (new_str == curr_line) {
tfree(firsttok_str);
continue;
}
/* restore first part of the line */
new_str = INPstrCat(firsttok_str, new_str, " ");
new_str = inp_remove_ws(new_str);
*card->line = '*';
/* Enter new line into deck */
insert_new_line(card, new_str, 0, card->linenum);
}
}
/* final memory clearance */
tfree(sub_count);
inp_delete_funcs(funcs);
}
/* append "()" to each 'identifier' in 'curr_line',
* unless already there */
static char *

Loading…
Cancel
Save