Check for number of nodes in an extra function getnumnodes()

This commit is contained in:
Holger Vogt 2021-02-20 18:42:02 +01:00
parent e425d355c6
commit 7595d4a7e1
4 changed files with 225 additions and 6 deletions

View File

@ -126,6 +126,7 @@ libfte_la_SOURCES = \
hpgl.h \
inp.c \
inp.h \
inp_numnode.c \
inpcom.c \
inpcom.h \
interp.c \

210
src/frontend/inp_numnode.c Normal file
View File

@ -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 <NS> <NT> MNAME <AREA> <OFF> <IC=VBE, VCE>
* <TEMP=T> */
/* 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;
}

View File

@ -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;
}

View File

@ -1487,6 +1487,7 @@
<ClCompile Include="..\src\frontend\init.c" />
<ClCompile Include="..\src\frontend\inp.c" />
<ClCompile Include="..\src\frontend\inpcom.c" />
<ClCompile Include="..\src\frontend\inp_numnode.c" />
<ClCompile Include="..\src\frontend\interp.c" />
<ClCompile Include="..\src\frontend\inventory.c" />
<ClCompile Include="..\src\frontend\linear.c" />