par('expression')

This commit is contained in:
h_vogt 2010-07-10 11:27:57 +00:00
parent 7d6abb2fde
commit fe2d079b31
5 changed files with 353 additions and 4 deletions

View File

@ -1,3 +1,8 @@
2010-07-10 Holger Vogt
* com_measure2.c: allow variables v(n1)=v(n2)
* inpcom.c: par('expression') in .four, .plot, .print, .meas, .save
* string.c, ngspice.h: new fcn gettok_iv()
2010-07-09 Robert Larice
* src/frontend/spiceif.c ,
* src/spicelib/analysis/tfanal.c ,

View File

@ -299,7 +299,7 @@ int measure_extract_variables( char *line )
char *item ; /* parsing item */
char *measure ; /* measure keyword */
char *analysis ; /* analysis option */
char *variable ; /* variable to trace */
char *variable, *variable2 ; /* variable to trace */
wordlist *measure_var ; /* wordlist of measurable */
ANALYSIS_TYPE_T op ; /* measure function type */
@ -326,16 +326,27 @@ int measure_extract_variables( char *line )
op = measure_function_type(item) ;
if( op != AT_UNKNOWN ){
/* We have a variable/complex variable coming next */
variable = gettok(&line) ;
variable = gettok_iv(&line) ;
variable2 = NULL;
if (*line == '=') variable2 = gettok_iv(&line) ;
if( variable ){
len = strlen(item) ;
if( item[len-1] == '=' ){
} else {
/* We may have something like V(n1)=1
or v(n1)=2 , same with i() */
measure_var = gettoks(variable) ;
com_save2(measure_var, analysis);
status = FALSE;
}
}
if( variable2 ){
/* We may have something like v(n1)=v(n2)
v(n2) is handled here, same with i() */
measure_var = gettoks(variable2) ;
com_save2(measure_var, analysis);
status = FALSE;
}
}
}
} while(line && *line) ;

View File

@ -3580,9 +3580,10 @@ inp_split_multi_param_lines( struct line *deck, int line_num )
static void inp_compat(struct line *deck)
{
char *str_ptr, *cut_line, *title_tok, *node1, *node2;
char *out_ptr, *exp_ptr, *beg_ptr, *end_ptr, *copy_ptr, *del_ptr;
char *xline;
size_t xlen, i;
char *ckt_array[4];
size_t xlen, i, pai=0, paui=0, ii;
char *ckt_array[100];
struct line *new_line, *tmp_ptr;
struct line *param_end = NULL, *param_beg = NULL;
@ -3906,6 +3907,295 @@ static void inp_compat(struct line *deck)
param_beg = param_end = NULL;
}
/* .probe -> .save
.print, .plot, .save, .four,
An ouput vector may be replaced by the following:
myoutput=par('expression')
.meas
A vector out_variable may be replaced by
par('expression')
*/
else if ( *curr_line == '.' ) {
// replace .probe by .save
if(str_ptr = strstr(curr_line, ".probe"))
memcpy(str_ptr, ".save ", 6);
/* Various formats for measure statement:
* .MEASURE {DC|AC|TRAN} result WHEN out_variable=val
* + <TD=td> <FROM=val> <TO=val>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
*
* .MEASURE {DC|AC|TRAN} result WHEN out_variable=out_variable2
* + <TD=td> <FROM=val> <TO=val>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
*
* .MEASURE {DC|AC|TRAN} result FIND out_variable WHEN out_variable2=val
* + <TD=td> <FROM=val> <TO=val>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
*
* .MEASURE {DC|AC|TRAN} result FIND out_variable WHEN out_variable2=out_variable3
* + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
*
* .MEASURE {DC|AC|TRAN} result FIND out_variable AT=val
* + <FROM=val> <TO=val>
*
* .MEASURE {DC|AC|TRAN} result {AVG|MIN|MAX|MIN_AT|MAX_AT|PP|RMS} out_variable
* + <TD=td> <FROM=val> <TO=val>
*
* .MEASURE {DC|AC|TRAN} result INTEG<RAL> out_variable
* + <TD=td> <FROM=val> <TO=val>
*
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable AT=val
*
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable WHEN out_variable2=val
* + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
*
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable WHEN out_variable2=out_variable3
* + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
The user may set any out_variable to par(' expr ').
We have to teplace this by v(pa_xx) and generate a B source line.
* ----------------------------------------------------------------- */
if ( ciprefix(".meas", curr_line) ) {
if (strstr(curr_line, "par") == NULL) continue;
cut_line = curr_line;
// search for 'par'
while(str_ptr = strstr(cut_line, "par")) {
if (i > 99) {
fprintf(stderr, "ERROR: No more than 99 'par' per input file\n",
curr_line);
controlled_exit(EXIT_FAILURE);
}
// we have ' par({ ... })', the right delimeter is a ' ' or '='
if ( ciprefix(" par({", (str_ptr-1)) ) {
// find expression
beg_ptr = end_ptr = str_ptr + 5;
while ((*end_ptr != ' ') && (*end_ptr != '=') && (*end_ptr != '\0'))
end_ptr++;
exp_ptr = copy_substring(beg_ptr, end_ptr-2);
cut_line = str_ptr;
// generate node
out_ptr = (char*)tmalloc(6);
sprintf(out_ptr, "pa_%02d", pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr)
xlen = 2*strlen(out_ptr) + strlen(exp_ptr )+ 15 - 2*3 + 1;
ckt_array[pai] = (char*)tmalloc(xlen);
sprintf(ckt_array[pai], "b%s %s 0 v = %s",
out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr)
xlen = strlen(out_ptr) + 4;
del_ptr = copy_ptr = (char*)tmalloc(xlen);
sprintf(copy_ptr, "v(%s)", out_ptr);
// length of the replacement part in original line
xlen = strlen(exp_ptr) + 7;
// copy the replacement without trailing '\0'
for (ii = 0; ii < xlen; ii++)
if (*copy_ptr)
*cut_line++ = *copy_ptr++;
else
*cut_line++ = ' ';
tfree(del_ptr); tfree(exp_ptr); tfree(out_ptr);
}
// or we have '={par({ ... })}', the right delimeter is a ' '
else if ( ciprefix("={par({", (str_ptr-2)) ) {
// find expression
beg_ptr = end_ptr = str_ptr + 5;
while ((*end_ptr != ' ') && (*end_ptr != '\0'))
end_ptr++;
exp_ptr = copy_substring(beg_ptr, end_ptr-3);
// generate node
out_ptr = (char*)tmalloc(6);
sprintf(out_ptr, "pa_%02d", pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr)
xlen = 2*strlen(out_ptr) + strlen(exp_ptr )+ 15 - 2*3 + 1;
ckt_array[pai] = (char*)tmalloc(xlen);
sprintf(ckt_array[pai], "b%s %s 0 v = %s",
out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr)
xlen = strlen(out_ptr) + 4;
del_ptr = copy_ptr = (char*)tmalloc(xlen);
sprintf(copy_ptr, "v(%s)", out_ptr);
// length of the replacement part in original line
xlen = strlen(exp_ptr) + 9;
// skip '='
cut_line++;
// copy the replacement without trailing '\0'
for (ii = 0; ii < xlen; ii++)
if (*copy_ptr)
*cut_line++ = *copy_ptr++;
else *cut_line++ = ' ';
tfree(del_ptr); tfree(exp_ptr); tfree(out_ptr);
}
// nothing to replace
else {
cut_line = str_ptr + 1;
continue;
}
} // while 'par'
// no replacement done, go to next line
if (pai == paui) continue;
// remove white spaces
card->li_line = inp_remove_ws(curr_line);
// insert new B source line immediately after current line
tmp_ptr = card->li_next;
for ( ii = paui; ii < pai; ii++ )
{
if ( param_end )
{
param_end->li_next = alloc(struct line);
param_end = param_end->li_next;
}
else
{
param_end = param_beg = alloc(struct line);
}
param_end->li_next = NULL;
param_end->li_error = NULL;
param_end->li_actual = NULL;
param_end->li_line = ckt_array[ii];
param_end->li_linenum = 0;
}
// insert new param lines immediately after current line
tmp_ptr = card->li_next;
card->li_next = param_beg;
param_end->li_next = tmp_ptr;
// point 'card' pointer to last in scalar list
card = param_end;
param_beg = param_end = NULL;
paui = pai;
}
else if (( ciprefix(".save", curr_line) ) || ( ciprefix(".four", curr_line) )
|| ( ciprefix(".print", curr_line) ) || ( ciprefix(".plot", curr_line) )) {
if (strstr(curr_line, "par") == NULL) continue;
cut_line = curr_line;
// search for 'par'
while(str_ptr = strstr(cut_line, "par")) {
if (pai > 99) {
fprintf(stderr, "ERROR: No more than 99 'par' per input file!\n",
curr_line);
controlled_exit(EXIT_FAILURE);
}
// we have ' par({ ... })'
if ( ciprefix(" par({", (str_ptr-1)) ) {
// find expression
beg_ptr = end_ptr = str_ptr + 5;
while ((*end_ptr != ' ') && (*end_ptr != '\0'))
end_ptr++;
exp_ptr = copy_substring(beg_ptr, end_ptr-2);
cut_line = str_ptr;
// generate node
out_ptr = (char*)tmalloc(6);
sprintf(out_ptr, "pa_%02d", pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr)
xlen = 2*strlen(out_ptr) + strlen(exp_ptr )+ 15 - 2*3 + 1;
ckt_array[pai] = (char*)tmalloc(xlen);
sprintf(ckt_array[pai], "b%s %s 0 v = %s",
out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr)
xlen = strlen(out_ptr) + 1;
del_ptr = copy_ptr = (char*)tmalloc(xlen);
sprintf(copy_ptr, "%s", out_ptr);
// length of the replacement part in original line
xlen = strlen(exp_ptr) + 7;
// copy the replacement without trailing '\0'
for (ii = 0; ii < xlen; ii++)
if (*copy_ptr)
*cut_line++ = *copy_ptr++;
else
*cut_line++ = ' ';
tfree(del_ptr); tfree(exp_ptr); tfree(out_ptr);
}
// or we have '={par({ ... })}'
else if ( ciprefix("={par({", (str_ptr-2)) ) {
// find myoutput
beg_ptr = end_ptr = str_ptr - 2;
while (*beg_ptr != ' ')
beg_ptr--;
out_ptr = copy_substring(beg_ptr + 1, end_ptr);
cut_line = beg_ptr + 1;
// find expression
beg_ptr = end_ptr = str_ptr + 5;
while ((*end_ptr != ' ') && (*end_ptr != '\0'))
end_ptr++;
exp_ptr = copy_substring(beg_ptr, end_ptr-3);
// Bout_ptr out_ptr 0 V = v(expr_ptr)
xlen = 2*strlen(out_ptr) + strlen(exp_ptr )+ 15 - 2*3 + 1;
ckt_array[pai] = (char*)tmalloc(xlen);
sprintf(ckt_array[pai], "b%s %s 0 v = %s",
out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr)
xlen = strlen(out_ptr) + 1;
del_ptr = copy_ptr = (char*)tmalloc(xlen);
sprintf(copy_ptr, "%s", out_ptr);
// length of the replacement part in original line
xlen = strlen(out_ptr) + strlen(exp_ptr) + 10;
// copy the replacement without trailing '\0'
for (ii = 0; ii < xlen; ii++)
if (*copy_ptr)
*cut_line++ = *copy_ptr++;
else *cut_line++ = ' ';
tfree(del_ptr); tfree(exp_ptr); tfree(out_ptr);
}
// nothing to replace
else
cut_line = str_ptr + 1;
} // while 'par'
// no replacement done, go to next line
if (pai == paui) continue;
// remove white spaces
card->li_line = inp_remove_ws(curr_line);
// insert new B source line immediately after current line
tmp_ptr = card->li_next;
for ( ii = paui; ii < pai; ii++ )
{
if ( param_end )
{
param_end->li_next = alloc(struct line);
param_end = param_end->li_next;
}
else
{
param_end = param_beg = alloc(struct line);
}
param_end->li_next = NULL;
param_end->li_error = NULL;
param_end->li_actual = NULL;
param_end->li_line = ckt_array[ii];
param_end->li_linenum = 0;
}
// comment out current variable capacitor line
// *(ckt_array[0]) = '*';
// insert new param lines immediately after current line
tmp_ptr = card->li_next;
card->li_next = param_beg;
param_end->li_next = tmp_ptr;
// point 'card' pointer to last in scalar list
card = param_end;
param_beg = param_end = NULL;
paui = pai;
// continue;
} // if .print etc.
} // if('.')
}
}
/* lines for B sources: no parsing in numparam code, just replacement of parameters.

View File

@ -201,6 +201,7 @@ extern struct timeb timebegin;
extern char *gettok(char **s);
extern char *gettok_noparens(char **s);
extern char *gettok_node(char **s);
extern char *gettok_iv(char **s);
extern int get_l_paren(char **s);
extern int get_r_paren(char **s);
extern void appendc(char *s, char c);

View File

@ -236,6 +236,48 @@ gettok(char **s)
return ( token ) ;
}
/*-------------------------------------------------------------------------*
* gettok skips over whitespaces or '=' and returns the next token found,
* if the token is something like i(xxx), v(yyy), or v(xxx,yyy)
* -- h_vogt 10.07.2010.
*-------------------------------------------------------------------------*/
char *
gettok_iv(char **s)
{
char c;
int paren;
char *token ; /* return token */
SPICE_DSTRING buf ; /* allow any length string */
paren = 0;
while ((isspace(**s)) || (**s=='='))
(*s)++;
if ((!**s) || ((**s != 'v') && (**s != 'i') && (**s != 'V') && (**s != 'I')))
return (NULL);
// initialize string
spice_dstring_init(&buf);
// add v or i to buf
spice_dstring_append_char( &buf, *(*s)++ ) ;
while (c = **s) {
if (c == '('/*)*/)
paren += 1;
else if (c == /*(*/')')
paren -= 1;
if (isspace(c))
*(*s)++;
else {
spice_dstring_append_char( &buf, *(*s)++ ) ;
if (paren == 0) break;
}
}
while (isspace(**s) || **s == ',')
(*s)++;
token = copy( spice_dstring_value(&buf) ) ;
spice_dstring_free(&buf) ;
return ( token ) ;
}
/*-------------------------------------------------------------------------*
* gettok_noparens was added by SDB on 4.21.2003.
* It acts like gettok, except that it treats parens and commas like