From 7595d4a7e1acb2a7372ef6ddd05510884de5b7b5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 20 Feb 2021 18:42:02 +0100 Subject: [PATCH] Check for number of nodes in an extra function getnumnodes() --- src/frontend/Makefile.am | 1 + src/frontend/inp_numnode.c | 210 +++++++++++++++++++++++++++++++++++++ src/frontend/inpcom.c | 19 ++-- visualc/vngspice.vcxproj | 1 + 4 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 src/frontend/inp_numnode.c diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index 2ebd79e19..252e0db68 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -126,6 +126,7 @@ libfte_la_SOURCES = \ hpgl.h \ inp.c \ inp.h \ + inp_numnode.c \ inpcom.c \ inpcom.h \ interp.c \ diff --git a/src/frontend/inp_numnode.c b/src/frontend/inp_numnode.c new file mode 100644 index 000000000..75c710ce2 --- /dev/null +++ b/src/frontend/inp_numnode.c @@ -0,0 +1,210 @@ +/********** +Copyright 2021 The ngspice team. All rights reserved. +Author: 2021 Holger Vogt +3-clause BSD +**********/ + +/* return the number of nodes */ + +#include "ngspice/ngspice.h" +#include "ngspice/inpdefs.h" +#include "ngspice/compatmode.h" + +extern char* inp_remove_ws(char* s); + +int getnumnodes(struct card *deck); + + +int +getnumnodes(struct card* deck) +{ + int skip_control = 0; + struct card* card; + + for (card = deck; card; card = card->nextcard) { + + int i, j, k; + char* name[12]; + char nam_buf[128]; + bool area_found = FALSE; + char* 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; + } + + switch (*curr_line) { + case '*': + case ' ': + case '\t': + case 'x': + case '$': + continue; + break; + } + + /* catch all models, including their scope */ + if (ciprefix(".model", curr_line)) + { } + + switch (*curr_line) { + case '.': + continue; + break; + + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'l': + case 'r': + case 'v': + case 'w': + card->nunodes = 2; + break; + + case 'j': + case 'u': + case 'z': + card->nunodes = 3; + break; + + case 'o': + case 's': + case 't': + case 'y': + card->nunodes = 4; + break; + + case 'm': /* recognition of 4, 5, 6, or 7 nodes for SOI devices needed + */ + { + i = 0; + char* cc, * ccfree; + /* we have 3 or 4 terminals with compatmode ps */ + if (newcompat.ps) { + char* token = curr_line; + token = nexttok(token); /* skip device name */ + token = nexttok(token); /* skip drain node */ + token = nexttok(token); /* skip gate node */ + token = nexttok(token); /* skip source node */ + if (token && *token == '[') /* bulk node starts with [ */ + card->nunodes = 4; + else + card->nunodes = 3; + break; + } + cc = copy(curr_line); + /* required to make m= 1 a single token m=1 */ + ccfree = cc = inp_remove_ws(cc); + /* find the first token with "off" or "=" in the line*/ + while ((i < 20) && (*cc != '\0')) { + char* inst = gettok_instance(&cc); + strncpy(nam_buf, inst, sizeof(nam_buf) - 1); + txfree(inst); + if (strstr(nam_buf, "off") || strchr(nam_buf, '=') || strstr(nam_buf, "tnodeout") || strstr(nam_buf, "thermal")) + break; + i++; + } + tfree(ccfree); + card->nunodes = i - 2; + break; + } + case 'p': /* recognition of up to 100 cpl nodes */ + i = j = 0; + /* find the last token in the line*/ + while ((i < 100) && (*curr_line != '\0')) { + char* tmp_inst = gettok_instance(&curr_line); + strncpy(nam_buf, tmp_inst, 32); + tfree(tmp_inst); + if (strchr(nam_buf, '=')) + j++; + i++; + } + if (i == 100) + return 0; + card->nunodes = i - j - 2; + break; + case 'q': /* recognition of 3, 4 or 5 terminal bjt's needed */ + /* QXXXXXXX NC NB NE MNAME + * */ + /* 12 tokens maximum */ + { + char* cc, * ccfree; + i = j = 0; + cc = copy(curr_line); + /* required to make m= 1 a single token m=1 */ + ccfree = cc = inp_remove_ws(cc); + while ((i < 12) && (*cc != '\0')) { + char* comma; + name[i] = gettok_instance(&cc); + if (strstr(name[i], "off") || strchr(name[i], '=')) + j++; +#ifdef CIDER + if (strstr(name[i], "save") || strstr(name[i], "print")) + j++; +#endif + /* If we have IC=VBE, VCE instead of IC=VBE,VCE we need to inc + * j */ + if ((comma = strchr(name[i], ',')) != NULL && + (*(++comma) == '\0')) + j++; + /* If we have IC=VBE , VCE ("," is a token) we need to inc j + */ + if (eq(name[i], ",")) + j++; + i++; + } + tfree(ccfree); + i--; + area_found = FALSE; + for (k = i; k > i - j - 1; k--) { + bool only_digits = TRUE; + char* nametmp = name[k]; + /* MNAME has to contain at least one alpha character. AREA may + be assumed if we have a token with only digits, and where + the previous token does not end with a ',' */ + while (*nametmp) { + if (isalpha_c(*nametmp) || (*nametmp == ',')) + only_digits = FALSE; + nametmp++; + } + if (only_digits && (strchr(name[k - 1], ',') == NULL)) + area_found = TRUE; + } + for (k = i; k >= 0; k--) + tfree(name[k]); + if (area_found) { + card->nunodes = i - j - 2; + } + else { + card->nunodes = i - j - 1; + } + break; + } + + case 'k': + card->nunodes = 0; + break; + + default: + card->nunodes = 0; + break; + } + } + return 0; +} + diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 85fb84d59..fba335519 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -101,6 +101,7 @@ struct func_temper }; extern void line_free_x(struct card *deck, bool recurse); +extern int getnumnodes(struct card* deck); /* Collect information for dynamic allocation of numparam arrays */ /* number of lines in input deck */ @@ -133,7 +134,7 @@ static void inp_reorder_params( static int inp_split_multi_param_lines(struct card *deck, int line_number); static void inp_sort_params(struct card *param_cards, struct card *card_bf_start, struct card *s_c, struct card *e_c); -static char *inp_remove_ws(char *s); +char *inp_remove_ws(char *s); static void inp_compat(struct card *deck); static void inp_bsource_compat(struct card *deck); static bool inp_temper_compat(struct card *card); @@ -210,7 +211,7 @@ static void inp_poly_err(struct card *deck); /* insert a new card, just behind the given card */ static struct card *insert_new_line( - struct card *card, char *line, int linenum, int linenum_orig, int numnodes) + struct card *card, char *line, int linenum, int linenum_orig, int nunodes) { struct card *x = TMALLOC(struct card, 1); @@ -220,7 +221,7 @@ static struct card *insert_new_line( x->line = line; x->linenum = linenum; x->linenum_orig = linenum_orig; - x->numnodes = numnodes; + x->nunodes = nunodes; x->level = card ? card->level : NULL; if (card) @@ -464,7 +465,7 @@ static void inp_stitch_continuation_lines(struct card *working) } else { prev->actualLine = - insert_new_line(NULL, s, prev->linenum, 0, prev->numnodes); + insert_new_line(NULL, s, prev->linenum, 0, prev->nunodes); prev->actualLine->level = prev->level; prev->actualLine->nextcard = working; } @@ -794,6 +795,8 @@ struct card *inp_readall(FILE *fp, const char *dir_name, struct nscope *root = inp_add_levels(working); + getnumnodes(working); + inp_fix_for_numparam(subckt_w_params, working); inp_remove_excess_ws(working); @@ -2871,7 +2874,7 @@ static char *inp_fix_subckt(struct names *subckt_w_params, char *s) * thats odd and very naive business */ -static char *inp_remove_ws(char *s) +char *inp_remove_ws(char *s) { char *x = s; char *d = s; @@ -3058,7 +3061,7 @@ static struct card *expand_section_ref(struct card *c, const char *dir_name) struct card *t = section_def; for (; t; t = t->nextcard) { c = insert_new_line( - c, copy(t->line), t->linenum, t->linenum_orig, t->numnodes); + c, copy(t->line), t->linenum, t->linenum_orig, t->nunodes); if (t == section_def) { c->line[0] = '*'; c->line[1] = '<'; @@ -7287,6 +7290,10 @@ static int inp_vdmos_model(struct card *deck) tfree(instmodname); return 1; } + else if (curr_line[0] == 'm' && newcompat.lt) { + /* VDMOS in LTSPICE have 4 nodes with S and B being equal. + So reduce the number of nodes to 3. */ + } } return 0; } diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index cedc9b4d0..461840332 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -1487,6 +1487,7 @@ +