Enable RKM notation also for inductors (e.g. 1u2 for 1.2u)

This commit is contained in:
Holger Vogt 2022-02-07 16:00:29 +01:00
parent 640fa7e17b
commit 0eb272243f
4 changed files with 250 additions and 2 deletions

View File

@ -2458,6 +2458,12 @@ static int is_a_modelname(char *s, const char* line)
if (*evalrc == '\0' && !error)
return FALSE;
}
if (newcompat.lt && *line == 'l') {
evalrc = s;
INPevaluateRKM_L(&evalrc, &error, 0);
if (*evalrc == '\0' && !error)
return FALSE;
}
/* first character of model name is character from alphabet */
if (isalpha_c(s[0]))
return TRUE;

View File

@ -118,6 +118,7 @@ char *INPerror(int);
double INPevaluate(char **, int *, int);
double INPevaluateRKM_R(char **, int *, int);
double INPevaluateRKM_C(char **, int *, int);
double INPevaluateRKM_L(char **, int *, int);
char *INPfindLev(char *, int *);
char *INPgetMod(CKTcircuit *, char *, INPmodel **, INPtables *);
char *INPgetModBin(CKTcircuit *, char *, INPmodel **, INPtables *, char *);

View File

@ -8,6 +8,7 @@ Author: 1988 Thomas L. Quarles
#include "ngspice/inpdefs.h"
#include "ngspice/inpmacs.h"
#include "ngspice/fteext.h"
#include "ngspice/compatmode.h"
#include "inpxx.h"
void INP2L(CKTcircuit *ckt, INPtables * tab, struct card *current)
@ -54,8 +55,14 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, struct card *current)
INPtermInsert(ckt, &nname1, tab, &node1);
INPgetNetTok(&line, &nname2, 1);
INPtermInsert(ckt, &nname2, tab, &node2);
val = INPevaluate(&line, &error1, 1);
// val = INPevaluate(&line, &error1, 1);
/* enable reading values like 4u7 */
if (newcompat.lt)
val = INPevaluateRKM_L(&line, &error1, 1); /* [<val>] */
else
val = INPevaluate(&line, &error1, 1); /* [<val>] */
saveline = line;
INPgetNetTok(&line, &model, 1);

View File

@ -661,3 +661,237 @@ INPevaluateRKM_C(char** line, int* error, int gobble)
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_L(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':
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 'f':
case 'F':
expo1 = expo1 - 15;
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;
}
/* 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)));
}