Check for number of nodes in an extra function getnumnodes()
This commit is contained in:
parent
e425d355c6
commit
7595d4a7e1
|
|
@ -126,6 +126,7 @@ libfte_la_SOURCES = \
|
|||
hpgl.h \
|
||||
inp.c \
|
||||
inp.h \
|
||||
inp_numnode.c \
|
||||
inpcom.c \
|
||||
inpcom.h \
|
||||
interp.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 <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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue