From daa3609e58c82ce0c14164ada39a77a5dcb93dd1 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Sep 2021 23:50:35 +0200 Subject: [PATCH] =?UTF-8?q?Enable=20RKM=20notation=20for=20R=20and=20C,=20?= =?UTF-8?q?when=20ngbehavior=20LT=20is=20selected.=20Add=202=20evaluation?= =?UTF-8?q?=20functions=20specific=20for=20R=20and=20C=20respectively.=20R?= =?UTF-8?q?=20has=20code=20letters=20L,=20R,=20K,=20M,=20G,=20T=20enabled.?= =?UTF-8?q?=20M=20here=20is=20Meg!=20C=20has=20code=20letters=20p,=20n,=20?= =?UTF-8?q?u=20or=20=C2=B5,=20m,=20F.=20F=20here=20is=20unity,=20femto=20i?= =?UTF-8?q?s=20not=20available,=20m=20is=20still=20milli!=20Two=20examples?= =?UTF-8?q?=20files=20show=20all=20cases.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/various/RKM-C-1.cir | 19 +++ examples/various/RKM-R-1.cir | 19 +++ src/include/ngspice/inpdefs.h | 3 +- src/spicelib/parser/inp2c.c | 2 +- src/spicelib/parser/inp2r.c | 2 +- src/spicelib/parser/inpeval.c | 250 ++++++++++++++++++++++++++++++++-- 6 files changed, 283 insertions(+), 12 deletions(-) create mode 100644 examples/various/RKM-C-1.cir create mode 100644 examples/various/RKM-R-1.cir diff --git a/examples/various/RKM-C-1.cir b/examples/various/RKM-C-1.cir new file mode 100644 index 000000000..7d51964a9 --- /dev/null +++ b/examples/various/RKM-C-1.cir @@ -0,0 +1,19 @@ +RKM Capacitors + +V1 2 0 1 +R1 2 1 4K7 +C1 1 0 4p7 +C2 1 0 4n7 +C3 1 0 4u7 +C4 1 0 4m7 +C5 1 0 4F7 +C6 1 0 47p3 +C7 1 0 470p +C8 1 0 4ยต76 tc1=1e-6 tc2=1e-9 dtemp=6 +C9 1 0 4m7 + +.control +show c +.endc + +.end diff --git a/examples/various/RKM-R-1.cir b/examples/various/RKM-R-1.cir new file mode 100644 index 000000000..c1126e785 --- /dev/null +++ b/examples/various/RKM-R-1.cir @@ -0,0 +1,19 @@ +RKM Resistors + +V1 1 0 1 +R1 1 0 4K7 +R2 1 0 4R7 +R3 1 0 R47 +R4 1 0 470R +R5 1 0 47K +R6 1 0 47K3 +R7 1 0 470K +R8 1 0 4M7 tc1=1e-6 tc2=1e-9 dtemp=6 +R9 1 0 4L7 +R10 1 0 470L + +.control +show r +.endc + +.end diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index 6de033ad6..94eb5ae19 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -116,7 +116,8 @@ char *INPerrCat(char *, char *); char *INPstrCat(char *, char, char *); char *INPerror(int); double INPevaluate(char **, int *, int); -double INPevaluateRKM(char **, int *, int); +double INPevaluateRKM_R(char **, int *, int); +double INPevaluateRKM_C(char **, int *, int); char *INPfindLev(char *, int *); char *INPgetMod(CKTcircuit *, char *, INPmodel **, INPtables *); char *INPgetModBin(CKTcircuit *, char *, INPmodel **, INPtables *, char *); diff --git a/src/spicelib/parser/inp2c.c b/src/spicelib/parser/inp2c.c index 0a1b12d51..7ef15766f 100644 --- a/src/spicelib/parser/inp2c.c +++ b/src/spicelib/parser/inp2c.c @@ -58,7 +58,7 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, struct card *current) /* enable reading values like 4u7 */ if (newcompat.lt) - val = INPevaluateRKM(&line, &error1, 1); /* [] */ + val = INPevaluateRKM_C(&line, &error1, 1); /* [] */ else val = INPevaluate(&line, &error1, 1); /* [] */ diff --git a/src/spicelib/parser/inp2r.c b/src/spicelib/parser/inp2r.c index 22d6088b1..587f940a5 100644 --- a/src/spicelib/parser/inp2r.c +++ b/src/spicelib/parser/inp2r.c @@ -67,7 +67,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, struct card *current) /* enable reading values like 4k7 */ if (newcompat.lt) - val = INPevaluateRKM(&line, &error1, 1); /* [] */ + val = INPevaluateRKM_R(&line, &error1, 1); /* [] */ else val = INPevaluate(&line, &error1, 1); /* [] */ diff --git a/src/spicelib/parser/inpeval.c b/src/spicelib/parser/inpeval.c index 5396e1551..5ba13fd8b 100644 --- a/src/spicelib/parser/inpeval.c +++ b/src/spicelib/parser/inpeval.c @@ -200,9 +200,9 @@ INPevaluate(char **line, int *error, int gobble) /* In addition to fcn INPevaluate() above, allow values like 4k7, - similar to the RKM code (used bei inp2c and inp2r) */ + similar to the RKM code (used by inp2r) */ double -INPevaluateRKM(char** line, int* error, int gobble) +INPevaluateRKM_R(char** line, int* error, int gobble) /* gobble: non-zero to gobble rest of token, zero to leave it alone */ { char* token; @@ -250,7 +250,7 @@ INPevaluateRKM(char** line, int* error, int gobble) sign = -1; } - if ((*here == '\0') || ((!(isdigit_c(*here))) && (*here != '.'))) { + if ((*here == '\0') || ((!(isdigit_c(*here))) && (*here != '.') && (*here != 'r'))) { /* number looks like just a sign! */ *error = 1; if (gobble) { @@ -363,6 +363,8 @@ INPevaluateRKM(char** line, int* error, int gobble) break; case 'r': case 'R': + case 'f': + case 'F': /* no femto when compat LT */ expo1 = expo1; hasmulti = TRUE; break; @@ -376,11 +378,6 @@ INPevaluateRKM(char** line, int* error, int gobble) expo1 = expo1 - 12; hasmulti = TRUE; break; - case 'f': - case 'F': - expo1 = expo1 - 15; - hasmulti = TRUE; - break; case 'm': case 'M': if (((here[1] == 'E') || (here[1] == 'e')) && @@ -397,10 +394,245 @@ INPevaluateRKM(char** line, int* error, int gobble) mantis *= 25.4; /* Mil */ } else { - expo1 = expo1 - 3; /* m, milli */ + expo1 = expo1 + 6; /* Meg as well */ hasmulti = TRUE; } break; + case 'l': + case 'L': + expo1 = expo1 - 3; /* m, milli */ + hasmulti = TRUE; + break; + default: + break; + } + + /* read a digit after multiplier */ + if (hasmulti) { + here++; + while (isdigit_c(*here)) { + deci = 10 * deci + *here - '0'; + expo3 = expo3 - 1; + here++; + } + mantis = mantis + deci * pow(10.0, (double)expo3); + } + + if (gobble) { + FREE(token); + } + else { + *line = here; + } + + return (sign * mantis * + pow(10.0, (double)(expo1 + expsgn * expo2))); +} + +/* In addition to fcn INPevaluate() above, allow values like 4k7, + similar to the RKM code (used by inp2r) */ +double +INPevaluateRKM_C(char** line, int* error, int gobble) +/* gobble: non-zero to gobble rest of token, zero to leave it alone */ +{ + char* token; + char* here; + double mantis; + double deci; + int expo1; + int expo2; + int expo3; + int sign; + int expsgn; + char* tmpline; + bool hasmulti = FALSE; + + /* setup */ + tmpline = *line; + + if (gobble) { + /* MW. INPgetUTok should be called with gobble=0 or it make + * errors in v(1,2) exp */ + *error = INPgetUTok(line, &token, 0); + if (*error) + return (0.0); + } + else { + token = *line; + *error = 0; + } + + mantis = 0; + deci = 0; + expo1 = 0; + expo2 = 0; + expo3 = 0; + sign = 1; + expsgn = 1; + + /* loop through all of the input token */ + here = token; + + if (*here == '+') + here++; /* plus, so do nothing except skip it */ + else if (*here == '-') { /* minus, so skip it, and change sign */ + here++; + sign = -1; + } + + if ((*here == '\0') || ((!(isdigit_c(*here))) && (*here != '.') && (*here != 'r'))) { + /* number looks like just a sign! */ + *error = 1; + if (gobble) { + FREE(token); + /* back out the 'gettok' operation */ + *line = tmpline; + } + return (0); + } + + while (isdigit_c(*here)) { + /* digit, so accumulate it. */ + mantis = 10 * mantis + *here - '0'; + here++; + } + + if (*here == '\0') { + /* reached the end of token - done. */ + if (gobble) { + FREE(token); + } + else { + *line = here; + } + return ((double)mantis * sign); + } + + if (*here == ':') { + /* ':' is no longer used for subcircuit node numbering + but is part of ternary function a?b:c + FIXME : subcircuit models still use ':' for model numbering + Will this hurt somewhere? */ + if (gobble) { + FREE(token); + } + else { + *line = here; + } + return ((double)mantis * sign); + } + + /* after decimal point! */ + if (*here == '.') { + /* found a decimal point! */ + here++; /* skip to next character */ + + if (*here == '\0') { + /* number ends in the decimal point */ + if (gobble) { + FREE(token); + } + else { + *line = here; + } + return ((double)mantis * sign); + } + + while (isdigit_c(*here)) { + /* digit, so accumulate it. */ + mantis = 10 * mantis + *here - '0'; + expo1 = expo1 - 1; + here++; + } + } + + /* now look for "E","e",etc to indicate an exponent */ + if ((*here == 'E') || (*here == 'e') || (*here == 'D') || (*here == 'd')) { + + /* have an exponent, so skip the e */ + here++; + + /* now look for exponent sign */ + if (*here == '+') + here++; /* just skip + */ + else if (*here == '-') { + here++; /* skip over minus sign */ + expsgn = -1; /* and make a negative exponent */ + /* now look for the digits of the exponent */ + } + + while (isdigit_c(*here)) { + expo2 = 10 * expo2 + *here - '0'; + here++; + } + } + + /* now we have all of the numeric part of the number, time to + * look for the scale factor (alphabetic) + */ + switch (*here) { + case 't': + case 'T': + expo1 = expo1 + 12; + hasmulti = TRUE; + break; + case 'g': + case 'G': + expo1 = expo1 + 9; + hasmulti = TRUE; + break; + case 'k': + case 'K': + expo1 = expo1 + 3; + hasmulti = TRUE; + break; + case 'u': + case 'U': + expo1 = expo1 - 6; + hasmulti = TRUE; + break; + case 'r': + case 'R': + case 'f': + case 'F': /* no femto when compat LT */ + expo1 = expo1; + hasmulti = TRUE; + break; + case 'n': + case 'N': + expo1 = expo1 - 9; + hasmulti = TRUE; + break; + case 'p': + case 'P': + expo1 = expo1 - 12; + hasmulti = TRUE; + break; + case 'm': + case 'M': + if (((here[1] == 'E') || (here[1] == 'e')) && + ((here[2] == 'G') || (here[2] == 'g'))) + { + expo1 = expo1 + 6; /* Meg */ + here += 2; + hasmulti = TRUE; + } + else if (((here[1] == 'I') || (here[1] == 'i')) && + ((here[2] == 'L') || (here[2] == 'l'))) + { + expo1 = expo1 - 6; + mantis *= 25.4; /* Mil */ + } + else { + expo1 = expo1 - 3; /* Meg as well */ + hasmulti = TRUE; + } + break; + case 'l': + case 'L': + expo1 = expo1 - 3; /* m, milli */ + hasmulti = TRUE; + break; default: break; }