diff --git a/src/frontend/com_commands.h b/src/frontend/com_commands.h index 38d959075..5ed96f87a 100644 --- a/src/frontend/com_commands.h +++ b/src/frontend/com_commands.h @@ -5,6 +5,7 @@ void com_showmod(wordlist *wl); void com_show(wordlist *wl); void com_alter(wordlist *wl); void com_altermod(wordlist *wl); +void com_alterparam(wordlist *wl); void com_meas(wordlist *wl); void com_sysinfo(wordlist *wl); void com_check_ifparm(wordlist *wl); diff --git a/src/frontend/commands.c b/src/frontend/commands.c index caf2877d4..40736f329 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -373,6 +373,10 @@ struct comm spcp_coms[] = { { 040, 040, 040, 040 }, E_DEFHMASK, 0, LOTS, NULL, "devspecs : parmname value : Alter model parameters." } , + { "alterparam", com_alterparam, TRUE, FALSE, + { 040, 040, 040, 040 }, E_DEFHMASK, 1, LOTS, + NULL, + "devspecs : parmname value : Alter .param parameters." }, { "resume", com_resume, TRUE, FALSE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0, NULL, diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 1819897b5..708c6110b 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -1204,6 +1204,139 @@ com_edit(wordlist *wl) } +/* alter a parameter, either + subckt param: alterparam subcktname pname=vpval + global .param: alterparam pname=pval + Changes params in mc_deck + To become effective, 'mc_source' has to be called after 'alterparam' */ +void +com_alterparam(wordlist *wl) +{ + struct card *dd; + char *pname, *pval, *tmp, *subcktname = NULL, *linein, *linefree, *s; + bool found = FALSE; + + if (!mc_deck) { + fprintf(cp_err, "Error: No internal deck available\n"); + return; + } + linefree = wl_flatten(wl); + linein = skip_ws(linefree); + s = tmp = gettok_char(&linein, '=', FALSE, FALSE); + if (!s) { + fprintf(cp_err, "\nError: Wrong format in line 'alterparam %s'\n command 'alterparam' skipped\n", linefree); + tfree(linefree); + return; + } + linein++; /* skip the '=' */ + pval = gettok(&linein); + subcktname = gettok(&tmp); + if (!pval || !subcktname) { + fprintf(cp_err, "\nError: Wrong format in line 'alterparam %s'\n command 'alterparam' skipped\n", linefree); + tfree(pval); + tfree(subcktname); + tfree(linefree); + return; + } + pname = gettok(&tmp); + if (!pname) { + pname = subcktname; + subcktname = NULL; + } + tfree(linefree); + tfree(s); + for (dd = mc_deck->nextcard; dd; dd = dd->nextcard) { + char *curr_line = dd->line; + /* alterparam subcktname pname=vpval + Parameters from within subcircuit are no longer .param lines, but have been added to + the .subckt line as pname=paval and to the x line as pval. pval in the x line takes + precedence when subciruit is called, so has to be replaced here. + Find subcircuit with subcktname. + After params: Count the number of parameters (notok) until parameter pname is found. + When found, search for x-line with subcktname. + Replace parameter value number notok by pval. + */ + if (subcktname) { + /* find subcircuit */ + if (ciprefix(".subckt", curr_line)) { + curr_line = nexttok(curr_line); /* skip .subckt */ + char *sname = gettok(&curr_line); + if (eq(sname, subcktname)) { + tfree(sname); + curr_line = strstr(curr_line, "params:"); + curr_line = skip_non_ws(curr_line); /* skip params: */ + /* string to search for */ + char *pname_eq = tprintf("%s=", pname); + int notok = 0; + while (*curr_line) { + char *token = gettok(&curr_line); + if (ciprefix(pname_eq, token)) { + tfree(token); + found = TRUE; + break; + } + notok++; + tfree(token); + } + tfree(pname_eq); + if (found) { + /* find x line with same subcircuit name */ + struct card *xx; + char *bsubb = tprintf(" %s ", subcktname); + for (xx = mc_deck->nextcard; xx; xx = xx->nextcard) { + char *xline = xx->line; + if (*xline == 'x') { + xline = strstr(xline, bsubb); + if (xline) { + xline = nexttok(xline); /* skip subcktname */ + int ii; + for (ii = 0; ii < notok; ii++) + xline = nexttok(xline); /* skip parameter values */ + char *beg = copy_substring(xx->line, xline); + xline = nexttok(xline); /* skip parameter value to be replaced */ + char *newline = tprintf("%s %s %s", beg, pval, xline); + tfree(xx->line); + xx->line = newline; + tfree(beg); + } + else + continue; + } + } + tfree(bsubb); + } + } + else { + tfree(sname); + continue; + } + } + } /* subcktname */ + /* alterparam pname=vpval */ + else { + if (ciprefix(".para", curr_line)) { + curr_line = nexttok(curr_line); /* skip .param */ + char *name = gettok_char(&curr_line, '=', FALSE, FALSE); + if (eq(name, pname)) { + curr_line = dd->line; + char *start = gettok_char(&curr_line, '=', TRUE, FALSE); + tfree(dd->line); + dd->line = tprintf("%s%s", start, pval); + found = TRUE; + tfree(start); + } + tfree(name); + } + } + } + if (!found) + fprintf(cp_err, "\nError: parameter '%s' not found,\n command 'alterparam' skipped\n", pname); + tfree(pval); + tfree(pname); + tfree(subcktname); +} + + static bool doedit(char *filename) {