diff --git a/src/frontend/inp.c b/src/frontend/inp.c index c12489ef8..a4c260df1 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -963,6 +963,10 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) /* Translate all SPICE 2G6 polynomial type sources */ deck->nextcard = ENHtranslate_poly(deck->nextcard); #endif + /* quote nodes of degmons, is required for parsing the a device node, + when [x] is part of a node nname. */ + int err = 0; + err = quote_degmons(deck->nextcard); line_free(deck->actualLine, FALSE); deck->actualLine = realdeck; diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 124e637ec..8d6a8b260 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -1100,6 +1100,9 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name, /* collect .agemodel data */ readdegparams(working); + /* Add degradation monitors to devices in X lines */ + adddegmonitors(working); + if (newcompat.lt && newcompat.a) ltspice_compat_a(working); if (newcompat.ps && newcompat.a) diff --git a/src/frontend/inpcom.h b/src/frontend/inpcom.h index 18fd33a48..502ec8379 100644 --- a/src/frontend/inpcom.h +++ b/src/frontend/inpcom.h @@ -14,5 +14,7 @@ extern char* inp_remove_ws(char* s); extern char* search_plain_identifier(char* str, const char* identifier); extern int readdegparams(struct card* deck); +extern int adddegmonitors(struct card* deck); +extern int quote_degmons(struct card* deck); #endif diff --git a/src/frontend/inpdeg.c b/src/frontend/inpdeg.c index 1ee7d0bd2..9ca563c2e 100644 --- a/src/frontend/inpdeg.c +++ b/src/frontend/inpdeg.c @@ -91,6 +91,10 @@ int readdegparams (struct card *deck) { ftok = dftok = gettok(&cut_line); /* parameter name */ f1 = gettok_char(&ftok, '=', FALSE, FALSE); + if (!f1) { + fprintf(stderr, "Error: bad.agemodel syntax in line\n % s", card->line); + controlled_exit(1); + } /* parameter value */ f2 = copy(ftok + 1); agemods[ageindex].paramnames[parno] = f1; @@ -116,4 +120,148 @@ int readdegparams (struct card *deck) { return 0; } +/* Look for an X line. + Check if the model in the x line is found in the model list agemodds. + Create a degradation monitor for each x line if model found. + Add the x instance name to the degmod name. + Add degmon line and its model line to the netlist.*/ +int adddegmonitors(struct card* deck) { + static int degmonno; + double tfuture = 315336e4; + int nodes = 4; + if (agemods[0].paramhash == NULL) + return 1; + for (; deck; deck = deck->nextcard) { + int skip_control = 0; + char* line = deck->line; + + if (*line == '*') { + continue; + } + /* there is no e source inside .control ... .endc */ + if (ciprefix(".control", line)) { + skip_control++; + continue; + } + else if (ciprefix(".endc", line)) { + skip_control--; + continue; + } + else if (skip_control > 0) { + continue; + } + if (*line == 'x') { + char *modname, *fournodes, *instname; + int ii; +// fprintf(stdout, "%.80s\n", line); + /* x instance model in subcircuit */ + /* get instance name */ + instname = gettok_instance(&line); + fournodes = line; + /* and 4 nodes */ + for (ii = 0; ii < nodes; ii++) + line = nexttok(line); + if (!line) { + /* Must be something else, not a 4-node MOS */ + continue; + } + fournodes = copy_substring(fournodes, line); + modname = gettok(&line); + + /*check if model is available in agemods */ + for (ii = 0; ii < DEGMODMAX; ii++) { + if (agemods[ii].devmodel) { + if (cieq(modname, agemods[ii].devmodel)) { +// fprintf(stdout, "device model %s found as no. %d\n\n", modname, ii); + /* get the channel length */ + char* lpos = strstr(line, "l="); + if (!lpos) { + fprintf(stderr, "Error, l not found in device %s \n\n", deck->line); + return 1; + } + char* clength = gettok(&lpos); + /* Now add a degradation monitor like + adegmon1 %v([z a vss vss]) mon degmon1 + .model degmon1 degmon (tfuture=3153360000 l=0.15e-6 devmod="sg13_lv_nmos") + */ + char* aline = tprintf("adegmon%d_%s %%v([%s]) mon%d degmon%d\n", + degmonno, instname, fournodes, degmonno, degmonno); + char* mline = tprintf(".model degmon%d degmon (tfuture=%e %s devmod=\"%s\"\n", + degmonno, tfuture, clength, modname); + tfree(clength); + insert_new_line(deck, aline, 0, deck->linenum_orig, deck->linesource); + insert_new_line(deck, mline, 0, deck->linenum_orig, deck->linesource); + degmonno++; + break; + } + } + else { +// fprintf(stderr, "No model found for device %.80s \n\n", deck->line); + break; + } + } + tfree(fournodes); + tfree(modname); + tfree(instname); + } + } + return 0; +} + +int quote_degmons(struct card* deck) { + for (; deck; deck = deck->nextcard) { + int skip_control = 0; + + char* line = deck->line; + + if (*line == '*') { + continue; + } + /* there is no e source inside .control ... .endc */ + if (ciprefix(".control", line)) { + skip_control++; + continue; + } + else if (ciprefix(".endc", line)) { + skip_control--; + continue; + } + else if (skip_control > 0) { + continue; + } + if (*line == 'a' && strstr(line, "adegmon")) { + char allnodes[1024]; + allnodes[0] = '\0'; + int ii, nodes = 4; + char* newnodes, *instname; + instname = gettok_instance(&line); + /* skip %v */ + line = nexttok(line); + char* deltoken; + char* nodetoken = deltoken = gettok_char(&line, ']', false, true); + if (!nodetoken) + break; + /* go beyond '[' */ + nodetoken++; + for (ii = 0; ii < nodes; ii++) { + char* nexttoken = gettok(&nodetoken); + sprintf(allnodes, "%s \"%s\"", allnodes, nexttoken); + if (!nexttoken) + break; + tfree(nexttoken); + } + if (!line || eq(line, "")) { + /* Must be something else, not a 4-node MOS */ + continue; + } + newnodes = tprintf("%s %%v [ %s %s", instname, allnodes, line); + + tfree(deltoken); + tfree(instname); + tfree(deck->line); + deck->line = newnodes; + } + } + return 0; +}