new compatibility handling with struct compat newcompat:

simplify the compatibility handling, better readability
make it easily extendable
add new flag 'ki' for KiCad compatibility
This commit is contained in:
Holger Vogt 2020-07-25 22:11:27 +02:00
parent 50c7625082
commit 4f1da9b5e1
5 changed files with 60 additions and 76 deletions

View File

@ -101,8 +101,6 @@ struct func_temper
extern void line_free_x(struct card *deck, bool recurse); extern void line_free_x(struct card *deck, bool recurse);
COMPATMODE_T inp_compat_mode;
/* Collect information for dynamic allocation of numparam arrays */ /* Collect information for dynamic allocation of numparam arrays */
/* number of lines in input deck */ /* number of lines in input deck */
int dynmaxline; /* inpcom.c 1529 */ int dynmaxline; /* inpcom.c 1529 */
@ -523,37 +521,46 @@ char *find_back_assignment(const char *p, const char *start)
/* Set a compatibility flag. /* Set a compatibility flag.
Currently available are flags for: Currently available are flags for:
- ngspice (standard) - LTSPICE, HSPICE, Spice3, PSPICE, KiCad
- a commercial simulator
- Spice3
- all compatibility stuff
*/ */
static COMPATMODE_T ngspice_compat_mode(void) struct compat newcompat;
static void new_compat_mode(void)
{ {
char behaviour[80]; char behaviour[80];
if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) { if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) {
if (strcasecmp(behaviour, "all") == 0) if (strstr(behaviour, "hs"))
return COMPATMODE_ALL; newcompat.hs = TRUE;
if (strcasecmp(behaviour, "hs") == 0) else
return COMPATMODE_HS; newcompat.hs = FALSE;
if (strcasecmp(behaviour, "ps") == 0) }
return COMPATMODE_PS; if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) {
if (strcasecmp(behaviour, "lt") == 0) if (strstr(behaviour, "ps"))
return COMPATMODE_LT; newcompat.ps = TRUE;
if (strcasecmp(behaviour, "ltps") == 0) else
return COMPATMODE_LTPS; newcompat.ps = FALSE;
if (strcasecmp(behaviour, "psa") == 0) }
return COMPATMODE_PSA; if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) {
if (strcasecmp(behaviour, "lta") == 0) if (strstr(behaviour, "lt"))
return COMPATMODE_LTA; newcompat.lt = TRUE;
if (strcasecmp(behaviour, "ltpsa") == 0) else
return COMPATMODE_LTPSA; newcompat.lt = FALSE;
if (strcasecmp(behaviour, "spice3") == 0) }
return COMPATMODE_SPICE3; if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) {
if (strstr(behaviour, "ki"))
newcompat.ki = TRUE;
else
newcompat.ki = FALSE;
}
if (cp_getvar("ngbehavior", CP_STRING, behaviour, sizeof(behaviour))) {
if (strstr(behaviour, "a"))
newcompat.a = TRUE;
else
newcompat.a = FALSE;
}
if (newcompat.hs && newcompat.ps) {
fprintf(stderr, "Warning: hs and ps compatibility are mutually exclusive, switch to ps!\n");
newcompat.hs = FALSE;
} }
return COMPATMODE_ALL;
} }
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
@ -600,7 +607,8 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
struct inp_read_t rv; struct inp_read_t rv;
num_libraries = 0; num_libraries = 0;
inp_compat_mode = ngspice_compat_mode(); /* set the members of the compatibility structure */
new_compat_mode();
rv = inp_read(fp, 0, dir_name, comfile, intfile); rv = inp_read(fp, 0, dir_name, comfile, intfile);
cc = rv.cc; cc = rv.cc;
@ -631,14 +639,10 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
/* some syntax checks, including title line */ /* some syntax checks, including title line */
inp_check_syntax(cc); inp_check_syntax(cc);
if (inp_compat_mode == COMPATMODE_LTA) if (newcompat.lt && newcompat.a)
ltspice_compat_a(working); ltspice_compat_a(working);
else if (inp_compat_mode == COMPATMODE_PSA) if (newcompat.ps && newcompat.a)
pspice_compat_a(working); pspice_compat_a(working);
else if (inp_compat_mode == COMPATMODE_LTPSA) {
ltspice_compat_a(working);
pspice_compat_a(working);
}
struct nscope *root = inp_add_levels(working); struct nscope *root = inp_add_levels(working);
@ -689,7 +693,7 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
inp_poly_err(working); inp_poly_err(working);
#endif #endif
bool expr_w_temper = FALSE; bool expr_w_temper = FALSE;
if (inp_compat_mode != COMPATMODE_SPICE3) { if (!newcompat.s3) {
/* Do all the compatibility stuff here */ /* Do all the compatibility stuff here */
working = cc->nextcard; working = cc->nextcard;
inp_meas_current(working); inp_meas_current(working);
@ -914,10 +918,7 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
/* new style .lib entries handling is in expand_section_references() /* new style .lib entries handling is in expand_section_references()
*/ */
if (ciprefix(".lib", buffer)) if (ciprefix(".lib", buffer))
if (inp_compat_mode == COMPATMODE_PS || if (newcompat.lt || newcompat.ps) {
inp_compat_mode == COMPATMODE_PSA ||
inp_compat_mode == COMPATMODE_LTPS ||
inp_compat_mode == COMPATMODE_LTPSA) {
/* compatibility mode, /* compatibility mode,
* this is neither a libray section definition nor a * this is neither a libray section definition nor a
* reference interpret as old style .lib <file name> (no lib * reference interpret as old style .lib <file name> (no lib
@ -997,14 +998,10 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
} }
if (newcard) { if (newcard) {
if (inp_compat_mode == COMPATMODE_LT) if (newcompat.lt && !newcompat.a)
newcard = ltspice_compat(newcard); newcard = ltspice_compat(newcard);
else if (inp_compat_mode == COMPATMODE_PS) if (newcompat.ps && !newcompat.a)
newcard = pspice_compat(newcard); newcard = pspice_compat(newcard);
else if (inp_compat_mode == COMPATMODE_LTPS) {
newcard = ltspice_compat(newcard);
newcard = pspice_compat(newcard);
}
int line_number_inc = 1; int line_number_inc = 1;
end->nextcard = newcard; end->nextcard = newcard;
@ -1209,9 +1206,7 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
insert_new_line( insert_new_line(
cc, copy("* gnd is not set to 0 automatically "), 1, 0); cc, copy("* gnd is not set to 0 automatically "), 1, 0);
if (inp_compat_mode == COMPATMODE_ALL || if (!newcompat.lt && !newcompat.ps && !newcompat.s3) {
inp_compat_mode == COMPATMODE_HS ||
inp_compat_mode == COMPATMODE_NATIVE) {
/* process all library section references */ /* process all library section references */
expand_section_references(cc, dir_name); expand_section_references(cc, dir_name);
} }
@ -2506,9 +2501,7 @@ static void inp_stripcomments_line(char *s, bool cs)
break; break;
} }
/* outside of .control section, and not in PS mode */ /* outside of .control section, and not in PS mode */
else if (!cs && (c == '$') && inp_compat_mode != COMPATMODE_PS && else if (!cs && (c == '$') && !newcompat.ps) {
inp_compat_mode != COMPATMODE_LTPS &&
inp_compat_mode != COMPATMODE_LTPSA) {
/* The character before '&' has to be ',' or ' ' or tab. /* The character before '&' has to be ',' or ' ' or tab.
A valid numerical expression directly before '$' is not yet A valid numerical expression directly before '$' is not yet
supported. */ supported. */
@ -2779,11 +2772,7 @@ static void inp_fix_for_numparam(
inp_change_quotes(c->line); inp_change_quotes(c->line);
if ((inp_compat_mode == COMPATMODE_ALL) || if (!newcompat.hs && !newcompat.s3)
(inp_compat_mode == COMPATMODE_PS) ||
(inp_compat_mode == COMPATMODE_PSA) ||
(inp_compat_mode == COMPATMODE_LTPS) ||
(inp_compat_mode == COMPATMODE_LTPSA))
if (ciprefix(".subckt", c->line) || ciprefix("x", c->line)) { if (ciprefix(".subckt", c->line) || ciprefix("x", c->line)) {
/* remove params: */ /* remove params: */
char *str_ptr = strstr(c->line, "params:"); char *str_ptr = strstr(c->line, "params:");

View File

@ -182,8 +182,7 @@ findsubname(dico_t *dico, DSTRINGPTR dstr_p)
char *t; char *t;
entry_t *entry; entry_t *entry;
/* check for known subckt name */ /* check for known subckt name */
if (inp_compat_mode == COMPATMODE_PS || inp_compat_mode == COMPATMODE_PSA if (newcompat.ps)
|| inp_compat_mode == COMPATMODE_LTPS || inp_compat_mode == COMPATMODE_LTPSA)
for (t = p; alfanumps(*t); t++) for (t = p; alfanumps(*t); t++)
; ;
else else

View File

@ -253,7 +253,7 @@ initdico(dico_t *dico)
dico->inst_symbols = NULL; /* instance qualified are lazily allocated */ dico->inst_symbols = NULL; /* instance qualified are lazily allocated */
if (inp_compat_mode == COMPATMODE_HS) if (newcompat.hs)
dico->hs_compatibility = 1; dico->hs_compatibility = 1;
else else
dico->hs_compatibility = 0; dico->hs_compatibility = 0;

View File

@ -3,19 +3,17 @@
#include "ngspice/config.h" #include "ngspice/config.h"
typedef enum { struct compat
COMPATMODE_NATIVE = 0, {
COMPATMODE_HS = 1, bool hs;
COMPATMODE_SPICE3 = 2, bool s3;
COMPATMODE_ALL = 3, bool all;
COMPATMODE_PS = 4, bool ps;
COMPATMODE_PSA = 5, bool lt;
COMPATMODE_LT = 6, bool ki;
COMPATMODE_LTA = 7, bool a;
COMPATMODE_LTPS = 8, };
COMPATMODE_LTPSA = 9
} COMPATMODE_T ;
extern COMPATMODE_T inp_compat_mode; extern struct compat newcompat;
#endif #endif

View File

@ -77,9 +77,7 @@ double
PTpwr(double arg1, double arg2) PTpwr(double arg1, double arg2)
{ {
/* if PSPICE device is evaluated */ /* if PSPICE device is evaluated */
if (arg1 == 0.0 && arg2 < 0.0 && if (arg1 == 0.0 && arg2 < 0.0 && newcompat.ps)
(inp_compat_mode == COMPATMODE_PS || inp_compat_mode == COMPATMODE_PSA
|| inp_compat_mode == COMPATMODE_LTPS || inp_compat_mode == COMPATMODE_LTPSA))
arg1 += PTfudge_factor; arg1 += PTfudge_factor;
if (arg1 < 0.0) if (arg1 < 0.0)