Enable spice notations like 2n or 5m in filesource inputs
Tests that spaces or tabs are o.k.
This commit is contained in:
parent
2dbbb68e63
commit
40078850f4
|
|
@ -1,12 +1,12 @@
|
||||||
* input test
|
* input test
|
||||||
0 0 1
|
0 0 1m
|
||||||
10e-6 0.1 0.9
|
10u 0.1m 0.9m
|
||||||
20e-6 0.2 0.8
|
20u 0.2m 0.8m
|
||||||
30e-6 0.3 0.7
|
30u 0.3m 0.7m
|
||||||
40e-6 0.4 0.6
|
40u 0.4m 0.6m
|
||||||
50e-6 0.5 0.5
|
50u 0.5m 0.5m
|
||||||
60e-6 0.6 0.4
|
60u 0.6m 0.4m
|
||||||
70e-6 0.7 0.3
|
70u 0.7m 0.3m
|
||||||
80e-6 0.8 0.2
|
80u 0.8m 0.2m
|
||||||
90e-6 0.9 0.1
|
90u 0.9m 0.1m
|
||||||
100e-6 1 0
|
100u 1m 0
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ AUTHORS
|
||||||
27 Feb 2017 Marcel Hendrix
|
27 Feb 2017 Marcel Hendrix
|
||||||
23 JUL 2018 Holger Vogt
|
23 JUL 2018 Holger Vogt
|
||||||
11 Aug 2025 Holger Vogt
|
11 Aug 2025 Holger Vogt
|
||||||
|
01 Aug 2026 Holger Vogt
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
@ -55,8 +56,8 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
/*=== CONSTANTS ========================*/
|
/*=== CONSTANTS ========================*/
|
||||||
|
|
||||||
|
#define OK 0
|
||||||
|
#define FAIL 1
|
||||||
|
|
||||||
/*=== MACROS ===========================*/
|
/*=== MACROS ===========================*/
|
||||||
|
|
||||||
|
|
@ -104,13 +105,220 @@ typedef struct {
|
||||||
|
|
||||||
} Local_Data_t;
|
} Local_Data_t;
|
||||||
|
|
||||||
|
typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */
|
||||||
|
|
||||||
|
|
||||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
||||||
|
|
||||||
|
|
||||||
|
/*=== Static CNV_get_spice_value ROUTINE =============*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function takes as input a string token from a SPICE
|
||||||
|
deck and returns a floating point equivalent value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int cnv_get_spice_value(
|
||||||
|
char *str, /* IN - The value text e.g. 1.2K */
|
||||||
|
double *p_value ) /* OUT - The numerical value */
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/* the following were "int4" devices - jpm */
|
||||||
|
size_t len;
|
||||||
|
size_t i;
|
||||||
|
int n_matched;
|
||||||
|
|
||||||
|
line_t val_str;
|
||||||
|
|
||||||
|
/*char *suffix;*/
|
||||||
|
char c = ' ';
|
||||||
|
char c1;
|
||||||
|
|
||||||
|
double scale_factor;
|
||||||
|
double value;
|
||||||
|
|
||||||
|
|
||||||
|
/* Scan the input string looking for an alpha character that is not */
|
||||||
|
/* 'e' or 'E'. Such a character is assumed to be an engineering */
|
||||||
|
/* suffix as defined in the Spice 2G.6 user's manual. */
|
||||||
|
|
||||||
|
len = strlen(str);
|
||||||
|
if( len > (sizeof(val_str) - 1))
|
||||||
|
len = sizeof(val_str) - 1;
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
c = str[i];
|
||||||
|
if( isalpha_c(c) && (c != 'E') && (c != 'e') )
|
||||||
|
break;
|
||||||
|
else if( isspace_c(c) )
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
val_str[i] = c;
|
||||||
|
}
|
||||||
|
val_str[i] = '\0';
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine the scale factor */
|
||||||
|
|
||||||
|
if( (i >= len) || (! isalpha_c(c)) )
|
||||||
|
scale_factor = 1.0;
|
||||||
|
else {
|
||||||
|
|
||||||
|
if(isupper_c(c))
|
||||||
|
c = tolower_c(c);
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
scale_factor = 1.0e12;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
scale_factor = 1.0e9;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
scale_factor = 1.0e3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
scale_factor = 1.0e-6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
scale_factor = 1.0e-9;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
scale_factor = 1.0e-12;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
scale_factor = 1.0e-15;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
scale_factor = 1.0e-18;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
i++;
|
||||||
|
if(i >= len) {
|
||||||
|
scale_factor = 1.0e-3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c1 = str[i];
|
||||||
|
if(! isalpha_c(c1)) {
|
||||||
|
scale_factor = 1.0e-3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(islower_c(c1))
|
||||||
|
c1 = toupper_c(c1);
|
||||||
|
if(c1 == 'E')
|
||||||
|
scale_factor = 1.0e6;
|
||||||
|
else if(c1 == 'I')
|
||||||
|
scale_factor = 25.4e-6;
|
||||||
|
else
|
||||||
|
scale_factor = 1.0e-3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
scale_factor = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the numeric portion to a float and multiply by the */
|
||||||
|
/* scale factor. */
|
||||||
|
|
||||||
|
n_matched = sscanf(val_str,"%le",&value);
|
||||||
|
|
||||||
|
if(n_matched < 1) {
|
||||||
|
*p_value = 0.0;
|
||||||
|
return(FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
*p_value = value * scale_factor;
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*=== Static CNVgettok ROUTINE ================*/
|
||||||
|
/*
|
||||||
|
Get the next token from the input string. The input string pointer
|
||||||
|
is advanced to the following token and the token from the input
|
||||||
|
string is copied to malloced storage and a pointer to that storage
|
||||||
|
is returned. The original input string is undisturbed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static char *CNVgettok(char **s)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
char *buf; /* temporary storage to copy token into */
|
||||||
|
/*char *temp;*/ /* temporary storage to copy token into */
|
||||||
|
char *ret_str; /* storage for returned string */
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* allocate space big enough for the whole string */
|
||||||
|
|
||||||
|
buf = (char *) malloc(strlen(*s) + 1);
|
||||||
|
|
||||||
|
/* skip over any white space */
|
||||||
|
|
||||||
|
while(isspace_c(**s) || (**s == '=') ||
|
||||||
|
(**s == '(') || (**s == ')') || (**s == ','))
|
||||||
|
(*s)++;
|
||||||
|
|
||||||
|
/* isolate the next token */
|
||||||
|
|
||||||
|
switch(**s) {
|
||||||
|
|
||||||
|
case '\0': /* End of string found */
|
||||||
|
if(buf) free(buf);
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
|
||||||
|
default: /* Otherwise, we are dealing with a */
|
||||||
|
/* string representation of a number */
|
||||||
|
/* or a mess o' characters. */
|
||||||
|
i = 0;
|
||||||
|
while( (**s != '\0') &&
|
||||||
|
(! ( isspace_c(**s) || (**s == '=') ||
|
||||||
|
(**s == '(') || (**s == ')') ||
|
||||||
|
(**s == ',')
|
||||||
|
) ) ) {
|
||||||
|
buf[i] = **s;
|
||||||
|
i++;
|
||||||
|
(*s)++;
|
||||||
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip over white space up to next token */
|
||||||
|
|
||||||
|
while(isspace_c(**s) || (**s == '=') ||
|
||||||
|
(**s == '(') || (**s == ')') || (**s == ','))
|
||||||
|
(*s)++;
|
||||||
|
|
||||||
|
/* make a copy using only the space needed by the string length */
|
||||||
|
|
||||||
|
|
||||||
|
ret_str = (char *) malloc(strlen(buf) + 1);
|
||||||
|
ret_str = strcpy(ret_str,buf);
|
||||||
|
|
||||||
|
if(buf) free(buf);
|
||||||
|
|
||||||
|
return(ret_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
|
|
||||||
FUNCTION void cm_filesource()
|
FUNCTION void cm_filesource()
|
||||||
|
|
@ -277,13 +485,14 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
|
||||||
free(cpdel);
|
free(cpdel);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
t = strtod(cp, &cp2);
|
char *ncp = CNVgettok(&cp);
|
||||||
if (cp2 == cp) {
|
int ret = cnv_get_spice_value(ncp, &t);
|
||||||
|
free(ncp);
|
||||||
|
if (ret == FAIL) {
|
||||||
free(cpdel);
|
free(cpdel);
|
||||||
terr = MIF_TRUE;
|
terr = MIF_TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cp = cp2;
|
|
||||||
if (!PARAM_NULL(timescale))
|
if (!PARAM_NULL(timescale))
|
||||||
t *= PARAM(timescale);
|
t *= PARAM(timescale);
|
||||||
if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE)
|
if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE)
|
||||||
|
|
@ -295,7 +504,7 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
|
||||||
|
|
||||||
/* before storing, check if vector size is large enough.
|
/* before storing, check if vector size is large enough.
|
||||||
If not, add another 1000*size doubles */
|
If not, add another 1000*size doubles */
|
||||||
if (count > (int) loc->indata->vecallocated - size) {
|
if (count > (int) loc->indata->vecallocated - stepsize) {
|
||||||
loc->indata->vecallocated += (size_t) (size * 1000);
|
loc->indata->vecallocated += (size_t) (size * 1000);
|
||||||
void * const p = realloc(loc->indata->datavec,
|
void * const p = realloc(loc->indata->datavec,
|
||||||
sizeof(double) * loc->indata->vecallocated);
|
sizeof(double) * loc->indata->vecallocated);
|
||||||
|
|
@ -311,12 +520,13 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
while (*cp && (isspace_c(*cp) || *cp == ','))
|
while (*cp && (isspace_c(*cp) || *cp == ','))
|
||||||
++cp;
|
++cp;
|
||||||
d = strtod(cp, &cp2);
|
char *ncp = CNVgettok(&cp);
|
||||||
if (cp2 == cp) {
|
int ret = cnv_get_spice_value(ncp, &d);
|
||||||
|
free(ncp);
|
||||||
|
if (ret == FAIL) {
|
||||||
derr = MIF_TRUE;
|
derr = MIF_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cp = cp2;
|
|
||||||
if (i < amplscalesize)
|
if (i < amplscalesize)
|
||||||
d *= PARAM(amplscale[i]);
|
d *= PARAM(amplscale[i]);
|
||||||
if (i < amploffssize)
|
if (i < amploffssize)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue